Lines Matching +full:dra7 +full:- +full:dsp
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2011-2020 Texas Instruments Incorporated - http://www.ti.com/
8 * Ohad Ben-Cohen <ohad@wizery.com>
12 * Suman Anna <s-anna@ti.com>
13 * Hari Kanigeri <h-kanigeri2@ti.com>
26 #include <linux/dma-mapping.h>
30 #include <linux/omap-iommu.h>
31 #include <linux/omap-mailbox.h>
35 #include <clocksource/timer-ti-dm.h>
37 #include <linux/platform_data/dmtimer-omap.h>
42 /* default auto-suspend delay (ms) */
46 * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs
49 * @boot_reg_shift: bit-field shift required for the boot address value in
59 * struct omap_rproc_mem - internal memory structure
62 * @dev_addr: device address of the memory region from DSP view
73 * struct omap_rproc_timer - data structure for a timer used by a omap rproc
85 * struct omap_rproc - omap remote processor state
94 * @autosuspend_delay: auto-suspend delay value to be used for runtime pm
121 * struct omap_rproc_mem_data - memory definitions for an omap remote processor
131 * struct omap_rproc_dev_data - device data for the omap remote processor
141 * omap_rproc_request_timer() - request a timer for a remoteproc
159 timer->odt = timer->timer_ops->request_by_node(np); in omap_rproc_request_timer()
160 if (!timer->odt) { in omap_rproc_request_timer()
162 return -EBUSY; in omap_rproc_request_timer()
165 ret = timer->timer_ops->set_source(timer->odt, OMAP_TIMER_SRC_SYS_CLK); in omap_rproc_request_timer()
169 timer->timer_ops->free(timer->odt); in omap_rproc_request_timer()
174 timer->timer_ops->set_load(timer->odt, 0); in omap_rproc_request_timer()
180 * omap_rproc_start_timer() - start a timer for a remoteproc
192 return timer->timer_ops->start(timer->odt); in omap_rproc_start_timer()
196 * omap_rproc_stop_timer() - stop a timer for a remoteproc
209 return timer->timer_ops->stop(timer->odt); in omap_rproc_stop_timer()
213 * omap_rproc_release_timer() - release a timer for a remoteproc
224 return timer->timer_ops->free(timer->odt); in omap_rproc_release_timer()
228 * omap_rproc_get_timer_irq() - get the irq for a timer
239 return timer->timer_ops->get_irq(timer->odt); in omap_rproc_get_timer_irq()
243 * omap_rproc_ack_timer_irq() - acknowledge a timer irq
252 timer->timer_ops->write_status(timer->odt, OMAP_TIMER_INT_OVERFLOW); in omap_rproc_ack_timer_irq()
256 * omap_rproc_watchdog_isr() - Watchdog ISR handler for remoteproc device
260 * This ISR routine executes the required necessary low-level code to
274 struct omap_rproc *oproc = rproc->priv; in omap_rproc_watchdog_isr()
275 struct device *dev = rproc->dev.parent; in omap_rproc_watchdog_isr()
276 struct omap_rproc_timer *timers = oproc->timers; in omap_rproc_watchdog_isr()
278 int num_timers = oproc->num_timers + oproc->num_wd_timers; in omap_rproc_watchdog_isr()
281 for (i = oproc->num_timers; i < num_timers; i++) { in omap_rproc_watchdog_isr()
301 * omap_rproc_enable_timers() - enable the timers for a remoteproc
319 struct omap_rproc *oproc = rproc->priv; in omap_rproc_enable_timers()
320 struct omap_rproc_timer *timers = oproc->timers; in omap_rproc_enable_timers()
321 struct device *dev = rproc->dev.parent; in omap_rproc_enable_timers()
323 int num_timers = oproc->num_timers + oproc->num_wd_timers; in omap_rproc_enable_timers()
332 if (i < oproc->num_timers) in omap_rproc_enable_timers()
333 np = of_parse_phandle(dev->of_node, "ti,timers", i); in omap_rproc_enable_timers()
335 np = of_parse_phandle(dev->of_node, in omap_rproc_enable_timers()
336 "ti,watchdog-timers", in omap_rproc_enable_timers()
337 (i - oproc->num_timers)); in omap_rproc_enable_timers()
339 ret = -ENXIO; in omap_rproc_enable_timers()
341 i < oproc->num_timers ? i : in omap_rproc_enable_timers()
342 i - oproc->num_timers, ret); in omap_rproc_enable_timers()
348 ret = -ENODEV; in omap_rproc_enable_timers()
353 tpdata = dev_get_platdata(&tpdev->dev); in omap_rproc_enable_timers()
354 put_device(&tpdev->dev); in omap_rproc_enable_timers()
356 ret = -EINVAL; in omap_rproc_enable_timers()
361 timer_ops = tpdata->timer_ops; in omap_rproc_enable_timers()
362 if (!timer_ops || !timer_ops->request_by_node || in omap_rproc_enable_timers()
363 !timer_ops->set_source || !timer_ops->set_load || in omap_rproc_enable_timers()
364 !timer_ops->free || !timer_ops->start || in omap_rproc_enable_timers()
365 !timer_ops->stop || !timer_ops->get_irq || in omap_rproc_enable_timers()
366 !timer_ops->write_status) { in omap_rproc_enable_timers()
367 ret = -EINVAL; in omap_rproc_enable_timers()
372 timers[i].irq = -1; in omap_rproc_enable_timers()
382 if (i >= oproc->num_timers) { in omap_rproc_enable_timers()
387 ret = -EBUSY; in omap_rproc_enable_timers()
393 "rproc-wdt", rproc); in omap_rproc_enable_timers()
400 timers[i].irq = -1; in omap_rproc_enable_timers()
418 i--; in omap_rproc_enable_timers()
428 while (i--) { in omap_rproc_enable_timers()
429 if (i >= oproc->num_timers) in omap_rproc_enable_timers()
434 timers[i].irq = -1; in omap_rproc_enable_timers()
441 * omap_rproc_disable_timers() - disable the timers for a remoteproc
455 struct omap_rproc *oproc = rproc->priv; in omap_rproc_disable_timers()
456 struct omap_rproc_timer *timers = oproc->timers; in omap_rproc_disable_timers()
457 int num_timers = oproc->num_timers + oproc->num_wd_timers; in omap_rproc_disable_timers()
465 if (i >= oproc->num_timers) in omap_rproc_disable_timers()
470 timers[i].irq = -1; in omap_rproc_disable_timers()
478 * omap_rproc_mbox_callback() - inbound mailbox message handler
487 * In addition to virtqueue indices, we also have some out-of-band values
495 struct device *dev = oproc->rproc->dev.parent; in omap_rproc_mbox_callback()
496 const char *name = oproc->rproc->name; in omap_rproc_mbox_callback()
508 rproc_report_crash(oproc->rproc, RPROC_FATAL_ERROR); in omap_rproc_mbox_callback()
515 oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK; in omap_rproc_mbox_callback()
516 complete(&oproc->pm_comp); in omap_rproc_mbox_callback()
521 if (msg > oproc->rproc->max_notifyid) { in omap_rproc_mbox_callback()
526 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) in omap_rproc_mbox_callback()
534 struct omap_rproc *oproc = rproc->priv; in omap_rproc_kick()
535 struct device *dev = rproc->dev.parent; in omap_rproc_kick()
548 ret = mbox_send_message(oproc->mbox, (void *)vqid); in omap_rproc_kick()
558 * omap_rproc_write_dsp_boot_addr() - set boot address for DSP remote processor
561 * Set boot address for a supported DSP remote processor.
563 * Return: 0 on success, or -EINVAL if boot address is not aligned properly
567 struct device *dev = rproc->dev.parent; in omap_rproc_write_dsp_boot_addr()
568 struct omap_rproc *oproc = rproc->priv; in omap_rproc_write_dsp_boot_addr()
569 struct omap_rproc_boot_data *bdata = oproc->boot_data; in omap_rproc_write_dsp_boot_addr()
570 u32 offset = bdata->boot_reg; in omap_rproc_write_dsp_boot_addr()
574 if (rproc->bootaddr & (SZ_1K - 1)) { in omap_rproc_write_dsp_boot_addr()
576 rproc->bootaddr); in omap_rproc_write_dsp_boot_addr()
577 return -EINVAL; in omap_rproc_write_dsp_boot_addr()
580 value = rproc->bootaddr >> bdata->boot_reg_shift; in omap_rproc_write_dsp_boot_addr()
581 mask = ~(SZ_1K - 1) >> bdata->boot_reg_shift; in omap_rproc_write_dsp_boot_addr()
583 return regmap_update_bits(bdata->syscon, offset, mask, value); in omap_rproc_write_dsp_boot_addr()
595 struct omap_rproc *oproc = rproc->priv; in omap_rproc_start()
596 struct device *dev = rproc->dev.parent; in omap_rproc_start()
598 struct mbox_client *client = &oproc->client; in omap_rproc_start()
600 if (oproc->boot_data) { in omap_rproc_start()
606 client->dev = dev; in omap_rproc_start()
607 client->tx_done = NULL; in omap_rproc_start()
608 client->rx_callback = omap_rproc_mbox_callback; in omap_rproc_start()
609 client->tx_block = false; in omap_rproc_start()
610 client->knows_txdone = false; in omap_rproc_start()
612 oproc->mbox = mbox_request_channel(client, 0); in omap_rproc_start()
613 if (IS_ERR(oproc->mbox)) { in omap_rproc_start()
614 ret = -EBUSY; in omap_rproc_start()
616 PTR_ERR(oproc->mbox)); in omap_rproc_start()
621 * Ping the remote processor. this is only for sanity-sake; in omap_rproc_start()
627 ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST); in omap_rproc_start()
639 ret = reset_control_deassert(oproc->reset); in omap_rproc_start()
647 * enable the auto-suspend. The device usage count is incremented in omap_rproc_start()
648 * manually for balancing it for auto-suspend in omap_rproc_start()
662 mbox_free_channel(oproc->mbox); in omap_rproc_start()
669 struct device *dev = rproc->dev.parent; in omap_rproc_stop()
670 struct omap_rproc *oproc = rproc->priv; in omap_rproc_stop()
687 ret = reset_control_assert(oproc->reset); in omap_rproc_stop()
695 mbox_free_channel(oproc->mbox); in omap_rproc_stop()
709 reset_control_deassert(oproc->reset); in omap_rproc_stop()
711 /* schedule the next auto-suspend */ in omap_rproc_stop()
718 * omap_rproc_da_to_va() - internal memory translation helper
725 * present in a DSP or IPU device). The translated addresses can be used
733 struct omap_rproc *oproc = rproc->priv; in omap_rproc_da_to_va()
740 if (!oproc->num_mems) in omap_rproc_da_to_va()
743 for (i = 0; i < oproc->num_mems; i++) { in omap_rproc_da_to_va()
744 if (da >= oproc->mem[i].dev_addr && da + len <= in omap_rproc_da_to_va()
745 oproc->mem[i].dev_addr + oproc->mem[i].size) { in omap_rproc_da_to_va()
746 offset = da - oproc->mem[i].dev_addr; in omap_rproc_da_to_va()
748 return (__force void *)(oproc->mem[i].cpu_addr + in omap_rproc_da_to_va()
766 return ti_clk_is_in_standby(oproc->fck); in _is_rproc_in_standby()
773 struct device *dev = rproc->dev.parent; in _omap_rproc_suspend()
774 struct omap_rproc *oproc = rproc->priv; in _omap_rproc_suspend()
781 reinit_completion(&oproc->pm_comp); in _omap_rproc_suspend()
782 oproc->suspend_acked = false; in _omap_rproc_suspend()
783 ret = mbox_send_message(oproc->mbox, (void *)suspend_msg); in _omap_rproc_suspend()
789 ret = wait_for_completion_timeout(&oproc->pm_comp, to); in _omap_rproc_suspend()
790 if (!oproc->suspend_acked) in _omap_rproc_suspend()
791 return -EBUSY; in _omap_rproc_suspend()
796 * function, and it cannot have any inter-dependencies against the IPC in _omap_rproc_suspend()
805 * appropriate target-specific WFI instruction causing the module to in _omap_rproc_suspend()
810 return -ETIME; in _omap_rproc_suspend()
814 ret = reset_control_assert(oproc->reset); in _omap_rproc_suspend()
833 ret = omap_iommu_domain_deactivate(rproc->domain); in _omap_rproc_suspend()
844 /* ignore errors on re-enabling code */ in _omap_rproc_suspend()
847 reset_control_deassert(oproc->reset); in _omap_rproc_suspend()
853 struct device *dev = rproc->dev.parent; in _omap_rproc_resume()
854 struct omap_rproc *oproc = rproc->priv; in _omap_rproc_resume()
863 ret = omap_iommu_domain_activate(rproc->domain); in _omap_rproc_resume()
871 if (oproc->boot_data) { in _omap_rproc_resume()
885 ret = reset_control_deassert(oproc->reset); in _omap_rproc_resume()
897 omap_iommu_domain_deactivate(rproc->domain); in _omap_rproc_resume()
905 struct omap_rproc *oproc = rproc->priv; in omap_rproc_suspend()
908 mutex_lock(&rproc->lock); in omap_rproc_suspend()
909 if (rproc->state == RPROC_OFFLINE) in omap_rproc_suspend()
912 if (rproc->state == RPROC_SUSPENDED) in omap_rproc_suspend()
915 if (rproc->state != RPROC_RUNNING) { in omap_rproc_suspend()
916 ret = -EBUSY; in omap_rproc_suspend()
930 oproc->need_resume = true; in omap_rproc_suspend()
931 rproc->state = RPROC_SUSPENDED; in omap_rproc_suspend()
934 mutex_unlock(&rproc->lock); in omap_rproc_suspend()
941 struct omap_rproc *oproc = rproc->priv; in omap_rproc_resume()
944 mutex_lock(&rproc->lock); in omap_rproc_resume()
945 if (rproc->state == RPROC_OFFLINE) in omap_rproc_resume()
948 if (rproc->state != RPROC_SUSPENDED) { in omap_rproc_resume()
949 ret = -EBUSY; in omap_rproc_resume()
954 * remoteproc was auto-suspended at the time of system suspend, in omap_rproc_resume()
955 * so no need to wake-up the processor (leave it in suspended in omap_rproc_resume()
958 if (!oproc->need_resume) in omap_rproc_resume()
967 oproc->need_resume = false; in omap_rproc_resume()
968 rproc->state = RPROC_RUNNING; in omap_rproc_resume()
972 mutex_unlock(&rproc->lock); in omap_rproc_resume()
979 struct omap_rproc *oproc = rproc->priv; in omap_rproc_runtime_suspend()
982 mutex_lock(&rproc->lock); in omap_rproc_runtime_suspend()
983 if (rproc->state == RPROC_CRASHED) { in omap_rproc_runtime_suspend()
985 ret = -EBUSY; in omap_rproc_runtime_suspend()
989 if (WARN_ON(rproc->state != RPROC_RUNNING)) { in omap_rproc_runtime_suspend()
991 ret = -EBUSY; in omap_rproc_runtime_suspend()
997 * idled for runtime auto-suspend in omap_rproc_runtime_suspend()
1000 ret = -EBUSY; in omap_rproc_runtime_suspend()
1008 rproc->state = RPROC_SUSPENDED; in omap_rproc_runtime_suspend()
1009 mutex_unlock(&rproc->lock); in omap_rproc_runtime_suspend()
1015 mutex_unlock(&rproc->lock); in omap_rproc_runtime_suspend()
1024 mutex_lock(&rproc->lock); in omap_rproc_runtime_resume()
1025 if (WARN_ON(rproc->state != RPROC_SUSPENDED)) { in omap_rproc_runtime_resume()
1027 rproc->state); in omap_rproc_runtime_resume()
1028 ret = -EBUSY; in omap_rproc_runtime_resume()
1038 rproc->state = RPROC_RUNNING; in omap_rproc_runtime_resume()
1040 mutex_unlock(&rproc->lock); in omap_rproc_runtime_resume()
1058 .device_name = "dsp",
1067 .device_name = "dsp",
1076 .device_name = "dsp",
1087 .compatible = "ti,omap4-dsp",
1091 .compatible = "ti,omap4-ipu",
1095 .compatible = "ti,omap5-dsp",
1099 .compatible = "ti,omap5-ipu",
1103 .compatible = "ti,dra7-dsp",
1107 .compatible = "ti,dra7-ipu",
1121 ret = of_property_read_string(pdev->dev.of_node, "firmware-name", in omap_rproc_get_firmware()
1132 struct device_node *np = pdev->dev.of_node; in omap_rproc_get_boot_data()
1133 struct omap_rproc *oproc = rproc->priv; in omap_rproc_get_boot_data()
1137 data = of_device_get_match_data(&pdev->dev); in omap_rproc_get_boot_data()
1139 return -ENODEV; in omap_rproc_get_boot_data()
1144 oproc->boot_data = devm_kzalloc(&pdev->dev, sizeof(*oproc->boot_data), in omap_rproc_get_boot_data()
1146 if (!oproc->boot_data) in omap_rproc_get_boot_data()
1147 return -ENOMEM; in omap_rproc_get_boot_data()
1149 oproc->boot_data->syscon = in omap_rproc_get_boot_data()
1151 if (IS_ERR(oproc->boot_data->syscon)) { in omap_rproc_get_boot_data()
1152 ret = PTR_ERR(oproc->boot_data->syscon); in omap_rproc_get_boot_data()
1157 &oproc->boot_data->boot_reg)) { in omap_rproc_get_boot_data()
1158 dev_err(&pdev->dev, "couldn't get the boot register\n"); in omap_rproc_get_boot_data()
1159 return -EINVAL; in omap_rproc_get_boot_data()
1163 &oproc->boot_data->boot_reg_shift); in omap_rproc_get_boot_data()
1171 struct omap_rproc *oproc = rproc->priv; in omap_rproc_of_get_internal_memories()
1172 struct device *dev = &pdev->dev; in omap_rproc_of_get_internal_memories()
1180 return -ENODEV; in omap_rproc_of_get_internal_memories()
1182 if (!data->mems) in omap_rproc_of_get_internal_memories()
1185 num_mems = of_property_count_elems_of_size(dev->of_node, "reg", in omap_rproc_of_get_internal_memories()
1188 oproc->mem = devm_kcalloc(dev, num_mems, sizeof(*oproc->mem), in omap_rproc_of_get_internal_memories()
1190 if (!oproc->mem) in omap_rproc_of_get_internal_memories()
1191 return -ENOMEM; in omap_rproc_of_get_internal_memories()
1193 for (i = 0; data->mems[i].name; i++) { in omap_rproc_of_get_internal_memories()
1195 data->mems[i].name); in omap_rproc_of_get_internal_memories()
1198 data->mems[i].name); in omap_rproc_of_get_internal_memories()
1199 return -ENOMEM; in omap_rproc_of_get_internal_memories()
1201 oproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res); in omap_rproc_of_get_internal_memories()
1202 if (IS_ERR(oproc->mem[i].cpu_addr)) { in omap_rproc_of_get_internal_memories()
1204 data->mems[i].name); in omap_rproc_of_get_internal_memories()
1205 return PTR_ERR(oproc->mem[i].cpu_addr); in omap_rproc_of_get_internal_memories()
1207 oproc->mem[i].bus_addr = res->start; in omap_rproc_of_get_internal_memories()
1208 oproc->mem[i].dev_addr = data->mems[i].dev_addr; in omap_rproc_of_get_internal_memories()
1209 oproc->mem[i].size = resource_size(res); in omap_rproc_of_get_internal_memories()
1212 data->mems[i].name, &oproc->mem[i].bus_addr, in omap_rproc_of_get_internal_memories()
1213 oproc->mem[i].size, oproc->mem[i].cpu_addr, in omap_rproc_of_get_internal_memories()
1214 oproc->mem[i].dev_addr); in omap_rproc_of_get_internal_memories()
1216 oproc->num_mems = num_mems; in omap_rproc_of_get_internal_memories()
1224 struct device_node *np = dev->of_node; in omap_rproc_count_wdog_timers()
1227 ret = of_count_phandle_with_args(np, "ti,watchdog-timers", NULL); in omap_rproc_count_wdog_timers()
1246 struct device_node *np = pdev->dev.of_node; in omap_rproc_of_get_timers()
1247 struct omap_rproc *oproc = rproc->priv; in omap_rproc_of_get_timers()
1248 struct device *dev = &pdev->dev; in omap_rproc_of_get_timers()
1255 oproc->num_timers = of_count_phandle_with_args(np, "ti,timers", NULL); in omap_rproc_of_get_timers()
1256 if (oproc->num_timers <= 0) { in omap_rproc_of_get_timers()
1258 oproc->num_timers); in omap_rproc_of_get_timers()
1259 oproc->num_timers = 0; in omap_rproc_of_get_timers()
1262 oproc->num_wd_timers = omap_rproc_count_wdog_timers(dev); in omap_rproc_of_get_timers()
1264 num_timers = oproc->num_timers + oproc->num_wd_timers; in omap_rproc_of_get_timers()
1266 oproc->timers = devm_kcalloc(dev, num_timers, in omap_rproc_of_get_timers()
1267 sizeof(*oproc->timers), in omap_rproc_of_get_timers()
1269 if (!oproc->timers) in omap_rproc_of_get_timers()
1270 return -ENOMEM; in omap_rproc_of_get_timers()
1273 oproc->num_timers, oproc->num_wd_timers); in omap_rproc_of_get_timers()
1281 struct device_node *np = pdev->dev.of_node; in omap_rproc_probe()
1289 dev_err(&pdev->dev, "only DT-based devices are supported\n"); in omap_rproc_probe()
1290 return -ENODEV; in omap_rproc_probe()
1293 reset = devm_reset_control_array_get_exclusive(&pdev->dev); in omap_rproc_probe()
1301 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); in omap_rproc_probe()
1303 dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret); in omap_rproc_probe()
1307 rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops, in omap_rproc_probe()
1310 return -ENOMEM; in omap_rproc_probe()
1312 oproc = rproc->priv; in omap_rproc_probe()
1313 oproc->rproc = rproc; in omap_rproc_probe()
1314 oproc->reset = reset; in omap_rproc_probe()
1315 /* All existing OMAP IPU and DSP processors have an MMU */ in omap_rproc_probe()
1316 rproc->has_iommu = true; in omap_rproc_probe()
1330 init_completion(&oproc->pm_comp); in omap_rproc_probe()
1331 oproc->autosuspend_delay = DEFAULT_AUTOSUSPEND_DELAY; in omap_rproc_probe()
1333 of_property_read_u32(pdev->dev.of_node, "ti,autosuspend-delay-ms", in omap_rproc_probe()
1334 &oproc->autosuspend_delay); in omap_rproc_probe()
1336 pm_runtime_set_autosuspend_delay(&pdev->dev, oproc->autosuspend_delay); in omap_rproc_probe()
1338 oproc->fck = devm_clk_get(&pdev->dev, 0); in omap_rproc_probe()
1339 if (IS_ERR(oproc->fck)) { in omap_rproc_probe()
1340 ret = PTR_ERR(oproc->fck); in omap_rproc_probe()
1344 ret = of_reserved_mem_device_init(&pdev->dev); in omap_rproc_probe()
1346 dev_warn(&pdev->dev, "device does not have specific CMA pool.\n"); in omap_rproc_probe()
1347 dev_warn(&pdev->dev, "Typically this should be provided,\n"); in omap_rproc_probe()
1348 dev_warn(&pdev->dev, "only omit if you know what you are doing.\n"); in omap_rproc_probe()
1360 of_reserved_mem_device_release(&pdev->dev); in omap_rproc_probe()
1372 of_reserved_mem_device_release(&pdev->dev); in omap_rproc_remove()
1387 .name = "omap-rproc",