Lines Matching +full:imx8qxp +full:- +full:dsp

1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <dt-bindings/firmware/imx/rsrc.h>
5 #include <linux/arm-smccc.h>
42 /* DSP own area */
44 /* DSP instruction area */
54 /* DSP audio mix registers */
76 * enum - Predefined Mailbox Messages
96 * struct imx_dsp_rproc - DSP remote processor state
130 * struct imx_dsp_rproc_dcfg - DSP remote processor configuration
181 /* Reset function for DSP on i.MX8MP */
187 /* Put DSP into reset and stall */ in imx8mp_dsp_reset()
195 regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2, in imx8mp_dsp_reset()
199 /* Take the DSP out of reset and keep stalled for FW loading */ in imx8mp_dsp_reset()
208 /* Reset function for DSP on i.MX8ULP */
213 /* Put DSP into reset and stall */ in imx8ulp_dsp_reset()
214 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
216 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
220 /* Configure resources of DSP through TFA */ in imx8ulp_dsp_reset()
223 /* Take the DSP out of reset and keep stalled for FW loading */ in imx8ulp_dsp_reset()
224 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
226 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
288 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_ready()
291 if (!priv->rxdb_ch) in imx_dsp_rproc_ready()
295 if (priv->flags & REMOTE_IS_READY) in imx_dsp_rproc_ready()
300 return -ETIMEDOUT; in imx_dsp_rproc_ready()
306 * There is a handshake for start procedure: when DSP starts, it
309 * a message to DSP.
313 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_start()
314 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_start()
315 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_start()
316 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_start()
319 switch (dcfg->method) { in imx_dsp_rproc_start()
321 ret = regmap_update_bits(priv->regmap, in imx_dsp_rproc_start()
322 dcfg->src_reg, in imx_dsp_rproc_start()
323 dcfg->src_mask, in imx_dsp_rproc_start()
324 dcfg->src_start); in imx_dsp_rproc_start()
327 ret = imx_sc_pm_cpu_start(priv->ipc_handle, in imx_dsp_rproc_start()
330 rproc->bootaddr); in imx_dsp_rproc_start()
333 return -EOPNOTSUPP; in imx_dsp_rproc_start()
350 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_stop()
351 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_stop()
352 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_stop()
353 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_stop()
356 if (rproc->state == RPROC_CRASHED) { in imx_dsp_rproc_stop()
357 priv->flags &= ~REMOTE_IS_READY; in imx_dsp_rproc_stop()
361 switch (dcfg->method) { in imx_dsp_rproc_stop()
363 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, in imx_dsp_rproc_stop()
364 dcfg->src_stop); in imx_dsp_rproc_stop()
367 ret = imx_sc_pm_cpu_start(priv->ipc_handle, in imx_dsp_rproc_stop()
370 rproc->bootaddr); in imx_dsp_rproc_stop()
373 return -EOPNOTSUPP; in imx_dsp_rproc_stop()
379 priv->flags &= ~REMOTE_IS_READY; in imx_dsp_rproc_stop()
385 * imx_dsp_rproc_sys_to_da() - internal memory translation helper
391 * Convert system address (DDR address) to device address (DSP)
397 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_sys_to_da()
398 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_sys_to_da()
402 for (i = 0; i < dcfg->att_size; i++) { in imx_dsp_rproc_sys_to_da()
403 const struct imx_rproc_att *att = &dcfg->att[i]; in imx_dsp_rproc_sys_to_da()
405 if (sys >= att->sa && sys + len <= att->sa + att->size) { in imx_dsp_rproc_sys_to_da()
406 unsigned int offset = sys - att->sa; in imx_dsp_rproc_sys_to_da()
408 *da = att->da + offset; in imx_dsp_rproc_sys_to_da()
413 return -ENOENT; in imx_dsp_rproc_sys_to_da()
418 * This function is executed upon scheduling of the i.MX DSP remoteproc
438 struct rproc *rproc = priv->rproc; in imx_dsp_rproc_vq_work()
440 mutex_lock(&rproc->lock); in imx_dsp_rproc_vq_work()
442 if (rproc->state != RPROC_RUNNING) in imx_dsp_rproc_vq_work()
445 rproc_vq_interrupt(priv->rproc, 0); in imx_dsp_rproc_vq_work()
446 rproc_vq_interrupt(priv->rproc, 1); in imx_dsp_rproc_vq_work()
449 mutex_unlock(&rproc->lock); in imx_dsp_rproc_vq_work()
453 * imx_dsp_rproc_rx_tx_callback() - inbound mailbox message handler
463 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_dsp_rproc_rx_tx_callback()
464 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_rx_tx_callback()
465 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_rx_tx_callback()
472 complete(&priv->pm_comp); in imx_dsp_rproc_rx_tx_callback()
475 complete(&priv->pm_comp); in imx_dsp_rproc_rx_tx_callback()
478 schedule_work(&priv->rproc_work); in imx_dsp_rproc_rx_tx_callback()
484 * imx_dsp_rproc_rxdb_callback() - inbound mailbox message handler
493 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_dsp_rproc_rxdb_callback()
494 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_rxdb_callback()
497 priv->flags |= REMOTE_IS_READY; in imx_dsp_rproc_rxdb_callback()
501 * imx_dsp_rproc_mbox_alloc() - request mailbox channels
508 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_mbox_alloc()
512 if (!of_property_present(dev->of_node, "mbox-names")) in imx_dsp_rproc_mbox_alloc()
515 cl = &priv->cl; in imx_dsp_rproc_mbox_alloc()
516 cl->dev = dev; in imx_dsp_rproc_mbox_alloc()
517 cl->tx_block = true; in imx_dsp_rproc_mbox_alloc()
518 cl->tx_tout = 100; in imx_dsp_rproc_mbox_alloc()
519 cl->knows_txdone = false; in imx_dsp_rproc_mbox_alloc()
520 cl->rx_callback = imx_dsp_rproc_rx_tx_callback; in imx_dsp_rproc_mbox_alloc()
523 priv->tx_ch = mbox_request_channel_byname(cl, "tx"); in imx_dsp_rproc_mbox_alloc()
524 if (IS_ERR(priv->tx_ch)) { in imx_dsp_rproc_mbox_alloc()
525 ret = PTR_ERR(priv->tx_ch); in imx_dsp_rproc_mbox_alloc()
526 dev_dbg(cl->dev, "failed to request tx mailbox channel: %d\n", in imx_dsp_rproc_mbox_alloc()
532 priv->rx_ch = mbox_request_channel_byname(cl, "rx"); in imx_dsp_rproc_mbox_alloc()
533 if (IS_ERR(priv->rx_ch)) { in imx_dsp_rproc_mbox_alloc()
534 ret = PTR_ERR(priv->rx_ch); in imx_dsp_rproc_mbox_alloc()
535 dev_dbg(cl->dev, "failed to request rx mailbox channel: %d\n", in imx_dsp_rproc_mbox_alloc()
540 cl = &priv->cl_rxdb; in imx_dsp_rproc_mbox_alloc()
541 cl->dev = dev; in imx_dsp_rproc_mbox_alloc()
542 cl->rx_callback = imx_dsp_rproc_rxdb_callback; in imx_dsp_rproc_mbox_alloc()
548 priv->rxdb_ch = mbox_request_channel_byname(cl, "rxdb"); in imx_dsp_rproc_mbox_alloc()
549 if (IS_ERR(priv->rxdb_ch)) { in imx_dsp_rproc_mbox_alloc()
550 ret = PTR_ERR(priv->rxdb_ch); in imx_dsp_rproc_mbox_alloc()
551 dev_dbg(cl->dev, "failed to request mbox chan rxdb, ret %d\n", in imx_dsp_rproc_mbox_alloc()
559 mbox_free_channel(priv->rx_ch); in imx_dsp_rproc_mbox_alloc()
561 mbox_free_channel(priv->tx_ch); in imx_dsp_rproc_mbox_alloc()
579 mbox_free_channel(priv->tx_ch); in imx_dsp_rproc_free_mbox()
580 mbox_free_channel(priv->rx_ch); in imx_dsp_rproc_free_mbox()
581 mbox_free_channel(priv->rxdb_ch); in imx_dsp_rproc_free_mbox()
585 * imx_dsp_rproc_add_carveout() - request mailbox channels
589 * The carveouts can help to mapping the memory address for DSP.
593 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_add_carveout()
594 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_add_carveout()
595 struct rproc *rproc = priv->rproc; in imx_dsp_rproc_add_carveout()
596 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_add_carveout()
597 struct device_node *np = dev->of_node; in imx_dsp_rproc_add_carveout()
606 for (a = 0; a < dcfg->att_size; a++) { in imx_dsp_rproc_add_carveout()
607 const struct imx_rproc_att *att = &dcfg->att[a]; in imx_dsp_rproc_add_carveout()
609 if (!(att->flags & ATT_OWN)) in imx_dsp_rproc_add_carveout()
612 if (imx_dsp_rproc_sys_to_da(priv, att->sa, att->size, &da)) in imx_dsp_rproc_add_carveout()
613 return -EINVAL; in imx_dsp_rproc_add_carveout()
615 cpu_addr = devm_ioremap_wc(dev, att->sa, att->size); in imx_dsp_rproc_add_carveout()
617 dev_err(dev, "failed to map memory %p\n", &att->sa); in imx_dsp_rproc_add_carveout()
618 return -ENOMEM; in imx_dsp_rproc_add_carveout()
622 mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa, in imx_dsp_rproc_add_carveout()
623 att->size, da, NULL, NULL, "dsp_mem"); in imx_dsp_rproc_add_carveout()
626 rproc_coredump_add_segment(rproc, da, att->size); in imx_dsp_rproc_add_carveout()
628 return -ENOMEM; in imx_dsp_rproc_add_carveout()
633 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); in imx_dsp_rproc_add_carveout()
639 if (!strcmp(it.node->name, "vdev0buffer")) in imx_dsp_rproc_add_carveout()
645 dev_err(dev, "unable to acquire memory-region\n"); in imx_dsp_rproc_add_carveout()
646 return -EINVAL; in imx_dsp_rproc_add_carveout()
649 if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) { in imx_dsp_rproc_add_carveout()
651 return -EINVAL; in imx_dsp_rproc_add_carveout()
654 cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); in imx_dsp_rproc_add_carveout()
657 dev_err(dev, "failed to map memory %p\n", &rmem->base); in imx_dsp_rproc_add_carveout()
658 return -ENOMEM; in imx_dsp_rproc_add_carveout()
662 mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base, in imx_dsp_rproc_add_carveout()
663 rmem->size, da, NULL, NULL, it.node->name); in imx_dsp_rproc_add_carveout()
666 rproc_coredump_add_segment(rproc, da, rmem->size); in imx_dsp_rproc_add_carveout()
669 return -ENOMEM; in imx_dsp_rproc_add_carveout()
681 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_prepare()
682 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_prepare()
698 list_for_each_entry(carveout, &rproc->carveouts, node) { in imx_dsp_rproc_prepare()
699 if (carveout->va) in imx_dsp_rproc_prepare()
700 memset(carveout->va, 0, carveout->len); in imx_dsp_rproc_prepare()
709 pm_runtime_put_sync(rproc->dev.parent); in imx_dsp_rproc_unprepare()
717 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_kick()
718 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_kick()
722 if (!priv->tx_ch) { in imx_dsp_rproc_kick()
733 err = mbox_send_message(priv->tx_ch, (void *)&mmsg); in imx_dsp_rproc_kick()
739 * Custom memory copy implementation for i.MX DSP Cores
741 * The IRAM is part of the HiFi DSP.
742 * According to hw specs only 32-bits writes are allowed.
755 return -EINVAL; in imx_dsp_rproc_memcpy()
786 * Custom memset implementation for i.MX DSP Cores
788 * The IRAM is part of the HiFi DSP.
789 * According to hw specs only 32-bits writes are allowed.
801 return -EINVAL; in imx_dsp_rproc_memset()
809 while (q--) in imx_dsp_rproc_memset()
831 * imx_dsp_rproc_elf_load_segments() - load firmware segments to memory
842 struct device *dev = &rproc->dev; in imx_dsp_rproc_elf_load_segments()
846 const u8 *elf_data = fw->data; in imx_dsp_rproc_elf_load_segments()
872 ret = -EINVAL; in imx_dsp_rproc_elf_load_segments()
876 if (offset + filesz > fw->size) { in imx_dsp_rproc_elf_load_segments()
878 offset + filesz, fw->size); in imx_dsp_rproc_elf_load_segments()
879 ret = -EINVAL; in imx_dsp_rproc_elf_load_segments()
886 ret = -EOVERFLOW; in imx_dsp_rproc_elf_load_segments()
895 ret = -EINVAL; in imx_dsp_rproc_elf_load_segments()
911 ret = imx_dsp_rproc_memset(ptr + filesz, 0, memsz - filesz); in imx_dsp_rproc_elf_load_segments()
926 dev_warn(&rproc->dev, "no resource table found for this firmware\n"); in imx_dsp_rproc_parse_fw()
945 * imx_dsp_attach_pm_domains() - attach the power domains
953 struct device *dev = priv->rproc->dev.parent; in imx_dsp_attach_pm_domains()
957 if (dev->pm_domain) in imx_dsp_attach_pm_domains()
960 ret = dev_pm_domain_attach_list(dev, NULL, &priv->pd_list); in imx_dsp_attach_pm_domains()
965 * imx_dsp_rproc_detect_mode() - detect DSP control mode
968 * Different platform has different control method for DSP, which depends
969 * on how the DSP is integrated in platform.
971 * For i.MX8QXP and i.MX8QM, DSP should be started and stopped by System
973 * For i.MX8MP and i.MX8ULP, DSP should be started and stopped by system
978 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_detect_mode()
979 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_detect_mode()
983 switch (dsp_dcfg->dcfg->method) { in imx_dsp_rproc_detect_mode()
985 ret = imx_scu_get_handle(&priv->ipc_handle); in imx_dsp_rproc_detect_mode()
990 regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,dsp-ctrl"); in imx_dsp_rproc_detect_mode()
996 priv->regmap = regmap; in imx_dsp_rproc_detect_mode()
999 ret = -EOPNOTSUPP; in imx_dsp_rproc_detect_mode()
1007 /* DSP clocks */
1013 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_clk_get()
1014 struct clk_bulk_data *clks = priv->clks; in imx_dsp_rproc_clk_get()
1026 struct device *dev = &pdev->dev; in imx_dsp_rproc_probe()
1034 return -ENODEV; in imx_dsp_rproc_probe()
1038 dev_err(dev, "failed to parse firmware-name property, ret = %d\n", in imx_dsp_rproc_probe()
1043 rproc = devm_rproc_alloc(dev, "imx-dsp-rproc", &imx_dsp_rproc_ops, in imx_dsp_rproc_probe()
1046 return -ENOMEM; in imx_dsp_rproc_probe()
1048 priv = rproc->priv; in imx_dsp_rproc_probe()
1049 priv->rproc = rproc; in imx_dsp_rproc_probe()
1050 priv->dsp_dcfg = dsp_dcfg; in imx_dsp_rproc_probe()
1059 INIT_WORK(&priv->rproc_work, imx_dsp_rproc_vq_work); in imx_dsp_rproc_probe()
1067 /* There are multiple power domains required by DSP on some platform */ in imx_dsp_rproc_probe()
1080 init_completion(&priv->pm_comp); in imx_dsp_rproc_probe()
1081 rproc->auto_boot = false; in imx_dsp_rproc_probe()
1093 dev_pm_domain_detach_list(priv->pd_list); in imx_dsp_rproc_probe()
1101 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_remove()
1103 pm_runtime_disable(&pdev->dev); in imx_dsp_rproc_remove()
1105 dev_pm_domain_detach_list(priv->pd_list); in imx_dsp_rproc_remove()
1112 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_runtime_resume()
1113 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_runtime_resume()
1128 ret = clk_bulk_prepare_enable(DSP_RPROC_CLK_MAX, priv->clks); in imx_dsp_runtime_resume()
1134 /* Reset DSP if needed */ in imx_dsp_runtime_resume()
1135 if (dsp_dcfg->reset) in imx_dsp_runtime_resume()
1136 dsp_dcfg->reset(priv); in imx_dsp_runtime_resume()
1144 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_runtime_suspend()
1146 clk_bulk_disable_unprepare(DSP_RPROC_CLK_MAX, priv->clks); in imx_dsp_runtime_suspend()
1167 ret = rproc->ops->start(rproc); in imx_dsp_load_firmware()
1171 rproc->ops->kick(rproc, 0); in imx_dsp_load_firmware()
1180 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_suspend()
1184 if (rproc->state != RPROC_RUNNING) in imx_dsp_suspend()
1187 reinit_completion(&priv->pm_comp); in imx_dsp_suspend()
1189 /* Tell DSP that suspend is happening */ in imx_dsp_suspend()
1190 ret = mbox_send_message(priv->tx_ch, (void *)&mmsg); in imx_dsp_suspend()
1197 * DSP need to save the context at suspend. in imx_dsp_suspend()
1198 * Here waiting the response for DSP, then power can be disabled. in imx_dsp_suspend()
1200 if (!wait_for_completion_timeout(&priv->pm_comp, msecs_to_jiffies(100))) in imx_dsp_suspend()
1201 return -EBUSY; in imx_dsp_suspend()
1205 * The power of DSP is disabled in suspend, so force pm runtime in imx_dsp_suspend()
1221 if (rproc->state != RPROC_RUNNING) in imx_dsp_resume()
1225 * The power of DSP is disabled at suspend, the memory of dsp in imx_dsp_resume()
1227 * firmware and restart the DSP if it is in running state. in imx_dsp_resume()
1230 rproc->firmware, dev, GFP_KERNEL, in imx_dsp_resume()
1251 { .compatible = "fsl,imx8qxp-hifi4", .data = &imx_dsp_rproc_cfg_imx8qxp },
1252 { .compatible = "fsl,imx8qm-hifi4", .data = &imx_dsp_rproc_cfg_imx8qm },
1253 { .compatible = "fsl,imx8mp-hifi4", .data = &imx_dsp_rproc_cfg_imx8mp },
1254 { .compatible = "fsl,imx8ulp-hifi4", .data = &imx_dsp_rproc_cfg_imx8ulp },
1263 .name = "imx-dsp-rproc",