lkml.org 
[lkml]   [2018]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 15/16] remoteproc/pru: add support for parsing pru interrupt mapping from DT
    Date
    From: Tero Kristo <t-kristo@ti.com>

    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 <t-kristo@ti.com>
    [s-anna@ti.com: various fixes and cleanups]
    Signed-off-by: Suman Anna <s-anna@ti.com>
    Signed-off-by: Roger Quadros <rogerq@ti.com>
    ---
    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)
    }
    }

    + ret = pru_get_intc_dt_config(dev, "ti,pru-interrupt-map",
    + index, &pru->intc_config);
    + if (ret < 0) {
    + dev_err(dev, "error getting DT interrupt map: %d\n", ret);
    + goto err;
    + }
    +
    + pru->dt_irqs = ret;
    +
    return rproc;

    err:
    @@ -568,7 +662,13 @@ static int pru_rproc_start(struct rproc *rproc)
    dev_dbg(dev, "starting PRU%d: entry-point = 0x%x\n",
    pru->id, (rproc->bootaddr >> 2));

    - /* TODO: INTC setup */
    + if (pru->dt_irqs) {
    + ret = pruss_intc_configure(pru->pruss, &pru->intc_config);
    + if (ret) {
    + dev_err(dev, "failed to configure intc %d\n", ret);
    + return ret;
    + }
    + }

    if (!list_empty(&pru->rproc->rvdevs)) {
    if (!pru->mbox && (pru->irq_vring <= 0 || pru->irq_kick <= 0)) {
    @@ -596,7 +696,8 @@ static int pru_rproc_start(struct rproc *rproc)
    return 0;

    fail:
    - /* TODO: INTC cleanup */
    + if (pru->dt_irqs)
    + pruss_intc_unconfigure(pru->pruss, &pru->intc_config);

    return ret;
    }
    @@ -618,7 +719,9 @@ static int pru_rproc_stop(struct rproc *rproc)
    !pru->mbox && pru->irq_vring > 0)
    free_irq(pru->irq_vring, pru);

    - /* TODO: INTC cleanup */
    + /* undo INTC config */
    + if (pru->dt_irqs)
    + pruss_intc_unconfigure(pru->pruss, &pru->intc_config);

    return 0;
    }
    --
    Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
    Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
    \
     
     \ /
      Last update: 2018-11-26 08:54    [W:4.346 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site