From: David Lechner <[email protected]>

This implements the irq_get_irqchip_state and irq_set_irqchip_state
callbacks for the TI PRUSS INTC driver. The set callback can be used
by drivers to "kick" a PRU by injecting a PRU system event.

Signed-off-by: David Lechner <[email protected]>
Signed-off-by: Suman Anna <[email protected]>
Signed-off-by: Grzegorz Jaszczyk <[email protected]>
Reviewed-by: Lee Jones <[email protected]>
---
v5->v6:
- Drop example from the commit log
v4->v5:
- No change.
v3->v4:
- Update commit message
v2->v3:
- Get rid of unnecessary pruss_intc_check_write() and use
  pruss_intc_write_reg directly.
v1->v2:
- https://patchwork.kernel.org/patch/11069769/
---
 drivers/irqchip/irq-pruss-intc.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 396dc55..41c6271 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -12,6 +12,7 @@
  * Copyright (C) 2019 David Lechner <[email protected]>
  */
 
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
@@ -323,6 +324,43 @@ static void pruss_intc_irq_relres(struct irq_data *data)
        module_put(THIS_MODULE);
 }
 
+static int pruss_intc_irq_get_irqchip_state(struct irq_data *data,
+                                           enum irqchip_irq_state which,
+                                           bool *state)
+{
+       struct pruss_intc *intc = irq_data_get_irq_chip_data(data);
+       u32 reg, mask, srsr;
+
+       if (which != IRQCHIP_STATE_PENDING)
+               return -EINVAL;
+
+       reg = PRU_INTC_SRSR(data->hwirq / 32);
+       mask = BIT(data->hwirq % 32);
+
+       srsr = pruss_intc_read_reg(intc, reg);
+
+       *state = !!(srsr & mask);
+
+       return 0;
+}
+
+static int pruss_intc_irq_set_irqchip_state(struct irq_data *data,
+                                           enum irqchip_irq_state which,
+                                           bool state)
+{
+       struct pruss_intc *intc = irq_data_get_irq_chip_data(data);
+
+       if (which != IRQCHIP_STATE_PENDING)
+               return -EINVAL;
+
+       if (state)
+               pruss_intc_write_reg(intc, PRU_INTC_SISR, data->hwirq);
+       else
+               pruss_intc_write_reg(intc, PRU_INTC_SICR, data->hwirq);
+
+       return 0;
+}
+
 static struct irq_chip pruss_irqchip = {
        .name                   = "pruss-intc",
        .irq_ack                = pruss_intc_irq_ack,
@@ -330,6 +368,8 @@ static struct irq_chip pruss_irqchip = {
        .irq_unmask             = pruss_intc_irq_unmask,
        .irq_request_resources  = pruss_intc_irq_reqres,
        .irq_release_resources  = pruss_intc_irq_relres,
+       .irq_get_irqchip_state  = pruss_intc_irq_get_irqchip_state,
+       .irq_set_irqchip_state  = pruss_intc_irq_set_irqchip_state,
 };
 
 static int pruss_intc_validate_mapping(struct pruss_intc *intc, int event,
-- 
2.7.4

Reply via email to