summaryrefslogtreecommitdiff
path: root/drivers/media/video/tegra/avp
diff options
context:
space:
mode:
authorKaz Fukuoka <kfukuoka@nvidia.com>2010-12-05 17:56:54 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-04-26 15:49:26 -0700
commitf6e2cc8e6d9ed71c198caac167e2720963e09a14 (patch)
treeb6884a4093012e2cc3ad89690c692c46e20d610c /drivers/media/video/tegra/avp
parent6d518c0c70471803e905a32efefb8f60c4d230a9 (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/Makefile6
-rw-r--r--drivers/media/video/tegra/avp/avp.c66
-rw-r--r--drivers/media/video/tegra/avp/headavp.S2
-rw-r--r--drivers/media/video/tegra/avp/headavp.h2
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__