diff options
Diffstat (limited to 'drivers/remoteproc/omap_remoteproc.c')
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.c | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 51db2441b506..5d6f17bdfb2f 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -397,18 +397,27 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) * * Set boot address for a supported DSP remote processor. */ -static void omap_rproc_write_dsp_boot_addr(struct rproc *rproc) +static int omap_rproc_write_dsp_boot_addr(struct rproc *rproc) { + struct device *dev = rproc->dev.parent; struct omap_rproc *oproc = rproc->priv; struct omap_rproc_boot_data *bdata = oproc->boot_data; u32 offset = bdata->boot_reg; unsigned int value = rproc->bootaddr; unsigned int mask = ~(SZ_1K - 1); + if (value & (SZ_1K - 1)) { + dev_err(dev, "invalid boot address 0x%x, must be aligned on a 1KB boundary\n", + value); + return -EINVAL; + } + value >>= bdata->boot_reg_shift; mask >>= bdata->boot_reg_shift; regmap_update_bits(bdata->syscon, offset, mask, value); + + return 0; } /* @@ -431,8 +440,11 @@ static int omap_rproc_start(struct rproc *rproc) * We set boot address irrespective of the value of the late attach flag * as boot address takes effect only on a deassert of remoteproc reset. */ - if (oproc->boot_data) - omap_rproc_write_dsp_boot_addr(rproc); + if (oproc->boot_data) { + ret = omap_rproc_write_dsp_boot_addr(rproc); + if (ret) + return ret; + } client->dev = dev; client->tx_done = NULL; @@ -715,8 +727,13 @@ static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend) } /* boot address could be lost after suspend, so restore it */ - if (oproc->boot_data) - omap_rproc_write_dsp_boot_addr(rproc); + if (oproc->boot_data) { + ret = omap_rproc_write_dsp_boot_addr(rproc); + if (ret) { + dev_err(dev, "boot address restore failed %d\n", ret); + goto suspend_iommu; + } + } ret = omap_rproc_enable_timers(pdev, false); if (ret) { @@ -836,6 +853,11 @@ static int omap_rproc_runtime_suspend(struct device *dev) struct omap_rproc *oproc = rproc->priv; int ret; + if (rproc->state == RPROC_CRASHED) { + dev_dbg(dev, "rproc cannot be runtime suspended when crashed!\n"); + return -EBUSY; + } + if (WARN_ON(rproc->state != RPROC_RUNNING)) { dev_err(dev, "rproc cannot be runtime suspended when not running!\n"); return -EBUSY; @@ -967,8 +989,8 @@ static int omap_rproc_get_autosuspend_delay(struct platform_device *pdev) data = match->data; - if (!of_device_is_compatible(np, "ti,dra7-rproc-dsp") && - !of_device_is_compatible(np, "ti,dra7-rproc-ipu")) { + if (!of_device_is_compatible(np, "ti,dra7-dsp") && + !of_device_is_compatible(np, "ti,dra7-ipu")) { delay = data->autosuspend_delay; goto out; } @@ -1052,12 +1074,15 @@ static int omap_rproc_get_boot_data(struct platform_device *pdev, static int omap_rproc_of_get_internal_memories(struct platform_device *pdev, struct rproc *rproc) { - static const char * const mem_names[] = {"l2ram"}; + static const char * const ipu_mem_names[] = {"l2ram"}; + static const char * const dra7_dsp_mem_names[] = {"l2ram", "l1pram", + "l1dram"}; struct device_node *np = pdev->dev.of_node; struct omap_rproc *oproc = rproc->priv; struct device *dev = &pdev->dev; + const char * const *mem_names; struct resource *res; - int num_mems = 0; + int num_mems; const __be32 *addrp; u32 l4_offset = 0; u64 size; @@ -1068,8 +1093,15 @@ static int omap_rproc_of_get_internal_memories(struct platform_device *pdev, of_device_is_compatible(np, "ti,omap5-dsp")) return 0; - /* XXX: add support for DRA7 DSP L1 RAMs if needed */ - num_mems = ARRAY_SIZE(mem_names); + /* DRA7 DSPs have two additional SRAMs at L1 level */ + if (of_device_is_compatible(np, "ti,dra7-dsp")) { + mem_names = dra7_dsp_mem_names; + num_mems = ARRAY_SIZE(dra7_dsp_mem_names); + } else { + mem_names = ipu_mem_names; + num_mems = ARRAY_SIZE(ipu_mem_names); + } + oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem), GFP_KERNEL); if (!oproc->mem) @@ -1218,7 +1250,9 @@ static int omap_rproc_probe(struct platform_device *pdev) oproc->num_wd_timers); oproc->num_wd_timers = 0; } else { - if (!timer_ops || !timer_ops->get_timer_irq || + if (!timer_ops || !timer_ops->request_timer || + !timer_ops->release_timer || !timer_ops->start_timer || + !timer_ops->stop_timer || !timer_ops->get_timer_irq || !timer_ops->ack_timer_irq) { dev_err(&pdev->dev, "device does not have required watchdog timer ops\n"); ret = -ENODEV; @@ -1242,19 +1276,26 @@ static int omap_rproc_probe(struct platform_device *pdev) init_completion(&oproc->pm_comp); oproc->autosuspend_delay = omap_rproc_get_autosuspend_delay(pdev); - if (oproc->autosuspend_delay < 0) + if (oproc->autosuspend_delay < 0) { + ret = oproc->autosuspend_delay; goto free_rproc; + } ret = of_property_read_u32(np, "ti,rproc-standby-info", &standby_addr); - if (ret || !standby_addr) + if (ret || !standby_addr) { + ret = !standby_addr ? -EINVAL : ret; goto free_rproc; + } oproc->standby_addr = devm_ioremap(&pdev->dev, standby_addr, sizeof(u32)); - if (!oproc->standby_addr) + if (!oproc->standby_addr) { + ret = -ENOMEM; goto free_rproc; + } - if (of_reserved_mem_device_init(&pdev->dev)) { + ret = of_reserved_mem_device_init(&pdev->dev); + if (ret) { dev_err(&pdev->dev, "device does not have specific CMA pool\n"); goto free_rproc; } |