summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngela Stegmaier <angelabaker@ti.com>2010-09-09 15:32:20 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-09-09 18:22:32 -0500
commitaf622912c97a4953e097ca3037fa52ea6d905a30 (patch)
tree254b6f5c38289e3133189b7b819dd52debce82a6
parent2b921ffa3dfd74daf5284021c25f002da2813e3f (diff)
omap:remoteproc - Add hibernating state
This patch adds a third state called hibernating state. This state is set when sleep is called to remoteproc. This patch also adds two new functions called sleep and wakeup. Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
-rw-r--r--arch/arm/mach-omap2/remoteproc44xx.c71
-rw-r--r--arch/arm/plat-omap/include/plat/remoteproc.h5
-rw-r--r--arch/arm/plat-omap/remoteproc.c48
3 files changed, 117 insertions, 7 deletions
diff --git a/arch/arm/mach-omap2/remoteproc44xx.c b/arch/arm/mach-omap2/remoteproc44xx.c
index e752380e531c..b56ea8595465 100644
--- a/arch/arm/mach-omap2/remoteproc44xx.c
+++ b/arch/arm/mach-omap2/remoteproc44xx.c
@@ -69,18 +69,71 @@ static inline int proc44x_stop(struct device *dev)
to_platform_device(dev));
int ret = 0;
- ret = omap_device_shutdown(pdev);
- if (ret)
- dev_err(dev, "%s err 0x%x\n", __func__, ret);
+ if (obj->state == OMAP_RPROC_RUNNING) {
+ ret = omap_device_shutdown(pdev);
+ if (ret)
+ dev_err(dev, "%s err 0x%x\n", __func__, ret);
+
+ if (!strcmp(obj->name, "tesla")) {
+ dev_info(dev, "disable GPTIMER5\n");
+ cm_write_mod_reg(ABE_GPTIMER_MODULE_DISABLE,
+ OMAP4430_CM1_ABE_MOD,
+ OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET);
+ }
+ }
+
+ obj->state = OMAP_RPROC_STOPPED;
+ return ret;
+}
+
+static inline int proc44x_sleep(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
+ to_platform_device(dev));
+ int ret = 0;
+
+ if (obj->state == OMAP_RPROC_RUNNING) {
+ ret = omap_device_shutdown(pdev);
+ if (ret)
+ dev_err(dev, "%s err 0x%x\n", __func__, ret);
+
+ if (!strcmp(obj->name, "tesla")) {
+ dev_info(dev, "disable GPTIMER5\n");
+ cm_write_mod_reg(ABE_GPTIMER_MODULE_DISABLE,
+ OMAP4430_CM1_ABE_MOD,
+ OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET);
+ }
+ }
+
+ obj->state = OMAP_RPROC_HIBERNATING;
+ return ret;
+}
+
+static inline int proc44x_wakeup(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_rproc *obj = (struct omap_rproc *)platform_get_drvdata(
+ to_platform_device(dev));
+ int ret = 0;
if (!strcmp(obj->name, "tesla")) {
- dev_info(dev, "disable GPTIMER5\n");
- cm_write_mod_reg(ABE_GPTIMER_MODULE_DISABLE,
+ dev_info(dev, "Enable GPTIMER5 for Tesla BIOS Clock\n");
+ /* Enable the GPTIMER5 clock */
+ cm_write_mod_reg(ABE_GPTIMER_MODULE_ENABLE,
OMAP4430_CM1_ABE_MOD,
OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET);
}
- obj->state = OMAP_RPROC_STOPPED;
+ ret = omap_device_enable(pdev);
+ if (ret)
+ goto err_start;
+
+ obj->state = OMAP_RPROC_RUNNING;
+ return 0;
+
+err_start:
+ dev_err(dev, "%s error 0x%x\n", __func__, ret);
return ret;
}
@@ -96,18 +149,24 @@ static inline int omap4_rproc_get_state(struct device *dev)
static struct omap_rproc_ops omap4_ducati0_ops = {
.start = proc44x_start,
.stop = proc44x_stop,
+ .sleep = proc44x_sleep,
+ .wakeup = proc44x_wakeup,
.get_state = omap4_rproc_get_state,
};
static struct omap_rproc_ops omap4_ducati1_ops = {
.start = proc44x_start,
.stop = proc44x_stop,
+ .sleep = proc44x_sleep,
+ .wakeup = proc44x_wakeup,
.get_state = omap4_rproc_get_state,
};
static struct omap_rproc_ops omap4_tesla_ops = {
.start = proc44x_start,
.stop = proc44x_stop,
+ .sleep = proc44x_sleep,
+ .wakeup = proc44x_wakeup,
.get_state = omap4_rproc_get_state,
};
diff --git a/arch/arm/plat-omap/include/plat/remoteproc.h b/arch/arm/plat-omap/include/plat/remoteproc.h
index a49c0ff3c043..1237434af0e6 100644
--- a/arch/arm/plat-omap/include/plat/remoteproc.h
+++ b/arch/arm/plat-omap/include/plat/remoteproc.h
@@ -41,6 +41,8 @@ struct omap_rproc;
struct omap_rproc_ops {
int (*start)(struct device *dev, u32 start_addr);
int (*stop)(struct device *dev);
+ int (*sleep)(struct device *dev);
+ int (*wakeup)(struct device *dev);
int (*get_state)(struct device *dev);
};
@@ -60,6 +62,7 @@ enum {
enum {
OMAP_RPROC_STOPPED,
OMAP_RPROC_RUNNING,
+ OMAP_RPROC_HIBERNATING,
};
struct omap_rproc_platform_data {
@@ -85,6 +88,8 @@ struct omap_rproc_start_args {
extern int rproc_start(struct omap_rproc *rproc, const void __user *arg);
extern int rproc_stop(struct omap_rproc *rproc);
+extern int rproc_sleep(struct omap_rproc *rproc);
+extern int rproc_wakeup(struct omap_rproc *rproc);
extern int omap_rproc_register_notifier(struct omap_rproc *rproc,
struct notifier_block *nb);
diff --git a/arch/arm/plat-omap/remoteproc.c b/arch/arm/plat-omap/remoteproc.c
index c69e5d023016..f387a71a2edd 100644
--- a/arch/arm/plat-omap/remoteproc.c
+++ b/arch/arm/plat-omap/remoteproc.c
@@ -102,6 +102,52 @@ int rproc_stop(struct omap_rproc *rproc)
}
EXPORT_SYMBOL_GPL(rproc_stop);
+int rproc_sleep(struct omap_rproc *rproc)
+{
+ int ret;
+ struct omap_rproc_platform_data *pdata;
+ if (!rproc->dev)
+ return -EINVAL;
+
+ pdata = rproc->dev->platform_data;
+ if (!pdata->ops)
+ return -EINVAL;
+
+ ret = mutex_lock_interruptible(&rproc->lock);
+ if (ret)
+ return ret;
+
+ ret = pdata->ops->sleep(rproc->dev);
+
+ mutex_unlock(&rproc->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_sleep);
+
+int rproc_wakeup(struct omap_rproc *rproc)
+{
+ int ret;
+ struct omap_rproc_platform_data *pdata;
+
+ if (!rproc->dev)
+ return -EINVAL;
+
+ pdata = rproc->dev->platform_data;
+ if (!pdata->ops)
+ return -EINVAL;
+
+ ret = mutex_lock_interruptible(&rproc->lock);
+ if (ret)
+ return ret;
+
+ ret = pdata->ops->wakeup(rproc->dev);
+
+ mutex_unlock(&rproc->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rproc_wakeup);
static inline int rproc_get_state(struct omap_rproc *rproc)
{
@@ -172,7 +218,7 @@ static int omap_rproc_release(struct inode *inode, struct file *filp)
pdata = rproc->dev->platform_data;
count = atomic_dec_return(&rproc->count);
- if (!count && (rproc->state == OMAP_RPROC_RUNNING))
+ if (!count && (rproc->state != OMAP_RPROC_STOPPED))
rproc_stop(rproc);
return 0;