16cf5df10SLaurentiu Mihalcea // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 26cf5df10SLaurentiu Mihalcea /* 36cf5df10SLaurentiu Mihalcea * Copyright 2025 NXP 46cf5df10SLaurentiu Mihalcea */ 56cf5df10SLaurentiu Mihalcea 66cf5df10SLaurentiu Mihalcea #include <linux/arm-smccc.h> 76cf5df10SLaurentiu Mihalcea 86cf5df10SLaurentiu Mihalcea #include "imx-common.h" 96cf5df10SLaurentiu Mihalcea 106cf5df10SLaurentiu Mihalcea #define IMX_SIP_SRC 0xC2000005 116cf5df10SLaurentiu Mihalcea #define IMX_SIP_SRC_M_RESET_ADDR_SET 0x03 126cf5df10SLaurentiu Mihalcea 136cf5df10SLaurentiu Mihalcea #define IMX95_CPU_VEC_FLAGS_BOOT BIT(29) 146cf5df10SLaurentiu Mihalcea 156cf5df10SLaurentiu Mihalcea #define IMX_SIP_LMM 0xC200000F 166cf5df10SLaurentiu Mihalcea #define IMX_SIP_LMM_BOOT 0x0 176cf5df10SLaurentiu Mihalcea #define IMX_SIP_LMM_SHUTDOWN 0x1 186cf5df10SLaurentiu Mihalcea 196cf5df10SLaurentiu Mihalcea #define IMX95_M7_LM_ID 0x1 206cf5df10SLaurentiu Mihalcea 216cf5df10SLaurentiu Mihalcea static struct snd_soc_dai_driver imx95_dai[] = { 226cf5df10SLaurentiu Mihalcea IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai3", 1, 32), 236cf5df10SLaurentiu Mihalcea }; 246cf5df10SLaurentiu Mihalcea 256cf5df10SLaurentiu Mihalcea static struct snd_sof_dsp_ops sof_imx9_ops; 266cf5df10SLaurentiu Mihalcea 276cf5df10SLaurentiu Mihalcea static int imx95_ops_init(struct snd_sof_dev *sdev) 286cf5df10SLaurentiu Mihalcea { 296cf5df10SLaurentiu Mihalcea /* first copy from template */ 306cf5df10SLaurentiu Mihalcea memcpy(&sof_imx9_ops, &sof_imx_ops, sizeof(sof_imx_ops)); 316cf5df10SLaurentiu Mihalcea 326cf5df10SLaurentiu Mihalcea /* ... and finally set DAI driver */ 336cf5df10SLaurentiu Mihalcea sof_imx9_ops.drv = get_chip_info(sdev)->drv; 346cf5df10SLaurentiu Mihalcea sof_imx9_ops.num_drv = get_chip_info(sdev)->num_drv; 356cf5df10SLaurentiu Mihalcea 366cf5df10SLaurentiu Mihalcea return 0; 376cf5df10SLaurentiu Mihalcea } 386cf5df10SLaurentiu Mihalcea 396cf5df10SLaurentiu Mihalcea static int imx95_chip_probe(struct snd_sof_dev *sdev) 406cf5df10SLaurentiu Mihalcea { 416cf5df10SLaurentiu Mihalcea struct arm_smccc_res smc_res; 426cf5df10SLaurentiu Mihalcea struct platform_device *pdev; 436cf5df10SLaurentiu Mihalcea struct resource *res; 446cf5df10SLaurentiu Mihalcea 456cf5df10SLaurentiu Mihalcea pdev = to_platform_device(sdev->dev); 466cf5df10SLaurentiu Mihalcea 476cf5df10SLaurentiu Mihalcea res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram"); 486cf5df10SLaurentiu Mihalcea if (!res) 496cf5df10SLaurentiu Mihalcea return dev_err_probe(sdev->dev, -ENODEV, 506cf5df10SLaurentiu Mihalcea "failed to fetch SRAM region\n"); 516cf5df10SLaurentiu Mihalcea 526cf5df10SLaurentiu Mihalcea /* set core boot reset address */ 536cf5df10SLaurentiu Mihalcea arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M_RESET_ADDR_SET, res->start, 546cf5df10SLaurentiu Mihalcea IMX95_CPU_VEC_FLAGS_BOOT, 0, 0, 0, 0, &smc_res); 556cf5df10SLaurentiu Mihalcea 566cf5df10SLaurentiu Mihalcea return smc_res.a0; 576cf5df10SLaurentiu Mihalcea } 586cf5df10SLaurentiu Mihalcea 596cf5df10SLaurentiu Mihalcea static int imx95_core_kick(struct snd_sof_dev *sdev) 606cf5df10SLaurentiu Mihalcea { 616cf5df10SLaurentiu Mihalcea struct arm_smccc_res smc_res; 626cf5df10SLaurentiu Mihalcea 636cf5df10SLaurentiu Mihalcea arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_BOOT, 646cf5df10SLaurentiu Mihalcea IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); 656cf5df10SLaurentiu Mihalcea 666cf5df10SLaurentiu Mihalcea return smc_res.a0; 676cf5df10SLaurentiu Mihalcea } 686cf5df10SLaurentiu Mihalcea 696cf5df10SLaurentiu Mihalcea static int imx95_core_shutdown(struct snd_sof_dev *sdev) 706cf5df10SLaurentiu Mihalcea { 716cf5df10SLaurentiu Mihalcea struct arm_smccc_res smc_res; 726cf5df10SLaurentiu Mihalcea 736cf5df10SLaurentiu Mihalcea arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_SHUTDOWN, 746cf5df10SLaurentiu Mihalcea IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); 756cf5df10SLaurentiu Mihalcea 766cf5df10SLaurentiu Mihalcea return smc_res.a0; 776cf5df10SLaurentiu Mihalcea } 786cf5df10SLaurentiu Mihalcea 796cf5df10SLaurentiu Mihalcea static const struct imx_chip_ops imx95_chip_ops = { 806cf5df10SLaurentiu Mihalcea .probe = imx95_chip_probe, 816cf5df10SLaurentiu Mihalcea .core_kick = imx95_core_kick, 826cf5df10SLaurentiu Mihalcea .core_shutdown = imx95_core_shutdown, 836cf5df10SLaurentiu Mihalcea }; 846cf5df10SLaurentiu Mihalcea 856cf5df10SLaurentiu Mihalcea static struct imx_memory_info imx95_memory_regions[] = { 866cf5df10SLaurentiu Mihalcea { .name = "sram", .reserved = false }, 876cf5df10SLaurentiu Mihalcea { } 886cf5df10SLaurentiu Mihalcea }; 896cf5df10SLaurentiu Mihalcea 906cf5df10SLaurentiu Mihalcea static const struct imx_chip_info imx95_chip_info = { 916cf5df10SLaurentiu Mihalcea .ipc_info = { 926cf5df10SLaurentiu Mihalcea .boot_mbox_offset = 0x6001000, 936cf5df10SLaurentiu Mihalcea .window_offset = 0x6000000, 946cf5df10SLaurentiu Mihalcea }, 956cf5df10SLaurentiu Mihalcea .has_dma_reserved = true, 966cf5df10SLaurentiu Mihalcea .memory = imx95_memory_regions, 976cf5df10SLaurentiu Mihalcea .drv = imx95_dai, 986cf5df10SLaurentiu Mihalcea .num_drv = ARRAY_SIZE(imx95_dai), 996cf5df10SLaurentiu Mihalcea .ops = &imx95_chip_ops, 1006cf5df10SLaurentiu Mihalcea }; 1016cf5df10SLaurentiu Mihalcea 1026cf5df10SLaurentiu Mihalcea static struct snd_sof_of_mach sof_imx9_machs[] = { 1036cf5df10SLaurentiu Mihalcea { 1046cf5df10SLaurentiu Mihalcea .compatible = "fsl,imx95-19x19-evk", 1056cf5df10SLaurentiu Mihalcea .sof_tplg_filename = "sof-imx95-wm8962.tplg", 1066cf5df10SLaurentiu Mihalcea .drv_name = "asoc-audio-graph-card2", 1076cf5df10SLaurentiu Mihalcea }, 1086cf5df10SLaurentiu Mihalcea { 1096cf5df10SLaurentiu Mihalcea } 1106cf5df10SLaurentiu Mihalcea }; 1116cf5df10SLaurentiu Mihalcea 1126cf5df10SLaurentiu Mihalcea IMX_SOF_DEV_DESC(imx95, sof_imx9_machs, &imx95_chip_info, &sof_imx9_ops, imx95_ops_init); 1136cf5df10SLaurentiu Mihalcea 1146cf5df10SLaurentiu Mihalcea static const struct of_device_id sof_of_imx9_ids[] = { 1156cf5df10SLaurentiu Mihalcea { 1166cf5df10SLaurentiu Mihalcea .compatible = "fsl,imx95-cm7-sof", 1176cf5df10SLaurentiu Mihalcea .data = &IMX_SOF_DEV_DESC_NAME(imx95), 1186cf5df10SLaurentiu Mihalcea }, 1196cf5df10SLaurentiu Mihalcea { 1206cf5df10SLaurentiu Mihalcea }, 1216cf5df10SLaurentiu Mihalcea }; 1226cf5df10SLaurentiu Mihalcea MODULE_DEVICE_TABLE(of, sof_of_imx9_ids); 1236cf5df10SLaurentiu Mihalcea 1246cf5df10SLaurentiu Mihalcea static struct platform_driver snd_sof_of_imx9_driver = { 1256cf5df10SLaurentiu Mihalcea .probe = sof_of_probe, 1266cf5df10SLaurentiu Mihalcea .remove = sof_of_remove, 1276cf5df10SLaurentiu Mihalcea .driver = { 1286cf5df10SLaurentiu Mihalcea .name = "sof-audio-of-imx9", 129*f8d952c5STakashi Iwai .pm = pm_ptr(&sof_of_pm), 1306cf5df10SLaurentiu Mihalcea .of_match_table = sof_of_imx9_ids, 1316cf5df10SLaurentiu Mihalcea }, 1326cf5df10SLaurentiu Mihalcea }; 1336cf5df10SLaurentiu Mihalcea module_platform_driver(snd_sof_of_imx9_driver); 1346cf5df10SLaurentiu Mihalcea 1356cf5df10SLaurentiu Mihalcea MODULE_LICENSE("Dual BSD/GPL"); 1366cf5df10SLaurentiu Mihalcea MODULE_DESCRIPTION("SOF driver for imx9 platforms"); 1376cf5df10SLaurentiu Mihalcea MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>"); 138