080-v4.20-0001-pinctrl-bcm-add-Northstar-driver.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. From c12fb1774deaa9c9408b19db8d43d3612f6e47a0 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
  3. Date: Wed, 26 Sep 2018 21:31:03 +0200
  4. Subject: [PATCH] pinctrl: bcm: add Northstar driver
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. This driver provides support for Northstar mux controller. It differs
  9. from Northstar Plus one so a new binding and driver were needed.
  10. Signed-off-by: Rafał Miłecki <[email protected]>
  11. Signed-off-by: Linus Walleij <[email protected]>
  12. ---
  13. drivers/pinctrl/bcm/Kconfig | 13 ++
  14. drivers/pinctrl/bcm/Makefile | 1 +
  15. drivers/pinctrl/bcm/pinctrl-ns.c | 372 +++++++++++++++++++++++++++++++++++++++
  16. 3 files changed, 386 insertions(+)
  17. create mode 100644 drivers/pinctrl/bcm/pinctrl-ns.c
  18. --- a/drivers/pinctrl/bcm/Kconfig
  19. +++ b/drivers/pinctrl/bcm/Kconfig
  20. @@ -73,6 +73,19 @@ config PINCTRL_CYGNUS_MUX
  21. configuration, with the exception that certain individual pins
  22. can be overridden to GPIO function
  23. +config PINCTRL_NS
  24. + bool "Broadcom Northstar pins driver"
  25. + depends on OF && (ARCH_BCM_5301X || COMPILE_TEST)
  26. + select PINMUX
  27. + select GENERIC_PINCONF
  28. + default ARCH_BCM_5301X
  29. + help
  30. + Say yes here to enable the Broadcom NS SoC pins driver.
  31. +
  32. + The Broadcom Northstar pins driver supports muxing multi-purpose pins
  33. + that can be used for various functions (e.g. SPI, I2C, UART) as well
  34. + as GPIOs.
  35. +
  36. config PINCTRL_NSP_GPIO
  37. bool "Broadcom NSP GPIO (with PINCONF) driver"
  38. depends on OF_GPIO && (ARCH_BCM_NSP || COMPILE_TEST)
  39. --- a/drivers/pinctrl/bcm/Makefile
  40. +++ b/drivers/pinctrl/bcm/Makefile
  41. @@ -5,6 +5,7 @@ obj-$(CONFIG_PINCTRL_BCM281XX) += pinct
  42. obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
  43. obj-$(CONFIG_PINCTRL_IPROC_GPIO) += pinctrl-iproc-gpio.o
  44. obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o
  45. +obj-$(CONFIG_PINCTRL_NS) += pinctrl-ns.o
  46. obj-$(CONFIG_PINCTRL_NSP_GPIO) += pinctrl-nsp-gpio.o
  47. obj-$(CONFIG_PINCTRL_NS2_MUX) += pinctrl-ns2-mux.o
  48. obj-$(CONFIG_PINCTRL_NSP_MUX) += pinctrl-nsp-mux.o
  49. --- /dev/null
  50. +++ b/drivers/pinctrl/bcm/pinctrl-ns.c
  51. @@ -0,0 +1,372 @@
  52. +// SPDX-License-Identifier: GPL-2.0
  53. +/*
  54. + * Copyright (C) 2018 Rafał Miłecki <[email protected]>
  55. + */
  56. +
  57. +#include <linux/err.h>
  58. +#include <linux/io.h>
  59. +#include <linux/module.h>
  60. +#include <linux/of.h>
  61. +#include <linux/of_device.h>
  62. +#include <linux/pinctrl/pinconf-generic.h>
  63. +#include <linux/pinctrl/pinctrl.h>
  64. +#include <linux/pinctrl/pinmux.h>
  65. +#include <linux/platform_device.h>
  66. +#include <linux/slab.h>
  67. +
  68. +#define FLAG_BCM4708 BIT(1)
  69. +#define FLAG_BCM4709 BIT(2)
  70. +#define FLAG_BCM53012 BIT(3)
  71. +
  72. +struct ns_pinctrl {
  73. + struct device *dev;
  74. + unsigned int chipset_flag;
  75. + struct pinctrl_dev *pctldev;
  76. + void __iomem *base;
  77. +
  78. + struct pinctrl_desc pctldesc;
  79. + struct ns_pinctrl_group *groups;
  80. + unsigned int num_groups;
  81. + struct ns_pinctrl_function *functions;
  82. + unsigned int num_functions;
  83. +};
  84. +
  85. +/*
  86. + * Pins
  87. + */
  88. +
  89. +static const struct pinctrl_pin_desc ns_pinctrl_pins[] = {
  90. + { 0, "spi_clk", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  91. + { 1, "spi_ss", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  92. + { 2, "spi_mosi", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  93. + { 3, "spi_miso", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  94. + { 4, "i2c_scl", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  95. + { 5, "i2c_sda", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  96. + { 6, "mdc", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  97. + { 7, "mdio", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  98. + { 8, "pwm0", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  99. + { 9, "pwm1", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  100. + { 10, "pwm2", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  101. + { 11, "pwm3", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  102. + { 12, "uart1_rx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  103. + { 13, "uart1_tx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  104. + { 14, "uart1_cts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  105. + { 15, "uart1_rts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
  106. + { 16, "uart2_rx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  107. + { 17, "uart2_tx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  108. +/* TODO { ??, "xtal_out", (void *)(FLAG_BCM4709) }, */
  109. + { 22, "sdio_pwr", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  110. + { 23, "sdio_en_1p8v", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
  111. +};
  112. +
  113. +/*
  114. + * Groups
  115. + */
  116. +
  117. +struct ns_pinctrl_group {
  118. + const char *name;
  119. + const unsigned int *pins;
  120. + const unsigned int num_pins;
  121. + unsigned int chipsets;
  122. +};
  123. +
  124. +static const unsigned int spi_pins[] = { 0, 1, 2, 3 };
  125. +static const unsigned int i2c_pins[] = { 4, 5 };
  126. +static const unsigned int mdio_pins[] = { 6, 7 };
  127. +static const unsigned int pwm0_pins[] = { 8 };
  128. +static const unsigned int pwm1_pins[] = { 9 };
  129. +static const unsigned int pwm2_pins[] = { 10 };
  130. +static const unsigned int pwm3_pins[] = { 11 };
  131. +static const unsigned int uart1_pins[] = { 12, 13, 14, 15 };
  132. +static const unsigned int uart2_pins[] = { 16, 17 };
  133. +static const unsigned int sdio_pwr_pins[] = { 22 };
  134. +static const unsigned int sdio_1p8v_pins[] = { 23 };
  135. +
  136. +#define NS_GROUP(_name, _pins, _chipsets) \
  137. +{ \
  138. + .name = _name, \
  139. + .pins = _pins, \
  140. + .num_pins = ARRAY_SIZE(_pins), \
  141. + .chipsets = _chipsets, \
  142. +}
  143. +
  144. +static const struct ns_pinctrl_group ns_pinctrl_groups[] = {
  145. + NS_GROUP("spi_grp", spi_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  146. + NS_GROUP("i2c_grp", i2c_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  147. + NS_GROUP("mdio_grp", mdio_pins, FLAG_BCM4709 | FLAG_BCM53012),
  148. + NS_GROUP("pwm0_grp", pwm0_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  149. + NS_GROUP("pwm1_grp", pwm1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  150. + NS_GROUP("pwm2_grp", pwm2_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  151. + NS_GROUP("pwm3_grp", pwm3_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  152. + NS_GROUP("uart1_grp", uart1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  153. + NS_GROUP("uart2_grp", uart2_pins, FLAG_BCM4709 | FLAG_BCM53012),
  154. + NS_GROUP("sdio_pwr_grp", sdio_pwr_pins, FLAG_BCM4709 | FLAG_BCM53012),
  155. + NS_GROUP("sdio_1p8v_grp", sdio_1p8v_pins, FLAG_BCM4709 | FLAG_BCM53012),
  156. +};
  157. +
  158. +/*
  159. + * Functions
  160. + */
  161. +
  162. +struct ns_pinctrl_function {
  163. + const char *name;
  164. + const char * const *groups;
  165. + const unsigned int num_groups;
  166. + unsigned int chipsets;
  167. +};
  168. +
  169. +static const char * const spi_groups[] = { "spi_grp" };
  170. +static const char * const i2c_groups[] = { "i2c_grp" };
  171. +static const char * const mdio_groups[] = { "mdio_grp" };
  172. +static const char * const pwm_groups[] = { "pwm0_grp", "pwm1_grp", "pwm2_grp",
  173. + "pwm3_grp" };
  174. +static const char * const uart1_groups[] = { "uart1_grp" };
  175. +static const char * const uart2_groups[] = { "uart2_grp" };
  176. +static const char * const sdio_groups[] = { "sdio_pwr_grp", "sdio_1p8v_grp" };
  177. +
  178. +#define NS_FUNCTION(_name, _groups, _chipsets) \
  179. +{ \
  180. + .name = _name, \
  181. + .groups = _groups, \
  182. + .num_groups = ARRAY_SIZE(_groups), \
  183. + .chipsets = _chipsets, \
  184. +}
  185. +
  186. +static const struct ns_pinctrl_function ns_pinctrl_functions[] = {
  187. + NS_FUNCTION("spi", spi_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  188. + NS_FUNCTION("i2c", i2c_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  189. + NS_FUNCTION("mdio", mdio_groups, FLAG_BCM4709 | FLAG_BCM53012),
  190. + NS_FUNCTION("pwm", pwm_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  191. + NS_FUNCTION("uart1", uart1_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
  192. + NS_FUNCTION("uart2", uart2_groups, FLAG_BCM4709 | FLAG_BCM53012),
  193. + NS_FUNCTION("sdio", sdio_groups, FLAG_BCM4709 | FLAG_BCM53012),
  194. +};
  195. +
  196. +/*
  197. + * Groups code
  198. + */
  199. +
  200. +static int ns_pinctrl_get_groups_count(struct pinctrl_dev *pctrl_dev)
  201. +{
  202. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  203. +
  204. + return ns_pinctrl->num_groups;
  205. +}
  206. +
  207. +static const char *ns_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev,
  208. + unsigned int selector)
  209. +{
  210. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  211. +
  212. + return ns_pinctrl->groups[selector].name;
  213. +}
  214. +
  215. +static int ns_pinctrl_get_group_pins(struct pinctrl_dev *pctrl_dev,
  216. + unsigned int selector,
  217. + const unsigned int **pins,
  218. + unsigned int *num_pins)
  219. +{
  220. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  221. +
  222. + *pins = ns_pinctrl->groups[selector].pins;
  223. + *num_pins = ns_pinctrl->groups[selector].num_pins;
  224. +
  225. + return 0;
  226. +}
  227. +
  228. +static const struct pinctrl_ops ns_pinctrl_ops = {
  229. + .get_groups_count = ns_pinctrl_get_groups_count,
  230. + .get_group_name = ns_pinctrl_get_group_name,
  231. + .get_group_pins = ns_pinctrl_get_group_pins,
  232. + .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
  233. + .dt_free_map = pinconf_generic_dt_free_map,
  234. +};
  235. +
  236. +/*
  237. + * Functions code
  238. + */
  239. +
  240. +static int ns_pinctrl_get_functions_count(struct pinctrl_dev *pctrl_dev)
  241. +{
  242. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  243. +
  244. + return ns_pinctrl->num_functions;
  245. +}
  246. +
  247. +static const char *ns_pinctrl_get_function_name(struct pinctrl_dev *pctrl_dev,
  248. + unsigned int selector)
  249. +{
  250. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  251. +
  252. + return ns_pinctrl->functions[selector].name;
  253. +}
  254. +
  255. +static int ns_pinctrl_get_function_groups(struct pinctrl_dev *pctrl_dev,
  256. + unsigned int selector,
  257. + const char * const **groups,
  258. + unsigned * const num_groups)
  259. +{
  260. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  261. +
  262. + *groups = ns_pinctrl->functions[selector].groups;
  263. + *num_groups = ns_pinctrl->functions[selector].num_groups;
  264. +
  265. + return 0;
  266. +}
  267. +
  268. +static int ns_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev,
  269. + unsigned int func_select,
  270. + unsigned int grp_select)
  271. +{
  272. + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  273. + u32 unset = 0;
  274. + u32 tmp;
  275. + int i;
  276. +
  277. + for (i = 0; i < ns_pinctrl->groups[grp_select].num_pins; i++) {
  278. + int pin_number = ns_pinctrl->groups[grp_select].pins[i];
  279. +
  280. + unset |= BIT(pin_number);
  281. + }
  282. +
  283. + tmp = readl(ns_pinctrl->base);
  284. + tmp &= ~unset;
  285. + writel(tmp, ns_pinctrl->base);
  286. +
  287. + return 0;
  288. +}
  289. +
  290. +static const struct pinmux_ops ns_pinctrl_pmxops = {
  291. + .get_functions_count = ns_pinctrl_get_functions_count,
  292. + .get_function_name = ns_pinctrl_get_function_name,
  293. + .get_function_groups = ns_pinctrl_get_function_groups,
  294. + .set_mux = ns_pinctrl_set_mux,
  295. +};
  296. +
  297. +/*
  298. + * Controller code
  299. + */
  300. +
  301. +static struct pinctrl_desc ns_pinctrl_desc = {
  302. + .name = "pinctrl-ns",
  303. + .pctlops = &ns_pinctrl_ops,
  304. + .pmxops = &ns_pinctrl_pmxops,
  305. +};
  306. +
  307. +static const struct of_device_id ns_pinctrl_of_match_table[] = {
  308. + { .compatible = "brcm,bcm4708-pinmux", .data = (void *)FLAG_BCM4708, },
  309. + { .compatible = "brcm,bcm4709-pinmux", .data = (void *)FLAG_BCM4709, },
  310. + { .compatible = "brcm,bcm53012-pinmux", .data = (void *)FLAG_BCM53012, },
  311. + { }
  312. +};
  313. +
  314. +static int ns_pinctrl_probe(struct platform_device *pdev)
  315. +{
  316. + struct device *dev = &pdev->dev;
  317. + const struct of_device_id *of_id;
  318. + struct ns_pinctrl *ns_pinctrl;
  319. + struct pinctrl_desc *pctldesc;
  320. + struct pinctrl_pin_desc *pin;
  321. + struct ns_pinctrl_group *group;
  322. + struct ns_pinctrl_function *function;
  323. + struct resource *res;
  324. + int i;
  325. +
  326. + ns_pinctrl = devm_kzalloc(dev, sizeof(*ns_pinctrl), GFP_KERNEL);
  327. + if (!ns_pinctrl)
  328. + return -ENOMEM;
  329. + pctldesc = &ns_pinctrl->pctldesc;
  330. + platform_set_drvdata(pdev, ns_pinctrl);
  331. +
  332. + /* Set basic properties */
  333. +
  334. + ns_pinctrl->dev = dev;
  335. +
  336. + of_id = of_match_device(ns_pinctrl_of_match_table, dev);
  337. + if (!of_id)
  338. + return -EINVAL;
  339. + ns_pinctrl->chipset_flag = (unsigned int)of_id->data;
  340. +
  341. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  342. + "cru_gpio_control");
  343. + ns_pinctrl->base = devm_ioremap_resource(dev, res);
  344. + if (IS_ERR(ns_pinctrl->base)) {
  345. + dev_err(dev, "Failed to map pinctrl regs\n");
  346. + return PTR_ERR(ns_pinctrl->base);
  347. + }
  348. +
  349. + memcpy(pctldesc, &ns_pinctrl_desc, sizeof(*pctldesc));
  350. +
  351. + /* Set pinctrl properties */
  352. +
  353. + pctldesc->pins = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_pins),
  354. + sizeof(struct pinctrl_pin_desc),
  355. + GFP_KERNEL);
  356. + if (!pctldesc->pins)
  357. + return -ENOMEM;
  358. + for (i = 0, pin = (struct pinctrl_pin_desc *)&pctldesc->pins[0];
  359. + i < ARRAY_SIZE(ns_pinctrl_pins); i++) {
  360. + const struct pinctrl_pin_desc *src = &ns_pinctrl_pins[i];
  361. + unsigned int chipsets = (unsigned int)src->drv_data;
  362. +
  363. + if (chipsets & ns_pinctrl->chipset_flag) {
  364. + memcpy(pin++, src, sizeof(*src));
  365. + pctldesc->npins++;
  366. + }
  367. + }
  368. +
  369. + ns_pinctrl->groups = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_groups),
  370. + sizeof(struct ns_pinctrl_group),
  371. + GFP_KERNEL);
  372. + if (!ns_pinctrl->groups)
  373. + return -ENOMEM;
  374. + for (i = 0, group = &ns_pinctrl->groups[0];
  375. + i < ARRAY_SIZE(ns_pinctrl_groups); i++) {
  376. + const struct ns_pinctrl_group *src = &ns_pinctrl_groups[i];
  377. +
  378. + if (src->chipsets & ns_pinctrl->chipset_flag) {
  379. + memcpy(group++, src, sizeof(*src));
  380. + ns_pinctrl->num_groups++;
  381. + }
  382. + }
  383. +
  384. + ns_pinctrl->functions = devm_kcalloc(dev,
  385. + ARRAY_SIZE(ns_pinctrl_functions),
  386. + sizeof(struct ns_pinctrl_function),
  387. + GFP_KERNEL);
  388. + if (!ns_pinctrl->functions)
  389. + return -ENOMEM;
  390. + for (i = 0, function = &ns_pinctrl->functions[0];
  391. + i < ARRAY_SIZE(ns_pinctrl_functions); i++) {
  392. + const struct ns_pinctrl_function *src = &ns_pinctrl_functions[i];
  393. +
  394. + if (src->chipsets & ns_pinctrl->chipset_flag) {
  395. + memcpy(function++, src, sizeof(*src));
  396. + ns_pinctrl->num_functions++;
  397. + }
  398. + }
  399. +
  400. + /* Register */
  401. +
  402. + ns_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, ns_pinctrl);
  403. + if (IS_ERR(ns_pinctrl->pctldev)) {
  404. + dev_err(dev, "Failed to register pinctrl\n");
  405. + return PTR_ERR(ns_pinctrl->pctldev);
  406. + }
  407. +
  408. + return 0;
  409. +}
  410. +
  411. +static struct platform_driver ns_pinctrl_driver = {
  412. + .probe = ns_pinctrl_probe,
  413. + .driver = {
  414. + .name = "ns-pinmux",
  415. + .of_match_table = ns_pinctrl_of_match_table,
  416. + },
  417. +};
  418. +
  419. +module_platform_driver(ns_pinctrl_driver);
  420. +
  421. +MODULE_AUTHOR("Rafał Miłecki");
  422. +MODULE_LICENSE("GPL v2");
  423. +MODULE_DEVICE_TABLE(of, ns_pinctrl_of_match_table);