diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 20:36:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 20:36:02 -0400 |
commit | 3645f0cd96fbf72c614673c5f4b1a8675f82a379 (patch) | |
tree | 84539c44e461eb9451cc0320dec70eedc9724796 /drivers/gpio | |
parent | f1d2c07d331f717da79a42952be7dc1c0d35f846 (diff) | |
parent | c7b0807b9d4faddd87a75a5acb079e5dbfedd211 (diff) |
Merge tag 'irq' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc sparse IRQ conversion from Arnd Bergmann:
"The I.MX platform is getting converted to use sparse IRQs. We are
doing this for all platforms over time, because this is one of the
requirements for building a multiplatform kernel, and generally a good
idea."
* tag 'irq' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
ARM: imx: select USE_OF
ARM: imx: Fix build error due to missing irqs.h include
ARM: imx: enable SPARSE_IRQ for imx platform
ARM: fiq: change FIQ_START to a variable
tty: serial: imx: remove the use of MXC_INTERNAL_IRQS
ARM: imx: remove unneeded mach/irq.h inclusion
i2c: imx: remove unneeded mach/irqs.h inclusion
ARM: imx: add a legacy irqdomain for mx31ads
ARM: imx: add a legacy irqdomain for 3ds_debugboard
ARM: imx: pass gpio than irq number into mxc_expio_init
ARM: imx: leave irq_base of wm8350_platform_data uninitialized
dma: ipu: remove the use of ipu_platform_data
ARM: imx: move irq_domain_add_legacy call into avic driver
ARM: imx: move irq_domain_add_legacy call into tzic driver
gpio/mxc: move irq_domain_add_legacy call into gpio driver
ARM: imx: eliminate macro IRQ_GPIOx()
ARM: imx: eliminate macro IOMUX_TO_IRQ()
ARM: imx: eliminate macro IMX_GPIO_TO_IRQ()
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index c89c4c1e668d..04691d3abe60 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/irqdomain.h> | ||
26 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
@@ -33,8 +34,6 @@ | |||
33 | #include <asm-generic/bug.h> | 34 | #include <asm-generic/bug.h> |
34 | #include <asm/mach/irq.h> | 35 | #include <asm/mach/irq.h> |
35 | 36 | ||
36 | #define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START) | ||
37 | |||
38 | enum mxc_gpio_hwtype { | 37 | enum mxc_gpio_hwtype { |
39 | IMX1_GPIO, /* runs on i.mx1 */ | 38 | IMX1_GPIO, /* runs on i.mx1 */ |
40 | IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ | 39 | IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ |
@@ -61,7 +60,7 @@ struct mxc_gpio_port { | |||
61 | void __iomem *base; | 60 | void __iomem *base; |
62 | int irq; | 61 | int irq; |
63 | int irq_high; | 62 | int irq_high; |
64 | int virtual_irq_start; | 63 | struct irq_domain *domain; |
65 | struct bgpio_chip bgc; | 64 | struct bgpio_chip bgc; |
66 | u32 both_edges; | 65 | u32 both_edges; |
67 | }; | 66 | }; |
@@ -144,14 +143,15 @@ static LIST_HEAD(mxc_gpio_ports); | |||
144 | 143 | ||
145 | static int gpio_set_irq_type(struct irq_data *d, u32 type) | 144 | static int gpio_set_irq_type(struct irq_data *d, u32 type) |
146 | { | 145 | { |
147 | u32 gpio = irq_to_gpio(d->irq); | ||
148 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 146 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
149 | struct mxc_gpio_port *port = gc->private; | 147 | struct mxc_gpio_port *port = gc->private; |
150 | u32 bit, val; | 148 | u32 bit, val; |
149 | u32 gpio_idx = d->hwirq; | ||
150 | u32 gpio = port->bgc.gc.base + gpio_idx; | ||
151 | int edge; | 151 | int edge; |
152 | void __iomem *reg = port->base; | 152 | void __iomem *reg = port->base; |
153 | 153 | ||
154 | port->both_edges &= ~(1 << (gpio & 31)); | 154 | port->both_edges &= ~(1 << gpio_idx); |
155 | switch (type) { | 155 | switch (type) { |
156 | case IRQ_TYPE_EDGE_RISING: | 156 | case IRQ_TYPE_EDGE_RISING: |
157 | edge = GPIO_INT_RISE_EDGE; | 157 | edge = GPIO_INT_RISE_EDGE; |
@@ -168,7 +168,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) | |||
168 | edge = GPIO_INT_HIGH_LEV; | 168 | edge = GPIO_INT_HIGH_LEV; |
169 | pr_debug("mxc: set GPIO %d to high trigger\n", gpio); | 169 | pr_debug("mxc: set GPIO %d to high trigger\n", gpio); |
170 | } | 170 | } |
171 | port->both_edges |= 1 << (gpio & 31); | 171 | port->both_edges |= 1 << gpio_idx; |
172 | break; | 172 | break; |
173 | case IRQ_TYPE_LEVEL_LOW: | 173 | case IRQ_TYPE_LEVEL_LOW: |
174 | edge = GPIO_INT_LOW_LEV; | 174 | edge = GPIO_INT_LOW_LEV; |
@@ -180,11 +180,11 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) | |||
180 | return -EINVAL; | 180 | return -EINVAL; |
181 | } | 181 | } |
182 | 182 | ||
183 | reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ | 183 | reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */ |
184 | bit = gpio & 0xf; | 184 | bit = gpio_idx & 0xf; |
185 | val = readl(reg) & ~(0x3 << (bit << 1)); | 185 | val = readl(reg) & ~(0x3 << (bit << 1)); |
186 | writel(val | (edge << (bit << 1)), reg); | 186 | writel(val | (edge << (bit << 1)), reg); |
187 | writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); | 187 | writel(1 << gpio_idx, port->base + GPIO_ISR); |
188 | 188 | ||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
@@ -217,15 +217,13 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio) | |||
217 | /* handle 32 interrupts in one status register */ | 217 | /* handle 32 interrupts in one status register */ |
218 | static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) | 218 | static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) |
219 | { | 219 | { |
220 | u32 gpio_irq_no_base = port->virtual_irq_start; | ||
221 | |||
222 | while (irq_stat != 0) { | 220 | while (irq_stat != 0) { |
223 | int irqoffset = fls(irq_stat) - 1; | 221 | int irqoffset = fls(irq_stat) - 1; |
224 | 222 | ||
225 | if (port->both_edges & (1 << irqoffset)) | 223 | if (port->both_edges & (1 << irqoffset)) |
226 | mxc_flip_edge(port, irqoffset); | 224 | mxc_flip_edge(port, irqoffset); |
227 | 225 | ||
228 | generic_handle_irq(gpio_irq_no_base + irqoffset); | 226 | generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); |
229 | 227 | ||
230 | irq_stat &= ~(1 << irqoffset); | 228 | irq_stat &= ~(1 << irqoffset); |
231 | } | 229 | } |
@@ -276,10 +274,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
276 | */ | 274 | */ |
277 | static int gpio_set_wake_irq(struct irq_data *d, u32 enable) | 275 | static int gpio_set_wake_irq(struct irq_data *d, u32 enable) |
278 | { | 276 | { |
279 | u32 gpio = irq_to_gpio(d->irq); | ||
280 | u32 gpio_idx = gpio & 0x1F; | ||
281 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 277 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
282 | struct mxc_gpio_port *port = gc->private; | 278 | struct mxc_gpio_port *port = gc->private; |
279 | u32 gpio_idx = d->hwirq; | ||
283 | 280 | ||
284 | if (enable) { | 281 | if (enable) { |
285 | if (port->irq_high && (gpio_idx >= 16)) | 282 | if (port->irq_high && (gpio_idx >= 16)) |
@@ -296,12 +293,12 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) | |||
296 | return 0; | 293 | return 0; |
297 | } | 294 | } |
298 | 295 | ||
299 | static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) | 296 | static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) |
300 | { | 297 | { |
301 | struct irq_chip_generic *gc; | 298 | struct irq_chip_generic *gc; |
302 | struct irq_chip_type *ct; | 299 | struct irq_chip_type *ct; |
303 | 300 | ||
304 | gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start, | 301 | gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base, |
305 | port->base, handle_level_irq); | 302 | port->base, handle_level_irq); |
306 | gc->private = port; | 303 | gc->private = port; |
307 | 304 | ||
@@ -352,7 +349,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
352 | struct mxc_gpio_port *port = | 349 | struct mxc_gpio_port *port = |
353 | container_of(bgc, struct mxc_gpio_port, bgc); | 350 | container_of(bgc, struct mxc_gpio_port, bgc); |
354 | 351 | ||
355 | return port->virtual_irq_start + offset; | 352 | return irq_find_mapping(port->domain, offset); |
356 | } | 353 | } |
357 | 354 | ||
358 | static int __devinit mxc_gpio_probe(struct platform_device *pdev) | 355 | static int __devinit mxc_gpio_probe(struct platform_device *pdev) |
@@ -360,6 +357,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) | |||
360 | struct device_node *np = pdev->dev.of_node; | 357 | struct device_node *np = pdev->dev.of_node; |
361 | struct mxc_gpio_port *port; | 358 | struct mxc_gpio_port *port; |
362 | struct resource *iores; | 359 | struct resource *iores; |
360 | int irq_base; | ||
363 | int err; | 361 | int err; |
364 | 362 | ||
365 | mxc_gpio_get_hw(pdev); | 363 | mxc_gpio_get_hw(pdev); |
@@ -432,20 +430,30 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) | |||
432 | if (err) | 430 | if (err) |
433 | goto out_bgpio_remove; | 431 | goto out_bgpio_remove; |
434 | 432 | ||
435 | /* | 433 | irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); |
436 | * In dt case, we use gpio number range dynamically | 434 | if (irq_base < 0) { |
437 | * allocated by gpio core. | 435 | err = irq_base; |
438 | */ | 436 | goto out_gpiochip_remove; |
439 | port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base : | 437 | } |
440 | pdev->id * 32); | 438 | |
439 | port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, | ||
440 | &irq_domain_simple_ops, NULL); | ||
441 | if (!port->domain) { | ||
442 | err = -ENODEV; | ||
443 | goto out_irqdesc_free; | ||
444 | } | ||
441 | 445 | ||
442 | /* gpio-mxc can be a generic irq chip */ | 446 | /* gpio-mxc can be a generic irq chip */ |
443 | mxc_gpio_init_gc(port); | 447 | mxc_gpio_init_gc(port, irq_base); |
444 | 448 | ||
445 | list_add_tail(&port->node, &mxc_gpio_ports); | 449 | list_add_tail(&port->node, &mxc_gpio_ports); |
446 | 450 | ||
447 | return 0; | 451 | return 0; |
448 | 452 | ||
453 | out_irqdesc_free: | ||
454 | irq_free_descs(irq_base, 32); | ||
455 | out_gpiochip_remove: | ||
456 | WARN_ON(gpiochip_remove(&port->bgc.gc) < 0); | ||
449 | out_bgpio_remove: | 457 | out_bgpio_remove: |
450 | bgpio_remove(&port->bgc); | 458 | bgpio_remove(&port->bgc); |
451 | out_iounmap: | 459 | out_iounmap: |