Lines Matching +full:imx93 +full:- +full:iomuxc
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()
691 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_addr_init()
692 struct device *dev = &pdev->dev; in imx_rproc_addr_init()
693 struct device_node *np = dev->of_node; in imx_rproc_addr_init()
697 for (a = 0; a < dcfg->att_size; a++) { in imx_rproc_addr_init()
698 const struct imx_rproc_att *att = &dcfg->att[a]; in imx_rproc_addr_init()
700 if (!(att->flags & ATT_OWN)) in imx_rproc_addr_init()
706 if (att->flags & ATT_IOMEM) in imx_rproc_addr_init()
707 priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, in imx_rproc_addr_init()
708 att->sa, att->size); in imx_rproc_addr_init()
710 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, in imx_rproc_addr_init()
711 att->sa, att->size); in imx_rproc_addr_init()
712 if (!priv->mem[b].cpu_addr) { in imx_rproc_addr_init()
713 dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa); in imx_rproc_addr_init()
714 return -ENOMEM; in imx_rproc_addr_init()
716 priv->mem[b].sys_addr = att->sa; in imx_rproc_addr_init()
717 priv->mem[b].size = att->size; in imx_rproc_addr_init()
721 /* memory-region is optional property */ in imx_rproc_addr_init()
722 nph = of_count_phandle_with_args(np, "memory-region", NULL); in imx_rproc_addr_init()
731 node = of_parse_phandle(np, "memory-region", a); in imx_rproc_addr_init()
733 if (!strncmp(node->name, "vdev", strlen("vdev"))) { in imx_rproc_addr_init()
748 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res)); in imx_rproc_addr_init()
749 if (!priv->mem[b].cpu_addr) { in imx_rproc_addr_init()
751 return -ENOMEM; in imx_rproc_addr_init()
753 priv->mem[b].sys_addr = res.start; in imx_rproc_addr_init()
754 priv->mem[b].size = resource_size(&res); in imx_rproc_addr_init()
755 if (!strcmp(node->name, "rsc-table")) in imx_rproc_addr_init()
756 priv->rsc_table = priv->mem[b].cpu_addr; in imx_rproc_addr_init()
776 struct rproc *rproc = priv->rproc; in imx_rproc_vq_work()
778 idr_for_each(&rproc->notifyids, imx_rproc_notified_idr_cb, rproc); in imx_rproc_vq_work()
783 struct rproc *rproc = dev_get_drvdata(cl->dev); in imx_rproc_rx_callback()
784 struct imx_rproc *priv = rproc->priv; in imx_rproc_rx_callback()
786 queue_work(priv->workqueue, &priv->rproc_work); in imx_rproc_rx_callback()
791 struct imx_rproc *priv = rproc->priv; in imx_rproc_xtr_mbox_init()
792 struct device *dev = priv->dev; in imx_rproc_xtr_mbox_init()
804 if (priv->tx_ch && priv->rx_ch) in imx_rproc_xtr_mbox_init()
807 if (!of_get_property(dev->of_node, "mbox-names", NULL)) in imx_rproc_xtr_mbox_init()
810 cl = &priv->cl; in imx_rproc_xtr_mbox_init()
811 cl->dev = dev; in imx_rproc_xtr_mbox_init()
812 cl->tx_block = true; in imx_rproc_xtr_mbox_init()
813 cl->tx_tout = 100; in imx_rproc_xtr_mbox_init()
814 cl->knows_txdone = false; in imx_rproc_xtr_mbox_init()
815 cl->rx_callback = imx_rproc_rx_callback; in imx_rproc_xtr_mbox_init()
817 priv->tx_ch = mbox_request_channel_byname(cl, "tx"); in imx_rproc_xtr_mbox_init()
818 if (IS_ERR(priv->tx_ch)) in imx_rproc_xtr_mbox_init()
819 return dev_err_probe(cl->dev, PTR_ERR(priv->tx_ch), in imx_rproc_xtr_mbox_init()
822 priv->rx_ch = mbox_request_channel_byname(cl, "rx"); in imx_rproc_xtr_mbox_init()
823 if (IS_ERR(priv->rx_ch)) { in imx_rproc_xtr_mbox_init()
824 mbox_free_channel(priv->tx_ch); in imx_rproc_xtr_mbox_init()
825 return dev_err_probe(cl->dev, PTR_ERR(priv->rx_ch), in imx_rproc_xtr_mbox_init()
834 struct imx_rproc *priv = rproc->priv; in imx_rproc_free_mbox()
836 if (priv->tx_ch) { in imx_rproc_free_mbox()
837 mbox_free_channel(priv->tx_ch); in imx_rproc_free_mbox()
838 priv->tx_ch = NULL; in imx_rproc_free_mbox()
841 if (priv->rx_ch) { in imx_rproc_free_mbox()
842 mbox_free_channel(priv->rx_ch); in imx_rproc_free_mbox()
843 priv->rx_ch = NULL; in imx_rproc_free_mbox()
849 struct imx_rproc *priv = rproc->priv; in imx_rproc_put_scu()
850 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_put_scu()
852 if (dcfg->method != IMX_RPROC_SCU_API) in imx_rproc_put_scu()
855 if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { in imx_rproc_put_scu()
860 imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), false); in imx_rproc_put_scu()
861 imx_scu_irq_unregister_notifier(&priv->rproc_nb); in imx_rproc_put_scu()
870 if (!((event & BIT(priv->rproc_pt)) && (*(u8 *)group == IMX_SC_IRQ_GROUP_REBOOTED))) in imx_rproc_partition_notify()
873 rproc_report_crash(priv->rproc, RPROC_WATCHDOG); in imx_rproc_partition_notify()
875 pr_info("Partition%d reset!\n", priv->rproc_pt); in imx_rproc_partition_notify()
882 struct device *dev = priv->dev; in imx_rproc_attach_pd()
886 * If there is only one power-domain entry, the platform driver framework in imx_rproc_attach_pd()
889 priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains", in imx_rproc_attach_pd()
890 "#power-domain-cells"); in imx_rproc_attach_pd()
891 if (priv->num_pd <= 1) in imx_rproc_attach_pd()
894 priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev), GFP_KERNEL); in imx_rproc_attach_pd()
895 if (!priv->pd_dev) in imx_rproc_attach_pd()
896 return -ENOMEM; in imx_rproc_attach_pd()
898 priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev_link), in imx_rproc_attach_pd()
901 if (!priv->pd_dev_link) in imx_rproc_attach_pd()
902 return -ENOMEM; in imx_rproc_attach_pd()
904 for (i = 0; i < priv->num_pd; i++) { in imx_rproc_attach_pd()
905 priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i); in imx_rproc_attach_pd()
906 if (IS_ERR(priv->pd_dev[i])) { in imx_rproc_attach_pd()
907 ret = PTR_ERR(priv->pd_dev[i]); in imx_rproc_attach_pd()
911 priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], DL_FLAG_STATELESS | in imx_rproc_attach_pd()
913 if (!priv->pd_dev_link[i]) { in imx_rproc_attach_pd()
914 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_attach_pd()
915 ret = -EINVAL; in imx_rproc_attach_pd()
923 while (--i >= 0) { in imx_rproc_attach_pd()
924 device_link_del(priv->pd_dev_link[i]); in imx_rproc_attach_pd()
925 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_attach_pd()
933 struct imx_rproc *priv = rproc->priv; in imx_rproc_detach_pd()
937 * If there is only one power-domain entry, the platform driver framework in imx_rproc_detach_pd()
940 if (priv->num_pd <= 1) in imx_rproc_detach_pd()
943 for (i = 0; i < priv->num_pd; i++) { in imx_rproc_detach_pd()
944 device_link_del(priv->pd_dev_link[i]); in imx_rproc_detach_pd()
945 dev_pm_domain_detach(priv->pd_dev[i], false); in imx_rproc_detach_pd()
953 struct regmap_config config = { .name = "imx-rproc" }; in imx_rproc_detect_mode()
954 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_detect_mode()
955 struct device *dev = priv->dev; in imx_rproc_detect_mode()
962 switch (dcfg->method) { in imx_rproc_detect_mode()
964 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
969 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
972 ret = imx_scu_get_handle(&priv->ipc_handle); in imx_rproc_detect_mode()
975 ret = of_property_read_u32(dev->of_node, "fsl,resource-id", &priv->rsrc_id); in imx_rproc_detect_mode()
977 dev_err(dev, "No fsl,resource-id property\n"); in imx_rproc_detect_mode()
981 if (priv->rsrc_id == IMX_SC_R_M4_1_PID0) in imx_rproc_detect_mode()
982 priv->core_index = 1; in imx_rproc_detect_mode()
984 priv->core_index = 0; in imx_rproc_detect_mode()
990 if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { in imx_rproc_detect_mode()
991 if (of_property_read_u32(dev->of_node, "fsl,entry-address", &priv->entry)) in imx_rproc_detect_mode()
992 return -EINVAL; in imx_rproc_detect_mode()
997 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
998 priv->rproc->recovery_disabled = false; in imx_rproc_detect_mode()
999 rproc_set_feature(priv->rproc, RPROC_FEAT_ATTACH_ON_RECOVERY); in imx_rproc_detect_mode()
1002 ret = imx_sc_rm_get_resource_owner(priv->ipc_handle, priv->rsrc_id, &pt); in imx_rproc_detect_mode()
1008 priv->rproc_pt = pt; in imx_rproc_detect_mode()
1009 priv->rproc_nb.notifier_call = imx_rproc_partition_notify; in imx_rproc_detect_mode()
1011 ret = imx_scu_irq_register_notifier(&priv->rproc_nb); in imx_rproc_detect_mode()
1017 ret = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), in imx_rproc_detect_mode()
1020 imx_scu_irq_unregister_notifier(&priv->rproc_nb); in imx_rproc_detect_mode()
1030 priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr"); in imx_rproc_detect_mode()
1031 if (IS_ERR(priv->gpr)) in imx_rproc_detect_mode()
1032 priv->gpr = NULL; in imx_rproc_detect_mode()
1034 regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); in imx_rproc_detect_mode()
1040 priv->regmap = regmap; in imx_rproc_detect_mode()
1043 if (priv->gpr) { in imx_rproc_detect_mode()
1044 ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val); in imx_rproc_detect_mode()
1045 if (val & dcfg->gpr_wait) { in imx_rproc_detect_mode()
1051 imx_rproc_stop(priv->rproc); in imx_rproc_detect_mode()
1056 ret = regmap_read(regmap, dcfg->src_reg, &val); in imx_rproc_detect_mode()
1062 if ((val & dcfg->src_mask) != dcfg->src_stop) in imx_rproc_detect_mode()
1063 priv->rproc->state = RPROC_DETACHED; in imx_rproc_detect_mode()
1070 const struct imx_rproc_dcfg *dcfg = priv->dcfg; in imx_rproc_clk_enable()
1071 struct device *dev = priv->dev; in imx_rproc_clk_enable()
1075 if (dcfg->method == IMX_RPROC_NONE) in imx_rproc_clk_enable()
1078 priv->clk = devm_clk_get(dev, NULL); in imx_rproc_clk_enable()
1079 if (IS_ERR(priv->clk)) { in imx_rproc_clk_enable()
1081 return PTR_ERR(priv->clk); in imx_rproc_clk_enable()
1088 ret = clk_prepare_enable(priv->clk); in imx_rproc_clk_enable()
1099 struct device *dev = &pdev->dev; in imx_rproc_probe()
1100 struct device_node *np = dev->of_node; in imx_rproc_probe()
1107 rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops, in imx_rproc_probe()
1110 return -ENOMEM; in imx_rproc_probe()
1114 ret = -EINVAL; in imx_rproc_probe()
1118 priv = rproc->priv; in imx_rproc_probe()
1119 priv->rproc = rproc; in imx_rproc_probe()
1120 priv->dcfg = dcfg; in imx_rproc_probe()
1121 priv->dev = dev; in imx_rproc_probe()
1124 priv->workqueue = create_workqueue(dev_name(dev)); in imx_rproc_probe()
1125 if (!priv->workqueue) { in imx_rproc_probe()
1127 ret = -ENOMEM; in imx_rproc_probe()
1149 INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); in imx_rproc_probe()
1151 if (rproc->state != RPROC_DETACHED) in imx_rproc_probe()
1152 rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); in imx_rproc_probe()
1163 clk_disable_unprepare(priv->clk); in imx_rproc_probe()
1169 destroy_workqueue(priv->workqueue); in imx_rproc_probe()
1179 struct imx_rproc *priv = rproc->priv; in imx_rproc_remove()
1181 clk_disable_unprepare(priv->clk); in imx_rproc_remove()
1185 destroy_workqueue(priv->workqueue); in imx_rproc_remove()
1190 { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp },
1191 { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d },
1192 { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx },
1193 { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq },
1194 { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
1195 { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
1196 { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
1197 { .compatible = "fsl,imx8mn-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
1198 { .compatible = "fsl,imx8mp-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
1199 { .compatible = "fsl,imx8qxp-cm4", .data = &imx_rproc_cfg_imx8qxp },
1200 { .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
1201 { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
1202 { .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
1211 .name = "imx-rproc",