Skip to content

Commit 34ed5a3

Browse files
committed
remoteproc/omap: add a remoteproc driver for OMAP4
Add a remoteproc driver for OMAP4, so we can boot the dual-M3 and and DSP subsystems. Use the omap_device_* API to control the hardware state, and utilize the OMAP mailbox to interrupt the remote processor when a new message is pending (the mailbox payload is used to tell it which virtqueue was the message placed in). Conversely, when an inbound mailbox message arrives, tell the remoteproc core which virtqueue is triggered. Later we will also use the mailbox payload to signal omap-specific events like remote crashes (which will be used to trigger remoteproc recovery) and power management transitions. At that point we will also extend the remoteproc core to support this. Based on (but now quite far from) work done by Fernando Guzman Lugo <[email protected]> and Hari Kanigeri <[email protected]>. Designed with Brian Swetland <[email protected]>. Signed-off-by: Ohad Ben-Cohen <[email protected]> Acked-by: Tony Lindgren <[email protected]> Cc: Brian Swetland <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Grant Likely <[email protected]> Cc: Russell King <[email protected]> Cc: Rusty Russell <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Greg KH <[email protected]> Cc: Stephen Boyd <[email protected]>
1 parent ac8954a commit 34ed5a3

File tree

5 files changed

+397
-0
lines changed

5 files changed

+397
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
20+
struct rproc_ops;
21+
struct 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+
*/
34+
struct 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+
47+
void __init omap_rproc_reserve_cma(void);
48+
49+
#else
50+
51+
void __init omap_rproc_reserve_cma(void)
52+
{
53+
}
54+
55+
#endif
56+
57+
#endif /* _PLAT_REMOTEPROC_H */

drivers/remoteproc/Kconfig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
11
# REMOTEPROC gets selected by whoever wants it
22
config REMOTEPROC
33
tristate
4+
5+
config 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.

drivers/remoteproc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc.o
66
remoteproc-y := remoteproc_core.o
77
remoteproc-y += remoteproc_debugfs.o
88
remoteproc-y += remoteproc_rpmsg.o
9+
obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o

drivers/remoteproc/omap_remoteproc.c

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 <[email protected]>
8+
* Brian Swetland <[email protected]>
9+
* Fernando Guzman Lugo <[email protected]>
10+
* Mark Grosen <[email protected]>
11+
* Suman Anna <[email protected]>
12+
* Hari Kanigeri <[email protected]>
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+
*/
43+
struct 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+
*/
64+
static 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 */
101+
static 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+
*/
119+
static 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+
157+
put_mbox:
158+
omap_mbox_put(oproc->mbox, &oproc->nb);
159+
return ret;
160+
}
161+
162+
/* power off the remote processor */
163+
static 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+
179+
static struct rproc_ops omap_rproc_ops = {
180+
.start = omap_rproc_start,
181+
.stop = omap_rproc_stop,
182+
.kick = omap_rproc_kick,
183+
};
184+
185+
static 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+
214+
free_rproc:
215+
rproc_free(rproc);
216+
return ret;
217+
}
218+
219+
static 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+
226+
static 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 */
236+
static int __init omap_rproc_init(void)
237+
{
238+
return platform_driver_register(&omap_rproc_driver);
239+
}
240+
module_init(omap_rproc_init);
241+
242+
static void __exit omap_rproc_exit(void)
243+
{
244+
platform_driver_unregister(&omap_rproc_driver);
245+
}
246+
module_exit(omap_rproc_exit);
247+
248+
MODULE_LICENSE("GPL v2");
249+
MODULE_DESCRIPTION("OMAP Remote Processor control driver");

0 commit comments

Comments
 (0)