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