diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2012-02-14 16:06:57 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-02-16 08:11:23 -0500 |
commit | 75294957be1dee7d22dd7d90bd31334ba410e836 (patch) | |
tree | afa8e2905af88ceeba2dccb50b56c42568e18ab9 | |
parent | 5769089ac72569d024817270ab79fdf0b9046dde (diff) |
irq_domain: Remove 'new' irq_domain in favour of the ppc one
This patch removes the simplistic implementation of irq_domains and enables
the powerpc infrastructure for all irq_domain users. The powerpc
infrastructure includes support for complex mappings between Linux and
hardware irq numbers, and can manage allocation of irq_descs.
This patch also converts the few users of irq_domain_add()/irq_domain_del()
to call irq_domain_add_legacy() instead.
v3: Fix bug that set up too many irqs in translation range.
v2: Fix removal of irq_alloc_descs() call in gic driver
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Milton Miller <miltonm@bga.com>
Tested-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/common/gic.c | 85 | ||||
-rw-r--r-- | arch/arm/common/vic.c | 16 | ||||
-rw-r--r-- | arch/arm/include/asm/hardware/gic.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/hardware/vic.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-versatile/core.c | 7 | ||||
-rw-r--r-- | drivers/mfd/twl-core.c | 14 | ||||
-rw-r--r-- | include/linux/irqdomain.h | 45 | ||||
-rw-r--r-- | kernel/irq/irqdomain.c | 159 |
9 files changed, 71 insertions, 263 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index dc19862be0a8..7275d808f76d 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -51,7 +51,6 @@ union gic_base { | |||
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct gic_chip_data { | 53 | struct gic_chip_data { |
54 | unsigned int irq_offset; | ||
55 | union gic_base dist_base; | 54 | union gic_base dist_base; |
56 | union gic_base cpu_base; | 55 | union gic_base cpu_base; |
57 | #ifdef CONFIG_CPU_PM | 56 | #ifdef CONFIG_CPU_PM |
@@ -61,9 +60,7 @@ struct gic_chip_data { | |||
61 | u32 __percpu *saved_ppi_enable; | 60 | u32 __percpu *saved_ppi_enable; |
62 | u32 __percpu *saved_ppi_conf; | 61 | u32 __percpu *saved_ppi_conf; |
63 | #endif | 62 | #endif |
64 | #ifdef CONFIG_IRQ_DOMAIN | 63 | struct irq_domain *domain; |
65 | struct irq_domain domain; | ||
66 | #endif | ||
67 | unsigned int gic_irqs; | 64 | unsigned int gic_irqs; |
68 | #ifdef CONFIG_GIC_NON_BANKED | 65 | #ifdef CONFIG_GIC_NON_BANKED |
69 | void __iomem *(*get_base)(union gic_base *); | 66 | void __iomem *(*get_base)(union gic_base *); |
@@ -282,7 +279,7 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | |||
282 | irqnr = irqstat & ~0x1c00; | 279 | irqnr = irqstat & ~0x1c00; |
283 | 280 | ||
284 | if (likely(irqnr > 15 && irqnr < 1021)) { | 281 | if (likely(irqnr > 15 && irqnr < 1021)) { |
285 | irqnr = irq_domain_to_irq(&gic->domain, irqnr); | 282 | irqnr = irq_find_mapping(gic->domain, irqnr); |
286 | handle_IRQ(irqnr, regs); | 283 | handle_IRQ(irqnr, regs); |
287 | continue; | 284 | continue; |
288 | } | 285 | } |
@@ -314,8 +311,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
314 | if (gic_irq == 1023) | 311 | if (gic_irq == 1023) |
315 | goto out; | 312 | goto out; |
316 | 313 | ||
317 | cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq); | 314 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); |
318 | if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS)) | 315 | if (unlikely(gic_irq < 32 || gic_irq > 1020)) |
319 | do_bad_IRQ(cascade_irq, desc); | 316 | do_bad_IRQ(cascade_irq, desc); |
320 | else | 317 | else |
321 | generic_handle_irq(cascade_irq); | 318 | generic_handle_irq(cascade_irq); |
@@ -348,10 +345,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | |||
348 | 345 | ||
349 | static void __init gic_dist_init(struct gic_chip_data *gic) | 346 | static void __init gic_dist_init(struct gic_chip_data *gic) |
350 | { | 347 | { |
351 | unsigned int i, irq; | 348 | unsigned int i; |
352 | u32 cpumask; | 349 | u32 cpumask; |
353 | unsigned int gic_irqs = gic->gic_irqs; | 350 | unsigned int gic_irqs = gic->gic_irqs; |
354 | struct irq_domain *domain = &gic->domain; | ||
355 | void __iomem *base = gic_data_dist_base(gic); | 351 | void __iomem *base = gic_data_dist_base(gic); |
356 | u32 cpu = cpu_logical_map(smp_processor_id()); | 352 | u32 cpu = cpu_logical_map(smp_processor_id()); |
357 | 353 | ||
@@ -386,23 +382,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
386 | for (i = 32; i < gic_irqs; i += 32) | 382 | for (i = 32; i < gic_irqs; i += 32) |
387 | writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); | 383 | writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); |
388 | 384 | ||
389 | /* | ||
390 | * Setup the Linux IRQ subsystem. | ||
391 | */ | ||
392 | irq_domain_for_each_irq(domain, i, irq) { | ||
393 | if (i < 32) { | ||
394 | irq_set_percpu_devid(irq); | ||
395 | irq_set_chip_and_handler(irq, &gic_chip, | ||
396 | handle_percpu_devid_irq); | ||
397 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); | ||
398 | } else { | ||
399 | irq_set_chip_and_handler(irq, &gic_chip, | ||
400 | handle_fasteoi_irq); | ||
401 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
402 | } | ||
403 | irq_set_chip_data(irq, gic); | ||
404 | } | ||
405 | |||
406 | writel_relaxed(1, base + GIC_DIST_CTRL); | 385 | writel_relaxed(1, base + GIC_DIST_CTRL); |
407 | } | 386 | } |
408 | 387 | ||
@@ -618,7 +597,23 @@ static void __init gic_pm_init(struct gic_chip_data *gic) | |||
618 | } | 597 | } |
619 | #endif | 598 | #endif |
620 | 599 | ||
621 | #ifdef CONFIG_OF | 600 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, |
601 | irq_hw_number_t hw) | ||
602 | { | ||
603 | if (hw < 32) { | ||
604 | irq_set_percpu_devid(irq); | ||
605 | irq_set_chip_and_handler(irq, &gic_chip, | ||
606 | handle_percpu_devid_irq); | ||
607 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); | ||
608 | } else { | ||
609 | irq_set_chip_and_handler(irq, &gic_chip, | ||
610 | handle_fasteoi_irq); | ||
611 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
612 | } | ||
613 | irq_set_chip_data(irq, d->host_data); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
622 | static int gic_irq_domain_xlate(struct irq_domain *d, | 617 | static int gic_irq_domain_xlate(struct irq_domain *d, |
623 | struct device_node *controller, | 618 | struct device_node *controller, |
624 | const u32 *intspec, unsigned int intsize, | 619 | const u32 *intspec, unsigned int intsize, |
@@ -639,26 +634,23 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
639 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; | 634 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; |
640 | return 0; | 635 | return 0; |
641 | } | 636 | } |
642 | #endif | ||
643 | 637 | ||
644 | struct irq_domain_ops gic_irq_domain_ops = { | 638 | struct irq_domain_ops gic_irq_domain_ops = { |
645 | #ifdef CONFIG_OF | 639 | .map = gic_irq_domain_map, |
646 | .xlate = gic_irq_domain_xlate, | 640 | .xlate = gic_irq_domain_xlate, |
647 | #endif | ||
648 | }; | 641 | }; |
649 | 642 | ||
650 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, | 643 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, |
651 | void __iomem *dist_base, void __iomem *cpu_base, | 644 | void __iomem *dist_base, void __iomem *cpu_base, |
652 | u32 percpu_offset) | 645 | u32 percpu_offset, struct device_node *node) |
653 | { | 646 | { |
647 | irq_hw_number_t hwirq_base; | ||
654 | struct gic_chip_data *gic; | 648 | struct gic_chip_data *gic; |
655 | struct irq_domain *domain; | 649 | int gic_irqs, irq_base; |
656 | int gic_irqs; | ||
657 | 650 | ||
658 | BUG_ON(gic_nr >= MAX_GIC_NR); | 651 | BUG_ON(gic_nr >= MAX_GIC_NR); |
659 | 652 | ||
660 | gic = &gic_data[gic_nr]; | 653 | gic = &gic_data[gic_nr]; |
661 | domain = &gic->domain; | ||
662 | #ifdef CONFIG_GIC_NON_BANKED | 654 | #ifdef CONFIG_GIC_NON_BANKED |
663 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ | 655 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ |
664 | unsigned int cpu; | 656 | unsigned int cpu; |
@@ -694,10 +686,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
694 | * For primary GICs, skip over SGIs. | 686 | * For primary GICs, skip over SGIs. |
695 | * For secondary GICs, skip over PPIs, too. | 687 | * For secondary GICs, skip over PPIs, too. |
696 | */ | 688 | */ |
697 | domain->hwirq_base = 32; | 689 | hwirq_base = 32; |
698 | if (gic_nr == 0) { | 690 | if (gic_nr == 0) { |
699 | if ((irq_start & 31) > 0) { | 691 | if ((irq_start & 31) > 0) { |
700 | domain->hwirq_base = 16; | 692 | hwirq_base = 16; |
701 | if (irq_start != -1) | 693 | if (irq_start != -1) |
702 | irq_start = (irq_start & ~31) + 16; | 694 | irq_start = (irq_start & ~31) + 16; |
703 | } | 695 | } |
@@ -713,17 +705,17 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
713 | gic_irqs = 1020; | 705 | gic_irqs = 1020; |
714 | gic->gic_irqs = gic_irqs; | 706 | gic->gic_irqs = gic_irqs; |
715 | 707 | ||
716 | domain->nr_irq = gic_irqs - domain->hwirq_base; | 708 | gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ |
717 | domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq, | 709 | irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); |
718 | numa_node_id()); | 710 | if (IS_ERR_VALUE(irq_base)) { |
719 | if (IS_ERR_VALUE(domain->irq_base)) { | ||
720 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", | 711 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", |
721 | irq_start); | 712 | irq_start); |
722 | domain->irq_base = irq_start; | 713 | irq_base = irq_start; |
723 | } | 714 | } |
724 | domain->host_data = gic; | 715 | gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, |
725 | domain->ops = &gic_irq_domain_ops; | 716 | hwirq_base, &gic_irq_domain_ops, gic); |
726 | irq_domain_add(domain); | 717 | if (WARN_ON(!gic->domain)) |
718 | return; | ||
727 | 719 | ||
728 | gic_chip.flags |= gic_arch_extn.flags; | 720 | gic_chip.flags |= gic_arch_extn.flags; |
729 | gic_dist_init(gic); | 721 | gic_dist_init(gic); |
@@ -768,7 +760,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) | |||
768 | void __iomem *dist_base; | 760 | void __iomem *dist_base; |
769 | u32 percpu_offset; | 761 | u32 percpu_offset; |
770 | int irq; | 762 | int irq; |
771 | struct irq_domain *domain = &gic_data[gic_cnt].domain; | ||
772 | 763 | ||
773 | if (WARN_ON(!node)) | 764 | if (WARN_ON(!node)) |
774 | return -ENODEV; | 765 | return -ENODEV; |
@@ -782,9 +773,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) | |||
782 | if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) | 773 | if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) |
783 | percpu_offset = 0; | 774 | percpu_offset = 0; |
784 | 775 | ||
785 | domain->of_node = of_node_get(node); | 776 | gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node); |
786 | |||
787 | gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); | ||
788 | 777 | ||
789 | if (parent) { | 778 | if (parent) { |
790 | irq = irq_of_parse_and_map(node, 0); | 779 | irq = irq_of_parse_and_map(node, 0); |
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index dcb004a804c7..7a66311f3066 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c | |||
@@ -56,7 +56,7 @@ struct vic_device { | |||
56 | u32 int_enable; | 56 | u32 int_enable; |
57 | u32 soft_int; | 57 | u32 soft_int; |
58 | u32 protect; | 58 | u32 protect; |
59 | struct irq_domain domain; | 59 | struct irq_domain *domain; |
60 | }; | 60 | }; |
61 | 61 | ||
62 | /* we cannot allocate memory when VICs are initially registered */ | 62 | /* we cannot allocate memory when VICs are initially registered */ |
@@ -192,14 +192,8 @@ static void __init vic_register(void __iomem *base, unsigned int irq, | |||
192 | v->resume_sources = resume_sources; | 192 | v->resume_sources = resume_sources; |
193 | v->irq = irq; | 193 | v->irq = irq; |
194 | vic_id++; | 194 | vic_id++; |
195 | 195 | v->domain = irq_domain_add_legacy(node, 32, irq, 0, | |
196 | v->domain.irq_base = irq; | 196 | &irq_domain_simple_ops, v); |
197 | v->domain.nr_irq = 32; | ||
198 | #ifdef CONFIG_OF_IRQ | ||
199 | v->domain.of_node = of_node_get(node); | ||
200 | #endif /* CONFIG_OF */ | ||
201 | v->domain.ops = &irq_domain_simple_ops; | ||
202 | irq_domain_add(&v->domain); | ||
203 | } | 197 | } |
204 | 198 | ||
205 | static void vic_ack_irq(struct irq_data *d) | 199 | static void vic_ack_irq(struct irq_data *d) |
@@ -348,7 +342,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, | |||
348 | vic_register(base, irq_start, 0, node); | 342 | vic_register(base, irq_start, 0, node); |
349 | } | 343 | } |
350 | 344 | ||
351 | static void __init __vic_init(void __iomem *base, unsigned int irq_start, | 345 | void __init __vic_init(void __iomem *base, unsigned int irq_start, |
352 | u32 vic_sources, u32 resume_sources, | 346 | u32 vic_sources, u32 resume_sources, |
353 | struct device_node *node) | 347 | struct device_node *node) |
354 | { | 348 | { |
@@ -444,7 +438,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | |||
444 | stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); | 438 | stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); |
445 | while (stat) { | 439 | while (stat) { |
446 | irq = ffs(stat) - 1; | 440 | irq = ffs(stat) - 1; |
447 | handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); | 441 | handle_IRQ(irq_find_mapping(vic->domain, irq), regs); |
448 | stat &= ~(1 << irq); | 442 | stat &= ~(1 << irq); |
449 | handled = 1; | 443 | handled = 1; |
450 | } | 444 | } |
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 4bdfe0018696..4b1ce6cd477f 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h | |||
@@ -39,7 +39,7 @@ struct device_node; | |||
39 | extern struct irq_chip gic_arch_extn; | 39 | extern struct irq_chip gic_arch_extn; |
40 | 40 | ||
41 | void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, | 41 | void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, |
42 | u32 offset); | 42 | u32 offset, struct device_node *); |
43 | int gic_of_init(struct device_node *node, struct device_node *parent); | 43 | int gic_of_init(struct device_node *node, struct device_node *parent); |
44 | void gic_secondary_init(unsigned int); | 44 | void gic_secondary_init(unsigned int); |
45 | void gic_handle_irq(struct pt_regs *regs); | 45 | void gic_handle_irq(struct pt_regs *regs); |
@@ -49,7 +49,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); | |||
49 | static inline void gic_init(unsigned int nr, int start, | 49 | static inline void gic_init(unsigned int nr, int start, |
50 | void __iomem *dist , void __iomem *cpu) | 50 | void __iomem *dist , void __iomem *cpu) |
51 | { | 51 | { |
52 | gic_init_bases(nr, start, dist, cpu, 0); | 52 | gic_init_bases(nr, start, dist, cpu, 0, NULL); |
53 | } | 53 | } |
54 | 54 | ||
55 | #endif | 55 | #endif |
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index f42ebd619590..e14af1a1a320 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h | |||
@@ -47,6 +47,8 @@ | |||
47 | struct device_node; | 47 | struct device_node; |
48 | struct pt_regs; | 48 | struct pt_regs; |
49 | 49 | ||
50 | void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, | ||
51 | u32 resume_sources, struct device_node *node); | ||
50 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); | 52 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); |
51 | int vic_of_init(struct device_node *node, struct device_node *parent); | 53 | int vic_of_init(struct device_node *node, struct device_node *parent); |
52 | void vic_handle_irq(struct pt_regs *regs); | 54 | void vic_handle_irq(struct pt_regs *regs); |
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index c59e18871006..6de298c5d2d3 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -402,7 +402,7 @@ void __init exynos4_init_irq(void) | |||
402 | gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; | 402 | gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; |
403 | 403 | ||
404 | if (!of_have_populated_dt()) | 404 | if (!of_have_populated_dt()) |
405 | gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset); | 405 | gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL); |
406 | #ifdef CONFIG_OF | 406 | #ifdef CONFIG_OF |
407 | else | 407 | else |
408 | of_irq_init(exynos4_dt_irq_match); | 408 | of_irq_init(exynos4_dt_irq_match); |
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 02b7b9303f3b..008ce22b9a06 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
@@ -98,8 +98,11 @@ static const struct of_device_id sic_of_match[] __initconst = { | |||
98 | 98 | ||
99 | void __init versatile_init_irq(void) | 99 | void __init versatile_init_irq(void) |
100 | { | 100 | { |
101 | vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0); | 101 | struct device_node *np; |
102 | irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START); | 102 | |
103 | np = of_find_matching_node_by_address(NULL, vic_of_match, | ||
104 | VERSATILE_VIC_BASE); | ||
105 | __vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np); | ||
103 | 106 | ||
104 | writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); | 107 | writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); |
105 | 108 | ||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 49677339ab5f..66f9bffc50f0 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -263,10 +263,6 @@ struct twl_client { | |||
263 | 263 | ||
264 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; | 264 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; |
265 | 265 | ||
266 | #ifdef CONFIG_IRQ_DOMAIN | ||
267 | static struct irq_domain domain; | ||
268 | #endif | ||
269 | |||
270 | /* mapping the module id to slave id and base address */ | 266 | /* mapping the module id to slave id and base address */ |
271 | struct twl_mapping { | 267 | struct twl_mapping { |
272 | unsigned char sid; /* Slave ID */ | 268 | unsigned char sid; /* Slave ID */ |
@@ -1227,14 +1223,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1227 | 1223 | ||
1228 | pdata->irq_base = status; | 1224 | pdata->irq_base = status; |
1229 | pdata->irq_end = pdata->irq_base + nr_irqs; | 1225 | pdata->irq_end = pdata->irq_base + nr_irqs; |
1230 | 1226 | irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0, | |
1231 | #ifdef CONFIG_IRQ_DOMAIN | 1227 | &irq_domain_simple_ops, NULL); |
1232 | domain.irq_base = pdata->irq_base; | ||
1233 | domain.nr_irq = nr_irqs; | ||
1234 | domain.of_node = of_node_get(node); | ||
1235 | domain.ops = &irq_domain_simple_ops; | ||
1236 | irq_domain_add(&domain); | ||
1237 | #endif | ||
1238 | 1228 | ||
1239 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { | 1229 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { |
1240 | dev_dbg(&client->dev, "can't talk I2C?\n"); | 1230 | dev_dbg(&client->dev, "can't talk I2C?\n"); |
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 7fef39ed5523..624e9ac89e79 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h | |||
@@ -55,9 +55,6 @@ typedef unsigned long irq_hw_number_t; | |||
55 | * @map: Create or update a mapping between a virtual irq number and a hw | 55 | * @map: Create or update a mapping between a virtual irq number and a hw |
56 | * irq number. This is called only once for a given mapping. | 56 | * irq number. This is called only once for a given mapping. |
57 | * @unmap: Dispose of such a mapping | 57 | * @unmap: Dispose of such a mapping |
58 | * @to_irq: (optional) given a local hardware irq number, return the linux | ||
59 | * irq number. If to_irq is not implemented, then the irq_domain | ||
60 | * will use this translation: irq = (domain->irq_base + hwirq) | ||
61 | * @xlate: Given a device tree node and interrupt specifier, decode | 58 | * @xlate: Given a device tree node and interrupt specifier, decode |
62 | * the hardware irq number and linux irq type value. | 59 | * the hardware irq number and linux irq type value. |
63 | * | 60 | * |
@@ -70,7 +67,6 @@ struct irq_domain_ops { | |||
70 | int (*match)(struct irq_domain *d, struct device_node *node); | 67 | int (*match)(struct irq_domain *d, struct device_node *node); |
71 | int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw); | 68 | int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw); |
72 | void (*unmap)(struct irq_domain *d, unsigned int virq); | 69 | void (*unmap)(struct irq_domain *d, unsigned int virq); |
73 | unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq); | ||
74 | int (*xlate)(struct irq_domain *d, struct device_node *node, | 70 | int (*xlate)(struct irq_domain *d, struct device_node *node, |
75 | const u32 *intspec, unsigned int intsize, | 71 | const u32 *intspec, unsigned int intsize, |
76 | unsigned long *out_hwirq, unsigned int *out_type); | 72 | unsigned long *out_hwirq, unsigned int *out_type); |
@@ -114,16 +110,11 @@ struct irq_domain { | |||
114 | void *host_data; | 110 | void *host_data; |
115 | irq_hw_number_t inval_irq; | 111 | irq_hw_number_t inval_irq; |
116 | 112 | ||
117 | unsigned int irq_base; | ||
118 | unsigned int nr_irq; | ||
119 | unsigned int hwirq_base; | ||
120 | |||
121 | /* Optional device node pointer */ | 113 | /* Optional device node pointer */ |
122 | struct device_node *of_node; | 114 | struct device_node *of_node; |
123 | }; | 115 | }; |
124 | 116 | ||
125 | #ifdef CONFIG_IRQ_DOMAIN | 117 | #ifdef CONFIG_IRQ_DOMAIN |
126 | #ifdef CONFIG_PPC | ||
127 | struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, | 118 | struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, |
128 | unsigned int size, | 119 | unsigned int size, |
129 | unsigned int first_irq, | 120 | unsigned int first_irq, |
@@ -153,6 +144,10 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( | |||
153 | return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, | 144 | return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, |
154 | host_data); | 145 | host_data); |
155 | } | 146 | } |
147 | extern struct irq_domain *irq_find_host(struct device_node *node); | ||
148 | extern void irq_set_default_host(struct irq_domain *host); | ||
149 | extern void irq_set_virq_count(unsigned int count); | ||
150 | |||
156 | 151 | ||
157 | extern unsigned int irq_create_mapping(struct irq_domain *host, | 152 | extern unsigned int irq_create_mapping(struct irq_domain *host, |
158 | irq_hw_number_t hwirq); | 153 | irq_hw_number_t hwirq); |
@@ -167,38 +162,7 @@ extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, | |||
167 | extern unsigned int irq_linear_revmap(struct irq_domain *host, | 162 | extern unsigned int irq_linear_revmap(struct irq_domain *host, |
168 | irq_hw_number_t hwirq); | 163 | irq_hw_number_t hwirq); |
169 | 164 | ||
170 | #else /* CONFIG_PPC */ | ||
171 | |||
172 | /** | ||
173 | * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number | ||
174 | * | ||
175 | * Returns the linux irq number associated with a hardware irq. By default, | ||
176 | * the mapping is irq == domain->irq_base + hwirq, but this mapping can | ||
177 | * be overridden if the irq_domain implements a .to_irq() hook. | ||
178 | */ | ||
179 | static inline unsigned int irq_domain_to_irq(struct irq_domain *d, | ||
180 | unsigned long hwirq) | ||
181 | { | ||
182 | if (d->ops->to_irq) | ||
183 | return d->ops->to_irq(d, hwirq); | ||
184 | if (WARN_ON(hwirq < d->hwirq_base)) | ||
185 | return 0; | ||
186 | return d->irq_base + hwirq - d->hwirq_base; | ||
187 | } | ||
188 | |||
189 | #define irq_domain_for_each_hwirq(d, hw) \ | ||
190 | for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++) | ||
191 | |||
192 | #define irq_domain_for_each_irq(d, hw, irq) \ | ||
193 | for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \ | ||
194 | hw < d->hwirq_base + d->nr_irq; \ | ||
195 | hw++, irq = irq_domain_to_irq(d, hw)) | ||
196 | |||
197 | extern void irq_domain_add(struct irq_domain *domain); | ||
198 | extern void irq_domain_del(struct irq_domain *domain); | ||
199 | |||
200 | extern struct irq_domain_ops irq_domain_simple_ops; | 165 | extern struct irq_domain_ops irq_domain_simple_ops; |
201 | |||
202 | #if defined(CONFIG_OF_IRQ) | 166 | #if defined(CONFIG_OF_IRQ) |
203 | extern void irq_domain_add_simple(struct device_node *controller, int irq_base); | 167 | extern void irq_domain_add_simple(struct device_node *controller, int irq_base); |
204 | extern void irq_domain_generate_simple(const struct of_device_id *match, | 168 | extern void irq_domain_generate_simple(const struct of_device_id *match, |
@@ -207,7 +171,6 @@ extern void irq_domain_generate_simple(const struct of_device_id *match, | |||
207 | static inline void irq_domain_generate_simple(const struct of_device_id *match, | 171 | static inline void irq_domain_generate_simple(const struct of_device_id *match, |
208 | u64 phys_base, unsigned int irq_start) { } | 172 | u64 phys_base, unsigned int irq_start) { } |
209 | #endif /* !CONFIG_OF_IRQ */ | 173 | #endif /* !CONFIG_OF_IRQ */ |
210 | #endif /* !CONFIG_PPC */ | ||
211 | #endif /* CONFIG_IRQ_DOMAIN */ | 174 | #endif /* CONFIG_IRQ_DOMAIN */ |
212 | 175 | ||
213 | #endif /* _LINUX_IRQDOMAIN_H */ | 176 | #endif /* _LINUX_IRQDOMAIN_H */ |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index c6740d72073e..2981ebfeb40c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
@@ -22,7 +22,6 @@ | |||
22 | static LIST_HEAD(irq_domain_list); | 22 | static LIST_HEAD(irq_domain_list); |
23 | static DEFINE_MUTEX(irq_domain_mutex); | 23 | static DEFINE_MUTEX(irq_domain_mutex); |
24 | 24 | ||
25 | #ifdef CONFIG_PPC | ||
26 | static DEFINE_MUTEX(revmap_trees_mutex); | 25 | static DEFINE_MUTEX(revmap_trees_mutex); |
27 | static unsigned int irq_virq_count = NR_IRQS; | 26 | static unsigned int irq_virq_count = NR_IRQS; |
28 | static struct irq_domain *irq_default_domain; | 27 | static struct irq_domain *irq_default_domain; |
@@ -694,124 +693,11 @@ static int __init irq_debugfs_init(void) | |||
694 | __initcall(irq_debugfs_init); | 693 | __initcall(irq_debugfs_init); |
695 | #endif /* CONFIG_VIRQ_DEBUG */ | 694 | #endif /* CONFIG_VIRQ_DEBUG */ |
696 | 695 | ||
697 | #else /* CONFIG_PPC */ | 696 | int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, |
698 | 697 | irq_hw_number_t hwirq) | |
699 | /** | ||
700 | * irq_domain_add() - Register an irq_domain | ||
701 | * @domain: ptr to initialized irq_domain structure | ||
702 | * | ||
703 | * Registers an irq_domain structure. The irq_domain must at a minimum be | ||
704 | * initialized with an ops structure pointer, and either a ->to_irq hook or | ||
705 | * a valid irq_base value. Everything else is optional. | ||
706 | */ | ||
707 | void irq_domain_add(struct irq_domain *domain) | ||
708 | { | ||
709 | struct irq_data *d; | ||
710 | int hwirq, irq; | ||
711 | |||
712 | /* | ||
713 | * This assumes that the irq_domain owner has already allocated | ||
714 | * the irq_descs. This block will be removed when support for dynamic | ||
715 | * allocation of irq_descs is added to irq_domain. | ||
716 | */ | ||
717 | irq_domain_for_each_irq(domain, hwirq, irq) { | ||
718 | d = irq_get_irq_data(irq); | ||
719 | if (!d) { | ||
720 | WARN(1, "error: assigning domain to non existant irq_desc"); | ||
721 | return; | ||
722 | } | ||
723 | if (d->domain) { | ||
724 | /* things are broken; just report, don't clean up */ | ||
725 | WARN(1, "error: irq_desc already assigned to a domain"); | ||
726 | return; | ||
727 | } | ||
728 | d->domain = domain; | ||
729 | d->hwirq = hwirq; | ||
730 | } | ||
731 | |||
732 | mutex_lock(&irq_domain_mutex); | ||
733 | list_add(&domain->link, &irq_domain_list); | ||
734 | mutex_unlock(&irq_domain_mutex); | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * irq_domain_del() - Unregister an irq_domain | ||
739 | * @domain: ptr to registered irq_domain. | ||
740 | */ | ||
741 | void irq_domain_del(struct irq_domain *domain) | ||
742 | { | ||
743 | struct irq_data *d; | ||
744 | int hwirq, irq; | ||
745 | |||
746 | mutex_lock(&irq_domain_mutex); | ||
747 | list_del(&domain->link); | ||
748 | mutex_unlock(&irq_domain_mutex); | ||
749 | |||
750 | /* Clear the irq_domain assignments */ | ||
751 | irq_domain_for_each_irq(domain, hwirq, irq) { | ||
752 | d = irq_get_irq_data(irq); | ||
753 | d->domain = NULL; | ||
754 | } | ||
755 | } | ||
756 | |||
757 | #if defined(CONFIG_OF_IRQ) | ||
758 | /** | ||
759 | * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec | ||
760 | * | ||
761 | * Used by the device tree interrupt mapping code to translate a device tree | ||
762 | * interrupt specifier to a valid linux irq number. Returns either a valid | ||
763 | * linux IRQ number or 0. | ||
764 | * | ||
765 | * When the caller no longer need the irq number returned by this function it | ||
766 | * should arrange to call irq_dispose_mapping(). | ||
767 | */ | ||
768 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
769 | const u32 *intspec, unsigned int intsize) | ||
770 | { | ||
771 | struct irq_domain *domain; | ||
772 | unsigned long hwirq; | ||
773 | unsigned int irq, type; | ||
774 | int rc = -EINVAL; | ||
775 | |||
776 | /* Find a domain which can translate the irq spec */ | ||
777 | mutex_lock(&irq_domain_mutex); | ||
778 | list_for_each_entry(domain, &irq_domain_list, link) { | ||
779 | if (!domain->ops->xlate) | ||
780 | continue; | ||
781 | rc = domain->ops->xlate(domain, controller, | ||
782 | intspec, intsize, &hwirq, &type); | ||
783 | if (rc == 0) | ||
784 | break; | ||
785 | } | ||
786 | mutex_unlock(&irq_domain_mutex); | ||
787 | |||
788 | if (rc != 0) | ||
789 | return 0; | ||
790 | |||
791 | irq = irq_domain_to_irq(domain, hwirq); | ||
792 | if (type != IRQ_TYPE_NONE) | ||
793 | irq_set_irq_type(irq, type); | ||
794 | pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n", | ||
795 | controller->full_name, (int)hwirq, irq, type); | ||
796 | return irq; | ||
797 | } | ||
798 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
799 | |||
800 | /** | ||
801 | * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping() | ||
802 | * @irq: linux irq number to be discarded | ||
803 | * | ||
804 | * Calling this function indicates the caller no longer needs a reference to | ||
805 | * the linux irq number returned by a prior call to irq_create_of_mapping(). | ||
806 | */ | ||
807 | void irq_dispose_mapping(unsigned int irq) | ||
808 | { | 698 | { |
809 | /* | 699 | return 0; |
810 | * nothing yet; will be filled when support for dynamic allocation of | ||
811 | * irq_descs is added to irq_domain | ||
812 | */ | ||
813 | } | 700 | } |
814 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); | ||
815 | 701 | ||
816 | int irq_domain_simple_xlate(struct irq_domain *d, | 702 | int irq_domain_simple_xlate(struct irq_domain *d, |
817 | struct device_node *controller, | 703 | struct device_node *controller, |
@@ -822,10 +708,6 @@ int irq_domain_simple_xlate(struct irq_domain *d, | |||
822 | return -EINVAL; | 708 | return -EINVAL; |
823 | if (intsize < 1) | 709 | if (intsize < 1) |
824 | return -EINVAL; | 710 | return -EINVAL; |
825 | if (d->nr_irq && ((intspec[0] < d->hwirq_base) || | ||
826 | (intspec[0] >= d->hwirq_base + d->nr_irq))) | ||
827 | return -EINVAL; | ||
828 | |||
829 | *out_hwirq = intspec[0]; | 711 | *out_hwirq = intspec[0]; |
830 | *out_type = IRQ_TYPE_NONE; | 712 | *out_type = IRQ_TYPE_NONE; |
831 | if (intsize > 1) | 713 | if (intsize > 1) |
@@ -833,23 +715,17 @@ int irq_domain_simple_xlate(struct irq_domain *d, | |||
833 | return 0; | 715 | return 0; |
834 | } | 716 | } |
835 | 717 | ||
836 | /** | 718 | struct irq_domain_ops irq_domain_simple_ops = { |
837 | * irq_domain_create_simple() - Set up a 'simple' translation range | 719 | .map = irq_domain_simple_map, |
838 | */ | 720 | .xlate = irq_domain_simple_xlate, |
721 | }; | ||
722 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); | ||
723 | |||
724 | #ifdef CONFIG_OF_IRQ | ||
839 | void irq_domain_add_simple(struct device_node *controller, int irq_base) | 725 | void irq_domain_add_simple(struct device_node *controller, int irq_base) |
840 | { | 726 | { |
841 | struct irq_domain *domain; | 727 | irq_domain_add_legacy(controller, 32, irq_base, 0, |
842 | 728 | &irq_domain_simple_ops, NULL); | |
843 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | ||
844 | if (!domain) { | ||
845 | WARN_ON(1); | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | domain->irq_base = irq_base; | ||
850 | domain->of_node = of_node_get(controller); | ||
851 | domain->ops = &irq_domain_simple_ops; | ||
852 | irq_domain_add(domain); | ||
853 | } | 729 | } |
854 | EXPORT_SYMBOL_GPL(irq_domain_add_simple); | 730 | EXPORT_SYMBOL_GPL(irq_domain_add_simple); |
855 | 731 | ||
@@ -864,13 +740,4 @@ void irq_domain_generate_simple(const struct of_device_id *match, | |||
864 | irq_domain_add_simple(node, irq_start); | 740 | irq_domain_add_simple(node, irq_start); |
865 | } | 741 | } |
866 | EXPORT_SYMBOL_GPL(irq_domain_generate_simple); | 742 | EXPORT_SYMBOL_GPL(irq_domain_generate_simple); |
867 | #endif /* CONFIG_OF_IRQ */ | 743 | #endif |
868 | |||
869 | struct irq_domain_ops irq_domain_simple_ops = { | ||
870 | #ifdef CONFIG_OF_IRQ | ||
871 | .xlate = irq_domain_simple_xlate, | ||
872 | #endif /* CONFIG_OF_IRQ */ | ||
873 | }; | ||
874 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); | ||
875 | |||
876 | #endif /* !CONFIG_PPC */ | ||