[PATCH 15/16] remoteproc/pru: add support for parsing pru interrupt mapping from DT

2018-11-25 Thread Roger Quadros
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

2018-11-25 Thread Roger Quadros
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)