aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/include/plat/remoteproc.h57
-rw-r--r--drivers/remoteproc/Kconfig21
-rw-r--r--drivers/remoteproc/Makefile1
-rw-r--r--drivers/remoteproc/omap_remoteproc.c249
-rw-r--r--drivers/remoteproc/omap_remoteproc.h69
5 files changed, 397 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/include/plat/remoteproc.h b/arch/arm/plat-omap/include/plat/remoteproc.h
new file mode 100644
index 000000000000..b10eac89e2e9
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/remoteproc.h
@@ -0,0 +1,57 @@
1/*
2 * Remote Processor - omap-specific bits
3 *
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Copyright (C) 2011 Google, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef _PLAT_REMOTEPROC_H
18#define _PLAT_REMOTEPROC_H
19
20struct rproc_ops;
21struct platform_device;
22
23/*
24 * struct omap_rproc_pdata - omap remoteproc's platform data
25 * @name: the remoteproc's name
26 * @oh_name: omap hwmod device
27 * @oh_name_opt: optional, secondary omap hwmod device
28 * @firmware: name of firmware file to load
29 * @mbox_name: name of omap mailbox device to use with this rproc
30 * @ops: start/stop rproc handlers
31 * @device_enable: omap-specific handler for enabling a device
32 * @device_shutdown: omap-specific handler for shutting down a device
33 */
34struct omap_rproc_pdata {
35 const char *name;
36 const char *oh_name;
37 const char *oh_name_opt;
38 const char *firmware;
39 const char *mbox_name;
40 const struct rproc_ops *ops;
41 int (*device_enable) (struct platform_device *pdev);
42 int (*device_shutdown) (struct platform_device *pdev);
43};
44
45#if defined(CONFIG_OMAP_REMOTEPROC) || defined(CONFIG_OMAP_REMOTEPROC_MODULE)
46
47void __init omap_rproc_reserve_cma(void);
48
49#else
50
51void __init omap_rproc_reserve_cma(void)
52{
53}
54
55#endif
56
57#endif /* _PLAT_REMOTEPROC_H */
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index b250b15c0686..396c97a2661f 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -1,3 +1,24 @@
1# REMOTEPROC gets selected by whoever wants it 1# REMOTEPROC gets selected by whoever wants it
2config REMOTEPROC 2config REMOTEPROC
3 tristate 3 tristate
4
5config OMAP_REMOTEPROC
6 tristate "OMAP remoteproc support"
7 depends on ARCH_OMAP4
8 select OMAP_IOMMU
9 select REMOTEPROC
10 select OMAP_MBOX_FWK
11 select RPMSG
12 default m
13 help
14 Say y here to support OMAP's remote processors (dual M3
15 and DSP on OMAP4) via the remote processor framework.
16
17 Currently only supported on OMAP4.
18
19 Usually you want to say y here, in order to enable multimedia
20 use-cases to run on your platform (multimedia codecs are
21 offloaded to remote DSP processors using this framework).
22
23 It's safe to say n here if you're not interested in multimedia
24 offloading or just want a bare minimum kernel.
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 370dffd54fee..df0897f69e16 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc.o
6remoteproc-y := remoteproc_core.o 6remoteproc-y := remoteproc_core.o
7remoteproc-y += remoteproc_debugfs.o 7remoteproc-y += remoteproc_debugfs.o
8remoteproc-y += remoteproc_rpmsg.o 8remoteproc-y += remoteproc_rpmsg.o
9obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
new file mode 100644
index 000000000000..b49ecbb91ef3
--- /dev/null
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -0,0 +1,249 @@
1/*
2 * OMAP Remote Processor driver
3 *
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Copyright (C) 2011 Google, Inc.
6 *
7 * Ohad Ben-Cohen <ohad@wizery.com>
8 * Brian Swetland <swetland@google.com>
9 * Fernando Guzman Lugo <fernando.lugo@ti.com>
10 * Mark Grosen <mgrosen@ti.com>
11 * Suman Anna <s-anna@ti.com>
12 * Hari Kanigeri <h-kanigeri2@ti.com>
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * version 2 as published by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/err.h>
27#include <linux/platform_device.h>
28#include <linux/dma-mapping.h>
29#include <linux/remoteproc.h>
30
31#include <plat/mailbox.h>
32#include <plat/remoteproc.h>
33
34#include "omap_remoteproc.h"
35#include "remoteproc_internal.h"
36
37/**
38 * struct omap_rproc - omap remote processor state
39 * @mbox: omap mailbox handle
40 * @nb: notifier block that will be invoked on inbound mailbox messages
41 * @rproc: rproc handle
42 */
43struct omap_rproc {
44 struct omap_mbox *mbox;
45 struct notifier_block nb;
46 struct rproc *rproc;
47};
48
49/**
50 * omap_rproc_mbox_callback() - inbound mailbox message handler
51 * @this: notifier block
52 * @index: unused
53 * @data: mailbox payload
54 *
55 * This handler is invoked by omap's mailbox driver whenever a mailbox
56 * message is received. Usually, the mailbox payload simply contains
57 * the index of the virtqueue that is kicked by the remote processor,
58 * and we let remoteproc core handle it.
59 *
60 * In addition to virtqueue indices, we also have some out-of-band values
61 * that indicates different events. Those values are deliberately very
62 * big so they don't coincide with virtqueue indices.
63 */
64static int omap_rproc_mbox_callback(struct notifier_block *this,
65 unsigned long index, void *data)
66{
67 mbox_msg_t msg = (mbox_msg_t) data;
68 struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
69 struct device *dev = oproc->rproc->dev;
70 const char *name = oproc->rproc->name;
71
72 dev_dbg(dev, "mbox msg: 0x%x\n", msg);
73
74 switch (msg) {
75 case RP_MBOX_CRASH:
76 /* just log this for now. later, we'll also do recovery */
77 dev_err(dev, "omap rproc %s crashed\n", name);
78 break;
79 case RP_MBOX_ECHO_REPLY:
80 dev_info(dev, "received echo reply from %s\n", name);
81 break;
82 default:
83 /* ignore vq indices which are too large to be valid */
84 if (msg >= 2) {
85 dev_warn(dev, "invalid mbox msg: 0x%x\n", msg);
86 break;
87 }
88
89 /*
90 * At this point, 'msg' contains the index of the vring
91 * which was just triggered.
92 */
93 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
94 dev_dbg(dev, "no message was found in vqid %d\n", msg);
95 }
96
97 return NOTIFY_DONE;
98}
99
100/* kick a virtqueue */
101static void omap_rproc_kick(struct rproc *rproc, int vqid)
102{
103 struct omap_rproc *oproc = rproc->priv;
104 int ret;
105
106 /* send the index of the triggered virtqueue in the mailbox payload */
107 ret = omap_mbox_msg_send(oproc->mbox, vqid);
108 if (ret)
109 dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret);
110}
111
112/*
113 * Power up the remote processor.
114 *
115 * This function will be invoked only after the firmware for this rproc
116 * was loaded, parsed successfully, and all of its resource requirements
117 * were met.
118 */
119static int omap_rproc_start(struct rproc *rproc)
120{
121 struct omap_rproc *oproc = rproc->priv;
122 struct platform_device *pdev = to_platform_device(rproc->dev);
123 struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
124 int ret;
125
126 oproc->nb.notifier_call = omap_rproc_mbox_callback;
127
128 /* every omap rproc is assigned a mailbox instance for messaging */
129 oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
130 if (IS_ERR(oproc->mbox)) {
131 ret = PTR_ERR(oproc->mbox);
132 dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret);
133 return ret;
134 }
135
136 /*
137 * Ping the remote processor. this is only for sanity-sake;
138 * there is no functional effect whatsoever.
139 *
140 * Note that the reply will _not_ arrive immediately: this message
141 * will wait in the mailbox fifo until the remote processor is booted.
142 */
143 ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
144 if (ret) {
145 dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret);
146 goto put_mbox;
147 }
148
149 ret = pdata->device_enable(pdev);
150 if (ret) {
151 dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret);
152 goto put_mbox;
153 }
154
155 return 0;
156
157put_mbox:
158 omap_mbox_put(oproc->mbox, &oproc->nb);
159 return ret;
160}
161
162/* power off the remote processor */
163static int omap_rproc_stop(struct rproc *rproc)
164{
165 struct platform_device *pdev = to_platform_device(rproc->dev);
166 struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
167 struct omap_rproc *oproc = rproc->priv;
168 int ret;
169
170 ret = pdata->device_shutdown(pdev);
171 if (ret)
172 return ret;
173
174 omap_mbox_put(oproc->mbox, &oproc->nb);
175
176 return 0;
177}
178
179static struct rproc_ops omap_rproc_ops = {
180 .start = omap_rproc_start,
181 .stop = omap_rproc_stop,
182 .kick = omap_rproc_kick,
183};
184
185static int __devinit omap_rproc_probe(struct platform_device *pdev)
186{
187 struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
188 struct omap_rproc *oproc;
189 struct rproc *rproc;
190 int ret;
191
192 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
193 if (ret) {
194 dev_err(pdev->dev.parent, "dma_set_coherent_mask: %d\n", ret);
195 return ret;
196 }
197
198 rproc = rproc_alloc(&pdev->dev, pdata->name, &omap_rproc_ops,
199 pdata->firmware, sizeof(*oproc));
200 if (!rproc)
201 return -ENOMEM;
202
203 oproc = rproc->priv;
204 oproc->rproc = rproc;
205
206 platform_set_drvdata(pdev, rproc);
207
208 ret = rproc_register(rproc);
209 if (ret)
210 goto free_rproc;
211
212 return 0;
213
214free_rproc:
215 rproc_free(rproc);
216 return ret;
217}
218
219static int __devexit omap_rproc_remove(struct platform_device *pdev)
220{
221 struct rproc *rproc = platform_get_drvdata(pdev);
222
223 return rproc_unregister(rproc);
224}
225
226static struct platform_driver omap_rproc_driver = {
227 .probe = omap_rproc_probe,
228 .remove = __devexit_p(omap_rproc_remove),
229 .driver = {
230 .name = "omap-rproc",
231 .owner = THIS_MODULE,
232 },
233};
234
235/* most of the below will go when module_platform_driver is merged */
236static int __init omap_rproc_init(void)
237{
238 return platform_driver_register(&omap_rproc_driver);
239}
240module_init(omap_rproc_init);
241
242static void __exit omap_rproc_exit(void)
243{
244 platform_driver_unregister(&omap_rproc_driver);
245}
246module_exit(omap_rproc_exit);
247
248MODULE_LICENSE("GPL v2");
249MODULE_DESCRIPTION("OMAP Remote Processor control driver");
diff --git a/drivers/remoteproc/omap_remoteproc.h b/drivers/remoteproc/omap_remoteproc.h
new file mode 100644
index 000000000000..f6d2036d383d
--- /dev/null
+++ b/drivers/remoteproc/omap_remoteproc.h
@@ -0,0 +1,69 @@
1/*
2 * Remote processor messaging
3 *
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Copyright (C) 2011 Google, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name Texas Instruments nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef _OMAP_RPMSG_H
36#define _OMAP_RPMSG_H
37
38/*
39 * enum - Predefined Mailbox Messages
40 *
41 * @RP_MBOX_READY: informs the M3's that we're up and running. this is
42 * part of the init sequence sent that the M3 expects to see immediately
43 * after it is booted.
44 *
45 * @RP_MBOX_PENDING_MSG: informs the receiver that there is an inbound
46 * message waiting in its own receive-side vring. please note that currently
47 * this message is optional: alternatively, one can explicitly send the index
48 * of the triggered virtqueue itself. the preferred approach will be decided
49 * as we progress and experiment with those two different approaches.
50 *
51 * @RP_MBOX_CRASH: this message is sent if BIOS crashes
52 *
53 * @RP_MBOX_ECHO_REQUEST: a mailbox-level "ping" message.
54 *
55 * @RP_MBOX_ECHO_REPLY: a mailbox-level reply to a "ping"
56 *
57 * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the
58 * recovery mechanism (to some extent).
59 */
60enum omap_rp_mbox_messages {
61 RP_MBOX_READY = 0xFFFFFF00,
62 RP_MBOX_PENDING_MSG = 0xFFFFFF01,
63 RP_MBOX_CRASH = 0xFFFFFF02,
64 RP_MBOX_ECHO_REQUEST = 0xFFFFFF03,
65 RP_MBOX_ECHO_REPLY = 0xFFFFFF04,
66 RP_MBOX_ABORT_REQUEST = 0xFFFFFF05,
67};
68
69#endif /* _OMAP_RPMSG_H */