Lines Matching +full:imx8mm +full:- +full:cm4

1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <dt-bindings/firmware/imx/rsrc.h>
7 #include <linux/arm-smccc.h>
74 * struct imx_rproc_mem - slim internal memory structure
124 /* TCM CODE NON-SECURE */
132 /* TCM SYS NON-SECURE*/
185 /* QSPI Code - alias */
187 /* DDR (Code) - alias */
191 /* OCRAM_S - alias */
205 /* TCML - alias */
213 /* QSPI Code - alias */
215 /* DDR (Code) - alias */
247 /* OCRAM_S (M4 Boot code) - alias */
251 /* OCRAM (Code) - alias */
253 /* OCRAM_EPDC (Code) - alias */
255 /* OCRAM_PXP (Code) - alias */
259 /* DDR (Code) - alias, first part of DDR (Data) */
276 /* TCML (M4 Boot Code) - alias */
280 /* OCRAM_S (Code) - alias */
284 /* DDR (Code) - alias, first part of DDR (Data) */
289 /* OCRAM_S (Data) - alias? */
375 struct imx_rproc *priv = rproc->priv; in imx_rproc_start()
376 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_start()
377 struct device *dev = priv->dev; in imx_rproc_start()
385 switch (dcfg->method) { in imx_rproc_start()
387 if (priv->gpr) { in imx_rproc_start()
388 ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg, in imx_rproc_start()
389 dcfg->gpr_wait); in imx_rproc_start()
391 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, in imx_rproc_start()
392 dcfg->src_mask, in imx_rproc_start()
393 dcfg->src_start); in imx_rproc_start()
401 ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry); in imx_rproc_start()
404 return -EOPNOTSUPP; in imx_rproc_start()
415 struct imx_rproc *priv = rproc->priv; in imx_rproc_stop()
416 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_stop()
417 struct device *dev = priv->dev; in imx_rproc_stop()
421 switch (dcfg->method) { in imx_rproc_stop()
423 if (priv->gpr) { in imx_rproc_stop()
424 ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg, in imx_rproc_stop()
425 dcfg->gpr_wait); in imx_rproc_stop()
427 dev_err(priv->dev, in imx_rproc_stop()
433 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, in imx_rproc_stop()
434 dcfg->src_stop); in imx_rproc_stop()
443 ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry); in imx_rproc_stop()
446 return -EOPNOTSUPP; in imx_rproc_stop()
460 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_da_to_sys()
464 for (i = 0; i < dcfg->att_size; i++) { in imx_rproc_da_to_sys()
465 const struct imx_rproc_att *att = &dcfg->att[i]; in imx_rproc_da_to_sys()
473 if (att->flags & ATT_CORE_MASK) { in imx_rproc_da_to_sys()
474 if (!((BIT(priv->core_index)) & (att->flags & ATT_CORE_MASK))) in imx_rproc_da_to_sys()
478 if (da >= att->da && da + len < att->da + att->size) { in imx_rproc_da_to_sys()
479 unsigned int offset = da - att->da; in imx_rproc_da_to_sys()
481 *sys = att->sa + offset; in imx_rproc_da_to_sys()
483 *is_iomem = att->flags & ATT_IOMEM; in imx_rproc_da_to_sys()
488 dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%zx\n", in imx_rproc_da_to_sys()
490 return -ENOENT; in imx_rproc_da_to_sys()
495 struct imx_rproc *priv = rproc->priv; in imx_rproc_da_to_va()
511 if (sys >= priv->mem[i].sys_addr && sys + len < in imx_rproc_da_to_va()
512 priv->mem[i].sys_addr + priv->mem[i].size) { in imx_rproc_da_to_va()
513 unsigned int offset = sys - priv->mem[i].sys_addr; in imx_rproc_da_to_va()
515 va = (__force void *)(priv->mem[i].cpu_addr + offset); in imx_rproc_da_to_va()
520 dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%zx va = 0x%p\n", in imx_rproc_da_to_va()
529 struct device *dev = rproc->dev.parent; in imx_rproc_mem_alloc()
532 dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len); in imx_rproc_mem_alloc()
533 va = ioremap_wc(mem->dma, mem->len); in imx_rproc_mem_alloc()
536 &mem->dma, mem->len); in imx_rproc_mem_alloc()
537 return -ENOMEM; in imx_rproc_mem_alloc()
541 mem->va = va; in imx_rproc_mem_alloc()
549 dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); in imx_rproc_mem_release()
550 iounmap(mem->va); in imx_rproc_mem_release()
557 struct imx_rproc *priv = rproc->priv; in imx_rproc_prepare()
558 struct device_node *np = priv->dev->of_node; in imx_rproc_prepare()
565 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); in imx_rproc_prepare()
571 if (!strcmp(it.node->name, "vdev0buffer")) in imx_rproc_prepare()
574 if (!strcmp(it.node->name, "rsc-table")) in imx_rproc_prepare()
580 dev_err(priv->dev, "unable to acquire memory-region\n"); in imx_rproc_prepare()
581 return -EINVAL; in imx_rproc_prepare()
585 da = rmem->base; in imx_rproc_prepare()
588 mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da, in imx_rproc_prepare()
590 it.node->name); in imx_rproc_prepare()
593 rproc_coredump_add_segment(rproc, da, rmem->size); in imx_rproc_prepare()
596 return -ENOMEM; in imx_rproc_prepare()
611 dev_info(&rproc->dev, "No resource table in elf\n"); in imx_rproc_parse_fw()
618 struct imx_rproc *priv = rproc->priv; in imx_rproc_kick()
622 if (!priv->tx_ch) { in imx_rproc_kick()
623 dev_err(priv->dev, "No initialized mbox tx channel\n"); in imx_rproc_kick()
633 err = mbox_send_message(priv->tx_ch, (void *)&mmsg); in imx_rproc_kick()
635 dev_err(priv->dev, "%s: failed (%d, err:%d)\n", in imx_rproc_kick()
646 struct imx_rproc *priv = rproc->priv; in imx_rproc_detach()
647 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_detach()
649 if (dcfg->method != IMX_RPROC_SCU_API) in imx_rproc_detach()
650 return -EOPNOTSUPP; in imx_rproc_detach()
652 if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) in imx_rproc_detach()
653 return -EOPNOTSUPP; in imx_rproc_detach()
662 struct imx_rproc *priv = rproc->priv; in imx_rproc_get_loaded_rsc_table()
665 if (!priv->rsc_table) in imx_rproc_get_loaded_rsc_table()
669 return (struct resource_table *)priv->rsc_table; in imx_rproc_get_loaded_rsc_table()
675 struct imx_rproc *priv = rproc->priv; in imx_rproc_elf_find_loaded_rsc_table()
677 if (priv->rsc_table) in imx_rproc_elf_find_loaded_rsc_table()
678 return (struct resource_table *)priv->rsc_table; in imx_rproc_elf_find_loaded_rsc_table()
702 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_addr_init()
703 struct device *dev = &pdev->dev; in imx_rproc_addr_init()
704 struct device_node *np = dev->of_node; in imx_rproc_addr_init()
708 for (a = 0; a < dcfg->att_size; a++) { in imx_rproc_addr_init()
709 const struct imx_rproc_att *att = &dcfg->att[a]; in imx_rproc_addr_init()
711 if (!(att->flags & ATT_OWN)) in imx_rproc_addr_init()
717 if (att->flags & ATT_IOMEM) in imx_rproc_addr_init()
718 priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, in imx_rproc_addr_init()
719 att->sa, att->size); in imx_rproc_addr_init()
721 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, in imx_rproc_addr_init()
722 att->sa, att->size); in imx_rproc_addr_init()
723 if (!priv->mem[b].cpu_addr) { in imx_rproc_addr_init()
724 dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa); in imx_rproc_addr_init()
725 return -ENOMEM; in imx_rproc_addr_init()
727 priv->mem[b].sys_addr = att->sa; in imx_rproc_addr_init()
728 priv->mem[b].size = att->size; in imx_rproc_addr_init()
732 /* memory-region is optional property */ in imx_rproc_addr_init()
733 nph = of_count_phandle_with_args(np, "memory-region", NULL); in imx_rproc_addr_init()
742 node = of_parse_phandle(np, "memory-region", a); in imx_rproc_addr_init()
746 if (!strncmp(node->name, "vdev", strlen("vdev"))) { in imx_rproc_addr_init()
763 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res)); in imx_rproc_addr_init()
764 if (!priv->mem[b].cpu_addr) { in imx_rproc_addr_init()
767 return -ENOMEM; in imx_rproc_addr_init()
769 priv->mem[b].sys_addr = res.start; in imx_rproc_addr_init()
770 priv->mem[b].size = resource_size(&res); in imx_rproc_addr_init()
771 if (!strcmp(node->name, "rsc-table")) in imx_rproc_addr_init()
772 priv->rsc_table = priv->mem[b].cpu_addr; in imx_rproc_addr_init()
793 struct rproc *rproc = priv->rproc; in imx_rproc_vq_work()
795 idr_for_each(&rproc->notifyids, imx_rproc_notified_idr_cb, rproc); in imx_rproc_vq_work()
800 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_rproc_rx_callback()
801 struct imx_rproc *priv = rproc->priv; in imx_rproc_rx_callback()
803 queue_work(priv->workqueue, &priv->rproc_work); in imx_rproc_rx_callback()
808 struct imx_rproc *priv = rproc->priv; in imx_rproc_xtr_mbox_init()
809 struct device *dev = priv->dev; in imx_rproc_xtr_mbox_init()
821 if (priv->tx_ch && priv->rx_ch) in imx_rproc_xtr_mbox_init()
824 if (!of_get_property(dev->of_node, "mbox-names", NULL)) in imx_rproc_xtr_mbox_init()
827 cl = &priv->cl; in imx_rproc_xtr_mbox_init()
828 cl->dev = dev; in imx_rproc_xtr_mbox_init()
829 cl->tx_block = true; in imx_rproc_xtr_mbox_init()
830 cl->tx_tout = 100; in imx_rproc_xtr_mbox_init()
831 cl->knows_txdone = false; in imx_rproc_xtr_mbox_init()
832 cl->rx_callback = imx_rproc_rx_callback; in imx_rproc_xtr_mbox_init()
834 priv->tx_ch = mbox_request_channel_byname(cl, "tx"); in imx_rproc_xtr_mbox_init()
835 if (IS_ERR(priv->tx_ch)) in imx_rproc_xtr_mbox_init()
836 return dev_err_probe(cl->dev, PTR_ERR(priv->tx_ch), in imx_rproc_xtr_mbox_init()
839 priv->rx_ch = mbox_request_channel_byname(cl, "rx"); in imx_rproc_xtr_mbox_init()
840 if (IS_ERR(priv->rx_ch)) { in imx_rproc_xtr_mbox_init()
841 mbox_free_channel(priv->tx_ch); in imx_rproc_xtr_mbox_init()
842 return dev_err_probe(cl->dev, PTR_ERR(priv->rx_ch), in imx_rproc_xtr_mbox_init()
851 struct imx_rproc *priv = rproc->priv; in imx_rproc_free_mbox()
853 if (priv->tx_ch) { in imx_rproc_free_mbox()
854 mbox_free_channel(priv->tx_ch); in imx_rproc_free_mbox()
855 priv->tx_ch = NULL; in imx_rproc_free_mbox()
858 if (priv->rx_ch) { in imx_rproc_free_mbox()
859 mbox_free_channel(priv->rx_ch); in imx_rproc_free_mbox()
860 priv->rx_ch = NULL; in imx_rproc_free_mbox()
866 struct imx_rproc *priv = rproc->priv; in imx_rproc_put_scu()
867 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_put_scu()
869 if (dcfg->method != IMX_RPROC_SCU_API) in imx_rproc_put_scu()
872 if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { in imx_rproc_put_scu()
877 imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), false); in imx_rproc_put_scu()
878 imx_scu_irq_unregister_notifier(&priv->rproc_nb); in imx_rproc_put_scu()
887 if (!((event & BIT(priv->rproc_pt)) && (*(u8 *)group == IMX_SC_IRQ_GROUP_REBOOTED))) in imx_rproc_partition_notify()
890 rproc_report_crash(priv->rproc, RPROC_WATCHDOG); in imx_rproc_partition_notify()
892 pr_info("Partition%d reset!\n", priv->rproc_pt); in imx_rproc_partition_notify()
899 struct device *dev = priv->dev; in imx_rproc_attach_pd()
903 * If there is only one power-domain entry, the platform driver framework in imx_rproc_attach_pd()
906 priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains", in imx_rproc_attach_pd()
907 "#power-domain-cells"); in imx_rproc_attach_pd()
908 if (priv->num_pd <= 1) in imx_rproc_attach_pd()
911 priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev), GFP_KERNEL); in imx_rproc_attach_pd()
912 if (!priv->pd_dev) in imx_rproc_attach_pd()
913 return -ENOMEM; in imx_rproc_attach_pd()
915 priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev_link), in imx_rproc_attach_pd()
918 if (!priv->pd_dev_link) in imx_rproc_attach_pd()
919 return -ENOMEM; in imx_rproc_attach_pd()
921 for (i = 0; i < priv->num_pd; i++) { in imx_rproc_attach_pd()
922 priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i); in imx_rproc_attach_pd()
923 if (IS_ERR(priv->pd_dev[i])) { in imx_rproc_attach_pd()
924 ret = PTR_ERR(priv->pd_dev[i]); in imx_rproc_attach_pd()
928 priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], DL_FLAG_STATELESS | in imx_rproc_attach_pd()
930 if (!priv->pd_dev_link[i]) { in imx_rproc_attach_pd()
931 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_attach_pd()
932 ret = -EINVAL; in imx_rproc_attach_pd()
940 while (--i >= 0) { in imx_rproc_attach_pd()
941 device_link_del(priv->pd_dev_link[i]); in imx_rproc_attach_pd()
942 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_attach_pd()
950 struct imx_rproc *priv = rproc->priv; in imx_rproc_detach_pd()
954 * If there is only one power-domain entry, the platform driver framework in imx_rproc_detach_pd()
957 if (priv->num_pd <= 1) in imx_rproc_detach_pd()
960 for (i = 0; i < priv->num_pd; i++) { in imx_rproc_detach_pd()
961 device_link_del(priv->pd_dev_link[i]); in imx_rproc_detach_pd()
962 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_detach_pd()
970 struct regmap_config config = { .name = "imx-rproc" }; in imx_rproc_detect_mode()
971 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_detect_mode()
972 struct device *dev = priv->dev; in imx_rproc_detect_mode()
979 switch (dcfg->method) { in imx_rproc_detect_mode()
981 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
986 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
989 ret = imx_scu_get_handle(&priv->ipc_handle); in imx_rproc_detect_mode()
992 ret = of_property_read_u32(dev->of_node, "fsl,resource-id", &priv->rsrc_id); in imx_rproc_detect_mode()
994 dev_err(dev, "No fsl,resource-id property\n"); in imx_rproc_detect_mode()
998 if (priv->rsrc_id == IMX_SC_R_M4_1_PID0) in imx_rproc_detect_mode()
999 priv->core_index = 1; in imx_rproc_detect_mode()
1001 priv->core_index = 0; in imx_rproc_detect_mode()
1007 if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { in imx_rproc_detect_mode()
1008 if (of_property_read_u32(dev->of_node, "fsl,entry-address", &priv->entry)) in imx_rproc_detect_mode()
1009 return -EINVAL; in imx_rproc_detect_mode()
1014 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
1015 priv->rproc->recovery_disabled = false; in imx_rproc_detect_mode()
1016 rproc_set_feature(priv->rproc, RPROC_FEAT_ATTACH_ON_RECOVERY); in imx_rproc_detect_mode()
1019 ret = imx_sc_rm_get_resource_owner(priv->ipc_handle, priv->rsrc_id, &pt); in imx_rproc_detect_mode()
1025 priv->rproc_pt = pt; in imx_rproc_detect_mode()
1026 priv->rproc_nb.notifier_call = imx_rproc_partition_notify; in imx_rproc_detect_mode()
1028 ret = imx_scu_irq_register_notifier(&priv->rproc_nb); in imx_rproc_detect_mode()
1034 ret = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), in imx_rproc_detect_mode()
1037 imx_scu_irq_unregister_notifier(&priv->rproc_nb); in imx_rproc_detect_mode()
1047 priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr"); in imx_rproc_detect_mode()
1048 if (IS_ERR(priv->gpr)) in imx_rproc_detect_mode()
1049 priv->gpr = NULL; in imx_rproc_detect_mode()
1051 regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); in imx_rproc_detect_mode()
1057 priv->regmap = regmap; in imx_rproc_detect_mode()
1060 if (priv->gpr) { in imx_rproc_detect_mode()
1061 ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val); in imx_rproc_detect_mode()
1062 if (val & dcfg->gpr_wait) { in imx_rproc_detect_mode()
1068 imx_rproc_stop(priv->rproc); in imx_rproc_detect_mode()
1073 ret = regmap_read(regmap, dcfg->src_reg, &val); in imx_rproc_detect_mode()
1079 if ((val & dcfg->src_mask) != dcfg->src_stop) in imx_rproc_detect_mode()
1080 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
1087 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_clk_enable()
1088 struct device *dev = priv->dev; in imx_rproc_clk_enable()
1092 if (dcfg->method == IMX_RPROC_NONE) in imx_rproc_clk_enable()
1095 priv->clk = devm_clk_get(dev, NULL); in imx_rproc_clk_enable()
1096 if (IS_ERR(priv->clk)) { in imx_rproc_clk_enable()
1098 return PTR_ERR(priv->clk); in imx_rproc_clk_enable()
1105 ret = clk_prepare_enable(priv->clk); in imx_rproc_clk_enable()
1116 struct device *dev = &pdev->dev; in imx_rproc_probe()
1117 struct device_node *np = dev->of_node; in imx_rproc_probe()
1124 rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops, in imx_rproc_probe()
1127 return -ENOMEM; in imx_rproc_probe()
1131 ret = -EINVAL; in imx_rproc_probe()
1135 priv = rproc->priv; in imx_rproc_probe()
1136 priv->rproc = rproc; in imx_rproc_probe()
1137 priv->dcfg = dcfg; in imx_rproc_probe()
1138 priv->dev = dev; in imx_rproc_probe()
1141 priv->workqueue = create_workqueue(dev_name(dev)); in imx_rproc_probe()
1142 if (!priv->workqueue) { in imx_rproc_probe()
1144 ret = -ENOMEM; in imx_rproc_probe()
1148 INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); in imx_rproc_probe()
1168 if (rproc->state != RPROC_DETACHED) in imx_rproc_probe()
1169 rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); in imx_rproc_probe()
1180 clk_disable_unprepare(priv->clk); in imx_rproc_probe()
1186 destroy_workqueue(priv->workqueue); in imx_rproc_probe()
1196 struct imx_rproc *priv = rproc->priv; in imx_rproc_remove()
1198 clk_disable_unprepare(priv->clk); in imx_rproc_remove()
1202 destroy_workqueue(priv->workqueue); in imx_rproc_remove()
1207 { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp },
1208 { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d },
1209 { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx },
1210 { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq },
1211 { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
1212 { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
1213 { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
1214 { .compatible = "fsl,imx8mn-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
1215 { .compatible = "fsl,imx8mp-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
1216 { .compatible = "fsl,imx8qxp-cm4", .data = &imx_rproc_cfg_imx8qxp },
1217 { .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
1218 { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
1219 { .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
1228 .name = "imx-rproc",