File Index
Files and directories
Sign in
FILE

st_remoteproc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/remoteproc/st_remoteproc.c C
  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
 36struct st_rproc_config {
 37	bool			sw_reset;
 38	bool			pwr_reset;
 39	unsigned long		bootaddr_mask;
 40};
 41
 42struct 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
 55static 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
 63static
 64void st_rproc_mbox_callback_vq0(struct mbox_client *mbox_client, void *data)
 65{
 66	st_rproc_mbox_callback(mbox_client->dev, 0);
 67}
 68
 69static
 70void st_rproc_mbox_callback_vq1(struct mbox_client *mbox_client, void *data)
 71{
 72	st_rproc_mbox_callback(mbox_client->dev, 1);
 73}
 74
 75static 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
 91static int st_rproc_mem_alloc(struct rproc *rproc,
 92			      struct rproc_mem_entry *mem)
 93{
 94	struct device *dev = rproc->dev.parent;
 95	void *va;
 96
 97	va = ioremap_wc(mem->dma, mem->len);
 98	if (!va) {
 99		dev_err(dev, "Unable to map memory region: %pa+%zx\n",
100			&mem->dma, mem->len);
101		return -ENOMEM;
102	}
103
104	/* Update memory entry va */
105	mem->va = va;
106
107	return 0;
108}
109
110static int st_rproc_mem_release(struct rproc *rproc,
111				struct rproc_mem_entry *mem)
112{
113	iounmap(mem->va);
114
115	return 0;
116}
117
118static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
119{
120	struct device *dev = rproc->dev.parent;
121	struct device_node *np = dev->of_node;
122	struct rproc_mem_entry *mem;
123	int entries;
124
125	entries = of_reserved_mem_region_count(np);
126
127	for (int index = 0; index < entries; index++) {
128		struct resource res;
129		int ret;
130
131		ret = of_reserved_mem_region_to_resource(np, index, &res);
132		if (ret)
133			return ret;
134
135		/*  No need to map vdev buffer */
136		if (!strstarts(res.name, "vdev0buffer")) {
137			/* Register memory region */
138			mem = rproc_mem_entry_init(dev, NULL,
139						   (dma_addr_t)res.start,
140						   resource_size(&res), res.start,
141						   st_rproc_mem_alloc,
142						   st_rproc_mem_release,
143						   "%.*s",
144						   strchrnul(res.name, '@') - res.name,
145						   res.name);
146		} else {
147			/* Register reserved memory for vdev buffer allocation */
148			mem = rproc_of_resm_mem_entry_init(dev, index,
149							   resource_size(&res),
150							   res.start,
151							   "vdev0buffer");
152		}
153
154		if (!mem)
155			return -ENOMEM;
156
157		rproc_add_carveout(rproc, mem);
158	}
159
160	return rproc_elf_load_rsc_table(rproc, fw);
161}
162
163static int st_rproc_start(struct rproc *rproc)
164{
165	struct st_rproc *ddata = rproc->priv;
166	int err;
167
168	regmap_update_bits(ddata->boot_base, ddata->boot_offset,
169			   ddata->config->bootaddr_mask, rproc->bootaddr);
170
171	err = clk_enable(ddata->clk);
172	if (err) {
173		dev_err(&rproc->dev, "Failed to enable clock\n");
174		return err;
175	}
176
177	if (ddata->config->sw_reset) {
178		err = reset_control_deassert(ddata->sw_reset);
179		if (err) {
180			dev_err(&rproc->dev, "Failed to deassert S/W Reset\n");
181			goto sw_reset_fail;
182		}
183	}
184
185	if (ddata->config->pwr_reset) {
186		err = reset_control_deassert(ddata->pwr_reset);
187		if (err) {
188			dev_err(&rproc->dev, "Failed to deassert Power Reset\n");
189			goto pwr_reset_fail;
190		}
191	}
192
193	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
194
195	return 0;
196
197
198pwr_reset_fail:
199	if (ddata->config->pwr_reset)
200		reset_control_assert(ddata->sw_reset);
201sw_reset_fail:
202	clk_disable(ddata->clk);
203
204	return err;
205}
206
207static int st_rproc_stop(struct rproc *rproc)
208{
209	struct st_rproc *ddata = rproc->priv;
210	int sw_err = 0, pwr_err = 0;
211
212	if (ddata->config->sw_reset) {
213		sw_err = reset_control_assert(ddata->sw_reset);
214		if (sw_err)
215			dev_err(&rproc->dev, "Failed to assert S/W Reset\n");
216	}
217
218	if (ddata->config->pwr_reset) {
219		pwr_err = reset_control_assert(ddata->pwr_reset);
220		if (pwr_err)
221			dev_err(&rproc->dev, "Failed to assert Power Reset\n");
222	}
223
224	clk_disable(ddata->clk);
225
226	return sw_err ?: pwr_err;
227}
228
229static const struct rproc_ops st_rproc_ops = {
230	.kick			= st_rproc_kick,
231	.start			= st_rproc_start,
232	.stop			= st_rproc_stop,
233	.parse_fw		= st_rproc_parse_fw,
234	.load			= rproc_elf_load_segments,
235	.find_loaded_rsc_table	= rproc_elf_find_loaded_rsc_table,
236	.sanity_check		= rproc_elf_sanity_check,
237	.get_boot_addr		= rproc_elf_get_boot_addr,
238};
239
240/*
241 * Fetch state of the processor: 0 is off, 1 is on.
242 */
243static int st_rproc_state(struct platform_device *pdev)
244{
245	struct rproc *rproc = platform_get_drvdata(pdev);
246	struct st_rproc *ddata = rproc->priv;
247	int reset_sw = 0, reset_pwr = 0;
248
249	if (ddata->config->sw_reset)
250		reset_sw = reset_control_status(ddata->sw_reset);
251
252	if (ddata->config->pwr_reset)
253		reset_pwr = reset_control_status(ddata->pwr_reset);
254
255	if (reset_sw < 0 || reset_pwr < 0)
256		return -EINVAL;
257
258	return !reset_sw && !reset_pwr;
259}
260
261static const struct st_rproc_config st40_rproc_cfg = {
262	.sw_reset = true,
263	.pwr_reset = true,
264	.bootaddr_mask = GENMASK(28, 1),
265};
266
267static const struct st_rproc_config st231_rproc_cfg = {
268	.sw_reset = true,
269	.pwr_reset = false,
270	.bootaddr_mask = GENMASK(31, 6),
271};
272
273static const struct of_device_id st_rproc_match[] = {
274	{ .compatible = "st,st40-rproc", .data = &st40_rproc_cfg },
275	{ .compatible = "st,st231-rproc", .data = &st231_rproc_cfg },
276	{},
277};
278MODULE_DEVICE_TABLE(of, st_rproc_match);
279
280static int st_rproc_parse_dt(struct platform_device *pdev)
281{
282	struct device *dev = &pdev->dev;
283	struct rproc *rproc = platform_get_drvdata(pdev);
284	struct st_rproc *ddata = rproc->priv;
285	struct device_node *np = dev->of_node;
286	int err;
287
288	if (ddata->config->sw_reset) {
289		ddata->sw_reset = devm_reset_control_get_exclusive(dev,
290								   "sw_reset");
291		if (IS_ERR(ddata->sw_reset))
292			return dev_err_probe(dev, PTR_ERR(ddata->sw_reset),
293					     "Failed to get S/W Reset\n");
294	}
295
296	if (ddata->config->pwr_reset) {
297		ddata->pwr_reset = devm_reset_control_get_exclusive(dev,
298								    "pwr_reset");
299		if (IS_ERR(ddata->pwr_reset))
300			return dev_err_probe(dev, PTR_ERR(ddata->pwr_reset),
301					     "Failed to get Power Reset\n");
302	}
303
304	ddata->clk = devm_clk_get(dev, NULL);
305	if (IS_ERR(ddata->clk))
306		return dev_err_probe(dev, PTR_ERR(ddata->clk),
307				     "Failed to get clock\n");
308
309	err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate);
310	if (err) {
311		dev_err(dev, "failed to get clock frequency\n");
312		return err;
313	}
314
315	ddata->boot_base = syscon_regmap_lookup_by_phandle_args(np, "st,syscfg",
316								1, &ddata->boot_offset);
317	if (IS_ERR(ddata->boot_base))
318		return dev_err_probe(dev, PTR_ERR(ddata->boot_base),
319				     "Boot base not found\n");
320
321	err = clk_prepare(ddata->clk);
322	if (err)
323		dev_err(dev, "failed to get clock\n");
324
325	return err;
326}
327
328static int st_rproc_probe(struct platform_device *pdev)
329{
330	struct device *dev = &pdev->dev;
331	struct st_rproc *ddata;
332	struct device_node *np = dev->of_node;
333	struct rproc *rproc;
334	struct mbox_chan *chan;
335	int enabled;
336	int ret, i;
337
338	rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
339	if (!rproc)
340		return -ENOMEM;
341
342	rproc->has_iommu = false;
343	ddata = rproc->priv;
344	ddata->config = (struct st_rproc_config *)device_get_match_data(dev);
345	if (!ddata->config)
346		return -ENODEV;
347
348	platform_set_drvdata(pdev, rproc);
349
350	ret = st_rproc_parse_dt(pdev);
351	if (ret)
352		return ret;
353
354	enabled = st_rproc_state(pdev);
355	if (enabled < 0) {
356		ret = enabled;
357		goto free_clk;
358	}
359
360	if (enabled) {
361		atomic_inc(&rproc->power);
362		rproc->state = RPROC_RUNNING;
363	} else {
364		clk_set_rate(ddata->clk, ddata->clk_rate);
365	}
366
367	if (of_property_present(np, "mbox-names")) {
368		ddata->mbox_client_vq0.dev		= dev;
369		ddata->mbox_client_vq0.tx_done		= NULL;
370		ddata->mbox_client_vq0.tx_block	= false;
371		ddata->mbox_client_vq0.knows_txdone	= false;
372		ddata->mbox_client_vq0.rx_callback	= st_rproc_mbox_callback_vq0;
373
374		ddata->mbox_client_vq1.dev		= dev;
375		ddata->mbox_client_vq1.tx_done		= NULL;
376		ddata->mbox_client_vq1.tx_block	= false;
377		ddata->mbox_client_vq1.knows_txdone	= false;
378		ddata->mbox_client_vq1.rx_callback	= st_rproc_mbox_callback_vq1;
379
380		/*
381		 * To control a co-processor without IPC mechanism.
382		 * This driver can be used without mbox and rpmsg.
383		 */
384		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
385		if (IS_ERR(chan)) {
386			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
387					    "failed to request mbox chan 0\n");
388			goto free_clk;
389		}
390		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;
391
392		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
393		if (IS_ERR(chan)) {
394			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
395					    "failed to request mbox chan 0\n");
396			goto free_mbox;
397		}
398		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;
399
400		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
401		if (IS_ERR(chan)) {
402			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
403					    "failed to request mbox chan 1\n");
404			goto free_mbox;
405		}
406		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;
407
408		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
409		if (IS_ERR(chan)) {
410			ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
411					    "failed to request mbox chan 1\n");
412			goto free_mbox;
413		}
414		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;
415	}
416
417	ret = rproc_add(rproc);
418	if (ret)
419		goto free_mbox;
420
421	return 0;
422
423free_mbox:
424	for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
425		mbox_free_channel(ddata->mbox_chan[i]);
426free_clk:
427	clk_unprepare(ddata->clk);
428
429	return ret;
430}
431
432static void st_rproc_remove(struct platform_device *pdev)
433{
434	struct rproc *rproc = platform_get_drvdata(pdev);
435	struct st_rproc *ddata = rproc->priv;
436	int i;
437
438	rproc_del(rproc);
439
440	clk_disable_unprepare(ddata->clk);
441
442	for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
443		mbox_free_channel(ddata->mbox_chan[i]);
444}
445
446static struct platform_driver st_rproc_driver = {
447	.probe = st_rproc_probe,
448	.remove = st_rproc_remove,
449	.driver = {
450		.name = "st-rproc",
451		.of_match_table = of_match_ptr(st_rproc_match),
452	},
453};
454module_platform_driver(st_rproc_driver);
455
456MODULE_DESCRIPTION("ST Remote Processor Control Driver");
457MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
458MODULE_LICENSE("GPL v2");
~/ Read-only file preview.