Messages in this thread | | | Date | Wed, 4 Oct 2017 15:03:02 +0100 | From | James Hogan <> | Subject | Re: [PATCH 4/4] irqchip: imgpdc: Pass on peripheral mask/unmasks to the parent |
| |
Hi Ed,
On Mon, Oct 02, 2017 at 10:55:59AM +0100, Ed Blake wrote: > > Pass on peripheral (RTC/IR/WD) irq masks and unmasks to the parent > interrupt controller, as well as setting / clearing the relevant bits > in the IRQ_ROUTE register. > > Clearing bits in the IRQ_ROUTE register will prevent future interrupts > from being passed on to the parent, but won't mask an existing > interrupt which has already made it to the parent.
Is it an edge or level sensitive interrupt from the PDC?
I'm a little rusty on the IRQ subsystem TBH, but if edge sensitive I would have expected the parent interrupt to be acked/cleared by the parent handler.
And if level sensitive I would have expected the deasserted parent interrupt to be masked by the parent handler, and immediately cleared upon rerouting.
Maybe you can clarify whats going on here.
Cheers James
> This is currently > causing peipheral interrupts to fire continuously when the system wakes > from a suspended state when one of the peripherals is used to wake the > system (e.g. RTC, IR). The interrupt occurs early in the wake process > (still in the noirq phase) and because the peripheral interrupt is > disabled at that point, the core marks it as pending and masks it out. > This mask must be passed to the parent controller to be effective. > > Signed-off-by: Ed Blake <ed.blake@sondrel.com> > --- > drivers/irqchip/irq-imgpdc.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c > index d1bcfef..05c48dd 100644 > --- a/drivers/irqchip/irq-imgpdc.c > +++ b/drivers/irqchip/irq-imgpdc.c > @@ -141,21 +141,31 @@ static struct pdc_intc_priv *irqd_to_priv(struct irq_data *data) > static void perip_irq_mask(struct irq_data *data) > { > struct pdc_intc_priv *priv = irqd_to_priv(data); > + unsigned int parent_irq = priv->perip_irqs[data->hwirq]; > + struct irq_data *parent_irq_data = irq_get_irq_data(parent_irq); > > raw_spin_lock(&priv->lock); > priv->irq_route &= ~data->mask; > pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route); > raw_spin_unlock(&priv->lock); > + > + /* Pass on the mask to the parent */ > + parent_irq_data->chip->irq_mask(parent_irq_data); > } > > static void perip_irq_unmask(struct irq_data *data) > { > struct pdc_intc_priv *priv = irqd_to_priv(data); > + unsigned int parent_irq = priv->perip_irqs[data->hwirq]; > + struct irq_data *parent_irq_data = irq_get_irq_data(parent_irq); > > raw_spin_lock(&priv->lock); > priv->irq_route |= data->mask; > pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route); > raw_spin_unlock(&priv->lock); > + > + /* Pass on the unmask to the parent */ > + parent_irq_data->chip->irq_unmask(parent_irq_data); > } > > static int syswake_irq_set_type(struct irq_data *data, unsigned int flow_type) > -- > 1.9.1 > [unhandled content-type:application/pgp-signature] | |