aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/iommu2.c3
-rw-r--r--arch/arm/mach-omap2/remoteproc.c6
-rw-r--r--arch/arm/plat-omap/include/plat/iommu2.h1
-rw-r--r--arch/arm/plat-omap/omap_rpmsg.c2
-rw-r--r--drivers/remoteproc/Kconfig7
-rw-r--r--drivers/remoteproc/omap_remoteproc.c59
-rw-r--r--drivers/remoteproc/remoteproc.c118
-rw-r--r--drivers/rpmsg/rpmsg_omx.c2
-rw-r--r--include/linux/remoteproc.h7
9 files changed, 176 insertions, 29 deletions
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index de06f56..faa7646 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -130,6 +130,9 @@ static int omap2_iommu_enable(struct iommu *obj)
__iommu_set_twl(obj, true);
+ if (cpu_is_omap44xx())
+ iommu_write_reg(obj, 0x1, MMU_GP_REG);
+
return 0;
}
diff --git a/arch/arm/mach-omap2/remoteproc.c b/arch/arm/mach-omap2/remoteproc.c
index 5d6ccdd..43d49eb 100644
--- a/arch/arm/mach-omap2/remoteproc.c
+++ b/arch/arm/mach-omap2/remoteproc.c
@@ -34,6 +34,10 @@
static struct omap_rproc_timers_info ipu_timers[] = {
{ .id = 3 },
{ .id = 4 },
+#ifdef CONFIG_REMOTEPROC_WATCHDOG
+ { .id = 9 },
+ { .id = 11 },
+#endif
};
static struct omap_rproc_pdata omap4_rproc_data[] = {
@@ -55,7 +59,7 @@ static struct omap_rproc_pdata omap4_rproc_data[] = {
.timers_cnt = ARRAY_SIZE(ipu_timers),
.idle_addr = OMAP4430_CM_M3_M3_CLKCTRL,
.idle_mask = OMAP4430_STBYST_MASK,
- .suspend_addr = 0xb7ff02d8,
+ .suspend_addr = 0xb43f02d8,
.suspend_mask = ~0,
.sus_timeout = 5000,
.sus_mbox_name = "mailbox-1",
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 10ad05f..45b2e36 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -36,6 +36,7 @@
#define MMU_READ_CAM 0x68
#define MMU_READ_RAM 0x6c
#define MMU_EMU_FAULT_AD 0x70
+#define MMU_GP_REG 0x88
#define MMU_REG_SIZE 256
diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c
index c4d1342..7de18ff 100644
--- a/arch/arm/plat-omap/omap_rpmsg.c
+++ b/arch/arm/plat-omap/omap_rpmsg.c
@@ -168,7 +168,7 @@ static int omap_rpmsg_mbox_callback(struct notifier_block *this,
switch (msg) {
case RP_MBOX_CRASH:
pr_err("%s has just crashed !\n", rpdev->rproc_name);
- /* todo: smarter error handling here */
+ rproc_errror_notify(rpdev->rproc);
break;
case RP_MBOX_ECHO_REPLY:
pr_info("received echo reply from %s !\n", rpdev->rproc_name);
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 069c8fd..5a6ba3a 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -41,3 +41,10 @@ config OMAP_RPRES
help
Say Y here if you want to use OMAP remote processor resources
frame work.
+
+config REMOTEPROC_WATCHDOG
+ bool "OMAP remoteproc watchdog timer"
+ depends on REMOTE_PROC
+ default y
+ help
+ Say y to enable watchdog timer for remote cores
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index c464c1d..2d2bcb6 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -39,6 +39,7 @@
struct omap_rproc_priv {
struct iommu *iommu;
int (*iommu_cb)(struct rproc *, u64, u32);
+ int (*wdt_cb)(struct rproc *);
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
struct omap_mbox *mbox;
void __iomem *idle;
@@ -321,7 +322,51 @@ static void _destroy_pm_flags(struct rproc *rproc)
}
}
#endif
+#ifdef CONFIG_REMOTEPROC_WATCHDOG
+static int omap_rproc_watchdog_init(struct rproc *rproc,
+ int (*callback)(struct rproc *rproc))
+{
+ struct omap_rproc_priv *rpp = rproc->priv;
+
+ rpp->wdt_cb = callback;
+ return 0;
+}
+
+static int omap_rproc_watchdog_exit(struct rproc *rproc)
+{
+ struct omap_rproc_priv *rpp = rproc->priv;
+
+ rpp->wdt_cb = NULL;
+ return 0;
+}
+
+static irqreturn_t omap_rproc_watchdog_isr(int irq, void *p)
+{
+ struct rproc *rproc = p;
+ struct omap_rproc_pdata *pdata = rproc->dev->platform_data;
+ struct omap_rproc_timers_info *timers = pdata->timers;
+ struct omap_dm_timer *timer = NULL;
+ struct omap_rproc_priv *rpp = rproc->priv;
+ int i;
+
+ for (i = 0; i < pdata->timers_cnt; i++) {
+ if (irq == omap_dm_timer_get_irq(timers[i].odt)) {
+ timer = timers[i].odt;
+ break;
+ }
+ }
+
+ if (!timer)
+ return IRQ_NONE;
+ omap_dm_timer_write_status(timer, OMAP_TIMER_INT_OVERFLOW);
+
+ if (rpp->wdt_cb)
+ rpp->wdt_cb(rproc);
+
+ return IRQ_HANDLED;
+}
+#endif
static inline int omap_rproc_start(struct rproc *rproc, u64 bootaddr)
{
struct device *dev = rproc->dev;
@@ -339,6 +384,16 @@ static inline int omap_rproc_start(struct rproc *rproc, u64 bootaddr)
goto out;
}
omap_dm_timer_set_source(timers[i].odt, OMAP_TIMER_SRC_SYS_CLK);
+#ifdef CONFIG_REMOTEPROC_WATCHDOG
+ /* GPT 9 and 11 are using as WDT */
+ if (timers[i].id == 9 || timers[i].id == 11) {
+ ret = request_irq(omap_dm_timer_get_irq(timers[i].odt),
+ omap_rproc_watchdog_isr, IRQF_DISABLED,
+ "rproc-wdt", rproc);
+ /* Clean counter, remoteproc proc will set the value */
+ omap_dm_timer_set_load(timers[i].odt, 0, 0);
+ }
+#endif
}
ret = omap_device_enable(pdev);
@@ -413,6 +468,10 @@ static struct rproc_ops omap_rproc_ops = {
.set_lat = omap_rproc_set_lat,
.set_bw = omap_rproc_set_l3_bw,
.scale = omap_rproc_scale,
+#ifdef CONFIG_REMOTEPROC_WATCHDOG
+ .watchdog_init = omap_rproc_watchdog_init,
+ .watchdog_exit = omap_rproc_watchdog_exit,
+#endif
};
static int omap_rproc_probe(struct platform_device *pdev)
diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c
index 4124011..2e9a6e0 100644
--- a/drivers/remoteproc/remoteproc.c
+++ b/drivers/remoteproc/remoteproc.c
@@ -55,8 +55,8 @@ static ssize_t rproc_format_trace_buf(char __user *userbuf, size_t count,
int i, w_pos;
/* Assume write_idx is the penultimate byte in the buffer trace*/
- w_idx = (int *)(buf + (size - (sizeof(u32) * 2)));
size = size - (sizeof(u32) * 2);
+ w_idx = (int *)(buf + size);
w_pos = *w_idx;
if (from_beg)
@@ -127,6 +127,10 @@ static const struct file_operations rproc_name_ops = {
DEBUGFS_READONLY_FILE(trace0, rproc->trace_buf0, rproc->trace_len0);
DEBUGFS_READONLY_FILE(trace1, rproc->trace_buf1, rproc->trace_len1);
+DEBUGFS_READONLY_FILE(trace0_last, rproc->last_trace_buf0,
+ rproc->last_trace_len0);
+DEBUGFS_READONLY_FILE(trace1_last, rproc->last_trace_buf1,
+ rproc->last_trace_len1);
#define DEBUGFS_ADD(name) \
debugfs_create_file(#name, 0400, rproc->dbg_dir, \
@@ -194,12 +198,19 @@ rproc_da_to_pa(const struct rproc_mem_entry *maps, u64 da, phys_addr_t *pa)
static int rproc_mmu_fault_isr(struct rproc *rproc, u64 da, u32 flags)
{
dev_err(rproc->dev, "%s\n", __func__);
- rproc->state = RPROC_CRASHED;
- schedule_work(&rproc->mmufault_work);
+ schedule_work(&rproc->error_work);
return -EIO;
}
+static int rproc_watchdog_isr(struct rproc *rproc)
+{
+ dev_err(rproc->dev, "Enter %s\n", __func__);
+ schedule_work(&rproc->error_work);
+
+ return 0;
+}
+
static int _event_notify(struct rproc *rproc, int type, void *data)
{
struct blocking_notifier_head *nh;
@@ -211,6 +222,12 @@ static int _event_notify(struct rproc *rproc, int type, void *data)
init_completion(&rproc->error_comp);
rproc->state = RPROC_CRASHED;
mutex_unlock(&rproc->lock);
+ if (rproc->trace_buf0 && rproc->last_trace_buf0)
+ memcpy(rproc->last_trace_buf0, rproc->trace_buf0,
+ rproc->last_trace_len0);
+ if (rproc->trace_buf1 && rproc->last_trace_buf1)
+ memcpy(rproc->last_trace_buf1, rproc->trace_buf1,
+ rproc->last_trace_len1);
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
pm_runtime_dont_use_autosuspend(rproc->dev);
#endif
@@ -259,6 +276,15 @@ static void rproc_start(struct rproc *rproc, u64 bootaddr)
}
}
+ if (rproc->ops->watchdog_init) {
+ err = rproc->ops->watchdog_init(rproc, rproc_watchdog_isr);
+ if (err) {
+ dev_err(dev, "can't configure watchdog timer %d\n",
+ err);
+ goto unlock_mutext;
+ }
+ }
+
err = rproc->ops->start(rproc, bootaddr);
if (err) {
dev_err(dev, "can't start rproc %s: %d\n", rproc->name, err);
@@ -393,9 +419,11 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
/* store the da for processing at the end */
if (!trace_da0) {
rproc->trace_len0 = rsc->len;
+ rproc->last_trace_len0 = rsc->len;
trace_da0 = da;
} else {
rproc->trace_len1 = rsc->len;
+ rproc->last_trace_len1 = rsc->len;
trace_da1 = da;
}
break;
@@ -446,6 +474,9 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
len -= sizeof(*rsc);
}
+ if (ret)
+ goto error;
+
/*
* post-process trace buffers, as we cannot rely on the order of the
* trace section and the carveout sections.
@@ -453,33 +484,54 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
* trace buffer memory _is_ normal memory, so we cast away the
* __iomem to make sparse happy
*/
- if (!ret && trace_da0) {
+ if (trace_da0) {
ret = rproc_da_to_pa(rproc->memory_maps, trace_da0, &pa);
- if (!ret) {
- rproc->trace_buf0 = (__force void *)
- ioremap_nocache(pa, rproc->trace_len0);
- if (rproc->trace_buf0)
- DEBUGFS_ADD(trace0);
- else {
- dev_err(dev, "can't ioremap trace buffer0\n");
- ret = -EIO;
+ if (ret)
+ goto error;
+ rproc->trace_buf0 = (__force void *)
+ ioremap_nocache(pa, rproc->trace_len0);
+ if (rproc->trace_buf0) {
+ DEBUGFS_ADD(trace0);
+ if (!rproc->last_trace_buf0) {
+ rproc->last_trace_buf0 = kzalloc(sizeof(u32) *
+ rproc->last_trace_len0,
+ GFP_KERNEL);
+ if (!rproc->last_trace_buf0) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ DEBUGFS_ADD(trace0_last);
}
+ } else {
+ dev_err(dev, "can't ioremap trace buffer0\n");
+ ret = -EIO;
+ goto error;
}
}
- if (!ret && trace_da1) {
+ if (trace_da1) {
ret = rproc_da_to_pa(rproc->memory_maps, trace_da1, &pa);
- if (!ret) {
- rproc->trace_buf1 = (__force void *)
- ioremap_nocache(pa, rproc->trace_len1);
- if (rproc->trace_buf1)
- DEBUGFS_ADD(trace1);
- else {
- dev_err(dev, "can't ioremap trace buffer1\n");
- ret = -EIO;
+ if (ret)
+ goto error;
+ rproc->trace_buf1 = (__force void *)
+ ioremap_nocache(pa, rproc->trace_len1);
+ if (rproc->trace_buf1) {
+ DEBUGFS_ADD(trace1);
+ if (!rproc->last_trace_buf1) {
+ rproc->last_trace_buf1 = kzalloc(sizeof(u32) *
+ rproc->last_trace_len1,
+ GFP_KERNEL);
+ if (!rproc->last_trace_buf1) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ DEBUGFS_ADD(trace1_last);
}
+ } else {
+ dev_err(dev, "can't ioremap trace buffer1\n");
+ ret = -EIO;
}
}
-
+error:
return ret;
}
@@ -638,6 +690,12 @@ static int rproc_loader(struct rproc *rproc)
return 0;
}
+int rproc_errror_notify(struct rproc *rproc)
+{
+ return _event_notify(rproc, RPROC_ERROR, NULL);
+}
+EXPORT_SYMBOL_GPL(rproc_errror_notify);
+
struct rproc *rproc_get(const char *name)
{
struct rproc *rproc, *ret = NULL;
@@ -760,6 +818,14 @@ void rproc_put(struct rproc *rproc)
ret);
goto out;
}
+ if (rproc->ops->watchdog_exit) {
+ ret = rproc->ops->watchdog_exit(rproc);
+ if (ret) {
+ dev_err(rproc->dev, "error watchdog_exit %d\n",
+ ret);
+ goto out;
+ }
+ }
if (rproc->ops->iommu_exit) {
ret = rproc->ops->iommu_exit(rproc);
if (ret) {
@@ -784,9 +850,9 @@ out:
}
EXPORT_SYMBOL_GPL(rproc_put);
-static void rproc_mmufault_work(struct work_struct *work)
+static void rproc_error_work(struct work_struct *work)
{
- struct rproc *rproc = container_of(work, struct rproc, mmufault_work);
+ struct rproc *rproc = container_of(work, struct rproc, error_work);
dev_dbg(rproc->dev, "Enter %s\n", __func__);
_event_notify(rproc, RPROC_ERROR, NULL);
@@ -1093,7 +1159,7 @@ int rproc_register(struct device *dev, const char *name,
mutex_init(&rproc->pm_lock);
#endif
mutex_init(&rproc->lock);
- INIT_WORK(&rproc->mmufault_work, rproc_mmufault_work);
+ INIT_WORK(&rproc->error_work, rproc_error_work);
BLOCKING_INIT_NOTIFIER_HEAD(&rproc->nb_error);
rproc->state = RPROC_OFFLINE;
@@ -1160,6 +1226,8 @@ int rproc_unregister(const char *name)
pm_qos_remove_request(rproc->qos_request);
kfree(rproc->qos_request);
+ kfree(rproc->last_trace_buf0);
+ kfree(rproc->last_trace_buf1);
kfree(rproc);
return 0;
diff --git a/drivers/rpmsg/rpmsg_omx.c b/drivers/rpmsg/rpmsg_omx.c
index b3a8b7e..bd417c4 100644
--- a/drivers/rpmsg/rpmsg_omx.c
+++ b/drivers/rpmsg/rpmsg_omx.c
@@ -111,7 +111,7 @@ static LIST_HEAD(rpmsg_omx_services_list);
*/
#define TILER_START 0x60000000
#define TILER_END 0x80000000
-#define ION_1D_START 0xBDF00000
+#define ION_1D_START 0xBA300000
#define ION_1D_END 0xBFD00000
#define ION_1D_VA 0x88000000
static u32 _rpmsg_pa_to_da(u32 pa)
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 7b9c549..8076cff 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -153,6 +153,8 @@ struct rproc_ops {
int (*set_lat)(struct rproc *rproc, long v);
int (*set_bw)(struct rproc *rproc, long v);
int (*scale)(struct rproc *rproc, long v);
+ int (*watchdog_init)(struct rproc *, int (*)(struct rproc *));
+ int (*watchdog_exit)(struct rproc *);
};
/*
@@ -244,9 +246,11 @@ struct rproc {
struct mutex lock;
struct dentry *dbg_dir;
char *trace_buf0, *trace_buf1;
+ char *last_trace_buf0, *last_trace_buf1;
int trace_len0, trace_len1;
+ int last_trace_len0, last_trace_len1;
struct completion firmware_loading_complete;
- struct work_struct mmufault_work;
+ struct work_struct error_work;
struct blocking_notifier_head nb_error;
struct completion error_comp;
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
@@ -277,5 +281,6 @@ extern const struct dev_pm_ops rproc_gen_pm_ops;
#define GENERIC_RPROC_PM_OPS NULL
#endif
int rproc_set_constraints(struct rproc *, enum rproc_constraint type, long v);
+int rproc_errror_notify(struct rproc *rproc);
#endif /* REMOTEPROC_H */