xref: /linux/drivers/remoteproc/ti_k3_dsp_remoteproc.c (revision 23ca32e4ead48f68e37000f2552b973ef1439acb)
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