aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-09 16:46:16 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-09 16:46:16 -0400
commit0b8467ee39721340450482e87471ca4c0d6170f3 (patch)
treeefabb381fdec807b3486c9bc8e93950c2d414b1c /drivers/irqchip
parent19ce4f4a03e52bc694dc837a4a832111cb4271b3 (diff)
parentdb35234ec7a7a10145cf472f68e1c73fbd48f79c (diff)
Merge tag 'pmu-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers
From Kukjin Kim <kgene.kim@samsung.com>: add support arm-pmu for exynos4 and exynos5250 * tag 'pmu-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: Add arm-pmu DT binding for exynos421x ARM: EXYNOS: Add arm-pmu DT binding for exynos5250 ARM: EXYNOS: Enable PMUs for exynos4 irqchip: exynos-combiner: Correct combined IRQs for exynos4 irqchip: exynos-combiner: Add set_irq_affinity function for combiner_irq Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/exynos-combiner.c80
1 files changed, 62 insertions, 18 deletions
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
index 04d86a9803f4..e8501dbaa0b7 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
36static struct irq_domain *combiner_irq_domain; 37static struct irq_domain *combiner_irq_domain;
@@ -87,22 +88,46 @@ 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
92static 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
90static struct irq_chip combiner_chip = { 106static 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
96static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) 115static unsigned int max_combiner_nr(void)
97{ 116{
98 unsigned int max_nr;
99
100 if (soc_is_exynos5250()) 117 if (soc_is_exynos5250())
101 max_nr = EXYNOS5_MAX_COMBINER_NR; 118 return EXYNOS5_MAX_COMBINER_NR;
119 else if (soc_is_exynos4412())
120 return EXYNOS4412_MAX_COMBINER_NR;
121 else if (soc_is_exynos4212())
122 return EXYNOS4212_MAX_COMBINER_NR;
102 else 123 else
103 max_nr = EXYNOS4_MAX_COMBINER_NR; 124 return EXYNOS4210_MAX_COMBINER_NR;
125}
104 126
105 if (combiner_nr >= max_nr) 127static void __init combiner_cascade_irq(unsigned int combiner_nr,
128 unsigned int irq)
129{
130 if (combiner_nr >= max_combiner_nr())
106 BUG(); 131 BUG();
107 if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) 132 if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
108 BUG(); 133 BUG();
@@ -110,12 +135,13 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i
110} 135}
111 136
112static void __init combiner_init_one(unsigned int combiner_nr, 137static void __init combiner_init_one(unsigned int combiner_nr,
113 void __iomem *base) 138 void __iomem *base, unsigned int irq)
114{ 139{
115 combiner_data[combiner_nr].base = base; 140 combiner_data[combiner_nr].base = base;
116 combiner_data[combiner_nr].irq_offset = irq_find_mapping( 141 combiner_data[combiner_nr].irq_offset = irq_find_mapping(
117 combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); 142 combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
118 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); 143 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
144 combiner_data[combiner_nr].parent_irq = irq;
119 145
120 /* Disable all interrupts */ 146 /* Disable all interrupts */
121 __raw_writel(combiner_data[combiner_nr].irq_mask, 147 __raw_writel(combiner_data[combiner_nr].irq_mask,
@@ -166,23 +192,38 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
166 .map = combiner_irq_domain_map, 192 .map = combiner_irq_domain_map,
167}; 193};
168 194
195static unsigned int exynos4x12_combiner_extra_irq(int group)
196{
197 switch (group) {
198 case 16:
199 return IRQ_SPI(107);
200 case 17:
201 return IRQ_SPI(108);
202 case 18:
203 return IRQ_SPI(48);
204 case 19:
205 return IRQ_SPI(42);
206 default:
207 return 0;
208 }
209}
210
169void __init combiner_init(void __iomem *combiner_base, 211void __init combiner_init(void __iomem *combiner_base,
170 struct device_node *np) 212 struct device_node *np)
171{ 213{
172 int i, irq, irq_base; 214 int i, irq, irq_base;
173 unsigned int max_nr, nr_irq; 215 unsigned int max_nr, nr_irq;
174 216
217 max_nr = max_combiner_nr();
218
175 if (np) { 219 if (np) {
176 if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { 220 if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
177 pr_warning("%s: number of combiners not specified, " 221 pr_info("%s: number of combiners not specified, "
178 "setting default as %d.\n", 222 "setting default as %d.\n",
179 __func__, EXYNOS4_MAX_COMBINER_NR); 223 __func__, max_nr);
180 max_nr = EXYNOS4_MAX_COMBINER_NR;
181 } 224 }
182 } else {
183 max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
184 EXYNOS4_MAX_COMBINER_NR;
185 } 225 }
226
186 nr_irq = max_nr * MAX_IRQ_IN_COMBINER; 227 nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
187 228
188 irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); 229 irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
@@ -199,12 +240,15 @@ void __init combiner_init(void __iomem *combiner_base,
199 } 240 }
200 241
201 for (i = 0; i < max_nr; i++) { 242 for (i = 0; i < max_nr; i++) {
202 combiner_init_one(i, combiner_base + (i >> 2) * 0x10); 243 if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
203 irq = IRQ_SPI(i); 244 irq = IRQ_SPI(i);
245 else
246 irq = exynos4x12_combiner_extra_irq(i);
204#ifdef CONFIG_OF 247#ifdef CONFIG_OF
205 if (np) 248 if (np)
206 irq = irq_of_parse_and_map(np, i); 249 irq = irq_of_parse_and_map(np, i);
207#endif 250#endif
251 combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq);
208 combiner_cascade_irq(i, irq); 252 combiner_cascade_irq(i, irq);
209 } 253 }
210} 254}