aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2012-09-19 16:52:58 -0400
committerJason Cooper <jason@lakedaemon.net>2012-09-22 10:51:36 -0400
commitfefe7b0923459ee00dcbeb0b3510f746af791b09 (patch)
tree9a3de7f4c814feb31221f7284532ee44d677f8d3 /drivers/gpio
parent5beb5f889e1de7e0bb89e9484c840c9dfa25da72 (diff)
gpio: introduce gpio-mvebu driver for Marvell SoCs
This driver aims at replacing the arch/arm/plat-orion/gpio.c driver, and is designed to be compatible with all Marvell EBU SoCs: Orion, Kirkwood, Dove, Armada 370/XP and Discovery. It has been successfully tested on Dove and Armada XP at the moment. Compared to the plat-orion driver, this new driver has the following added benefits: *) Support for Armada 370 and Armada XP *) It is integrated with the mvebu pinctrl driver so that GPIO pins are properly muxed, and the GPIO driver knows which GPIO pins are output-only or input-only. *) Properly placed in drivers/gpio *) More extensible mechanism to support platform differences. The plat-orion driver uses a simple mask-offset DT property, which works fine for Discovery MV78200 but not for Armada XP. The new driver uses different compatible strings to identify the different variants of the GPIO controllers. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Linus Walleij <linus.walleij@stericsson.com> Cc: Andrew Lunn <andrew@lunn.ch> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Gregory Clement <gregory.clement@free-electrons.com> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Andrew Lunn <andrew@lunn.ch> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-mvebu.c679
3 files changed, 686 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f5c099..66a59510887f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -150,6 +150,12 @@ config GPIO_MSM_V2
150 Qualcomm MSM chips. Most of the pins on the MSM can be 150 Qualcomm MSM chips. Most of the pins on the MSM can be
151 selected for GPIO, and are controlled by this driver. 151 selected for GPIO, and are controlled by this driver.
152 152
153config GPIO_MVEBU
154 def_bool y
155 depends on ARCH_MVEBU
156 select GPIO_GENERIC
157 select GENERIC_IRQ_CHIP
158
153config GPIO_MXC 159config GPIO_MXC
154 def_bool y 160 def_bool y
155 depends on ARCH_MXC 161 depends on ARCH_MXC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153caceeb053..1a33e6716e10 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
41obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o 41obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
42obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o 42obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o
43obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o 43obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
44obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
44obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o 45obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
45obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o 46obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
46obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o 47obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
new file mode 100644
index 000000000000..902af437eaf2
--- /dev/null
+++ b/drivers/gpio/gpio-mvebu.c
@@ -0,0 +1,679 @@
1/*
2 * GPIO driver for Marvell SoCs
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7 * Andrew Lunn <andrew@lunn.ch>
8 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 *
14 * This driver is a fairly straightforward GPIO driver for the
15 * complete family of Marvell EBU SoC platforms (Orion, Dove,
16 * Kirkwood, Discovery, Armada 370/XP). The only complexity of this
17 * driver is the different register layout that exists between the
18 * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP
19 * platforms (MV78200 from the Discovery family and the Armada
20 * XP). Therefore, this driver handles three variants of the GPIO
21 * block:
22 * - the basic variant, called "orion-gpio", with the simplest
23 * register set. Used on Orion, Dove, Kirkwoord, Armada 370 and
24 * non-SMP Discovery systems
25 * - the mv78200 variant for MV78200 Discovery systems. This variant
26 * turns the edge mask and level mask registers into CPU0 edge
27 * mask/level mask registers, and adds CPU1 edge mask/level mask
28 * registers.
29 * - the armadaxp variant for Armada XP systems. This variant keeps
30 * the normal cause/edge mask/level mask registers when the global
31 * interrupts are used, but adds per-CPU cause/edge mask/level mask
32 * registers n a separate memory area for the per-CPU GPIO
33 * interrupts.
34 */
35
36#include <linux/module.h>
37#include <linux/gpio.h>
38#include <linux/irq.h>
39#include <linux/slab.h>
40#include <linux/irqdomain.h>
41#include <linux/io.h>
42#include <linux/of_irq.h>
43#include <linux/of_device.h>
44#include <linux/platform_device.h>
45#include <linux/pinctrl/consumer.h>
46
47/*
48 * GPIO unit register offsets.
49 */
50#define GPIO_OUT_OFF 0x0000
51#define GPIO_IO_CONF_OFF 0x0004
52#define GPIO_BLINK_EN_OFF 0x0008
53#define GPIO_IN_POL_OFF 0x000c
54#define GPIO_DATA_IN_OFF 0x0010
55#define GPIO_EDGE_CAUSE_OFF 0x0014
56#define GPIO_EDGE_MASK_OFF 0x0018
57#define GPIO_LEVEL_MASK_OFF 0x001c
58
59/* The MV78200 has per-CPU registers for edge mask and level mask */
60#define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
61#define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C)
62
63/* The Armada XP has per-CPU registers for interrupt cause, interrupt
64 * mask and interrupt level mask. Those are relative to the
65 * percpu_membase. */
66#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
67#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
68#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
69
70#define MVEBU_GPIO_SOC_VARIANT_ORION 0x1
71#define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2
72#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
73
74#define MVEBU_MAX_GPIO_PER_BANK 32
75
76struct mvebu_gpio_chip {
77 struct gpio_chip chip;
78 spinlock_t lock;
79 void __iomem *membase;
80 void __iomem *percpu_membase;
81 unsigned int irqbase;
82 struct irq_domain *domain;
83 int soc_variant;
84};
85
86/*
87 * Functions returning addresses of individual registers for a given
88 * GPIO controller.
89 */
90static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
91{
92 return mvchip->membase + GPIO_OUT_OFF;
93}
94
95static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
96{
97 return mvchip->membase + GPIO_IO_CONF_OFF;
98}
99
100static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
101{
102 return mvchip->membase + GPIO_IN_POL_OFF;
103}
104
105static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
106{
107 return mvchip->membase + GPIO_DATA_IN_OFF;
108}
109
110static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
111{
112 int cpu;
113
114 switch(mvchip->soc_variant) {
115 case MVEBU_GPIO_SOC_VARIANT_ORION:
116 case MVEBU_GPIO_SOC_VARIANT_MV78200:
117 return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
118 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
119 cpu = smp_processor_id();
120 return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
121 default:
122 BUG();
123 }
124}
125
126static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
127{
128 int cpu;
129
130 switch(mvchip->soc_variant) {
131 case MVEBU_GPIO_SOC_VARIANT_ORION:
132 return mvchip->membase + GPIO_EDGE_MASK_OFF;
133 case MVEBU_GPIO_SOC_VARIANT_MV78200:
134 cpu = smp_processor_id();
135 return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
136 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
137 cpu = smp_processor_id();
138 return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
139 default:
140 BUG();
141 }
142}
143
144static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
145{
146 int cpu;
147
148 switch(mvchip->soc_variant) {
149 case MVEBU_GPIO_SOC_VARIANT_ORION:
150 return mvchip->membase + GPIO_LEVEL_MASK_OFF;
151 case MVEBU_GPIO_SOC_VARIANT_MV78200:
152 cpu = smp_processor_id();
153 return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
154 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
155 cpu = smp_processor_id();
156 return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
157 default:
158 BUG();
159 }
160}
161
162/*
163 * Functions implementing the gpio_chip methods
164 */
165
166int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
167{
168 return pinctrl_request_gpio(chip->base + pin);
169}
170
171void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
172{
173 pinctrl_free_gpio(chip->base + pin);
174}
175
176static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
177{
178 struct mvebu_gpio_chip *mvchip =
179 container_of(chip, struct mvebu_gpio_chip, chip);
180 unsigned long flags;
181 u32 u;
182
183 spin_lock_irqsave(&mvchip->lock, flags);
184 u = readl_relaxed(mvebu_gpioreg_out(mvchip));
185 if (value)
186 u |= 1 << pin;
187 else
188 u &= ~(1 << pin);
189 writel_relaxed(u, mvebu_gpioreg_out(mvchip));
190 spin_unlock_irqrestore(&mvchip->lock, flags);
191}
192
193static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
194{
195 struct mvebu_gpio_chip *mvchip =
196 container_of(chip, struct mvebu_gpio_chip, chip);
197 u32 u;
198
199 if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
200 u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
201 readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
202 } else {
203 u = readl_relaxed(mvebu_gpioreg_out(mvchip));
204 }
205
206 return (u >> pin) & 1;
207}
208
209static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
210{
211 struct mvebu_gpio_chip *mvchip =
212 container_of(chip, struct mvebu_gpio_chip, chip);
213 unsigned long flags;
214 int ret;
215 u32 u;
216
217 /* Check with the pinctrl driver whether this pin is usable as
218 * an input GPIO */
219 ret = pinctrl_gpio_direction_input(chip->base + pin);
220 if (ret)
221 return ret;
222
223 spin_lock_irqsave(&mvchip->lock, flags);
224 u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
225 u |= 1 << pin;
226 writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
227 spin_unlock_irqrestore(&mvchip->lock, flags);
228
229 return 0;
230}
231
232static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
233 int value)
234{
235 struct mvebu_gpio_chip *mvchip =
236 container_of(chip, struct mvebu_gpio_chip, chip);
237 unsigned long flags;
238 int ret;
239 u32 u;
240
241 /* Check with the pinctrl driver whether this pin is usable as
242 * an output GPIO */
243 ret = pinctrl_gpio_direction_output(chip->base + pin);
244 if (ret)
245 return ret;
246
247 spin_lock_irqsave(&mvchip->lock, flags);
248 u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
249 u &= ~(1 << pin);
250 writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
251 spin_unlock_irqrestore(&mvchip->lock, flags);
252
253 return 0;
254}
255
256static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
257{
258 struct mvebu_gpio_chip *mvchip =
259 container_of(chip, struct mvebu_gpio_chip, chip);
260 return irq_create_mapping(mvchip->domain, pin);
261}
262
263/*
264 * Functions implementing the irq_chip methods
265 */
266static void mvebu_gpio_irq_ack(struct irq_data *d)
267{
268 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
269 struct mvebu_gpio_chip *mvchip = gc->private;
270 u32 mask = ~(1 << (d->irq - gc->irq_base));
271
272 irq_gc_lock(gc);
273 writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
274 irq_gc_unlock(gc);
275}
276
277static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
278{
279 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
280 struct mvebu_gpio_chip *mvchip = gc->private;
281 u32 mask = 1 << (d->irq - gc->irq_base);
282
283 irq_gc_lock(gc);
284 gc->mask_cache &= ~mask;
285 writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
286 irq_gc_unlock(gc);
287}
288
289static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
290{
291 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
292 struct mvebu_gpio_chip *mvchip = gc->private;
293 u32 mask = 1 << (d->irq - gc->irq_base);
294
295 irq_gc_lock(gc);
296 gc->mask_cache |= mask;
297 writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
298 irq_gc_unlock(gc);
299}
300
301static void mvebu_gpio_level_irq_mask(struct irq_data *d)
302{
303 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
304 struct mvebu_gpio_chip *mvchip = gc->private;
305 u32 mask = 1 << (d->irq - gc->irq_base);
306
307 irq_gc_lock(gc);
308 gc->mask_cache &= ~mask;
309 writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
310 irq_gc_unlock(gc);
311}
312
313static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
314{
315 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
316 struct mvebu_gpio_chip *mvchip = gc->private;
317 u32 mask = 1 << (d->irq - gc->irq_base);
318
319 irq_gc_lock(gc);
320 gc->mask_cache |= mask;
321 writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
322 irq_gc_unlock(gc);
323}
324
325/*****************************************************************************
326 * MVEBU GPIO IRQ
327 *
328 * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
329 * value of the line or the opposite value.
330 *
331 * Level IRQ handlers: DATA_IN is used directly as cause register.
332 * Interrupt are masked by LEVEL_MASK registers.
333 * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
334 * Interrupt are masked by EDGE_MASK registers.
335 * Both-edge handlers: Similar to regular Edge handlers, but also swaps
336 * the polarity to catch the next line transaction.
337 * This is a race condition that might not perfectly
338 * work on some use cases.
339 *
340 * Every eight GPIO lines are grouped (OR'ed) before going up to main
341 * cause register.
342 *
343 * EDGE cause mask
344 * data-in /--------| |-----| |----\
345 * -----| |----- ---- to main cause reg
346 * X \----------------| |----/
347 * polarity LEVEL mask
348 *
349 ****************************************************************************/
350
351static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
352{
353 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
354 struct irq_chip_type *ct = irq_data_get_chip_type(d);
355 struct mvebu_gpio_chip *mvchip = gc->private;
356 int pin;
357 u32 u;
358
359 pin = d->hwirq;
360
361 u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
362 if (!u) {
363 return -EINVAL;
364 }
365
366 type &= IRQ_TYPE_SENSE_MASK;
367 if (type == IRQ_TYPE_NONE)
368 return -EINVAL;
369
370 /* Check if we need to change chip and handler */
371 if (!(ct->type & type))
372 if (irq_setup_alt_chip(d, type))
373 return -EINVAL;
374
375 /*
376 * Configure interrupt polarity.
377 */
378 switch(type) {
379 case IRQ_TYPE_EDGE_RISING:
380 case IRQ_TYPE_LEVEL_HIGH:
381 u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
382 u &= ~(1 << pin);
383 writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
384 case IRQ_TYPE_EDGE_FALLING:
385 case IRQ_TYPE_LEVEL_LOW:
386 u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
387 u |= 1 << pin;
388 writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
389 case IRQ_TYPE_EDGE_BOTH: {
390 u32 v;
391
392 v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^
393 readl_relaxed(mvebu_gpioreg_data_in(mvchip));
394
395 /*
396 * set initial polarity based on current input level
397 */
398 u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
399 if (v & (1 << pin))
400 u |= 1 << pin; /* falling */
401 else
402 u &= ~(1 << pin); /* rising */
403 writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
404 }
405 }
406 return 0;
407}
408
409static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
410{
411 struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
412 u32 cause, type;
413 int i;
414
415 if (mvchip == NULL)
416 return;
417
418 cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
419 readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
420 cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
421 readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
422
423 for (i = 0; i < mvchip->chip.ngpio; i++) {
424 int irq;
425
426 irq = mvchip->irqbase + i;
427
428 if (!(cause & (1 << i)))
429 continue;
430
431 type = irqd_get_trigger_type(irq_get_irq_data(irq));
432 if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
433 /* Swap polarity (race with GPIO line) */
434 u32 polarity;
435
436 polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
437 polarity ^= 1 << i;
438 writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
439 }
440 generic_handle_irq(irq);
441 }
442}
443
444static struct platform_device_id mvebu_gpio_ids[] = {
445 {
446 .name = "orion-gpio",
447 }, {
448 .name = "mv78200-gpio",
449 }, {
450 .name = "armadaxp-gpio",
451 }, {
452 /* sentinel */
453 },
454};
455MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
456
457static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
458 {
459 .compatible = "marvell,orion-gpio",
460 .data = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
461 },
462 {
463 .compatible = "marvell,mv78200-gpio",
464 .data = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
465 },
466 {
467 .compatible = "marvell,armadaxp-gpio",
468 .data = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
469 },
470 {
471 /* sentinel */
472 },
473};
474MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
475
476static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
477{
478 struct mvebu_gpio_chip *mvchip;
479 const struct of_device_id *match;
480 struct device_node *np = pdev->dev.of_node;
481 struct resource *res;
482 struct irq_chip_generic *gc;
483 struct irq_chip_type *ct;
484 unsigned int ngpios;
485 int soc_variant;
486 int i, cpu, id;
487
488 match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
489 if (match)
490 soc_variant = (int) match->data;
491 else
492 soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
493
494 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
495 if (! res) {
496 dev_err(&pdev->dev, "Cannot get memory resource\n");
497 return -ENODEV;
498 }
499
500 mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
501 if (! mvchip){
502 dev_err(&pdev->dev, "Cannot allocate memory\n");
503 return -ENOMEM;
504 }
505
506 if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
507 dev_err(&pdev->dev, "Missing ngpios OF property\n");
508 return -ENODEV;
509 }
510
511 id = of_alias_get_id(pdev->dev.of_node, "gpio");
512 if (id < 0) {
513 dev_err(&pdev->dev, "Couldn't get OF id\n");
514 return id;
515 }
516
517 mvchip->soc_variant = soc_variant;
518 mvchip->chip.label = dev_name(&pdev->dev);
519 mvchip->chip.dev = &pdev->dev;
520 mvchip->chip.request = mvebu_gpio_request;
521 mvchip->chip.direction_input = mvebu_gpio_direction_input;
522 mvchip->chip.get = mvebu_gpio_get;
523 mvchip->chip.direction_output = mvebu_gpio_direction_output;
524 mvchip->chip.set = mvebu_gpio_set;
525 mvchip->chip.to_irq = mvebu_gpio_to_irq;
526 mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
527 mvchip->chip.ngpio = ngpios;
528 mvchip->chip.can_sleep = 0;
529#ifdef CONFIG_OF
530 mvchip->chip.of_node = np;
531#endif
532
533 spin_lock_init(&mvchip->lock);
534 mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
535 if (! mvchip->membase) {
536 dev_err(&pdev->dev, "Cannot ioremap\n");
537 kfree(mvchip->chip.label);
538 return -ENOMEM;
539 }
540
541 /* The Armada XP has a second range of registers for the
542 * per-CPU registers */
543 if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
544 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
545 if (! res) {
546 dev_err(&pdev->dev, "Cannot get memory resource\n");
547 kfree(mvchip->chip.label);
548 return -ENODEV;
549 }
550
551 mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
552 if (! mvchip->percpu_membase) {
553 dev_err(&pdev->dev, "Cannot ioremap\n");
554 kfree(mvchip->chip.label);
555 return -ENOMEM;
556 }
557 }
558
559 /*
560 * Mask and clear GPIO interrupts.
561 */
562 switch(soc_variant) {
563 case MVEBU_GPIO_SOC_VARIANT_ORION:
564 writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
565 writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
566 writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
567 break;
568 case MVEBU_GPIO_SOC_VARIANT_MV78200:
569 writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
570 for (cpu = 0; cpu < 2; cpu++) {
571 writel_relaxed(0, mvchip->membase +
572 GPIO_EDGE_MASK_MV78200_OFF(cpu));
573 writel_relaxed(0, mvchip->membase +
574 GPIO_LEVEL_MASK_MV78200_OFF(cpu));
575 }
576 break;
577 case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
578 writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
579 writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
580 writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
581 for (cpu = 0; cpu < 4; cpu++) {
582 writel_relaxed(0, mvchip->percpu_membase +
583 GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu));
584 writel_relaxed(0, mvchip->percpu_membase +
585 GPIO_EDGE_MASK_ARMADAXP_OFF(cpu));
586 writel_relaxed(0, mvchip->percpu_membase +
587 GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu));
588 }
589 break;
590 default:
591 BUG();
592 }
593
594 gpiochip_add(&mvchip->chip);
595
596 /* Some gpio controllers do not provide irq support */
597 if (!of_irq_count(np))
598 return 0;
599
600 /* Setup the interrupt handlers. Each chip can have up to 4
601 * interrupt handlers, with each handler dealing with 8 GPIO
602 * pins. */
603 for (i = 0; i < 4; i++) {
604 int irq;
605 irq = platform_get_irq(pdev, i);
606 if (irq < 0)
607 continue;
608 irq_set_handler_data(irq, mvchip);
609 irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
610 }
611
612 mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
613 if (mvchip->irqbase < 0) {
614 dev_err(&pdev->dev, "no irqs\n");
615 kfree(mvchip->chip.label);
616 return -ENOMEM;
617 }
618
619 gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
620 mvchip->membase, handle_level_irq);
621 if (! gc) {
622 dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
623 kfree(mvchip->chip.label);
624 return -ENOMEM;
625 }
626
627 gc->private = mvchip;
628 ct = &gc->chip_types[0];
629 ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
630 ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
631 ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
632 ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
633 ct->chip.name = mvchip->chip.label;
634
635 ct = &gc->chip_types[1];
636 ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
637 ct->chip.irq_ack = mvebu_gpio_irq_ack;
638 ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
639 ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
640 ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
641 ct->handler = handle_edge_irq;
642 ct->chip.name = mvchip->chip.label;
643
644 irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
645 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
646
647 /* Setup irq domain on top of the generic chip. */
648 mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
649 mvchip->irqbase, 0,
650 &irq_domain_simple_ops,
651 mvchip);
652 if (!mvchip->domain) {
653 dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
654 mvchip->chip.label);
655 irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
656 IRQ_LEVEL | IRQ_NOPROBE);
657 kfree(gc);
658 kfree(mvchip->chip.label);
659 return -ENODEV;
660 }
661
662 return 0;
663}
664
665static struct platform_driver mvebu_gpio_driver = {
666 .driver = {
667 .name = "mvebu-gpio",
668 .owner = THIS_MODULE,
669 .of_match_table = mvebu_gpio_of_match,
670 },
671 .probe = mvebu_gpio_probe,
672 .id_table = mvebu_gpio_ids,
673};
674
675static int __init mvebu_gpio_init(void)
676{
677 return platform_driver_register(&mvebu_gpio_driver);
678}
679postcore_initcall(mvebu_gpio_init);