1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 /* 3 * Copyright 2025 NXP 4 */ 5 6 #include <linux/arm-smccc.h> 7 8 #include "imx-common.h" 9 10 #define IMX_SIP_SRC 0xC2000005 11 #define IMX_SIP_SRC_M_RESET_ADDR_SET 0x03 12 13 #define IMX95_CPU_VEC_FLAGS_BOOT BIT(29) 14 15 #define IMX_SIP_LMM 0xC200000F 16 #define IMX_SIP_LMM_BOOT 0x0 17 #define IMX_SIP_LMM_SHUTDOWN 0x1 18 19 #define IMX95_M7_LM_ID 0x1 20 21 static struct snd_soc_dai_driver imx95_dai[] = { 22 IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai3", 1, 32), 23 }; 24 25 static struct snd_sof_dsp_ops sof_imx9_ops; 26 27 static int imx95_ops_init(struct snd_sof_dev *sdev) 28 { 29 /* first copy from template */ 30 memcpy(&sof_imx9_ops, &sof_imx_ops, sizeof(sof_imx_ops)); 31 32 /* ... and finally set DAI driver */ 33 sof_imx9_ops.drv = get_chip_info(sdev)->drv; 34 sof_imx9_ops.num_drv = get_chip_info(sdev)->num_drv; 35 36 return 0; 37 } 38 39 static int imx95_chip_probe(struct snd_sof_dev *sdev) 40 { 41 struct arm_smccc_res smc_res; 42 struct platform_device *pdev; 43 struct resource *res; 44 45 pdev = to_platform_device(sdev->dev); 46 47 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram"); 48 if (!res) 49 return dev_err_probe(sdev->dev, -ENODEV, 50 "failed to fetch SRAM region\n"); 51 52 /* set core boot reset address */ 53 arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M_RESET_ADDR_SET, res->start, 54 IMX95_CPU_VEC_FLAGS_BOOT, 0, 0, 0, 0, &smc_res); 55 56 return smc_res.a0; 57 } 58 59 static int imx95_core_kick(struct snd_sof_dev *sdev) 60 { 61 struct arm_smccc_res smc_res; 62 63 arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_BOOT, 64 IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); 65 66 return smc_res.a0; 67 } 68 69 static int imx95_core_shutdown(struct snd_sof_dev *sdev) 70 { 71 struct arm_smccc_res smc_res; 72 73 arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_SHUTDOWN, 74 IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); 75 76 return smc_res.a0; 77 } 78 79 static const struct imx_chip_ops imx95_chip_ops = { 80 .probe = imx95_chip_probe, 81 .core_kick = imx95_core_kick, 82 .core_shutdown = imx95_core_shutdown, 83 }; 84 85 static struct imx_memory_info imx95_memory_regions[] = { 86 { .name = "sram", .reserved = false }, 87 { } 88 }; 89 90 static const struct imx_chip_info imx95_chip_info = { 91 .ipc_info = { 92 .boot_mbox_offset = 0x6001000, 93 .window_offset = 0x6000000, 94 }, 95 .has_dma_reserved = true, 96 .memory = imx95_memory_regions, 97 .drv = imx95_dai, 98 .num_drv = ARRAY_SIZE(imx95_dai), 99 .ops = &imx95_chip_ops, 100 }; 101 102 static struct snd_sof_of_mach sof_imx9_machs[] = { 103 { 104 .compatible = "fsl,imx95-19x19-evk", 105 .sof_tplg_filename = "sof-imx95-wm8962.tplg", 106 .drv_name = "asoc-audio-graph-card2", 107 }, 108 { 109 } 110 }; 111 112 IMX_SOF_DEV_DESC(imx95, sof_imx9_machs, &imx95_chip_info, &sof_imx9_ops, imx95_ops_init); 113 114 static const struct of_device_id sof_of_imx9_ids[] = { 115 { 116 .compatible = "fsl,imx95-cm7-sof", 117 .data = &IMX_SOF_DEV_DESC_NAME(imx95), 118 }, 119 { 120 }, 121 }; 122 MODULE_DEVICE_TABLE(of, sof_of_imx9_ids); 123 124 static struct platform_driver snd_sof_of_imx9_driver = { 125 .probe = sof_of_probe, 126 .remove = sof_of_remove, 127 .driver = { 128 .name = "sof-audio-of-imx9", 129 .pm = pm_ptr(&sof_of_pm), 130 .of_match_table = sof_of_imx9_ids, 131 }, 132 }; 133 module_platform_driver(snd_sof_of_imx9_driver); 134 135 MODULE_LICENSE("Dual BSD/GPL"); 136 MODULE_DESCRIPTION("SOF driver for imx9 platforms"); 137 MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>"); 138