diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/irqchip/exynos-combiner.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index 04d86a9803f4..b5ff271bfd64 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c | |||
@@ -31,6 +31,7 @@ struct combiner_chip_data { | |||
31 | unsigned int irq_offset; | 31 | unsigned int irq_offset; |
32 | unsigned int irq_mask; | 32 | unsigned int irq_mask; |
33 | void __iomem *base; | 33 | void __iomem *base; |
34 | unsigned int parent_irq; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | static struct irq_domain *combiner_irq_domain; | 37 | static struct irq_domain *combiner_irq_domain; |
@@ -87,10 +88,28 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
87 | chained_irq_exit(chip, desc); | 88 | chained_irq_exit(chip, desc); |
88 | } | 89 | } |
89 | 90 | ||
91 | #ifdef CONFIG_SMP | ||
92 | static int combiner_set_affinity(struct irq_data *d, | ||
93 | const struct cpumask *mask_val, bool force) | ||
94 | { | ||
95 | struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d); | ||
96 | struct irq_chip *chip = irq_get_chip(chip_data->parent_irq); | ||
97 | struct irq_data *data = irq_get_irq_data(chip_data->parent_irq); | ||
98 | |||
99 | if (chip && chip->irq_set_affinity) | ||
100 | return chip->irq_set_affinity(data, mask_val, force); | ||
101 | else | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | #endif | ||
105 | |||
90 | static struct irq_chip combiner_chip = { | 106 | static struct irq_chip combiner_chip = { |
91 | .name = "COMBINER", | 107 | .name = "COMBINER", |
92 | .irq_mask = combiner_mask_irq, | 108 | .irq_mask = combiner_mask_irq, |
93 | .irq_unmask = combiner_unmask_irq, | 109 | .irq_unmask = combiner_unmask_irq, |
110 | #ifdef CONFIG_SMP | ||
111 | .irq_set_affinity = combiner_set_affinity, | ||
112 | #endif | ||
94 | }; | 113 | }; |
95 | 114 | ||
96 | static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) | 115 | static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) |
@@ -110,12 +129,13 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i | |||
110 | } | 129 | } |
111 | 130 | ||
112 | static void __init combiner_init_one(unsigned int combiner_nr, | 131 | static void __init combiner_init_one(unsigned int combiner_nr, |
113 | void __iomem *base) | 132 | void __iomem *base, unsigned int irq) |
114 | { | 133 | { |
115 | combiner_data[combiner_nr].base = base; | 134 | combiner_data[combiner_nr].base = base; |
116 | combiner_data[combiner_nr].irq_offset = irq_find_mapping( | 135 | combiner_data[combiner_nr].irq_offset = irq_find_mapping( |
117 | combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); | 136 | combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); |
118 | combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); | 137 | combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); |
138 | combiner_data[combiner_nr].parent_irq = irq; | ||
119 | 139 | ||
120 | /* Disable all interrupts */ | 140 | /* Disable all interrupts */ |
121 | __raw_writel(combiner_data[combiner_nr].irq_mask, | 141 | __raw_writel(combiner_data[combiner_nr].irq_mask, |
@@ -199,12 +219,12 @@ void __init combiner_init(void __iomem *combiner_base, | |||
199 | } | 219 | } |
200 | 220 | ||
201 | for (i = 0; i < max_nr; i++) { | 221 | for (i = 0; i < max_nr; i++) { |
202 | combiner_init_one(i, combiner_base + (i >> 2) * 0x10); | ||
203 | irq = IRQ_SPI(i); | 222 | irq = IRQ_SPI(i); |
204 | #ifdef CONFIG_OF | 223 | #ifdef CONFIG_OF |
205 | if (np) | 224 | if (np) |
206 | irq = irq_of_parse_and_map(np, i); | 225 | irq = irq_of_parse_and_map(np, i); |
207 | #endif | 226 | #endif |
227 | combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq); | ||
208 | combiner_cascade_irq(i, irq); | 228 | combiner_cascade_irq(i, irq); |
209 | } | 229 | } |
210 | } | 230 | } |