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