140-pinctrl-add-a-pincontrol-driver-for-BCM6368.patch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. From 90be3cb4f1a45b8be4a4ec264cd66c2f8e893fcb Mon Sep 17 00:00:00 2001
  2. From: Jonas Gorski <[email protected]>
  3. Date: Fri, 24 Jun 2016 22:18:25 +0200
  4. Subject: [PATCH 11/16] pinctrl: add a pincontrol driver for BCM6368
  5. Add a pincontrol driver for BCM6368. BCM6368 allows muxing the first 32
  6. GPIOs onto alternative functions. Not all are documented.
  7. Signed-off-by: Jonas Gorski <[email protected]>
  8. ---
  9. drivers/pinctrl/bcm63xx/Kconfig | 15 +
  10. drivers/pinctrl/bcm63xx/Makefile | 1 +
  11. drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c | 573 ++++++++++++++++++++++++++++++
  12. 3 files changed, 589 insertions(+)
  13. create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
  14. --- a/drivers/pinctrl/bcm63xx/Kconfig
  15. +++ b/drivers/pinctrl/bcm63xx/Kconfig
  16. @@ -30,3 +30,18 @@ config PINCTRL_BCM6362
  17. select PINCONF
  18. select PINCTRL_BCM63XX
  19. select GENERIC_PINCONF
  20. +
  21. +config PINCTRL_BCM6368
  22. + bool "BCM6368 pincontrol driver" if COMPILE_TEST
  23. + select PINMUX
  24. + select PINCONF
  25. + select PINCTRL_BCM63XX
  26. + select GENERIC_PINCONF
  27. + select MFD_SYSCON
  28. +
  29. +config PINCTRL_BCM63268
  30. + bool "BCM63268 pincontrol driver" if COMPILE_TEST
  31. + select PINMUX
  32. + select PINCONF
  33. + select PINCTRL_BCM63XX
  34. + select GENERIC_PINCONF
  35. --- a/drivers/pinctrl/bcm63xx/Makefile
  36. +++ b/drivers/pinctrl/bcm63xx/Makefile
  37. @@ -3,3 +3,4 @@ obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl
  38. obj-$(CONFIG_PINCTRL_BCM6348) += pinctrl-bcm6348.o
  39. obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
  40. obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
  41. +obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
  42. --- /dev/null
  43. +++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
  44. @@ -0,0 +1,573 @@
  45. +/*
  46. + * This file is subject to the terms and conditions of the GNU General Public
  47. + * License. See the file "COPYING" in the main directory of this archive
  48. + * for more details.
  49. + *
  50. + * Copyright (C) 2016 Jonas Gorski <[email protected]>
  51. + */
  52. +
  53. +#include <linux/bitops.h>
  54. +#include <linux/kernel.h>
  55. +#include <linux/gpio.h>
  56. +#include <linux/mfd/syscon.h>
  57. +#include <linux/of.h>
  58. +#include <linux/of_address.h>
  59. +#include <linux/of_gpio.h>
  60. +#include <linux/pinctrl/pinconf.h>
  61. +#include <linux/pinctrl/pinconf-generic.h>
  62. +#include <linux/pinctrl/pinmux.h>
  63. +#include <linux/pinctrl/machine.h>
  64. +#include <linux/platform_device.h>
  65. +#include <linux/regmap.h>
  66. +#include <linux/slab.h>
  67. +#include <linux/spinlock.h>
  68. +
  69. +#include "../core.h"
  70. +#include "../pinctrl-utils.h"
  71. +
  72. +#include "pinctrl-bcm63xx.h"
  73. +
  74. +#define BCM6368_NGPIO 38
  75. +
  76. +#define BCM6368_BASEMODE_MASK 0x7
  77. +#define BCM6368_BASEMODE_GPIO 0x0
  78. +#define BCM6368_BASEMODE_UART1 0x1
  79. +
  80. +struct bcm6368_pingroup {
  81. + const char *name;
  82. + const unsigned * const pins;
  83. + const unsigned num_pins;
  84. +};
  85. +
  86. +struct bcm6368_function {
  87. + const char *name;
  88. + const char * const *groups;
  89. + const unsigned num_groups;
  90. +
  91. + unsigned dir_out:16;
  92. + unsigned basemode:3;
  93. +};
  94. +
  95. +struct bcm6368_pinctrl {
  96. + struct pinctrl_dev *pctldev;
  97. + struct pinctrl_desc desc;
  98. +
  99. + void __iomem *mode;
  100. + struct regmap_field *overlay;
  101. +
  102. + /* register access lock */
  103. + spinlock_t lock;
  104. +
  105. + struct gpio_chip gpio[2];
  106. +};
  107. +
  108. +#define BCM6368_BASEMODE_PIN(a, b) \
  109. + { \
  110. + .number = a, \
  111. + .name = b, \
  112. + .drv_data = (void *)true \
  113. + }
  114. +
  115. +static const struct pinctrl_pin_desc bcm6368_pins[] = {
  116. + PINCTRL_PIN(0, "gpio0"),
  117. + PINCTRL_PIN(1, "gpio1"),
  118. + PINCTRL_PIN(2, "gpio2"),
  119. + PINCTRL_PIN(3, "gpio3"),
  120. + PINCTRL_PIN(4, "gpio4"),
  121. + PINCTRL_PIN(5, "gpio5"),
  122. + PINCTRL_PIN(6, "gpio6"),
  123. + PINCTRL_PIN(7, "gpio7"),
  124. + PINCTRL_PIN(8, "gpio8"),
  125. + PINCTRL_PIN(9, "gpio9"),
  126. + PINCTRL_PIN(10, "gpio10"),
  127. + PINCTRL_PIN(11, "gpio11"),
  128. + PINCTRL_PIN(12, "gpio12"),
  129. + PINCTRL_PIN(13, "gpio13"),
  130. + PINCTRL_PIN(14, "gpio14"),
  131. + PINCTRL_PIN(15, "gpio15"),
  132. + PINCTRL_PIN(16, "gpio16"),
  133. + PINCTRL_PIN(17, "gpio17"),
  134. + PINCTRL_PIN(18, "gpio18"),
  135. + PINCTRL_PIN(19, "gpio19"),
  136. + PINCTRL_PIN(20, "gpio20"),
  137. + PINCTRL_PIN(21, "gpio21"),
  138. + PINCTRL_PIN(22, "gpio22"),
  139. + PINCTRL_PIN(23, "gpio23"),
  140. + PINCTRL_PIN(24, "gpio24"),
  141. + PINCTRL_PIN(25, "gpio25"),
  142. + PINCTRL_PIN(26, "gpio26"),
  143. + PINCTRL_PIN(27, "gpio27"),
  144. + PINCTRL_PIN(28, "gpio28"),
  145. + PINCTRL_PIN(29, "gpio29"),
  146. + BCM6368_BASEMODE_PIN(30, "gpio30"),
  147. + BCM6368_BASEMODE_PIN(31, "gpio31"),
  148. + BCM6368_BASEMODE_PIN(32, "gpio32"),
  149. + BCM6368_BASEMODE_PIN(33, "gpio33"),
  150. + PINCTRL_PIN(34, "gpio34"),
  151. + PINCTRL_PIN(35, "gpio35"),
  152. + PINCTRL_PIN(36, "gpio36"),
  153. + PINCTRL_PIN(37, "gpio37"),
  154. +};
  155. +
  156. +static unsigned gpio0_pins[] = { 0 };
  157. +static unsigned gpio1_pins[] = { 1 };
  158. +static unsigned gpio2_pins[] = { 2 };
  159. +static unsigned gpio3_pins[] = { 3 };
  160. +static unsigned gpio4_pins[] = { 4 };
  161. +static unsigned gpio5_pins[] = { 5 };
  162. +static unsigned gpio6_pins[] = { 6 };
  163. +static unsigned gpio7_pins[] = { 7 };
  164. +static unsigned gpio8_pins[] = { 8 };
  165. +static unsigned gpio9_pins[] = { 9 };
  166. +static unsigned gpio10_pins[] = { 10 };
  167. +static unsigned gpio11_pins[] = { 11 };
  168. +static unsigned gpio12_pins[] = { 12 };
  169. +static unsigned gpio13_pins[] = { 13 };
  170. +static unsigned gpio14_pins[] = { 14 };
  171. +static unsigned gpio15_pins[] = { 15 };
  172. +static unsigned gpio16_pins[] = { 16 };
  173. +static unsigned gpio17_pins[] = { 17 };
  174. +static unsigned gpio18_pins[] = { 18 };
  175. +static unsigned gpio19_pins[] = { 19 };
  176. +static unsigned gpio20_pins[] = { 20 };
  177. +static unsigned gpio21_pins[] = { 21 };
  178. +static unsigned gpio22_pins[] = { 22 };
  179. +static unsigned gpio23_pins[] = { 23 };
  180. +static unsigned gpio24_pins[] = { 24 };
  181. +static unsigned gpio25_pins[] = { 25 };
  182. +static unsigned gpio26_pins[] = { 26 };
  183. +static unsigned gpio27_pins[] = { 27 };
  184. +static unsigned gpio28_pins[] = { 28 };
  185. +static unsigned gpio29_pins[] = { 29 };
  186. +static unsigned gpio30_pins[] = { 30 };
  187. +static unsigned gpio31_pins[] = { 31 };
  188. +static unsigned uart1_grp_pins[] = { 30, 31, 32, 33 };
  189. +
  190. +#define BCM6368_GROUP(n) \
  191. + { \
  192. + .name = #n, \
  193. + .pins = n##_pins, \
  194. + .num_pins = ARRAY_SIZE(n##_pins), \
  195. + }
  196. +
  197. +static struct bcm6368_pingroup bcm6368_groups[] = {
  198. + BCM6368_GROUP(gpio0),
  199. + BCM6368_GROUP(gpio1),
  200. + BCM6368_GROUP(gpio2),
  201. + BCM6368_GROUP(gpio3),
  202. + BCM6368_GROUP(gpio4),
  203. + BCM6368_GROUP(gpio5),
  204. + BCM6368_GROUP(gpio6),
  205. + BCM6368_GROUP(gpio7),
  206. + BCM6368_GROUP(gpio8),
  207. + BCM6368_GROUP(gpio9),
  208. + BCM6368_GROUP(gpio10),
  209. + BCM6368_GROUP(gpio11),
  210. + BCM6368_GROUP(gpio12),
  211. + BCM6368_GROUP(gpio13),
  212. + BCM6368_GROUP(gpio14),
  213. + BCM6368_GROUP(gpio15),
  214. + BCM6368_GROUP(gpio16),
  215. + BCM6368_GROUP(gpio17),
  216. + BCM6368_GROUP(gpio18),
  217. + BCM6368_GROUP(gpio19),
  218. + BCM6368_GROUP(gpio20),
  219. + BCM6368_GROUP(gpio21),
  220. + BCM6368_GROUP(gpio22),
  221. + BCM6368_GROUP(gpio23),
  222. + BCM6368_GROUP(gpio24),
  223. + BCM6368_GROUP(gpio25),
  224. + BCM6368_GROUP(gpio26),
  225. + BCM6368_GROUP(gpio27),
  226. + BCM6368_GROUP(gpio28),
  227. + BCM6368_GROUP(gpio29),
  228. + BCM6368_GROUP(gpio30),
  229. + BCM6368_GROUP(gpio31),
  230. + BCM6368_GROUP(uart1_grp),
  231. +};
  232. +
  233. +static const char * const analog_afe_0_groups[] = {
  234. + "gpio0",
  235. +};
  236. +
  237. +static const char * const analog_afe_1_groups[] = {
  238. + "gpio1",
  239. +};
  240. +
  241. +static const char * const sys_irq_groups[] = {
  242. + "gpio2",
  243. +};
  244. +
  245. +static const char * const serial_led_data_groups[] = {
  246. + "gpio3",
  247. +};
  248. +
  249. +static const char * const serial_led_clk_groups[] = {
  250. + "gpio4",
  251. +};
  252. +
  253. +static const char * const inet_led_groups[] = {
  254. + "gpio5",
  255. +};
  256. +
  257. +static const char * const ephy0_led_groups[] = {
  258. + "gpio6",
  259. +};
  260. +
  261. +static const char * const ephy1_led_groups[] = {
  262. + "gpio7",
  263. +};
  264. +
  265. +static const char * const ephy2_led_groups[] = {
  266. + "gpio8",
  267. +};
  268. +
  269. +static const char * const ephy3_led_groups[] = {
  270. + "gpio9",
  271. +};
  272. +
  273. +static const char * const robosw_led_data_groups[] = {
  274. + "gpio10",
  275. +};
  276. +
  277. +static const char * const robosw_led_clk_groups[] = {
  278. + "gpio11",
  279. +};
  280. +
  281. +static const char * const robosw_led0_groups[] = {
  282. + "gpio12",
  283. +};
  284. +
  285. +static const char * const robosw_led1_groups[] = {
  286. + "gpio13",
  287. +};
  288. +
  289. +static const char * const usb_device_led_groups[] = {
  290. + "gpio14",
  291. +};
  292. +
  293. +static const char * const pci_req1_groups[] = {
  294. + "gpio16",
  295. +};
  296. +
  297. +static const char * const pci_gnt1_groups[] = {
  298. + "gpio17",
  299. +};
  300. +
  301. +static const char * const pci_intb_groups[] = {
  302. + "gpio18",
  303. +};
  304. +
  305. +static const char * const pci_req0_groups[] = {
  306. + "gpio19",
  307. +};
  308. +
  309. +static const char * const pci_gnt0_groups[] = {
  310. + "gpio20",
  311. +};
  312. +
  313. +static const char * const pcmcia_cd1_groups[] = {
  314. + "gpio22",
  315. +};
  316. +
  317. +static const char * const pcmcia_cd2_groups[] = {
  318. + "gpio23",
  319. +};
  320. +
  321. +static const char * const pcmcia_vs1_groups[] = {
  322. + "gpio24",
  323. +};
  324. +
  325. +static const char * const pcmcia_vs2_groups[] = {
  326. + "gpio25",
  327. +};
  328. +
  329. +static const char * const ebi_cs2_groups[] = {
  330. + "gpio26",
  331. +};
  332. +
  333. +static const char * const ebi_cs3_groups[] = {
  334. + "gpio27",
  335. +};
  336. +
  337. +static const char * const spi_cs2_groups[] = {
  338. + "gpio28",
  339. +};
  340. +
  341. +static const char * const spi_cs3_groups[] = {
  342. + "gpio29",
  343. +};
  344. +
  345. +static const char * const spi_cs4_groups[] = {
  346. + "gpio30",
  347. +};
  348. +
  349. +static const char * const spi_cs5_groups[] = {
  350. + "gpio31",
  351. +};
  352. +
  353. +static const char * const uart1_groups[] = {
  354. + "uart1_grp",
  355. +};
  356. +
  357. +#define BCM6368_FUN(n, out) \
  358. + { \
  359. + .name = #n, \
  360. + .groups = n##_groups, \
  361. + .num_groups = ARRAY_SIZE(n##_groups), \
  362. + .dir_out = out, \
  363. + }
  364. +
  365. +#define BCM6368_BASEMODE_FUN(n, val, out) \
  366. + { \
  367. + .name = #n, \
  368. + .groups = n##_groups, \
  369. + .num_groups = ARRAY_SIZE(n##_groups), \
  370. + .basemode = BCM6368_BASEMODE_##val, \
  371. + .dir_out = out, \
  372. + }
  373. +
  374. +static const struct bcm6368_function bcm6368_funcs[] = {
  375. + BCM6368_FUN(analog_afe_0, 1),
  376. + BCM6368_FUN(analog_afe_1, 1),
  377. + BCM6368_FUN(sys_irq, 1),
  378. + BCM6368_FUN(serial_led_data, 1),
  379. + BCM6368_FUN(serial_led_clk, 1),
  380. + BCM6368_FUN(inet_led, 1),
  381. + BCM6368_FUN(ephy0_led, 1),
  382. + BCM6368_FUN(ephy1_led, 1),
  383. + BCM6368_FUN(ephy2_led, 1),
  384. + BCM6368_FUN(ephy3_led, 1),
  385. + BCM6368_FUN(robosw_led_data, 1),
  386. + BCM6368_FUN(robosw_led_clk, 1),
  387. + BCM6368_FUN(robosw_led0, 1),
  388. + BCM6368_FUN(robosw_led1, 1),
  389. + BCM6368_FUN(usb_device_led, 1),
  390. + BCM6368_FUN(pci_req1, 0),
  391. + BCM6368_FUN(pci_gnt1, 0),
  392. + BCM6368_FUN(pci_intb, 0),
  393. + BCM6368_FUN(pci_req0, 0),
  394. + BCM6368_FUN(pci_gnt0, 0),
  395. + BCM6368_FUN(pcmcia_cd1, 0),
  396. + BCM6368_FUN(pcmcia_cd2, 0),
  397. + BCM6368_FUN(pcmcia_vs1, 0),
  398. + BCM6368_FUN(pcmcia_vs2, 0),
  399. + BCM6368_FUN(ebi_cs2, 1),
  400. + BCM6368_FUN(ebi_cs3, 1),
  401. + BCM6368_FUN(spi_cs2, 1),
  402. + BCM6368_FUN(spi_cs3, 1),
  403. + BCM6368_FUN(spi_cs4, 1),
  404. + BCM6368_FUN(spi_cs5, 1),
  405. + BCM6368_BASEMODE_FUN(uart1, UART1, 0x6),
  406. +};
  407. +
  408. +static int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
  409. +{
  410. + return ARRAY_SIZE(bcm6368_groups);
  411. +}
  412. +
  413. +static const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
  414. + unsigned group)
  415. +{
  416. + return bcm6368_groups[group].name;
  417. +}
  418. +
  419. +static int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
  420. + unsigned group, const unsigned **pins,
  421. + unsigned *num_pins)
  422. +{
  423. + *pins = bcm6368_groups[group].pins;
  424. + *num_pins = bcm6368_groups[group].num_pins;
  425. +
  426. + return 0;
  427. +}
  428. +
  429. +static int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
  430. +{
  431. + return ARRAY_SIZE(bcm6368_funcs);
  432. +}
  433. +
  434. +static const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
  435. + unsigned selector)
  436. +{
  437. + return bcm6368_funcs[selector].name;
  438. +}
  439. +
  440. +static int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev,
  441. + unsigned selector,
  442. + const char * const **groups,
  443. + unsigned * const num_groups)
  444. +{
  445. + *groups = bcm6368_funcs[selector].groups;
  446. + *num_groups = bcm6368_funcs[selector].num_groups;
  447. +
  448. + return 0;
  449. +}
  450. +
  451. +static void bcm6368_rmw_mux(struct bcm6368_pinctrl *pctl, void __iomem *reg,
  452. + u32 mask, u32 val)
  453. +{
  454. + u32 tmp;
  455. +
  456. + tmp = __raw_readl(reg);
  457. + tmp &= ~mask;
  458. + tmp |= (val & mask);
  459. + __raw_writel(tmp, reg);
  460. +}
  461. +
  462. +static int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev,
  463. + unsigned selector, unsigned group)
  464. +{
  465. + struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  466. + const struct bcm6368_pingroup *grp = &bcm6368_groups[group];
  467. + const struct bcm6368_function *fun = &bcm6368_funcs[selector];
  468. + unsigned long flags;
  469. + int i, pin;
  470. +
  471. + spin_lock_irqsave(&pctl->lock, flags);
  472. + if (fun->basemode) {
  473. + u32 mask = 0;
  474. +
  475. + for (i = 0; i < grp->num_pins; i++) {
  476. + pin = grp->pins[i];
  477. + if (pin < 32)
  478. + mask |= BIT(pin);
  479. + }
  480. +
  481. + bcm6368_rmw_mux(pctl, pctl->mode, mask, 0);
  482. + regmap_field_write(pctl->overlay, fun->basemode);
  483. + } else {
  484. + pin = grp->pins[0];
  485. +
  486. + if (bcm6368_pins[pin].drv_data)
  487. + regmap_field_write(pctl->overlay,
  488. + BCM6368_BASEMODE_GPIO);
  489. +
  490. + bcm6368_rmw_mux(pctl, pctl->mode, BIT(pin), BIT(pin));
  491. + }
  492. + spin_unlock_irqrestore(&pctl->lock, flags);
  493. +
  494. + for (pin = 0; pin < grp->num_pins; pin++) {
  495. + int hw_gpio = bcm6368_pins[pin].number;
  496. + struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
  497. +
  498. + if (fun->dir_out & BIT(pin))
  499. + gc->direction_output(gc, hw_gpio % 32, 0);
  500. + else
  501. + gc->direction_input(gc, hw_gpio % 32);
  502. + }
  503. +
  504. + return 0;
  505. +}
  506. +
  507. +static int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev,
  508. + struct pinctrl_gpio_range *range,
  509. + unsigned offset)
  510. +{
  511. + struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  512. + unsigned long flags;
  513. +
  514. + if (offset >= 32 && !bcm6368_pins[offset].drv_data)
  515. + return 0;
  516. +
  517. + spin_lock_irqsave(&pctl->lock, flags);
  518. + /* disable all functions using this pin */
  519. + if (offset < 32)
  520. + bcm6368_rmw_mux(pctl, pctl->mode, BIT(offset), 0);
  521. +
  522. + if (bcm6368_pins[offset].drv_data)
  523. + regmap_field_write(pctl->overlay, BCM6368_BASEMODE_GPIO);
  524. +
  525. + spin_unlock_irqrestore(&pctl->lock, flags);
  526. +
  527. + return 0;
  528. +}
  529. +
  530. +static struct pinctrl_ops bcm6368_pctl_ops = {
  531. + .get_groups_count = bcm6368_pinctrl_get_group_count,
  532. + .get_group_name = bcm6368_pinctrl_get_group_name,
  533. + .get_group_pins = bcm6368_pinctrl_get_group_pins,
  534. +#ifdef CONFIG_OF
  535. + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
  536. + .dt_free_map = pinctrl_utils_free_map,
  537. +#endif
  538. +};
  539. +
  540. +static struct pinmux_ops bcm6368_pmx_ops = {
  541. + .get_functions_count = bcm6368_pinctrl_get_func_count,
  542. + .get_function_name = bcm6368_pinctrl_get_func_name,
  543. + .get_function_groups = bcm6368_pinctrl_get_groups,
  544. + .set_mux = bcm6368_pinctrl_set_mux,
  545. + .gpio_request_enable = bcm6368_gpio_request_enable,
  546. + .strict = true,
  547. +};
  548. +
  549. +static int bcm6368_pinctrl_probe(struct platform_device *pdev)
  550. +{
  551. + struct bcm6368_pinctrl *pctl;
  552. + struct resource *res;
  553. + void __iomem *mode;
  554. + struct regmap *basemode;
  555. + struct reg_field overlay = REG_FIELD(0, 0, 3);
  556. +
  557. + if (pdev->dev.of_node)
  558. + basemode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
  559. + "brcm,gpiobasemode");
  560. + else
  561. + basemode = syscon_regmap_lookup_by_pdevname("syscon.b00000b8");
  562. +
  563. + if (IS_ERR(basemode))
  564. + return PTR_ERR(basemode);
  565. +
  566. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
  567. + mode = devm_ioremap_resource(&pdev->dev, res);
  568. + if (IS_ERR(mode))
  569. + return PTR_ERR(mode);
  570. +
  571. + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
  572. + if (!pctl)
  573. + return -ENOMEM;
  574. +
  575. + pctl->overlay = devm_regmap_field_alloc(&pdev->dev, basemode, overlay);
  576. + if (IS_ERR(pctl->overlay))
  577. + return PTR_ERR(pctl->overlay);
  578. +
  579. + spin_lock_init(&pctl->lock);
  580. +
  581. + pctl->mode = mode;
  582. +
  583. + /* disable all muxes by default */
  584. + __raw_writel(0, pctl->mode);
  585. +
  586. + pctl->desc.name = dev_name(&pdev->dev);
  587. + pctl->desc.owner = THIS_MODULE;
  588. + pctl->desc.pctlops = &bcm6368_pctl_ops;
  589. + pctl->desc.pmxops = &bcm6368_pmx_ops;
  590. +
  591. + pctl->desc.npins = ARRAY_SIZE(bcm6368_pins);
  592. + pctl->desc.pins = bcm6368_pins;
  593. +
  594. + platform_set_drvdata(pdev, pctl);
  595. +
  596. + pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
  597. + pctl->gpio, BCM6368_NGPIO);
  598. + if (IS_ERR(pctl->pctldev))
  599. + return PTR_ERR(pctl->pctldev);
  600. +
  601. + return 0;
  602. +}
  603. +
  604. +static const struct of_device_id bcm6368_pinctrl_match[] = {
  605. + { .compatible = "brcm,bcm6368-pinctrl", },
  606. + { },
  607. +};
  608. +
  609. +static struct platform_driver bcm6368_pinctrl_driver = {
  610. + .probe = bcm6368_pinctrl_probe,
  611. + .driver = {
  612. + .name = "bcm6368-pinctrl",
  613. + .of_match_table = bcm6368_pinctrl_match,
  614. + },
  615. +};
  616. +
  617. +builtin_platform_driver(bcm6368_pinctrl_driver);