diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2012-11-08 12:01:51 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-11-17 15:08:32 -0500 |
commit | 55ecd26373bc995c279a5d988ee36c2767e4f3ca (patch) | |
tree | 3b902afb48eff5425b10ac4bd2a0a1e794fce429 /drivers/gpio | |
parent | 3764bdde1dc2fe53a87db1777440c2532cfccd58 (diff) |
gpio: pca953x: Register an IRQ domain
The PCA953x used to register no IRQ domain, which made it impossible to
use it as an interrupt-parent from the device tree.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 9c693ae17956..5ba7e60de942 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/irqdomain.h> | ||
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/i2c/pca953x.h> | 21 | #include <linux/i2c/pca953x.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -83,6 +84,7 @@ struct pca953x_chip { | |||
83 | u32 irq_trig_raise; | 84 | u32 irq_trig_raise; |
84 | u32 irq_trig_fall; | 85 | u32 irq_trig_fall; |
85 | int irq_base; | 86 | int irq_base; |
87 | struct irq_domain *domain; | ||
86 | #endif | 88 | #endif |
87 | 89 | ||
88 | struct i2c_client *client; | 90 | struct i2c_client *client; |
@@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d) | |||
333 | { | 335 | { |
334 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 336 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
335 | 337 | ||
336 | chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); | 338 | chip->irq_mask &= ~(1 << d->hwirq); |
337 | } | 339 | } |
338 | 340 | ||
339 | static void pca953x_irq_unmask(struct irq_data *d) | 341 | static void pca953x_irq_unmask(struct irq_data *d) |
340 | { | 342 | { |
341 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 343 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
342 | 344 | ||
343 | chip->irq_mask |= 1 << (d->irq - chip->irq_base); | 345 | chip->irq_mask |= 1 << d->hwirq; |
344 | } | 346 | } |
345 | 347 | ||
346 | static void pca953x_irq_bus_lock(struct irq_data *d) | 348 | static void pca953x_irq_bus_lock(struct irq_data *d) |
@@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) | |||
372 | static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) | 374 | static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) |
373 | { | 375 | { |
374 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 376 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
375 | u32 level = d->irq - chip->irq_base; | 377 | u32 mask = 1 << d->hwirq; |
376 | u32 mask = 1 << level; | ||
377 | 378 | ||
378 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | 379 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { |
379 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | 380 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", |
@@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) | |||
454 | 455 | ||
455 | do { | 456 | do { |
456 | level = __ffs(pending); | 457 | level = __ffs(pending); |
457 | handle_nested_irq(level + chip->irq_base); | 458 | handle_nested_irq(irq_find_mapping(chip->domain, level)); |
458 | 459 | ||
459 | pending &= ~(1 << level); | 460 | pending &= ~(1 << level); |
460 | } while (pending); | 461 | } while (pending); |
@@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
499 | if (chip->irq_base < 0) | 500 | if (chip->irq_base < 0) |
500 | goto out_failed; | 501 | goto out_failed; |
501 | 502 | ||
503 | chip->domain = irq_domain_add_legacy(client->dev.of_node, | ||
504 | chip->gpio_chip.ngpio, | ||
505 | chip->irq_base, | ||
506 | 0, | ||
507 | &irq_domain_simple_ops, | ||
508 | NULL); | ||
509 | if (!chip->domain) { | ||
510 | ret = -ENODEV; | ||
511 | goto out_irqdesc_free; | ||
512 | } | ||
513 | |||
502 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { | 514 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { |
503 | int irq = lvl + chip->irq_base; | 515 | int irq = lvl + chip->irq_base; |
504 | 516 | ||
@@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
521 | if (ret) { | 533 | if (ret) { |
522 | dev_err(&client->dev, "failed to request irq %d\n", | 534 | dev_err(&client->dev, "failed to request irq %d\n", |
523 | client->irq); | 535 | client->irq); |
524 | goto out_failed; | 536 | goto out_irqdesc_free; |
525 | } | 537 | } |
526 | 538 | ||
527 | chip->gpio_chip.to_irq = pca953x_gpio_to_irq; | 539 | chip->gpio_chip.to_irq = pca953x_gpio_to_irq; |
@@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
529 | 541 | ||
530 | return 0; | 542 | return 0; |
531 | 543 | ||
544 | out_irqdesc_free: | ||
545 | irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); | ||
532 | out_failed: | 546 | out_failed: |
533 | chip->irq_base = -1; | 547 | chip->irq_base = -1; |
534 | return ret; | 548 | return ret; |