pinctrl-loongson2.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Author: zhanghongchen <zhanghongchen@loongson.cn>
  4. * Yinbo Zhu <zhuyinbo@loongson.cn>
  5. * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
  6. */
  7. #include <linux/init.h>
  8. #include <linux/module.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/mod_devicetable.h>
  11. #include <linux/pinctrl/pinmux.h>
  12. #include <linux/pinctrl/pinconf-generic.h>
  13. #include <linux/pinctrl/pinctrl.h>
  14. #include <linux/bitops.h>
  15. #include <linux/io.h>
  16. #include <linux/seq_file.h>
  17. #include "core.h"
  18. #include "pinctrl-utils.h"
  19. #define PMX_GROUP(name, offset, bitv) \
  20. { \
  21. .grp = PINCTRL_PINGROUP((#name), (name ## _pins), \
  22. ARRAY_SIZE((name ## _pins))), \
  23. .reg = offset, \
  24. .bit = bitv, \
  25. }
  26. #define SPECIFIC_GROUP(group) \
  27. static const char * const group##_groups[] = { \
  28. #group \
  29. }
  30. #define FUNCTION(fn) \
  31. { \
  32. .name = #fn, \
  33. .groups = fn ## _groups, \
  34. .num_groups = ARRAY_SIZE(fn ## _groups), \
  35. }
  36. struct loongson2_pinctrl {
  37. struct device *dev;
  38. struct pinctrl_dev *pcdev;
  39. struct pinctrl_desc desc;
  40. struct device_node *of_node;
  41. spinlock_t lock;
  42. void __iomem *reg_base;
  43. };
  44. struct loongson2_pmx_group {
  45. struct pingroup grp;
  46. unsigned int reg;
  47. unsigned int bit;
  48. };
  49. struct loongson2_pmx_func {
  50. const char *name;
  51. const char * const *groups;
  52. unsigned int num_groups;
  53. };
  54. #define LOONGSON2_PIN(x) PINCTRL_PIN(x, "gpio"#x)
  55. static const struct pinctrl_pin_desc loongson2_pctrl_pins[] = {
  56. LOONGSON2_PIN(0), LOONGSON2_PIN(1), LOONGSON2_PIN(2), LOONGSON2_PIN(3),
  57. LOONGSON2_PIN(4), LOONGSON2_PIN(5), LOONGSON2_PIN(6), LOONGSON2_PIN(7),
  58. LOONGSON2_PIN(8), LOONGSON2_PIN(9), LOONGSON2_PIN(10), LOONGSON2_PIN(11),
  59. LOONGSON2_PIN(12), LOONGSON2_PIN(13), LOONGSON2_PIN(14),
  60. LOONGSON2_PIN(16), LOONGSON2_PIN(17), LOONGSON2_PIN(18), LOONGSON2_PIN(19),
  61. LOONGSON2_PIN(20), LOONGSON2_PIN(21), LOONGSON2_PIN(22), LOONGSON2_PIN(23),
  62. LOONGSON2_PIN(24), LOONGSON2_PIN(25), LOONGSON2_PIN(26), LOONGSON2_PIN(27),
  63. LOONGSON2_PIN(28), LOONGSON2_PIN(29), LOONGSON2_PIN(30),
  64. LOONGSON2_PIN(32), LOONGSON2_PIN(33), LOONGSON2_PIN(34), LOONGSON2_PIN(35),
  65. LOONGSON2_PIN(36), LOONGSON2_PIN(37), LOONGSON2_PIN(38), LOONGSON2_PIN(39),
  66. LOONGSON2_PIN(40), LOONGSON2_PIN(41),
  67. LOONGSON2_PIN(44), LOONGSON2_PIN(45), LOONGSON2_PIN(46), LOONGSON2_PIN(47),
  68. LOONGSON2_PIN(48), LOONGSON2_PIN(49), LOONGSON2_PIN(50), LOONGSON2_PIN(51),
  69. LOONGSON2_PIN(52), LOONGSON2_PIN(53), LOONGSON2_PIN(54), LOONGSON2_PIN(55),
  70. LOONGSON2_PIN(56), LOONGSON2_PIN(57), LOONGSON2_PIN(58), LOONGSON2_PIN(59),
  71. LOONGSON2_PIN(60), LOONGSON2_PIN(61), LOONGSON2_PIN(62), LOONGSON2_PIN(63),
  72. };
  73. static const unsigned int gpio_pins[] = {0, 1, 2, 3, 4, 5, 6, 7,
  74. 8, 9, 10, 11, 12, 13, 14,
  75. 16, 17, 18, 19, 20, 21, 22, 23,
  76. 24, 25, 26, 27, 28, 29, 30,
  77. 32, 33, 34, 35, 36, 37, 38, 39,
  78. 40, 43, 44, 45, 46, 47,
  79. 48, 49, 50, 51, 52, 53, 46, 55,
  80. 56, 57, 58, 59, 60, 61, 62, 63};
  81. static const unsigned int sdio_pins[] = {36, 37, 38, 39, 40, 41};
  82. static const unsigned int can1_pins[] = {34, 35};
  83. static const unsigned int can0_pins[] = {32, 33};
  84. static const unsigned int pwm3_pins[] = {23};
  85. static const unsigned int pwm2_pins[] = {22};
  86. static const unsigned int pwm1_pins[] = {21};
  87. static const unsigned int pwm0_pins[] = {20};
  88. static const unsigned int i2c1_pins[] = {18, 19};
  89. static const unsigned int i2c0_pins[] = {16, 17};
  90. static const unsigned int nand_pins[] = {44, 45, 46, 47, 48, 49, 50, 51,
  91. 52, 53, 54, 55, 56, 57, 58, 59, 60,
  92. 61, 62, 63};
  93. static const unsigned int sata_led_pins[] = {14};
  94. static const unsigned int i2s_pins[] = {24, 25, 26, 27, 28};
  95. static const unsigned int hda_pins[] = {24, 25, 26, 27, 28, 29, 30};
  96. static struct loongson2_pmx_group loongson2_pmx_groups[] = {
  97. PMX_GROUP(gpio, 0x0, 64),
  98. PMX_GROUP(sdio, 0x0, 20),
  99. PMX_GROUP(can1, 0x0, 17),
  100. PMX_GROUP(can0, 0x0, 16),
  101. PMX_GROUP(pwm3, 0x0, 15),
  102. PMX_GROUP(pwm2, 0x0, 14),
  103. PMX_GROUP(pwm1, 0x0, 13),
  104. PMX_GROUP(pwm0, 0x0, 12),
  105. PMX_GROUP(i2c1, 0x0, 11),
  106. PMX_GROUP(i2c0, 0x0, 10),
  107. PMX_GROUP(nand, 0x0, 9),
  108. PMX_GROUP(sata_led, 0x0, 8),
  109. PMX_GROUP(i2s, 0x0, 6),
  110. PMX_GROUP(hda, 0x0, 4),
  111. };
  112. SPECIFIC_GROUP(sdio);
  113. SPECIFIC_GROUP(can1);
  114. SPECIFIC_GROUP(can0);
  115. SPECIFIC_GROUP(pwm3);
  116. SPECIFIC_GROUP(pwm2);
  117. SPECIFIC_GROUP(pwm1);
  118. SPECIFIC_GROUP(pwm0);
  119. SPECIFIC_GROUP(i2c1);
  120. SPECIFIC_GROUP(i2c0);
  121. SPECIFIC_GROUP(nand);
  122. SPECIFIC_GROUP(sata_led);
  123. SPECIFIC_GROUP(i2s);
  124. SPECIFIC_GROUP(hda);
  125. static const char * const gpio_groups[] = {
  126. "sdio",
  127. "can1", "can0",
  128. "pwm3", "pwm2", "pwm1", "pwm0",
  129. "i2c1", "i2c0",
  130. "nand",
  131. "sata_led",
  132. "i2s",
  133. "hda",
  134. };
  135. static const struct loongson2_pmx_func loongson2_pmx_functions[] = {
  136. FUNCTION(gpio),
  137. FUNCTION(sdio),
  138. FUNCTION(can1),
  139. FUNCTION(can0),
  140. FUNCTION(pwm3),
  141. FUNCTION(pwm2),
  142. FUNCTION(pwm1),
  143. FUNCTION(pwm0),
  144. FUNCTION(i2c1),
  145. FUNCTION(i2c0),
  146. FUNCTION(nand),
  147. FUNCTION(sata_led),
  148. FUNCTION(i2s),
  149. FUNCTION(hda),
  150. };
  151. static int loongson2_get_groups_count(struct pinctrl_dev *pcdev)
  152. {
  153. return ARRAY_SIZE(loongson2_pmx_groups);
  154. }
  155. static const char *loongson2_get_group_name(struct pinctrl_dev *pcdev,
  156. unsigned int selector)
  157. {
  158. return loongson2_pmx_groups[selector].grp.name;
  159. }
  160. static int loongson2_get_group_pins(struct pinctrl_dev *pcdev, unsigned int selector,
  161. const unsigned int **pins, unsigned int *num_pins)
  162. {
  163. *pins = loongson2_pmx_groups[selector].grp.pins;
  164. *num_pins = loongson2_pmx_groups[selector].grp.npins;
  165. return 0;
  166. }
  167. static void loongson2_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
  168. unsigned int offset)
  169. {
  170. seq_printf(s, " %s", dev_name(pcdev->dev));
  171. }
  172. static const struct pinctrl_ops loongson2_pctrl_ops = {
  173. .get_groups_count = loongson2_get_groups_count,
  174. .get_group_name = loongson2_get_group_name,
  175. .get_group_pins = loongson2_get_group_pins,
  176. .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
  177. .dt_free_map = pinctrl_utils_free_map,
  178. .pin_dbg_show = loongson2_pin_dbg_show,
  179. };
  180. static int loongson2_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned int func_num,
  181. unsigned int group_num)
  182. {
  183. struct loongson2_pinctrl *pctrl = pinctrl_dev_get_drvdata(pcdev);
  184. void __iomem *reg = pctrl->reg_base +
  185. loongson2_pmx_groups[group_num].reg;
  186. unsigned int mux_bit = loongson2_pmx_groups[group_num].bit;
  187. unsigned int val;
  188. unsigned long flags;
  189. spin_lock_irqsave(&pctrl->lock, flags);
  190. val = readl(reg);
  191. if (func_num == 0)
  192. val &= ~BIT(mux_bit);
  193. else
  194. val |= BIT(mux_bit);
  195. writel(val, reg);
  196. spin_unlock_irqrestore(&pctrl->lock, flags);
  197. return 0;
  198. }
  199. static int loongson2_pmx_get_funcs_count(struct pinctrl_dev *pcdev)
  200. {
  201. return ARRAY_SIZE(loongson2_pmx_functions);
  202. }
  203. static const char *loongson2_pmx_get_func_name(struct pinctrl_dev *pcdev,
  204. unsigned int selector)
  205. {
  206. return loongson2_pmx_functions[selector].name;
  207. }
  208. static int loongson2_pmx_get_groups(struct pinctrl_dev *pcdev,
  209. unsigned int selector,
  210. const char * const **groups,
  211. unsigned int * const num_groups)
  212. {
  213. *groups = loongson2_pmx_functions[selector].groups;
  214. *num_groups = loongson2_pmx_functions[selector].num_groups;
  215. return 0;
  216. }
  217. static const struct pinmux_ops loongson2_pmx_ops = {
  218. .set_mux = loongson2_pmx_set_mux,
  219. .get_functions_count = loongson2_pmx_get_funcs_count,
  220. .get_function_name = loongson2_pmx_get_func_name,
  221. .get_function_groups = loongson2_pmx_get_groups,
  222. };
  223. static int loongson2_pinctrl_probe(struct platform_device *pdev)
  224. {
  225. struct device *dev = &pdev->dev;
  226. struct loongson2_pinctrl *pctrl;
  227. pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
  228. if (!pctrl)
  229. return -ENOMEM;
  230. pctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
  231. if (IS_ERR(pctrl->reg_base))
  232. return PTR_ERR(pctrl->reg_base);
  233. spin_lock_init(&pctrl->lock);
  234. pctrl->dev = dev;
  235. pctrl->desc.name = "pinctrl-loongson2";
  236. pctrl->desc.owner = THIS_MODULE;
  237. pctrl->desc.pctlops = &loongson2_pctrl_ops;
  238. pctrl->desc.pmxops = &loongson2_pmx_ops;
  239. pctrl->desc.pins = loongson2_pctrl_pins;
  240. pctrl->desc.npins = ARRAY_SIZE(loongson2_pctrl_pins);
  241. pctrl->pcdev = devm_pinctrl_register(pctrl->dev, &pctrl->desc, pctrl);
  242. if (IS_ERR(pctrl->pcdev))
  243. return dev_err_probe(pctrl->dev, PTR_ERR(pctrl->pcdev),
  244. "can't register pinctrl device");
  245. return 0;
  246. }
  247. static const struct of_device_id loongson2_pinctrl_dt_match[] = {
  248. {
  249. .compatible = "loongson,ls2k-pinctrl",
  250. },
  251. { }
  252. };
  253. MODULE_DEVICE_TABLE(of, loongson2_pinctrl_dt_match);
  254. static struct platform_driver loongson2_pinctrl_driver = {
  255. .probe = loongson2_pinctrl_probe,
  256. .driver = {
  257. .name = "loongson2-pinctrl",
  258. .of_match_table = loongson2_pinctrl_dt_match,
  259. },
  260. };
  261. static int __init loongson2_pinctrl_init(void)
  262. {
  263. return platform_driver_register(&loongson2_pinctrl_driver);
  264. }
  265. arch_initcall(loongson2_pinctrl_init);
  266. static void __exit loongson2_pinctrl_exit(void)
  267. {
  268. platform_driver_unregister(&loongson2_pinctrl_driver);
  269. }
  270. module_exit(loongson2_pinctrl_exit);
  271. MODULE_DESCRIPTION("Loongson2 Pinctrl driver");
  272. MODULE_LICENSE("GPL");