aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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