aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/kernel/mcip.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/kernel/mcip.c')
-rw-r--r--arch/arc/kernel/mcip.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index c424d5abc318..f39142acc89e 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -181,6 +181,8 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
181{ 181{
182 unsigned long flags; 182 unsigned long flags;
183 cpumask_t online; 183 cpumask_t online;
184 unsigned int destination_bits;
185 unsigned int distribution_mode;
184 186
185 /* errout if no online cpu per @cpumask */ 187 /* errout if no online cpu per @cpumask */
186 if (!cpumask_and(&online, cpumask, cpu_online_mask)) 188 if (!cpumask_and(&online, cpumask, cpu_online_mask))
@@ -188,8 +190,15 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
188 190
189 raw_spin_lock_irqsave(&mcip_lock, flags); 191 raw_spin_lock_irqsave(&mcip_lock, flags);
190 192
191 idu_set_dest(data->hwirq, cpumask_bits(&online)[0]); 193 destination_bits = cpumask_bits(&online)[0];
192 idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR); 194 idu_set_dest(data->hwirq, destination_bits);
195
196 if (ffs(destination_bits) == fls(destination_bits))
197 distribution_mode = IDU_M_DISTRI_DEST;
198 else
199 distribution_mode = IDU_M_DISTRI_RR;
200
201 idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
193 202
194 raw_spin_unlock_irqrestore(&mcip_lock, flags); 203 raw_spin_unlock_irqrestore(&mcip_lock, flags);
195 204
@@ -207,16 +216,15 @@ static struct irq_chip idu_irq_chip = {
207 216
208}; 217};
209 218
210static int idu_first_irq; 219static irq_hw_number_t idu_first_hwirq;
211 220
212static void idu_cascade_isr(struct irq_desc *desc) 221static void idu_cascade_isr(struct irq_desc *desc)
213{ 222{
214 struct irq_domain *domain = irq_desc_get_handler_data(desc); 223 struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
215 unsigned int core_irq = irq_desc_get_irq(desc); 224 irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
216 unsigned int idu_irq; 225 irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
217 226
218 idu_irq = core_irq - idu_first_irq; 227 generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
219 generic_handle_irq(irq_find_mapping(domain, idu_irq));
220} 228}
221 229
222static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq) 230static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
@@ -282,7 +290,7 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
282 struct irq_domain *domain; 290 struct irq_domain *domain;
283 /* Read IDU BCR to confirm nr_irqs */ 291 /* Read IDU BCR to confirm nr_irqs */
284 int nr_irqs = of_irq_count(intc); 292 int nr_irqs = of_irq_count(intc);
285 int i, irq; 293 int i, virq;
286 struct mcip_bcr mp; 294 struct mcip_bcr mp;
287 295
288 READ_BCR(ARC_REG_MCIP_BCR, mp); 296 READ_BCR(ARC_REG_MCIP_BCR, mp);
@@ -303,11 +311,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
303 * however we need it to get the parent virq and set IDU handler 311 * however we need it to get the parent virq and set IDU handler
304 * as first level isr 312 * as first level isr
305 */ 313 */
306 irq = irq_of_parse_and_map(intc, i); 314 virq = irq_of_parse_and_map(intc, i);
307 if (!i) 315 if (!i)
308 idu_first_irq = irq; 316 idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
309 317
310 irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain); 318 irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
311 } 319 }
312 320
313 __mcip_cmd(CMD_IDU_ENABLE, 0); 321 __mcip_cmd(CMD_IDU_ENABLE, 0);