summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/acr_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/acr_gm20b.c1444
1 files changed, 1444 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
new file mode 100644
index 00000000..a39cdf2c
--- /dev/null
+++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
@@ -0,0 +1,1444 @@
1/*
2 * Copyright (c) 2015-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/types.h>
24#include <nvgpu/dma.h>
25#include <nvgpu/gmmu.h>
26#include <nvgpu/timers.h>
27#include <nvgpu/nvgpu_common.h>
28#include <nvgpu/kmem.h>
29#include <nvgpu/nvgpu_mem.h>
30#include <nvgpu/acr/nvgpu_acr.h>
31#include <nvgpu/firmware.h>
32#include <nvgpu/pmu.h>
33#include <nvgpu/falcon.h>
34#include <nvgpu/enabled.h>
35#include <nvgpu/mm.h>
36
37#include "gk20a/gk20a.h"
38#include "gk20a/pmu_gk20a.h"
39#include "mm_gm20b.h"
40#include "acr_gm20b.h"
41
42#include <nvgpu/hw/gm20b/hw_pwr_gm20b.h>
43
44/*Defines*/
45#define gm20b_dbg_pmu(fmt, arg...) \
46 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
47
48typedef int (*get_ucode_details)(struct gk20a *g, struct flcn_ucode_img *udata);
49
50/*Externs*/
51
52/*Forwards*/
53static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
54static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
55static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
56static int lsfm_discover_ucode_images(struct gk20a *g,
57 struct ls_flcn_mgr *plsfm);
58static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm,
59 struct flcn_ucode_img *ucode_image, u32 falcon_id);
60static void lsfm_free_ucode_img_res(struct gk20a *g,
61 struct flcn_ucode_img *p_img);
62static void lsfm_free_nonpmu_ucode_img_res(struct gk20a *g,
63 struct flcn_ucode_img *p_img);
64static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm);
65static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm,
66 struct nvgpu_mem *nonwpr);
67static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm);
68
69/*Globals*/
70static get_ucode_details pmu_acr_supp_ucode_list[] = {
71 pmu_ucode_details,
72 fecs_ucode_details,
73 gpccs_ucode_details,
74};
75
76/*Once is LS mode, cpuctl_alias is only accessible*/
77static void start_gm20b_pmu(struct gk20a *g)
78{
79 /*disable irqs for hs falcon booting as we will poll for halt*/
80 nvgpu_mutex_acquire(&g->pmu.isr_mutex);
81 pmu_enable_irq(&g->pmu, true);
82 g->pmu.isr_enabled = true;
83 nvgpu_mutex_release(&g->pmu.isr_mutex);
84 gk20a_writel(g, pwr_falcon_cpuctl_alias_r(),
85 pwr_falcon_cpuctl_startcpu_f(1));
86}
87
88void gm20b_wpr_info(struct gk20a *g, struct wpr_carveout_info *inf)
89{
90 g->ops.fb.read_wpr_info(g, inf);
91}
92
93bool gm20b_is_pmu_supported(struct gk20a *g)
94{
95 return true;
96}
97
98static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
99{
100 struct nvgpu_firmware *pmu_fw, *pmu_desc, *pmu_sig;
101 struct nvgpu_pmu *pmu = &g->pmu;
102 struct lsf_ucode_desc *lsf_desc;
103 int err;
104 gm20b_dbg_pmu("requesting PMU ucode in GM20B\n");
105 pmu_fw = nvgpu_request_firmware(g, GM20B_PMU_UCODE_IMAGE, 0);
106 if (!pmu_fw) {
107 nvgpu_err(g, "failed to load pmu ucode!!");
108 return -ENOENT;
109 }
110 g->acr.pmu_fw = pmu_fw;
111 gm20b_dbg_pmu("Loaded PMU ucode in for blob preparation");
112
113 gm20b_dbg_pmu("requesting PMU ucode desc in GM20B\n");
114 pmu_desc = nvgpu_request_firmware(g, GM20B_PMU_UCODE_DESC, 0);
115 if (!pmu_desc) {
116 nvgpu_err(g, "failed to load pmu ucode desc!!");
117 err = -ENOENT;
118 goto release_img_fw;
119 }
120 pmu_sig = nvgpu_request_firmware(g, GM20B_PMU_UCODE_SIG, 0);
121 if (!pmu_sig) {
122 nvgpu_err(g, "failed to load pmu sig!!");
123 err = -ENOENT;
124 goto release_desc;
125 }
126 pmu->desc = (struct pmu_ucode_desc *)pmu_desc->data;
127 pmu->ucode_image = (u32 *)pmu_fw->data;
128 g->acr.pmu_desc = pmu_desc;
129
130 err = nvgpu_init_pmu_fw_support(pmu);
131 if (err) {
132 gm20b_dbg_pmu("failed to set function pointers\n");
133 goto release_sig;
134 }
135
136 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
137 if (!lsf_desc) {
138 err = -ENOMEM;
139 goto release_sig;
140 }
141 memcpy(lsf_desc, (void *)pmu_sig->data, sizeof(struct lsf_ucode_desc));
142 lsf_desc->falcon_id = LSF_FALCON_ID_PMU;
143
144 p_img->desc = pmu->desc;
145 p_img->data = pmu->ucode_image;
146 p_img->data_size = pmu->desc->image_size;
147 p_img->fw_ver = NULL;
148 p_img->header = NULL;
149 p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
150 gm20b_dbg_pmu("requesting PMU ucode in GM20B exit\n");
151 nvgpu_release_firmware(g, pmu_sig);
152 return 0;
153release_sig:
154 nvgpu_release_firmware(g, pmu_sig);
155release_desc:
156 nvgpu_release_firmware(g, pmu_desc);
157 g->acr.pmu_desc = NULL;
158release_img_fw:
159 nvgpu_release_firmware(g, pmu_fw);
160 g->acr.pmu_fw = NULL;
161 return err;
162}
163
164static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
165{
166 struct lsf_ucode_desc *lsf_desc;
167 struct nvgpu_firmware *fecs_sig;
168 int err;
169
170 fecs_sig = nvgpu_request_firmware(g, GM20B_FECS_UCODE_SIG, 0);
171 if (!fecs_sig) {
172 nvgpu_err(g, "failed to load fecs sig");
173 return -ENOENT;
174 }
175 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
176 if (!lsf_desc) {
177 err = -ENOMEM;
178 goto rel_sig;
179 }
180 memcpy(lsf_desc, (void *)fecs_sig->data, sizeof(struct lsf_ucode_desc));
181 lsf_desc->falcon_id = LSF_FALCON_ID_FECS;
182
183 p_img->desc = nvgpu_kzalloc(g, sizeof(struct pmu_ucode_desc));
184 if (p_img->desc == NULL) {
185 err = -ENOMEM;
186 goto free_lsf_desc;
187 }
188
189 p_img->desc->bootloader_start_offset =
190 g->ctxsw_ucode_info.fecs.boot.offset;
191 p_img->desc->bootloader_size =
192 ALIGN(g->ctxsw_ucode_info.fecs.boot.size, 256);
193 p_img->desc->bootloader_imem_offset =
194 g->ctxsw_ucode_info.fecs.boot_imem_offset;
195 p_img->desc->bootloader_entry_point =
196 g->ctxsw_ucode_info.fecs.boot_entry;
197
198 p_img->desc->image_size =
199 ALIGN(g->ctxsw_ucode_info.fecs.boot.size, 256) +
200 ALIGN(g->ctxsw_ucode_info.fecs.code.size, 256) +
201 ALIGN(g->ctxsw_ucode_info.fecs.data.size, 256);
202 p_img->desc->app_size = ALIGN(g->ctxsw_ucode_info.fecs.code.size, 256) +
203 ALIGN(g->ctxsw_ucode_info.fecs.data.size, 256);
204 p_img->desc->app_start_offset = g->ctxsw_ucode_info.fecs.code.offset;
205 p_img->desc->app_imem_offset = 0;
206 p_img->desc->app_imem_entry = 0;
207 p_img->desc->app_dmem_offset = 0;
208 p_img->desc->app_resident_code_offset = 0;
209 p_img->desc->app_resident_code_size =
210 g->ctxsw_ucode_info.fecs.code.size;
211 p_img->desc->app_resident_data_offset =
212 g->ctxsw_ucode_info.fecs.data.offset -
213 g->ctxsw_ucode_info.fecs.code.offset;
214 p_img->desc->app_resident_data_size =
215 g->ctxsw_ucode_info.fecs.data.size;
216 p_img->data = g->ctxsw_ucode_info.surface_desc.cpu_va;
217 p_img->data_size = p_img->desc->image_size;
218
219 p_img->fw_ver = NULL;
220 p_img->header = NULL;
221 p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
222 gm20b_dbg_pmu("fecs fw loaded\n");
223 nvgpu_release_firmware(g, fecs_sig);
224 return 0;
225free_lsf_desc:
226 nvgpu_kfree(g, lsf_desc);
227rel_sig:
228 nvgpu_release_firmware(g, fecs_sig);
229 return err;
230}
231static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
232{
233 struct lsf_ucode_desc *lsf_desc;
234 struct nvgpu_firmware *gpccs_sig;
235 int err;
236
237 if (!nvgpu_is_enabled(g, NVGPU_SEC_SECUREGPCCS))
238 return -ENOENT;
239
240 gpccs_sig = nvgpu_request_firmware(g, T18x_GPCCS_UCODE_SIG, 0);
241 if (!gpccs_sig) {
242 nvgpu_err(g, "failed to load gpccs sig");
243 return -ENOENT;
244 }
245 lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
246 if (!lsf_desc) {
247 err = -ENOMEM;
248 goto rel_sig;
249 }
250 memcpy(lsf_desc, (void *)gpccs_sig->data,
251 sizeof(struct lsf_ucode_desc));
252 lsf_desc->falcon_id = LSF_FALCON_ID_GPCCS;
253
254 p_img->desc = nvgpu_kzalloc(g, sizeof(struct pmu_ucode_desc));
255 if (p_img->desc == NULL) {
256 err = -ENOMEM;
257 goto free_lsf_desc;
258 }
259
260 p_img->desc->bootloader_start_offset =
261 0;
262 p_img->desc->bootloader_size =
263 ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256);
264 p_img->desc->bootloader_imem_offset =
265 g->ctxsw_ucode_info.gpccs.boot_imem_offset;
266 p_img->desc->bootloader_entry_point =
267 g->ctxsw_ucode_info.gpccs.boot_entry;
268
269 p_img->desc->image_size =
270 ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256) +
271 ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256) +
272 ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
273 p_img->desc->app_size = ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256)
274 + ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
275 p_img->desc->app_start_offset = p_img->desc->bootloader_size;
276 p_img->desc->app_imem_offset = 0;
277 p_img->desc->app_imem_entry = 0;
278 p_img->desc->app_dmem_offset = 0;
279 p_img->desc->app_resident_code_offset = 0;
280 p_img->desc->app_resident_code_size =
281 ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256);
282 p_img->desc->app_resident_data_offset =
283 ALIGN(g->ctxsw_ucode_info.gpccs.data.offset, 256) -
284 ALIGN(g->ctxsw_ucode_info.gpccs.code.offset, 256);
285 p_img->desc->app_resident_data_size =
286 ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256);
287 p_img->data = (u32 *)((u8 *)g->ctxsw_ucode_info.surface_desc.cpu_va +
288 g->ctxsw_ucode_info.gpccs.boot.offset);
289 p_img->data_size = ALIGN(p_img->desc->image_size, 256);
290 p_img->fw_ver = NULL;
291 p_img->header = NULL;
292 p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
293 gm20b_dbg_pmu("gpccs fw loaded\n");
294 nvgpu_release_firmware(g, gpccs_sig);
295 return 0;
296free_lsf_desc:
297 nvgpu_kfree(g, lsf_desc);
298rel_sig:
299 nvgpu_release_firmware(g, gpccs_sig);
300 return err;
301}
302
303bool gm20b_is_lazy_bootstrap(u32 falcon_id)
304{
305 bool enable_status = false;
306
307 switch (falcon_id) {
308 case LSF_FALCON_ID_FECS:
309 enable_status = false;
310 break;
311 case LSF_FALCON_ID_GPCCS:
312 enable_status = false;
313 break;
314 default:
315 break;
316 }
317
318 return enable_status;
319}
320
321bool gm20b_is_priv_load(u32 falcon_id)
322{
323 bool enable_status = false;
324
325 switch (falcon_id) {
326 case LSF_FALCON_ID_FECS:
327 enable_status = false;
328 break;
329 case LSF_FALCON_ID_GPCCS:
330 enable_status = false;
331 break;
332 default:
333 break;
334 }
335
336 return enable_status;
337}
338
339int gm20b_alloc_blob_space(struct gk20a *g,
340 size_t size, struct nvgpu_mem *mem)
341{
342 int err;
343
344 err = nvgpu_dma_alloc_sys(g, size, mem);
345
346 return err;
347}
348
349int prepare_ucode_blob(struct gk20a *g)
350{
351
352 int err;
353 struct ls_flcn_mgr lsfm_l, *plsfm;
354 struct nvgpu_pmu *pmu = &g->pmu;
355 struct wpr_carveout_info wpr_inf;
356
357 if (g->acr.ucode_blob.cpu_va) {
358 /*Recovery case, we do not need to form
359 non WPR blob of ucodes*/
360 err = nvgpu_init_pmu_fw_support(pmu);
361 if (err) {
362 gm20b_dbg_pmu("failed to set function pointers\n");
363 return err;
364 }
365 return 0;
366 }
367 plsfm = &lsfm_l;
368 memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr));
369 gm20b_dbg_pmu("fetching GMMU regs\n");
370 g->ops.fb.vpr_info_fetch(g);
371 gr_gk20a_init_ctxsw_ucode(g);
372
373 g->ops.pmu.get_wpr(g, &wpr_inf);
374 gm20b_dbg_pmu("wpr carveout base:%llx\n", wpr_inf.wpr_base);
375 gm20b_dbg_pmu("wpr carveout size :%llx\n", wpr_inf.size);
376
377 /* Discover all managed falcons*/
378 err = lsfm_discover_ucode_images(g, plsfm);
379 gm20b_dbg_pmu(" Managed Falcon cnt %d\n", plsfm->managed_flcn_cnt);
380 if (err)
381 goto free_sgt;
382
383 if (plsfm->managed_flcn_cnt && !g->acr.ucode_blob.cpu_va) {
384 /* Generate WPR requirements*/
385 err = lsf_gen_wpr_requirements(g, plsfm);
386 if (err)
387 goto free_sgt;
388
389 /*Alloc memory to hold ucode blob contents*/
390 err = g->ops.pmu.alloc_blob_space(g, plsfm->wpr_size
391 , &g->acr.ucode_blob);
392 if (err)
393 goto free_sgt;
394
395 gm20b_dbg_pmu("managed LS falcon %d, WPR size %d bytes.\n",
396 plsfm->managed_flcn_cnt, plsfm->wpr_size);
397 lsfm_init_wpr_contents(g, plsfm, &g->acr.ucode_blob);
398 } else {
399 gm20b_dbg_pmu("LSFM is managing no falcons.\n");
400 }
401 gm20b_dbg_pmu("prepare ucode blob return 0\n");
402 free_acr_resources(g, plsfm);
403free_sgt:
404 return err;
405}
406
407static u8 lsfm_falcon_disabled(struct gk20a *g, struct ls_flcn_mgr *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 *plsfm)
416{
417 struct nvgpu_pmu *pmu = &g->pmu;
418 struct flcn_ucode_img 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)
428 return status;
429
430 /* The falon_id is formed by grabbing the static base
431 * falon_id from the image and adding the
432 * engine-designated falcon instance.*/
433 pmu->pmu_mode |= PMU_SECURE_MODE;
434 falcon_id = ucode_img.lsf_desc->falcon_id +
435 ucode_img.flcn_inst;
436
437 if (!lsfm_falcon_disabled(g, plsfm, falcon_id)) {
438 pmu->falcon_id = falcon_id;
439 if (lsfm_add_ucode_img(g, plsfm, &ucode_img,
440 pmu->falcon_id) == 0)
441 pmu->pmu_mode |= PMU_LSFM_MANAGED;
442
443 plsfm->managed_flcn_cnt++;
444 } else {
445 gm20b_dbg_pmu("id not managed %d\n",
446 ucode_img.lsf_desc->falcon_id);
447 }
448
449 /*Free any ucode image resources if not managing this falcon*/
450 if (!(pmu->pmu_mode & PMU_LSFM_MANAGED)) {
451 gm20b_dbg_pmu("pmu is not LSFM managed\n");
452 lsfm_free_ucode_img_res(g, &ucode_img);
453 }
454
455 /* Enumerate all constructed falcon objects,
456 as we need the ucode image info and total falcon count.*/
457
458 /*0th index is always PMU which is already handled in earlier
459 if condition*/
460 for (i = 1; i < (MAX_SUPPORTED_LSFM); i++) {
461 memset(&ucode_img, 0, sizeof(ucode_img));
462 if (pmu_acr_supp_ucode_list[i](g, &ucode_img) == 0) {
463 if (ucode_img.lsf_desc != NULL) {
464 /* We have engine sigs, ensure that this falcon
465 is aware of the secure mode expectations
466 (ACR status)*/
467
468 /* falon_id is formed by grabbing the static
469 base falonId from the image and adding the
470 engine-designated falcon instance. */
471 falcon_id = ucode_img.lsf_desc->falcon_id +
472 ucode_img.flcn_inst;
473
474 if (!lsfm_falcon_disabled(g, plsfm,
475 falcon_id)) {
476 /* Do not manage non-FB ucode*/
477 if (lsfm_add_ucode_img(g,
478 plsfm, &ucode_img, falcon_id)
479 == 0)
480 plsfm->managed_flcn_cnt++;
481 } else {
482 gm20b_dbg_pmu("not managed %d\n",
483 ucode_img.lsf_desc->falcon_id);
484 lsfm_free_nonpmu_ucode_img_res(g,
485 &ucode_img);
486 }
487 }
488 } else {
489 /* Consumed all available falcon objects */
490 gm20b_dbg_pmu("Done checking for ucodes %d\n", i);
491 break;
492 }
493 }
494 return 0;
495}
496
497
498int gm20b_pmu_populate_loader_cfg(struct gk20a *g,
499 void *lsfm, u32 *p_bl_gen_desc_size)
500{
501 struct wpr_carveout_info wpr_inf;
502 struct nvgpu_pmu *pmu = &g->pmu;
503 struct lsfm_managed_ucode_img *p_lsfm =
504 (struct lsfm_managed_ucode_img *)lsfm;
505 struct flcn_ucode_img *p_img = &(p_lsfm->ucode_img);
506 struct loader_config *ldr_cfg = &(p_lsfm->bl_gen_desc.loader_cfg);
507 u64 addr_base;
508 struct pmu_ucode_desc *desc;
509 u64 addr_code, addr_data;
510 u32 addr_args;
511
512 if (p_img->desc == NULL) /*This means its a header based ucode,
513 and so we do not fill BL gen desc structure*/
514 return -EINVAL;
515 desc = p_img->desc;
516 /*
517 Calculate physical and virtual addresses for various portions of
518 the PMU ucode image
519 Calculate the 32-bit addresses for the application code, application
520 data, and bootloader code. These values are all based on IM_BASE.
521 The 32-bit addresses will be the upper 32-bits of the virtual or
522 physical addresses of each respective segment.
523 */
524 addr_base = p_lsfm->lsb_header.ucode_off;
525 g->ops.pmu.get_wpr(g, &wpr_inf);
526 addr_base += wpr_inf.wpr_base;
527 gm20b_dbg_pmu("pmu loader cfg u32 addrbase %x\n", (u32)addr_base);
528 /*From linux*/
529 addr_code = u64_lo32((addr_base +
530 desc->app_start_offset +
531 desc->app_resident_code_offset) >> 8);
532 gm20b_dbg_pmu("app start %d app res code off %d\n",
533 desc->app_start_offset, desc->app_resident_code_offset);
534 addr_data = u64_lo32((addr_base +
535 desc->app_start_offset +
536 desc->app_resident_data_offset) >> 8);
537 gm20b_dbg_pmu("app res data offset%d\n",
538 desc->app_resident_data_offset);
539 gm20b_dbg_pmu("bl start off %d\n", desc->bootloader_start_offset);
540
541 addr_args = ((pwr_falcon_hwcfg_dmem_size_v(
542 gk20a_readl(g, pwr_falcon_hwcfg_r())))
543 << GK20A_PMU_DMEM_BLKSIZE2);
544 addr_args -= g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu);
545
546 gm20b_dbg_pmu("addr_args %x\n", addr_args);
547
548 /* Populate the loader_config state*/
549 ldr_cfg->dma_idx = GK20A_PMU_DMAIDX_UCODE;
550 ldr_cfg->code_dma_base = addr_code;
551 ldr_cfg->code_dma_base1 = 0x0;
552 ldr_cfg->code_size_total = desc->app_size;
553 ldr_cfg->code_size_to_load = desc->app_resident_code_size;
554 ldr_cfg->code_entry_point = desc->app_imem_entry;
555 ldr_cfg->data_dma_base = addr_data;
556 ldr_cfg->data_dma_base1 = 0;
557 ldr_cfg->data_size = desc->app_resident_data_size;
558 ldr_cfg->overlay_dma_base = addr_code;
559 ldr_cfg->overlay_dma_base1 = 0x0;
560
561 /* Update the argc/argv members*/
562 ldr_cfg->argc = 1;
563 ldr_cfg->argv = addr_args;
564
565 *p_bl_gen_desc_size = sizeof(struct loader_config);
566 g->acr.pmu_args = addr_args;
567 return 0;
568}
569
570int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g,
571 void *lsfm, u32 *p_bl_gen_desc_size, u32 falconid)
572{
573 struct wpr_carveout_info wpr_inf;
574 struct lsfm_managed_ucode_img *p_lsfm =
575 (struct lsfm_managed_ucode_img *)lsfm;
576 struct flcn_ucode_img *p_img = &(p_lsfm->ucode_img);
577 struct flcn_bl_dmem_desc *ldr_cfg =
578 &(p_lsfm->bl_gen_desc.bl_dmem_desc);
579 u64 addr_base;
580 struct pmu_ucode_desc *desc;
581 u64 addr_code, addr_data;
582
583 if (p_img->desc == NULL) /*This means its a header based ucode,
584 and so we do not fill BL gen desc structure*/
585 return -EINVAL;
586 desc = p_img->desc;
587
588 /*
589 Calculate physical and virtual addresses for various portions of
590 the PMU ucode image
591 Calculate the 32-bit addresses for the application code, application
592 data, and bootloader code. These values are all based on IM_BASE.
593 The 32-bit addresses will be the upper 32-bits of the virtual or
594 physical addresses of each respective segment.
595 */
596 addr_base = p_lsfm->lsb_header.ucode_off;
597 g->ops.pmu.get_wpr(g, &wpr_inf);
598 addr_base += wpr_inf.wpr_base;
599
600 gm20b_dbg_pmu("gen loader cfg %x u32 addrbase %x ID\n", (u32)addr_base,
601 p_lsfm->wpr_header.falcon_id);
602 addr_code = u64_lo32((addr_base +
603 desc->app_start_offset +
604 desc->app_resident_code_offset) >> 8);
605 addr_data = u64_lo32((addr_base +
606 desc->app_start_offset +
607 desc->app_resident_data_offset) >> 8);
608
609 gm20b_dbg_pmu("gen cfg %x u32 addrcode %x & data %x load offset %xID\n",
610 (u32)addr_code, (u32)addr_data, desc->bootloader_start_offset,
611 p_lsfm->wpr_header.falcon_id);
612
613 /* Populate the LOADER_CONFIG state */
614 memset((void *) ldr_cfg, 0, sizeof(struct flcn_bl_dmem_desc));
615 ldr_cfg->ctx_dma = GK20A_PMU_DMAIDX_UCODE;
616 ldr_cfg->code_dma_base = addr_code;
617 ldr_cfg->non_sec_code_size = desc->app_resident_code_size;
618 ldr_cfg->data_dma_base = addr_data;
619 ldr_cfg->data_size = desc->app_resident_data_size;
620 ldr_cfg->code_entry_point = desc->app_imem_entry;
621 *p_bl_gen_desc_size = sizeof(struct flcn_bl_dmem_desc);
622 return 0;
623}
624
625/* Populate falcon boot loader generic desc.*/
626static int lsfm_fill_flcn_bl_gen_desc(struct gk20a *g,
627 struct lsfm_managed_ucode_img *pnode)
628{
629
630 struct nvgpu_pmu *pmu = &g->pmu;
631 if (pnode->wpr_header.falcon_id != pmu->falcon_id) {
632 gm20b_dbg_pmu("non pmu. write flcn bl gen desc\n");
633 g->ops.pmu.flcn_populate_bl_dmem_desc(g,
634 pnode, &pnode->bl_gen_desc_size,
635 pnode->wpr_header.falcon_id);
636 return 0;
637 }
638
639 if (pmu->pmu_mode & PMU_LSFM_MANAGED) {
640 gm20b_dbg_pmu("pmu write flcn bl gen desc\n");
641 if (pnode->wpr_header.falcon_id == pmu->falcon_id)
642 return g->ops.pmu.pmu_populate_loader_cfg(g, pnode,
643 &pnode->bl_gen_desc_size);
644 }
645
646 /* Failed to find the falcon requested. */
647 return -ENOENT;
648}
649
650/* Initialize WPR contents */
651static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm,
652 struct nvgpu_mem *ucode)
653{
654 struct lsfm_managed_ucode_img *pnode = plsfm->ucode_img_list;
655 struct lsf_wpr_header last_wpr_hdr;
656 u32 i;
657
658 /* The WPR array is at the base of the WPR */
659 pnode = plsfm->ucode_img_list;
660 memset(&last_wpr_hdr, 0, sizeof(struct lsf_wpr_header));
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 nvgpu_mem_wr_n(g, ucode, i * sizeof(pnode->wpr_header),
671 &pnode->wpr_header, sizeof(pnode->wpr_header));
672
673 gm20b_dbg_pmu("wpr header");
674 gm20b_dbg_pmu("falconid :%d",
675 pnode->wpr_header.falcon_id);
676 gm20b_dbg_pmu("lsb_offset :%x",
677 pnode->wpr_header.lsb_offset);
678 gm20b_dbg_pmu("bootstrap_owner :%d",
679 pnode->wpr_header.bootstrap_owner);
680 gm20b_dbg_pmu("lazy_bootstrap :%d",
681 pnode->wpr_header.lazy_bootstrap);
682 gm20b_dbg_pmu("status :%d",
683 pnode->wpr_header.status);
684
685 /*Flush LSB header to memory*/
686 nvgpu_mem_wr_n(g, ucode, pnode->wpr_header.lsb_offset,
687 &pnode->lsb_header, sizeof(pnode->lsb_header));
688
689 gm20b_dbg_pmu("lsb header");
690 gm20b_dbg_pmu("ucode_off :%x",
691 pnode->lsb_header.ucode_off);
692 gm20b_dbg_pmu("ucode_size :%x",
693 pnode->lsb_header.ucode_size);
694 gm20b_dbg_pmu("data_size :%x",
695 pnode->lsb_header.data_size);
696 gm20b_dbg_pmu("bl_code_size :%x",
697 pnode->lsb_header.bl_code_size);
698 gm20b_dbg_pmu("bl_imem_off :%x",
699 pnode->lsb_header.bl_imem_off);
700 gm20b_dbg_pmu("bl_data_off :%x",
701 pnode->lsb_header.bl_data_off);
702 gm20b_dbg_pmu("bl_data_size :%x",
703 pnode->lsb_header.bl_data_size);
704 gm20b_dbg_pmu("app_code_off :%x",
705 pnode->lsb_header.app_code_off);
706 gm20b_dbg_pmu("app_code_size :%x",
707 pnode->lsb_header.app_code_size);
708 gm20b_dbg_pmu("app_data_off :%x",
709 pnode->lsb_header.app_data_off);
710 gm20b_dbg_pmu("app_data_size :%x",
711 pnode->lsb_header.app_data_size);
712 gm20b_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 nvgpu_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 nvgpu_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 last_wpr_hdr.falcon_id = LSF_FALCON_ID_INVALID;
735 nvgpu_mem_wr_n(g, ucode,
736 plsfm->managed_flcn_cnt * sizeof(struct lsf_wpr_header),
737 &last_wpr_hdr,
738 sizeof(struct lsf_wpr_header));
739}
740
741/*!
742 * lsfm_parse_no_loader_ucode: parses UCODE header of falcon
743 *
744 * @param[in] p_ucodehdr : UCODE header
745 * @param[out] lsb_hdr : updates values in LSB header
746 *
747 * @return 0
748 */
749static int lsfm_parse_no_loader_ucode(u32 *p_ucodehdr,
750 struct lsf_lsb_header *lsb_hdr)
751{
752
753 u32 code_size = 0;
754 u32 data_size = 0;
755 u32 i = 0;
756 u32 total_apps = p_ucodehdr[FLCN_NL_UCODE_HDR_NUM_APPS_IND];
757
758 /* Lets calculate code size*/
759 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_CODE_SIZE_IND];
760 for (i = 0; i < total_apps; i++) {
761 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_APP_CODE_SIZE_IND
762 (total_apps, i)];
763 }
764 code_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_OVL_SIZE_IND(total_apps)];
765
766 /* Calculate data size*/
767 data_size += p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_SIZE_IND];
768 for (i = 0; i < total_apps; i++) {
769 data_size += p_ucodehdr[FLCN_NL_UCODE_HDR_APP_DATA_SIZE_IND
770 (total_apps, i)];
771 }
772
773 lsb_hdr->ucode_size = code_size;
774 lsb_hdr->data_size = data_size;
775 lsb_hdr->bl_code_size = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_CODE_SIZE_IND];
776 lsb_hdr->bl_imem_off = 0;
777 lsb_hdr->bl_data_off = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_OFF_IND];
778 lsb_hdr->bl_data_size = p_ucodehdr[FLCN_NL_UCODE_HDR_OS_DATA_SIZE_IND];
779 return 0;
780}
781
782/*!
783 * @brief lsfm_fill_static_lsb_hdr_info
784 * Populate static LSB header infomation using the provided ucode image
785 */
786static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
787 u32 falcon_id, struct lsfm_managed_ucode_img *pnode)
788{
789
790 struct nvgpu_pmu *pmu = &g->pmu;
791 u32 full_app_size = 0;
792 u32 data = 0;
793
794 if (pnode->ucode_img.lsf_desc)
795 memcpy(&pnode->lsb_header.signature, pnode->ucode_img.lsf_desc,
796 sizeof(struct lsf_ucode_desc));
797 pnode->lsb_header.ucode_size = pnode->ucode_img.data_size;
798
799 /* The remainder of the LSB depends on the loader usage */
800 if (pnode->ucode_img.header) {
801 /* Does not use a loader */
802 pnode->lsb_header.data_size = 0;
803 pnode->lsb_header.bl_code_size = 0;
804 pnode->lsb_header.bl_data_off = 0;
805 pnode->lsb_header.bl_data_size = 0;
806
807 lsfm_parse_no_loader_ucode(pnode->ucode_img.header,
808 &(pnode->lsb_header));
809
810 /* Load the first 256 bytes of IMEM. */
811 /* Set LOAD_CODE_AT_0 and DMACTL_REQ_CTX.
812 True for all method based falcons */
813 data = NV_FLCN_ACR_LSF_FLAG_LOAD_CODE_AT_0_TRUE |
814 NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE;
815 pnode->lsb_header.flags = data;
816 } else {
817 /* Uses a loader. that is has a desc */
818 pnode->lsb_header.data_size = 0;
819
820 /* The loader code size is already aligned (padded) such that
821 the code following it is aligned, but the size in the image
822 desc is not, bloat it up to be on a 256 byte alignment. */
823 pnode->lsb_header.bl_code_size = ALIGN(
824 pnode->ucode_img.desc->bootloader_size,
825 LSF_BL_CODE_SIZE_ALIGNMENT);
826 full_app_size = ALIGN(pnode->ucode_img.desc->app_size,
827 LSF_BL_CODE_SIZE_ALIGNMENT) +
828 pnode->lsb_header.bl_code_size;
829 pnode->lsb_header.ucode_size = ALIGN(
830 pnode->ucode_img.desc->app_resident_data_offset,
831 LSF_BL_CODE_SIZE_ALIGNMENT) +
832 pnode->lsb_header.bl_code_size;
833 pnode->lsb_header.data_size = full_app_size -
834 pnode->lsb_header.ucode_size;
835 /* Though the BL is located at 0th offset of the image, the VA
836 is different to make sure that it doesnt collide the actual OS
837 VA range */
838 pnode->lsb_header.bl_imem_off =
839 pnode->ucode_img.desc->bootloader_imem_offset;
840
841 /* TODO: OBJFLCN should export properties using which the below
842 flags should be populated.*/
843 pnode->lsb_header.flags = 0;
844
845 if (falcon_id == pmu->falcon_id) {
846 data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE;
847 pnode->lsb_header.flags = data;
848 }
849
850 if (g->ops.pmu.is_priv_load(falcon_id)) {
851 pnode->lsb_header.flags |=
852 NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE;
853 }
854 }
855}
856
857/* Adds a ucode image to the list of managed ucode images managed. */
858static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm,
859 struct flcn_ucode_img *ucode_image, u32 falcon_id)
860{
861
862 struct lsfm_managed_ucode_img *pnode;
863 pnode = nvgpu_kzalloc(g, sizeof(struct lsfm_managed_ucode_img));
864 if (pnode == NULL)
865 return -ENOMEM;
866
867 /* Keep a copy of the ucode image info locally */
868 memcpy(&pnode->ucode_img, ucode_image, sizeof(struct flcn_ucode_img));
869
870 /* Fill in static WPR header info*/
871 pnode->wpr_header.falcon_id = falcon_id;
872 pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT;
873 pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY;
874
875 pnode->wpr_header.lazy_bootstrap =
876 g->ops.pmu.is_lazy_bootstrap(falcon_id);
877
878 /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by
879 Android */
880 /* Fill in static LSB header info elsewhere */
881 lsfm_fill_static_lsb_hdr_info(g, falcon_id, pnode);
882 pnode->next = plsfm->ucode_img_list;
883 plsfm->ucode_img_list = pnode;
884 return 0;
885}
886
887/* Free any ucode image structure resources. */
888static void lsfm_free_ucode_img_res(struct gk20a *g,
889 struct flcn_ucode_img *p_img)
890{
891 if (p_img->lsf_desc != NULL) {
892 nvgpu_kfree(g, p_img->lsf_desc);
893 p_img->lsf_desc = NULL;
894 }
895}
896
897/* Free any ucode image structure resources. */
898static void lsfm_free_nonpmu_ucode_img_res(struct gk20a *g,
899 struct flcn_ucode_img *p_img)
900{
901 if (p_img->lsf_desc != NULL) {
902 nvgpu_kfree(g, p_img->lsf_desc);
903 p_img->lsf_desc = NULL;
904 }
905 if (p_img->desc != NULL) {
906 nvgpu_kfree(g, p_img->desc);
907 p_img->desc = NULL;
908 }
909}
910
911static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm)
912{
913 u32 cnt = plsfm->managed_flcn_cnt;
914 struct lsfm_managed_ucode_img *mg_ucode_img;
915 while (cnt) {
916 mg_ucode_img = plsfm->ucode_img_list;
917 if (mg_ucode_img->ucode_img.lsf_desc->falcon_id ==
918 LSF_FALCON_ID_PMU)
919 lsfm_free_ucode_img_res(g, &mg_ucode_img->ucode_img);
920 else
921 lsfm_free_nonpmu_ucode_img_res(g,
922 &mg_ucode_img->ucode_img);
923 plsfm->ucode_img_list = mg_ucode_img->next;
924 nvgpu_kfree(g, mg_ucode_img);
925 cnt--;
926 }
927}
928
929/* Generate WPR requirements for ACR allocation request */
930static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm)
931{
932 struct lsfm_managed_ucode_img *pnode = plsfm->ucode_img_list;
933 u32 wpr_offset;
934
935 /* Calculate WPR size required */
936
937 /* Start with an array of WPR headers at the base of the WPR.
938 The expectation here is that the secure falcon will do a single DMA
939 read of this array and cache it internally so it's OK to pack these.
940 Also, we add 1 to the falcon count to indicate the end of the array.*/
941 wpr_offset = sizeof(struct lsf_wpr_header) *
942 (plsfm->managed_flcn_cnt+1);
943
944 /* Walk the managed falcons, accounting for the LSB structs
945 as well as the ucode images. */
946 while (pnode) {
947 /* Align, save off, and include an LSB header size */
948 wpr_offset = ALIGN(wpr_offset,
949 LSF_LSB_HEADER_ALIGNMENT);
950 pnode->wpr_header.lsb_offset = wpr_offset;
951 wpr_offset += sizeof(struct lsf_lsb_header);
952
953 /* Align, save off, and include the original (static)
954 ucode image size */
955 wpr_offset = ALIGN(wpr_offset,
956 LSF_UCODE_DATA_ALIGNMENT);
957 pnode->lsb_header.ucode_off = wpr_offset;
958 wpr_offset += pnode->ucode_img.data_size;
959
960 /* For falcons that use a boot loader (BL), we append a loader
961 desc structure on the end of the ucode image and consider this
962 the boot loader data. The host will then copy the loader desc
963 args to this space within the WPR region (before locking down)
964 and the HS bin will then copy them to DMEM 0 for the loader. */
965 if (!pnode->ucode_img.header) {
966 /* Track the size for LSB details filled in later
967 Note that at this point we don't know what kind of i
968 boot loader desc, so we just take the size of the
969 generic one, which is the largest it will will ever be.
970 */
971 /* Align (size bloat) and save off generic
972 descriptor size*/
973 pnode->lsb_header.bl_data_size = ALIGN(
974 sizeof(pnode->bl_gen_desc),
975 LSF_BL_DATA_SIZE_ALIGNMENT);
976
977 /*Align, save off, and include the additional BL data*/
978 wpr_offset = ALIGN(wpr_offset,
979 LSF_BL_DATA_ALIGNMENT);
980 pnode->lsb_header.bl_data_off = wpr_offset;
981 wpr_offset += pnode->lsb_header.bl_data_size;
982 } else {
983 /* bl_data_off is already assigned in static
984 information. But that is from start of the image */
985 pnode->lsb_header.bl_data_off +=
986 (wpr_offset - pnode->ucode_img.data_size);
987 }
988
989 /* Finally, update ucode surface size to include updates */
990 pnode->full_ucode_size = wpr_offset -
991 pnode->lsb_header.ucode_off;
992 if (pnode->wpr_header.falcon_id != LSF_FALCON_ID_PMU) {
993 pnode->lsb_header.app_code_off =
994 pnode->lsb_header.bl_code_size;
995 pnode->lsb_header.app_code_size =
996 pnode->lsb_header.ucode_size -
997 pnode->lsb_header.bl_code_size;
998 pnode->lsb_header.app_data_off =
999 pnode->lsb_header.ucode_size;
1000 pnode->lsb_header.app_data_size =
1001 pnode->lsb_header.data_size;
1002 }
1003 pnode = pnode->next;
1004 }
1005 plsfm->wpr_size = wpr_offset;
1006 return 0;
1007}
1008
1009/*Loads ACR bin to FB mem and bootstraps PMU with bootloader code
1010 * start and end are addresses of ucode blob in non-WPR region*/
1011int gm20b_bootstrap_hs_flcn(struct gk20a *g)
1012{
1013 struct mm_gk20a *mm = &g->mm;
1014 struct vm_gk20a *vm = mm->pmu.vm;
1015 int err = 0;
1016 u64 *acr_dmem;
1017 u32 img_size_in_bytes = 0;
1018 u32 status, size;
1019 u64 start;
1020 struct acr_desc *acr = &g->acr;
1021 struct nvgpu_firmware *acr_fw = acr->acr_fw;
1022 struct flcn_bl_dmem_desc *bl_dmem_desc = &acr->bl_dmem_desc;
1023 u32 *acr_ucode_header_t210_load;
1024 u32 *acr_ucode_data_t210_load;
1025
1026 start = nvgpu_mem_get_addr(g, &acr->ucode_blob);
1027 size = acr->ucode_blob.size;
1028
1029 gm20b_dbg_pmu("");
1030
1031 if (!acr_fw) {
1032 /*First time init case*/
1033 acr_fw = nvgpu_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE, 0);
1034 if (!acr_fw) {
1035 nvgpu_err(g, "pmu ucode get fail");
1036 return -ENOENT;
1037 }
1038 acr->acr_fw = acr_fw;
1039 acr->hsbin_hdr = (struct bin_hdr *)acr_fw->data;
1040 acr->fw_hdr = (struct acr_fw_header *)(acr_fw->data +
1041 acr->hsbin_hdr->header_offset);
1042 acr_ucode_data_t210_load = (u32 *)(acr_fw->data +
1043 acr->hsbin_hdr->data_offset);
1044 acr_ucode_header_t210_load = (u32 *)(acr_fw->data +
1045 acr->fw_hdr->hdr_offset);
1046 img_size_in_bytes = ALIGN((acr->hsbin_hdr->data_size), 256);
1047
1048 /* Lets patch the signatures first.. */
1049 if (acr_ucode_patch_sig(g, acr_ucode_data_t210_load,
1050 (u32 *)(acr_fw->data +
1051 acr->fw_hdr->sig_prod_offset),
1052 (u32 *)(acr_fw->data +
1053 acr->fw_hdr->sig_dbg_offset),
1054 (u32 *)(acr_fw->data +
1055 acr->fw_hdr->patch_loc),
1056 (u32 *)(acr_fw->data +
1057 acr->fw_hdr->patch_sig)) < 0) {
1058 nvgpu_err(g, "patch signatures fail");
1059 err = -1;
1060 goto err_release_acr_fw;
1061 }
1062 err = nvgpu_dma_alloc_map_sys(vm, img_size_in_bytes,
1063 &acr->acr_ucode);
1064 if (err) {
1065 err = -ENOMEM;
1066 goto err_release_acr_fw;
1067 }
1068
1069 acr_dmem = (u64 *)
1070 &(((u8 *)acr_ucode_data_t210_load)[
1071 acr_ucode_header_t210_load[2]]);
1072 acr->acr_dmem_desc = (struct flcn_acr_desc *)((u8 *)(
1073 acr->acr_ucode.cpu_va) + acr_ucode_header_t210_load[2]);
1074 ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_start =
1075 start;
1076 ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_size =
1077 size;
1078 ((struct flcn_acr_desc *)acr_dmem)->regions.no_regions = 2;
1079 ((struct flcn_acr_desc *)acr_dmem)->wpr_offset = 0;
1080
1081 nvgpu_mem_wr_n(g, &acr->acr_ucode, 0,
1082 acr_ucode_data_t210_load, img_size_in_bytes);
1083 /*
1084 * In order to execute this binary, we will be using
1085 * a bootloader which will load this image into PMU IMEM/DMEM.
1086 * Fill up the bootloader descriptor for PMU HAL to use..
1087 * TODO: Use standard descriptor which the generic bootloader is
1088 * checked in.
1089 */
1090
1091 bl_dmem_desc->signature[0] = 0;
1092 bl_dmem_desc->signature[1] = 0;
1093 bl_dmem_desc->signature[2] = 0;
1094 bl_dmem_desc->signature[3] = 0;
1095 bl_dmem_desc->ctx_dma = GK20A_PMU_DMAIDX_VIRT;
1096 bl_dmem_desc->code_dma_base =
1097 (unsigned int)(((u64)acr->acr_ucode.gpu_va >> 8));
1098 bl_dmem_desc->code_dma_base1 = 0x0;
1099 bl_dmem_desc->non_sec_code_off = acr_ucode_header_t210_load[0];
1100 bl_dmem_desc->non_sec_code_size = acr_ucode_header_t210_load[1];
1101 bl_dmem_desc->sec_code_off = acr_ucode_header_t210_load[5];
1102 bl_dmem_desc->sec_code_size = acr_ucode_header_t210_load[6];
1103 bl_dmem_desc->code_entry_point = 0; /* Start at 0th offset */
1104 bl_dmem_desc->data_dma_base =
1105 bl_dmem_desc->code_dma_base +
1106 ((acr_ucode_header_t210_load[2]) >> 8);
1107 bl_dmem_desc->data_dma_base1 = 0x0;
1108 bl_dmem_desc->data_size = acr_ucode_header_t210_load[3];
1109 } else
1110 acr->acr_dmem_desc->nonwpr_ucode_blob_size = 0;
1111 status = pmu_exec_gen_bl(g, bl_dmem_desc, 1);
1112 if (status != 0) {
1113 err = status;
1114 goto err_free_ucode_map;
1115 }
1116 return 0;
1117err_free_ucode_map:
1118 nvgpu_dma_unmap_free(vm, &acr->acr_ucode);
1119err_release_acr_fw:
1120 nvgpu_release_firmware(g, acr_fw);
1121 acr->acr_fw = NULL;
1122 return err;
1123}
1124
1125static u8 pmu_is_debug_mode_en(struct gk20a *g)
1126{
1127 u32 ctl_stat = gk20a_readl(g, pwr_pmu_scpctl_stat_r());
1128 return pwr_pmu_scpctl_stat_debug_mode_v(ctl_stat);
1129}
1130
1131/*
1132 * @brief Patch signatures into ucode image
1133 */
1134int acr_ucode_patch_sig(struct gk20a *g,
1135 unsigned int *p_img,
1136 unsigned int *p_prod_sig,
1137 unsigned int *p_dbg_sig,
1138 unsigned int *p_patch_loc,
1139 unsigned int *p_patch_ind)
1140{
1141 unsigned int i, *p_sig;
1142 gm20b_dbg_pmu("");
1143
1144 if (!pmu_is_debug_mode_en(g)) {
1145 p_sig = p_prod_sig;
1146 gm20b_dbg_pmu("PRODUCTION MODE\n");
1147 } else {
1148 p_sig = p_dbg_sig;
1149 gm20b_dbg_pmu("DEBUG MODE\n");
1150 }
1151
1152 /* Patching logic:*/
1153 for (i = 0; i < sizeof(*p_patch_loc)>>2; i++) {
1154 p_img[(p_patch_loc[i]>>2)] = p_sig[(p_patch_ind[i]<<2)];
1155 p_img[(p_patch_loc[i]>>2)+1] = p_sig[(p_patch_ind[i]<<2)+1];
1156 p_img[(p_patch_loc[i]>>2)+2] = p_sig[(p_patch_ind[i]<<2)+2];
1157 p_img[(p_patch_loc[i]>>2)+3] = p_sig[(p_patch_ind[i]<<2)+3];
1158 }
1159 return 0;
1160}
1161
1162static int bl_bootstrap(struct nvgpu_pmu *pmu,
1163 struct flcn_bl_dmem_desc *pbl_desc, u32 bl_sz)
1164{
1165 struct gk20a *g = gk20a_from_pmu(pmu);
1166 struct acr_desc *acr = &g->acr;
1167 struct mm_gk20a *mm = &g->mm;
1168 u32 virt_addr = 0;
1169 struct hsflcn_bl_desc *pmu_bl_gm10x_desc = g->acr.pmu_hsbl_desc;
1170 u32 dst;
1171
1172 gk20a_dbg_fn("");
1173 gk20a_writel(g, pwr_falcon_itfen_r(),
1174 gk20a_readl(g, pwr_falcon_itfen_r()) |
1175 pwr_falcon_itfen_ctxen_enable_f());
1176 gk20a_writel(g, pwr_pmu_new_instblk_r(),
1177 pwr_pmu_new_instblk_ptr_f(
1178 nvgpu_inst_block_addr(g, &mm->pmu.inst_block) >> 12) |
1179 pwr_pmu_new_instblk_valid_f(1) |
1180 pwr_pmu_new_instblk_target_sys_coh_f());
1181
1182 /*copy bootloader interface structure to dmem*/
1183 nvgpu_flcn_copy_to_dmem(pmu->flcn, 0, (u8 *)pbl_desc,
1184 sizeof(struct flcn_bl_dmem_desc), 0);
1185
1186 /* copy bootloader to TOP of IMEM */
1187 dst = (pwr_falcon_hwcfg_imem_size_v(
1188 gk20a_readl(g, pwr_falcon_hwcfg_r())) << 8) - bl_sz;
1189
1190 nvgpu_flcn_copy_to_imem(pmu->flcn, dst,
1191 (u8 *)(acr->hsbl_ucode.cpu_va), bl_sz, 0, 0,
1192 pmu_bl_gm10x_desc->bl_start_tag);
1193
1194 gm20b_dbg_pmu("Before starting falcon with BL\n");
1195
1196 virt_addr = pmu_bl_gm10x_desc->bl_start_tag << 8;
1197
1198 nvgpu_flcn_bootstrap(pmu->flcn, virt_addr);
1199
1200 return 0;
1201}
1202
1203int gm20b_init_nspmu_setup_hw1(struct gk20a *g)
1204{
1205 struct nvgpu_pmu *pmu = &g->pmu;
1206 int err = 0;
1207
1208 gk20a_dbg_fn("");
1209
1210 nvgpu_mutex_acquire(&pmu->isr_mutex);
1211 nvgpu_flcn_reset(pmu->flcn);
1212 pmu->isr_enabled = true;
1213 nvgpu_mutex_release(&pmu->isr_mutex);
1214
1215 /* setup apertures - virtual */
1216 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
1217 pwr_fbif_transcfg_mem_type_virtual_f());
1218 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_VIRT),
1219 pwr_fbif_transcfg_mem_type_virtual_f());
1220 /* setup apertures - physical */
1221 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_VID),
1222 pwr_fbif_transcfg_mem_type_physical_f() |
1223 pwr_fbif_transcfg_target_local_fb_f());
1224 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_COH),
1225 pwr_fbif_transcfg_mem_type_physical_f() |
1226 pwr_fbif_transcfg_target_coherent_sysmem_f());
1227 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_NCOH),
1228 pwr_fbif_transcfg_mem_type_physical_f() |
1229 pwr_fbif_transcfg_target_noncoherent_sysmem_f());
1230
1231 err = g->ops.pmu.pmu_nsbootstrap(pmu);
1232
1233 return err;
1234}
1235
1236int gm20b_init_pmu_setup_hw1(struct gk20a *g,
1237 void *desc, u32 bl_sz)
1238{
1239
1240 struct nvgpu_pmu *pmu = &g->pmu;
1241 int err;
1242
1243 gk20a_dbg_fn("");
1244
1245 nvgpu_mutex_acquire(&pmu->isr_mutex);
1246 nvgpu_flcn_reset(pmu->flcn);
1247 pmu->isr_enabled = true;
1248 nvgpu_mutex_release(&pmu->isr_mutex);
1249
1250 /* setup apertures - virtual */
1251 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
1252 pwr_fbif_transcfg_mem_type_physical_f() |
1253 pwr_fbif_transcfg_target_local_fb_f());
1254 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_VIRT),
1255 pwr_fbif_transcfg_mem_type_virtual_f());
1256 /* setup apertures - physical */
1257 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_VID),
1258 pwr_fbif_transcfg_mem_type_physical_f() |
1259 pwr_fbif_transcfg_target_local_fb_f());
1260 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_COH),
1261 pwr_fbif_transcfg_mem_type_physical_f() |
1262 pwr_fbif_transcfg_target_coherent_sysmem_f());
1263 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_NCOH),
1264 pwr_fbif_transcfg_mem_type_physical_f() |
1265 pwr_fbif_transcfg_target_noncoherent_sysmem_f());
1266
1267 /*Copying pmu cmdline args*/
1268 g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
1269 g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_PWRCLK));
1270 g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode(pmu, 1);
1271 g->ops.pmu_ver.set_pmu_cmdline_args_trace_size(
1272 pmu, GK20A_PMU_TRACE_BUFSIZE);
1273 g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_base(pmu);
1274 g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_idx(
1275 pmu, GK20A_PMU_DMAIDX_VIRT);
1276 nvgpu_flcn_copy_to_dmem(pmu->flcn, g->acr.pmu_args,
1277 (u8 *)(g->ops.pmu_ver.get_pmu_cmdline_args_ptr(pmu)),
1278 g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu), 0);
1279 /*disable irqs for hs falcon booting as we will poll for halt*/
1280 nvgpu_mutex_acquire(&pmu->isr_mutex);
1281 pmu_enable_irq(pmu, false);
1282 pmu->isr_enabled = false;
1283 nvgpu_mutex_release(&pmu->isr_mutex);
1284 /*Clearing mailbox register used to reflect capabilities*/
1285 gk20a_writel(g, pwr_falcon_mailbox1_r(), 0);
1286 err = bl_bootstrap(pmu, desc, bl_sz);
1287 if (err)
1288 return err;
1289 return 0;
1290}
1291
1292/*
1293* Executes a generic bootloader and wait for PMU to halt.
1294* This BL will be used for those binaries that are loaded
1295* and executed at times other than RM PMU Binary execution.
1296*
1297* @param[in] g gk20a pointer
1298* @param[in] desc Bootloader descriptor
1299* @param[in] dma_idx DMA Index
1300* @param[in] b_wait_for_halt Wait for PMU to HALT
1301*/
1302int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt)
1303{
1304 struct mm_gk20a *mm = &g->mm;
1305 struct vm_gk20a *vm = mm->pmu.vm;
1306 int err = 0;
1307 u32 bl_sz;
1308 struct acr_desc *acr = &g->acr;
1309 struct nvgpu_firmware *hsbl_fw = acr->hsbl_fw;
1310 struct hsflcn_bl_desc *pmu_bl_gm10x_desc;
1311 u32 *pmu_bl_gm10x = NULL;
1312 gm20b_dbg_pmu("");
1313
1314 if (!hsbl_fw) {
1315 hsbl_fw = nvgpu_request_firmware(g,
1316 GM20B_HSBIN_PMU_BL_UCODE_IMAGE, 0);
1317 if (!hsbl_fw) {
1318 nvgpu_err(g, "pmu ucode load fail");
1319 return -ENOENT;
1320 }
1321 acr->hsbl_fw = hsbl_fw;
1322 acr->bl_bin_hdr = (struct bin_hdr *)hsbl_fw->data;
1323 acr->pmu_hsbl_desc = (struct hsflcn_bl_desc *)(hsbl_fw->data +
1324 acr->bl_bin_hdr->header_offset);
1325 pmu_bl_gm10x_desc = acr->pmu_hsbl_desc;
1326 pmu_bl_gm10x = (u32 *)(hsbl_fw->data +
1327 acr->bl_bin_hdr->data_offset);
1328 bl_sz = ALIGN(pmu_bl_gm10x_desc->bl_img_hdr.bl_code_size,
1329 256);
1330 acr->hsbl_ucode.size = bl_sz;
1331 gm20b_dbg_pmu("Executing Generic Bootloader\n");
1332
1333 /*TODO in code verify that enable PMU is done,
1334 scrubbing etc is done*/
1335 /*TODO in code verify that gmmu vm init is done*/
1336 err = nvgpu_dma_alloc_flags_sys(g,
1337 NVGPU_DMA_READ_ONLY, bl_sz, &acr->hsbl_ucode);
1338 if (err) {
1339 nvgpu_err(g, "failed to allocate memory");
1340 goto err_done;
1341 }
1342
1343 acr->hsbl_ucode.gpu_va = nvgpu_gmmu_map(vm,
1344 &acr->hsbl_ucode,
1345 bl_sz,
1346 0, /* flags */
1347 gk20a_mem_flag_read_only, false,
1348 acr->hsbl_ucode.aperture);
1349 if (!acr->hsbl_ucode.gpu_va) {
1350 nvgpu_err(g, "failed to map pmu ucode memory!!");
1351 goto err_free_ucode;
1352 }
1353
1354 nvgpu_mem_wr_n(g, &acr->hsbl_ucode, 0, pmu_bl_gm10x, bl_sz);
1355 gm20b_dbg_pmu("Copied bl ucode to bl_cpuva\n");
1356 }
1357 /*
1358 * Disable interrupts to avoid kernel hitting breakpoint due
1359 * to PMU halt
1360 */
1361
1362 if (g->ops.pmu.falcon_clear_halt_interrupt_status(g,
1363 gk20a_get_gr_idle_timeout(g)))
1364 goto err_unmap_bl;
1365
1366 gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g,
1367 pwr_falcon_mmu_phys_sec_r()));
1368 gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r()));
1369
1370 g->ops.pmu.init_falcon_setup_hw(g, desc, acr->hsbl_ucode.size);
1371
1372 /* Poll for HALT */
1373 if (b_wait_for_halt) {
1374 err = g->ops.pmu.falcon_wait_for_halt(g,
1375 ACR_COMPLETION_TIMEOUT_MS);
1376 if (err == 0) {
1377 /* Clear the HALT interrupt */
1378 if (g->ops.pmu.falcon_clear_halt_interrupt_status(g,
1379 gk20a_get_gr_idle_timeout(g)))
1380 goto err_unmap_bl;
1381 }
1382 else
1383 goto err_unmap_bl;
1384 }
1385 gm20b_dbg_pmu("after waiting for halt, err %x\n", err);
1386 gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g,
1387 pwr_falcon_mmu_phys_sec_r()));
1388 gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r()));
1389 start_gm20b_pmu(g);
1390 return 0;
1391err_unmap_bl:
1392 nvgpu_gmmu_unmap(vm, &acr->hsbl_ucode, acr->hsbl_ucode.gpu_va);
1393err_free_ucode:
1394 nvgpu_dma_free(g, &acr->hsbl_ucode);
1395err_done:
1396 nvgpu_release_firmware(g, hsbl_fw);
1397 return err;
1398}
1399
1400/*!
1401* Wait for PMU to halt
1402* @param[in] g GPU object pointer
1403* @param[in] timeout_ms Timeout in msec for PMU to halt
1404* @return '0' if PMU halts
1405*/
1406int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout_ms)
1407{
1408 struct nvgpu_pmu *pmu = &g->pmu;
1409 u32 data = 0;
1410 int ret = -EBUSY;
1411
1412 ret = nvgpu_flcn_wait_for_halt(pmu->flcn, timeout_ms);
1413 if (ret) {
1414 nvgpu_err(g, "ACR boot timed out");
1415 return ret;
1416 }
1417
1418 g->acr.capabilities = gk20a_readl(g, pwr_falcon_mailbox1_r());
1419 gm20b_dbg_pmu("ACR capabilities %x\n", g->acr.capabilities);
1420 data = gk20a_readl(g, pwr_falcon_mailbox0_r());
1421 if (data) {
1422 nvgpu_err(g, "ACR boot failed, err %x", data);
1423 ret = -EAGAIN;
1424 }
1425
1426 return ret;
1427}
1428
1429/*!
1430* Wait for PMU halt interrupt status to be cleared
1431* @param[in] g GPU object pointer
1432* @param[in] timeout_ms Timeout in msec for halt to clear
1433* @return '0' if PMU halt irq status is clear
1434*/
1435int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout_ms)
1436{
1437 struct nvgpu_pmu *pmu = &g->pmu;
1438 int status = 0;
1439
1440 if (nvgpu_flcn_clear_halt_intr_status(pmu->flcn, timeout_ms))
1441 status = -EBUSY;
1442
1443 return status;
1444}