Re: [PATCH] irqchip/irq-pruss-intc: implement set_type() callback

From: Marc Zyngier
Date: Tue Jan 05 2021 - 03:48:39 EST


On 2021-01-04 18:36, David Lechner wrote:
This implements the irqchip set_type() callback for the TI PRUSS
interrupt controller. This is needed for cases where an event needs
to be active low.

According to the technical reference manual, the polarity should always
be set to high, however in practice, the polarity needs to be set low
for the McASP Tx/Rx system event in conjunction with soft UART PRU
firmware for TI AM18XX SoCs, otherwise it doesn't work.

I remember asking about this when I reviewed the patch series, and
was told that there was no need to handle anything *but* level high.
As a consequence, the DT binding doesn't have any way to express
the trigger configuration.

Now this? What is going to drive the configuration?


Signed-off-by: David Lechner <david@xxxxxxxxxxxxxx>
---
drivers/irqchip/irq-pruss-intc.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 5409016e6ca0..f882af8a7ded 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -334,6 +334,32 @@ static void pruss_intc_irq_unmask(struct irq_data *data)
pruss_intc_write_reg(intc, PRU_INTC_EISR, hwirq);
}

+static int pruss_intc_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct pruss_intc *intc = irq_data_get_irq_chip_data(data);
+ u32 reg, bit, val;
+
+ if (type & IRQ_TYPE_LEVEL_MASK) {
+ /* polarity register */
+ reg = PRU_INTC_SIPR(data->hwirq / 32);
+ bit = BIT(data->hwirq % 32);
+ val = pruss_intc_read_reg(intc, reg);
+
+ /*
+ * This check also ensures that IRQ_TYPE_DEFAULT will result
+ * in setting the level to high.
+ */
+ if (type & IRQ_TYPE_LEVEL_HIGH)
+ val |= bit;
+ else
+ val &= ~bit;
+
+ pruss_intc_write_reg(intc, reg, val);

RMW of a shared register without locking?

+ }
+
+ return 0;

What happens when this is passed an edge configuration? It should at
least return an error.

+}
+
static int pruss_intc_irq_reqres(struct irq_data *data)
{
if (!try_module_get(THIS_MODULE))
@@ -389,6 +415,7 @@ static struct irq_chip pruss_irqchip = {
.irq_ack = pruss_intc_irq_ack,
.irq_mask = pruss_intc_irq_mask,
.irq_unmask = pruss_intc_irq_unmask,
+ .irq_set_type = pruss_intc_irq_set_type,
.irq_request_resources = pruss_intc_irq_reqres,
.irq_release_resources = pruss_intc_irq_relres,
.irq_get_irqchip_state = pruss_intc_irq_get_irqchip_state,

Thanks,

M.
--
Jazz is not dead. It just smells funny...