summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp106/acr_gp106.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gp106/acr_gp106.c')
-rw-r--r--drivers/gpu/nvgpu/gp106/acr_gp106.c1174
1 files changed, 1174 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp106/acr_gp106.c b/drivers/gpu/nvgpu/gp106/acr_gp106.c
new file mode 100644
index 00000000..0dfa8e0e
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/acr_gp106.c
@@ -0,0 +1,1174 @@
1/*
2 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/nvgpu_common.h>
24#include <nvgpu/kmem.h>
25#include <nvgpu/dma.h>
26#include <nvgpu/acr/nvgpu_acr.h>
27#include <nvgpu/firmware.h>
28#include <nvgpu/pmu.h>
29#include <nvgpu/enabled.h>
30
31#include "gk20a/gk20a.h"
32#include "gk20a/pmu_gk20a.h"
33
34#include "gm20b/mm_gm20b.h"
35#include "gm20b/acr_gm20b.h"
36#include "gp106/acr_gp106.h"
37#include "gp106/pmu_gp106.h"
38
39#include "sec2_gp106.h"
40
41#include <nvgpu/hw/gp106/hw_psec_gp106.h>
42#include <nvgpu/hw/gp106/hw_pwr_gp106.h>
43
44#ifdef CONFIG_TEGRA_19x_GPU
45#include "nvgpu_gpuid_t19x.h"
46#include "acr_t19x.h"
47#endif
48
49/*Defines*/
50#define gp106_dbg_pmu(fmt, arg...) \
51 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
52
53typedef int (*get_ucode_details)(struct gk20a *g,
54 struct flcn_ucode_img_v1 *udata);
55
56/* Both size and address of WPR need to be 128K-aligned */
57#define WPR_ALIGNMENT 0x20000
58#define GP106_DGPU_NONWPR NVGPU_VIDMEM_BOOTSTRAP_ALLOCATOR_BASE
59#define GP106_DGPU_WPR_OFFSET 0x400000
60#define DGPU_WPR_SIZE 0x100000
61
62/*Externs*/
63
64/*Forwards*/
65
66/*Globals*/
67static get_ucode_details pmu_acr_supp_ucode_list[] = {
68 pmu_ucode_details,
69 fecs_ucode_details,
70 gpccs_ucode_details,
71};
72
73void gp106_wpr_info(struct gk20a *g, struct wpr_carveout_info *inf)
74{
75 inf->nonwpr_base = g->mm.vidmem.bootstrap_base;
76 inf->wpr_base = inf->nonwpr_base + GP106_DGPU_WPR_OFFSET;
77 inf->size = DGPU_WPR_SIZE;
78}
79
80static void flcn64_set_dma(struct falc_u64 *dma_addr, u64 value)
81{
82 dma_addr->lo |= u64_lo32(value);
83 dma_addr->hi |= u64_hi32(value);
84}
85
86int gp106_alloc_blob_space(struct gk20a *g,
87 size_t size, struct nvgpu_mem *mem)
88{
89 struct wpr_carveout_info wpr_inf;
90 int err;
91
92 if (mem->size)
93 return 0;
94
95 g->ops.pmu.get_wpr(g, &wpr_inf);
96
97 /*
98 * Even though this mem_desc wouldn't be used, the wpr region needs to
99 * be reserved in the allocator.
100 */
101 err = nvgpu_dma_alloc_flags_vid_at(g,
102 NVGPU_DMA_NO_KERNEL_MAPPING, wpr_inf.size,
103 &g->acr.wpr_dummy, wpr_inf.wpr_base);
104 if (err)
105 return err;
106
107 return nvgpu_dma_alloc_flags_vid_at(g,
108 NVGPU_DMA_NO_KERNEL_MAPPING, wpr_inf.size, mem,
109 wpr_inf.nonwpr_base);
110}
111/* TODO - check if any free blob res needed*/
112
113int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img)
114{
115 struct nvgpu_firmware *pmu_fw, *pmu_desc, *pmu_sig;
116 struct nvgpu_pmu *pmu = &g->pmu;
117 struct lsf_ucode_desc_v1 *lsf_desc;
118 int err;
119
120 gp106_dbg_pmu("requesting PMU ucode in gp106\n");
121 pmu_fw = nvgpu_request_firmware(g, GM20B_PMU_UCODE_IMAGE,
122 NVGPU_REQUEST_FIRMWARE_NO_SOC);
123 if (!pmu_fw) {
124 nvgpu_err(g, "failed to load pmu ucode!!");
125 return -ENOENT;
126 }
127 g->acr.pmu_fw = pmu_fw;
128 gp106_dbg_pmu("Loaded PMU ucode in for blob preparation");
129
130 gp106_dbg_pmu("requesting PMU ucode desc in GM20B\n");
131 pmu_desc = nvgpu_request_firmware(g, GM20B_PMU_UCODE_DESC,
132 NVGPU_REQUEST_FIRMWARE_NO_SOC);
133 if (!pmu_desc) {
134 nvgpu_err(g, "failed to load pmu ucode desc!!");
135 err = -ENOENT;
136 goto release_img_fw;
137 }
138 pmu_sig = nvgpu_request_firmware(g, GM20B_PMU_UCODE_SIG,
139 NVGPU_REQUEST_FIRMWARE_NO_SOC);
140 if (!pmu_sig) {
141 nvgpu_err(g, "failed to load pmu sig!!");
142 err = -ENOENT;
143 goto release_desc;
144 }
145 pmu->desc_v1 = (struct pmu_ucode_desc_v1 *)pmu_desc->data;
146 pmu->ucode_image = (u32 *)pmu_fw->data;
147 g->acr.pmu_desc = pmu_desc;
148
149 err = nvgpu_init_pmu_fw_support(pmu);
150 if (err) {
151 nvgpu_err(g, "failed to set function pointers");
152 goto release_sig;
153 }
154
155 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_v1));
156 if (!lsf_desc) {
157 err = -ENOMEM;
158 goto release_sig;
159 }
160 memcpy(lsf_desc, (void *)pmu_sig->data, sizeof(struct lsf_ucode_desc_v1));
161 lsf_desc->falcon_id = LSF_FALCON_ID_PMU;
162
163 p_img->desc = pmu->desc_v1;
164 p_img->data = pmu->ucode_image;
165 p_img->data_size = pmu->desc_v1->app_start_offset
166 + pmu->desc_v1->app_size;
167 p_img->fw_ver = NULL;
168 p_img->header = NULL;
169 p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc;
170 gp106_dbg_pmu("requesting PMU ucode in GM20B exit\n");
171
172 nvgpu_release_firmware(g, pmu_sig);
173 return 0;
174release_sig:
175 nvgpu_release_firmware(g, pmu_sig);
176release_desc:
177 nvgpu_release_firmware(g, pmu_desc);
178 g->acr.pmu_desc = NULL;
179release_img_fw:
180 nvgpu_release_firmware(g, pmu_fw);
181 g->acr.pmu_fw = NULL;
182 return err;
183}
184
185int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img)
186{
187 u32 ver = g->params.gpu_arch + g->params.gpu_impl;
188 struct lsf_ucode_desc_v1 *lsf_desc;
189 struct nvgpu_firmware *fecs_sig = NULL;
190 int err;
191
192 switch (ver) {
193 case NVGPU_GPUID_GP104:
194 fecs_sig = nvgpu_request_firmware(g,
195 GP104_FECS_UCODE_SIG,
196 NVGPU_REQUEST_FIRMWARE_NO_SOC);
197 break;
198 case NVGPU_GPUID_GP106:
199 fecs_sig = nvgpu_request_firmware(g,
200 GP106_FECS_UCODE_SIG,
201 NVGPU_REQUEST_FIRMWARE_NO_SOC);
202 break;
203#if defined(CONFIG_TEGRA_19x_GPU)
204 case TEGRA_19x_GPUID:
205 fecs_sig = nvgpu_request_firmware(g,
206 GM20B_FECS_UCODE_SIG, 0);
207 break;
208 case BIGGPU_19x_GPUID:
209 fecs_sig = nvgpu_request_firmware(g,
210 BIGGPU_FECS_UCODE_SIG,
211 NVGPU_REQUEST_FIRMWARE_NO_SOC);
212 break;
213#endif
214 default:
215 nvgpu_err(g, "no support for GPUID %x", ver);
216 }
217
218 if (!fecs_sig) {
219 nvgpu_err(g, "failed to load fecs sig");
220 return -ENOENT;
221 }
222 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_v1));
223 if (!lsf_desc) {
224 err = -ENOMEM;
225 goto rel_sig;
226 }
227 memcpy(lsf_desc, (void *)fecs_sig->data, sizeof(struct lsf_ucode_desc_v1));
228 lsf_desc->falcon_id = LSF_FALCON_ID_FECS;
229
230 p_img->desc = nvgpu_kzalloc(g, sizeof(struct pmu_ucode_desc_v1));
231 if (p_img->desc == NULL) {
232 err = -ENOMEM;
233 goto free_lsf_desc;
234 }
235
236 p_img->desc->bootloader_start_offset =
237 g->ctxsw_ucode_info.fecs.boot.offset;
238 p_img->desc->bootloader_size =
239 ALIGN(g->ctxsw_ucode_info.fecs.boot.size, 256);
240 p_img->desc->bootloader_imem_offset =
241 g->ctxsw_ucode_info.fecs.boot_imem_offset;
242 p_img->desc->bootloader_entry_point =
243 g->ctxsw_ucode_info.fecs.boot_entry;
244
245 p_img->desc->image_size =
246 ALIGN(g->ctxsw_ucode_info.fecs.boot.size, 256) +
247 ALIGN(g->ctxsw_ucode_info.fecs.code.size, 256) +
248 ALIGN(g->ctxsw_ucode_info.fecs.data.size, 256);
249 p_img->desc->app_size = ALIGN(g->ctxsw_ucode_info.fecs.code.size, 256) +
250 ALIGN(g->ctxsw_ucode_info.fecs.data.size, 256);
251 p_img->desc->app_start_offset = g->ctxsw_ucode_info.fecs.code.offset;
252 p_img->desc->app_imem_offset = 0;
253 p_img->desc->app_imem_entry = 0;
254 p_img->desc->app_dmem_offset = 0;
255 p_img->desc->app_resident_code_offset = 0;
256 p_img->desc->app_resident_code_size =
257 g->ctxsw_ucode_info.fecs.code.size;
258 p_img->desc->app_resident_data_offset =
259 g->ctxsw_ucode_info.fecs.data.offset -
260 g->ctxsw_ucode_info.fecs.code.offset;
261 p_img->desc->app_resident_data_size =
262 g->ctxsw_ucode_info.fecs.data.size;
263 p_img->data = g->ctxsw_ucode_info.surface_desc.cpu_va;
264 p_img->data_size = p_img->desc->image_size;
265
266 p_img->fw_ver = NULL;
267 p_img->header = NULL;
268 p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc;
269 gp106_dbg_pmu("fecs fw loaded\n");
270 nvgpu_release_firmware(g, fecs_sig);
271 return 0;
272free_lsf_desc:
273 nvgpu_kfree(g, lsf_desc);
274rel_sig:
275 nvgpu_release_firmware(g, fecs_sig);
276 return err;
277}
278
279int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img)
280{
281 u32 ver = g->params.gpu_arch + g->params.gpu_impl;
282 struct lsf_ucode_desc_v1 *lsf_desc;
283 struct nvgpu_firmware *gpccs_sig = NULL;
284 int err;
285
286 if (!nvgpu_is_enabled(g, NVGPU_SEC_SECUREGPCCS))
287 return -ENOENT;
288
289 switch (ver) {
290 case NVGPU_GPUID_GP104:
291 gpccs_sig = nvgpu_request_firmware(g,
292 GP104_GPCCS_UCODE_SIG,
293 NVGPU_REQUEST_FIRMWARE_NO_SOC);
294 break;
295 case NVGPU_GPUID_GP106:
296 gpccs_sig = nvgpu_request_firmware(g,
297 GP106_GPCCS_UCODE_SIG,
298 NVGPU_REQUEST_FIRMWARE_NO_SOC);
299 break;
300#if defined(CONFIG_TEGRA_19x_GPU)
301 case TEGRA_19x_GPUID:
302 gpccs_sig = nvgpu_request_firmware(g,
303 T18x_GPCCS_UCODE_SIG, 0);
304 break;
305 case BIGGPU_19x_GPUID:
306 gpccs_sig = nvgpu_request_firmware(g,
307 BIGGPU_GPCCS_UCODE_SIG,
308 NVGPU_REQUEST_FIRMWARE_NO_SOC);
309 break;
310#endif
311 default:
312 nvgpu_err(g, "no support for GPUID %x", ver);
313 }
314
315 if (!gpccs_sig) {
316 nvgpu_err(g, "failed to load gpccs sig");
317 return -ENOENT;
318 }
319 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_v1));
320 if (!lsf_desc) {
321 err = -ENOMEM;
322 goto rel_sig;
323 }
324 memcpy(lsf_desc, (void *)gpccs_sig->data,
325 sizeof(struct lsf_ucode_desc_v1));
326 lsf_desc->falcon_id = LSF_FALCON_ID_GPCCS;
327
328 p_img->desc = nvgpu_kzalloc(g, sizeof(struct pmu_ucode_desc_v1));
329 if (p_img->desc == NULL) {
330 err = -ENOMEM;
331 goto free_lsf_desc;
332 }
333
334 p_img->desc->bootloader_start_offset =
335 0;
336 p_img->desc->bootloader_size =
337 ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256);
338 p_img->desc->bootloader_imem_offset =
339 g->ctxsw_ucode_info.gpccs.boot_imem_offset;
340 p_img->desc->bootloader_entry_point =
341 g->ctxsw_ucode_info.gpccs.boot_entry;
342
343 p_img->desc->image_size =
344 ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256) +
345 ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256) +
346 ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
347 p_img->desc->app_size = ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256)
348 + ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
349 p_img->desc->app_start_offset = p_img->desc->bootloader_size;
350 p_img->desc->app_imem_offset = 0;
351 p_img->desc->app_imem_entry = 0;
352 p_img->desc->app_dmem_offset = 0;
353 p_img->desc->app_resident_code_offset = 0;
354 p_img->desc->app_resident_code_size =
355 ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256);
356 p_img->desc->app_resident_data_offset =
357 ALIGN(g->ctxsw_ucode_info.gpccs.data.offset, 256) -
358 ALIGN(g->ctxsw_ucode_info.gpccs.code.offset, 256);
359 p_img->desc->app_resident_data_size =
360 ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
361 p_img->data = (u32 *)((u8 *)g->ctxsw_ucode_info.surface_desc.cpu_va +
362 g->ctxsw_ucode_info.gpccs.boot.offset);
363 p_img->data_size = ALIGN(p_img->desc->image_size, 256);
364 p_img->fw_ver = NULL;
365 p_img->header = NULL;
366 p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc;
367 gp106_dbg_pmu("gpccs fw loaded\n");
368 nvgpu_release_firmware(g, gpccs_sig);
369 return 0;
370free_lsf_desc:
371 nvgpu_kfree(g, lsf_desc);
372rel_sig:
373 nvgpu_release_firmware(g, gpccs_sig);
374 return err;
375}
376
377int gp106_prepare_ucode_blob(struct gk20a *g)
378{
379
380 int err;
381 struct ls_flcn_mgr_v1 lsfm_l, *plsfm;
382 struct nvgpu_pmu *pmu = &g->pmu;
383 struct wpr_carveout_info wpr_inf;
384
385 if (g->acr.ucode_blob.cpu_va) {
386 /*Recovery case, we do not need to form
387 non WPR blob of ucodes*/
388 err = nvgpu_init_pmu_fw_support(pmu);
389 if (err) {
390 gp106_dbg_pmu("failed to set function pointers\n");
391 return err;
392 }
393 return 0;
394 }
395 plsfm = &lsfm_l;
396 memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr_v1));
397 gr_gk20a_init_ctxsw_ucode(g);
398
399 g->ops.pmu.get_wpr(g, &wpr_inf);
400 gp106_dbg_pmu("wpr carveout base:%llx\n", (wpr_inf.wpr_base));
401 gp106_dbg_pmu("wpr carveout size :%x\n", (u32)wpr_inf.size);
402
403 /* Discover all managed falcons*/
404 err = lsfm_discover_ucode_images(g, plsfm);
405 gp106_dbg_pmu(" Managed Falcon cnt %d\n", plsfm->managed_flcn_cnt);
406 if (err)
407 goto exit_err;
408
409 if (plsfm->managed_flcn_cnt && !g->acr.ucode_blob.cpu_va) {
410 /* Generate WPR requirements*/
411 err = lsf_gen_wpr_requirements(g, plsfm);
412 if (err)
413 goto exit_err;
414
415 /*Alloc memory to hold ucode blob contents*/
416 err = g->ops.pmu.alloc_blob_space(g, plsfm->wpr_size
417 ,&g->acr.ucode_blob);
418 if (err)
419 goto exit_err;
420
421 gp106_dbg_pmu("managed LS falcon %d, WPR size %d bytes.\n",
422 plsfm->managed_flcn_cnt, plsfm->wpr_size);
423
424 lsfm_init_wpr_contents(g, plsfm, &g->acr.ucode_blob);
425 } else {
426 gp106_dbg_pmu("LSFM is managing no falcons.\n");
427 }
428 gp106_dbg_pmu("prepare ucode blob return 0\n");
429 free_acr_resources(g, plsfm);
430
431 exit_err:
432 return err;
433}
434
435static u8 lsfm_falcon_disabled(struct gk20a *g, struct ls_flcn_mgr_v1 *plsfm,
436 u32 falcon_id)
437{
438 return (plsfm->disable_mask >> falcon_id) & 0x1;
439}
440
441/* Discover all managed falcon ucode images */
442int lsfm_discover_ucode_images(struct gk20a *g,
443 struct ls_flcn_mgr_v1 *plsfm)
444{
445 struct nvgpu_pmu *pmu = &g->pmu;
446 struct flcn_ucode_img_v1 ucode_img;
447 u32 falcon_id;
448 u32 i;
449 int status;
450
451 /* LSFM requires a secure PMU, discover it first.*/
452 /* Obtain the PMU ucode image and add it to the list if required*/
453 memset(&ucode_img, 0, sizeof(ucode_img));
454 status = pmu_ucode_details(g, &ucode_img);
455 if (status)
456 return status;
457
458 if (ucode_img.lsf_desc != NULL) {
459 /* The falon_id is formed by grabbing the static base
460 * falon_id from the image and adding the
461 * engine-designated falcon instance.*/
462 pmu->pmu_mode |= PMU_SECURE_MODE;
463 falcon_id = ucode_img.lsf_desc->falcon_id +
464 ucode_img.flcn_inst;
465
466 if (!lsfm_falcon_disabled(g, plsfm, falcon_id)) {
467 pmu->falcon_id = falcon_id;
468 if (lsfm_add_ucode_img(g, plsfm, &ucode_img,
469 pmu->falcon_id) == 0)
470 pmu->pmu_mode |= PMU_LSFM_MANAGED;
471
472 plsfm->managed_flcn_cnt++;
473 } else {
474 gp106_dbg_pmu("id not managed %d\n",
475 ucode_img.lsf_desc->falcon_id);
476 }
477 }
478
479 /*Free any ucode image resources if not managing this falcon*/
480 if (!(pmu->pmu_mode & PMU_LSFM_MANAGED)) {
481 gp106_dbg_pmu("pmu is not LSFM managed\n");
482 lsfm_free_ucode_img_res(g, &ucode_img);
483 }
484
485 /* Enumerate all constructed falcon objects,
486 as we need the ucode image info and total falcon count.*/
487
488 /*0th index is always PMU which is already handled in earlier
489 if condition*/
490 for (i = 1; i < (MAX_SUPPORTED_LSFM); i++) {
491 memset(&ucode_img, 0, sizeof(ucode_img));
492 if (pmu_acr_supp_ucode_list[i](g, &ucode_img) == 0) {
493 if (ucode_img.lsf_desc != NULL) {
494 /* We have engine sigs, ensure that this falcon
495 is aware of the secure mode expectations
496 (ACR status)*/
497
498 /* falon_id is formed by grabbing the static
499 base falonId from the image and adding the
500 engine-designated falcon instance. */
501 falcon_id = ucode_img.lsf_desc->falcon_id +
502 ucode_img.flcn_inst;
503
504 if (!lsfm_falcon_disabled(g, plsfm,
505 falcon_id)) {
506 /* Do not manage non-FB ucode*/
507 if (lsfm_add_ucode_img(g,
508 plsfm, &ucode_img, falcon_id)
509 == 0)
510 plsfm->managed_flcn_cnt++;
511 } else {
512 gp106_dbg_pmu("not managed %d\n",
513 ucode_img.lsf_desc->falcon_id);
514 lsfm_free_nonpmu_ucode_img_res(g,
515 &ucode_img);
516 }
517 }
518 } else {
519 /* Consumed all available falcon objects */
520 gp106_dbg_pmu("Done checking for ucodes %d\n", i);
521 break;
522 }
523 }
524 return 0;
525}
526
527int gp106_pmu_populate_loader_cfg(struct gk20a *g,
528 void *lsfm, u32 *p_bl_gen_desc_size)
529{
530 struct wpr_carveout_info wpr_inf;
531 struct nvgpu_pmu *pmu = &g->pmu;
532 struct lsfm_managed_ucode_img_v2 *p_lsfm =
533 (struct lsfm_managed_ucode_img_v2 *)lsfm;
534 struct flcn_ucode_img_v1 *p_img = &(p_lsfm->ucode_img);
535 struct flcn_bl_dmem_desc_v1 *ldr_cfg =
536 &(p_lsfm->bl_gen_desc.bl_dmem_desc_v1);
537 u64 addr_base;
538 struct pmu_ucode_desc_v1 *desc;
539 u64 addr_code, addr_data;
540 u32 addr_args;
541
542 if (p_img->desc == NULL) /*This means its a header based ucode,
543 and so we do not fill BL gen desc structure*/
544 return -EINVAL;
545 desc = p_img->desc;
546 /*
547 Calculate physical and virtual addresses for various portions of
548 the PMU ucode image
549 Calculate the 32-bit addresses for the application code, application
550 data, and bootloader code. These values are all based on IM_BASE.
551 The 32-bit addresses will be the upper 32-bits of the virtual or
552 physical addresses of each respective segment.
553 */
554 addr_base = p_lsfm->lsb_header.ucode_off;
555 g->ops.pmu.get_wpr(g, &wpr_inf);
556 addr_base += (wpr_inf.wpr_base);
557
558 gp106_dbg_pmu("pmu loader cfg addrbase 0x%llx\n", addr_base);
559 /*From linux*/
560 addr_code = addr_base +
561 desc->app_start_offset +
562 desc->app_resident_code_offset;
563 gp106_dbg_pmu("app start %d app res code off %d\n",
564 desc->app_start_offset, desc->app_resident_code_offset);
565 addr_data = addr_base +
566 desc->app_start_offset +
567 desc->app_resident_data_offset;
568 gp106_dbg_pmu("app res data offset%d\n",
569 desc->app_resident_data_offset);
570 gp106_dbg_pmu("bl start off %d\n", desc->bootloader_start_offset);
571
572 addr_args = ((pwr_falcon_hwcfg_dmem_size_v(
573 gk20a_readl(g, pwr_falcon_hwcfg_r())))
574 << GK20A_PMU_DMEM_BLKSIZE2);
575
576 addr_args -= g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu);
577
578 gp106_dbg_pmu("addr_args %x\n", addr_args);
579
580 /* Populate the LOADER_CONFIG state */
581 memset((void *) ldr_cfg, 0, sizeof(struct flcn_bl_dmem_desc_v1));
582 ldr_cfg->ctx_dma = GK20A_PMU_DMAIDX_UCODE;
583 flcn64_set_dma(&ldr_cfg->code_dma_base, addr_code);
584 ldr_cfg->non_sec_code_off = desc->app_resident_code_offset;
585 ldr_cfg->non_sec_code_size = desc->app_resident_code_size;
586 flcn64_set_dma(&ldr_cfg->data_dma_base, addr_data);
587 ldr_cfg->data_size = desc->app_resident_data_size;
588 ldr_cfg->code_entry_point = desc->app_imem_entry;
589
590 /* Update the argc/argv members*/
591 ldr_cfg->argc = 1;
592 ldr_cfg->argv = addr_args;
593
594 *p_bl_gen_desc_size = sizeof(struct flcn_bl_dmem_desc_v1);
595
596 g->acr.pmu_args = addr_args;
597 return 0;
598}
599
600int gp106_flcn_populate_bl_dmem_desc(struct gk20a *g,
601 void *lsfm, u32 *p_bl_gen_desc_size, u32 falconid)
602{
603 struct wpr_carveout_info wpr_inf;
604 struct lsfm_managed_ucode_img_v2 *p_lsfm =
605 (struct lsfm_managed_ucode_img_v2 *)lsfm;
606 struct flcn_ucode_img_v1 *p_img = &(p_lsfm->ucode_img);
607 struct flcn_bl_dmem_desc_v1 *ldr_cfg =
608 &(p_lsfm->bl_gen_desc.bl_dmem_desc_v1);
609 u64 addr_base;
610 struct pmu_ucode_desc_v1 *desc;
611 u64 addr_code, addr_data;
612
613 if (p_img->desc == NULL) /*This means its a header based ucode,
614 and so we do not fill BL gen desc structure*/
615 return -EINVAL;
616 desc = p_img->desc;
617
618 /*
619 Calculate physical and virtual addresses for various portions of
620 the PMU ucode image
621 Calculate the 32-bit addresses for the application code, application
622 data, and bootloader code. These values are all based on IM_BASE.
623 The 32-bit addresses will be the upper 32-bits of the virtual or
624 physical addresses of each respective segment.
625 */
626 addr_base = p_lsfm->lsb_header.ucode_off;
627 g->ops.pmu.get_wpr(g, &wpr_inf);
628 addr_base += wpr_inf.wpr_base;
629
630 gp106_dbg_pmu("falcon ID %x", p_lsfm->wpr_header.falcon_id);
631 gp106_dbg_pmu("gen loader cfg addrbase %llx ", addr_base);
632 addr_code = addr_base +
633 desc->app_start_offset +
634 desc->app_resident_code_offset;
635 addr_data = addr_base +
636 desc->app_start_offset +
637 desc->app_resident_data_offset;
638
639 gp106_dbg_pmu("gen cfg addrcode %llx data %llx load offset %x",
640 addr_code, addr_data, desc->bootloader_start_offset);
641
642 /* Populate the LOADER_CONFIG state */
643 memset((void *) ldr_cfg, 0, sizeof(struct flcn_bl_dmem_desc_v1));
644 ldr_cfg->ctx_dma = GK20A_PMU_DMAIDX_UCODE;
645 flcn64_set_dma(&ldr_cfg->code_dma_base, addr_code);
646 ldr_cfg->non_sec_code_size = desc->app_resident_code_size;
647 flcn64_set_dma(&ldr_cfg->data_dma_base, addr_data);
648 ldr_cfg->data_size = desc->app_resident_data_size;
649 ldr_cfg->code_entry_point = desc->app_imem_entry;
650
651 *p_bl_gen_desc_size = sizeof(struct flcn_bl_dmem_desc_v1);
652 return 0;
653}
654
655/* Populate falcon boot loader generic desc.*/
656int lsfm_fill_flcn_bl_gen_desc(struct gk20a *g,
657 struct lsfm_managed_ucode_img_v2 *pnode)
658{
659
660 struct nvgpu_pmu *pmu = &g->pmu;
661 if (pnode->wpr_header.falcon_id != pmu->falcon_id) {
662 gp106_dbg_pmu("non pmu. write flcn bl gen desc\n");
663 g->ops.pmu.flcn_populate_bl_dmem_desc(g,
664 pnode, &pnode->bl_gen_desc_size,
665 pnode->wpr_header.falcon_id);
666 return 0;
667 }
668
669 if (pmu->pmu_mode & PMU_LSFM_MANAGED) {
670 gp106_dbg_pmu("pmu write flcn bl gen desc\n");
671 if (pnode->wpr_header.falcon_id == pmu->falcon_id)
672 return g->ops.pmu.pmu_populate_loader_cfg(g, pnode,
673 &pnode->bl_gen_desc_size);
674 }
675
676 /* Failed to find the falcon requested. */
677 return -ENOENT;
678}
679
680/* Initialize WPR contents */
681void lsfm_init_wpr_contents(struct gk20a *g,
682 struct ls_flcn_mgr_v1 *plsfm, struct nvgpu_mem *ucode)
683{
684 struct lsfm_managed_ucode_img_v2 *pnode = plsfm->ucode_img_list;
685 struct lsf_wpr_header_v1 last_wpr_hdr;
686 u32 i;
687
688 /* The WPR array is at the base of the WPR */
689 pnode = plsfm->ucode_img_list;
690 memset(&last_wpr_hdr, 0, sizeof(struct lsf_wpr_header_v1));
691 i = 0;
692
693 /*
694 * Walk the managed falcons, flush WPR and LSB headers to FB.
695 * flush any bl args to the storage area relative to the
696 * ucode image (appended on the end as a DMEM area).
697 */
698 while (pnode) {
699 /* Flush WPR header to memory*/
700 nvgpu_mem_wr_n(g, ucode, i * sizeof(pnode->wpr_header),
701 &pnode->wpr_header, sizeof(pnode->wpr_header));
702
703 gp106_dbg_pmu("wpr header");
704 gp106_dbg_pmu("falconid :%d",
705 pnode->wpr_header.falcon_id);
706 gp106_dbg_pmu("lsb_offset :%x",
707 pnode->wpr_header.lsb_offset);
708 gp106_dbg_pmu("bootstrap_owner :%d",
709 pnode->wpr_header.bootstrap_owner);
710 gp106_dbg_pmu("lazy_bootstrap :%d",
711 pnode->wpr_header.lazy_bootstrap);
712 gp106_dbg_pmu("status :%d",
713 pnode->wpr_header.status);
714
715 /*Flush LSB header to memory*/
716 nvgpu_mem_wr_n(g, ucode, pnode->wpr_header.lsb_offset,
717 &pnode->lsb_header, sizeof(pnode->lsb_header));
718
719 gp106_dbg_pmu("lsb header");
720 gp106_dbg_pmu("ucode_off :%x",
721 pnode->lsb_header.ucode_off);
722 gp106_dbg_pmu("ucode_size :%x",
723 pnode->lsb_header.ucode_size);
724 gp106_dbg_pmu("data_size :%x",
725 pnode->lsb_header.data_size);
726 gp106_dbg_pmu("bl_code_size :%x",
727 pnode->lsb_header.bl_code_size);
728 gp106_dbg_pmu("bl_imem_off :%x",
729 pnode->lsb_header.bl_imem_off);
730 gp106_dbg_pmu("bl_data_off :%x",
731 pnode->lsb_header.bl_data_off);
732 gp106_dbg_pmu("bl_data_size :%x",
733 pnode->lsb_header.bl_data_size);
734 gp106_dbg_pmu("app_code_off :%x",
735 pnode->lsb_header.app_code_off);
736 gp106_dbg_pmu("app_code_size :%x",
737 pnode->lsb_header.app_code_size);
738 gp106_dbg_pmu("app_data_off :%x",
739 pnode->lsb_header.app_data_off);
740 gp106_dbg_pmu("app_data_size :%x",
741 pnode->lsb_header.app_data_size);
742 gp106_dbg_pmu("flags :%x",
743 pnode->lsb_header.flags);
744
745 /*If this falcon has a boot loader and related args,
746 * flush them.*/
747 if (!pnode->ucode_img.header) {
748 /*Populate gen bl and flush to memory*/
749 lsfm_fill_flcn_bl_gen_desc(g, pnode);
750 nvgpu_mem_wr_n(g, ucode,
751 pnode->lsb_header.bl_data_off,
752 &pnode->bl_gen_desc,
753 pnode->bl_gen_desc_size);
754 }
755 /*Copying of ucode*/
756 nvgpu_mem_wr_n(g, ucode, pnode->lsb_header.ucode_off,
757 pnode->ucode_img.data,
758 pnode->ucode_img.data_size);
759 pnode = pnode->next;
760 i++;
761 }
762
763 /* Tag the terminator WPR header with an invalid falcon ID. */
764 last_wpr_hdr.falcon_id = LSF_FALCON_ID_INVALID;
765 nvgpu_mem_wr_n(g, ucode,
766 plsfm->managed_flcn_cnt * sizeof(struct lsf_wpr_header_v1),
767 &last_wpr_hdr,
768 sizeof(struct lsf_wpr_header_v1));
769}
770
771/*!
772 * lsfm_parse_no_loader_ucode: parses UCODE header of falcon
773 *
774 * @param[in] p_ucodehdr : UCODE header
775 * @param[out] lsb_hdr : updates values in LSB header
776 *
777 * @return 0
778 */
779static int lsfm_parse_no_loader_ucode(u32 *p_ucodehdr,
780 struct lsf_lsb_header_v1 *lsb_hdr)
781{
782
783 u32 code_size = 0;
784 u32 data_size = 0;
785 u32 i = 0;
786 u32 total_apps = p_ucodehdr[FLCN_NL_UCODE_HDR_NUM_APPS_IND];
787
788 /* Lets calculate code size*/
789 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_CODE_SIZE_IND];
790 for (i = 0; i < total_apps; i++) {
791 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_APP_CODE_SIZE_IND
792 (total_apps, i)];
793 }
794 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_OVL_SIZE_IND(total_apps)];
795
796 /* Calculate data size*/
797 data_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_SIZE_IND];
798 for (i = 0; i < total_apps; i++) {
799 data_size += p_ucodehdr[FLCN_NL_UCODE_HDR_APP_DATA_SIZE_IND
800 (total_apps, i)];
801 }
802
803 lsb_hdr->ucode_size = code_size;
804 lsb_hdr->data_size = data_size;
805 lsb_hdr->bl_code_size = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_CODE_SIZE_IND];
806 lsb_hdr->bl_imem_off = 0;
807 lsb_hdr->bl_data_off = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_OFF_IND];
808 lsb_hdr->bl_data_size = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_SIZE_IND];
809 return 0;
810}
811
812/*!
813 * @brief lsfm_fill_static_lsb_hdr_info
814 * Populate static LSB header infomation using the provided ucode image
815 */
816void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
817 u32 falcon_id, struct lsfm_managed_ucode_img_v2 *pnode)
818{
819
820 struct nvgpu_pmu *pmu = &g->pmu;
821 u32 full_app_size = 0;
822 u32 data = 0;
823
824 if (pnode->ucode_img.lsf_desc)
825 memcpy(&pnode->lsb_header.signature, pnode->ucode_img.lsf_desc,
826 sizeof(struct lsf_ucode_desc_v1));
827 pnode->lsb_header.ucode_size = pnode->ucode_img.data_size;
828
829 /* The remainder of the LSB depends on the loader usage */
830 if (pnode->ucode_img.header) {
831 /* Does not use a loader */
832 pnode->lsb_header.data_size = 0;
833 pnode->lsb_header.bl_code_size = 0;
834 pnode->lsb_header.bl_data_off = 0;
835 pnode->lsb_header.bl_data_size = 0;
836
837 lsfm_parse_no_loader_ucode(pnode->ucode_img.header,
838 &(pnode->lsb_header));
839
840 /* Load the first 256 bytes of IMEM. */
841 /* Set LOAD_CODE_AT_0 and DMACTL_REQ_CTX.
842 True for all method based falcons */
843 data = NV_FLCN_ACR_LSF_FLAG_LOAD_CODE_AT_0_TRUE |
844 NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE;
845 pnode->lsb_header.flags = data;
846 } else {
847 /* Uses a loader. that is has a desc */
848 pnode->lsb_header.data_size = 0;
849
850 /* The loader code size is already aligned (padded) such that
851 the code following it is aligned, but the size in the image
852 desc is not, bloat it up to be on a 256 byte alignment. */
853 pnode->lsb_header.bl_code_size = ALIGN(
854 pnode->ucode_img.desc->bootloader_size,
855 LSF_BL_CODE_SIZE_ALIGNMENT);
856 full_app_size = ALIGN(pnode->ucode_img.desc->app_size,
857 LSF_BL_CODE_SIZE_ALIGNMENT) +
858 pnode->lsb_header.bl_code_size;
859 pnode->lsb_header.ucode_size = ALIGN(
860 pnode->ucode_img.desc->app_resident_data_offset,
861 LSF_BL_CODE_SIZE_ALIGNMENT) +
862 pnode->lsb_header.bl_code_size;
863 pnode->lsb_header.data_size = full_app_size -
864 pnode->lsb_header.ucode_size;
865 /* Though the BL is located at 0th offset of the image, the VA
866 is different to make sure that it doesnt collide the actual OS
867 VA range */
868 pnode->lsb_header.bl_imem_off =
869 pnode->ucode_img.desc->bootloader_imem_offset;
870
871 /* TODO: OBJFLCN should export properties using which the below
872 flags should be populated.*/
873 pnode->lsb_header.flags = 0;
874
875 if (falcon_id == pmu->falcon_id) {
876 data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE;
877 pnode->lsb_header.flags = data;
878 }
879
880 if(g->ops.pmu.is_priv_load(falcon_id))
881 pnode->lsb_header.flags |=
882 NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE;
883 }
884}
885
886/* Adds a ucode image to the list of managed ucode images managed. */
887int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr_v1 *plsfm,
888 struct flcn_ucode_img_v1 *ucode_image, u32 falcon_id)
889{
890 struct lsfm_managed_ucode_img_v2 *pnode;
891
892 pnode = nvgpu_kzalloc(g, sizeof(struct lsfm_managed_ucode_img_v2));
893 if (pnode == NULL)
894 return -ENOMEM;
895
896 /* Keep a copy of the ucode image info locally */
897 memcpy(&pnode->ucode_img, ucode_image, sizeof(struct flcn_ucode_img_v1));
898
899 /* Fill in static WPR header info*/
900 pnode->wpr_header.falcon_id = falcon_id;
901 pnode->wpr_header.bootstrap_owner = g->bootstrap_owner;
902 pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY;
903
904 pnode->wpr_header.lazy_bootstrap =
905 g->ops.pmu.is_lazy_bootstrap(falcon_id);
906
907 /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by
908 Android */
909 /* Fill in static LSB header info elsewhere */
910 lsfm_fill_static_lsb_hdr_info(g, falcon_id, pnode);
911 pnode->wpr_header.bin_version = pnode->lsb_header.signature.version;
912 pnode->next = plsfm->ucode_img_list;
913 plsfm->ucode_img_list = pnode;
914 return 0;
915}
916
917/* Free any ucode image structure resources. */
918void lsfm_free_ucode_img_res(struct gk20a *g,
919 struct flcn_ucode_img_v1 *p_img)
920{
921 if (p_img->lsf_desc != NULL) {
922 nvgpu_kfree(g, p_img->lsf_desc);
923 p_img->lsf_desc = NULL;
924 }
925}
926
927/* Free any ucode image structure resources. */
928void lsfm_free_nonpmu_ucode_img_res(struct gk20a *g,
929 struct flcn_ucode_img_v1 *p_img)
930{
931 if (p_img->lsf_desc != NULL) {
932 nvgpu_kfree(g, p_img->lsf_desc);
933 p_img->lsf_desc = NULL;
934 }
935 if (p_img->desc != NULL) {
936 nvgpu_kfree(g, p_img->desc);
937 p_img->desc = NULL;
938 }
939}
940
941void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr_v1 *plsfm)
942{
943 u32 cnt = plsfm->managed_flcn_cnt;
944 struct lsfm_managed_ucode_img_v2 *mg_ucode_img;
945
946 while (cnt) {
947 mg_ucode_img = plsfm->ucode_img_list;
948 if (mg_ucode_img->ucode_img.lsf_desc->falcon_id ==
949 LSF_FALCON_ID_PMU)
950 lsfm_free_ucode_img_res(g, &mg_ucode_img->ucode_img);
951 else
952 lsfm_free_nonpmu_ucode_img_res(g,
953 &mg_ucode_img->ucode_img);
954 plsfm->ucode_img_list = mg_ucode_img->next;
955 nvgpu_kfree(g, mg_ucode_img);
956 cnt--;
957 }
958}
959
960/* Generate WPR requirements for ACR allocation request */
961int lsf_gen_wpr_requirements(struct gk20a *g,
962 struct ls_flcn_mgr_v1 *plsfm)
963{
964 struct lsfm_managed_ucode_img_v2 *pnode = plsfm->ucode_img_list;
965 u32 wpr_offset;
966
967 /* Calculate WPR size required */
968
969 /* Start with an array of WPR headers at the base of the WPR.
970 The expectation here is that the secure falcon will do a single DMA
971 read of this array and cache it internally so it's OK to pack these.
972 Also, we add 1 to the falcon count to indicate the end of the array.*/
973 wpr_offset = sizeof(struct lsf_wpr_header_v1) *
974 (plsfm->managed_flcn_cnt+1);
975
976 /* Walk the managed falcons, accounting for the LSB structs
977 as well as the ucode images. */
978 while (pnode) {
979 /* Align, save off, and include an LSB header size */
980 wpr_offset = ALIGN(wpr_offset,
981 LSF_LSB_HEADER_ALIGNMENT);
982 pnode->wpr_header.lsb_offset = wpr_offset;
983 wpr_offset += sizeof(struct lsf_lsb_header_v1);
984
985 /* Align, save off, and include the original (static)
986 ucode image size */
987 wpr_offset = ALIGN(wpr_offset,
988 LSF_UCODE_DATA_ALIGNMENT);
989 pnode->lsb_header.ucode_off = wpr_offset;
990 wpr_offset += pnode->ucode_img.data_size;
991
992 /* For falcons that use a boot loader (BL), we append a loader
993 desc structure on the end of the ucode image and consider this
994 the boot loader data. The host will then copy the loader desc
995 args to this space within the WPR region (before locking down)
996 and the HS bin will then copy them to DMEM 0 for the loader. */
997 if (!pnode->ucode_img.header) {
998 /* Track the size for LSB details filled in later
999 Note that at this point we don't know what kind of i
1000 boot loader desc, so we just take the size of the
1001 generic one, which is the largest it will will ever be.
1002 */
1003 /* Align (size bloat) and save off generic
1004 descriptor size*/
1005 pnode->lsb_header.bl_data_size = ALIGN(
1006 sizeof(pnode->bl_gen_desc),
1007 LSF_BL_DATA_SIZE_ALIGNMENT);
1008
1009 /*Align, save off, and include the additional BL data*/
1010 wpr_offset = ALIGN(wpr_offset,
1011 LSF_BL_DATA_ALIGNMENT);
1012 pnode->lsb_header.bl_data_off = wpr_offset;
1013 wpr_offset += pnode->lsb_header.bl_data_size;
1014 } else {
1015 /* bl_data_off is already assigned in static
1016 information. But that is from start of the image */
1017 pnode->lsb_header.bl_data_off +=
1018 (wpr_offset - pnode->ucode_img.data_size);
1019 }
1020
1021 /* Finally, update ucode surface size to include updates */
1022 pnode->full_ucode_size = wpr_offset -
1023 pnode->lsb_header.ucode_off;
1024 if (pnode->wpr_header.falcon_id != LSF_FALCON_ID_PMU) {
1025 pnode->lsb_header.app_code_off =
1026 pnode->lsb_header.bl_code_size;
1027 pnode->lsb_header.app_code_size =
1028 pnode->lsb_header.ucode_size -
1029 pnode->lsb_header.bl_code_size;
1030 pnode->lsb_header.app_data_off =
1031 pnode->lsb_header.ucode_size;
1032 pnode->lsb_header.app_data_size =
1033 pnode->lsb_header.data_size;
1034 }
1035 pnode = pnode->next;
1036 }
1037 plsfm->wpr_size = wpr_offset;
1038 return 0;
1039}
1040
1041/*Loads ACR bin to FB mem and bootstraps PMU with bootloader code
1042 * start and end are addresses of ucode blob in non-WPR region*/
1043int gp106_bootstrap_hs_flcn(struct gk20a *g)
1044{
1045 struct mm_gk20a *mm = &g->mm;
1046 struct vm_gk20a *vm = mm->pmu.vm;
1047 int err = 0;
1048 u64 *acr_dmem;
1049 u32 img_size_in_bytes = 0;
1050 u32 status;
1051 struct acr_desc *acr = &g->acr;
1052 struct nvgpu_firmware *acr_fw = acr->acr_fw;
1053 struct flcn_bl_dmem_desc_v1 *bl_dmem_desc = &acr->bl_dmem_desc_v1;
1054 u32 *acr_ucode_header_t210_load;
1055 u32 *acr_ucode_data_t210_load;
1056 struct wpr_carveout_info wpr_inf;
1057
1058 gp106_dbg_pmu("");
1059
1060 if (!acr_fw) {
1061 /*First time init case*/
1062 acr_fw = nvgpu_request_firmware(g,
1063 GM20B_HSBIN_PMU_UCODE_IMAGE,
1064 NVGPU_REQUEST_FIRMWARE_NO_SOC);
1065 if (!acr_fw) {
1066 nvgpu_err(g, "pmu ucode get fail");
1067 return -ENOENT;
1068 }
1069 acr->acr_fw = acr_fw;
1070 acr->hsbin_hdr = (struct bin_hdr *)acr_fw->data;
1071 acr->fw_hdr = (struct acr_fw_header *)(acr_fw->data +
1072 acr->hsbin_hdr->header_offset);
1073 acr_ucode_data_t210_load = (u32 *)(acr_fw->data +
1074 acr->hsbin_hdr->data_offset);
1075 acr_ucode_header_t210_load = (u32 *)(acr_fw->data +
1076 acr->fw_hdr->hdr_offset);
1077 img_size_in_bytes = ALIGN((acr->hsbin_hdr->data_size), 256);
1078
1079 /* Lets patch the signatures first.. */
1080 if (acr_ucode_patch_sig(g, acr_ucode_data_t210_load,
1081 (u32 *)(acr_fw->data +
1082 acr->fw_hdr->sig_prod_offset),
1083 (u32 *)(acr_fw->data +
1084 acr->fw_hdr->sig_dbg_offset),
1085 (u32 *)(acr_fw->data +
1086 acr->fw_hdr->patch_loc),
1087 (u32 *)(acr_fw->data +
1088 acr->fw_hdr->patch_sig)) < 0) {
1089 nvgpu_err(g, "patch signatures fail");
1090 err = -1;
1091 goto err_release_acr_fw;
1092 }
1093 err = nvgpu_dma_alloc_map_sys(vm, img_size_in_bytes,
1094 &acr->acr_ucode);
1095 if (err) {
1096 err = -ENOMEM;
1097 goto err_release_acr_fw;
1098 }
1099
1100 g->ops.pmu.get_wpr(g, &wpr_inf);
1101
1102 acr_dmem = (u64 *)
1103 &(((u8 *)acr_ucode_data_t210_load)[
1104 acr_ucode_header_t210_load[2]]);
1105 acr->acr_dmem_desc_v1 = (struct flcn_acr_desc_v1 *)((u8 *)(
1106 acr->acr_ucode.cpu_va) + acr_ucode_header_t210_load[2]);
1107 ((struct flcn_acr_desc_v1 *)acr_dmem)->nonwpr_ucode_blob_start =
1108 wpr_inf.nonwpr_base;
1109 ((struct flcn_acr_desc_v1 *)acr_dmem)->nonwpr_ucode_blob_size =
1110 wpr_inf.size;
1111 ((struct flcn_acr_desc_v1 *)acr_dmem)->regions.no_regions = 1;
1112 ((struct flcn_acr_desc_v1 *)acr_dmem)->wpr_offset = 0;
1113
1114 ((struct flcn_acr_desc_v1 *)acr_dmem)->wpr_region_id = 1;
1115 ((struct flcn_acr_desc_v1 *)acr_dmem)->regions.region_props[
1116 0].region_id = 1;
1117 ((struct flcn_acr_desc_v1 *)acr_dmem)->regions.region_props[
1118 0].start_addr = (wpr_inf.wpr_base ) >> 8;
1119 ((struct flcn_acr_desc_v1 *)acr_dmem)->regions.region_props[
1120 0].end_addr = ((wpr_inf.wpr_base) + wpr_inf.size) >> 8;
1121 ((struct flcn_acr_desc_v1 *)acr_dmem)->regions.region_props[
1122 0].shadowmMem_startaddress = wpr_inf.nonwpr_base >> 8;
1123
1124 nvgpu_mem_wr_n(g, &acr->acr_ucode, 0,
1125 acr_ucode_data_t210_load, img_size_in_bytes);
1126
1127 /*
1128 * In order to execute this binary, we will be using
1129 * a bootloader which will load this image into PMU IMEM/DMEM.
1130 * Fill up the bootloader descriptor for PMU HAL to use..
1131 * TODO: Use standard descriptor which the generic bootloader is
1132 * checked in.
1133 */
1134
1135 bl_dmem_desc->signature[0] = 0;
1136 bl_dmem_desc->signature[1] = 0;
1137 bl_dmem_desc->signature[2] = 0;
1138 bl_dmem_desc->signature[3] = 0;
1139 bl_dmem_desc->ctx_dma = GK20A_PMU_DMAIDX_VIRT;
1140 flcn64_set_dma( &bl_dmem_desc->code_dma_base,
1141 acr->acr_ucode.gpu_va);
1142 bl_dmem_desc->non_sec_code_off = acr_ucode_header_t210_load[0];
1143 bl_dmem_desc->non_sec_code_size = acr_ucode_header_t210_load[1];
1144 bl_dmem_desc->sec_code_off = acr_ucode_header_t210_load[5];
1145 bl_dmem_desc->sec_code_size = acr_ucode_header_t210_load[6];
1146 bl_dmem_desc->code_entry_point = 0; /* Start at 0th offset */
1147 flcn64_set_dma( &bl_dmem_desc->data_dma_base,
1148 acr->acr_ucode.gpu_va +
1149 (acr_ucode_header_t210_load[2]));
1150 bl_dmem_desc->data_size = acr_ucode_header_t210_load[3];
1151 } else
1152 acr->acr_dmem_desc->nonwpr_ucode_blob_size = 0;
1153
1154 status = pmu_exec_gen_bl(g, bl_dmem_desc, 1);
1155 if (status != 0) {
1156 err = status;
1157 goto err_free_ucode_map;
1158 }
1159
1160 /* sec2 reset - to keep it idle */
1161 gk20a_writel(g, psec_falcon_engine_r(),
1162 pwr_falcon_engine_reset_true_f());
1163 nvgpu_udelay(10);
1164 gk20a_writel(g, psec_falcon_engine_r(),
1165 pwr_falcon_engine_reset_false_f());
1166
1167 return 0;
1168err_free_ucode_map:
1169 nvgpu_dma_unmap_free(vm, &acr->acr_ucode);
1170err_release_acr_fw:
1171 nvgpu_release_firmware(g, acr_fw);
1172 acr->acr_fw = NULL;
1173 return err;
1174}