diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-03-09 11:46:54 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-26 09:56:53 -0400 |
commit | 9a95e8d25a140ba95654b34b44f531d0c485c7a7 (patch) | |
tree | a106ff15a9bad40cea35e3ef47a670a7bb512950 | |
parent | 9a1651dcc123e8650d8da0b31fd6dc94940a935d (diff) |
gpio: remove etraxfs driver
The cris architecture is getting removed, so we no longer need the
etraxfs driver.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt | 22 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 9 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-etraxfs.c | 475 |
4 files changed, 0 insertions, 507 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt b/Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt deleted file mode 100644 index 170194af3027..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | Axis ETRAX FS General I/O controller bindings | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: one of: | ||
6 | - "axis,etraxfs-gio" | ||
7 | - "axis,artpec3-gio" | ||
8 | - reg: Physical base address and length of the controller's registers. | ||
9 | - #gpio-cells: Should be 3 | ||
10 | - The first cell is the gpio offset number. | ||
11 | - The second cell is reserved and is currently unused. | ||
12 | - The third cell is the port number (hex). | ||
13 | - gpio-controller: Marks the device node as a GPIO controller. | ||
14 | |||
15 | Example: | ||
16 | |||
17 | gio: gpio@b001a000 { | ||
18 | compatible = "axis,etraxfs-gio"; | ||
19 | reg = <0xb001a000 0x1000>; | ||
20 | gpio-controller; | ||
21 | #gpio-cells = <3>; | ||
22 | }; | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8dbb2280538d..68d812b38be7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -170,15 +170,6 @@ config GPIO_EP93XX | |||
170 | depends on ARCH_EP93XX | 170 | depends on ARCH_EP93XX |
171 | select GPIO_GENERIC | 171 | select GPIO_GENERIC |
172 | 172 | ||
173 | config GPIO_ETRAXFS | ||
174 | bool "Axis ETRAX FS General I/O" | ||
175 | depends on CRIS || COMPILE_TEST | ||
176 | depends on OF_GPIO | ||
177 | select GPIO_GENERIC | ||
178 | select GPIOLIB_IRQCHIP | ||
179 | help | ||
180 | Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. | ||
181 | |||
182 | config GPIO_EXAR | 173 | config GPIO_EXAR |
183 | tristate "Support for GPIO pins on XR17V352/354/358" | 174 | tristate "Support for GPIO pins on XR17V352/354/358" |
184 | depends on SERIAL_8250_EXAR | 175 | depends on SERIAL_8250_EXAR |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index cccb0d40846c..db8c9d4ea2ef 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -46,7 +46,6 @@ obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o | |||
46 | obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o | 46 | obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o |
47 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 47 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
48 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 48 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
49 | obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o | ||
50 | obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o | 49 | obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o |
51 | obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o | 50 | obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o |
52 | obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o | 51 | obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o |
diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c deleted file mode 100644 index 94db1bf4bfdb..000000000000 --- a/drivers/gpio/gpio-etraxfs.c +++ /dev/null | |||
@@ -1,475 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/gpio/driver.h> | ||
5 | #include <linux/of_gpio.h> | ||
6 | #include <linux/io.h> | ||
7 | #include <linux/interrupt.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | |||
10 | #define ETRAX_FS_rw_pa_dout 0 | ||
11 | #define ETRAX_FS_r_pa_din 4 | ||
12 | #define ETRAX_FS_rw_pa_oe 8 | ||
13 | #define ETRAX_FS_rw_intr_cfg 12 | ||
14 | #define ETRAX_FS_rw_intr_mask 16 | ||
15 | #define ETRAX_FS_rw_ack_intr 20 | ||
16 | #define ETRAX_FS_r_intr 24 | ||
17 | #define ETRAX_FS_r_masked_intr 28 | ||
18 | #define ETRAX_FS_rw_pb_dout 32 | ||
19 | #define ETRAX_FS_r_pb_din 36 | ||
20 | #define ETRAX_FS_rw_pb_oe 40 | ||
21 | #define ETRAX_FS_rw_pc_dout 48 | ||
22 | #define ETRAX_FS_r_pc_din 52 | ||
23 | #define ETRAX_FS_rw_pc_oe 56 | ||
24 | #define ETRAX_FS_rw_pd_dout 64 | ||
25 | #define ETRAX_FS_r_pd_din 68 | ||
26 | #define ETRAX_FS_rw_pd_oe 72 | ||
27 | #define ETRAX_FS_rw_pe_dout 80 | ||
28 | #define ETRAX_FS_r_pe_din 84 | ||
29 | #define ETRAX_FS_rw_pe_oe 88 | ||
30 | |||
31 | #define ARTPEC3_r_pa_din 0 | ||
32 | #define ARTPEC3_rw_pa_dout 4 | ||
33 | #define ARTPEC3_rw_pa_oe 8 | ||
34 | #define ARTPEC3_r_pb_din 44 | ||
35 | #define ARTPEC3_rw_pb_dout 48 | ||
36 | #define ARTPEC3_rw_pb_oe 52 | ||
37 | #define ARTPEC3_r_pc_din 88 | ||
38 | #define ARTPEC3_rw_pc_dout 92 | ||
39 | #define ARTPEC3_rw_pc_oe 96 | ||
40 | #define ARTPEC3_r_pd_din 116 | ||
41 | #define ARTPEC3_rw_intr_cfg 120 | ||
42 | #define ARTPEC3_rw_intr_pins 124 | ||
43 | #define ARTPEC3_rw_intr_mask 128 | ||
44 | #define ARTPEC3_rw_ack_intr 132 | ||
45 | #define ARTPEC3_r_masked_intr 140 | ||
46 | |||
47 | #define GIO_CFG_OFF 0 | ||
48 | #define GIO_CFG_HI 1 | ||
49 | #define GIO_CFG_LO 2 | ||
50 | #define GIO_CFG_SET 3 | ||
51 | #define GIO_CFG_POSEDGE 5 | ||
52 | #define GIO_CFG_NEGEDGE 6 | ||
53 | #define GIO_CFG_ANYEDGE 7 | ||
54 | |||
55 | struct etraxfs_gpio_info; | ||
56 | |||
57 | struct etraxfs_gpio_block { | ||
58 | raw_spinlock_t lock; | ||
59 | u32 mask; | ||
60 | u32 cfg; | ||
61 | u32 pins; | ||
62 | unsigned int group[8]; | ||
63 | |||
64 | void __iomem *regs; | ||
65 | const struct etraxfs_gpio_info *info; | ||
66 | }; | ||
67 | |||
68 | struct etraxfs_gpio_chip { | ||
69 | struct gpio_chip gc; | ||
70 | struct etraxfs_gpio_block *block; | ||
71 | }; | ||
72 | |||
73 | struct etraxfs_gpio_port { | ||
74 | const char *label; | ||
75 | unsigned int oe; | ||
76 | unsigned int dout; | ||
77 | unsigned int din; | ||
78 | unsigned int ngpio; | ||
79 | }; | ||
80 | |||
81 | struct etraxfs_gpio_info { | ||
82 | unsigned int num_ports; | ||
83 | const struct etraxfs_gpio_port *ports; | ||
84 | |||
85 | unsigned int rw_ack_intr; | ||
86 | unsigned int rw_intr_mask; | ||
87 | unsigned int rw_intr_cfg; | ||
88 | unsigned int rw_intr_pins; | ||
89 | unsigned int r_masked_intr; | ||
90 | }; | ||
91 | |||
92 | static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { | ||
93 | { | ||
94 | .label = "A", | ||
95 | .ngpio = 8, | ||
96 | .oe = ETRAX_FS_rw_pa_oe, | ||
97 | .dout = ETRAX_FS_rw_pa_dout, | ||
98 | .din = ETRAX_FS_r_pa_din, | ||
99 | }, | ||
100 | { | ||
101 | .label = "B", | ||
102 | .ngpio = 18, | ||
103 | .oe = ETRAX_FS_rw_pb_oe, | ||
104 | .dout = ETRAX_FS_rw_pb_dout, | ||
105 | .din = ETRAX_FS_r_pb_din, | ||
106 | }, | ||
107 | { | ||
108 | .label = "C", | ||
109 | .ngpio = 18, | ||
110 | .oe = ETRAX_FS_rw_pc_oe, | ||
111 | .dout = ETRAX_FS_rw_pc_dout, | ||
112 | .din = ETRAX_FS_r_pc_din, | ||
113 | }, | ||
114 | { | ||
115 | .label = "D", | ||
116 | .ngpio = 18, | ||
117 | .oe = ETRAX_FS_rw_pd_oe, | ||
118 | .dout = ETRAX_FS_rw_pd_dout, | ||
119 | .din = ETRAX_FS_r_pd_din, | ||
120 | }, | ||
121 | { | ||
122 | .label = "E", | ||
123 | .ngpio = 18, | ||
124 | .oe = ETRAX_FS_rw_pe_oe, | ||
125 | .dout = ETRAX_FS_rw_pe_dout, | ||
126 | .din = ETRAX_FS_r_pe_din, | ||
127 | }, | ||
128 | }; | ||
129 | |||
130 | static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = { | ||
131 | .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), | ||
132 | .ports = etraxfs_gpio_etraxfs_ports, | ||
133 | .rw_ack_intr = ETRAX_FS_rw_ack_intr, | ||
134 | .rw_intr_mask = ETRAX_FS_rw_intr_mask, | ||
135 | .rw_intr_cfg = ETRAX_FS_rw_intr_cfg, | ||
136 | .r_masked_intr = ETRAX_FS_r_masked_intr, | ||
137 | }; | ||
138 | |||
139 | static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = { | ||
140 | { | ||
141 | .label = "A", | ||
142 | .ngpio = 32, | ||
143 | .oe = ARTPEC3_rw_pa_oe, | ||
144 | .dout = ARTPEC3_rw_pa_dout, | ||
145 | .din = ARTPEC3_r_pa_din, | ||
146 | }, | ||
147 | { | ||
148 | .label = "B", | ||
149 | .ngpio = 32, | ||
150 | .oe = ARTPEC3_rw_pb_oe, | ||
151 | .dout = ARTPEC3_rw_pb_dout, | ||
152 | .din = ARTPEC3_r_pb_din, | ||
153 | }, | ||
154 | { | ||
155 | .label = "C", | ||
156 | .ngpio = 16, | ||
157 | .oe = ARTPEC3_rw_pc_oe, | ||
158 | .dout = ARTPEC3_rw_pc_dout, | ||
159 | .din = ARTPEC3_r_pc_din, | ||
160 | }, | ||
161 | { | ||
162 | .label = "D", | ||
163 | .ngpio = 32, | ||
164 | .din = ARTPEC3_r_pd_din, | ||
165 | }, | ||
166 | }; | ||
167 | |||
168 | static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = { | ||
169 | .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports), | ||
170 | .ports = etraxfs_gpio_artpec3_ports, | ||
171 | .rw_ack_intr = ARTPEC3_rw_ack_intr, | ||
172 | .rw_intr_mask = ARTPEC3_rw_intr_mask, | ||
173 | .rw_intr_cfg = ARTPEC3_rw_intr_cfg, | ||
174 | .r_masked_intr = ARTPEC3_r_masked_intr, | ||
175 | .rw_intr_pins = ARTPEC3_rw_intr_pins, | ||
176 | }; | ||
177 | |||
178 | static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc) | ||
179 | { | ||
180 | return gc->label[0] - 'A'; | ||
181 | } | ||
182 | |||
183 | static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, | ||
184 | const struct of_phandle_args *gpiospec, | ||
185 | u32 *flags) | ||
186 | { | ||
187 | /* | ||
188 | * Port numbers are A to E, and the properties are integers, so we | ||
189 | * specify them as 0xA - 0xE. | ||
190 | */ | ||
191 | if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2]) | ||
192 | return -EINVAL; | ||
193 | |||
194 | return of_gpio_simple_xlate(gc, gpiospec, flags); | ||
195 | } | ||
196 | |||
197 | static const struct of_device_id etraxfs_gpio_of_table[] = { | ||
198 | { | ||
199 | .compatible = "axis,etraxfs-gio", | ||
200 | .data = &etraxfs_gpio_etraxfs, | ||
201 | }, | ||
202 | { | ||
203 | .compatible = "axis,artpec3-gio", | ||
204 | .data = &etraxfs_gpio_artpec3, | ||
205 | }, | ||
206 | {}, | ||
207 | }; | ||
208 | |||
209 | static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio) | ||
210 | { | ||
211 | return gpio % 8; | ||
212 | } | ||
213 | |||
214 | static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip, | ||
215 | unsigned int gpio) | ||
216 | { | ||
217 | return 4 * etraxfs_gpio_chip_to_port(&chip->gc) + gpio / 8; | ||
218 | } | ||
219 | |||
220 | static void etraxfs_gpio_irq_ack(struct irq_data *d) | ||
221 | { | ||
222 | struct etraxfs_gpio_chip *chip = | ||
223 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
224 | struct etraxfs_gpio_block *block = chip->block; | ||
225 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
226 | |||
227 | writel(BIT(grpirq), block->regs + block->info->rw_ack_intr); | ||
228 | } | ||
229 | |||
230 | static void etraxfs_gpio_irq_mask(struct irq_data *d) | ||
231 | { | ||
232 | struct etraxfs_gpio_chip *chip = | ||
233 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
234 | struct etraxfs_gpio_block *block = chip->block; | ||
235 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
236 | |||
237 | raw_spin_lock(&block->lock); | ||
238 | block->mask &= ~BIT(grpirq); | ||
239 | writel(block->mask, block->regs + block->info->rw_intr_mask); | ||
240 | raw_spin_unlock(&block->lock); | ||
241 | } | ||
242 | |||
243 | static void etraxfs_gpio_irq_unmask(struct irq_data *d) | ||
244 | { | ||
245 | struct etraxfs_gpio_chip *chip = | ||
246 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
247 | struct etraxfs_gpio_block *block = chip->block; | ||
248 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
249 | |||
250 | raw_spin_lock(&block->lock); | ||
251 | block->mask |= BIT(grpirq); | ||
252 | writel(block->mask, block->regs + block->info->rw_intr_mask); | ||
253 | raw_spin_unlock(&block->lock); | ||
254 | } | ||
255 | |||
256 | static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) | ||
257 | { | ||
258 | struct etraxfs_gpio_chip *chip = | ||
259 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
260 | struct etraxfs_gpio_block *block = chip->block; | ||
261 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
262 | u32 cfg; | ||
263 | |||
264 | switch (type) { | ||
265 | case IRQ_TYPE_EDGE_RISING: | ||
266 | cfg = GIO_CFG_POSEDGE; | ||
267 | break; | ||
268 | case IRQ_TYPE_EDGE_FALLING: | ||
269 | cfg = GIO_CFG_NEGEDGE; | ||
270 | break; | ||
271 | case IRQ_TYPE_EDGE_BOTH: | ||
272 | cfg = GIO_CFG_ANYEDGE; | ||
273 | break; | ||
274 | case IRQ_TYPE_LEVEL_LOW: | ||
275 | cfg = GIO_CFG_LO; | ||
276 | break; | ||
277 | case IRQ_TYPE_LEVEL_HIGH: | ||
278 | cfg = GIO_CFG_HI; | ||
279 | break; | ||
280 | default: | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | raw_spin_lock(&block->lock); | ||
285 | block->cfg &= ~(0x7 << (grpirq * 3)); | ||
286 | block->cfg |= (cfg << (grpirq * 3)); | ||
287 | writel(block->cfg, block->regs + block->info->rw_intr_cfg); | ||
288 | raw_spin_unlock(&block->lock); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int etraxfs_gpio_irq_request_resources(struct irq_data *d) | ||
294 | { | ||
295 | struct etraxfs_gpio_chip *chip = | ||
296 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
297 | struct etraxfs_gpio_block *block = chip->block; | ||
298 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
299 | int ret = -EBUSY; | ||
300 | |||
301 | raw_spin_lock(&block->lock); | ||
302 | if (block->group[grpirq]) | ||
303 | goto out; | ||
304 | |||
305 | ret = gpiochip_lock_as_irq(&chip->gc, d->hwirq); | ||
306 | if (ret) | ||
307 | goto out; | ||
308 | |||
309 | block->group[grpirq] = d->irq; | ||
310 | if (block->info->rw_intr_pins) { | ||
311 | unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq); | ||
312 | |||
313 | block->pins &= ~(0xf << (grpirq * 4)); | ||
314 | block->pins |= (pin << (grpirq * 4)); | ||
315 | |||
316 | writel(block->pins, block->regs + block->info->rw_intr_pins); | ||
317 | } | ||
318 | |||
319 | out: | ||
320 | raw_spin_unlock(&block->lock); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | static void etraxfs_gpio_irq_release_resources(struct irq_data *d) | ||
325 | { | ||
326 | struct etraxfs_gpio_chip *chip = | ||
327 | gpiochip_get_data(irq_data_get_irq_chip_data(d)); | ||
328 | struct etraxfs_gpio_block *block = chip->block; | ||
329 | unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); | ||
330 | |||
331 | raw_spin_lock(&block->lock); | ||
332 | block->group[grpirq] = 0; | ||
333 | gpiochip_unlock_as_irq(&chip->gc, d->hwirq); | ||
334 | raw_spin_unlock(&block->lock); | ||
335 | } | ||
336 | |||
337 | static struct irq_chip etraxfs_gpio_irq_chip = { | ||
338 | .name = "gpio-etraxfs", | ||
339 | .irq_ack = etraxfs_gpio_irq_ack, | ||
340 | .irq_mask = etraxfs_gpio_irq_mask, | ||
341 | .irq_unmask = etraxfs_gpio_irq_unmask, | ||
342 | .irq_set_type = etraxfs_gpio_irq_set_type, | ||
343 | .irq_request_resources = etraxfs_gpio_irq_request_resources, | ||
344 | .irq_release_resources = etraxfs_gpio_irq_release_resources, | ||
345 | }; | ||
346 | |||
347 | static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id) | ||
348 | { | ||
349 | struct etraxfs_gpio_block *block = dev_id; | ||
350 | unsigned long intr = readl(block->regs + block->info->r_masked_intr); | ||
351 | int bit; | ||
352 | |||
353 | for_each_set_bit(bit, &intr, 8) | ||
354 | generic_handle_irq(block->group[bit]); | ||
355 | |||
356 | return IRQ_RETVAL(intr & 0xff); | ||
357 | } | ||
358 | |||
359 | static int etraxfs_gpio_probe(struct platform_device *pdev) | ||
360 | { | ||
361 | struct device *dev = &pdev->dev; | ||
362 | const struct etraxfs_gpio_info *info; | ||
363 | const struct of_device_id *match; | ||
364 | struct etraxfs_gpio_block *block; | ||
365 | struct etraxfs_gpio_chip *chips; | ||
366 | struct resource *res, *irq; | ||
367 | bool allportsirq = false; | ||
368 | void __iomem *regs; | ||
369 | int ret; | ||
370 | int i; | ||
371 | |||
372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
373 | regs = devm_ioremap_resource(dev, res); | ||
374 | if (IS_ERR(regs)) | ||
375 | return PTR_ERR(regs); | ||
376 | |||
377 | match = of_match_node(etraxfs_gpio_of_table, dev->of_node); | ||
378 | if (!match) | ||
379 | return -EINVAL; | ||
380 | |||
381 | info = match->data; | ||
382 | |||
383 | chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL); | ||
384 | if (!chips) | ||
385 | return -ENOMEM; | ||
386 | |||
387 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
388 | if (!irq) | ||
389 | return -EINVAL; | ||
390 | |||
391 | block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL); | ||
392 | if (!block) | ||
393 | return -ENOMEM; | ||
394 | |||
395 | raw_spin_lock_init(&block->lock); | ||
396 | |||
397 | block->regs = regs; | ||
398 | block->info = info; | ||
399 | |||
400 | writel(0, block->regs + info->rw_intr_mask); | ||
401 | writel(0, block->regs + info->rw_intr_cfg); | ||
402 | if (info->rw_intr_pins) { | ||
403 | allportsirq = true; | ||
404 | writel(0, block->regs + info->rw_intr_pins); | ||
405 | } | ||
406 | |||
407 | ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt, | ||
408 | IRQF_SHARED, dev_name(dev), block); | ||
409 | if (ret) { | ||
410 | dev_err(dev, "Unable to request irq %d\n", ret); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | for (i = 0; i < info->num_ports; i++) { | ||
415 | struct etraxfs_gpio_chip *chip = &chips[i]; | ||
416 | struct gpio_chip *gc = &chip->gc; | ||
417 | const struct etraxfs_gpio_port *port = &info->ports[i]; | ||
418 | unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET; | ||
419 | void __iomem *dat = regs + port->din; | ||
420 | void __iomem *set = regs + port->dout; | ||
421 | void __iomem *dirout = regs + port->oe; | ||
422 | |||
423 | chip->block = block; | ||
424 | |||
425 | if (dirout == set) { | ||
426 | dirout = set = NULL; | ||
427 | flags = BGPIOF_NO_OUTPUT; | ||
428 | } | ||
429 | |||
430 | ret = bgpio_init(gc, dev, 4, | ||
431 | dat, set, NULL, dirout, NULL, | ||
432 | flags); | ||
433 | if (ret) { | ||
434 | dev_err(dev, "Unable to init port %s\n", | ||
435 | port->label); | ||
436 | continue; | ||
437 | } | ||
438 | |||
439 | gc->ngpio = port->ngpio; | ||
440 | gc->label = port->label; | ||
441 | |||
442 | gc->of_node = dev->of_node; | ||
443 | gc->of_gpio_n_cells = 3; | ||
444 | gc->of_xlate = etraxfs_gpio_of_xlate; | ||
445 | |||
446 | ret = gpiochip_add_data(gc, chip); | ||
447 | if (ret) { | ||
448 | dev_err(dev, "Unable to register port %s\n", | ||
449 | gc->label); | ||
450 | continue; | ||
451 | } | ||
452 | |||
453 | if (i > 0 && !allportsirq) | ||
454 | continue; | ||
455 | |||
456 | ret = gpiochip_irqchip_add(gc, &etraxfs_gpio_irq_chip, 0, | ||
457 | handle_level_irq, IRQ_TYPE_NONE); | ||
458 | if (ret) { | ||
459 | dev_err(dev, "Unable to add irqchip to port %s\n", | ||
460 | gc->label); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static struct platform_driver etraxfs_gpio_driver = { | ||
468 | .driver = { | ||
469 | .name = "etraxfs-gpio", | ||
470 | .of_match_table = of_match_ptr(etraxfs_gpio_of_table), | ||
471 | }, | ||
472 | .probe = etraxfs_gpio_probe, | ||
473 | }; | ||
474 | |||
475 | builtin_platform_driver(etraxfs_gpio_driver); | ||