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) | |||
397 | * | 397 | * |
398 | * Set boot address for a supported DSP remote processor. | 398 | * Set boot address for a supported DSP remote processor. |
399 | */ | 399 | */ |
400 | static void omap_rproc_write_dsp_boot_addr(struct rproc *rproc) | 400 | static int omap_rproc_write_dsp_boot_addr(struct rproc *rproc) |
401 | { | 401 | { |
402 | struct device *dev = rproc->dev.parent; | ||
402 | struct omap_rproc *oproc = rproc->priv; | 403 | struct omap_rproc *oproc = rproc->priv; |
403 | struct omap_rproc_boot_data *bdata = oproc->boot_data; | 404 | struct omap_rproc_boot_data *bdata = oproc->boot_data; |
404 | u32 offset = bdata->boot_reg; | 405 | u32 offset = bdata->boot_reg; |
405 | unsigned int value = rproc->bootaddr; | 406 | unsigned int value = rproc->bootaddr; |
406 | unsigned int mask = ~(SZ_1K - 1); | 407 | unsigned int mask = ~(SZ_1K - 1); |
407 | 408 | ||
409 | if (value & (SZ_1K - 1)) { | ||
410 | dev_err(dev, "invalid boot address 0x%x, must be aligned on a 1KB boundary\n", | ||
411 | value); | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
408 | value >>= bdata->boot_reg_shift; | 415 | value >>= bdata->boot_reg_shift; |
409 | mask >>= bdata->boot_reg_shift; | 416 | mask >>= bdata->boot_reg_shift; |
410 | 417 | ||
411 | regmap_update_bits(bdata->syscon, offset, mask, value); | 418 | regmap_update_bits(bdata->syscon, offset, mask, value); |
419 | |||
420 | return 0; | ||
412 | } | 421 | } |
413 | 422 | ||
414 | /* | 423 | /* |
@@ -431,8 +440,11 @@ static int omap_rproc_start(struct rproc *rproc) | |||
431 | * We set boot address irrespective of the value of the late attach flag | 440 | * We set boot address irrespective of the value of the late attach flag |
432 | * as boot address takes effect only on a deassert of remoteproc reset. | 441 | * as boot address takes effect only on a deassert of remoteproc reset. |
433 | */ | 442 | */ |
434 | if (oproc->boot_data) | 443 | if (oproc->boot_data) { |
435 | omap_rproc_write_dsp_boot_addr(rproc); | 444 | ret = omap_rproc_write_dsp_boot_addr(rproc); |
445 | if (ret) | ||
446 | return ret; | ||
447 | } | ||
436 | 448 | ||
437 | client->dev = dev; | 449 | client->dev = dev; |
438 | client->tx_done = NULL; | 450 | client->tx_done = NULL; |
@@ -715,8 +727,13 @@ static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend) | |||
715 | } | 727 | } |
716 | 728 | ||
717 | /* boot address could be lost after suspend, so restore it */ | 729 | /* boot address could be lost after suspend, so restore it */ |
718 | if (oproc->boot_data) | 730 | if (oproc->boot_data) { |
719 | omap_rproc_write_dsp_boot_addr(rproc); | 731 | ret = omap_rproc_write_dsp_boot_addr(rproc); |
732 | if (ret) { | ||
733 | dev_err(dev, "boot address restore failed %d\n", ret); | ||
734 | goto suspend_iommu; | ||
735 | } | ||
736 | } | ||
720 | 737 | ||
721 | ret = omap_rproc_enable_timers(pdev, false); | 738 | ret = omap_rproc_enable_timers(pdev, false); |
722 | if (ret) { | 739 | if (ret) { |
@@ -836,6 +853,11 @@ static int omap_rproc_runtime_suspend(struct device *dev) | |||
836 | struct omap_rproc *oproc = rproc->priv; | 853 | struct omap_rproc *oproc = rproc->priv; |
837 | int ret; | 854 | int ret; |
838 | 855 | ||
856 | if (rproc->state == RPROC_CRASHED) { | ||
857 | dev_dbg(dev, "rproc cannot be runtime suspended when crashed!\n"); | ||
858 | return -EBUSY; | ||
859 | } | ||
860 | |||
839 | if (WARN_ON(rproc->state != RPROC_RUNNING)) { | 861 | if (WARN_ON(rproc->state != RPROC_RUNNING)) { |
840 | dev_err(dev, "rproc cannot be runtime suspended when not running!\n"); | 862 | dev_err(dev, "rproc cannot be runtime suspended when not running!\n"); |
841 | return -EBUSY; | 863 | return -EBUSY; |
@@ -967,8 +989,8 @@ static int omap_rproc_get_autosuspend_delay(struct platform_device *pdev) | |||
967 | 989 | ||
968 | data = match->data; | 990 | data = match->data; |
969 | 991 | ||
970 | if (!of_device_is_compatible(np, "ti,dra7-rproc-dsp") && | 992 | if (!of_device_is_compatible(np, "ti,dra7-dsp") && |
971 | !of_device_is_compatible(np, "ti,dra7-rproc-ipu")) { | 993 | !of_device_is_compatible(np, "ti,dra7-ipu")) { |
972 | delay = data->autosuspend_delay; | 994 | delay = data->autosuspend_delay; |
973 | goto out; | 995 | goto out; |
974 | } | 996 | } |
@@ -1052,12 +1074,15 @@ static int omap_rproc_get_boot_data(struct platform_device *pdev, | |||
1052 | static int omap_rproc_of_get_internal_memories(struct platform_device *pdev, | 1074 | static int omap_rproc_of_get_internal_memories(struct platform_device *pdev, |
1053 | struct rproc *rproc) | 1075 | struct rproc *rproc) |
1054 | { | 1076 | { |
1055 | static const char * const mem_names[] = {"l2ram"}; | 1077 | static const char * const ipu_mem_names[] = {"l2ram"}; |
1078 | static const char * const dra7_dsp_mem_names[] = {"l2ram", "l1pram", | ||
1079 | "l1dram"}; | ||
1056 | struct device_node *np = pdev->dev.of_node; | 1080 | struct device_node *np = pdev->dev.of_node; |
1057 | struct omap_rproc *oproc = rproc->priv; | 1081 | struct omap_rproc *oproc = rproc->priv; |
1058 | struct device *dev = &pdev->dev; | 1082 | struct device *dev = &pdev->dev; |
1083 | const char * const *mem_names; | ||
1059 | struct resource *res; | 1084 | struct resource *res; |
1060 | int num_mems = 0; | 1085 | int num_mems; |
1061 | const __be32 *addrp; | 1086 | const __be32 *addrp; |
1062 | u32 l4_offset = 0; | 1087 | u32 l4_offset = 0; |
1063 | u64 size; | 1088 | u64 size; |
@@ -1068,8 +1093,15 @@ static int omap_rproc_of_get_internal_memories(struct platform_device *pdev, | |||
1068 | of_device_is_compatible(np, "ti,omap5-dsp")) | 1093 | of_device_is_compatible(np, "ti,omap5-dsp")) |
1069 | return 0; | 1094 | return 0; |
1070 | 1095 | ||
1071 | /* XXX: add support for DRA7 DSP L1 RAMs if needed */ | 1096 | /* DRA7 DSPs have two additional SRAMs at L1 level */ |
1072 | num_mems = ARRAY_SIZE(mem_names); | 1097 | if (of_device_is_compatible(np, "ti,dra7-dsp")) { |
1098 | mem_names = dra7_dsp_mem_names; | ||
1099 | num_mems = ARRAY_SIZE(dra7_dsp_mem_names); | ||
1100 | } else { | ||
1101 | mem_names = ipu_mem_names; | ||
1102 | num_mems = ARRAY_SIZE(ipu_mem_names); | ||
1103 | } | ||
1104 | |||
1073 | oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem), | 1105 | oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem), |
1074 | GFP_KERNEL); | 1106 | GFP_KERNEL); |
1075 | if (!oproc->mem) | 1107 | if (!oproc->mem) |
@@ -1218,7 +1250,9 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
1218 | oproc->num_wd_timers); | 1250 | oproc->num_wd_timers); |
1219 | oproc->num_wd_timers = 0; | 1251 | oproc->num_wd_timers = 0; |
1220 | } else { | 1252 | } else { |
1221 | if (!timer_ops || !timer_ops->get_timer_irq || | 1253 | if (!timer_ops || !timer_ops->request_timer || |
1254 | !timer_ops->release_timer || !timer_ops->start_timer || | ||
1255 | !timer_ops->stop_timer || !timer_ops->get_timer_irq || | ||
1222 | !timer_ops->ack_timer_irq) { | 1256 | !timer_ops->ack_timer_irq) { |
1223 | dev_err(&pdev->dev, "device does not have required watchdog timer ops\n"); | 1257 | dev_err(&pdev->dev, "device does not have required watchdog timer ops\n"); |
1224 | ret = -ENODEV; | 1258 | ret = -ENODEV; |
@@ -1242,19 +1276,26 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
1242 | 1276 | ||
1243 | init_completion(&oproc->pm_comp); | 1277 | init_completion(&oproc->pm_comp); |
1244 | oproc->autosuspend_delay = omap_rproc_get_autosuspend_delay(pdev); | 1278 | oproc->autosuspend_delay = omap_rproc_get_autosuspend_delay(pdev); |
1245 | if (oproc->autosuspend_delay < 0) | 1279 | if (oproc->autosuspend_delay < 0) { |
1280 | ret = oproc->autosuspend_delay; | ||
1246 | goto free_rproc; | 1281 | goto free_rproc; |
1282 | } | ||
1247 | 1283 | ||
1248 | ret = of_property_read_u32(np, "ti,rproc-standby-info", &standby_addr); | 1284 | ret = of_property_read_u32(np, "ti,rproc-standby-info", &standby_addr); |
1249 | if (ret || !standby_addr) | 1285 | if (ret || !standby_addr) { |
1286 | ret = !standby_addr ? -EINVAL : ret; | ||
1250 | goto free_rproc; | 1287 | goto free_rproc; |
1288 | } | ||
1251 | 1289 | ||
1252 | oproc->standby_addr = devm_ioremap(&pdev->dev, standby_addr, | 1290 | oproc->standby_addr = devm_ioremap(&pdev->dev, standby_addr, |
1253 | sizeof(u32)); | 1291 | sizeof(u32)); |
1254 | if (!oproc->standby_addr) | 1292 | if (!oproc->standby_addr) { |
1293 | ret = -ENOMEM; | ||
1255 | goto free_rproc; | 1294 | goto free_rproc; |
1295 | } | ||
1256 | 1296 | ||
1257 | if (of_reserved_mem_device_init(&pdev->dev)) { | 1297 | ret = of_reserved_mem_device_init(&pdev->dev); |
1298 | if (ret) { | ||
1258 | dev_err(&pdev->dev, "device does not have specific CMA pool\n"); | 1299 | dev_err(&pdev->dev, "device does not have specific CMA pool\n"); |
1259 | goto free_rproc; | 1300 | goto free_rproc; |
1260 | } | 1301 | } |