aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoic Pallardy <loic.pallardy@st.com>2017-01-31 07:35:54 -0500
committerBjorn Andersson <bjorn.andersson@linaro.org>2017-02-06 16:10:12 -0500
commit231c8dfd1a9ff530869e1327ba4168dbe592f3f9 (patch)
tree9d94a97973571c838159cbd8bb70e40c692244d2
parent3e49ecf6b49c31b70235d260b957376c00265c1e (diff)
remoteproc: st: add virtio communication support
This patch provides virtio communication support based on mailbox for ST co-processors. Signed-off-by: Loic Pallardy <loic.pallardy@st.com> Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--drivers/remoteproc/Kconfig3
-rw-r--r--drivers/remoteproc/st_remoteproc.c113
2 files changed, 114 insertions, 2 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 402de7089302..65f86bc24c07 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -118,6 +118,9 @@ config ST_REMOTEPROC
118 tristate "ST remoteproc support" 118 tristate "ST remoteproc support"
119 depends on ARCH_STI 119 depends on ARCH_STI
120 depends on REMOTEPROC 120 depends on REMOTEPROC
121 select MAILBOX
122 select STI_MBOX
123 select RPMSG_VIRTIO
121 help 124 help
122 Say y here to support ST's adjunct processors via the remote 125 Say y here to support ST's adjunct processors via the remote
123 processor framework. 126 processor framework.
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index 1468ba213811..d534bf23dc56 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -15,6 +15,7 @@
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/mailbox_client.h>
18#include <linux/mfd/syscon.h> 19#include <linux/mfd/syscon.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/of.h> 21#include <linux/of.h>
@@ -25,6 +26,16 @@
25#include <linux/remoteproc.h> 26#include <linux/remoteproc.h>
26#include <linux/reset.h> 27#include <linux/reset.h>
27 28
29#include "remoteproc_internal.h"
30
31#define ST_RPROC_VQ0 0
32#define ST_RPROC_VQ1 1
33#define ST_RPROC_MAX_VRING 2
34
35#define MBOX_RX 0
36#define MBOX_TX 1
37#define MBOX_MAX 2
38
28struct st_rproc_config { 39struct st_rproc_config {
29 bool sw_reset; 40 bool sw_reset;
30 bool pwr_reset; 41 bool pwr_reset;
@@ -39,8 +50,47 @@ struct st_rproc {
39 u32 clk_rate; 50 u32 clk_rate;
40 struct regmap *boot_base; 51 struct regmap *boot_base;
41 u32 boot_offset; 52 u32 boot_offset;
53 struct mbox_chan *mbox_chan[ST_RPROC_MAX_VRING * MBOX_MAX];
54 struct mbox_client mbox_client_vq0;
55 struct mbox_client mbox_client_vq1;
42}; 56};
43 57
58static void st_rproc_mbox_callback(struct device *dev, u32 msg)
59{
60 struct rproc *rproc = dev_get_drvdata(dev);
61
62 if (rproc_vq_interrupt(rproc, msg) == IRQ_NONE)
63 dev_dbg(dev, "no message was found in vqid %d\n", msg);
64}
65
66static
67void st_rproc_mbox_callback_vq0(struct mbox_client *mbox_client, void *data)
68{
69 st_rproc_mbox_callback(mbox_client->dev, 0);
70}
71
72static
73void st_rproc_mbox_callback_vq1(struct mbox_client *mbox_client, void *data)
74{
75 st_rproc_mbox_callback(mbox_client->dev, 1);
76}
77
78static void st_rproc_kick(struct rproc *rproc, int vqid)
79{
80 struct st_rproc *ddata = rproc->priv;
81 struct device *dev = rproc->dev.parent;
82 int ret;
83
84 /* send the index of the triggered virtqueue in the mailbox payload */
85 if (WARN_ON(vqid >= ST_RPROC_MAX_VRING))
86 return;
87
88 ret = mbox_send_message(ddata->mbox_chan[vqid * MBOX_MAX + MBOX_TX],
89 (void *)&vqid);
90 if (ret < 0)
91 dev_err(dev, "failed to send message via mbox: %d\n", ret);
92}
93
44static int st_rproc_start(struct rproc *rproc) 94static int st_rproc_start(struct rproc *rproc)
45{ 95{
46 struct st_rproc *ddata = rproc->priv; 96 struct st_rproc *ddata = rproc->priv;
@@ -108,6 +158,7 @@ static int st_rproc_stop(struct rproc *rproc)
108} 158}
109 159
110static const struct rproc_ops st_rproc_ops = { 160static const struct rproc_ops st_rproc_ops = {
161 .kick = st_rproc_kick,
111 .start = st_rproc_start, 162 .start = st_rproc_start,
112 .stop = st_rproc_stop, 163 .stop = st_rproc_stop,
113}; 164};
@@ -221,8 +272,9 @@ static int st_rproc_probe(struct platform_device *pdev)
221 struct st_rproc *ddata; 272 struct st_rproc *ddata;
222 struct device_node *np = dev->of_node; 273 struct device_node *np = dev->of_node;
223 struct rproc *rproc; 274 struct rproc *rproc;
275 struct mbox_chan *chan;
224 int enabled; 276 int enabled;
225 int ret; 277 int ret, i;
226 278
227 match = of_match_device(st_rproc_match, dev); 279 match = of_match_device(st_rproc_match, dev);
228 if (!match || !match->data) { 280 if (!match || !match->data) {
@@ -257,12 +309,65 @@ static int st_rproc_probe(struct platform_device *pdev)
257 clk_set_rate(ddata->clk, ddata->clk_rate); 309 clk_set_rate(ddata->clk, ddata->clk_rate);
258 } 310 }
259 311
312 if (of_get_property(np, "mbox-names", NULL)) {
313 ddata->mbox_client_vq0.dev = dev;
314 ddata->mbox_client_vq0.tx_done = NULL;
315 ddata->mbox_client_vq0.tx_block = false;
316 ddata->mbox_client_vq0.knows_txdone = false;
317 ddata->mbox_client_vq0.rx_callback = st_rproc_mbox_callback_vq0;
318
319 ddata->mbox_client_vq1.dev = dev;
320 ddata->mbox_client_vq1.tx_done = NULL;
321 ddata->mbox_client_vq1.tx_block = false;
322 ddata->mbox_client_vq1.knows_txdone = false;
323 ddata->mbox_client_vq1.rx_callback = st_rproc_mbox_callback_vq1;
324
325 /*
326 * To control a co-processor without IPC mechanism.
327 * This driver can be used without mbox and rpmsg.
328 */
329 chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
330 if (IS_ERR(chan)) {
331 dev_err(&rproc->dev, "failed to request mbox chan 0\n");
332 ret = PTR_ERR(chan);
333 goto free_clk;
334 }
335 ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;
336
337 chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
338 if (IS_ERR(chan)) {
339 dev_err(&rproc->dev, "failed to request mbox chan 0\n");
340 ret = PTR_ERR(chan);
341 goto free_mbox;
342 }
343 ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;
344
345 chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
346 if (IS_ERR(chan)) {
347 dev_err(&rproc->dev, "failed to request mbox chan 1\n");
348 ret = PTR_ERR(chan);
349 goto free_mbox;
350 }
351 ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;
352
353 chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
354 if (IS_ERR(chan)) {
355 dev_err(&rproc->dev, "failed to request mbox chan 1\n");
356 ret = PTR_ERR(chan);
357 goto free_mbox;
358 }
359 ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;
360 }
361
260 ret = rproc_add(rproc); 362 ret = rproc_add(rproc);
261 if (ret) 363 if (ret)
262 goto free_clk; 364 goto free_mbox;
263 365
264 return 0; 366 return 0;
265 367
368free_mbox:
369 for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
370 mbox_free_channel(ddata->mbox_chan[i]);
266free_clk: 371free_clk:
267 clk_unprepare(ddata->clk); 372 clk_unprepare(ddata->clk);
268free_rproc: 373free_rproc:
@@ -274,6 +379,7 @@ static int st_rproc_remove(struct platform_device *pdev)
274{ 379{
275 struct rproc *rproc = platform_get_drvdata(pdev); 380 struct rproc *rproc = platform_get_drvdata(pdev);
276 struct st_rproc *ddata = rproc->priv; 381 struct st_rproc *ddata = rproc->priv;
382 int i;
277 383
278 rproc_del(rproc); 384 rproc_del(rproc);
279 385
@@ -281,6 +387,9 @@ static int st_rproc_remove(struct platform_device *pdev)
281 387
282 of_reserved_mem_device_release(&pdev->dev); 388 of_reserved_mem_device_release(&pdev->dev);
283 389
390 for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
391 mbox_free_channel(ddata->mbox_chan[i]);
392
284 rproc_free(rproc); 393 rproc_free(rproc);
285 394
286 return 0; 395 return 0;