diff mbox series

[PATCHv3,4/6] irqchip/irq-pruss-intc: Implement irq_{get,set}_irqchip_state ops

Message ID 1593699479-1445-5-git-send-email-grzegorz.jaszczyk@linaro.org
State New
Headers show
Series Add TI PRUSS Local Interrupt Controller IRQChip driver | expand

Commit Message

Grzegorz Jaszczyk July 2, 2020, 2:17 p.m. UTC
From: David Lechner <david@lechnology.com>


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 enabling a PRU system event.

Example:
     irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true);

Signed-off-by: David Lechner <david@lechnology.com>

Signed-off-by: Suman Anna <s-anna@ti.com>

Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>

Reviewed-by: Lee Jones <lee.jones@linaro.org>

---
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 | 43 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

-- 
2.7.4

Comments

Marc Zyngier July 2, 2020, 5:54 p.m. UTC | #1
On 2020-07-02 15:17, Grzegorz Jaszczyk wrote:
> From: David Lechner <david@lechnology.com>

> 

> 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 enabling a PRU system event.


"enabling"? That'd be unmasking an interrupt, which isn't what this
does. "injecting", maybe?

> 

> Example:

>      irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true);


Nice example.

What this example does explain is how you are actually going to kick
a PRU via this interface. For that to happen, you'd have to have on
the Linux side an interrupt that is actually routed to a PRU.
And from what I have understood of the previous patches, this can't
be the case. What didi I miss?

> 

> Signed-off-by: David Lechner <david@lechnology.com>

> Signed-off-by: Suman Anna <s-anna@ti.com>

> Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>

> Reviewed-by: Lee Jones <lee.jones@linaro.org>

> ---

> 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 | 43 

> ++++++++++++++++++++++++++++++++++++++--

>  1 file changed, 41 insertions(+), 2 deletions(-)

> 

> diff --git a/drivers/irqchip/irq-pruss-intc.c 

> b/drivers/irqchip/irq-pruss-intc.c

> index 49c936f..19b3d38 100644

> --- a/drivers/irqchip/irq-pruss-intc.c

> +++ b/drivers/irqchip/irq-pruss-intc.c

> @@ -7,6 +7,7 @@

>   *	Suman Anna <s-anna@ti.com>

>   */

> 

> +#include <linux/interrupt.h>

>  #include <linux/irq.h>

>  #include <linux/irqchip/chained_irq.h>

>  #include <linux/irqdomain.h>

> @@ -39,8 +40,7 @@

>  #define PRU_INTC_HIEISR		0x0034

>  #define PRU_INTC_HIDISR		0x0038

>  #define PRU_INTC_GPIR		0x0080

> -#define PRU_INTC_SRSR0		0x0200

> -#define PRU_INTC_SRSR1		0x0204

> +#define PRU_INTC_SRSR(x)	(0x0200 + (x) * 4)

>  #define PRU_INTC_SECR0		0x0280

>  #define PRU_INTC_SECR1		0x0284

>  #define PRU_INTC_ESR0		0x0300

> @@ -145,6 +145,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);


I assume the register file scales as more interrupts are added in the
subsequent patch?

> +	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,

> @@ -152,6 +189,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_irq_domain_map(struct irq_domain *d, unsigned 

> int virq,


Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
diff mbox series

Patch

diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 49c936f..19b3d38 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -7,6 +7,7 @@ 
  *	Suman Anna <s-anna@ti.com>
  */
 
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
@@ -39,8 +40,7 @@ 
 #define PRU_INTC_HIEISR		0x0034
 #define PRU_INTC_HIDISR		0x0038
 #define PRU_INTC_GPIR		0x0080
-#define PRU_INTC_SRSR0		0x0200
-#define PRU_INTC_SRSR1		0x0204
+#define PRU_INTC_SRSR(x)	(0x0200 + (x) * 4)
 #define PRU_INTC_SECR0		0x0280
 #define PRU_INTC_SECR1		0x0284
 #define PRU_INTC_ESR0		0x0300
@@ -145,6 +145,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,
@@ -152,6 +189,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_irq_domain_map(struct irq_domain *d, unsigned int virq,