From 2904e3ac0081d4e898378f6ba667658c85547368 Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Wed, 4 Oct 2017 19:41:04 +0530 Subject: gpu: nvgpu: gv100 memory unlock support - Added method to load mem unlock binary into nvdec falcon & execute to perform mem unlock if VPR enabled. - Updated .mem_unlock gv100 HAL to point method gv100_fb_memory_unlock(). - Updated .mem_unlock gv11b HAL to NULL. - Added vpr info hw registers - Added nvdec enable hw register Change-Id: Ia4bf820ae103baede679d300d1d390fd748c919a Signed-off-by: Mahantesh Kumbar (cherry picked from commit 2e176ad9d47316bf4d001692a2ae07e6c1fb1ccb) Reviewed-on: https://git-master.nvidia.com/r/1573101 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gv100/fb_gv100.c | 124 +++++++++++++++++++++ drivers/gpu/nvgpu/gv100/fb_gv100.h | 1 + drivers/gpu/nvgpu/gv100/hal_gv100.c | 1 + drivers/gpu/nvgpu/gv11b/hal_gv11b.c | 1 + .../gpu/nvgpu/include/nvgpu/hw/gv100/hw_fb_gv100.h | 36 ++++++ .../gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h | 8 ++ 6 files changed, 171 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gv100/fb_gv100.c b/drivers/gpu/nvgpu/gv100/fb_gv100.c index bcb6d740..0a2939bf 100644 --- a/drivers/gpu/nvgpu/gv100/fb_gv100.c +++ b/drivers/gpu/nvgpu/gv100/fb_gv100.c @@ -28,14 +28,25 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "gk20a/gk20a.h" #include "gv100/fb_gv100.h" +#include "gm20b/acr_gm20b.h" #include +#include +#include #define HW_SCRUB_TIMEOUT_DEFAULT 100 /* usec */ #define HW_SCRUB_TIMEOUT_MAX 2000000 /* usec */ +#define MEM_UNLOCK_TIMEOUT 3500 /* msec */ void gv100_fb_reset(struct gk20a *g) { @@ -58,3 +69,116 @@ void gv100_fb_reset(struct gk20a *g) val &= ~fb_mmu_priv_level_mask_write_violation_m(); gk20a_writel(g, fb_mmu_priv_level_mask_r(), val); } + +int gv100_fb_memory_unlock(struct gk20a *g) +{ + struct nvgpu_firmware *mem_unlock_fw = NULL; + struct bin_hdr *hsbin_hdr = NULL; + struct acr_fw_header *fw_hdr = NULL; + u32 *mem_unlock_ucode = NULL; + u32 *mem_unlock_ucode_header = NULL; + u32 sec_imem_dest = 0; + u32 val = 0; + int err = 0; + + nvgpu_log_fn(g, " "); + + /* Check vpr enable status */ + val = gk20a_readl(g, fb_mmu_vpr_info_r()); + val &= ~fb_mmu_vpr_info_index_m(); + val |= fb_mmu_vpr_info_index_cya_lo_v(); + gk20a_writel(g, fb_mmu_vpr_info_r(), val); + val = gk20a_readl(g, fb_mmu_vpr_info_r()); + if (!(val & fb_mmu_vpr_info_cya_lo_in_use_m())) { + nvgpu_log_info(g, "mem unlock not required on this SKU, skipping"); + goto exit; + } + + /* get mem unlock ucode binary */ + mem_unlock_fw = nvgpu_request_firmware(g, "mem_unlock.bin", 0); + if (!mem_unlock_fw) { + nvgpu_err(g, "mem unlock ucode get fail"); + err = -ENOENT; + goto exit; + } + + /* Enable nvdec */ + g->ops.mc.enable(g, mc_enable_nvdec_enabled_f()); + + /* nvdec falcon reset */ + nvgpu_flcn_reset(&g->nvdec_flcn); + + hsbin_hdr = (struct bin_hdr *)mem_unlock_fw->data; + fw_hdr = (struct acr_fw_header *)(mem_unlock_fw->data + + hsbin_hdr->header_offset); + + mem_unlock_ucode_header = (u32 *)(mem_unlock_fw->data + + fw_hdr->hdr_offset); + mem_unlock_ucode = (u32 *)(mem_unlock_fw->data + + hsbin_hdr->data_offset); + + /* Patch Ucode singnatures */ + if (acr_ucode_patch_sig(g, mem_unlock_ucode, + (u32 *)(mem_unlock_fw->data + fw_hdr->sig_prod_offset), + (u32 *)(mem_unlock_fw->data + fw_hdr->sig_dbg_offset), + (u32 *)(mem_unlock_fw->data + fw_hdr->patch_loc), + (u32 *)(mem_unlock_fw->data + fw_hdr->patch_sig)) < 0) { + nvgpu_err(g, "mem unlock patch signatures fail"); + err = -EPERM; + goto exit; + } + + /* Clear interrupts */ + nvgpu_flcn_set_irq(&g->nvdec_flcn, false, 0x0, 0x0); + + /* Copy Non Secure IMEM code */ + nvgpu_flcn_copy_to_imem(&g->nvdec_flcn, 0, + (u8 *)&mem_unlock_ucode[ + mem_unlock_ucode_header[OS_CODE_OFFSET] >> 2], + mem_unlock_ucode_header[OS_CODE_SIZE], 0, false, + GET_IMEM_TAG(mem_unlock_ucode_header[OS_CODE_OFFSET])); + + /* Put secure code after non-secure block */ + sec_imem_dest = GET_NEXT_BLOCK(mem_unlock_ucode_header[OS_CODE_SIZE]); + + nvgpu_flcn_copy_to_imem(&g->nvdec_flcn, sec_imem_dest, + (u8 *)&mem_unlock_ucode[ + mem_unlock_ucode_header[APP_0_CODE_OFFSET] >> 2], + mem_unlock_ucode_header[APP_0_CODE_SIZE], 0, true, + GET_IMEM_TAG(mem_unlock_ucode_header[APP_0_CODE_OFFSET])); + + /* load DMEM: ensure that signatures are patched */ + nvgpu_flcn_copy_to_dmem(&g->nvdec_flcn, 0, (u8 *)&mem_unlock_ucode[ + mem_unlock_ucode_header[OS_DATA_OFFSET] >> 2], + mem_unlock_ucode_header[OS_DATA_SIZE], 0); + + nvgpu_log_info(g, "nvdec sctl reg %x\n", + gk20a_readl(g, g->nvdec_flcn.flcn_base + + falcon_falcon_sctl_r())); + + /* set BOOTVEC to start of non-secure code */ + nvgpu_flcn_bootstrap(&g->nvdec_flcn, 0); + + /* wait for complete & halt */ + nvgpu_flcn_wait_for_halt(&g->nvdec_flcn, MEM_UNLOCK_TIMEOUT); + + /* check mem unlock status */ + val = nvgpu_flcn_mailbox_read(&g->nvdec_flcn, 0); + if (val) { + nvgpu_err(g, "memory unlock failed, err %x", val); + err = -1; + goto exit; + } + + nvgpu_log_info(g, "nvdec sctl reg %x\n", + gk20a_readl(g, g->nvdec_flcn.flcn_base + + falcon_falcon_sctl_r())); + +exit: + if (mem_unlock_fw) + nvgpu_release_firmware(g, mem_unlock_fw); + + nvgpu_log_fn(g, "done, status - %d", err); + + return err; +} diff --git a/drivers/gpu/nvgpu/gv100/fb_gv100.h b/drivers/gpu/nvgpu/gv100/fb_gv100.h index d5a36661..b6db262a 100644 --- a/drivers/gpu/nvgpu/gv100/fb_gv100.h +++ b/drivers/gpu/nvgpu/gv100/fb_gv100.h @@ -28,4 +28,5 @@ struct gk20a; void gv100_fb_reset(struct gk20a *g); +int gv100_fb_memory_unlock(struct gk20a *g); #endif diff --git a/drivers/gpu/nvgpu/gv100/hal_gv100.c b/drivers/gpu/nvgpu/gv100/hal_gv100.c index 2007eee0..4e05f22b 100644 --- a/drivers/gpu/nvgpu/gv100/hal_gv100.c +++ b/drivers/gpu/nvgpu/gv100/hal_gv100.c @@ -421,6 +421,7 @@ static const struct gpu_ops gv100_ops = { .set_debug_mode = gm20b_fb_set_debug_mode, .tlb_invalidate = gk20a_fb_tlb_invalidate, .hub_isr = gv11b_fb_hub_isr, + .mem_unlock = gv100_fb_memory_unlock, }, .fifo = { .init_fifo_setup_hw = gv11b_init_fifo_setup_hw, diff --git a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c index 22beabf7..729727c9 100644 --- a/drivers/gpu/nvgpu/gv11b/hal_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/hal_gv11b.c @@ -385,6 +385,7 @@ static const struct gpu_ops gv11b_ops = { .set_debug_mode = gm20b_fb_set_debug_mode, .tlb_invalidate = gk20a_fb_tlb_invalidate, .hub_isr = gv11b_fb_hub_isr, + .mem_unlock = NULL, }, .clock_gating = { .slcg_bus_load_gating_prod = diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_fb_gv100.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_fb_gv100.h index 3bba3fb8..a4fcd1e6 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_fb_gv100.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_fb_gv100.h @@ -460,6 +460,42 @@ static inline u32 fb_mmu_vpr_info_r(void) { return 0x00100cd0U; } +static inline u32 fb_mmu_vpr_info_index_f(u32 v) +{ + return (v & 0x3U) << 0U; +} +static inline u32 fb_mmu_vpr_info_index_v(u32 r) +{ + return (r >> 0U) & 0x3U; +} +static inline u32 fb_mmu_vpr_info_index_m(void) +{ + return 0x3U << 0U; +} +static inline u32 fb_mmu_vpr_info_index_addr_lo_v(void) +{ + return 0x00000000U; +} +static inline u32 fb_mmu_vpr_info_index_addr_hi_v(void) +{ + return 0x00000001U; +} +static inline u32 fb_mmu_vpr_info_index_cya_lo_v(void) +{ + return 0x00000002U; +} +static inline u32 fb_mmu_vpr_info_index_cya_hi_v(void) +{ + return 0x00000003U; +} +static inline u32 fb_mmu_vpr_info_cya_lo_in_use_m(void) +{ + return 0x1U << 4U; +} +static inline u32 fb_mmu_vpr_info_fetch_f(u32 v) +{ + return (v & 0x1U) << 2U; +} static inline u32 fb_mmu_vpr_info_fetch_v(u32 r) { return (r >> 2U) & 0x1U; diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h index 2efeac79..f367991e 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h @@ -196,6 +196,14 @@ static inline u32 mc_enable_hub_enabled_f(void) { return 0x20000000U; } +static inline u32 mc_enable_nvdec_disabled_v(void) +{ + return 0x00000000U; +} +static inline u32 mc_enable_nvdec_enabled_f(void) +{ + return 0x8000U; +} static inline u32 mc_intr_ltc_r(void) { return 0x000001c0U; -- cgit v1.2.2