aboutsummaryrefslogtreecommitdiff
path: root/drivers/remoteproc/omap_remoteproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc/omap_remoteproc.c')
-rw-r--r--drivers/remoteproc/omap_remoteproc.c73
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;
}