aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/remoteproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/remoteproc.c')
-rw-r--r--arch/arm/mach-omap2/remoteproc.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/remoteproc.c b/arch/arm/mach-omap2/remoteproc.c
new file mode 100644
index 0000000..b8ae36f
--- /dev/null
+++ b/arch/arm/mach-omap2/remoteproc.c
@@ -0,0 +1,164 @@
+/*
+ * Remote processor machine-specific module for OMAP4
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/remoteproc.h>
+#include <linux/memblock.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+#include <plat/remoteproc.h>
+#include <plat/dsp.h>
+#include <plat/io.h>
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+
+#define OMAP4430_CM_M3_M3_CLKCTRL (OMAP4430_CM2_BASE + OMAP4430_CM2_CORE_INST \
+ + OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET)
+
+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[] = {
+ {
+ .name = "dsp",
+ .iommu_name = "tesla",
+ .firmware = "tesla-dsp.bin",
+ .oh_name = "dsp_c0",
+ .clkdm_name = "dsp_clkdm",
+ },
+ {
+ .name = "ipu",
+ .iommu_name = "ducati",
+ .firmware = "ducati-m3.bin",
+ .oh_name = "ipu_c0",
+ .oh_name_opt = "ipu_c1",
+ .clkdm_name = "ducati_clkdm",
+ .timers = ipu_timers,
+ .timers_cnt = ARRAY_SIZE(ipu_timers),
+ .idle_addr = OMAP4430_CM_M3_M3_CLKCTRL,
+ .idle_mask = OMAP4430_STBYST_MASK,
+ .suspend_addr = 0xb3bf02d8,
+ .suspend_mask = ~0,
+ .sus_timeout = 5000,
+ .sus_mbox_name = "mailbox-1",
+ },
+};
+
+static struct omap_device_pm_latency omap_rproc_latency[] = {
+ {
+ OMAP_RPROC_DEFAULT_PM_LATENCY,
+ },
+};
+
+static struct rproc_mem_pool *omap_rproc_get_pool(const char *name)
+{
+ struct rproc_mem_pool *pool = NULL;
+
+ /* check for ipu currently. dsp will be handled later */
+ if (!strcmp("ipu", name)) {
+ phys_addr_t paddr1 = omap_ipu_get_mempool_base(
+ OMAP_RPROC_MEMPOOL_STATIC);
+ phys_addr_t paddr2 = omap_ipu_get_mempool_base(
+ OMAP_RPROC_MEMPOOL_DYNAMIC);
+ u32 len1 = omap_ipu_get_mempool_size(OMAP_RPROC_MEMPOOL_STATIC);
+ u32 len2 = omap_ipu_get_mempool_size(OMAP_RPROC_MEMPOOL_DYNAMIC);
+
+ if (!paddr1 && !paddr2) {
+ pr_err("no carveout memory available at all for "
+ "remotproc\n");
+ return pool;
+ }
+ if (!paddr1 || !len1)
+ pr_warn("static memory is unavailable: 0x%x, 0x%x\n",
+ paddr1, len1);
+ if (!paddr2 || !len2)
+ pr_warn("carveout memory is unavailable: 0x%x, 0x%x\n",
+ paddr2, len2);
+
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ if (pool) {
+ pool->st_base = paddr1;
+ pool->st_size = len1;
+ pool->mem_base = paddr2;
+ pool->mem_size = len2;
+ pool->cur_base = paddr2;
+ pool->cur_size = len2;
+ }
+ }
+
+ return pool;
+}
+
+static int __init omap_rproc_init(void)
+{
+ const char *pdev_name = "omap-rproc";
+ struct omap_hwmod *oh[2];
+ struct omap_device *od;
+ int i, ret = 0, oh_count;
+
+ /* names like ipu_cx/dsp_cx might show up on other OMAPs, too */
+ if (!cpu_is_omap44xx())
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(omap4_rproc_data); i++) {
+ const char *oh_name = omap4_rproc_data[i].oh_name;
+ const char *oh_name_opt = omap4_rproc_data[i].oh_name_opt;
+ oh_count = 0;
+
+ oh[0] = omap_hwmod_lookup(oh_name);
+ if (!oh[0]) {
+ pr_err("could not look up %s\n", oh_name);
+ continue;
+ }
+ oh_count++;
+
+ if (oh_name_opt) {
+ oh[1] = omap_hwmod_lookup(oh_name_opt);
+ if (!oh[1]) {
+ pr_err("could not look up %s\n", oh_name_opt);
+ continue;
+ }
+ oh_count++;
+ }
+
+ omap4_rproc_data[i].memory_pool =
+ omap_rproc_get_pool(omap4_rproc_data[i].name);
+ od = omap_device_build_ss(pdev_name, i, oh, oh_count,
+ &omap4_rproc_data[i],
+ sizeof(struct omap_rproc_pdata),
+ omap_rproc_latency,
+ ARRAY_SIZE(omap_rproc_latency),
+ false);
+ if (IS_ERR(od)) {
+ pr_err("Could not build omap_device for %s:%s\n",
+ pdev_name, oh_name);
+ ret = PTR_ERR(od);
+ }
+ }
+
+ return ret;
+}
+/* must be ready in time for device_initcall users */
+subsys_initcall(omap_rproc_init);