Lines Matching +full:imx8mp +full:- +full:reset
1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <dt-bindings/firmware/imx/rsrc.h>
5 #include <linux/arm-smccc.h>
69 * enum - Predefined Mailbox Messages
89 * struct imx_dsp_rproc - DSP remote processor state
127 * struct imx_dsp_rproc_dcfg - DSP remote processor configuration
129 * @reset: reset callback function
133 int (*reset)(struct imx_dsp_rproc *priv); member
175 /* Reset function for DSP on i.MX8MP */
181 /* Put DSP into reset and stall */ in imx8mp_dsp_reset()
186 /* Keep reset asserted for 10 cycles */ in imx8mp_dsp_reset()
189 regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2, in imx8mp_dsp_reset()
193 /* Take the DSP out of reset and keep stalled for FW loading */ in imx8mp_dsp_reset()
202 /* Reset function for DSP on i.MX8ULP */
207 /* Put DSP into reset and stall */ in imx8ulp_dsp_reset()
208 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
210 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
217 /* Take the DSP out of reset and keep stalled for FW loading */ in imx8ulp_dsp_reset()
218 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
220 regmap_update_bits(priv->regmap, IMX8ULP_SIM_LPAV_REG_SYSCTRL0, in imx8ulp_dsp_reset()
239 .reset = imx8mp_dsp_reset,
255 .reset = imx8ulp_dsp_reset,
282 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_ready()
285 if (!priv->rxdb_ch) in imx_dsp_rproc_ready()
289 if (priv->flags & REMOTE_IS_READY) in imx_dsp_rproc_ready()
294 return -ETIMEDOUT; in imx_dsp_rproc_ready()
307 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_start()
308 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_start()
309 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_start()
310 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_start()
313 switch (dcfg->method) { in imx_dsp_rproc_start()
315 ret = regmap_update_bits(priv->regmap, in imx_dsp_rproc_start()
316 dcfg->src_reg, in imx_dsp_rproc_start()
317 dcfg->src_mask, in imx_dsp_rproc_start()
318 dcfg->src_start); in imx_dsp_rproc_start()
321 ret = imx_sc_pm_cpu_start(priv->ipc_handle, in imx_dsp_rproc_start()
324 rproc->bootaddr); in imx_dsp_rproc_start()
327 return -EOPNOTSUPP; in imx_dsp_rproc_start()
344 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_stop()
345 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_stop()
346 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_stop()
347 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_stop()
351 flush_work(&priv->rproc_work); in imx_dsp_rproc_stop()
353 if (rproc->state == RPROC_CRASHED) { in imx_dsp_rproc_stop()
354 priv->flags &= ~REMOTE_IS_READY; in imx_dsp_rproc_stop()
358 switch (dcfg->method) { in imx_dsp_rproc_stop()
360 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, in imx_dsp_rproc_stop()
361 dcfg->src_stop); in imx_dsp_rproc_stop()
364 ret = imx_sc_pm_cpu_start(priv->ipc_handle, in imx_dsp_rproc_stop()
367 rproc->bootaddr); in imx_dsp_rproc_stop()
370 return -EOPNOTSUPP; in imx_dsp_rproc_stop()
376 priv->flags &= ~REMOTE_IS_READY; in imx_dsp_rproc_stop()
382 * imx_dsp_rproc_sys_to_da() - internal memory translation helper
394 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_sys_to_da()
395 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_sys_to_da()
399 for (i = 0; i < dcfg->att_size; i++) { in imx_dsp_rproc_sys_to_da()
400 const struct imx_rproc_att *att = &dcfg->att[i]; in imx_dsp_rproc_sys_to_da()
402 if (sys >= att->sa && sys + len <= att->sa + att->size) { in imx_dsp_rproc_sys_to_da()
403 unsigned int offset = sys - att->sa; in imx_dsp_rproc_sys_to_da()
405 *da = att->da + offset; in imx_dsp_rproc_sys_to_da()
410 return -ENOENT; in imx_dsp_rproc_sys_to_da()
436 rproc_vq_interrupt(priv->rproc, 0); in imx_dsp_rproc_vq_work()
437 rproc_vq_interrupt(priv->rproc, 1); in imx_dsp_rproc_vq_work()
441 * imx_dsp_rproc_rx_tx_callback() - inbound mailbox message handler
451 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_dsp_rproc_rx_tx_callback()
452 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_rx_tx_callback()
453 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_rx_tx_callback()
460 complete(&priv->pm_comp); in imx_dsp_rproc_rx_tx_callback()
463 complete(&priv->pm_comp); in imx_dsp_rproc_rx_tx_callback()
466 schedule_work(&priv->rproc_work); in imx_dsp_rproc_rx_tx_callback()
472 * imx_dsp_rproc_rxdb_callback() - inbound mailbox message handler
481 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_dsp_rproc_rxdb_callback()
482 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_rxdb_callback()
485 priv->flags |= REMOTE_IS_READY; in imx_dsp_rproc_rxdb_callback()
489 * imx_dsp_rproc_mbox_init() - request mailbox channels
496 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_mbox_init()
500 if (!of_get_property(dev->of_node, "mbox-names", NULL)) in imx_dsp_rproc_mbox_init()
503 cl = &priv->cl; in imx_dsp_rproc_mbox_init()
504 cl->dev = dev; in imx_dsp_rproc_mbox_init()
505 cl->tx_block = true; in imx_dsp_rproc_mbox_init()
506 cl->tx_tout = 100; in imx_dsp_rproc_mbox_init()
507 cl->knows_txdone = false; in imx_dsp_rproc_mbox_init()
508 cl->rx_callback = imx_dsp_rproc_rx_tx_callback; in imx_dsp_rproc_mbox_init()
511 priv->tx_ch = mbox_request_channel_byname(cl, "tx"); in imx_dsp_rproc_mbox_init()
512 if (IS_ERR(priv->tx_ch)) { in imx_dsp_rproc_mbox_init()
513 ret = PTR_ERR(priv->tx_ch); in imx_dsp_rproc_mbox_init()
514 dev_dbg(cl->dev, "failed to request tx mailbox channel: %d\n", in imx_dsp_rproc_mbox_init()
520 priv->rx_ch = mbox_request_channel_byname(cl, "rx"); in imx_dsp_rproc_mbox_init()
521 if (IS_ERR(priv->rx_ch)) { in imx_dsp_rproc_mbox_init()
522 ret = PTR_ERR(priv->rx_ch); in imx_dsp_rproc_mbox_init()
523 dev_dbg(cl->dev, "failed to request rx mailbox channel: %d\n", in imx_dsp_rproc_mbox_init()
528 cl = &priv->cl_rxdb; in imx_dsp_rproc_mbox_init()
529 cl->dev = dev; in imx_dsp_rproc_mbox_init()
530 cl->rx_callback = imx_dsp_rproc_rxdb_callback; in imx_dsp_rproc_mbox_init()
536 priv->rxdb_ch = mbox_request_channel_byname(cl, "rxdb"); in imx_dsp_rproc_mbox_init()
537 if (IS_ERR(priv->rxdb_ch)) { in imx_dsp_rproc_mbox_init()
538 ret = PTR_ERR(priv->rxdb_ch); in imx_dsp_rproc_mbox_init()
539 dev_dbg(cl->dev, "failed to request mbox chan rxdb, ret %d\n", in imx_dsp_rproc_mbox_init()
547 if (!IS_ERR(priv->tx_ch)) in imx_dsp_rproc_mbox_init()
548 mbox_free_channel(priv->tx_ch); in imx_dsp_rproc_mbox_init()
549 if (!IS_ERR(priv->rx_ch)) in imx_dsp_rproc_mbox_init()
550 mbox_free_channel(priv->rx_ch); in imx_dsp_rproc_mbox_init()
551 if (!IS_ERR(priv->rxdb_ch)) in imx_dsp_rproc_mbox_init()
552 mbox_free_channel(priv->rxdb_ch); in imx_dsp_rproc_mbox_init()
559 mbox_free_channel(priv->tx_ch); in imx_dsp_rproc_free_mbox()
560 mbox_free_channel(priv->rx_ch); in imx_dsp_rproc_free_mbox()
561 mbox_free_channel(priv->rxdb_ch); in imx_dsp_rproc_free_mbox()
565 * imx_dsp_rproc_add_carveout() - request mailbox channels
573 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_add_carveout()
574 const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; in imx_dsp_rproc_add_carveout()
575 struct rproc *rproc = priv->rproc; in imx_dsp_rproc_add_carveout()
576 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_add_carveout()
577 struct device_node *np = dev->of_node; in imx_dsp_rproc_add_carveout()
586 for (a = 0; a < dcfg->att_size; a++) { in imx_dsp_rproc_add_carveout()
587 const struct imx_rproc_att *att = &dcfg->att[a]; in imx_dsp_rproc_add_carveout()
589 if (!(att->flags & ATT_OWN)) in imx_dsp_rproc_add_carveout()
592 if (imx_dsp_rproc_sys_to_da(priv, att->sa, att->size, &da)) in imx_dsp_rproc_add_carveout()
593 return -EINVAL; in imx_dsp_rproc_add_carveout()
595 cpu_addr = devm_ioremap_wc(dev, att->sa, att->size); in imx_dsp_rproc_add_carveout()
597 dev_err(dev, "failed to map memory %p\n", &att->sa); in imx_dsp_rproc_add_carveout()
598 return -ENOMEM; in imx_dsp_rproc_add_carveout()
602 mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa, in imx_dsp_rproc_add_carveout()
603 att->size, da, NULL, NULL, "dsp_mem"); in imx_dsp_rproc_add_carveout()
606 rproc_coredump_add_segment(rproc, da, att->size); in imx_dsp_rproc_add_carveout()
608 return -ENOMEM; in imx_dsp_rproc_add_carveout()
613 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); in imx_dsp_rproc_add_carveout()
619 if (!strcmp(it.node->name, "vdev0buffer")) in imx_dsp_rproc_add_carveout()
624 dev_err(dev, "unable to acquire memory-region\n"); in imx_dsp_rproc_add_carveout()
625 return -EINVAL; in imx_dsp_rproc_add_carveout()
628 if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) in imx_dsp_rproc_add_carveout()
629 return -EINVAL; in imx_dsp_rproc_add_carveout()
631 cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); in imx_dsp_rproc_add_carveout()
633 dev_err(dev, "failed to map memory %p\n", &rmem->base); in imx_dsp_rproc_add_carveout()
634 return -ENOMEM; in imx_dsp_rproc_add_carveout()
638 mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base, in imx_dsp_rproc_add_carveout()
639 rmem->size, da, NULL, NULL, it.node->name); in imx_dsp_rproc_add_carveout()
642 rproc_coredump_add_segment(rproc, da, rmem->size); in imx_dsp_rproc_add_carveout()
644 return -ENOMEM; in imx_dsp_rproc_add_carveout()
655 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_prepare()
656 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_prepare()
672 list_for_each_entry(carveout, &rproc->carveouts, node) { in imx_dsp_rproc_prepare()
673 if (carveout->va) in imx_dsp_rproc_prepare()
674 memset(carveout->va, 0, carveout->len); in imx_dsp_rproc_prepare()
683 pm_runtime_put_sync(rproc->dev.parent); in imx_dsp_rproc_unprepare()
691 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_kick()
692 struct device *dev = rproc->dev.parent; in imx_dsp_rproc_kick()
696 if (!priv->tx_ch) { in imx_dsp_rproc_kick()
707 err = mbox_send_message(priv->tx_ch, (void *)&mmsg); in imx_dsp_rproc_kick()
715 dev_warn(&rproc->dev, "no resource table found for this firmware\n"); in imx_dsp_rproc_parse_fw()
733 * imx_dsp_attach_pm_domains() - attach the power domains
741 struct device *dev = priv->rproc->dev.parent; in imx_dsp_attach_pm_domains()
744 priv->num_domains = of_count_phandle_with_args(dev->of_node, in imx_dsp_attach_pm_domains()
745 "power-domains", in imx_dsp_attach_pm_domains()
746 "#power-domain-cells"); in imx_dsp_attach_pm_domains()
749 if (priv->num_domains <= 1) in imx_dsp_attach_pm_domains()
752 priv->pd_dev = devm_kmalloc_array(dev, priv->num_domains, in imx_dsp_attach_pm_domains()
753 sizeof(*priv->pd_dev), in imx_dsp_attach_pm_domains()
755 if (!priv->pd_dev) in imx_dsp_attach_pm_domains()
756 return -ENOMEM; in imx_dsp_attach_pm_domains()
758 priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_domains, in imx_dsp_attach_pm_domains()
759 sizeof(*priv->pd_dev_link), in imx_dsp_attach_pm_domains()
761 if (!priv->pd_dev_link) in imx_dsp_attach_pm_domains()
762 return -ENOMEM; in imx_dsp_attach_pm_domains()
764 for (i = 0; i < priv->num_domains; i++) { in imx_dsp_attach_pm_domains()
765 priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i); in imx_dsp_attach_pm_domains()
766 if (IS_ERR(priv->pd_dev[i])) { in imx_dsp_attach_pm_domains()
767 ret = PTR_ERR(priv->pd_dev[i]); in imx_dsp_attach_pm_domains()
772 * device_link_add will check priv->pd_dev[i], if it is in imx_dsp_attach_pm_domains()
775 priv->pd_dev_link[i] = device_link_add(dev, in imx_dsp_attach_pm_domains()
776 priv->pd_dev[i], in imx_dsp_attach_pm_domains()
779 if (!priv->pd_dev_link[i]) { in imx_dsp_attach_pm_domains()
780 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_dsp_attach_pm_domains()
781 ret = -EINVAL; in imx_dsp_attach_pm_domains()
789 while (--i >= 0) { in imx_dsp_attach_pm_domains()
790 device_link_del(priv->pd_dev_link[i]); in imx_dsp_attach_pm_domains()
791 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_dsp_attach_pm_domains()
801 if (priv->num_domains <= 1) in imx_dsp_detach_pm_domains()
804 for (i = 0; i < priv->num_domains; i++) { in imx_dsp_detach_pm_domains()
805 device_link_del(priv->pd_dev_link[i]); in imx_dsp_detach_pm_domains()
806 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_dsp_detach_pm_domains()
813 * imx_dsp_rproc_detect_mode() - detect DSP control mode
826 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_rproc_detect_mode()
827 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_detect_mode()
831 switch (dsp_dcfg->dcfg->method) { in imx_dsp_rproc_detect_mode()
833 ret = imx_scu_get_handle(&priv->ipc_handle); in imx_dsp_rproc_detect_mode()
838 regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,dsp-ctrl"); in imx_dsp_rproc_detect_mode()
844 priv->regmap = regmap; in imx_dsp_rproc_detect_mode()
847 ret = -EOPNOTSUPP; in imx_dsp_rproc_detect_mode()
861 struct device *dev = priv->rproc->dev.parent; in imx_dsp_rproc_clk_get()
862 struct clk_bulk_data *clks = priv->clks; in imx_dsp_rproc_clk_get()
874 struct device *dev = &pdev->dev; in imx_dsp_rproc_probe()
882 return -ENODEV; in imx_dsp_rproc_probe()
886 dev_err(dev, "failed to parse firmware-name property, ret = %d\n", in imx_dsp_rproc_probe()
891 rproc = rproc_alloc(dev, "imx-dsp-rproc", &imx_dsp_rproc_ops, fw_name, in imx_dsp_rproc_probe()
894 return -ENOMEM; in imx_dsp_rproc_probe()
896 priv = rproc->priv; in imx_dsp_rproc_probe()
897 priv->rproc = rproc; in imx_dsp_rproc_probe()
898 priv->dsp_dcfg = dsp_dcfg; in imx_dsp_rproc_probe()
902 INIT_WORK(&priv->rproc_work, imx_dsp_rproc_vq_work); in imx_dsp_rproc_probe()
923 init_completion(&priv->pm_comp); in imx_dsp_rproc_probe()
924 rproc->auto_boot = false; in imx_dsp_rproc_probe()
946 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_rproc_remove()
948 pm_runtime_disable(&pdev->dev); in imx_dsp_rproc_remove()
960 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_runtime_resume()
961 const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; in imx_dsp_runtime_resume()
976 ret = clk_bulk_prepare_enable(DSP_RPROC_CLK_MAX, priv->clks); in imx_dsp_runtime_resume()
982 /* Reset DSP if needed */ in imx_dsp_runtime_resume()
983 if (dsp_dcfg->reset) in imx_dsp_runtime_resume()
984 dsp_dcfg->reset(priv); in imx_dsp_runtime_resume()
992 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_runtime_suspend()
994 clk_bulk_disable_unprepare(DSP_RPROC_CLK_MAX, priv->clks); in imx_dsp_runtime_suspend()
1015 ret = rproc->ops->start(rproc); in imx_dsp_load_firmware()
1019 rproc->ops->kick(rproc, 0); in imx_dsp_load_firmware()
1028 struct imx_dsp_rproc *priv = rproc->priv; in imx_dsp_suspend()
1032 if (rproc->state != RPROC_RUNNING) in imx_dsp_suspend()
1035 reinit_completion(&priv->pm_comp); in imx_dsp_suspend()
1038 ret = mbox_send_message(priv->tx_ch, (void *)&mmsg); in imx_dsp_suspend()
1048 if (!wait_for_completion_timeout(&priv->pm_comp, msecs_to_jiffies(100))) in imx_dsp_suspend()
1049 return -EBUSY; in imx_dsp_suspend()
1069 if (rproc->state != RPROC_RUNNING) in imx_dsp_resume()
1074 * is reset, the image segments are lost. So need to reload in imx_dsp_resume()
1078 rproc->firmware, dev, GFP_KERNEL, in imx_dsp_resume()
1100 { .compatible = "fsl,imx8qxp-hifi4", .data = &imx_dsp_rproc_cfg_imx8qxp },
1101 { .compatible = "fsl,imx8qm-hifi4", .data = &imx_dsp_rproc_cfg_imx8qm },
1102 { .compatible = "fsl,imx8mp-hifi4", .data = &imx_dsp_rproc_cfg_imx8mp },
1103 { .compatible = "fsl,imx8ulp-hifi4", .data = &imx_dsp_rproc_cfg_imx8ulp },
1112 .name = "imx-dsp-rproc",