2
* Remote Processor machine-specific module for OMAP3
4
* Copyright (C) 2010 Texas Instruments Inc.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* version 2 as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21
#include <linux/kernel.h>
22
#include <linux/clk.h>
23
#include <linux/err.h>
24
#include <linux/platform_device.h>
26
#include <plat/remoteproc.h>
27
#include <plat/dmtimer.h>
29
#include <plat/omap_device.h>
30
#include <plat/omap_hwmod.h>
33
static inline int proc44x_start(struct device *dev, u32 start_addr)
35
struct platform_device *pdev = to_platform_device(dev);
36
struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
37
to_platform_device(dev));
40
/* Enable the Timer that would be used by co-processor for HIB/WD*/
41
if (obj->timer_hib_id >= 0) {
43
omap_dm_timer_request_specific(obj->timer_hib_id);
48
omap_dm_timer_set_int_enable(obj->dmtimer,
49
OMAP_TIMER_INT_OVERFLOW);
50
omap_dm_timer_set_source(obj->dmtimer, OMAP_TIMER_SRC_SYS_CLK);
53
/* Enable the Timer that would be used by co-processor as Clock*/
54
if (obj->timer_clk_id >= 0) {
56
omap_dm_timer_request_specific(obj->timer_clk_id);
57
if (!obj->dmtimer_clk) {
62
omap_dm_timer_set_source(obj->dmtimer_clk,
63
OMAP_TIMER_SRC_SYS_CLK);
66
ret = omap_device_enable(pdev);
70
obj->state = OMAP_RPROC_RUNNING;
74
dev_err(dev, "%s error 0x%x\n", __func__, ret);
78
static inline int proc44x_stop(struct device *dev)
80
struct platform_device *pdev = to_platform_device(dev);
81
struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
82
to_platform_device(dev));
85
if (obj->state == OMAP_RPROC_RUNNING) {
86
ret = omap_device_shutdown(pdev);
88
dev_err(dev, "%s err 0x%x\n", __func__, ret);
92
omap_dm_timer_free(obj->dmtimer);
96
if (obj->dmtimer_clk) {
97
omap_dm_timer_free(obj->dmtimer_clk);
98
obj->dmtimer_clk = NULL;
101
obj->state = OMAP_RPROC_STOPPED;
105
static inline int proc44x_sleep(struct device *dev)
107
struct platform_device *pdev = to_platform_device(dev);
108
struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
109
to_platform_device(dev));
112
if (obj->state == OMAP_RPROC_RUNNING) {
113
ret = omap_device_shutdown(pdev);
115
dev_err(dev, "%s err 0x%x\n", __func__, ret);
118
omap_dm_timer_stop(obj->dmtimer);
119
if (obj->dmtimer_clk)
120
omap_dm_timer_stop(obj->dmtimer_clk);
123
obj->state = OMAP_RPROC_HIBERNATING;
127
static inline int proc44x_wakeup(struct device *dev)
129
struct platform_device *pdev = to_platform_device(dev);
130
struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
131
to_platform_device(dev));
135
omap_dm_timer_start(obj->dmtimer);
136
if (obj->dmtimer_clk)
137
omap_dm_timer_start(obj->dmtimer_clk);
139
ret = omap_device_enable(pdev);
143
obj->state = OMAP_RPROC_RUNNING;
147
dev_err(dev, "%s error 0x%x\n", __func__, ret);
152
static inline int omap4_rproc_get_state(struct device *dev)
154
struct platform_device *pdev = to_platform_device(dev);
155
struct omap_device *odev = to_omap_device(pdev);
160
static struct omap_rproc_ops omap4_ducati0_ops = {
161
.start = proc44x_start,
162
.stop = proc44x_stop,
163
.sleep = proc44x_sleep,
164
.wakeup = proc44x_wakeup,
165
.get_state = omap4_rproc_get_state,
168
static struct omap_rproc_ops omap4_ducati1_ops = {
169
.start = proc44x_start,
170
.stop = proc44x_stop,
171
.sleep = proc44x_sleep,
172
.wakeup = proc44x_wakeup,
173
.get_state = omap4_rproc_get_state,
176
static struct omap_rproc_ops omap4_tesla_ops = {
177
.start = proc44x_start,
178
.stop = proc44x_stop,
179
.sleep = proc44x_sleep,
180
.wakeup = proc44x_wakeup,
181
.get_state = omap4_rproc_get_state,
184
static struct omap_rproc_platform_data omap4_rproc_data[] = {
187
.ops = &omap4_tesla_ops,
193
.name = "ducati-proc0",
194
.ops = &omap4_ducati0_ops,
197
#ifdef CONFIG_SYSLINK_IPU_SELF_HIBERNATION
204
.name = "ducati-proc1",
205
.ops = &omap4_ducati1_ops,
213
static struct omap_device_pm_latency omap_rproc_latency[] = {
215
.deactivate_func = omap_device_idle_hwmods,
216
.activate_func = omap_device_enable_hwmods,
222
struct omap_rproc_platform_data *omap4_get_rproc_data(void)
224
return omap4_rproc_data;
228
#define NR_RPROC_DEVICES ARRAY_SIZE(omap4_rproc_data)
230
static struct omap_device *omap4_rproc_pdev[NR_RPROC_OMAP4_DEVICES];
232
static int __init omap4_rproc_init(void)
234
struct omap_hwmod *oh;
235
struct omap_device_pm_latency *ohl;
236
char *oh_name, *pdev_name;
239
struct omap_rproc_platform_data *rproc_data;
241
pdev_name = "omap-remoteproc";
242
ohl = omap_rproc_latency;
243
ohl_cnt = ARRAY_SIZE(omap_rproc_latency);
246
rproc_data = omap4_get_rproc_data();
247
rproc_data_size = NR_RPROC_OMAP4_DEVICES;
249
for (i = 0; i < rproc_data_size; i++) {
250
oh_name = rproc_data[i].oh_name;
251
oh = omap_hwmod_lookup(oh_name);
253
pr_err("%s: could not look up %s\n", __func__, oh_name);
256
omap4_rproc_pdev[i] = omap_device_build(pdev_name, i, oh,
258
sizeof(struct omap_rproc_platform_data),
259
ohl, ohl_cnt, false);
260
WARN(IS_ERR(omap4_rproc_pdev[i]), "Could not build omap_device"
261
"for %s %s\n", pdev_name, oh_name);
265
module_init(omap4_rproc_init);
267
static void __exit omap4_rproc_exit(void)
271
module_exit(omap4_rproc_exit);
273
MODULE_LICENSE("GPL v2");
274
MODULE_DESCRIPTION("OMAP4 Remote Processor module");
275
MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");
276
MODULE_AUTHOR("Hari Kanigeri <h-kanigeri2@ti.com>");