/* * 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 #include #include #include #include #include #include #include #include #include #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);