Message ID | 1595927918-19845-5-git-send-email-grzegorz.jaszczyk@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add TI PRUSS Local Interrupt Controller IRQChip driver | expand |
On 7/28/20 4:18 AM, 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 injecting a PRU system event. > > Example: We could improve this example by showing a device tree node of a firmware-defined device implemented in the PRU: /* Software-defined UART in PRU */ pru_uart: serial@XXXX { compatible = "ti,pru-uart"; ... interrupt-parent = <&pruss_intc>; /* PRU system event 31, channel 0, host event 0 */ interrupts = <31 0 0>, ...; interrupt-names = "kick", ...; ... }, Then driver would request the IRQ during probe: data->kick_irq = of_irq_get_byname(dev, "kick"); if (data->kick_irq < 0) ... And later the driver would use the IRQ to kick the PRU: irq_set_irqchip_state(data->kick_irq, IRQCHIP_STATE_PENDING, true); > 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> > ---
On Wed, 29 Jul 2020 at 21:23, David Lechner <david@lechnology.com> wrote: > > On 7/28/20 4:18 AM, 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 injecting a PRU system event. > > > > Example: > > We could improve this example by showing a device tree node of a > firmware-defined device implemented in the PRU: > > /* Software-defined UART in PRU */ > pru_uart: serial@XXXX { > compatible = "ti,pru-uart"; > ... > interrupt-parent = <&pruss_intc>; > /* PRU system event 31, channel 0, host event 0 */ > interrupts = <31 0 0>, ...; > interrupt-names = "kick", ...; > ... > }, > > Then driver would request the IRQ during probe: > > data->kick_irq = of_irq_get_byname(dev, "kick"); > if (data->kick_irq < 0) > ... > > > And later the driver would use the IRQ to kick the PRU: > > irq_set_irqchip_state(data->kick_irq, IRQCHIP_STATE_PENDING, true); > > We could but I am not sure if this kind of complex example should land in the commit log. Marc could you please comment how you want to see this? Thank you, Grzegorz
On 7/31/20 7:28 AM, Grzegorz Jaszczyk wrote: > On Wed, 29 Jul 2020 at 21:23, David Lechner <david@lechnology.com> wrote: >> >> On 7/28/20 4:18 AM, 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 injecting a PRU system event. >>> >>> Example: >> >> We could improve this example by showing a device tree node of a >> firmware-defined device implemented in the PRU: >> >> /* Software-defined UART in PRU */ >> pru_uart: serial@XXXX { >> compatible = "ti,pru-uart"; >> ... >> interrupt-parent = <&pruss_intc>; >> /* PRU system event 31, channel 0, host event 0 */ >> interrupts = <31 0 0>, ...; >> interrupt-names = "kick", ...; >> ... >> }, >> >> Then driver would request the IRQ during probe: >> >> data->kick_irq = of_irq_get_byname(dev, "kick"); >> if (data->kick_irq < 0) >> ... >> >> >> And later the driver would use the IRQ to kick the PRU: >> >> irq_set_irqchip_state(data->kick_irq, IRQCHIP_STATE_PENDING, true); >> >> > > We could but I am not sure if this kind of complex example should land > in the commit log. > Marc could you please comment how you want to see this? > > Thank you, > Grzegorz > Based on the discussion in the device tree binding patch, the expanded example I gave is incorrect, so we can just drop it.
diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c index cf9a59b..c13ba14 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> @@ -316,6 +317,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, @@ -323,6 +361,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,