summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gv100/fb_gv100.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gv100/fb_gv100.c')
-rw-r--r--drivers/gpu/nvgpu/gv100/fb_gv100.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gv100/fb_gv100.c b/drivers/gpu/nvgpu/gv100/fb_gv100.c
new file mode 100644
index 00000000..0a2939bf
--- /dev/null
+++ b/drivers/gpu/nvgpu/gv100/fb_gv100.c
@@ -0,0 +1,184 @@
1/*
2 * GV100 FB
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <nvgpu/types.h>
26
27#include <nvgpu/dma.h>
28#include <nvgpu/log.h>
29#include <nvgpu/enabled.h>
30#include <nvgpu/gmmu.h>
31#include <nvgpu/nvgpu_common.h>
32#include <nvgpu/kmem.h>
33#include <nvgpu/nvgpu_mem.h>
34#include <nvgpu/acr/nvgpu_acr.h>
35#include <nvgpu/firmware.h>
36#include <nvgpu/pmu.h>
37#include <nvgpu/falcon.h>
38
39#include "gk20a/gk20a.h"
40#include "gv100/fb_gv100.h"
41#include "gm20b/acr_gm20b.h"
42
43#include <nvgpu/hw/gv100/hw_fb_gv100.h>
44#include <nvgpu/hw/gv100/hw_falcon_gv100.h>
45#include <nvgpu/hw/gv100/hw_mc_gv100.h>
46
47#define HW_SCRUB_TIMEOUT_DEFAULT 100 /* usec */
48#define HW_SCRUB_TIMEOUT_MAX 2000000 /* usec */
49#define MEM_UNLOCK_TIMEOUT 3500 /* msec */
50
51void gv100_fb_reset(struct gk20a *g)
52{
53 u32 val;
54 int retries = HW_SCRUB_TIMEOUT_MAX / HW_SCRUB_TIMEOUT_DEFAULT;
55
56 nvgpu_info(g, "reset gv100 fb");
57
58 /* wait for memory to be accessible */
59 do {
60 u32 w = gk20a_readl(g, fb_niso_scrub_status_r());
61 if (fb_niso_scrub_status_flag_v(w)) {
62 nvgpu_info(g, "done");
63 break;
64 }
65 nvgpu_udelay(HW_SCRUB_TIMEOUT_DEFAULT);
66 } while (--retries);
67
68 val = gk20a_readl(g, fb_mmu_priv_level_mask_r());
69 val &= ~fb_mmu_priv_level_mask_write_violation_m();
70 gk20a_writel(g, fb_mmu_priv_level_mask_r(), val);
71}
72
73int gv100_fb_memory_unlock(struct gk20a *g)
74{
75 struct nvgpu_firmware *mem_unlock_fw = NULL;
76 struct bin_hdr *hsbin_hdr = NULL;
77 struct acr_fw_header *fw_hdr = NULL;
78 u32 *mem_unlock_ucode = NULL;
79 u32 *mem_unlock_ucode_header = NULL;
80 u32 sec_imem_dest = 0;
81 u32 val = 0;
82 int err = 0;
83
84 nvgpu_log_fn(g, " ");
85
86 /* Check vpr enable status */
87 val = gk20a_readl(g, fb_mmu_vpr_info_r());
88 val &= ~fb_mmu_vpr_info_index_m();
89 val |= fb_mmu_vpr_info_index_cya_lo_v();
90 gk20a_writel(g, fb_mmu_vpr_info_r(), val);
91 val = gk20a_readl(g, fb_mmu_vpr_info_r());
92 if (!(val & fb_mmu_vpr_info_cya_lo_in_use_m())) {
93 nvgpu_log_info(g, "mem unlock not required on this SKU, skipping");
94 goto exit;
95 }
96
97 /* get mem unlock ucode binary */
98 mem_unlock_fw = nvgpu_request_firmware(g, "mem_unlock.bin", 0);
99 if (!mem_unlock_fw) {
100 nvgpu_err(g, "mem unlock ucode get fail");
101 err = -ENOENT;
102 goto exit;
103 }
104
105 /* Enable nvdec */
106 g->ops.mc.enable(g, mc_enable_nvdec_enabled_f());
107
108 /* nvdec falcon reset */
109 nvgpu_flcn_reset(&g->nvdec_flcn);
110
111 hsbin_hdr = (struct bin_hdr *)mem_unlock_fw->data;
112 fw_hdr = (struct acr_fw_header *)(mem_unlock_fw->data +
113 hsbin_hdr->header_offset);
114
115 mem_unlock_ucode_header = (u32 *)(mem_unlock_fw->data +
116 fw_hdr->hdr_offset);
117 mem_unlock_ucode = (u32 *)(mem_unlock_fw->data +
118 hsbin_hdr->data_offset);
119
120 /* Patch Ucode singnatures */
121 if (acr_ucode_patch_sig(g, mem_unlock_ucode,
122 (u32 *)(mem_unlock_fw->data + fw_hdr->sig_prod_offset),
123 (u32 *)(mem_unlock_fw->data + fw_hdr->sig_dbg_offset),
124 (u32 *)(mem_unlock_fw->data + fw_hdr->patch_loc),
125 (u32 *)(mem_unlock_fw->data + fw_hdr->patch_sig)) < 0) {
126 nvgpu_err(g, "mem unlock patch signatures fail");
127 err = -EPERM;
128 goto exit;
129 }
130
131 /* Clear interrupts */
132 nvgpu_flcn_set_irq(&g->nvdec_flcn, false, 0x0, 0x0);
133
134 /* Copy Non Secure IMEM code */
135 nvgpu_flcn_copy_to_imem(&g->nvdec_flcn, 0,
136 (u8 *)&mem_unlock_ucode[
137 mem_unlock_ucode_header[OS_CODE_OFFSET] >> 2],
138 mem_unlock_ucode_header[OS_CODE_SIZE], 0, false,
139 GET_IMEM_TAG(mem_unlock_ucode_header[OS_CODE_OFFSET]));
140
141 /* Put secure code after non-secure block */
142 sec_imem_dest = GET_NEXT_BLOCK(mem_unlock_ucode_header[OS_CODE_SIZE]);
143
144 nvgpu_flcn_copy_to_imem(&g->nvdec_flcn, sec_imem_dest,
145 (u8 *)&mem_unlock_ucode[
146 mem_unlock_ucode_header[APP_0_CODE_OFFSET] >> 2],
147 mem_unlock_ucode_header[APP_0_CODE_SIZE], 0, true,
148 GET_IMEM_TAG(mem_unlock_ucode_header[APP_0_CODE_OFFSET]));
149
150 /* load DMEM: ensure that signatures are patched */
151 nvgpu_flcn_copy_to_dmem(&g->nvdec_flcn, 0, (u8 *)&mem_unlock_ucode[
152 mem_unlock_ucode_header[OS_DATA_OFFSET] >> 2],
153 mem_unlock_ucode_header[OS_DATA_SIZE], 0);
154
155 nvgpu_log_info(g, "nvdec sctl reg %x\n",
156 gk20a_readl(g, g->nvdec_flcn.flcn_base +
157 falcon_falcon_sctl_r()));
158
159 /* set BOOTVEC to start of non-secure code */
160 nvgpu_flcn_bootstrap(&g->nvdec_flcn, 0);
161
162 /* wait for complete & halt */
163 nvgpu_flcn_wait_for_halt(&g->nvdec_flcn, MEM_UNLOCK_TIMEOUT);
164
165 /* check mem unlock status */
166 val = nvgpu_flcn_mailbox_read(&g->nvdec_flcn, 0);
167 if (val) {
168 nvgpu_err(g, "memory unlock failed, err %x", val);
169 err = -1;
170 goto exit;
171 }
172
173 nvgpu_log_info(g, "nvdec sctl reg %x\n",
174 gk20a_readl(g, g->nvdec_flcn.flcn_base +
175 falcon_falcon_sctl_r()));
176
177exit:
178 if (mem_unlock_fw)
179 nvgpu_release_firmware(g, mem_unlock_fw);
180
181 nvgpu_log_fn(g, "done, status - %d", err);
182
183 return err;
184}