diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2012-08-20 04:43:32 -0400 |
---|---|---|
committer | Shawn Guo <shawn.guo@linaro.org> | 2012-09-02 21:31:44 -0400 |
commit | 0b76c5412146c1c9e8aef495d2926f31351bc3c0 (patch) | |
tree | e99af001689a62706776681577c1bcafa9d85b5f /drivers/gpio/gpio-mxs.c | |
parent | d9875690d9b89a866022ff49e3fcea892345ad92 (diff) |
gpio/mxs: adopt irq_domain support for mxs gpio driver
Remove irq_domain_add_legacy call from mach-mxs.c and have the gpio
driver adopt irqdomain support, so that we can have the mapping
between gpio and irq number available without using virtual_irq_start
and MXS_GPIO_IRQ_START.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-mxs.c')
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 39e495669961..796fb13e4815 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
27 | #include <linux/irqdomain.h> | ||
27 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
28 | #include <linux/of.h> | 29 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | 30 | #include <linux/of_address.h> |
@@ -52,8 +53,6 @@ | |||
52 | #define GPIO_INT_LEV_MASK (1 << 0) | 53 | #define GPIO_INT_LEV_MASK (1 << 0) |
53 | #define GPIO_INT_POL_MASK (1 << 1) | 54 | #define GPIO_INT_POL_MASK (1 << 1) |
54 | 55 | ||
55 | #define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) | ||
56 | |||
57 | enum mxs_gpio_id { | 56 | enum mxs_gpio_id { |
58 | IMX23_GPIO, | 57 | IMX23_GPIO, |
59 | IMX28_GPIO, | 58 | IMX28_GPIO, |
@@ -63,7 +62,7 @@ struct mxs_gpio_port { | |||
63 | void __iomem *base; | 62 | void __iomem *base; |
64 | int id; | 63 | int id; |
65 | int irq; | 64 | int irq; |
66 | int virtual_irq_start; | 65 | struct irq_domain *domain; |
67 | struct bgpio_chip bgc; | 66 | struct bgpio_chip bgc; |
68 | enum mxs_gpio_id devid; | 67 | enum mxs_gpio_id devid; |
69 | }; | 68 | }; |
@@ -82,8 +81,7 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port) | |||
82 | 81 | ||
83 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | 82 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) |
84 | { | 83 | { |
85 | u32 gpio = irq_to_gpio(d->irq); | 84 | u32 pin_mask = 1 << d->hwirq; |
86 | u32 pin_mask = 1 << (gpio & 31); | ||
87 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 85 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
88 | struct mxs_gpio_port *port = gc->private; | 86 | struct mxs_gpio_port *port = gc->private; |
89 | void __iomem *pin_addr; | 87 | void __iomem *pin_addr; |
@@ -120,7 +118,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | |||
120 | else | 118 | else |
121 | writel(pin_mask, pin_addr + MXS_CLR); | 119 | writel(pin_mask, pin_addr + MXS_CLR); |
122 | 120 | ||
123 | writel(1 << (gpio & 0x1f), | 121 | writel(pin_mask, |
124 | port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); | 122 | port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); |
125 | 123 | ||
126 | return 0; | 124 | return 0; |
@@ -131,7 +129,6 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
131 | { | 129 | { |
132 | u32 irq_stat; | 130 | u32 irq_stat; |
133 | struct mxs_gpio_port *port = irq_get_handler_data(irq); | 131 | struct mxs_gpio_port *port = irq_get_handler_data(irq); |
134 | u32 gpio_irq_no_base = port->virtual_irq_start; | ||
135 | 132 | ||
136 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 133 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
137 | 134 | ||
@@ -140,7 +137,7 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
140 | 137 | ||
141 | while (irq_stat != 0) { | 138 | while (irq_stat != 0) { |
142 | int irqoffset = fls(irq_stat) - 1; | 139 | int irqoffset = fls(irq_stat) - 1; |
143 | generic_handle_irq(gpio_irq_no_base + irqoffset); | 140 | generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); |
144 | irq_stat &= ~(1 << irqoffset); | 141 | irq_stat &= ~(1 << irqoffset); |
145 | } | 142 | } |
146 | } | 143 | } |
@@ -167,12 +164,12 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) | |||
167 | return 0; | 164 | return 0; |
168 | } | 165 | } |
169 | 166 | ||
170 | static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) | 167 | static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) |
171 | { | 168 | { |
172 | struct irq_chip_generic *gc; | 169 | struct irq_chip_generic *gc; |
173 | struct irq_chip_type *ct; | 170 | struct irq_chip_type *ct; |
174 | 171 | ||
175 | gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start, | 172 | gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base, |
176 | port->base, handle_level_irq); | 173 | port->base, handle_level_irq); |
177 | gc->private = port; | 174 | gc->private = port; |
178 | 175 | ||
@@ -194,7 +191,7 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
194 | struct mxs_gpio_port *port = | 191 | struct mxs_gpio_port *port = |
195 | container_of(bgc, struct mxs_gpio_port, bgc); | 192 | container_of(bgc, struct mxs_gpio_port, bgc); |
196 | 193 | ||
197 | return port->virtual_irq_start + offset; | 194 | return irq_find_mapping(port->domain, offset); |
198 | } | 195 | } |
199 | 196 | ||
200 | static struct platform_device_id mxs_gpio_ids[] = { | 197 | static struct platform_device_id mxs_gpio_ids[] = { |
@@ -226,6 +223,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) | |||
226 | static void __iomem *base; | 223 | static void __iomem *base; |
227 | struct mxs_gpio_port *port; | 224 | struct mxs_gpio_port *port; |
228 | struct resource *iores = NULL; | 225 | struct resource *iores = NULL; |
226 | int irq_base; | ||
229 | int err; | 227 | int err; |
230 | 228 | ||
231 | port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); | 229 | port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); |
@@ -241,7 +239,6 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) | |||
241 | port->id = pdev->id; | 239 | port->id = pdev->id; |
242 | port->devid = pdev->id_entry->driver_data; | 240 | port->devid = pdev->id_entry->driver_data; |
243 | } | 241 | } |
244 | port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; | ||
245 | 242 | ||
246 | port->irq = platform_get_irq(pdev, 0); | 243 | port->irq = platform_get_irq(pdev, 0); |
247 | if (port->irq < 0) | 244 | if (port->irq < 0) |
@@ -275,8 +272,19 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) | |||
275 | /* clear address has to be used to clear IRQSTAT bits */ | 272 | /* clear address has to be used to clear IRQSTAT bits */ |
276 | writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); | 273 | writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); |
277 | 274 | ||
275 | irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); | ||
276 | if (irq_base < 0) | ||
277 | return irq_base; | ||
278 | |||
279 | port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, | ||
280 | &irq_domain_simple_ops, NULL); | ||
281 | if (!port->domain) { | ||
282 | err = -ENODEV; | ||
283 | goto out_irqdesc_free; | ||
284 | } | ||
285 | |||
278 | /* gpio-mxs can be a generic irq chip */ | 286 | /* gpio-mxs can be a generic irq chip */ |
279 | mxs_gpio_init_gc(port); | 287 | mxs_gpio_init_gc(port, irq_base); |
280 | 288 | ||
281 | /* setup one handler for each entry */ | 289 | /* setup one handler for each entry */ |
282 | irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); | 290 | irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); |
@@ -287,18 +295,22 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) | |||
287 | port->base + PINCTRL_DOUT(port), NULL, | 295 | port->base + PINCTRL_DOUT(port), NULL, |
288 | port->base + PINCTRL_DOE(port), NULL, 0); | 296 | port->base + PINCTRL_DOE(port), NULL, 0); |
289 | if (err) | 297 | if (err) |
290 | return err; | 298 | goto out_irqdesc_free; |
291 | 299 | ||
292 | port->bgc.gc.to_irq = mxs_gpio_to_irq; | 300 | port->bgc.gc.to_irq = mxs_gpio_to_irq; |
293 | port->bgc.gc.base = port->id * 32; | 301 | port->bgc.gc.base = port->id * 32; |
294 | 302 | ||
295 | err = gpiochip_add(&port->bgc.gc); | 303 | err = gpiochip_add(&port->bgc.gc); |
296 | if (err) { | 304 | if (err) |
297 | bgpio_remove(&port->bgc); | 305 | goto out_bgpio_remove; |
298 | return err; | ||
299 | } | ||
300 | 306 | ||
301 | return 0; | 307 | return 0; |
308 | |||
309 | out_bgpio_remove: | ||
310 | bgpio_remove(&port->bgc); | ||
311 | out_irqdesc_free: | ||
312 | irq_free_descs(irq_base, 32); | ||
313 | return err; | ||
302 | } | 314 | } |
303 | 315 | ||
304 | static struct platform_driver mxs_gpio_driver = { | 316 | static struct platform_driver mxs_gpio_driver = { |