1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * TI K3 DSP Remote Processor(s) driver 4 * 5 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ 6 * Suman Anna <s-anna@ti.com> 7 */ 8 9 #include <linux/io.h> 10 #include <linux/mailbox_client.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_reserved_mem.h> 14 #include <linux/omap-mailbox.h> 15 #include <linux/platform_device.h> 16 #include <linux/remoteproc.h> 17 #include <linux/reset.h> 18 #include <linux/slab.h> 19 20 #include "omap_remoteproc.h" 21 #include "remoteproc_internal.h" 22 #include "ti_sci_proc.h" 23 #include "ti_k3_common.h" 24 25 /* 26 * Power up the DSP remote processor. 27 * 28 * This function will be invoked only after the firmware for this rproc 29 * was loaded, parsed successfully, and all of its resource requirements 30 * were met. This callback is invoked only in remoteproc mode. 31 */ 32 static int k3_dsp_rproc_start(struct rproc *rproc) 33 { 34 struct k3_rproc *kproc = rproc->priv; 35 struct device *dev = kproc->dev; 36 u32 boot_addr; 37 int ret; 38 39 boot_addr = rproc->bootaddr; 40 if (boot_addr & (kproc->data->boot_align_addr - 1)) { 41 dev_err(dev, "invalid boot address 0x%x, must be aligned on a 0x%x boundary\n", 42 boot_addr, kproc->data->boot_align_addr); 43 return -EINVAL; 44 } 45 46 dev_dbg(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr); 47 ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0); 48 if (ret) 49 return ret; 50 51 /* Call the K3 common start function after doing DSP specific stuff */ 52 ret = k3_rproc_start(rproc); 53 if (ret) 54 return ret; 55 56 return 0; 57 } 58 59 static const struct rproc_ops k3_dsp_rproc_ops = { 60 .start = k3_dsp_rproc_start, 61 .stop = k3_rproc_stop, 62 .attach = k3_rproc_attach, 63 .detach = k3_rproc_detach, 64 .kick = k3_rproc_kick, 65 .da_to_va = k3_rproc_da_to_va, 66 .get_loaded_rsc_table = k3_get_loaded_rsc_table, 67 }; 68 69 static int k3_dsp_rproc_probe(struct platform_device *pdev) 70 { 71 struct device *dev = &pdev->dev; 72 struct device_node *np = dev->of_node; 73 const struct k3_rproc_dev_data *data; 74 struct k3_rproc *kproc; 75 struct rproc *rproc; 76 const char *fw_name; 77 bool p_state = false; 78 int ret = 0; 79 80 data = of_device_get_match_data(dev); 81 if (!data) 82 return -ENODEV; 83 84 ret = rproc_of_parse_firmware(dev, 0, &fw_name); 85 if (ret) 86 return dev_err_probe(dev, ret, "failed to parse firmware-name property\n"); 87 88 rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_dsp_rproc_ops, 89 fw_name, sizeof(*kproc)); 90 if (!rproc) 91 return -ENOMEM; 92 93 rproc->has_iommu = false; 94 rproc->recovery_disabled = true; 95 if (data->uses_lreset) { 96 rproc->ops->prepare = k3_rproc_prepare; 97 rproc->ops->unprepare = k3_rproc_unprepare; 98 } 99 kproc = rproc->priv; 100 kproc->rproc = rproc; 101 kproc->dev = dev; 102 kproc->data = data; 103 104 ret = k3_rproc_request_mbox(rproc); 105 if (ret) 106 return ret; 107 108 kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); 109 if (IS_ERR(kproc->ti_sci)) 110 return dev_err_probe(dev, PTR_ERR(kproc->ti_sci), 111 "failed to get ti-sci handle\n"); 112 113 ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id); 114 if (ret) 115 return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n"); 116 117 kproc->reset = devm_reset_control_get_exclusive(dev, NULL); 118 if (IS_ERR(kproc->reset)) 119 return dev_err_probe(dev, PTR_ERR(kproc->reset), 120 "failed to get reset\n"); 121 122 kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci); 123 if (IS_ERR(kproc->tsp)) 124 return dev_err_probe(dev, PTR_ERR(kproc->tsp), 125 "failed to construct ti-sci proc control\n"); 126 127 ret = ti_sci_proc_request(kproc->tsp); 128 if (ret < 0) { 129 dev_err_probe(dev, ret, "ti_sci_proc_request failed\n"); 130 return ret; 131 } 132 ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp); 133 if (ret) 134 return ret; 135 136 ret = k3_rproc_of_get_memories(pdev, kproc); 137 if (ret) 138 return ret; 139 140 ret = k3_reserved_mem_init(kproc); 141 if (ret) 142 return dev_err_probe(dev, ret, "reserved memory init failed\n"); 143 144 ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id, 145 NULL, &p_state); 146 if (ret) 147 return dev_err_probe(dev, ret, "failed to get initial state, mode cannot be determined\n"); 148 149 /* configure J721E devices for either remoteproc or IPC-only mode */ 150 if (p_state) { 151 dev_info(dev, "configured DSP for IPC-only mode\n"); 152 rproc->state = RPROC_DETACHED; 153 } else { 154 dev_info(dev, "configured DSP for remoteproc mode\n"); 155 } 156 157 ret = devm_rproc_add(dev, rproc); 158 if (ret) 159 return dev_err_probe(dev, ret, "failed to add register device with remoteproc core\n"); 160 161 platform_set_drvdata(pdev, kproc); 162 163 return 0; 164 } 165 166 static void k3_dsp_rproc_remove(struct platform_device *pdev) 167 { 168 struct k3_rproc *kproc = platform_get_drvdata(pdev); 169 struct rproc *rproc = kproc->rproc; 170 struct device *dev = &pdev->dev; 171 int ret; 172 173 if (rproc->state == RPROC_ATTACHED) { 174 ret = rproc_detach(rproc); 175 if (ret) 176 dev_err(dev, "failed to detach proc (%pe)\n", ERR_PTR(ret)); 177 } 178 179 mbox_free_channel(kproc->mbox); 180 } 181 182 static const struct k3_rproc_mem_data c66_mems[] = { 183 { .name = "l2sram", .dev_addr = 0x800000 }, 184 { .name = "l1pram", .dev_addr = 0xe00000 }, 185 { .name = "l1dram", .dev_addr = 0xf00000 }, 186 }; 187 188 /* C71x cores only have a L1P Cache, there are no L1P SRAMs */ 189 static const struct k3_rproc_mem_data c71_mems[] = { 190 { .name = "l2sram", .dev_addr = 0x800000 }, 191 { .name = "l1dram", .dev_addr = 0xe00000 }, 192 }; 193 194 static const struct k3_rproc_mem_data c7xv_mems[] = { 195 { .name = "l2sram", .dev_addr = 0x800000 }, 196 }; 197 198 static const struct k3_rproc_dev_data c66_data = { 199 .mems = c66_mems, 200 .num_mems = ARRAY_SIZE(c66_mems), 201 .boot_align_addr = SZ_1K, 202 .uses_lreset = true, 203 }; 204 205 static const struct k3_rproc_dev_data c71_data = { 206 .mems = c71_mems, 207 .num_mems = ARRAY_SIZE(c71_mems), 208 .boot_align_addr = SZ_2M, 209 .uses_lreset = false, 210 }; 211 212 static const struct k3_rproc_dev_data c7xv_data = { 213 .mems = c7xv_mems, 214 .num_mems = ARRAY_SIZE(c7xv_mems), 215 .boot_align_addr = SZ_2M, 216 .uses_lreset = false, 217 }; 218 219 static const struct of_device_id k3_dsp_of_match[] = { 220 { .compatible = "ti,j721e-c66-dsp", .data = &c66_data, }, 221 { .compatible = "ti,j721e-c71-dsp", .data = &c71_data, }, 222 { .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, }, 223 { .compatible = "ti,am62a-c7xv-dsp", .data = &c7xv_data, }, 224 { /* sentinel */ }, 225 }; 226 MODULE_DEVICE_TABLE(of, k3_dsp_of_match); 227 228 static struct platform_driver k3_dsp_rproc_driver = { 229 .probe = k3_dsp_rproc_probe, 230 .remove = k3_dsp_rproc_remove, 231 .driver = { 232 .name = "k3-dsp-rproc", 233 .of_match_table = k3_dsp_of_match, 234 }, 235 }; 236 237 module_platform_driver(k3_dsp_rproc_driver); 238 239 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>"); 240 MODULE_LICENSE("GPL v2"); 241 MODULE_DESCRIPTION("TI K3 DSP Remoteproc driver"); 242