aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/imx27-dt.c13
-rw-r--r--arch/arm/mach-imx/imx51-dt.c12
-rw-r--r--arch/arm/mach-imx/imx53-dt.c12
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c14
-rw-r--r--drivers/gpio/gpio-mxc.c56
5 files changed, 32 insertions, 75 deletions
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index eee0cc8d92a4..c734e564f204 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -40,21 +40,8 @@ static int __init imx27_avic_add_irq_domain(struct device_node *np,
40 return 0; 40 return 0;
41} 41}
42 42
43static int __init imx27_gpio_add_irq_domain(struct device_node *np,
44 struct device_node *interrupt_parent)
45{
46 static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
47
48 gpio_irq_base -= 32;
49 irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
50 NULL);
51
52 return 0;
53}
54
55static const struct of_device_id imx27_irq_match[] __initconst = { 43static const struct of_device_id imx27_irq_match[] __initconst = {
56 { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, }, 44 { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, },
57 { .compatible = "fsl,imx27-gpio", .data = imx27_gpio_add_irq_domain, },
58 { /* sentinel */ } 45 { /* sentinel */ }
59}; 46};
60 47
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index 18e78dba4298..3bdabbc64f43 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -52,20 +52,8 @@ static int __init imx51_tzic_add_irq_domain(struct device_node *np,
52 return 0; 52 return 0;
53} 53}
54 54
55static int __init imx51_gpio_add_irq_domain(struct device_node *np,
56 struct device_node *interrupt_parent)
57{
58 static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
59
60 gpio_irq_base -= 32;
61 irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
62
63 return 0;
64}
65
66static const struct of_device_id imx51_irq_match[] __initconst = { 55static const struct of_device_id imx51_irq_match[] __initconst = {
67 { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, }, 56 { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
68 { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
69 { /* sentinel */ } 57 { /* sentinel */ }
70}; 58};
71 59
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
index eb04b6248e48..17fca3cac268 100644
--- a/arch/arm/mach-imx/imx53-dt.c
+++ b/arch/arm/mach-imx/imx53-dt.c
@@ -59,20 +59,8 @@ static int __init imx53_tzic_add_irq_domain(struct device_node *np,
59 return 0; 59 return 0;
60} 60}
61 61
62static int __init imx53_gpio_add_irq_domain(struct device_node *np,
63 struct device_node *interrupt_parent)
64{
65 static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
66
67 gpio_irq_base -= 32;
68 irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
69
70 return 0;
71}
72
73static const struct of_device_id imx53_irq_match[] __initconst = { 62static const struct of_device_id imx53_irq_match[] __initconst = {
74 { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, }, 63 { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
75 { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
76 { /* sentinel */ } 64 { /* sentinel */ }
77}; 65};
78 66
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index b47e98b7d539..8c2a649192ca 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -16,7 +16,6 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/irq.h> 18#include <linux/irq.h>
19#include <linux/irqdomain.h>
20#include <linux/of.h> 19#include <linux/of.h>
21#include <linux/of_address.h> 20#include <linux/of_address.h>
22#include <linux/of_irq.h> 21#include <linux/of_irq.h>
@@ -136,21 +135,8 @@ static void __init imx6q_map_io(void)
136 imx6q_clock_map_io(); 135 imx6q_clock_map_io();
137} 136}
138 137
139static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
140 struct device_node *interrupt_parent)
141{
142 static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
143
144 gpio_irq_base -= 32;
145 irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
146 NULL);
147
148 return 0;
149}
150
151static const struct of_device_id imx6q_irq_match[] __initconst = { 138static const struct of_device_id imx6q_irq_match[] __initconst = {
152 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, 139 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
153 { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
154 { /* sentinel */ } 140 { /* sentinel */ }
155}; 141};
156 142
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index c337143b18f8..e5db670d0002 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
38enum mxc_gpio_hwtype { 37enum 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
145static int gpio_set_irq_type(struct irq_data *d, u32 type) 144static 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 */
218static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) 218static 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 */
277static int gpio_set_wake_irq(struct irq_data *d, u32 enable) 275static 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
299static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) 296static 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
358static int __devinit mxc_gpio_probe(struct platform_device *pdev) 355static 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);
@@ -430,20 +428,30 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
430 if (err) 428 if (err)
431 goto out_bgpio_remove; 429 goto out_bgpio_remove;
432 430
433 /* 431 irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
434 * In dt case, we use gpio number range dynamically 432 if (irq_base < 0) {
435 * allocated by gpio core. 433 err = irq_base;
436 */ 434 goto out_gpiochip_remove;
437 port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base : 435 }
438 pdev->id * 32); 436
437 port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
438 &irq_domain_simple_ops, NULL);
439 if (!port->domain) {
440 err = -ENODEV;
441 goto out_irqdesc_free;
442 }
439 443
440 /* gpio-mxc can be a generic irq chip */ 444 /* gpio-mxc can be a generic irq chip */
441 mxc_gpio_init_gc(port); 445 mxc_gpio_init_gc(port, irq_base);
442 446
443 list_add_tail(&port->node, &mxc_gpio_ports); 447 list_add_tail(&port->node, &mxc_gpio_ports);
444 448
445 return 0; 449 return 0;
446 450
451out_irqdesc_free:
452 irq_free_descs(irq_base, 32);
453out_gpiochip_remove:
454 WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
447out_bgpio_remove: 455out_bgpio_remove:
448 bgpio_remove(&port->bgc); 456 bgpio_remove(&port->bgc);
449out_iounmap: 457out_iounmap: