OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | @@ -351,6 +351,7 @@ config PINCTRL_RK805 |
||
25 | |||
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 | @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805) += pinctrl-r |
||
35 | |||
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 |