summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp106/sec2_gp106.c
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2016-06-08 07:57:49 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:17 -0500
commit6ed3cffb73488b22d671c88d30061cd045417378 (patch)
tree8993140fd548fa76ad6f634985de91790ffdf15c /drivers/gpu/nvgpu/gp106/sec2_gp106.c
parent7b43eac2bc1e9e5946f1c721686f841af0550aef (diff)
gpu: nvgpu: ACR boot on SEC2
ACR/SEC2 methods to support ACR boot SEC2 falcon JIRA DNVGPU-34 Change-Id: I917be1d6c61a1c1ae61a918f50228ea00492cd50 Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com> Reviewed-on: http://git-master/r/1161122 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gp106/sec2_gp106.c')
-rw-r--r--drivers/gpu/nvgpu/gp106/sec2_gp106.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp106/sec2_gp106.c b/drivers/gpu/nvgpu/gp106/sec2_gp106.c
new file mode 100644
index 00000000..f8b32f8f
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/sec2_gp106.c
@@ -0,0 +1,384 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include <linux/delay.h> /* for udelay */
15#include <linux/clk.h>
16#include "gk20a/gk20a.h"
17#include "gk20a/pmu_gk20a.h"
18
19#include "gm206/pmu_gm206.h"
20#include "gm20b/pmu_gm20b.h"
21#include "gp10b/pmu_gp10b.h"
22#include "gp106/pmu_gp106.h"
23#include "gp106/acr_gp106.h"
24#include "gp106/hw_mc_gp106.h"
25#include "gp106/hw_pwr_gp106.h"
26#include "gp106/hw_psec_gp106.h"
27#include "sec2_gp106.h"
28#include "acr.h"
29
30/*Defines*/
31#define gm20b_dbg_pmu(fmt, arg...) \
32 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
33
34int sec2_clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout)
35{
36 u32 data = 0;
37 unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout);
38
39 while (time_before(jiffies, end_jiffies) ||
40 !tegra_platform_is_silicon()) {
41 gk20a_writel(g, psec_falcon_irqsclr_r(),
42 gk20a_readl(g, psec_falcon_irqsclr_r()) | (0x10));
43 data = gk20a_readl(g, psec_falcon_irqstat_r());
44 if ((data & psec_falcon_irqstat_halt_true_f()) !=
45 psec_falcon_irqstat_halt_true_f())
46 /*halt irq is clear*/
47 break;
48 timeout--;
49 udelay(1);
50 }
51 if (timeout == 0)
52 return -EBUSY;
53 return 0;
54}
55
56int sec2_wait_for_halt(struct gk20a *g, unsigned int timeout)
57{
58 u32 data = 0;
59 int completion = -EBUSY;
60 unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout);
61
62 while (time_before(jiffies, end_jiffies) ||
63 !tegra_platform_is_silicon()) {
64 data = gk20a_readl(g, psec_falcon_cpuctl_r());
65 if (data & psec_falcon_cpuctl_halt_intr_m()) {
66 /*CPU is halted break*/
67 completion = 0;
68 break;
69 }
70 udelay(1);
71 }
72 if (completion){
73 gk20a_err(dev_from_gk20a(g), "ACR boot timed out");
74 }
75 else {
76
77 g->acr.capabilities = gk20a_readl(g, psec_falcon_mailbox1_r());
78 gm20b_dbg_pmu("ACR capabilities %x\n", g->acr.capabilities);
79 data = gk20a_readl(g, psec_falcon_mailbox0_r());
80 if (data) {
81
82 gk20a_err(dev_from_gk20a(g),
83 "ACR boot failed, err %x", data);
84 completion = -EAGAIN;
85 }
86 }
87
88 init_pmu_setup_hw1(g);
89
90 return completion;
91}
92
93void sec2_copy_to_dmem(struct pmu_gk20a *pmu,
94 u32 dst, u8 *src, u32 size, u8 port)
95{
96 struct gk20a *g = gk20a_from_pmu(pmu);
97 u32 i, words, bytes;
98 u32 data, addr_mask;
99 u32 *src_u32 = (u32*)src;
100
101 if (size == 0) {
102 gk20a_err(dev_from_gk20a(g),
103 "size is zero");
104 return;
105 }
106
107 if (dst & 0x3) {
108 gk20a_err(dev_from_gk20a(g),
109 "dst (0x%08x) not 4-byte aligned", dst);
110 return;
111 }
112
113 mutex_lock(&pmu->pmu_copy_lock);
114
115 words = size >> 2;
116 bytes = size & 0x3;
117
118 addr_mask = psec_falcon_dmemc_offs_m() |
119 psec_falcon_dmemc_blk_m();
120
121 dst &= addr_mask;
122
123 gk20a_writel(g, psec_falcon_dmemc_r(port),
124 dst | psec_falcon_dmemc_aincw_f(1));
125
126 for (i = 0; i < words; i++)
127 gk20a_writel(g, psec_falcon_dmemd_r(port), src_u32[i]);
128
129 if (bytes > 0) {
130 data = 0;
131 for (i = 0; i < bytes; i++)
132 ((u8 *)&data)[i] = src[(words << 2) + i];
133 gk20a_writel(g, psec_falcon_dmemd_r(port), data);
134 }
135
136 data = gk20a_readl(g, psec_falcon_dmemc_r(port)) & addr_mask;
137 size = ALIGN(size, 4);
138 if (data != dst + size) {
139 gk20a_err(dev_from_gk20a(g),
140 "copy failed. bytes written %d, expected %d",
141 data - dst, size);
142 }
143 mutex_unlock(&pmu->pmu_copy_lock);
144 return;
145}
146
147int bl_bootstrap_sec2(struct pmu_gk20a *pmu,
148 void *desc, u32 bl_sz)
149{
150 struct gk20a *g = gk20a_from_pmu(pmu);
151 struct acr_desc *acr = &g->acr;
152 struct mm_gk20a *mm = &g->mm;
153 u32 imem_dst_blk = 0;
154 u32 virt_addr = 0;
155 u32 tag = 0;
156 u32 index = 0;
157 struct hsflcn_bl_desc *pmu_bl_gm10x_desc = g->acr.pmu_hsbl_desc;
158 u32 *bl_ucode;
159 u32 data = 0;
160
161 gk20a_dbg_fn("");
162
163 /* SEC2 Config */
164 gk20a_writel(g, psec_falcon_itfen_r(),
165 gk20a_readl(g, psec_falcon_itfen_r()) |
166 psec_falcon_itfen_ctxen_enable_f());
167
168 gk20a_writel(g, psec_falcon_nxtctx_r(),
169 pwr_pmu_new_instblk_ptr_f(
170 gk20a_mm_inst_block_addr(g, &mm->pmu.inst_block) >> 12) |
171 pwr_pmu_new_instblk_valid_f(1) |
172 pwr_pmu_new_instblk_target_sys_coh_f());
173
174 data = gk20a_readl(g, psec_falcon_debug1_r());
175 data |= psec_falcon_debug1_ctxsw_mode_m();
176 gk20a_writel(g, psec_falcon_debug1_r(), data);
177
178 data = gk20a_readl(g, psec_falcon_engctl_r());
179 data |= (1 << 3);
180 gk20a_writel(g, psec_falcon_engctl_r(), data);
181
182 /* TBD: load all other surfaces */
183 /*copy bootloader interface structure to dmem*/
184 gk20a_writel(g, psec_falcon_dmemc_r(0),
185 psec_falcon_dmemc_offs_f(0) |
186 psec_falcon_dmemc_blk_f(0) |
187 psec_falcon_dmemc_aincw_f(1));
188 sec2_copy_to_dmem(pmu, 0, (u8 *)desc,
189 sizeof(struct flcn_bl_dmem_desc), 0);
190 /*TODO This had to be copied to bl_desc_dmem_load_off, but since
191 * this is 0, so ok for now*/
192
193 /* Now copy bootloader to TOP of IMEM */
194 imem_dst_blk = (psec_falcon_hwcfg_imem_size_v(
195 gk20a_readl(g, psec_falcon_hwcfg_r()))) - bl_sz/256;
196
197 /* Set Auto-Increment on write */
198 gk20a_writel(g, psec_falcon_imemc_r(0),
199 psec_falcon_imemc_offs_f(0) |
200 psec_falcon_imemc_blk_f(imem_dst_blk) |
201 psec_falcon_imemc_aincw_f(1));
202 virt_addr = pmu_bl_gm10x_desc->bl_start_tag << 8;
203 tag = virt_addr >> 8; /* tag is always 256B aligned */
204 bl_ucode = (u32 *)(acr->hsbl_ucode.cpu_va);
205 for (index = 0; index < bl_sz/4; index++) {
206 if ((index % 64) == 0) {
207 gk20a_writel(g, psec_falcon_imemt_r(0),
208 (tag & 0xffff) << 0);
209 tag++;
210 }
211 gk20a_writel(g, psec_falcon_imemd_r(0),
212 bl_ucode[index] & 0xffffffff);
213 }
214 gk20a_writel(g, psec_falcon_imemt_r(0), (0 & 0xffff) << 0);
215
216 gm20b_dbg_pmu("Before starting falcon with BL\n");
217
218 gk20a_writel(g, psec_falcon_mailbox0_r(), 0xDEADA5A5);
219
220 gk20a_writel(g, psec_falcon_bootvec_r(),
221 psec_falcon_bootvec_vec_f(virt_addr));
222
223 gk20a_writel(g, psec_falcon_cpuctl_r(),
224 psec_falcon_cpuctl_startcpu_f(1));
225
226 return 0;
227}
228
229void sec_enable_irq(struct pmu_gk20a *pmu, bool enable)
230{
231 struct gk20a *g = gk20a_from_pmu(pmu);
232
233 gk20a_dbg_fn("");
234
235 gk20a_writel(g, psec_falcon_irqmclr_r(),
236 psec_falcon_irqmclr_gptmr_f(1) |
237 psec_falcon_irqmclr_wdtmr_f(1) |
238 psec_falcon_irqmclr_mthd_f(1) |
239 psec_falcon_irqmclr_ctxsw_f(1) |
240 psec_falcon_irqmclr_halt_f(1) |
241 psec_falcon_irqmclr_exterr_f(1) |
242 psec_falcon_irqmclr_swgen0_f(1) |
243 psec_falcon_irqmclr_swgen1_f(1) |
244 psec_falcon_irqmclr_ext_f(0xff));
245
246 if (enable) {
247 /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */
248 gk20a_writel(g, psec_falcon_irqdest_r(),
249 psec_falcon_irqdest_host_gptmr_f(0) |
250 psec_falcon_irqdest_host_wdtmr_f(1) |
251 psec_falcon_irqdest_host_mthd_f(0) |
252 psec_falcon_irqdest_host_ctxsw_f(0) |
253 psec_falcon_irqdest_host_halt_f(1) |
254 psec_falcon_irqdest_host_exterr_f(0) |
255 psec_falcon_irqdest_host_swgen0_f(1) |
256 psec_falcon_irqdest_host_swgen1_f(0) |
257 psec_falcon_irqdest_host_ext_f(0xff) |
258 psec_falcon_irqdest_target_gptmr_f(1) |
259 psec_falcon_irqdest_target_wdtmr_f(0) |
260 psec_falcon_irqdest_target_mthd_f(0) |
261 psec_falcon_irqdest_target_ctxsw_f(0) |
262 psec_falcon_irqdest_target_halt_f(0) |
263 psec_falcon_irqdest_target_exterr_f(0) |
264 psec_falcon_irqdest_target_swgen0_f(0) |
265 psec_falcon_irqdest_target_swgen1_f(1) |
266 psec_falcon_irqdest_target_ext_f(0xff));
267
268 /* 0=disable, 1=enable */
269 gk20a_writel(g, psec_falcon_irqmset_r(),
270 psec_falcon_irqmset_gptmr_f(1) |
271 psec_falcon_irqmset_wdtmr_f(1) |
272 psec_falcon_irqmset_mthd_f(0) |
273 psec_falcon_irqmset_ctxsw_f(0) |
274 psec_falcon_irqmset_halt_f(1) |
275 psec_falcon_irqmset_exterr_f(1) |
276 psec_falcon_irqmset_swgen0_f(1) |
277 psec_falcon_irqmset_swgen1_f(1));
278
279 }
280
281 gk20a_dbg_fn("done");
282}
283
284void init_pmu_setup_hw1(struct gk20a *g)
285{
286 struct mm_gk20a *mm = &g->mm;
287 struct pmu_gk20a *pmu = &g->pmu;
288 struct gk20a_platform *platform = dev_get_drvdata(g->dev);
289
290 /* PMU TRANSCFG */
291 /* setup apertures - virtual */
292 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
293 pwr_fbif_transcfg_mem_type_physical_f() |
294 pwr_fbif_transcfg_target_local_fb_f());
295 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_VIRT),
296 pwr_fbif_transcfg_mem_type_virtual_f());
297 /* setup apertures - physical */
298 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_VID),
299 pwr_fbif_transcfg_mem_type_physical_f() |
300 pwr_fbif_transcfg_target_local_fb_f());
301 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_COH),
302 pwr_fbif_transcfg_mem_type_physical_f() |
303 pwr_fbif_transcfg_target_coherent_sysmem_f());
304 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_NCOH),
305 pwr_fbif_transcfg_mem_type_physical_f() |
306 pwr_fbif_transcfg_target_noncoherent_sysmem_f());
307
308 /* PMU Config */
309 gk20a_writel(g, pwr_falcon_itfen_r(),
310 gk20a_readl(g, pwr_falcon_itfen_r()) |
311 pwr_falcon_itfen_ctxen_enable_f());
312 gk20a_writel(g, pwr_pmu_new_instblk_r(),
313 pwr_pmu_new_instblk_ptr_f(
314 gk20a_mm_inst_block_addr(g, &mm->pmu.inst_block) >> 12) |
315 pwr_pmu_new_instblk_valid_f(1) |
316 pwr_pmu_new_instblk_target_sys_coh_f());
317
318 /*Copying pmu cmdline args*/
319 g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
320 clk_get_rate(platform->clk[1]));
321 g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode(pmu, 1);
322 g->ops.pmu_ver.set_pmu_cmdline_args_trace_size(
323 pmu, GK20A_PMU_TRACE_BUFSIZE);
324 g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_base(pmu);
325 g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_idx(
326 pmu, GK20A_PMU_DMAIDX_VIRT);
327
328 pmu_copy_to_dmem(pmu, g->acr.pmu_args,
329 (u8 *)(g->ops.pmu_ver.get_pmu_cmdline_args_ptr(pmu)),
330 g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu), 0);
331
332}
333
334int init_sec2_setup_hw1(struct gk20a *g,
335 void *desc, u32 bl_sz)
336{
337 struct pmu_gk20a *pmu = &g->pmu;
338 int err;
339 u32 data = 0;
340
341 gk20a_dbg_fn("");
342
343 mutex_lock(&pmu->isr_mutex);
344 g->ops.pmu.reset(g);
345 pmu->isr_enabled = true;
346 mutex_unlock(&pmu->isr_mutex);
347
348 data = gk20a_readl(g, psec_fbif_ctl_r());
349 data |= psec_fbif_ctl_allow_phys_no_ctx_allow_f();
350 gk20a_writel(g, psec_fbif_ctl_r(), data);
351
352 data = gk20a_readl(g, psec_falcon_dmactl_r());
353 data &= ~(psec_falcon_dmactl_require_ctx_f(1));
354 gk20a_writel(g, psec_falcon_dmactl_r(), data);
355
356 /* setup apertures - virtual */
357 gk20a_writel(g, psec_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
358 psec_fbif_transcfg_mem_type_physical_f() |
359 psec_fbif_transcfg_target_local_fb_f());
360 gk20a_writel(g, psec_fbif_transcfg_r(GK20A_PMU_DMAIDX_VIRT),
361 psec_fbif_transcfg_mem_type_virtual_f());
362 /* setup apertures - physical */
363 gk20a_writel(g, psec_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_VID),
364 psec_fbif_transcfg_mem_type_physical_f() |
365 psec_fbif_transcfg_target_local_fb_f());
366 gk20a_writel(g, psec_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_COH),
367 psec_fbif_transcfg_mem_type_physical_f() |
368 psec_fbif_transcfg_target_coherent_sysmem_f());
369 gk20a_writel(g, psec_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_NCOH),
370 psec_fbif_transcfg_mem_type_physical_f() |
371 psec_fbif_transcfg_target_noncoherent_sysmem_f());
372
373 /*disable irqs for hs falcon booting as we will poll for halt*/
374 mutex_lock(&pmu->isr_mutex);
375 pmu_enable_irq(pmu, false);
376 sec_enable_irq(pmu, false);
377 pmu->isr_enabled = false;
378 mutex_unlock(&pmu->isr_mutex);
379 err = bl_bootstrap_sec2(pmu, desc, bl_sz);
380 if (err)
381 return err;
382
383 return 0;
384}