[PATCH 15/16] remoteproc/pru: add support for parsing pru interrupt mapping from DT
From: Tero Kristo PRU interrupt mapping can now be parsed from devicetree also, from ti,pru-interrupt-map property. This is an alternative configuration method in addition to the legacy resource table config. If both are provided, the config in DT takes precedence. Signed-off-by: Tero Kristo [s-a...@ti.com: various fixes and cleanups] Signed-off-by: Suman Anna Signed-off-by: Roger Quadros --- drivers/remoteproc/pru_rproc.c | 109 +++-- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 84f006b..540cce3 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -63,6 +63,7 @@ enum pru_mem { * @irq_ring: IRQ number to use for processing vring buffers * @irq_kick: IRQ number to use to perform virtio kick * @mem_regions: data for each of the PRU memory regions + * @intc_config: PRU INTC configuration data * @dram0: PRUSS DRAM0 region * @dram1: PRUSS DRAM1 region * @shrdram: PRUSS SHARED RAM region @@ -73,6 +74,7 @@ enum pru_mem { * @shrdram_da: device address of shared Data RAM * @fw_name: name of firmware image used during loading * @gpmux_save: saved value for gpmux config + * @dt_irqs: number of irqs configured from DT * @lock: mutex to protect client usage * @dbg_single_step: debug state variable to set PRU into single step mode * @dbg_continuous: debug state variable to restore PRU execution mode @@ -87,6 +89,7 @@ struct pru_rproc { int irq_vring; int irq_kick; struct pruss_mem_region mem_regions[PRU_MEM_MAX]; + struct pruss_intc_config intc_config; struct pruss_mem_region dram0; struct pruss_mem_region dram1; struct pruss_mem_region shrdram; @@ -97,6 +100,7 @@ struct pru_rproc { u32 shrdram_da; const char *fw_name; u8 gpmux_save; + int dt_irqs; struct mutex lock; /* client access lock */ u32 dbg_single_step; u32 dbg_continuous; @@ -180,6 +184,87 @@ static struct rproc *__pru_rproc_get(struct device_node *np, int index) return rproc; } +static int pru_get_intc_dt_config(struct device *dev, const char *propname, + int index, + struct pruss_intc_config *intc_config) +{ + struct device_node *np = dev->of_node; + struct property *prop; + int ret = 0, entries, i; + int dt_irqs = 0; + u32 *arr; + int max_system_events, max_pru_channels, max_pru_host_ints; + + max_system_events = MAX_PRU_SYS_EVENTS; + max_pru_channels = MAX_PRU_CHANNELS; + max_pru_host_ints = MAX_PRU_CHANNELS; + + prop = of_find_property(np, propname, NULL); + if (!prop) + return 0; + + entries = of_property_count_u32_elems(np, propname); + if (entries <= 0 || entries % 4) + return -EINVAL; + + arr = kmalloc_array(entries, sizeof(u32), GFP_KERNEL); + if (!arr) + return -ENOMEM; + + ret = of_property_read_u32_array(np, propname, arr, entries); + if (ret) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(intc_config->sysev_to_ch); i++) + intc_config->sysev_to_ch[i] = -1; + + for (i = 0; i < ARRAY_SIZE(intc_config->ch_to_host); i++) + intc_config->ch_to_host[i] = -1; + + for (i = 0; i < entries; i += 4) { + if (arr[i] != index) + continue; + + if (arr[i + 1] < 0 || + arr[i + 1] >= max_system_events) { + dev_dbg(dev, "bad sys event %d\n", arr[i + 1]); + ret = -EINVAL; + goto err; + } + + if (arr[i + 2] < 0 || + arr[i + 2] >= max_pru_channels) { + dev_dbg(dev, "bad channel %d\n", arr[i + 2]); + ret = -EINVAL; + goto err; + } + + if (arr[i + 3] < 0 || + arr[i + 3] >= max_pru_host_ints) { + dev_dbg(dev, "bad irq %d\n", arr[i + 3]); + ret = -EINVAL; + goto err; + } + + intc_config->sysev_to_ch[arr[i + 1]] = arr[i + 2]; + dev_dbg(dev, "sysevt-to-ch[%d] -> %d\n", arr[i + 1], + arr[i + 2]); + + intc_config->ch_to_host[arr[i + 2]] = arr[i + 3]; + dev_dbg(dev, "chnl-to-host[%d] -> %d\n", arr[i + 2], + arr[i + 3]); + + dt_irqs++; + } + + kfree(arr); + return dt_irqs; + +err: + kfree(arr); + return ret; +} + /** * pru_rproc_get() - get the PRU rproc instance from a device node * @np: the user/client device node @@ -251,6 +336,15 @@ struct rproc *pru_rproc_get(struct device_node *np, int index)
[PATCH 15/16] remoteproc/pru: add support for parsing pru interrupt mapping from DT
From: Tero Kristo PRU interrupt mapping can now be parsed from devicetree also, from ti,pru-interrupt-map property. This is an alternative configuration method in addition to the legacy resource table config. If both are provided, the config in DT takes precedence. Signed-off-by: Tero Kristo [s-a...@ti.com: various fixes and cleanups] Signed-off-by: Suman Anna Signed-off-by: Roger Quadros --- drivers/remoteproc/pru_rproc.c | 109 +++-- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 84f006b..540cce3 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -63,6 +63,7 @@ enum pru_mem { * @irq_ring: IRQ number to use for processing vring buffers * @irq_kick: IRQ number to use to perform virtio kick * @mem_regions: data for each of the PRU memory regions + * @intc_config: PRU INTC configuration data * @dram0: PRUSS DRAM0 region * @dram1: PRUSS DRAM1 region * @shrdram: PRUSS SHARED RAM region @@ -73,6 +74,7 @@ enum pru_mem { * @shrdram_da: device address of shared Data RAM * @fw_name: name of firmware image used during loading * @gpmux_save: saved value for gpmux config + * @dt_irqs: number of irqs configured from DT * @lock: mutex to protect client usage * @dbg_single_step: debug state variable to set PRU into single step mode * @dbg_continuous: debug state variable to restore PRU execution mode @@ -87,6 +89,7 @@ struct pru_rproc { int irq_vring; int irq_kick; struct pruss_mem_region mem_regions[PRU_MEM_MAX]; + struct pruss_intc_config intc_config; struct pruss_mem_region dram0; struct pruss_mem_region dram1; struct pruss_mem_region shrdram; @@ -97,6 +100,7 @@ struct pru_rproc { u32 shrdram_da; const char *fw_name; u8 gpmux_save; + int dt_irqs; struct mutex lock; /* client access lock */ u32 dbg_single_step; u32 dbg_continuous; @@ -180,6 +184,87 @@ static struct rproc *__pru_rproc_get(struct device_node *np, int index) return rproc; } +static int pru_get_intc_dt_config(struct device *dev, const char *propname, + int index, + struct pruss_intc_config *intc_config) +{ + struct device_node *np = dev->of_node; + struct property *prop; + int ret = 0, entries, i; + int dt_irqs = 0; + u32 *arr; + int max_system_events, max_pru_channels, max_pru_host_ints; + + max_system_events = MAX_PRU_SYS_EVENTS; + max_pru_channels = MAX_PRU_CHANNELS; + max_pru_host_ints = MAX_PRU_CHANNELS; + + prop = of_find_property(np, propname, NULL); + if (!prop) + return 0; + + entries = of_property_count_u32_elems(np, propname); + if (entries <= 0 || entries % 4) + return -EINVAL; + + arr = kmalloc_array(entries, sizeof(u32), GFP_KERNEL); + if (!arr) + return -ENOMEM; + + ret = of_property_read_u32_array(np, propname, arr, entries); + if (ret) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(intc_config->sysev_to_ch); i++) + intc_config->sysev_to_ch[i] = -1; + + for (i = 0; i < ARRAY_SIZE(intc_config->ch_to_host); i++) + intc_config->ch_to_host[i] = -1; + + for (i = 0; i < entries; i += 4) { + if (arr[i] != index) + continue; + + if (arr[i + 1] < 0 || + arr[i + 1] >= max_system_events) { + dev_dbg(dev, "bad sys event %d\n", arr[i + 1]); + ret = -EINVAL; + goto err; + } + + if (arr[i + 2] < 0 || + arr[i + 2] >= max_pru_channels) { + dev_dbg(dev, "bad channel %d\n", arr[i + 2]); + ret = -EINVAL; + goto err; + } + + if (arr[i + 3] < 0 || + arr[i + 3] >= max_pru_host_ints) { + dev_dbg(dev, "bad irq %d\n", arr[i + 3]); + ret = -EINVAL; + goto err; + } + + intc_config->sysev_to_ch[arr[i + 1]] = arr[i + 2]; + dev_dbg(dev, "sysevt-to-ch[%d] -> %d\n", arr[i + 1], + arr[i + 2]); + + intc_config->ch_to_host[arr[i + 2]] = arr[i + 3]; + dev_dbg(dev, "chnl-to-host[%d] -> %d\n", arr[i + 2], + arr[i + 3]); + + dt_irqs++; + } + + kfree(arr); + return dt_irqs; + +err: + kfree(arr); + return ret; +} + /** * pru_rproc_get() - get the PRU rproc instance from a device node * @np: the user/client device node @@ -251,6 +336,15 @@ struct rproc *pru_rproc_get(struct device_node *np, int index)