aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2012-12-10 05:07:54 -0500
committerLinus Walleij <linus.walleij@linaro.org>2012-12-10 05:23:30 -0500
commitfc13d5a5b17c657b7682c145d367dcb859c507d9 (patch)
tree9770c0263213f556f87af4e6fb30e2d4e9ca8fab
parent759f5f3752e03f15727688b5288e360ef90c1306 (diff)
gpio: Provide the STMPE GPIO driver with its own IRQ Domain
The STMPE GPIO driver can be used as an IRQ controller by some related devices. Here we provide it with its very own IRQ Domain so that IRQs can be issued dynamically. This will stand the driver in good stead when it is enabled for Device Tree, as this it a prerequisite. Cc: Grant Likely <grant.likely@secretlab.ca> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpio-stmpe.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 522c90ee96e8..3e1d39895cef 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -11,6 +11,7 @@
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/gpio.h> 12#include <linux/gpio.h>
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/irqdomain.h>
14#include <linux/interrupt.h> 15#include <linux/interrupt.h>
15#include <linux/of.h> 16#include <linux/of.h>
16#include <linux/mfd/stmpe.h> 17#include <linux/mfd/stmpe.h>
@@ -29,6 +30,7 @@ struct stmpe_gpio {
29 struct stmpe *stmpe; 30 struct stmpe *stmpe;
30 struct device *dev; 31 struct device *dev;
31 struct mutex irq_lock; 32 struct mutex irq_lock;
33 struct irq_domain *domain;
32 34
33 int irq_base; 35 int irq_base;
34 unsigned norequest_mask; 36 unsigned norequest_mask;
@@ -104,7 +106,7 @@ static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
104{ 106{
105 struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 107 struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
106 108
107 return stmpe_gpio->irq_base + offset; 109 return irq_create_mapping(stmpe_gpio->domain, offset);
108} 110}
109 111
110static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) 112static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -133,7 +135,7 @@ static struct gpio_chip template_chip = {
133static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) 135static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
134{ 136{
135 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 137 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
136 int offset = d->irq - stmpe_gpio->irq_base; 138 int offset = d->hwirq;
137 int regoffset = offset / 8; 139 int regoffset = offset / 8;
138 int mask = 1 << (offset % 8); 140 int mask = 1 << (offset % 8);
139 141
@@ -200,7 +202,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
200static void stmpe_gpio_irq_mask(struct irq_data *d) 202static void stmpe_gpio_irq_mask(struct irq_data *d)
201{ 203{
202 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 204 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
203 int offset = d->irq - stmpe_gpio->irq_base; 205 int offset = d->hwirq;
204 int regoffset = offset / 8; 206 int regoffset = offset / 8;
205 int mask = 1 << (offset % 8); 207 int mask = 1 << (offset % 8);
206 208
@@ -210,7 +212,7 @@ static void stmpe_gpio_irq_mask(struct irq_data *d)
210static void stmpe_gpio_irq_unmask(struct irq_data *d) 212static void stmpe_gpio_irq_unmask(struct irq_data *d)
211{ 213{
212 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 214 struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
213 int offset = d->irq - stmpe_gpio->irq_base; 215 int offset = d->hwirq;
214 int regoffset = offset / 8; 216 int regoffset = offset / 8;
215 int mask = 1 << (offset % 8); 217 int mask = 1 << (offset % 8);
216 218
@@ -252,8 +254,9 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
252 while (stat) { 254 while (stat) {
253 int bit = __ffs(stat); 255 int bit = __ffs(stat);
254 int line = bank * 8 + bit; 256 int line = bank * 8 + bit;
257 int virq = irq_find_mapping(stmpe_gpio->domain, line);
255 258
256 handle_nested_irq(stmpe_gpio->irq_base + line); 259 handle_nested_irq(virq);
257 stat &= ~(1 << bit); 260 stat &= ~(1 << bit);
258 } 261 }
259 262
@@ -268,38 +271,55 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
268 return IRQ_HANDLED; 271 return IRQ_HANDLED;
269} 272}
270 273
271static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) 274int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
275 irq_hw_number_t hwirq)
272{ 276{
273 int base = stmpe_gpio->irq_base; 277 struct stmpe_gpio *stmpe_gpio = d->host_data;
274 int irq; 278
279 if (!stmpe_gpio)
280 return -EINVAL;
275 281
276 for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { 282 irq_set_chip_data(hwirq, stmpe_gpio);
277 irq_set_chip_data(irq, stmpe_gpio); 283 irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip,
278 irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip, 284 handle_simple_irq);
279 handle_simple_irq); 285 irq_set_nested_thread(hwirq, 1);
280 irq_set_nested_thread(irq, 1);
281#ifdef CONFIG_ARM 286#ifdef CONFIG_ARM
282 set_irq_flags(irq, IRQF_VALID); 287 set_irq_flags(hwirq, IRQF_VALID);
283#else 288#else
284 irq_set_noprobe(irq); 289 irq_set_noprobe(hwirq);
285#endif 290#endif
286 }
287 291
288 return 0; 292 return 0;
289} 293}
290 294
291static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) 295void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
292{ 296{
293 int base = stmpe_gpio->irq_base;
294 int irq;
295
296 for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
297#ifdef CONFIG_ARM 297#ifdef CONFIG_ARM
298 set_irq_flags(irq, 0); 298 set_irq_flags(virq, 0);
299#endif 299#endif
300 irq_set_chip_and_handler(irq, NULL, NULL); 300 irq_set_chip_and_handler(virq, NULL, NULL);
301 irq_set_chip_data(irq, NULL); 301 irq_set_chip_data(virq, NULL);
302}
303
304static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
305 .unmap = stmpe_gpio_irq_unmap,
306 .map = stmpe_gpio_irq_map,
307 .xlate = irq_domain_xlate_twocell,
308};
309
310static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
311{
312 int base = stmpe_gpio->irq_base;
313
314 stmpe_gpio->domain = irq_domain_add_simple(NULL,
315 stmpe_gpio->chip.ngpio, base,
316 &stmpe_gpio_irq_simple_ops, stmpe_gpio);
317 if (!stmpe_gpio->domain) {
318 dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
319 return -ENOSYS;
302 } 320 }
321
322 return 0;
303} 323}
304 324
305static int __devinit stmpe_gpio_probe(struct platform_device *pdev) 325static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
@@ -354,7 +374,7 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
354 IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio); 374 IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
355 if (ret) { 375 if (ret) {
356 dev_err(&pdev->dev, "unable to get irq: %d\n", ret); 376 dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
357 goto out_removeirq; 377 goto out_disable;
358 } 378 }
359 } 379 }
360 380
@@ -374,9 +394,6 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
374out_freeirq: 394out_freeirq:
375 if (irq >= 0) 395 if (irq >= 0)
376 free_irq(irq, stmpe_gpio); 396 free_irq(irq, stmpe_gpio);
377out_removeirq:
378 if (irq >= 0)
379 stmpe_gpio_irq_remove(stmpe_gpio);
380out_disable: 397out_disable:
381 stmpe_disable(stmpe, STMPE_BLOCK_GPIO); 398 stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
382out_free: 399out_free:
@@ -404,10 +421,9 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
404 421
405 stmpe_disable(stmpe, STMPE_BLOCK_GPIO); 422 stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
406 423
407 if (irq >= 0) { 424 if (irq >= 0)
408 free_irq(irq, stmpe_gpio); 425 free_irq(irq, stmpe_gpio);
409 stmpe_gpio_irq_remove(stmpe_gpio); 426
410 }
411 platform_set_drvdata(pdev, NULL); 427 platform_set_drvdata(pdev, NULL);
412 kfree(stmpe_gpio); 428 kfree(stmpe_gpio);
413 429