diff options
author | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-10-01 22:23:20 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-02 05:43:11 -0400 |
commit | 837c8293ba24d08cd7438d82ad9bb8d2fb0f8a5b (patch) | |
tree | 09d494a5b4dddc0da916727fcaed0b748d325a62 /drivers/mfd | |
parent | 8284328cd98b9ac9eebf646e6fcb9047bc12bf55 (diff) |
mfd: 88pm860x: Use irqdomain
Use irqdomain and allocating interrupts. It's necessary for supporting
DT mode.
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/88pm860x-core.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 72bf290bd020..5b56fe8250b4 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irqdomain.h> | ||
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -520,15 +521,12 @@ static void pm860x_irq_sync_unlock(struct irq_data *data) | |||
520 | 521 | ||
521 | static void pm860x_irq_enable(struct irq_data *data) | 522 | static void pm860x_irq_enable(struct irq_data *data) |
522 | { | 523 | { |
523 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 524 | pm860x_irqs[data->hwirq].enable = pm860x_irqs[data->hwirq].offs; |
524 | pm860x_irqs[data->irq - chip->irq_base].enable | ||
525 | = pm860x_irqs[data->irq - chip->irq_base].offs; | ||
526 | } | 525 | } |
527 | 526 | ||
528 | static void pm860x_irq_disable(struct irq_data *data) | 527 | static void pm860x_irq_disable(struct irq_data *data) |
529 | { | 528 | { |
530 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 529 | pm860x_irqs[data->hwirq].enable = 0; |
531 | pm860x_irqs[data->irq - chip->irq_base].enable = 0; | ||
532 | } | 530 | } |
533 | 531 | ||
534 | static struct irq_chip pm860x_irq_chip = { | 532 | static struct irq_chip pm860x_irq_chip = { |
@@ -539,6 +537,25 @@ static struct irq_chip pm860x_irq_chip = { | |||
539 | .irq_disable = pm860x_irq_disable, | 537 | .irq_disable = pm860x_irq_disable, |
540 | }; | 538 | }; |
541 | 539 | ||
540 | static int pm860x_irq_domain_map(struct irq_domain *d, unsigned int virq, | ||
541 | irq_hw_number_t hw) | ||
542 | { | ||
543 | irq_set_chip_data(virq, d->host_data); | ||
544 | irq_set_chip_and_handler(virq, &pm860x_irq_chip, handle_edge_irq); | ||
545 | irq_set_nested_thread(virq, 1); | ||
546 | #ifdef CONFIG_ARM | ||
547 | set_irq_flags(virq, IRQF_VALID); | ||
548 | #else | ||
549 | irq_set_noprobe(virq); | ||
550 | #endif | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static struct irq_domain_ops pm860x_irq_domain_ops = { | ||
555 | .map = pm860x_irq_domain_map, | ||
556 | .xlate = irq_domain_xlate_onetwocell, | ||
557 | }; | ||
558 | |||
542 | static int __devinit device_gpadc_init(struct pm860x_chip *chip, | 559 | static int __devinit device_gpadc_init(struct pm860x_chip *chip, |
543 | struct pm860x_platform_data *pdata) | 560 | struct pm860x_platform_data *pdata) |
544 | { | 561 | { |
@@ -593,13 +610,9 @@ static int __devinit device_irq_init(struct pm860x_chip *chip, | |||
593 | : chip->companion; | 610 | : chip->companion; |
594 | unsigned char status_buf[INT_STATUS_NUM]; | 611 | unsigned char status_buf[INT_STATUS_NUM]; |
595 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | 612 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; |
596 | int i, data, mask, ret = -EINVAL; | 613 | int data, mask, ret = -EINVAL; |
597 | int __irq; | 614 | int nr_irqs, irq_base = -1; |
598 | 615 | struct device_node *node = i2c->dev.of_node; | |
599 | if (!pdata || !pdata->irq_base) { | ||
600 | dev_warn(chip->dev, "No interrupt support on IRQ base\n"); | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | 616 | ||
604 | mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR | 617 | mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR |
605 | | PM8607_B0_MISC1_INT_MASK; | 618 | | PM8607_B0_MISC1_INT_MASK; |
@@ -639,25 +652,23 @@ static int __devinit device_irq_init(struct pm860x_chip *chip, | |||
639 | goto out; | 652 | goto out; |
640 | 653 | ||
641 | mutex_init(&chip->irq_lock); | 654 | mutex_init(&chip->irq_lock); |
642 | chip->irq_base = pdata->irq_base; | 655 | |
656 | if (pdata && pdata->irq_base) | ||
657 | irq_base = pdata->irq_base; | ||
658 | nr_irqs = ARRAY_SIZE(pm860x_irqs); | ||
659 | chip->irq_base = irq_alloc_descs(irq_base, 0, nr_irqs, 0); | ||
660 | if (chip->irq_base < 0) { | ||
661 | dev_err(&i2c->dev, "Failed to allocate interrupts, ret:%d\n", | ||
662 | chip->irq_base); | ||
663 | ret = -EBUSY; | ||
664 | goto out; | ||
665 | } | ||
666 | irq_domain_add_legacy(node, nr_irqs, chip->irq_base, 0, | ||
667 | &pm860x_irq_domain_ops, chip); | ||
643 | chip->core_irq = i2c->irq; | 668 | chip->core_irq = i2c->irq; |
644 | if (!chip->core_irq) | 669 | if (!chip->core_irq) |
645 | goto out; | 670 | goto out; |
646 | 671 | ||
647 | /* register IRQ by genirq */ | ||
648 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { | ||
649 | __irq = i + chip->irq_base; | ||
650 | irq_set_chip_data(__irq, chip); | ||
651 | irq_set_chip_and_handler(__irq, &pm860x_irq_chip, | ||
652 | handle_edge_irq); | ||
653 | irq_set_nested_thread(__irq, 1); | ||
654 | #ifdef CONFIG_ARM | ||
655 | set_irq_flags(__irq, IRQF_VALID); | ||
656 | #else | ||
657 | irq_set_noprobe(__irq); | ||
658 | #endif | ||
659 | } | ||
660 | |||
661 | ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT, | 672 | ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT, |
662 | "88pm860x", chip); | 673 | "88pm860x", chip); |
663 | if (ret) { | 674 | if (ret) { |