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