1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * TI K3 Cortex-M4 Remote Processor(s) driver 4 * 5 * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/ 6 * Hari Nagalla <hnagalla@ti.com> 7 */ 8 9 #include <linux/io.h> 10 #include <linux/mailbox_client.h> 11 #include <linux/module.h> 12 #include <linux/of_address.h> 13 #include <linux/of_reserved_mem.h> 14 #include <linux/platform_device.h> 15 #include <linux/remoteproc.h> 16 #include <linux/reset.h> 17 #include <linux/slab.h> 18 19 #include "omap_remoteproc.h" 20 #include "remoteproc_internal.h" 21 #include "ti_sci_proc.h" 22 #include "ti_k3_common.h" 23 24 static const struct rproc_ops k3_m4_rproc_ops = { 25 .prepare = k3_rproc_prepare, 26 .unprepare = k3_rproc_unprepare, 27 .start = k3_rproc_start, 28 .stop = k3_rproc_stop, 29 .attach = k3_rproc_attach, 30 .detach = k3_rproc_detach, 31 .kick = k3_rproc_kick, 32 .da_to_va = k3_rproc_da_to_va, 33 .get_loaded_rsc_table = k3_get_loaded_rsc_table, 34 }; 35 36 static int k3_m4_rproc_probe(struct platform_device *pdev) 37 { 38 const struct k3_rproc_dev_data *data; 39 struct device *dev = &pdev->dev; 40 struct k3_rproc *kproc; 41 struct rproc *rproc; 42 const char *fw_name; 43 bool r_state = false; 44 bool p_state = false; 45 int ret; 46 47 data = of_device_get_match_data(dev); 48 if (!data) 49 return -ENODEV; 50 51 ret = rproc_of_parse_firmware(dev, 0, &fw_name); 52 if (ret) 53 return dev_err_probe(dev, ret, "failed to parse firmware-name property\n"); 54 55 rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_m4_rproc_ops, fw_name, 56 sizeof(*kproc)); 57 if (!rproc) 58 return -ENOMEM; 59 60 rproc->has_iommu = false; 61 rproc->recovery_disabled = true; 62 kproc = rproc->priv; 63 kproc->dev = dev; 64 kproc->rproc = rproc; 65 kproc->data = data; 66 platform_set_drvdata(pdev, rproc); 67 68 kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); 69 if (IS_ERR(kproc->ti_sci)) 70 return dev_err_probe(dev, PTR_ERR(kproc->ti_sci), 71 "failed to get ti-sci handle\n"); 72 73 ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &kproc->ti_sci_id); 74 if (ret) 75 return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n"); 76 77 kproc->reset = devm_reset_control_get_exclusive(dev, NULL); 78 if (IS_ERR(kproc->reset)) 79 return dev_err_probe(dev, PTR_ERR(kproc->reset), "failed to get reset\n"); 80 81 kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci); 82 if (IS_ERR(kproc->tsp)) 83 return dev_err_probe(dev, PTR_ERR(kproc->tsp), 84 "failed to construct ti-sci proc control\n"); 85 86 ret = ti_sci_proc_request(kproc->tsp); 87 if (ret < 0) 88 return dev_err_probe(dev, ret, "ti_sci_proc_request failed\n"); 89 ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp); 90 if (ret) 91 return ret; 92 93 ret = k3_rproc_of_get_memories(pdev, kproc); 94 if (ret) 95 return ret; 96 97 ret = k3_reserved_mem_init(kproc); 98 if (ret) 99 return dev_err_probe(dev, ret, "reserved memory init failed\n"); 100 101 ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id, 102 &r_state, &p_state); 103 if (ret) 104 return dev_err_probe(dev, ret, 105 "failed to get initial state, mode cannot be determined\n"); 106 107 /* configure devices for either remoteproc or IPC-only mode */ 108 if (p_state) { 109 rproc->state = RPROC_DETACHED; 110 dev_info(dev, "configured M4F for IPC-only mode\n"); 111 } else { 112 dev_info(dev, "configured M4F for remoteproc mode\n"); 113 } 114 115 ret = k3_rproc_request_mbox(rproc); 116 if (ret) 117 return ret; 118 119 ret = devm_rproc_add(dev, rproc); 120 if (ret) 121 return dev_err_probe(dev, ret, 122 "failed to register device with remoteproc core\n"); 123 124 return 0; 125 } 126 127 static const struct k3_rproc_mem_data am64_m4_mems[] = { 128 { .name = "iram", .dev_addr = 0x0 }, 129 { .name = "dram", .dev_addr = 0x30000 }, 130 }; 131 132 static const struct k3_rproc_dev_data am64_m4_data = { 133 .mems = am64_m4_mems, 134 .num_mems = ARRAY_SIZE(am64_m4_mems), 135 .boot_align_addr = SZ_1K, 136 .uses_lreset = true, 137 }; 138 139 static const struct of_device_id k3_m4_of_match[] = { 140 { .compatible = "ti,am64-m4fss", .data = &am64_m4_data, }, 141 { /* sentinel */ }, 142 }; 143 MODULE_DEVICE_TABLE(of, k3_m4_of_match); 144 145 static struct platform_driver k3_m4_rproc_driver = { 146 .probe = k3_m4_rproc_probe, 147 .driver = { 148 .name = "k3-m4-rproc", 149 .of_match_table = k3_m4_of_match, 150 }, 151 }; 152 module_platform_driver(k3_m4_rproc_driver); 153 154 MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com>"); 155 MODULE_DESCRIPTION("TI K3 M4 Remoteproc driver"); 156 MODULE_LICENSE("GPL"); 157