aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/xics/xics-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/xics/xics-common.c')
-rw-r--r--arch/powerpc/sysdev/xics/xics-common.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index a795a5f0301c..9d530f479588 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -328,8 +328,12 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
328 328
329 pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); 329 pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
330 330
331 /* They aren't all level sensitive but we just don't really know */ 331 /*
332 irq_set_status_flags(virq, IRQ_LEVEL); 332 * Mark interrupts as edge sensitive by default so that resend
333 * actually works. The device-tree parsing will turn the LSIs
334 * back to level.
335 */
336 irq_clear_status_flags(virq, IRQ_LEVEL);
333 337
334 /* Don't call into ICS for IPIs */ 338 /* Don't call into ICS for IPIs */
335 if (hw == XICS_IPI) { 339 if (hw == XICS_IPI) {
@@ -351,13 +355,54 @@ static int xics_host_xlate(struct irq_domain *h, struct device_node *ct,
351 irq_hw_number_t *out_hwirq, unsigned int *out_flags) 355 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
352 356
353{ 357{
354 /* Current xics implementation translates everything
355 * to level. It is not technically right for MSIs but this
356 * is irrelevant at this point. We might get smarter in the future
357 */
358 *out_hwirq = intspec[0]; 358 *out_hwirq = intspec[0];
359 *out_flags = IRQ_TYPE_LEVEL_LOW;
360 359
360 /*
361 * If intsize is at least 2, we look for the type in the second cell,
362 * we assume the LSB indicates a level interrupt.
363 */
364 if (intsize > 1) {
365 if (intspec[1] & 1)
366 *out_flags = IRQ_TYPE_LEVEL_LOW;
367 else
368 *out_flags = IRQ_TYPE_EDGE_RISING;
369 } else
370 *out_flags = IRQ_TYPE_LEVEL_LOW;
371
372 return 0;
373}
374
375int xics_set_irq_type(struct irq_data *d, unsigned int flow_type)
376{
377 /*
378 * We only support these. This has really no effect other than setting
379 * the corresponding descriptor bits mind you but those will in turn
380 * affect the resend function when re-enabling an edge interrupt.
381 *
382 * Set set the default to edge as explained in map().
383 */
384 if (flow_type == IRQ_TYPE_DEFAULT || flow_type == IRQ_TYPE_NONE)
385 flow_type = IRQ_TYPE_EDGE_RISING;
386
387 if (flow_type != IRQ_TYPE_EDGE_RISING &&
388 flow_type != IRQ_TYPE_LEVEL_LOW)
389 return -EINVAL;
390
391 irqd_set_trigger_type(d, flow_type);
392
393 return IRQ_SET_MASK_OK_NOCOPY;
394}
395
396int xics_retrigger(struct irq_data *data)
397{
398 /*
399 * We need to push a dummy CPPR when retriggering, since the subsequent
400 * EOI will try to pop it. Passing 0 works, as the function hard codes
401 * the priority value anyway.
402 */
403 xics_push_cppr(0);
404
405 /* Tell the core to do a soft retrigger */
361 return 0; 406 return 0;
362} 407}
363 408