diff options
author | Lee Jones <lee.jones@linaro.org> | 2012-09-24 04:11:46 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-24 17:04:53 -0400 |
commit | f3f1f0a1eac6fd1529d552b8e2a0e1ac07293c62 (patch) | |
tree | 74e4f13bcc3f46d81a135dfabda6dddfdc940e8b /drivers/mfd | |
parent | 0f471916d4d03503cf6fb696f7c8baf12fec30b9 (diff) |
mfd: Provide the PRCMU with its own IRQ domain
The PRCMU has its own USB, Thermal, GPIO, Modem, HSI and RTC drivers,
amongst other things. This patch allows those subordinate devices to
use it as an interrupt controller as and when they are DT enabled.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 6fb11b76071e..bac4876d090f 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -270,6 +270,8 @@ static struct { | |||
270 | struct prcmu_fw_version version; | 270 | struct prcmu_fw_version version; |
271 | } fw_info; | 271 | } fw_info; |
272 | 272 | ||
273 | static struct irq_domain *db8500_irq_domain; | ||
274 | |||
273 | /* | 275 | /* |
274 | * This vector maps irq numbers to the bits in the bit field used in | 276 | * This vector maps irq numbers to the bits in the bit field used in |
275 | * communication with the PRCMU firmware. | 277 | * communication with the PRCMU firmware. |
@@ -2623,7 +2625,7 @@ static void prcmu_irq_mask(struct irq_data *d) | |||
2623 | 2625 | ||
2624 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); | 2626 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); |
2625 | 2627 | ||
2626 | mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; | 2628 | mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq]; |
2627 | 2629 | ||
2628 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); | 2630 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); |
2629 | 2631 | ||
@@ -2637,7 +2639,7 @@ static void prcmu_irq_unmask(struct irq_data *d) | |||
2637 | 2639 | ||
2638 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); | 2640 | spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); |
2639 | 2641 | ||
2640 | mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE]; | 2642 | mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq]; |
2641 | 2643 | ||
2642 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); | 2644 | spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); |
2643 | 2645 | ||
@@ -2677,9 +2679,37 @@ static char *fw_project_name(u8 project) | |||
2677 | } | 2679 | } |
2678 | } | 2680 | } |
2679 | 2681 | ||
2682 | static int db8500_irq_map(struct irq_domain *d, unsigned int virq, | ||
2683 | irq_hw_number_t hwirq) | ||
2684 | { | ||
2685 | irq_set_chip_and_handler(virq, &prcmu_irq_chip, | ||
2686 | handle_simple_irq); | ||
2687 | set_irq_flags(virq, IRQF_VALID); | ||
2688 | |||
2689 | return 0; | ||
2690 | } | ||
2691 | |||
2692 | static struct irq_domain_ops db8500_irq_ops = { | ||
2693 | .map = db8500_irq_map, | ||
2694 | .xlate = irq_domain_xlate_twocell, | ||
2695 | }; | ||
2696 | |||
2697 | static int db8500_irq_init(struct device_node *np) | ||
2698 | { | ||
2699 | db8500_irq_domain = irq_domain_add_legacy( | ||
2700 | np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE, | ||
2701 | 0, &db8500_irq_ops, NULL); | ||
2702 | |||
2703 | if (!db8500_irq_domain) { | ||
2704 | pr_err("Failed to create irqdomain\n"); | ||
2705 | return -ENOSYS; | ||
2706 | } | ||
2707 | |||
2708 | return 0; | ||
2709 | } | ||
2710 | |||
2680 | void __init db8500_prcmu_early_init(void) | 2711 | void __init db8500_prcmu_early_init(void) |
2681 | { | 2712 | { |
2682 | unsigned int i; | ||
2683 | if (cpu_is_u8500v2()) { | 2713 | if (cpu_is_u8500v2()) { |
2684 | void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); | 2714 | void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); |
2685 | 2715 | ||
@@ -2724,15 +2754,6 @@ void __init db8500_prcmu_early_init(void) | |||
2724 | 2754 | ||
2725 | INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); | 2755 | INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); |
2726 | 2756 | ||
2727 | /* Initalize irqs. */ | ||
2728 | for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) { | ||
2729 | unsigned int irq; | ||
2730 | |||
2731 | irq = IRQ_PRCMU_BASE + i; | ||
2732 | irq_set_chip_and_handler(irq, &prcmu_irq_chip, | ||
2733 | handle_simple_irq); | ||
2734 | set_irq_flags(irq, IRQF_VALID); | ||
2735 | } | ||
2736 | compute_armss_rate(); | 2757 | compute_armss_rate(); |
2737 | } | 2758 | } |
2738 | 2759 | ||
@@ -3040,6 +3061,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) | |||
3040 | goto no_irq_return; | 3061 | goto no_irq_return; |
3041 | } | 3062 | } |
3042 | 3063 | ||
3064 | db8500_irq_init(np); | ||
3065 | |||
3043 | for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { | 3066 | for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { |
3044 | if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { | 3067 | if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { |
3045 | db8500_prcmu_devs[i].platform_data = ab8500_platdata; | 3068 | db8500_prcmu_devs[i].platform_data = ab8500_platdata; |