080-v5.18-0002-pinctrl-bcm-add-driver-for-BCM4908-pinmux.patch 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. From f7e322d99f1180270fb4a3e1ae992b3116cfcf34 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
  3. Date: Mon, 24 Jan 2022 11:22:43 +0100
  4. Subject: [PATCH] pinctrl: bcm: add driver for BCM4908 pinmux
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. BCM4908 has its own pins layout so it needs a custom binding and a Linux
  9. driver.
  10. Signed-off-by: Rafał Miłecki <[email protected]>
  11. Reviewed-by: Andy Shevchenko <[email protected]>
  12. Link: https://lore.kernel.org/r/[email protected]
  13. Signed-off-by: Linus Walleij <[email protected]>
  14. ---
  15. MAINTAINERS | 1 +
  16. drivers/pinctrl/bcm/Kconfig | 14 +
  17. drivers/pinctrl/bcm/Makefile | 1 +
  18. drivers/pinctrl/bcm/pinctrl-bcm4908.c | 563 ++++++++++++++++++++++++++
  19. 4 files changed, 579 insertions(+)
  20. create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm4908.c
  21. --- a/MAINTAINERS
  22. +++ b/MAINTAINERS
  23. @@ -3579,6 +3579,7 @@ M: [email protected]
  24. L: [email protected]
  25. S: Maintained
  26. F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml
  27. +F: drivers/pinctrl/bcm/pinctrl-bcm4908.c
  28. BROADCOM BCM5301X ARM ARCHITECTURE
  29. M: Hauke Mehrtens <[email protected]>
  30. --- a/drivers/pinctrl/bcm/Kconfig
  31. +++ b/drivers/pinctrl/bcm/Kconfig
  32. @@ -29,6 +29,20 @@ config PINCTRL_BCM2835
  33. help
  34. Say Y here to enable the Broadcom BCM2835 GPIO driver.
  35. +config PINCTRL_BCM4908
  36. + tristate "Broadcom BCM4908 pinmux driver"
  37. + depends on OF && (ARCH_BCM4908 || COMPILE_TEST)
  38. + select PINMUX
  39. + select PINCONF
  40. + select GENERIC_PINCONF
  41. + select GENERIC_PINCTRL_GROUPS
  42. + select GENERIC_PINMUX_FUNCTIONS
  43. + default ARCH_BCM4908
  44. + help
  45. + Driver for BCM4908 family SoCs with integrated pin controller.
  46. +
  47. + If compiled as module it will be called pinctrl-bcm4908.
  48. +
  49. config PINCTRL_BCM63XX
  50. bool
  51. select PINMUX
  52. --- a/drivers/pinctrl/bcm/Makefile
  53. +++ b/drivers/pinctrl/bcm/Makefile
  54. @@ -3,6 +3,7 @@
  55. obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
  56. obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
  57. +obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o
  58. obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
  59. obj-$(CONFIG_PINCTRL_BCM6318) += pinctrl-bcm6318.o
  60. obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
  61. --- /dev/null
  62. +++ b/drivers/pinctrl/bcm/pinctrl-bcm4908.c
  63. @@ -0,0 +1,560 @@
  64. +// SPDX-License-Identifier: GPL-2.0
  65. +/* Copyright (C) 2021 Rafał Miłecki <[email protected]> */
  66. +
  67. +#include <linux/err.h>
  68. +#include <linux/io.h>
  69. +#include <linux/mod_devicetable.h>
  70. +#include <linux/module.h>
  71. +#include <linux/pinctrl/pinconf-generic.h>
  72. +#include <linux/pinctrl/pinctrl.h>
  73. +#include <linux/pinctrl/pinmux.h>
  74. +#include <linux/platform_device.h>
  75. +#include <linux/slab.h>
  76. +#include <linux/string_helpers.h>
  77. +
  78. +#include "../core.h"
  79. +#include "../pinmux.h"
  80. +
  81. +#define BCM4908_NUM_PINS 86
  82. +
  83. +#define BCM4908_TEST_PORT_BLOCK_EN_LSB 0x00
  84. +#define BCM4908_TEST_PORT_BLOCK_DATA_MSB 0x04
  85. +#define BCM4908_TEST_PORT_BLOCK_DATA_LSB 0x08
  86. +#define BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT 12
  87. +#define BCM4908_TEST_PORT_COMMAND 0x0c
  88. +#define BCM4908_TEST_PORT_CMD_LOAD_MUX_REG 0x00000021
  89. +
  90. +struct bcm4908_pinctrl {
  91. + struct device *dev;
  92. + void __iomem *base;
  93. + struct mutex mutex;
  94. + struct pinctrl_dev *pctldev;
  95. + struct pinctrl_desc pctldesc;
  96. +};
  97. +
  98. +/*
  99. + * Groups
  100. + */
  101. +
  102. +struct bcm4908_pinctrl_pin_setup {
  103. + unsigned int number;
  104. + unsigned int function;
  105. +};
  106. +
  107. +static const struct bcm4908_pinctrl_pin_setup led_0_pins_a[] = {
  108. + { 0, 3 },
  109. +};
  110. +
  111. +static const struct bcm4908_pinctrl_pin_setup led_1_pins_a[] = {
  112. + { 1, 3 },
  113. +};
  114. +
  115. +static const struct bcm4908_pinctrl_pin_setup led_2_pins_a[] = {
  116. + { 2, 3 },
  117. +};
  118. +
  119. +static const struct bcm4908_pinctrl_pin_setup led_3_pins_a[] = {
  120. + { 3, 3 },
  121. +};
  122. +
  123. +static const struct bcm4908_pinctrl_pin_setup led_4_pins_a[] = {
  124. + { 4, 3 },
  125. +};
  126. +
  127. +static const struct bcm4908_pinctrl_pin_setup led_5_pins_a[] = {
  128. + { 5, 3 },
  129. +};
  130. +
  131. +static const struct bcm4908_pinctrl_pin_setup led_6_pins_a[] = {
  132. + { 6, 3 },
  133. +};
  134. +
  135. +static const struct bcm4908_pinctrl_pin_setup led_7_pins_a[] = {
  136. + { 7, 3 },
  137. +};
  138. +
  139. +static const struct bcm4908_pinctrl_pin_setup led_8_pins_a[] = {
  140. + { 8, 3 },
  141. +};
  142. +
  143. +static const struct bcm4908_pinctrl_pin_setup led_9_pins_a[] = {
  144. + { 9, 3 },
  145. +};
  146. +
  147. +static const struct bcm4908_pinctrl_pin_setup led_10_pins_a[] = {
  148. + { 10, 3 },
  149. +};
  150. +
  151. +static const struct bcm4908_pinctrl_pin_setup led_11_pins_a[] = {
  152. + { 11, 3 },
  153. +};
  154. +
  155. +static const struct bcm4908_pinctrl_pin_setup led_12_pins_a[] = {
  156. + { 12, 3 },
  157. +};
  158. +
  159. +static const struct bcm4908_pinctrl_pin_setup led_13_pins_a[] = {
  160. + { 13, 3 },
  161. +};
  162. +
  163. +static const struct bcm4908_pinctrl_pin_setup led_14_pins_a[] = {
  164. + { 14, 3 },
  165. +};
  166. +
  167. +static const struct bcm4908_pinctrl_pin_setup led_15_pins_a[] = {
  168. + { 15, 3 },
  169. +};
  170. +
  171. +static const struct bcm4908_pinctrl_pin_setup led_16_pins_a[] = {
  172. + { 16, 3 },
  173. +};
  174. +
  175. +static const struct bcm4908_pinctrl_pin_setup led_17_pins_a[] = {
  176. + { 17, 3 },
  177. +};
  178. +
  179. +static const struct bcm4908_pinctrl_pin_setup led_18_pins_a[] = {
  180. + { 18, 3 },
  181. +};
  182. +
  183. +static const struct bcm4908_pinctrl_pin_setup led_19_pins_a[] = {
  184. + { 19, 3 },
  185. +};
  186. +
  187. +static const struct bcm4908_pinctrl_pin_setup led_20_pins_a[] = {
  188. + { 20, 3 },
  189. +};
  190. +
  191. +static const struct bcm4908_pinctrl_pin_setup led_21_pins_a[] = {
  192. + { 21, 3 },
  193. +};
  194. +
  195. +static const struct bcm4908_pinctrl_pin_setup led_22_pins_a[] = {
  196. + { 22, 3 },
  197. +};
  198. +
  199. +static const struct bcm4908_pinctrl_pin_setup led_23_pins_a[] = {
  200. + { 23, 3 },
  201. +};
  202. +
  203. +static const struct bcm4908_pinctrl_pin_setup led_24_pins_a[] = {
  204. + { 24, 3 },
  205. +};
  206. +
  207. +static const struct bcm4908_pinctrl_pin_setup led_25_pins_a[] = {
  208. + { 25, 3 },
  209. +};
  210. +
  211. +static const struct bcm4908_pinctrl_pin_setup led_26_pins_a[] = {
  212. + { 26, 3 },
  213. +};
  214. +
  215. +static const struct bcm4908_pinctrl_pin_setup led_27_pins_a[] = {
  216. + { 27, 3 },
  217. +};
  218. +
  219. +static const struct bcm4908_pinctrl_pin_setup led_28_pins_a[] = {
  220. + { 28, 3 },
  221. +};
  222. +
  223. +static const struct bcm4908_pinctrl_pin_setup led_29_pins_a[] = {
  224. + { 29, 3 },
  225. +};
  226. +
  227. +static const struct bcm4908_pinctrl_pin_setup led_30_pins_a[] = {
  228. + { 30, 3 },
  229. +};
  230. +
  231. +static const struct bcm4908_pinctrl_pin_setup led_31_pins_a[] = {
  232. + { 31, 3 },
  233. +};
  234. +
  235. +static const struct bcm4908_pinctrl_pin_setup led_10_pins_b[] = {
  236. + { 8, 2 },
  237. +};
  238. +
  239. +static const struct bcm4908_pinctrl_pin_setup led_11_pins_b[] = {
  240. + { 9, 2 },
  241. +};
  242. +
  243. +static const struct bcm4908_pinctrl_pin_setup led_12_pins_b[] = {
  244. + { 0, 2 },
  245. +};
  246. +
  247. +static const struct bcm4908_pinctrl_pin_setup led_13_pins_b[] = {
  248. + { 1, 2 },
  249. +};
  250. +
  251. +static const struct bcm4908_pinctrl_pin_setup led_31_pins_b[] = {
  252. + { 30, 2 },
  253. +};
  254. +
  255. +static const struct bcm4908_pinctrl_pin_setup hs_uart_pins[] = {
  256. + { 10, 0 }, /* CTS */
  257. + { 11, 0 }, /* RTS */
  258. + { 12, 0 }, /* RXD */
  259. + { 13, 0 }, /* TXD */
  260. +};
  261. +
  262. +static const struct bcm4908_pinctrl_pin_setup i2c_pins_a[] = {
  263. + { 18, 0 }, /* SDA */
  264. + { 19, 0 }, /* SCL */
  265. +};
  266. +
  267. +static const struct bcm4908_pinctrl_pin_setup i2c_pins_b[] = {
  268. + { 22, 0 }, /* SDA */
  269. + { 23, 0 }, /* SCL */
  270. +};
  271. +
  272. +static const struct bcm4908_pinctrl_pin_setup i2s_pins[] = {
  273. + { 27, 0 }, /* MCLK */
  274. + { 28, 0 }, /* LRCK */
  275. + { 29, 0 }, /* SDATA */
  276. + { 30, 0 }, /* SCLK */
  277. +};
  278. +
  279. +static const struct bcm4908_pinctrl_pin_setup nand_ctrl_pins[] = {
  280. + { 32, 0 },
  281. + { 33, 0 },
  282. + { 34, 0 },
  283. + { 43, 0 },
  284. + { 44, 0 },
  285. + { 45, 0 },
  286. + { 56, 1 },
  287. +};
  288. +
  289. +static const struct bcm4908_pinctrl_pin_setup nand_data_pins[] = {
  290. + { 35, 0 },
  291. + { 36, 0 },
  292. + { 37, 0 },
  293. + { 38, 0 },
  294. + { 39, 0 },
  295. + { 40, 0 },
  296. + { 41, 0 },
  297. + { 42, 0 },
  298. +};
  299. +
  300. +static const struct bcm4908_pinctrl_pin_setup emmc_ctrl_pins[] = {
  301. + { 46, 0 },
  302. + { 47, 0 },
  303. +};
  304. +
  305. +static const struct bcm4908_pinctrl_pin_setup usb0_pwr_pins[] = {
  306. + { 63, 0 },
  307. + { 64, 0 },
  308. +};
  309. +
  310. +static const struct bcm4908_pinctrl_pin_setup usb1_pwr_pins[] = {
  311. + { 66, 0 },
  312. + { 67, 0 },
  313. +};
  314. +
  315. +struct bcm4908_pinctrl_grp {
  316. + const char *name;
  317. + const struct bcm4908_pinctrl_pin_setup *pins;
  318. + const unsigned int num_pins;
  319. +};
  320. +
  321. +static const struct bcm4908_pinctrl_grp bcm4908_pinctrl_grps[] = {
  322. + { "led_0_grp_a", led_0_pins_a, ARRAY_SIZE(led_0_pins_a) },
  323. + { "led_1_grp_a", led_1_pins_a, ARRAY_SIZE(led_1_pins_a) },
  324. + { "led_2_grp_a", led_2_pins_a, ARRAY_SIZE(led_2_pins_a) },
  325. + { "led_3_grp_a", led_3_pins_a, ARRAY_SIZE(led_3_pins_a) },
  326. + { "led_4_grp_a", led_4_pins_a, ARRAY_SIZE(led_4_pins_a) },
  327. + { "led_5_grp_a", led_5_pins_a, ARRAY_SIZE(led_5_pins_a) },
  328. + { "led_6_grp_a", led_6_pins_a, ARRAY_SIZE(led_6_pins_a) },
  329. + { "led_7_grp_a", led_7_pins_a, ARRAY_SIZE(led_7_pins_a) },
  330. + { "led_8_grp_a", led_8_pins_a, ARRAY_SIZE(led_8_pins_a) },
  331. + { "led_9_grp_a", led_9_pins_a, ARRAY_SIZE(led_9_pins_a) },
  332. + { "led_10_grp_a", led_10_pins_a, ARRAY_SIZE(led_10_pins_a) },
  333. + { "led_11_grp_a", led_11_pins_a, ARRAY_SIZE(led_11_pins_a) },
  334. + { "led_12_grp_a", led_12_pins_a, ARRAY_SIZE(led_12_pins_a) },
  335. + { "led_13_grp_a", led_13_pins_a, ARRAY_SIZE(led_13_pins_a) },
  336. + { "led_14_grp_a", led_14_pins_a, ARRAY_SIZE(led_14_pins_a) },
  337. + { "led_15_grp_a", led_15_pins_a, ARRAY_SIZE(led_15_pins_a) },
  338. + { "led_16_grp_a", led_16_pins_a, ARRAY_SIZE(led_16_pins_a) },
  339. + { "led_17_grp_a", led_17_pins_a, ARRAY_SIZE(led_17_pins_a) },
  340. + { "led_18_grp_a", led_18_pins_a, ARRAY_SIZE(led_18_pins_a) },
  341. + { "led_19_grp_a", led_19_pins_a, ARRAY_SIZE(led_19_pins_a) },
  342. + { "led_20_grp_a", led_20_pins_a, ARRAY_SIZE(led_20_pins_a) },
  343. + { "led_21_grp_a", led_21_pins_a, ARRAY_SIZE(led_21_pins_a) },
  344. + { "led_22_grp_a", led_22_pins_a, ARRAY_SIZE(led_22_pins_a) },
  345. + { "led_23_grp_a", led_23_pins_a, ARRAY_SIZE(led_23_pins_a) },
  346. + { "led_24_grp_a", led_24_pins_a, ARRAY_SIZE(led_24_pins_a) },
  347. + { "led_25_grp_a", led_25_pins_a, ARRAY_SIZE(led_25_pins_a) },
  348. + { "led_26_grp_a", led_26_pins_a, ARRAY_SIZE(led_26_pins_a) },
  349. + { "led_27_grp_a", led_27_pins_a, ARRAY_SIZE(led_27_pins_a) },
  350. + { "led_28_grp_a", led_28_pins_a, ARRAY_SIZE(led_28_pins_a) },
  351. + { "led_29_grp_a", led_29_pins_a, ARRAY_SIZE(led_29_pins_a) },
  352. + { "led_30_grp_a", led_30_pins_a, ARRAY_SIZE(led_30_pins_a) },
  353. + { "led_31_grp_a", led_31_pins_a, ARRAY_SIZE(led_31_pins_a) },
  354. + { "led_10_grp_b", led_10_pins_b, ARRAY_SIZE(led_10_pins_b) },
  355. + { "led_11_grp_b", led_11_pins_b, ARRAY_SIZE(led_11_pins_b) },
  356. + { "led_12_grp_b", led_12_pins_b, ARRAY_SIZE(led_12_pins_b) },
  357. + { "led_13_grp_b", led_13_pins_b, ARRAY_SIZE(led_13_pins_b) },
  358. + { "led_31_grp_b", led_31_pins_b, ARRAY_SIZE(led_31_pins_b) },
  359. + { "hs_uart_grp", hs_uart_pins, ARRAY_SIZE(hs_uart_pins) },
  360. + { "i2c_grp_a", i2c_pins_a, ARRAY_SIZE(i2c_pins_a) },
  361. + { "i2c_grp_b", i2c_pins_b, ARRAY_SIZE(i2c_pins_b) },
  362. + { "i2s_grp", i2s_pins, ARRAY_SIZE(i2s_pins) },
  363. + { "nand_ctrl_grp", nand_ctrl_pins, ARRAY_SIZE(nand_ctrl_pins) },
  364. + { "nand_data_grp", nand_data_pins, ARRAY_SIZE(nand_data_pins) },
  365. + { "emmc_ctrl_grp", emmc_ctrl_pins, ARRAY_SIZE(emmc_ctrl_pins) },
  366. + { "usb0_pwr_grp", usb0_pwr_pins, ARRAY_SIZE(usb0_pwr_pins) },
  367. + { "usb1_pwr_grp", usb1_pwr_pins, ARRAY_SIZE(usb1_pwr_pins) },
  368. +};
  369. +
  370. +/*
  371. + * Functions
  372. + */
  373. +
  374. +struct bcm4908_pinctrl_function {
  375. + const char *name;
  376. + const char **groups;
  377. + const unsigned int num_groups;
  378. +};
  379. +
  380. +static const char *led_0_groups[] = { "led_0_grp_a" };
  381. +static const char *led_1_groups[] = { "led_1_grp_a" };
  382. +static const char *led_2_groups[] = { "led_2_grp_a" };
  383. +static const char *led_3_groups[] = { "led_3_grp_a" };
  384. +static const char *led_4_groups[] = { "led_4_grp_a" };
  385. +static const char *led_5_groups[] = { "led_5_grp_a" };
  386. +static const char *led_6_groups[] = { "led_6_grp_a" };
  387. +static const char *led_7_groups[] = { "led_7_grp_a" };
  388. +static const char *led_8_groups[] = { "led_8_grp_a" };
  389. +static const char *led_9_groups[] = { "led_9_grp_a" };
  390. +static const char *led_10_groups[] = { "led_10_grp_a", "led_10_grp_b" };
  391. +static const char *led_11_groups[] = { "led_11_grp_a", "led_11_grp_b" };
  392. +static const char *led_12_groups[] = { "led_12_grp_a", "led_12_grp_b" };
  393. +static const char *led_13_groups[] = { "led_13_grp_a", "led_13_grp_b" };
  394. +static const char *led_14_groups[] = { "led_14_grp_a" };
  395. +static const char *led_15_groups[] = { "led_15_grp_a" };
  396. +static const char *led_16_groups[] = { "led_16_grp_a" };
  397. +static const char *led_17_groups[] = { "led_17_grp_a" };
  398. +static const char *led_18_groups[] = { "led_18_grp_a" };
  399. +static const char *led_19_groups[] = { "led_19_grp_a" };
  400. +static const char *led_20_groups[] = { "led_20_grp_a" };
  401. +static const char *led_21_groups[] = { "led_21_grp_a" };
  402. +static const char *led_22_groups[] = { "led_22_grp_a" };
  403. +static const char *led_23_groups[] = { "led_23_grp_a" };
  404. +static const char *led_24_groups[] = { "led_24_grp_a" };
  405. +static const char *led_25_groups[] = { "led_25_grp_a" };
  406. +static const char *led_26_groups[] = { "led_26_grp_a" };
  407. +static const char *led_27_groups[] = { "led_27_grp_a" };
  408. +static const char *led_28_groups[] = { "led_28_grp_a" };
  409. +static const char *led_29_groups[] = { "led_29_grp_a" };
  410. +static const char *led_30_groups[] = { "led_30_grp_a" };
  411. +static const char *led_31_groups[] = { "led_31_grp_a", "led_31_grp_b" };
  412. +static const char *hs_uart_groups[] = { "hs_uart_grp" };
  413. +static const char *i2c_groups[] = { "i2c_grp_a", "i2c_grp_b" };
  414. +static const char *i2s_groups[] = { "i2s_grp" };
  415. +static const char *nand_ctrl_groups[] = { "nand_ctrl_grp" };
  416. +static const char *nand_data_groups[] = { "nand_data_grp" };
  417. +static const char *emmc_ctrl_groups[] = { "emmc_ctrl_grp" };
  418. +static const char *usb0_pwr_groups[] = { "usb0_pwr_grp" };
  419. +static const char *usb1_pwr_groups[] = { "usb1_pwr_grp" };
  420. +
  421. +static const struct bcm4908_pinctrl_function bcm4908_pinctrl_functions[] = {
  422. + { "led_0", led_0_groups, ARRAY_SIZE(led_0_groups) },
  423. + { "led_1", led_1_groups, ARRAY_SIZE(led_1_groups) },
  424. + { "led_2", led_2_groups, ARRAY_SIZE(led_2_groups) },
  425. + { "led_3", led_3_groups, ARRAY_SIZE(led_3_groups) },
  426. + { "led_4", led_4_groups, ARRAY_SIZE(led_4_groups) },
  427. + { "led_5", led_5_groups, ARRAY_SIZE(led_5_groups) },
  428. + { "led_6", led_6_groups, ARRAY_SIZE(led_6_groups) },
  429. + { "led_7", led_7_groups, ARRAY_SIZE(led_7_groups) },
  430. + { "led_8", led_8_groups, ARRAY_SIZE(led_8_groups) },
  431. + { "led_9", led_9_groups, ARRAY_SIZE(led_9_groups) },
  432. + { "led_10", led_10_groups, ARRAY_SIZE(led_10_groups) },
  433. + { "led_11", led_11_groups, ARRAY_SIZE(led_11_groups) },
  434. + { "led_12", led_12_groups, ARRAY_SIZE(led_12_groups) },
  435. + { "led_13", led_13_groups, ARRAY_SIZE(led_13_groups) },
  436. + { "led_14", led_14_groups, ARRAY_SIZE(led_14_groups) },
  437. + { "led_15", led_15_groups, ARRAY_SIZE(led_15_groups) },
  438. + { "led_16", led_16_groups, ARRAY_SIZE(led_16_groups) },
  439. + { "led_17", led_17_groups, ARRAY_SIZE(led_17_groups) },
  440. + { "led_18", led_18_groups, ARRAY_SIZE(led_18_groups) },
  441. + { "led_19", led_19_groups, ARRAY_SIZE(led_19_groups) },
  442. + { "led_20", led_20_groups, ARRAY_SIZE(led_20_groups) },
  443. + { "led_21", led_21_groups, ARRAY_SIZE(led_21_groups) },
  444. + { "led_22", led_22_groups, ARRAY_SIZE(led_22_groups) },
  445. + { "led_23", led_23_groups, ARRAY_SIZE(led_23_groups) },
  446. + { "led_24", led_24_groups, ARRAY_SIZE(led_24_groups) },
  447. + { "led_25", led_25_groups, ARRAY_SIZE(led_25_groups) },
  448. + { "led_26", led_26_groups, ARRAY_SIZE(led_26_groups) },
  449. + { "led_27", led_27_groups, ARRAY_SIZE(led_27_groups) },
  450. + { "led_28", led_28_groups, ARRAY_SIZE(led_28_groups) },
  451. + { "led_29", led_29_groups, ARRAY_SIZE(led_29_groups) },
  452. + { "led_30", led_30_groups, ARRAY_SIZE(led_30_groups) },
  453. + { "led_31", led_31_groups, ARRAY_SIZE(led_31_groups) },
  454. + { "hs_uart", hs_uart_groups, ARRAY_SIZE(hs_uart_groups) },
  455. + { "i2c", i2c_groups, ARRAY_SIZE(i2c_groups) },
  456. + { "i2s", i2s_groups, ARRAY_SIZE(i2s_groups) },
  457. + { "nand_ctrl", nand_ctrl_groups, ARRAY_SIZE(nand_ctrl_groups) },
  458. + { "nand_data", nand_data_groups, ARRAY_SIZE(nand_data_groups) },
  459. + { "emmc_ctrl", emmc_ctrl_groups, ARRAY_SIZE(emmc_ctrl_groups) },
  460. + { "usb0_pwr", usb0_pwr_groups, ARRAY_SIZE(usb0_pwr_groups) },
  461. + { "usb1_pwr", usb1_pwr_groups, ARRAY_SIZE(usb1_pwr_groups) },
  462. +};
  463. +
  464. +/*
  465. + * Groups code
  466. + */
  467. +
  468. +static const struct pinctrl_ops bcm4908_pinctrl_ops = {
  469. + .get_groups_count = pinctrl_generic_get_group_count,
  470. + .get_group_name = pinctrl_generic_get_group_name,
  471. + .get_group_pins = pinctrl_generic_get_group_pins,
  472. + .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
  473. + .dt_free_map = pinconf_generic_dt_free_map,
  474. +};
  475. +
  476. +/*
  477. + * Functions code
  478. + */
  479. +
  480. +static int bcm4908_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev,
  481. + unsigned int func_selector,
  482. + unsigned int group_selector)
  483. +{
  484. + struct bcm4908_pinctrl *bcm4908_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  485. + const struct bcm4908_pinctrl_grp *group;
  486. + struct group_desc *group_desc;
  487. + int i;
  488. +
  489. + group_desc = pinctrl_generic_get_group(pctrl_dev, group_selector);
  490. + if (!group_desc)
  491. + return -EINVAL;
  492. + group = group_desc->data;
  493. +
  494. + mutex_lock(&bcm4908_pinctrl->mutex);
  495. + for (i = 0; i < group->num_pins; i++) {
  496. + u32 lsb = 0;
  497. +
  498. + lsb |= group->pins[i].number;
  499. + lsb |= group->pins[i].function << BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT;
  500. +
  501. + writel(0x0, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_MSB);
  502. + writel(lsb, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_LSB);
  503. + writel(BCM4908_TEST_PORT_CMD_LOAD_MUX_REG,
  504. + bcm4908_pinctrl->base + BCM4908_TEST_PORT_COMMAND);
  505. + }
  506. + mutex_unlock(&bcm4908_pinctrl->mutex);
  507. +
  508. + return 0;
  509. +}
  510. +
  511. +static const struct pinmux_ops bcm4908_pinctrl_pmxops = {
  512. + .get_functions_count = pinmux_generic_get_function_count,
  513. + .get_function_name = pinmux_generic_get_function_name,
  514. + .get_function_groups = pinmux_generic_get_function_groups,
  515. + .set_mux = bcm4908_pinctrl_set_mux,
  516. +};
  517. +
  518. +/*
  519. + * Controller code
  520. + */
  521. +
  522. +static struct pinctrl_desc bcm4908_pinctrl_desc = {
  523. + .name = "bcm4908-pinctrl",
  524. + .pctlops = &bcm4908_pinctrl_ops,
  525. + .pmxops = &bcm4908_pinctrl_pmxops,
  526. +};
  527. +
  528. +static const struct of_device_id bcm4908_pinctrl_of_match_table[] = {
  529. + { .compatible = "brcm,bcm4908-pinctrl", },
  530. + { }
  531. +};
  532. +
  533. +static int bcm4908_pinctrl_probe(struct platform_device *pdev)
  534. +{
  535. + struct device *dev = &pdev->dev;
  536. + struct bcm4908_pinctrl *bcm4908_pinctrl;
  537. + struct pinctrl_desc *pctldesc;
  538. + struct pinctrl_pin_desc *pins;
  539. + int i;
  540. +
  541. + bcm4908_pinctrl = devm_kzalloc(dev, sizeof(*bcm4908_pinctrl), GFP_KERNEL);
  542. + if (!bcm4908_pinctrl)
  543. + return -ENOMEM;
  544. + pctldesc = &bcm4908_pinctrl->pctldesc;
  545. + platform_set_drvdata(pdev, bcm4908_pinctrl);
  546. +
  547. + /* Set basic properties */
  548. +
  549. + bcm4908_pinctrl->dev = dev;
  550. +
  551. + bcm4908_pinctrl->base = devm_platform_ioremap_resource(pdev, 0);
  552. + if (IS_ERR(bcm4908_pinctrl->base))
  553. + return PTR_ERR(bcm4908_pinctrl->base);
  554. +
  555. + mutex_init(&bcm4908_pinctrl->mutex);
  556. +
  557. + memcpy(pctldesc, &bcm4908_pinctrl_desc, sizeof(*pctldesc));
  558. +
  559. + /* Set pinctrl properties */
  560. +
  561. + pins = devm_kcalloc(dev, BCM4908_NUM_PINS, sizeof(*pins), GFP_KERNEL);
  562. + if (!pins)
  563. + return -ENOMEM;
  564. + for (i = 0; i < BCM4908_NUM_PINS; i++) {
  565. + pins[i].number = i;
  566. + pins[i].name = devm_kasprintf(dev, GFP_KERNEL, "pin-%d", i);
  567. + if (!pins[i].name)
  568. + return -ENOMEM;
  569. + }
  570. + pctldesc->pins = pins;
  571. + pctldesc->npins = BCM4908_NUM_PINS;
  572. +
  573. + /* Register */
  574. +
  575. + bcm4908_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, bcm4908_pinctrl);
  576. + if (IS_ERR(bcm4908_pinctrl->pctldev))
  577. + return dev_err_probe(dev, PTR_ERR(bcm4908_pinctrl->pctldev),
  578. + "Failed to register pinctrl\n");
  579. +
  580. + /* Groups */
  581. +
  582. + for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_grps); i++) {
  583. + const struct bcm4908_pinctrl_grp *group = &bcm4908_pinctrl_grps[i];
  584. + int *pins;
  585. + int j;
  586. +
  587. + pins = devm_kcalloc(dev, group->num_pins, sizeof(*pins), GFP_KERNEL);
  588. + if (!pins)
  589. + return -ENOMEM;
  590. + for (j = 0; j < group->num_pins; j++)
  591. + pins[j] = group->pins[j].number;
  592. +
  593. + pinctrl_generic_add_group(bcm4908_pinctrl->pctldev, group->name,
  594. + pins, group->num_pins, (void *)group);
  595. + }
  596. +
  597. + /* Functions */
  598. +
  599. + for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_functions); i++) {
  600. + const struct bcm4908_pinctrl_function *function = &bcm4908_pinctrl_functions[i];
  601. +
  602. + pinmux_generic_add_function(bcm4908_pinctrl->pctldev,
  603. + function->name,
  604. + function->groups,
  605. + function->num_groups, NULL);
  606. + }
  607. +
  608. + return 0;
  609. +}
  610. +
  611. +static struct platform_driver bcm4908_pinctrl_driver = {
  612. + .probe = bcm4908_pinctrl_probe,
  613. + .driver = {
  614. + .name = "bcm4908-pinctrl",
  615. + .of_match_table = bcm4908_pinctrl_of_match_table,
  616. + },
  617. +};
  618. +
  619. +module_platform_driver(bcm4908_pinctrl_driver);
  620. +
  621. +MODULE_AUTHOR("Rafał Miłecki");
  622. +MODULE_LICENSE("GPL v2");
  623. +MODULE_DEVICE_TABLE(of, bcm4908_pinctrl_of_match_table);