xref: /linux/drivers/remoteproc/st_remoteproc.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ST's Remote Processor Control Driver
4  *
5  * Copyright (C) 2015 STMicroelectronics - All Rights Reserved
6  *
7  * Author: Ludovic Barre <ludovic.barre@st.com>
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/err.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/mailbox_client.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/of_reserved_mem.h>
20 #include <linux/platform_device.h>
21 #include <linux/property.h>
22 #include <linux/regmap.h>
23 #include <linux/remoteproc.h>
24 #include <linux/reset.h>
25 
26 #include "remoteproc_internal.h"
27 
28 #define ST_RPROC_VQ0		0
29 #define ST_RPROC_VQ1		1
30 #define ST_RPROC_MAX_VRING	2
31 
32 #define MBOX_RX			0
33 #define MBOX_TX			1
34 #define MBOX_MAX		2
35 
36 struct st_rproc_config {
37 	bool			sw_reset;
38 	bool			pwr_reset;
39 	unsigned long		bootaddr_mask;
40 };
41 
42 struct st_rproc {
43 	struct st_rproc_config	*config;
44 	struct reset_control	*sw_reset;
45 	struct reset_control	*pwr_reset;
46 	struct clk		*clk;
47 	u32			clk_rate;
48 	struct regmap		*boot_base;
49 	u32			boot_offset;
50 	struct mbox_chan	*mbox_chan[ST_RPROC_MAX_VRING * MBOX_MAX];
51 	struct mbox_client mbox_client_vq0;
52 	struct mbox_client mbox_client_vq1;
53 };
54 
55 static void st_rproc_mbox_callback(struct device *dev, u32 msg)
56 {
57 	struct rproc *rproc = dev_get_drvdata(dev);
58 
59 	if (rproc_vq_interrupt(rproc, msg) == IRQ_NONE)
60 		dev_dbg(dev, "no message was found in vqid %d\n", msg);
61 }
62 
63 static
64 void st_rproc_mbox_callback_vq0(struct mbox_client *mbox_client, void *data)
65 {
66 	st_rproc_mbox_callback(mbox_client->dev, 0);
67 }
68 
69 static
70 void st_rproc_mbox_callback_vq1(struct mbox_client *mbox_client, void *data)
71 {
72 	st_rproc_mbox_callback(mbox_client->dev, 1);
73 }
74 
75 static void st_rproc_kick(struct rproc *rproc, int vqid)
76 {
77 	struct st_rproc *ddata = rproc->priv;
78 	struct device *dev = rproc->dev.parent;
79 	int ret;
80 
81 	/* send the index of the triggered virtqueue in the mailbox payload */
82 	if (WARN_ON(vqid >= ST_RPROC_MAX_VRING))
83 		return;
84 
85 	ret = mbox_send_message(ddata->mbox_chan[vqid * MBOX_MAX + MBOX_TX],
86 				(void *)&vqid);
87 	if (ret < 0)
88 		dev_err(dev, "failed to send message via mbox: %d\n", ret);
89 }
90 
91 static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
92 {
93 	struct device *dev = rproc->dev.parent;
94 	struct device_node *np = dev->of_node;
95 	struct rproc_mem_entry *mem;
96 	int entries;
97 
98 	entries = of_reserved_mem_region_count(np);
99 
100 	for (int index = 0; index < entries; index++) {
101 		struct resource res;
102 		int ret;
103 
104 		ret = of_reserved_mem_region_to_resource(np, index, &res);
105 		if (ret)
106 			return ret;
107 
108 		/*  No need to map vdev buffer */
109 		if (!strstarts(res.name, "vdev0buffer")) {
110 			/* Register memory region */
111 			mem = rproc_mem_entry_init(dev, NULL,
112 						   (dma_addr_t)res.start,
113 						   resource_size(&res), res.start,
114 						   rproc_mem_entry_ioremap_wc,
115 						   rproc_mem_entry_iounmap,
116 						   "%.*s",
117 						   strchrnul(res.name, '@') - res.name,
118 						   res.name);
119 		} else {
120 			/* Register reserved memory for vdev buffer allocation */
121 			mem = rproc_of_resm_mem_entry_init(dev, index,
122 							   resource_size(&res),
123 							   res.start,
124 							   "vdev0buffer");
125 		}
126 
127 		if (!mem)
128 			return -ENOMEM;
129 
130 		rproc_add_carveout(rproc, mem);
131 	}
132 
133 	return rproc_elf_load_rsc_table(rproc, fw);
134 }
135 
136 static int st_rproc_start(struct rproc *rproc)
137 {
138 	struct st_rproc *ddata = rproc->priv;
139 	int err;
140 
141 	regmap_update_bits(ddata->boot_base, ddata->boot_offset,
142 			   ddata->config->bootaddr_mask, rproc->bootaddr);
143 
144 	err = clk_enable(ddata->clk);
145 	if (err) {
146 		dev_err(&rproc->dev, "Failed to enable clock\n");
147 		return err;
148 	}
149 
150 	if (ddata->config->sw_reset) {
151 		err = reset_control_deassert(ddata->sw_reset);
152 		if (err) {
153 			dev_err(&rproc->dev, "Failed to deassert S/W Reset\n");
154 			goto sw_reset_fail;
155 		}
156 	}
157 
158 	if (ddata->config->pwr_reset) {
159 		err = reset_control_deassert(ddata->pwr_reset);
160 		if (err) {
161 			dev_err(&rproc->dev, "Failed to deassert Power Reset\n");
162 			goto pwr_reset_fail;
163 		}
164 	}
165 
166 	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
167 
168 	return 0;
169 
170 
171 pwr_reset_fail:
172 	if (ddata->config->pwr_reset)
173 		reset_control_assert(ddata->sw_reset);
174 sw_reset_fail:
175 	clk_disable(ddata->clk);
176 
177 	return err;
178 }
179 
180 static int st_rproc_stop(struct rproc *rproc)
181 {
182 	struct st_rproc *ddata = rproc->priv;
183 	int sw_err = 0, pwr_err = 0;
184 
185 	if (ddata->config->sw_reset) {
186 		sw_err = reset_control_assert(ddata->sw_reset);
187 		if (sw_err)
188 			dev_err(&rproc->dev, "Failed to assert S/W Reset\n");
189 	}
190 
191 	if (ddata->config->pwr_reset) {
192 		pwr_err = reset_control_assert(ddata->pwr_reset);
193 		if (pwr_err)
194 			dev_err(&rproc->dev, "Failed to assert Power Reset\n");
195 	}
196 
197 	clk_disable(ddata->clk);
198 
199 	return sw_err ?: pwr_err;
200 }
201 
202 static const struct rproc_ops st_rproc_ops = {
203 	.kick			= st_rproc_kick,
204 	.start			= st_rproc_start,
205 	.stop			= st_rproc_stop,
206 	.parse_fw		= st_rproc_parse_fw,
207 	.load			= rproc_elf_load_segments,
208 	.find_loaded_rsc_table	= rproc_elf_find_loaded_rsc_table,
209 	.sanity_check		= rproc_elf_sanity_check,
210 	.get_boot_addr		= rproc_elf_get_boot_addr,
211 };
212 
213 /*
214  * Fetch state of the processor: 0 is off, 1 is on.
215  */
216 static int st_rproc_state(struct platform_device *pdev)
217 {
218 	struct rproc *rproc = platform_get_drvdata(pdev);
219 	struct st_rproc *ddata = rproc->priv;
220 	int reset_sw = 0, reset_pwr = 0;
221 
222 	if (ddata->config->sw_reset)
223 		reset_sw = reset_control_status(ddata->sw_reset);
224 
225 	if (ddata->config->pwr_reset)
226 		reset_pwr = reset_control_status(ddata->pwr_reset);
227 
228 	if (reset_sw < 0 || reset_pwr < 0)
229 		return -EINVAL;
230 
231 	return !reset_sw && !reset_pwr;
232 }
233 
234 static const struct st_rproc_config st40_rproc_cfg = {
235 	.sw_reset = true,
236 	.pwr_reset = true,
237 	.bootaddr_mask = GENMASK(28, 1),
238 };
239 
240 static const struct st_rproc_config st231_rproc_cfg = {
241 	.sw_reset = true,
242 	.pwr_reset = false,
243 	.bootaddr_mask = GENMASK(31, 6),
244 };
245 
246 static const struct of_device_id st_rproc_match[] = {
247 	{ .compatible = "st,st40-rproc", .data = &st40_rproc_cfg },
248 	{ .compatible = "st,st231-rproc", .data = &st231_rproc_cfg },
249 	{},
250 };
251 MODULE_DEVICE_TABLE(of, st_rproc_match);
252 
253 static int st_rproc_parse_dt(struct platform_device *pdev)
254 {
255 	struct device *dev = &pdev->dev;
256 	struct rproc *rproc = platform_get_drvdata(pdev);
257 	struct st_rproc *ddata = rproc->priv;
258 	struct device_node *np = dev->of_node;
259 	int err;
260 
261 	if (ddata->config->sw_reset) {
262 		ddata->sw_reset = devm_reset_control_get_exclusive(dev,
263 								   "sw_reset");
264 		if (IS_ERR(ddata->sw_reset))
265 			return dev_err_probe(dev, PTR_ERR(ddata->sw_reset),
266 					     "Failed to get S/W Reset\n");
267 	}
268 
269 	if (ddata->config->pwr_reset) {
270 		ddata->pwr_reset = devm_reset_control_get_exclusive(dev,
271 								    "pwr_reset");
272 		if (IS_ERR(ddata->pwr_reset))
273 			return dev_err_probe(dev, PTR_ERR(ddata->pwr_reset),
274 					     "Failed to get Power Reset\n");
275 	}
276 
277 	ddata->clk = devm_clk_get(dev, NULL);
278 	if (IS_ERR(ddata->clk))
279 		return dev_err_probe(dev, PTR_ERR(ddata->clk),
280 				     "Failed to get clock\n");
281 
282 	err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate);
283 	if (err) {
284 		dev_err(dev, "failed to get clock frequency\n");
285 		return err;
286 	}
287 
288 	ddata->boot_base = syscon_regmap_lookup_by_phandle_args(np, "st,syscfg",
289 								1, &ddata->boot_offset);
290 	if (IS_ERR(ddata->boot_base))
291 		return dev_err_probe(dev, PTR_ERR(ddata->boot_base),
292 				     "Boot base not found\n");
293 
294 	err = clk_prepare(ddata->clk);
295 	if (err)
296 		dev_err(dev, "failed to get clock\n");
297 
298 	return err;
299 }
300 
301 static int st_rproc_probe(struct platform_device *pdev)
302 {
303 	struct device *dev = &pdev->dev;
304 	struct st_rproc *ddata;
305 	struct device_node *np = dev->of_node;
306 	struct rproc *rproc;
307 	struct mbox_chan *chan;
308 	int enabled;
309 	int ret, i;
310 
311 	rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
312 	if (!rproc)
313 		return -ENOMEM;
314 
315 	rproc->has_iommu = false;
316 	ddata = rproc->priv;
317 	ddata->config = (struct st_rproc_config *)device_get_match_data(dev);
318 	if (!ddata->config)
319 		return -ENODEV;
320 
321 	platform_set_drvdata(pdev, rproc);
322 
323 	ret = st_rproc_parse_dt(pdev);
324 	if (ret)
325 		return ret;
326 
327 	enabled = st_rproc_state(pdev);
328 	if (enabled < 0) {
329 		ret = enabled;
330 		goto free_clk;
331 	}
332 
333 	if (enabled) {
334 		atomic_inc(&rproc->power);
335 		rproc->state = RPROC_RUNNING;
336 	} else {
337 		clk_set_rate(ddata->clk, ddata->clk_rate);
338 	}
339 
340 	if (of_property_present(np, "mbox-names")) {
341 		ddata->mbox_client_vq0.dev		= dev;
342 		ddata->mbox_client_vq0.tx_done		= NULL;
343 		ddata->mbox_client_vq0.tx_block	= false;
344 		ddata->mbox_client_vq0.knows_txdone	= false;
345 		ddata->mbox_client_vq0.rx_callback	= st_rproc_mbox_callback_vq0;
346 
347 		ddata->mbox_client_vq1.dev		= dev;
348 		ddata->mbox_client_vq1.tx_done		= NULL;
349 		ddata->mbox_client_vq1.tx_block	= false;
350 		ddata->mbox_client_vq1.knows_txdone	= false;
351 		ddata->mbox_client_vq1.rx_callback	= st_rproc_mbox_callback_vq1;
352 
353 		/*
354 		 * To control a co-processor without IPC mechanism.
355 		 * This driver can be used without mbox and rpmsg.
356 		 */
357 		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
358 		if (IS_ERR(chan)) {
359 			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
360 					    "failed to request mbox chan 0\n");
361 			goto free_clk;
362 		}
363 		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;
364 
365 		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
366 		if (IS_ERR(chan)) {
367 			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
368 					    "failed to request mbox chan 0\n");
369 			goto free_mbox;
370 		}
371 		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;
372 
373 		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
374 		if (IS_ERR(chan)) {
375 			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
376 					    "failed to request mbox chan 1\n");
377 			goto free_mbox;
378 		}
379 		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;
380 
381 		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
382 		if (IS_ERR(chan)) {
383 			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
384 					    "failed to request mbox chan 1\n");
385 			goto free_mbox;
386 		}
387 		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;
388 	}
389 
390 	ret = rproc_add(rproc);
391 	if (ret)
392 		goto free_mbox;
393 
394 	return 0;
395 
396 free_mbox:
397 	for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
398 		mbox_free_channel(ddata->mbox_chan[i]);
399 free_clk:
400 	clk_unprepare(ddata->clk);
401 
402 	return ret;
403 }
404 
405 static void st_rproc_remove(struct platform_device *pdev)
406 {
407 	struct rproc *rproc = platform_get_drvdata(pdev);
408 	struct st_rproc *ddata = rproc->priv;
409 	int i;
410 
411 	rproc_del(rproc);
412 
413 	clk_disable_unprepare(ddata->clk);
414 
415 	for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
416 		mbox_free_channel(ddata->mbox_chan[i]);
417 }
418 
419 static struct platform_driver st_rproc_driver = {
420 	.probe = st_rproc_probe,
421 	.remove = st_rproc_remove,
422 	.driver = {
423 		.name = "st-rproc",
424 		.of_match_table = of_match_ptr(st_rproc_match),
425 	},
426 };
427 module_platform_driver(st_rproc_driver);
428 
429 MODULE_DESCRIPTION("ST Remote Processor Control Driver");
430 MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
431 MODULE_LICENSE("GPL v2");
432