pinctrl-bcm4908.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (C) 2021 Rafał Miłecki <[email protected]> */
  3. #include <linux/err.h>
  4. #include <linux/io.h>
  5. #include <linux/mod_devicetable.h>
  6. #include <linux/module.h>
  7. #include <linux/pinctrl/pinconf-generic.h>
  8. #include <linux/pinctrl/pinctrl.h>
  9. #include <linux/pinctrl/pinmux.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/slab.h>
  12. #include <linux/string_helpers.h>
  13. #include "../core.h"
  14. #include "../pinmux.h"
  15. #define BCM4908_NUM_PINS 86
  16. #define BCM4908_TEST_PORT_BLOCK_EN_LSB 0x00
  17. #define BCM4908_TEST_PORT_BLOCK_DATA_MSB 0x04
  18. #define BCM4908_TEST_PORT_BLOCK_DATA_LSB 0x08
  19. #define BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT 12
  20. #define BCM4908_TEST_PORT_COMMAND 0x0c
  21. #define BCM4908_TEST_PORT_CMD_LOAD_MUX_REG 0x00000021
  22. struct bcm4908_pinctrl {
  23. struct device *dev;
  24. void __iomem *base;
  25. struct mutex mutex;
  26. struct pinctrl_dev *pctldev;
  27. struct pinctrl_desc pctldesc;
  28. };
  29. /*
  30. * Groups
  31. */
  32. struct bcm4908_pinctrl_pin_setup {
  33. unsigned int number;
  34. unsigned int function;
  35. };
  36. static const struct bcm4908_pinctrl_pin_setup led_0_pins_a[] = {
  37. { 0, 3 },
  38. };
  39. static const struct bcm4908_pinctrl_pin_setup led_1_pins_a[] = {
  40. { 1, 3 },
  41. };
  42. static const struct bcm4908_pinctrl_pin_setup led_2_pins_a[] = {
  43. { 2, 3 },
  44. };
  45. static const struct bcm4908_pinctrl_pin_setup led_3_pins_a[] = {
  46. { 3, 3 },
  47. };
  48. static const struct bcm4908_pinctrl_pin_setup led_4_pins_a[] = {
  49. { 4, 3 },
  50. };
  51. static const struct bcm4908_pinctrl_pin_setup led_5_pins_a[] = {
  52. { 5, 3 },
  53. };
  54. static const struct bcm4908_pinctrl_pin_setup led_6_pins_a[] = {
  55. { 6, 3 },
  56. };
  57. static const struct bcm4908_pinctrl_pin_setup led_7_pins_a[] = {
  58. { 7, 3 },
  59. };
  60. static const struct bcm4908_pinctrl_pin_setup led_8_pins_a[] = {
  61. { 8, 3 },
  62. };
  63. static const struct bcm4908_pinctrl_pin_setup led_9_pins_a[] = {
  64. { 9, 3 },
  65. };
  66. static const struct bcm4908_pinctrl_pin_setup led_10_pins_a[] = {
  67. { 10, 3 },
  68. };
  69. static const struct bcm4908_pinctrl_pin_setup led_11_pins_a[] = {
  70. { 11, 3 },
  71. };
  72. static const struct bcm4908_pinctrl_pin_setup led_12_pins_a[] = {
  73. { 12, 3 },
  74. };
  75. static const struct bcm4908_pinctrl_pin_setup led_13_pins_a[] = {
  76. { 13, 3 },
  77. };
  78. static const struct bcm4908_pinctrl_pin_setup led_14_pins_a[] = {
  79. { 14, 3 },
  80. };
  81. static const struct bcm4908_pinctrl_pin_setup led_15_pins_a[] = {
  82. { 15, 3 },
  83. };
  84. static const struct bcm4908_pinctrl_pin_setup led_16_pins_a[] = {
  85. { 16, 3 },
  86. };
  87. static const struct bcm4908_pinctrl_pin_setup led_17_pins_a[] = {
  88. { 17, 3 },
  89. };
  90. static const struct bcm4908_pinctrl_pin_setup led_18_pins_a[] = {
  91. { 18, 3 },
  92. };
  93. static const struct bcm4908_pinctrl_pin_setup led_19_pins_a[] = {
  94. { 19, 3 },
  95. };
  96. static const struct bcm4908_pinctrl_pin_setup led_20_pins_a[] = {
  97. { 20, 3 },
  98. };
  99. static const struct bcm4908_pinctrl_pin_setup led_21_pins_a[] = {
  100. { 21, 3 },
  101. };
  102. static const struct bcm4908_pinctrl_pin_setup led_22_pins_a[] = {
  103. { 22, 3 },
  104. };
  105. static const struct bcm4908_pinctrl_pin_setup led_23_pins_a[] = {
  106. { 23, 3 },
  107. };
  108. static const struct bcm4908_pinctrl_pin_setup led_24_pins_a[] = {
  109. { 24, 3 },
  110. };
  111. static const struct bcm4908_pinctrl_pin_setup led_25_pins_a[] = {
  112. { 25, 3 },
  113. };
  114. static const struct bcm4908_pinctrl_pin_setup led_26_pins_a[] = {
  115. { 26, 3 },
  116. };
  117. static const struct bcm4908_pinctrl_pin_setup led_27_pins_a[] = {
  118. { 27, 3 },
  119. };
  120. static const struct bcm4908_pinctrl_pin_setup led_28_pins_a[] = {
  121. { 28, 3 },
  122. };
  123. static const struct bcm4908_pinctrl_pin_setup led_29_pins_a[] = {
  124. { 29, 3 },
  125. };
  126. static const struct bcm4908_pinctrl_pin_setup led_30_pins_a[] = {
  127. { 30, 3 },
  128. };
  129. static const struct bcm4908_pinctrl_pin_setup led_31_pins_a[] = {
  130. { 31, 3 },
  131. };
  132. static const struct bcm4908_pinctrl_pin_setup led_10_pins_b[] = {
  133. { 8, 2 },
  134. };
  135. static const struct bcm4908_pinctrl_pin_setup led_11_pins_b[] = {
  136. { 9, 2 },
  137. };
  138. static const struct bcm4908_pinctrl_pin_setup led_12_pins_b[] = {
  139. { 0, 2 },
  140. };
  141. static const struct bcm4908_pinctrl_pin_setup led_13_pins_b[] = {
  142. { 1, 2 },
  143. };
  144. static const struct bcm4908_pinctrl_pin_setup led_31_pins_b[] = {
  145. { 30, 2 },
  146. };
  147. static const struct bcm4908_pinctrl_pin_setup hs_uart_pins[] = {
  148. { 10, 0 }, /* CTS */
  149. { 11, 0 }, /* RTS */
  150. { 12, 0 }, /* RXD */
  151. { 13, 0 }, /* TXD */
  152. };
  153. static const struct bcm4908_pinctrl_pin_setup i2c_pins_a[] = {
  154. { 18, 0 }, /* SDA */
  155. { 19, 0 }, /* SCL */
  156. };
  157. static const struct bcm4908_pinctrl_pin_setup i2c_pins_b[] = {
  158. { 22, 0 }, /* SDA */
  159. { 23, 0 }, /* SCL */
  160. };
  161. static const struct bcm4908_pinctrl_pin_setup i2s_pins[] = {
  162. { 27, 0 }, /* MCLK */
  163. { 28, 0 }, /* LRCK */
  164. { 29, 0 }, /* SDATA */
  165. { 30, 0 }, /* SCLK */
  166. };
  167. static const struct bcm4908_pinctrl_pin_setup nand_ctrl_pins[] = {
  168. { 32, 0 },
  169. { 33, 0 },
  170. { 34, 0 },
  171. { 43, 0 },
  172. { 44, 0 },
  173. { 45, 0 },
  174. { 56, 1 },
  175. };
  176. static const struct bcm4908_pinctrl_pin_setup nand_data_pins[] = {
  177. { 35, 0 },
  178. { 36, 0 },
  179. { 37, 0 },
  180. { 38, 0 },
  181. { 39, 0 },
  182. { 40, 0 },
  183. { 41, 0 },
  184. { 42, 0 },
  185. };
  186. static const struct bcm4908_pinctrl_pin_setup emmc_ctrl_pins[] = {
  187. { 46, 0 },
  188. { 47, 0 },
  189. };
  190. static const struct bcm4908_pinctrl_pin_setup usb0_pwr_pins[] = {
  191. { 63, 0 },
  192. { 64, 0 },
  193. };
  194. static const struct bcm4908_pinctrl_pin_setup usb1_pwr_pins[] = {
  195. { 66, 0 },
  196. { 67, 0 },
  197. };
  198. struct bcm4908_pinctrl_grp {
  199. const char *name;
  200. const struct bcm4908_pinctrl_pin_setup *pins;
  201. const unsigned int num_pins;
  202. };
  203. static const struct bcm4908_pinctrl_grp bcm4908_pinctrl_grps[] = {
  204. { "led_0_grp_a", led_0_pins_a, ARRAY_SIZE(led_0_pins_a) },
  205. { "led_1_grp_a", led_1_pins_a, ARRAY_SIZE(led_1_pins_a) },
  206. { "led_2_grp_a", led_2_pins_a, ARRAY_SIZE(led_2_pins_a) },
  207. { "led_3_grp_a", led_3_pins_a, ARRAY_SIZE(led_3_pins_a) },
  208. { "led_4_grp_a", led_4_pins_a, ARRAY_SIZE(led_4_pins_a) },
  209. { "led_5_grp_a", led_5_pins_a, ARRAY_SIZE(led_5_pins_a) },
  210. { "led_6_grp_a", led_6_pins_a, ARRAY_SIZE(led_6_pins_a) },
  211. { "led_7_grp_a", led_7_pins_a, ARRAY_SIZE(led_7_pins_a) },
  212. { "led_8_grp_a", led_8_pins_a, ARRAY_SIZE(led_8_pins_a) },
  213. { "led_9_grp_a", led_9_pins_a, ARRAY_SIZE(led_9_pins_a) },
  214. { "led_10_grp_a", led_10_pins_a, ARRAY_SIZE(led_10_pins_a) },
  215. { "led_11_grp_a", led_11_pins_a, ARRAY_SIZE(led_11_pins_a) },
  216. { "led_12_grp_a", led_12_pins_a, ARRAY_SIZE(led_12_pins_a) },
  217. { "led_13_grp_a", led_13_pins_a, ARRAY_SIZE(led_13_pins_a) },
  218. { "led_14_grp_a", led_14_pins_a, ARRAY_SIZE(led_14_pins_a) },
  219. { "led_15_grp_a", led_15_pins_a, ARRAY_SIZE(led_15_pins_a) },
  220. { "led_16_grp_a", led_16_pins_a, ARRAY_SIZE(led_16_pins_a) },
  221. { "led_17_grp_a", led_17_pins_a, ARRAY_SIZE(led_17_pins_a) },
  222. { "led_18_grp_a", led_18_pins_a, ARRAY_SIZE(led_18_pins_a) },
  223. { "led_19_grp_a", led_19_pins_a, ARRAY_SIZE(led_19_pins_a) },
  224. { "led_20_grp_a", led_20_pins_a, ARRAY_SIZE(led_20_pins_a) },
  225. { "led_21_grp_a", led_21_pins_a, ARRAY_SIZE(led_21_pins_a) },
  226. { "led_22_grp_a", led_22_pins_a, ARRAY_SIZE(led_22_pins_a) },
  227. { "led_23_grp_a", led_23_pins_a, ARRAY_SIZE(led_23_pins_a) },
  228. { "led_24_grp_a", led_24_pins_a, ARRAY_SIZE(led_24_pins_a) },
  229. { "led_25_grp_a", led_25_pins_a, ARRAY_SIZE(led_25_pins_a) },
  230. { "led_26_grp_a", led_26_pins_a, ARRAY_SIZE(led_26_pins_a) },
  231. { "led_27_grp_a", led_27_pins_a, ARRAY_SIZE(led_27_pins_a) },
  232. { "led_28_grp_a", led_28_pins_a, ARRAY_SIZE(led_28_pins_a) },
  233. { "led_29_grp_a", led_29_pins_a, ARRAY_SIZE(led_29_pins_a) },
  234. { "led_30_grp_a", led_30_pins_a, ARRAY_SIZE(led_30_pins_a) },
  235. { "led_31_grp_a", led_31_pins_a, ARRAY_SIZE(led_31_pins_a) },
  236. { "led_10_grp_b", led_10_pins_b, ARRAY_SIZE(led_10_pins_b) },
  237. { "led_11_grp_b", led_11_pins_b, ARRAY_SIZE(led_11_pins_b) },
  238. { "led_12_grp_b", led_12_pins_b, ARRAY_SIZE(led_12_pins_b) },
  239. { "led_13_grp_b", led_13_pins_b, ARRAY_SIZE(led_13_pins_b) },
  240. { "led_31_grp_b", led_31_pins_b, ARRAY_SIZE(led_31_pins_b) },
  241. { "hs_uart_grp", hs_uart_pins, ARRAY_SIZE(hs_uart_pins) },
  242. { "i2c_grp_a", i2c_pins_a, ARRAY_SIZE(i2c_pins_a) },
  243. { "i2c_grp_b", i2c_pins_b, ARRAY_SIZE(i2c_pins_b) },
  244. { "i2s_grp", i2s_pins, ARRAY_SIZE(i2s_pins) },
  245. { "nand_ctrl_grp", nand_ctrl_pins, ARRAY_SIZE(nand_ctrl_pins) },
  246. { "nand_data_grp", nand_data_pins, ARRAY_SIZE(nand_data_pins) },
  247. { "emmc_ctrl_grp", emmc_ctrl_pins, ARRAY_SIZE(emmc_ctrl_pins) },
  248. { "usb0_pwr_grp", usb0_pwr_pins, ARRAY_SIZE(usb0_pwr_pins) },
  249. { "usb1_pwr_grp", usb1_pwr_pins, ARRAY_SIZE(usb1_pwr_pins) },
  250. };
  251. /*
  252. * Functions
  253. */
  254. struct bcm4908_pinctrl_function {
  255. const char *name;
  256. const char * const *groups;
  257. const unsigned int num_groups;
  258. };
  259. static const char * const led_0_groups[] = { "led_0_grp_a" };
  260. static const char * const led_1_groups[] = { "led_1_grp_a" };
  261. static const char * const led_2_groups[] = { "led_2_grp_a" };
  262. static const char * const led_3_groups[] = { "led_3_grp_a" };
  263. static const char * const led_4_groups[] = { "led_4_grp_a" };
  264. static const char * const led_5_groups[] = { "led_5_grp_a" };
  265. static const char * const led_6_groups[] = { "led_6_grp_a" };
  266. static const char * const led_7_groups[] = { "led_7_grp_a" };
  267. static const char * const led_8_groups[] = { "led_8_grp_a" };
  268. static const char * const led_9_groups[] = { "led_9_grp_a" };
  269. static const char * const led_10_groups[] = { "led_10_grp_a", "led_10_grp_b" };
  270. static const char * const led_11_groups[] = { "led_11_grp_a", "led_11_grp_b" };
  271. static const char * const led_12_groups[] = { "led_12_grp_a", "led_12_grp_b" };
  272. static const char * const led_13_groups[] = { "led_13_grp_a", "led_13_grp_b" };
  273. static const char * const led_14_groups[] = { "led_14_grp_a" };
  274. static const char * const led_15_groups[] = { "led_15_grp_a" };
  275. static const char * const led_16_groups[] = { "led_16_grp_a" };
  276. static const char * const led_17_groups[] = { "led_17_grp_a" };
  277. static const char * const led_18_groups[] = { "led_18_grp_a" };
  278. static const char * const led_19_groups[] = { "led_19_grp_a" };
  279. static const char * const led_20_groups[] = { "led_20_grp_a" };
  280. static const char * const led_21_groups[] = { "led_21_grp_a" };
  281. static const char * const led_22_groups[] = { "led_22_grp_a" };
  282. static const char * const led_23_groups[] = { "led_23_grp_a" };
  283. static const char * const led_24_groups[] = { "led_24_grp_a" };
  284. static const char * const led_25_groups[] = { "led_25_grp_a" };
  285. static const char * const led_26_groups[] = { "led_26_grp_a" };
  286. static const char * const led_27_groups[] = { "led_27_grp_a" };
  287. static const char * const led_28_groups[] = { "led_28_grp_a" };
  288. static const char * const led_29_groups[] = { "led_29_grp_a" };
  289. static const char * const led_30_groups[] = { "led_30_grp_a" };
  290. static const char * const led_31_groups[] = { "led_31_grp_a", "led_31_grp_b" };
  291. static const char * const hs_uart_groups[] = { "hs_uart_grp" };
  292. static const char * const i2c_groups[] = { "i2c_grp_a", "i2c_grp_b" };
  293. static const char * const i2s_groups[] = { "i2s_grp" };
  294. static const char * const nand_ctrl_groups[] = { "nand_ctrl_grp" };
  295. static const char * const nand_data_groups[] = { "nand_data_grp" };
  296. static const char * const emmc_ctrl_groups[] = { "emmc_ctrl_grp" };
  297. static const char * const usb0_pwr_groups[] = { "usb0_pwr_grp" };
  298. static const char * const usb1_pwr_groups[] = { "usb1_pwr_grp" };
  299. static const struct bcm4908_pinctrl_function bcm4908_pinctrl_functions[] = {
  300. { "led_0", led_0_groups, ARRAY_SIZE(led_0_groups) },
  301. { "led_1", led_1_groups, ARRAY_SIZE(led_1_groups) },
  302. { "led_2", led_2_groups, ARRAY_SIZE(led_2_groups) },
  303. { "led_3", led_3_groups, ARRAY_SIZE(led_3_groups) },
  304. { "led_4", led_4_groups, ARRAY_SIZE(led_4_groups) },
  305. { "led_5", led_5_groups, ARRAY_SIZE(led_5_groups) },
  306. { "led_6", led_6_groups, ARRAY_SIZE(led_6_groups) },
  307. { "led_7", led_7_groups, ARRAY_SIZE(led_7_groups) },
  308. { "led_8", led_8_groups, ARRAY_SIZE(led_8_groups) },
  309. { "led_9", led_9_groups, ARRAY_SIZE(led_9_groups) },
  310. { "led_10", led_10_groups, ARRAY_SIZE(led_10_groups) },
  311. { "led_11", led_11_groups, ARRAY_SIZE(led_11_groups) },
  312. { "led_12", led_12_groups, ARRAY_SIZE(led_12_groups) },
  313. { "led_13", led_13_groups, ARRAY_SIZE(led_13_groups) },
  314. { "led_14", led_14_groups, ARRAY_SIZE(led_14_groups) },
  315. { "led_15", led_15_groups, ARRAY_SIZE(led_15_groups) },
  316. { "led_16", led_16_groups, ARRAY_SIZE(led_16_groups) },
  317. { "led_17", led_17_groups, ARRAY_SIZE(led_17_groups) },
  318. { "led_18", led_18_groups, ARRAY_SIZE(led_18_groups) },
  319. { "led_19", led_19_groups, ARRAY_SIZE(led_19_groups) },
  320. { "led_20", led_20_groups, ARRAY_SIZE(led_20_groups) },
  321. { "led_21", led_21_groups, ARRAY_SIZE(led_21_groups) },
  322. { "led_22", led_22_groups, ARRAY_SIZE(led_22_groups) },
  323. { "led_23", led_23_groups, ARRAY_SIZE(led_23_groups) },
  324. { "led_24", led_24_groups, ARRAY_SIZE(led_24_groups) },
  325. { "led_25", led_25_groups, ARRAY_SIZE(led_25_groups) },
  326. { "led_26", led_26_groups, ARRAY_SIZE(led_26_groups) },
  327. { "led_27", led_27_groups, ARRAY_SIZE(led_27_groups) },
  328. { "led_28", led_28_groups, ARRAY_SIZE(led_28_groups) },
  329. { "led_29", led_29_groups, ARRAY_SIZE(led_29_groups) },
  330. { "led_30", led_30_groups, ARRAY_SIZE(led_30_groups) },
  331. { "led_31", led_31_groups, ARRAY_SIZE(led_31_groups) },
  332. { "hs_uart", hs_uart_groups, ARRAY_SIZE(hs_uart_groups) },
  333. { "i2c", i2c_groups, ARRAY_SIZE(i2c_groups) },
  334. { "i2s", i2s_groups, ARRAY_SIZE(i2s_groups) },
  335. { "nand_ctrl", nand_ctrl_groups, ARRAY_SIZE(nand_ctrl_groups) },
  336. { "nand_data", nand_data_groups, ARRAY_SIZE(nand_data_groups) },
  337. { "emmc_ctrl", emmc_ctrl_groups, ARRAY_SIZE(emmc_ctrl_groups) },
  338. { "usb0_pwr", usb0_pwr_groups, ARRAY_SIZE(usb0_pwr_groups) },
  339. { "usb1_pwr", usb1_pwr_groups, ARRAY_SIZE(usb1_pwr_groups) },
  340. };
  341. /*
  342. * Groups code
  343. */
  344. static const struct pinctrl_ops bcm4908_pinctrl_ops = {
  345. .get_groups_count = pinctrl_generic_get_group_count,
  346. .get_group_name = pinctrl_generic_get_group_name,
  347. .get_group_pins = pinctrl_generic_get_group_pins,
  348. .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
  349. .dt_free_map = pinconf_generic_dt_free_map,
  350. };
  351. /*
  352. * Functions code
  353. */
  354. static int bcm4908_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev,
  355. unsigned int func_selector,
  356. unsigned int group_selector)
  357. {
  358. struct bcm4908_pinctrl *bcm4908_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  359. const struct bcm4908_pinctrl_grp *group;
  360. struct group_desc *group_desc;
  361. int i;
  362. group_desc = pinctrl_generic_get_group(pctrl_dev, group_selector);
  363. if (!group_desc)
  364. return -EINVAL;
  365. group = group_desc->data;
  366. mutex_lock(&bcm4908_pinctrl->mutex);
  367. for (i = 0; i < group->num_pins; i++) {
  368. u32 lsb = 0;
  369. lsb |= group->pins[i].number;
  370. lsb |= group->pins[i].function << BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT;
  371. writel(0x0, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_MSB);
  372. writel(lsb, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_LSB);
  373. writel(BCM4908_TEST_PORT_CMD_LOAD_MUX_REG,
  374. bcm4908_pinctrl->base + BCM4908_TEST_PORT_COMMAND);
  375. }
  376. mutex_unlock(&bcm4908_pinctrl->mutex);
  377. return 0;
  378. }
  379. static const struct pinmux_ops bcm4908_pinctrl_pmxops = {
  380. .get_functions_count = pinmux_generic_get_function_count,
  381. .get_function_name = pinmux_generic_get_function_name,
  382. .get_function_groups = pinmux_generic_get_function_groups,
  383. .set_mux = bcm4908_pinctrl_set_mux,
  384. };
  385. /*
  386. * Controller code
  387. */
  388. static struct pinctrl_desc bcm4908_pinctrl_desc = {
  389. .name = "bcm4908-pinctrl",
  390. .pctlops = &bcm4908_pinctrl_ops,
  391. .pmxops = &bcm4908_pinctrl_pmxops,
  392. };
  393. static const struct of_device_id bcm4908_pinctrl_of_match_table[] = {
  394. { .compatible = "brcm,bcm4908-pinctrl", },
  395. { }
  396. };
  397. static int bcm4908_pinctrl_probe(struct platform_device *pdev)
  398. {
  399. struct device *dev = &pdev->dev;
  400. struct bcm4908_pinctrl *bcm4908_pinctrl;
  401. struct pinctrl_desc *pctldesc;
  402. struct pinctrl_pin_desc *pins;
  403. char **pin_names;
  404. int i;
  405. bcm4908_pinctrl = devm_kzalloc(dev, sizeof(*bcm4908_pinctrl), GFP_KERNEL);
  406. if (!bcm4908_pinctrl)
  407. return -ENOMEM;
  408. pctldesc = &bcm4908_pinctrl->pctldesc;
  409. platform_set_drvdata(pdev, bcm4908_pinctrl);
  410. /* Set basic properties */
  411. bcm4908_pinctrl->dev = dev;
  412. bcm4908_pinctrl->base = devm_platform_ioremap_resource(pdev, 0);
  413. if (IS_ERR(bcm4908_pinctrl->base))
  414. return PTR_ERR(bcm4908_pinctrl->base);
  415. mutex_init(&bcm4908_pinctrl->mutex);
  416. memcpy(pctldesc, &bcm4908_pinctrl_desc, sizeof(*pctldesc));
  417. /* Set pinctrl properties */
  418. pin_names = devm_kasprintf_strarray(dev, "pin", BCM4908_NUM_PINS);
  419. if (IS_ERR(pin_names))
  420. return PTR_ERR(pin_names);
  421. pins = devm_kcalloc(dev, BCM4908_NUM_PINS, sizeof(*pins), GFP_KERNEL);
  422. if (!pins)
  423. return -ENOMEM;
  424. for (i = 0; i < BCM4908_NUM_PINS; i++) {
  425. pins[i].number = i;
  426. pins[i].name = pin_names[i];
  427. }
  428. pctldesc->pins = pins;
  429. pctldesc->npins = BCM4908_NUM_PINS;
  430. /* Register */
  431. bcm4908_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, bcm4908_pinctrl);
  432. if (IS_ERR(bcm4908_pinctrl->pctldev))
  433. return dev_err_probe(dev, PTR_ERR(bcm4908_pinctrl->pctldev),
  434. "Failed to register pinctrl\n");
  435. /* Groups */
  436. for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_grps); i++) {
  437. const struct bcm4908_pinctrl_grp *group = &bcm4908_pinctrl_grps[i];
  438. int *pins;
  439. int j;
  440. pins = devm_kcalloc(dev, group->num_pins, sizeof(*pins), GFP_KERNEL);
  441. if (!pins)
  442. return -ENOMEM;
  443. for (j = 0; j < group->num_pins; j++)
  444. pins[j] = group->pins[j].number;
  445. pinctrl_generic_add_group(bcm4908_pinctrl->pctldev, group->name,
  446. pins, group->num_pins, (void *)group);
  447. }
  448. /* Functions */
  449. for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_functions); i++) {
  450. const struct bcm4908_pinctrl_function *function = &bcm4908_pinctrl_functions[i];
  451. pinmux_generic_add_function(bcm4908_pinctrl->pctldev,
  452. function->name,
  453. function->groups,
  454. function->num_groups, NULL);
  455. }
  456. return 0;
  457. }
  458. static struct platform_driver bcm4908_pinctrl_driver = {
  459. .probe = bcm4908_pinctrl_probe,
  460. .driver = {
  461. .name = "bcm4908-pinctrl",
  462. .of_match_table = bcm4908_pinctrl_of_match_table,
  463. },
  464. };
  465. module_platform_driver(bcm4908_pinctrl_driver);
  466. MODULE_AUTHOR("Rafał Miłecki");
  467. MODULE_LICENSE("GPL v2");
  468. MODULE_DEVICE_TABLE(of, bcm4908_pinctrl_of_match_table);