130-pinctrl-add-bcm63xx-base-code.patch 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
  2. From: Jonas Gorski <[email protected]>
  3. Date: Fri, 24 Jun 2016 22:07:42 +0200
  4. Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
  5. Setup directory and add a helper for bcm63xx pinctrl support.
  6. Signed-off-by: Jonas Gorski <[email protected]>
  7. ---
  8. drivers/pinctrl/Kconfig | 1 +
  9. drivers/pinctrl/Makefile | 1 +
  10. drivers/pinctrl/bcm63xx/Kconfig | 3 +
  11. drivers/pinctrl/bcm63xx/Makefile | 1 +
  12. drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
  13. drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
  14. 7 files changed, 163 insertions(+)
  15. create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
  16. create mode 100644 drivers/pinctrl/bcm63xx/Makefile
  17. create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
  18. create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
  19. --- a/drivers/pinctrl/Kconfig
  20. +++ b/drivers/pinctrl/Kconfig
  21. @@ -258,6 +258,7 @@ config PINCTRL_ZYNQ
  22. source "drivers/pinctrl/aspeed/Kconfig"
  23. source "drivers/pinctrl/bcm/Kconfig"
  24. +source "drivers/pinctrl/bcm63xx/Kconfig"
  25. source "drivers/pinctrl/berlin/Kconfig"
  26. source "drivers/pinctrl/freescale/Kconfig"
  27. source "drivers/pinctrl/intel/Kconfig"
  28. --- a/drivers/pinctrl/Makefile
  29. +++ b/drivers/pinctrl/Makefile
  30. @@ -39,6 +39,7 @@ obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zy
  31. obj-$(CONFIG_ARCH_ASPEED) += aspeed/
  32. obj-y += bcm/
  33. +obj-y += bcm63xx/
  34. obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
  35. obj-y += freescale/
  36. obj-$(CONFIG_X86) += intel/
  37. --- /dev/null
  38. +++ b/drivers/pinctrl/bcm63xx/Kconfig
  39. @@ -0,0 +1,3 @@
  40. +config PINCTRL_BCM63XX
  41. + bool
  42. + select GPIO_GENERIC
  43. --- /dev/null
  44. +++ b/drivers/pinctrl/bcm63xx/Makefile
  45. @@ -0,0 +1 @@
  46. +obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
  47. --- /dev/null
  48. +++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
  49. @@ -0,0 +1,155 @@
  50. +/*
  51. + * This file is subject to the terms and conditions of the GNU General Public
  52. + * License. See the file "COPYING" in the main directory of this archive
  53. + * for more details.
  54. + *
  55. + * Copyright (C) 2016 Jonas Gorski <[email protected]>
  56. + */
  57. +
  58. +#include <linux/bitops.h>
  59. +#include <linux/device.h>
  60. +#include <linux/gpio/driver.h>
  61. +#include <linux/of_irq.h>
  62. +
  63. +#include "pinctrl-bcm63xx.h"
  64. +#include "../core.h"
  65. +
  66. +#define BANK_SIZE sizeof(u32)
  67. +#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
  68. +
  69. +#ifdef CONFIG_OF
  70. +static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
  71. + const struct of_phandle_args *gpiospec,
  72. + u32 *flags)
  73. +{
  74. + struct gpio_chip *base = gpiochip_get_data(gc);
  75. + int pin = gpiospec->args[0];
  76. +
  77. + if (gc != &base[pin / PINS_PER_BANK])
  78. + return -EINVAL;
  79. +
  80. + pin = pin % PINS_PER_BANK;
  81. +
  82. + if (pin >= gc->ngpio)
  83. + return -EINVAL;
  84. +
  85. + if (flags)
  86. + *flags = gpiospec->args[1];
  87. +
  88. + return pin;
  89. +}
  90. +#endif
  91. +
  92. +static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  93. +{
  94. + struct gpio_chip *base = gpiochip_get_data(chip);
  95. + char irq_name[7]; /* "gpioXX" */
  96. +
  97. + /* FIXME: this is ugly */
  98. + sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
  99. + return of_irq_get_byname(chip->of_node, irq_name);
  100. +}
  101. +
  102. +static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
  103. + void __iomem *dirout, void __iomem *data,
  104. + size_t sz, int ngpio)
  105. +
  106. +{
  107. + int banks, chips, i, ret = -EINVAL;
  108. +
  109. + chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
  110. + banks = sz / BANK_SIZE;
  111. +
  112. + for (i = 0; i < chips; i++) {
  113. + int offset, pins;
  114. + int reg_offset;
  115. + char *label;
  116. +
  117. + label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
  118. + if (!label)
  119. + return -ENOMEM;
  120. +
  121. + offset = i * PINS_PER_BANK;
  122. + pins = min_t(int, ngpio - offset, PINS_PER_BANK);
  123. +
  124. + /* the registers are treated like a huge big endian register */
  125. + reg_offset = (banks - i - 1) * BANK_SIZE;
  126. +
  127. + ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
  128. + NULL, NULL, dirout + reg_offset, NULL,
  129. + BGPIOF_BIG_ENDIAN_BYTE_ORDER);
  130. + if (ret)
  131. + return ret;
  132. +
  133. + gc[i].request = gpiochip_generic_request;
  134. + gc[i].free = gpiochip_generic_free;
  135. +
  136. + if (of_get_property(dev->of_node, "interrupt-names", NULL))
  137. + gc[i].to_irq = bcm63xx_gpio_to_irq;
  138. +
  139. +#ifdef CONFIG_OF
  140. + gc[i].of_gpio_n_cells = 2;
  141. + gc[i].of_xlate = bcm63xx_gpio_of_xlate;
  142. +#endif
  143. +
  144. + gc[i].label = label;
  145. + gc[i].ngpio = pins;
  146. +
  147. + devm_gpiochip_add_data(dev, &gc[i], gc);
  148. + }
  149. +
  150. + return 0;
  151. +}
  152. +
  153. +static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
  154. + int ngpio)
  155. +{
  156. + int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
  157. +
  158. + for (i = 0; i < chips; i++) {
  159. + int offset, pins;
  160. +
  161. + offset = i * PINS_PER_BANK;
  162. + pins = min_t(int, ngpio - offset, PINS_PER_BANK);
  163. +
  164. + gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
  165. + }
  166. +}
  167. +
  168. +struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
  169. + struct pinctrl_desc *desc,
  170. + void *priv, struct gpio_chip *gc,
  171. + int ngpio)
  172. +{
  173. + struct pinctrl_dev *pctldev;
  174. + struct resource *res;
  175. + void __iomem *dirout, *data;
  176. + size_t sz;
  177. + int ret;
  178. +
  179. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
  180. + dirout = devm_ioremap_resource(&pdev->dev, res);
  181. + if (IS_ERR(dirout))
  182. + return ERR_CAST(dirout);
  183. +
  184. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
  185. + data = devm_ioremap_resource(&pdev->dev, res);
  186. + if (IS_ERR(data))
  187. + return ERR_CAST(data);
  188. +
  189. + sz = resource_size(res);
  190. +
  191. + ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
  192. + if (ret)
  193. + return ERR_PTR(ret);
  194. +
  195. + pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
  196. + if (IS_ERR(pctldev))
  197. + return pctldev;
  198. +
  199. + bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
  200. +
  201. + dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
  202. +
  203. + return pctldev;
  204. +}
  205. --- /dev/null
  206. +++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
  207. @@ -0,0 +1,14 @@
  208. +#ifndef __PINCTRL_BCM63XX
  209. +#define __PINCTRL_BCM63XX
  210. +
  211. +#include <linux/kernel.h>
  212. +#include <linux/gpio.h>
  213. +#include <linux/pinctrl/pinctrl.h>
  214. +#include <linux/platform_device.h>
  215. +
  216. +struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
  217. + struct pinctrl_desc *desc,
  218. + void *priv, struct gpio_chip *gc,
  219. + int ngpio);
  220. +
  221. +#endif