diff options
author | Kaz Fukuoka <kfukuoka@nvidia.com> | 2011-04-20 18:53:42 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2012-03-23 00:41:07 -0700 |
commit | 9d815afb7e3fcdec3f2be2a488af79145fdf2b07 (patch) | |
tree | c5c9f102b963dc57c28839c34a0db6fd3de8429d /drivers/media/video/tegra/avp | |
parent | c31d46cb1b4f27663c377b92cde9e834e23d90f2 (diff) |
media: tegra: avp: Use SMMU to load AVP kernel
- Use nvrm_avp_e0000000.bin is for Tegra3 A01
- Use nvrm_avp_00001000.bin is for Tegra3 A02 and later
bug 765965
Original-Change-Id: I9bc28b122bd1b0cd2c1ece3bc681550de5912229
Reviewed-on: http://git-master/r/31202
Reviewed-by: Kaz Fukuoka <kfukuoka@nvidia.com>
Tested-by: Kaz Fukuoka <kfukuoka@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Tested-by: Mayuresh Kulkarni <mkulkarni@nvidia.com>
Rebase-Id: R02295b1e1327407ef762b8ef1954b0a0f78afd32
Diffstat (limited to 'drivers/media/video/tegra/avp')
-rw-r--r-- | drivers/media/video/tegra/avp/avp.c | 110 | ||||
-rw-r--r-- | drivers/media/video/tegra/avp/headavp.h | 2 |
2 files changed, 74 insertions, 38 deletions
diff --git a/drivers/media/video/tegra/avp/avp.c b/drivers/media/video/tegra/avp/avp.c index 04608b41d866..81788c697169 100644 --- a/drivers/media/video/tegra/avp/avp.c +++ b/drivers/media/video/tegra/avp/avp.c @@ -143,6 +143,7 @@ struct tegra_avp_info { void *iram_backup_data; phys_addr_t iram_backup_phys; unsigned long resume_addr; + unsigned long reset_addr; struct trpc_endpoint *avp_ep; struct rb_root endpoints; @@ -944,7 +945,7 @@ 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; + char fw_file[30]; avp->nvmap_libs = nvmap_create_client(nvmap_dev, "avp_libs"); if (IS_ERR(avp->nvmap_libs)) { @@ -957,28 +958,44 @@ static int avp_init(struct tegra_avp_info *avp) * to read out when its kernel boots. */ mbox_writel(avp->msg, MBOX_TO_AVP); -#ifdef CONFIG_TEGRA_AVP_KERNEL_ON_MMU +#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */ + /* paddr is any address returned from nvmap_pin */ + /* vaddr is AVP_KERNEL_VIRT_BASE */ pr_info("%s: Using AVP MMU to relocate AVP kernel\n", __func__); -#else - // Find nvmem carveout. + sprintf(fw_file, "nvrm_avp.bin"); + avp->reset_addr = AVP_KERNEL_VIRT_BASE; +#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */ + /* paddr is any address behind SMMU */ + /* vaddr is TEGRA_SMMU_BASE */ + pr_info("%s: Using SMMU at %lx to load AVP kernel\n", + __func__, avp->kernel_phys); + BUG_ON(avp->kernel_phys != 0xe0000000 + && avp->kernel_phys != 0x00001000); + sprintf(fw_file, "nvrm_avp_%08lx.bin", avp->kernel_phys); + avp->reset_addr = avp->kernel_phys; +#else /* nvmem= carveout */ + /* paddr is found in nvmem= carveout */ + /* vaddr is same as paddr */ + /* 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 { + pr_err("Cannot find nvmem= carveout to load AVP kernel\n"); + pr_err("Check kernel command line " + "to see if nvmem= is defined\n"); BUG(); } - - pr_info("%s: Using carveout at %lx to load AVP kernel\n", - __func__, (unsigned long)(avp->kernel_phys)); + pr_info("%s: Using nvmem= carveout at %lx to load AVP kernel\n", + __func__, avp->kernel_phys); + sprintf(fw_file, "nvrm_avp_%08lx.bin", avp->kernel_phys); + avp->reset_addr = avp->kernel_phys; avp->kernel_data = ioremap(avp->kernel_phys, SZ_1M); #endif @@ -987,7 +1004,7 @@ static int avp_init(struct tegra_avp_info *avp) 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: Reading firmware from '%s' (%d bytes)\n", __func__, fw_file, avp_fw->size); pr_info("%s: Loading AVP kernel at vaddr=%p paddr=%lx\n", @@ -998,11 +1015,7 @@ static int avp_init(struct tegra_avp_info *avp) 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 + ret = avp_reset(avp, avp->reset_addr); if (ret) { pr_err("%s: cannot reset the AVP.. aborting..\n", __func__); goto err_reset; @@ -1549,6 +1562,7 @@ static int tegra_avp_probe(struct platform_device *pdev) struct tegra_avp_info *avp; int ret = 0; int irq; + unsigned int heap_mask; irq = platform_get_irq_byname(pdev, "mbox_from_avp_pending"); if (irq < 0) { @@ -1569,26 +1583,48 @@ static int tegra_avp_probe(struct platform_device *pdev) goto err_nvmap_create_drv_client; } - avp->kernel_handle = nvmap_alloc(avp->nvmap_drv, SZ_1M, SZ_1M, - NVMAP_HANDLE_WRITE_COMBINE); - if (IS_ERR(avp->kernel_handle)) { - pr_err("%s: cannot create handle\n", __func__); - ret = PTR_ERR(avp->kernel_handle); - goto err_nvmap_alloc; - } +#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */ + heap_mask = NVMAP_HEAP_CARVEOUT_MASK; +#elif defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 with SMMU */ + heap_mask = NVMAP_HEAP_IOVMM; +#else /* nvmem= carveout */ + heap_mask = 0; +#endif - avp->kernel_data = nvmap_mmap(avp->kernel_handle); - if (!avp->kernel_data) { - pr_err("%s: cannot map kernel handle\n", __func__); - ret = -ENOMEM; - goto err_nvmap_mmap; - } + if (heap_mask) { + avp->kernel_handle = nvmap_create_handle(avp->nvmap_drv, SZ_1M); + if (IS_ERR(avp->kernel_handle)) { + pr_err("%s: cannot create kernel handle\n", __func__); + ret = PTR_ERR(avp->kernel_handle); + goto err_nvmap_create_handle; + } - avp->kernel_phys = nvmap_pin(avp->nvmap_drv, avp->kernel_handle); - if (IS_ERR((void *)avp->kernel_phys)) { - pr_err("%s: cannot pin kernel handle\n", __func__); - ret = PTR_ERR((void *)avp->kernel_phys); - goto err_nvmap_pin; + ret = nvmap_alloc_handle_id(avp->nvmap_drv, + nvmap_ref_to_id(avp->kernel_handle), + heap_mask, PAGE_SIZE, + NVMAP_HANDLE_WRITE_COMBINE); + if (ret) { + pr_err("%s: cannot allocate kernel memory\n", __func__); + goto err_nvmap_alloc; + } + + avp->kernel_data = nvmap_mmap(avp->kernel_handle); + if (!avp->kernel_data) { + pr_err("%s: cannot map kernel handle\n", __func__); + ret = -ENOMEM; + goto err_nvmap_mmap; + } + + avp->kernel_phys = + nvmap_pin(avp->nvmap_drv, avp->kernel_handle); + if (IS_ERR((void *)avp->kernel_phys)) { + pr_err("%s: cannot pin kernel handle\n", __func__); + ret = PTR_ERR((void *)avp->kernel_phys); + goto err_nvmap_pin; + } + + pr_info("%s: allocated memory at %lx for AVP kernel\n", + __func__, avp->kernel_phys); } /* allocate an extra 4 bytes at the end which AVP uses to signal to @@ -1691,8 +1727,7 @@ static int tegra_avp_probe(struct platform_device *pdev) tegra_avp = avp; - pr_info("%s: driver registered, kernel %lx(%p), msg area %lx/%lx\n", - __func__, (unsigned long)(avp->kernel_phys), avp->kernel_data, + pr_info("%s: message area %lx/%lx\n", __func__, (unsigned long)avp->msg_area_addr, (unsigned long)avp->msg_area_addr + AVP_MSG_AREA_SIZE); @@ -1724,6 +1759,9 @@ err_nvmap_pin: err_nvmap_mmap: nvmap_free(avp->nvmap_drv, avp->kernel_handle); err_nvmap_alloc: + nvmap_free_handle_id(avp->nvmap_drv, + nvmap_ref_to_id(avp->kernel_handle)); +err_nvmap_create_handle: nvmap_client_put(avp->nvmap_drv); err_nvmap_create_drv_client: kfree(avp); diff --git a/drivers/media/video/tegra/avp/headavp.h b/drivers/media/video/tegra/avp/headavp.h index 8ef0936089e7..2bcc3297bfa4 100644 --- a/drivers/media/video/tegra/avp/headavp.h +++ b/drivers/media/video/tegra/avp/headavp.h @@ -22,9 +22,7 @@ #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__ |