diff options
author | Kaz Fukuoka <kfukuoka@nvidia.com> | 2010-12-05 17:56:54 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-04-26 15:49:26 -0700 |
commit | f6e2cc8e6d9ed71c198caac167e2720963e09a14 (patch) | |
tree | b6884a4093012e2cc3ad89690c692c46e20d610c /drivers/media/video/tegra/avp | |
parent | 6d518c0c70471803e905a32efefb8f60c4d230a9 (diff) |
tegra: avp: enable AVP and moduleloader
- Load AVP kernel at fixed address.
- Use nvmem= carveout to load AVP kernel.
bug 765965
bug 777221
Original-Change-Id: I60b650a395936450687cea9b881f78bcee854421
Reviewed-on: http://git-master/r/15343
Tested-by: Kaz Fukuoka <kfukuoka@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Change-Id: I34b6acd03075325733a7bc3f005b71a7c1721919
Diffstat (limited to 'drivers/media/video/tegra/avp')
-rw-r--r-- | drivers/media/video/tegra/avp/Makefile | 6 | ||||
-rw-r--r-- | drivers/media/video/tegra/avp/avp.c | 66 | ||||
-rw-r--r-- | drivers/media/video/tegra/avp/headavp.S | 2 | ||||
-rw-r--r-- | drivers/media/video/tegra/avp/headavp.h | 2 |
4 files changed, 69 insertions, 7 deletions
diff --git a/drivers/media/video/tegra/avp/Makefile b/drivers/media/video/tegra/avp/Makefile index 6d8be11c3f81..6be6afc25490 100644 --- a/drivers/media/video/tegra/avp/Makefile +++ b/drivers/media/video/tegra/avp/Makefile @@ -1,3 +1,9 @@ +# FIXME: Forcing these options to test AVP moduleloader. +# In the formal Kconfig layout, those options depend on CONFIG_MEDIA_SUPPORT. +# AVP moduleloader has to be tested before enabling CONFIG_MEDIA_SUPPORT. +CONFIG_TEGRA_RPC=y +CONFIG_TEGRA_AVP=y + obj-$(CONFIG_TEGRA_RPC) += tegra_rpc.o obj-$(CONFIG_TEGRA_RPC) += trpc_local.o obj-$(CONFIG_TEGRA_RPC) += trpc_sema.o diff --git a/drivers/media/video/tegra/avp/avp.c b/drivers/media/video/tegra/avp/avp.c index 384fd5af3890..32e2011366fe 100644 --- a/drivers/media/video/tegra/avp/avp.c +++ b/drivers/media/video/tegra/avp/avp.c @@ -60,7 +60,15 @@ enum { AVP_DBG_TRACE_LIB = 1U << 6, }; -static u32 avp_debug_mask; +static u32 avp_debug_mask = + AVP_DBG_TRACE_XPC | + AVP_DBG_TRACE_XPC_IRQ | + AVP_DBG_TRACE_XPC_MSG | + AVP_DBG_TRACE_XPC_CONN | + AVP_DBG_TRACE_TRPC_MSG | + AVP_DBG_TRACE_TRPC_CONN | + AVP_DBG_TRACE_LIB; + module_param_named(debug_mask, avp_debug_mask, uint, S_IWUSR | S_IRUGO); #define DBG(flag, args...) \ @@ -68,8 +76,6 @@ module_param_named(debug_mask, avp_debug_mask, uint, S_IWUSR | S_IRUGO); #define TEGRA_AVP_NAME "tegra-avp" -#define TEGRA_AVP_KERNEL_FW "nvrm_avp.bin" - #define TEGRA_AVP_RESET_VECTOR_ADDR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x200) @@ -882,6 +888,9 @@ static int avp_reset(struct tegra_avp_info *avp, unsigned long reset_addr) writel(stub_code_phys, TEGRA_AVP_RESET_VECTOR_ADDR); + pr_err("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR)); + pr_err("%s: Resetting AVP: reset_addr=%lx\n", __func__, reset_addr); + tegra_periph_reset_assert(avp->cop_clk); udelay(10); tegra_periph_reset_deassert(avp->cop_clk); @@ -892,12 +901,16 @@ static int avp_reset(struct tegra_avp_info *avp, unsigned long reset_addr) * starts, so a dead kernel can be detected by polling this value */ timeout = jiffies + msecs_to_jiffies(2000); while (time_before(jiffies, timeout)) { + pr_err("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR)); if (readl(TEGRA_AVP_RESET_VECTOR_ADDR) != stub_code_phys) break; cpu_relax(); } - if (readl(TEGRA_AVP_RESET_VECTOR_ADDR) == stub_code_phys) + if (readl(TEGRA_AVP_RESET_VECTOR_ADDR) == stub_code_phys) { + pr_err("%s: Timed out waiting for AVP kernel to start\n", __func__); ret = -EINVAL; + } + pr_err("%s: TEGRA_AVP_RESET_VECTOR=%x\n", __func__, readl(TEGRA_AVP_RESET_VECTOR_ADDR)); WARN_ON(ret); dma_unmap_single(NULL, stub_data_phys, sizeof(_tegra_avp_boot_stub_data), @@ -924,11 +937,12 @@ static void avp_halt(struct tegra_avp_info *avp) * of the char dev for receiving replies for managing remote * libraries/modules. */ -static int avp_init(struct tegra_avp_info *avp, const char *fw_file) +static int avp_init(struct tegra_avp_info *avp) { const struct firmware *avp_fw; int ret; struct trpc_endpoint *ep; + const char *fw_file = AVP_KERNEL_FW; avp->nvmap_libs = nvmap_create_client(nvmap_dev, "avp_libs"); if (IS_ERR(avp->nvmap_libs)) { @@ -941,19 +955,52 @@ static int avp_init(struct tegra_avp_info *avp, const char *fw_file) * to read out when its kernel boots. */ mbox_writel(avp->msg, MBOX_TO_AVP); +#ifdef CONFIG_TEGRA_AVP_KERNEL_ON_MMU + pr_err("%s: Using AVP MMU to relocate AVP kernel\n", __func__); +#else + // Find nvmem carveout. + if (!pfn_valid(__phys_to_pfn(0x8e000000))) { + fw_file = "nvrm_avp_8e000000.bin"; + avp->kernel_phys = 0x8e000000; + } + else if (!pfn_valid(__phys_to_pfn(0x9e000000))) { + fw_file = "nvrm_avp_9e000000.bin"; + avp->kernel_phys = 0x9e000000; + } + else if (!pfn_valid(__phys_to_pfn(0xbe000000))) { + fw_file = "nvrm_avp_be000000.bin"; + avp->kernel_phys = 0xbe000000; + } + else { + BUG(); + } + + pr_err("%s: Using carveout at %x to load AVP kernel\n", + __func__, avp->kernel_phys); + avp->kernel_data = ioremap(avp->kernel_phys, SZ_1M); +#endif + ret = request_firmware(&avp_fw, fw_file, avp->misc_dev.this_device); if (ret) { pr_err("%s: Cannot read firmware '%s'\n", __func__, fw_file); goto err_req_fw; } - pr_info("%s: read firmware from '%s' (%d bytes)\n", __func__, + pr_info("%s: Read firmware from '%s' (%d bytes)\n", __func__, fw_file, avp_fw->size); + + pr_err("%s: Loading AVP kernel at vaddr=%p paddr=%lx\n", + __func__, avp->kernel_data, avp->kernel_phys); memcpy(avp->kernel_data, avp_fw->data, avp_fw->size); memset(avp->kernel_data + avp_fw->size, 0, SZ_1M - avp_fw->size); + wmb(); release_firmware(avp_fw); +#ifdef CONFIG_TEGRA_AVP_KERNEL_ON_MMU ret = avp_reset(avp, AVP_KERNEL_VIRT_BASE); +#else + ret = avp_reset(avp, avp->kernel_phys); +#endif if (ret) { pr_err("%s: cannot reset the AVP.. aborting..\n", __func__); goto err_reset; @@ -1233,6 +1280,7 @@ static int handle_load_lib_ioctl(struct tegra_avp_info *avp, unsigned long arg) struct tegra_avp_lib lib; int ret; + pr_info("%s: \n", __func__); if (copy_from_user(&lib, (void __user *)arg, sizeof(lib))) return -EFAULT; lib.name[TEGRA_AVP_LIB_MAX_NAME - 1] = '\0'; @@ -1320,7 +1368,7 @@ int tegra_avp_open(struct tegra_avp_info **avp) mutex_lock(&new_avp->open_lock); if (!new_avp->refcount) - ret = avp_init(new_avp, TEGRA_AVP_KERNEL_FW); + ret = avp_init(new_avp); if (ret < 0) { new_avp = 0; @@ -1347,6 +1395,10 @@ int tegra_avp_release(struct tegra_avp_info *avp) { int ret = 0; + // FIXME: Just for now, to test AVP loading. + pr_info("%s: FIXME: ignoring release\n", __func__); + return 0; + mutex_lock(&avp->open_lock); if (!avp->refcount) { pr_err("%s: releasing while in invalid state\n", __func__); diff --git a/drivers/media/video/tegra/avp/headavp.S b/drivers/media/video/tegra/avp/headavp.S index 5304067f0d83..c1f8e9fea1cb 100644 --- a/drivers/media/video/tegra/avp/headavp.S +++ b/drivers/media/video/tegra/avp/headavp.S @@ -48,12 +48,14 @@ ENTRY(_tegra_avp_boot_stub) adr r4, _tegra_avp_boot_stub_data ldmia r4, {r0-r3} +#ifdef CONFIG_TEGRA_AVP_KERNEL_ON_MMU str r2, [r0, #PTE0_COMPARE] bic r3, r3, #0xff0 bic r3, r3, #0x00f orr r3, r3, #TRANSLATE_OPT orr r3, r3, #TRANSLATE_EN str r3, [r0, #PTE0_TRANSLATE] +#endif bx r1 b . ENDPROC(_tegra_avp_boot_stub) diff --git a/drivers/media/video/tegra/avp/headavp.h b/drivers/media/video/tegra/avp/headavp.h index 2bcc3297bfa4..8ef0936089e7 100644 --- a/drivers/media/video/tegra/avp/headavp.h +++ b/drivers/media/video/tegra/avp/headavp.h @@ -22,7 +22,9 @@ #define _MACH_TEGRA_HEADAVP_H #define AVP_MMU_TLB_BASE 0xF000F000 + #define AVP_KERNEL_VIRT_BASE 0x00100000 +#define AVP_KERNEL_FW "nvrm_avp.bin" #ifndef __ASSEMBLY__ |