diff options
author | Mahantesh Kumbar <mkumbar@nvidia.com> | 2016-05-23 06:42:11 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-05-26 19:04:25 -0400 |
commit | e9d5e7dfca6ac2fa7af380ceea0a0ca4ac3827c6 (patch) | |
tree | 1b46893ce4b27ef947937162eb3f3782ca3f39a2 /drivers | |
parent | ad24c028dba639cebefc3326f925e62c3724a59e (diff) |
gpu: nvgpu: secure boot HAL update
Updated/added secure boot HAL with methods
required to support multiple GPU chips.
JIRA DNVGPU-10
Change-Id: I343b289f2236fd6a6b0ecf9115367ce19990e7d5
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: http://git-master/r/1151784
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 153 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.h | 12 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 10 |
5 files changed, 163 insertions, 44 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index d131862b..d96ce3d8 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -534,6 +534,25 @@ struct gpu_ops { | |||
534 | (struct gk20a *g, u32 mask); | 534 | (struct gk20a *g, u32 mask); |
535 | void (*dump_secure_fuses)(struct gk20a *g); | 535 | void (*dump_secure_fuses)(struct gk20a *g); |
536 | int (*reset)(struct gk20a *g); | 536 | int (*reset)(struct gk20a *g); |
537 | int (*falcon_wait_for_halt)(struct gk20a *g, | ||
538 | unsigned int timeout); | ||
539 | int (*falcon_clear_halt_interrupt_status)(struct gk20a *g, | ||
540 | unsigned int timeout); | ||
541 | int (*init_falcon_setup_hw)(struct gk20a *g, | ||
542 | struct flcn_bl_dmem_desc *desc, u32 bl_sz); | ||
543 | bool (*is_lazy_bootstrap)(u32 falcon_id); | ||
544 | bool (*is_priv_load)(u32 falcon_id); | ||
545 | void (*get_wpr)(struct gk20a *g, u64 *base, u64 *size); | ||
546 | int (*alloc_blob_space)(struct gk20a *g, | ||
547 | size_t size, struct mem_desc *mem); | ||
548 | int (*pmu_populate_loader_cfg)(struct gk20a *g, | ||
549 | struct lsfm_managed_ucode_img *lsfm, | ||
550 | union flcn_bl_generic_desc *p_bl_gen_desc, | ||
551 | u32 *p_bl_gen_desc_size); | ||
552 | int (*flcn_populate_bl_dmem_desc)(struct gk20a *g, | ||
553 | struct lsfm_managed_ucode_img *lsfm, | ||
554 | union flcn_bl_generic_desc *p_bl_gen_desc, | ||
555 | u32 *p_bl_gen_desc_size, u32 falconid); | ||
537 | u32 lspmuwprinitdone; | 556 | u32 lspmuwprinitdone; |
538 | u32 lsfloadedfalconid; | 557 | u32 lsfloadedfalconid; |
539 | bool fecsbootstrapdone; | 558 | bool fecsbootstrapdone; |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 08ef7738..a8ebaf7a 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -2758,9 +2758,12 @@ static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) | |||
2758 | 2758 | ||
2759 | int gk20a_pmu_reset(struct gk20a *g) | 2759 | int gk20a_pmu_reset(struct gk20a *g) |
2760 | { | 2760 | { |
2761 | gk20a_reset(g, mc_enable_pwr_enabled_f()); | 2761 | int err; |
2762 | struct pmu_gk20a *pmu = &g->pmu; | ||
2762 | 2763 | ||
2763 | return 0; | 2764 | err = pmu_reset(pmu); |
2765 | |||
2766 | return err; | ||
2764 | } | 2767 | } |
2765 | 2768 | ||
2766 | void gk20a_init_pmu_ops(struct gpu_ops *gops) | 2769 | void gk20a_init_pmu_ops(struct gpu_ops *gops) |
@@ -2776,6 +2779,12 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops) | |||
2776 | gops->pmu.pmu_pg_grinit_param = NULL; | 2779 | gops->pmu.pmu_pg_grinit_param = NULL; |
2777 | gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = NULL; | 2780 | gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = NULL; |
2778 | gops->pmu.dump_secure_fuses = NULL; | 2781 | gops->pmu.dump_secure_fuses = NULL; |
2782 | gops->pmu.is_lazy_bootstrap = NULL; | ||
2783 | gops->pmu.is_priv_load = NULL; | ||
2784 | gops->pmu.get_wpr = NULL; | ||
2785 | gops->pmu.alloc_blob_space = NULL; | ||
2786 | gops->pmu.pmu_populate_loader_cfg = NULL; | ||
2787 | gops->pmu.flcn_populate_bl_dmem_desc = NULL; | ||
2779 | gops->pmu.reset = gk20a_pmu_reset; | 2788 | gops->pmu.reset = gk20a_pmu_reset; |
2780 | } | 2789 | } |
2781 | 2790 | ||
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index 3ac2cec8..ea4500eb 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c | |||
@@ -36,6 +36,14 @@ typedef int (*get_ucode_details)(struct gk20a *g, struct flcn_ucode_img *udata); | |||
36 | /*Externs*/ | 36 | /*Externs*/ |
37 | 37 | ||
38 | /*Forwards*/ | 38 | /*Forwards*/ |
39 | static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
40 | static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
41 | static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
42 | static int gm20b_bootstrap_hs_flcn(struct gk20a *g); | ||
43 | static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout); | ||
44 | static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout); | ||
45 | static int gm20b_init_pmu_setup_hw1(struct gk20a *g, | ||
46 | struct flcn_bl_dmem_desc *desc, u32 bl_sz); | ||
39 | static int lsfm_discover_ucode_images(struct gk20a *g, | 47 | static int lsfm_discover_ucode_images(struct gk20a *g, |
40 | struct ls_flcn_mgr *plsfm); | 48 | struct ls_flcn_mgr *plsfm); |
41 | static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, | 49 | static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, |
@@ -45,13 +53,18 @@ static void lsfm_free_nonpmu_ucode_img_res(struct flcn_ucode_img *p_img); | |||
45 | static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm); | 53 | static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm); |
46 | static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm, | 54 | static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm, |
47 | struct mem_desc *nonwpr); | 55 | struct mem_desc *nonwpr); |
48 | static int acr_ucode_patch_sig(struct gk20a *g, | ||
49 | unsigned int *p_img, | ||
50 | unsigned int *p_prod_sig, | ||
51 | unsigned int *p_dbg_sig, | ||
52 | unsigned int *p_patch_loc, | ||
53 | unsigned int *p_patch_ind); | ||
54 | static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm); | 56 | static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm); |
57 | static int gm20b_pmu_populate_loader_cfg(struct gk20a *g, | ||
58 | struct lsfm_managed_ucode_img *lsfm, | ||
59 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size); | ||
60 | static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g, | ||
61 | struct lsfm_managed_ucode_img *lsfm, | ||
62 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size, | ||
63 | u32 falconid); | ||
64 | static int gm20b_alloc_blob_space(struct gk20a *g, | ||
65 | size_t size, struct mem_desc *mem); | ||
66 | static bool gm20b_is_priv_load(u32 falcon_id); | ||
67 | static bool gm20b_is_lazy_bootstrap(u32 falcon_id); | ||
55 | 68 | ||
56 | /*Globals*/ | 69 | /*Globals*/ |
57 | static get_ucode_details pmu_acr_supp_ucode_list[] = { | 70 | static get_ucode_details pmu_acr_supp_ucode_list[] = { |
@@ -72,14 +85,33 @@ static void start_gm20b_pmu(struct gk20a *g) | |||
72 | pwr_falcon_cpuctl_startcpu_f(1)); | 85 | pwr_falcon_cpuctl_startcpu_f(1)); |
73 | } | 86 | } |
74 | 87 | ||
88 | void gm20b_wpr_info(struct gk20a *g, u64 *base, u64 *size) | ||
89 | { | ||
90 | struct mc_carveout_info inf; | ||
91 | |||
92 | mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); | ||
93 | *base = inf.base; | ||
94 | *size = inf.size; | ||
95 | } | ||
96 | |||
75 | void gm20b_init_secure_pmu(struct gpu_ops *gops) | 97 | void gm20b_init_secure_pmu(struct gpu_ops *gops) |
76 | { | 98 | { |
77 | gops->pmu.prepare_ucode = prepare_ucode_blob; | 99 | gops->pmu.prepare_ucode = prepare_ucode_blob; |
78 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; | 100 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; |
101 | gops->pmu.is_lazy_bootstrap = gm20b_is_lazy_bootstrap; | ||
102 | gops->pmu.is_priv_load = gm20b_is_priv_load; | ||
103 | gops->pmu.get_wpr = gm20b_wpr_info; | ||
104 | gops->pmu.alloc_blob_space = gm20b_alloc_blob_space; | ||
105 | gops->pmu.pmu_populate_loader_cfg = gm20b_pmu_populate_loader_cfg; | ||
106 | gops->pmu.flcn_populate_bl_dmem_desc = gm20b_flcn_populate_bl_dmem_desc; | ||
107 | gops->pmu.falcon_wait_for_halt = pmu_wait_for_halt; | ||
108 | gops->pmu.falcon_clear_halt_interrupt_status = | ||
109 | clear_halt_interrupt_status; | ||
110 | gops->pmu.init_falcon_setup_hw = gm20b_init_pmu_setup_hw1; | ||
79 | } | 111 | } |
80 | /* TODO - check if any free blob res needed*/ | 112 | /* TODO - check if any free blob res needed*/ |
81 | 113 | ||
82 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 114 | static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
83 | { | 115 | { |
84 | const struct firmware *pmu_fw, *pmu_desc, *pmu_sig; | 116 | const struct firmware *pmu_fw, *pmu_desc, *pmu_sig; |
85 | struct pmu_gk20a *pmu = &g->pmu; | 117 | struct pmu_gk20a *pmu = &g->pmu; |
@@ -143,7 +175,7 @@ release_img_fw: | |||
143 | return err; | 175 | return err; |
144 | } | 176 | } |
145 | 177 | ||
146 | int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 178 | static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
147 | { | 179 | { |
148 | struct lsf_ucode_desc *lsf_desc; | 180 | struct lsf_ucode_desc *lsf_desc; |
149 | const struct firmware *fecs_sig; | 181 | const struct firmware *fecs_sig; |
@@ -210,7 +242,7 @@ rel_sig: | |||
210 | release_firmware(fecs_sig); | 242 | release_firmware(fecs_sig); |
211 | return err; | 243 | return err; |
212 | } | 244 | } |
213 | int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 245 | static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
214 | { | 246 | { |
215 | struct lsf_ucode_desc *lsf_desc; | 247 | struct lsf_ucode_desc *lsf_desc; |
216 | const struct firmware *gpccs_sig; | 248 | const struct firmware *gpccs_sig; |
@@ -282,6 +314,52 @@ rel_sig: | |||
282 | return err; | 314 | return err; |
283 | } | 315 | } |
284 | 316 | ||
317 | static bool gm20b_is_lazy_bootstrap(u32 falcon_id) | ||
318 | { | ||
319 | bool enable_status = false; | ||
320 | |||
321 | switch (falcon_id) { | ||
322 | case LSF_FALCON_ID_FECS: | ||
323 | enable_status = false; | ||
324 | break; | ||
325 | case LSF_FALCON_ID_GPCCS: | ||
326 | enable_status = false; | ||
327 | break; | ||
328 | default: | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | return enable_status; | ||
333 | } | ||
334 | |||
335 | static bool gm20b_is_priv_load(u32 falcon_id) | ||
336 | { | ||
337 | bool enable_status = false; | ||
338 | |||
339 | switch (falcon_id) { | ||
340 | case LSF_FALCON_ID_FECS: | ||
341 | enable_status = false; | ||
342 | break; | ||
343 | case LSF_FALCON_ID_GPCCS: | ||
344 | enable_status = false; | ||
345 | break; | ||
346 | default: | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | return enable_status; | ||
351 | } | ||
352 | |||
353 | static int gm20b_alloc_blob_space(struct gk20a *g, | ||
354 | size_t size, struct mem_desc *mem) | ||
355 | { | ||
356 | int err; | ||
357 | |||
358 | err = gk20a_gmmu_alloc(g, size, mem); | ||
359 | |||
360 | return err; | ||
361 | } | ||
362 | |||
285 | int prepare_ucode_blob(struct gk20a *g) | 363 | int prepare_ucode_blob(struct gk20a *g) |
286 | { | 364 | { |
287 | 365 | ||
@@ -312,11 +390,12 @@ int prepare_ucode_blob(struct gk20a *g) | |||
312 | gm20b_mm_mmu_vpr_info_fetch(g); | 390 | gm20b_mm_mmu_vpr_info_fetch(g); |
313 | gr_gk20a_init_ctxsw_ucode(g); | 391 | gr_gk20a_init_ctxsw_ucode(g); |
314 | 392 | ||
315 | mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); | 393 | g->ops.pmu.get_wpr(g, &inf.base, &inf.size); |
316 | gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base); | ||
317 | wpr_addr = (phys_addr_t)inf.base; | 394 | wpr_addr = (phys_addr_t)inf.base; |
318 | gm20b_dbg_pmu("wpr carveout size :%llx\n", inf.size); | ||
319 | wprsize = (u32)inf.size; | 395 | wprsize = (u32)inf.size; |
396 | gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base); | ||
397 | gm20b_dbg_pmu("wpr carveout size :%x\n", wprsize); | ||
398 | |||
320 | sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); | 399 | sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); |
321 | if (!sgt) { | 400 | if (!sgt) { |
322 | gk20a_err(dev_from_gk20a(g), "failed to allocate memory\n"); | 401 | gk20a_err(dev_from_gk20a(g), "failed to allocate memory\n"); |
@@ -349,7 +428,8 @@ int prepare_ucode_blob(struct gk20a *g) | |||
349 | goto free_sgt; | 428 | goto free_sgt; |
350 | 429 | ||
351 | /*Alloc memory to hold ucode blob contents*/ | 430 | /*Alloc memory to hold ucode blob contents*/ |
352 | err = gk20a_gmmu_alloc(g, plsfm->wpr_size, &g->acr.ucode_blob); | 431 | err = g->ops.pmu.alloc_blob_space(g, plsfm->wpr_size |
432 | , &g->acr.ucode_blob); | ||
353 | if (err) | 433 | if (err) |
354 | goto free_sgt; | 434 | goto free_sgt; |
355 | 435 | ||
@@ -458,7 +538,7 @@ static int lsfm_discover_ucode_images(struct gk20a *g, | |||
458 | } | 538 | } |
459 | 539 | ||
460 | 540 | ||
461 | static int pmu_populate_loader_cfg(struct gk20a *g, | 541 | static int gm20b_pmu_populate_loader_cfg(struct gk20a *g, |
462 | struct lsfm_managed_ucode_img *lsfm, | 542 | struct lsfm_managed_ucode_img *lsfm, |
463 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size) | 543 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size) |
464 | { | 544 | { |
@@ -485,7 +565,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g, | |||
485 | physical addresses of each respective segment. | 565 | physical addresses of each respective segment. |
486 | */ | 566 | */ |
487 | addr_base = lsfm->lsb_header.ucode_off; | 567 | addr_base = lsfm->lsb_header.ucode_off; |
488 | mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); | 568 | g->ops.pmu.get_wpr(g, &inf.base, &inf.size); |
489 | addr_base += inf.base; | 569 | addr_base += inf.base; |
490 | gm20b_dbg_pmu("pmu loader cfg u32 addrbase %x\n", (u32)addr_base); | 570 | gm20b_dbg_pmu("pmu loader cfg u32 addrbase %x\n", (u32)addr_base); |
491 | /*From linux*/ | 571 | /*From linux*/ |
@@ -530,7 +610,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g, | |||
530 | return 0; | 610 | return 0; |
531 | } | 611 | } |
532 | 612 | ||
533 | static int flcn_populate_bl_dmem_desc(struct gk20a *g, | 613 | static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g, |
534 | struct lsfm_managed_ucode_img *lsfm, | 614 | struct lsfm_managed_ucode_img *lsfm, |
535 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size, | 615 | union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size, |
536 | u32 falconid) | 616 | u32 falconid) |
@@ -557,13 +637,13 @@ static int flcn_populate_bl_dmem_desc(struct gk20a *g, | |||
557 | physical addresses of each respective segment. | 637 | physical addresses of each respective segment. |
558 | */ | 638 | */ |
559 | addr_base = lsfm->lsb_header.ucode_off; | 639 | addr_base = lsfm->lsb_header.ucode_off; |
560 | mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); | 640 | g->ops.pmu.get_wpr(g, &inf.base, &inf.size); |
561 | if (falconid == LSF_FALCON_ID_GPCCS) | 641 | if (falconid == LSF_FALCON_ID_GPCCS) |
562 | addr_base += g->pmu.wpr_buf.gpu_va; | 642 | addr_base += g->pmu.wpr_buf.gpu_va; |
563 | else | 643 | else |
564 | addr_base += inf.base; | 644 | addr_base += inf.base; |
565 | gm20b_dbg_pmu("gen loader cfg %x u32 addrbase %x ID\n", (u32)addr_base, | 645 | gm20b_dbg_pmu("gen loader cfg %x u32 addrbase %x ID\n", (u32)addr_base, |
566 | lsfm->wpr_header.falcon_id); | 646 | lsfm->wpr_header.falcon_id); |
567 | addr_code = u64_lo32((addr_base + | 647 | addr_code = u64_lo32((addr_base + |
568 | desc->app_start_offset + | 648 | desc->app_start_offset + |
569 | desc->app_resident_code_offset) >> 8); | 649 | desc->app_resident_code_offset) >> 8); |
@@ -595,16 +675,17 @@ static int lsfm_fill_flcn_bl_gen_desc(struct gk20a *g, | |||
595 | struct pmu_gk20a *pmu = &g->pmu; | 675 | struct pmu_gk20a *pmu = &g->pmu; |
596 | if (pnode->wpr_header.falcon_id != pmu->falcon_id) { | 676 | if (pnode->wpr_header.falcon_id != pmu->falcon_id) { |
597 | gm20b_dbg_pmu("non pmu. write flcn bl gen desc\n"); | 677 | gm20b_dbg_pmu("non pmu. write flcn bl gen desc\n"); |
598 | flcn_populate_bl_dmem_desc(g, pnode, &pnode->bl_gen_desc, | 678 | g->ops.pmu.flcn_populate_bl_dmem_desc(g, |
599 | &pnode->bl_gen_desc_size, | 679 | pnode, &pnode->bl_gen_desc, |
600 | pnode->wpr_header.falcon_id); | 680 | &pnode->bl_gen_desc_size, |
681 | pnode->wpr_header.falcon_id); | ||
601 | return 0; | 682 | return 0; |
602 | } | 683 | } |
603 | 684 | ||
604 | if (pmu->pmu_mode & PMU_LSFM_MANAGED) { | 685 | if (pmu->pmu_mode & PMU_LSFM_MANAGED) { |
605 | gm20b_dbg_pmu("pmu write flcn bl gen desc\n"); | 686 | gm20b_dbg_pmu("pmu write flcn bl gen desc\n"); |
606 | if (pnode->wpr_header.falcon_id == pmu->falcon_id) | 687 | if (pnode->wpr_header.falcon_id == pmu->falcon_id) |
607 | return pmu_populate_loader_cfg(g, pnode, | 688 | return g->ops.pmu.pmu_populate_loader_cfg(g, pnode, |
608 | &pnode->bl_gen_desc, &pnode->bl_gen_desc_size); | 689 | &pnode->bl_gen_desc, &pnode->bl_gen_desc_size); |
609 | } | 690 | } |
610 | 691 | ||
@@ -808,7 +889,8 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g, | |||
808 | data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE; | 889 | data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE; |
809 | pnode->lsb_header.flags = data; | 890 | pnode->lsb_header.flags = data; |
810 | } | 891 | } |
811 | if (falcon_id == LSF_FALCON_ID_GPCCS) { | 892 | |
893 | if (g->ops.pmu.is_priv_load(falcon_id)) { | ||
812 | pnode->lsb_header.flags |= | 894 | pnode->lsb_header.flags |= |
813 | NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE; | 895 | NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE; |
814 | } | 896 | } |
@@ -833,8 +915,8 @@ static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, | |||
833 | pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT; | 915 | pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT; |
834 | pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY; | 916 | pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY; |
835 | 917 | ||
836 | if (falcon_id == LSF_FALCON_ID_GPCCS) | 918 | pnode->wpr_header.lazy_bootstrap = |
837 | pnode->wpr_header.lazy_bootstrap = 1; | 919 | g->ops.pmu.is_lazy_bootstrap(falcon_id); |
838 | 920 | ||
839 | /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by | 921 | /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by |
840 | Android */ | 922 | Android */ |
@@ -1090,8 +1172,7 @@ static u8 pmu_is_debug_mode_en(struct gk20a *g) | |||
1090 | /* | 1172 | /* |
1091 | * @brief Patch signatures into ucode image | 1173 | * @brief Patch signatures into ucode image |
1092 | */ | 1174 | */ |
1093 | static int | 1175 | int acr_ucode_patch_sig(struct gk20a *g, |
1094 | acr_ucode_patch_sig(struct gk20a *g, | ||
1095 | unsigned int *p_img, | 1176 | unsigned int *p_img, |
1096 | unsigned int *p_prod_sig, | 1177 | unsigned int *p_prod_sig, |
1097 | unsigned int *p_dbg_sig, | 1178 | unsigned int *p_dbg_sig, |
@@ -1231,7 +1312,7 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g, | |||
1231 | gk20a_dbg_fn(""); | 1312 | gk20a_dbg_fn(""); |
1232 | 1313 | ||
1233 | mutex_lock(&pmu->isr_mutex); | 1314 | mutex_lock(&pmu->isr_mutex); |
1234 | pmu_reset(pmu); | 1315 | g->ops.pmu.reset(g); |
1235 | pmu->isr_enabled = true; | 1316 | pmu->isr_enabled = true; |
1236 | mutex_unlock(&pmu->isr_mutex); | 1317 | mutex_unlock(&pmu->isr_mutex); |
1237 | 1318 | ||
@@ -1346,20 +1427,24 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | |||
1346 | * to PMU halt | 1427 | * to PMU halt |
1347 | */ | 1428 | */ |
1348 | 1429 | ||
1349 | if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g))) | 1430 | if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, |
1431 | gk20a_get_gr_idle_timeout(g))) | ||
1350 | goto err_unmap_bl; | 1432 | goto err_unmap_bl; |
1351 | 1433 | ||
1352 | gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g, | 1434 | gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g, |
1353 | pwr_falcon_mmu_phys_sec_r())); | 1435 | pwr_falcon_mmu_phys_sec_r())); |
1354 | gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); | 1436 | gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); |
1355 | 1437 | ||
1356 | gm20b_init_pmu_setup_hw1(g, desc, acr->hsbl_ucode.size); | 1438 | g->ops.pmu.init_falcon_setup_hw(g, desc, acr->hsbl_ucode.size); |
1439 | |||
1357 | /* Poll for HALT */ | 1440 | /* Poll for HALT */ |
1358 | if (b_wait_for_halt) { | 1441 | if (b_wait_for_halt) { |
1359 | err = pmu_wait_for_halt(g, ACR_COMPLETION_TIMEOUT_MS); | 1442 | err = g->ops.pmu.falcon_wait_for_halt(g, |
1443 | ACR_COMPLETION_TIMEOUT_MS); | ||
1360 | if (err == 0) { | 1444 | if (err == 0) { |
1361 | /* Clear the HALT interrupt */ | 1445 | /* Clear the HALT interrupt */ |
1362 | if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g))) | 1446 | if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, |
1447 | gk20a_get_gr_idle_timeout(g))) | ||
1363 | goto err_unmap_bl; | 1448 | goto err_unmap_bl; |
1364 | } | 1449 | } |
1365 | else | 1450 | else |
@@ -1387,7 +1472,7 @@ err_done: | |||
1387 | * @param[in] timeout Timeout in msec for PMU to halt | 1472 | * @param[in] timeout Timeout in msec for PMU to halt |
1388 | * @return '0' if PMU halts | 1473 | * @return '0' if PMU halts |
1389 | */ | 1474 | */ |
1390 | int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) | 1475 | static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) |
1391 | { | 1476 | { |
1392 | u32 data = 0; | 1477 | u32 data = 0; |
1393 | int completion = -EBUSY; | 1478 | int completion = -EBUSY; |
@@ -1424,7 +1509,7 @@ int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) | |||
1424 | * @param[in] timeout_us Timeout in msec for halt to clear | 1509 | * @param[in] timeout_us Timeout in msec for halt to clear |
1425 | * @return '0' if PMU halt irq status is clear | 1510 | * @return '0' if PMU halt irq status is clear |
1426 | */ | 1511 | */ |
1427 | int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout) | 1512 | static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout) |
1428 | { | 1513 | { |
1429 | u32 data = 0; | 1514 | u32 data = 0; |
1430 | unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); | 1515 | unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); |
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h index 414e22b6..179345b9 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h | |||
@@ -406,13 +406,13 @@ struct acr_gm20b { | |||
406 | 406 | ||
407 | void gm20b_init_secure_pmu(struct gpu_ops *gops); | 407 | void gm20b_init_secure_pmu(struct gpu_ops *gops); |
408 | int prepare_ucode_blob(struct gk20a *g); | 408 | int prepare_ucode_blob(struct gk20a *g); |
409 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
410 | int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
411 | int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); | ||
412 | int gm20b_bootstrap_hs_flcn(struct gk20a *g); | ||
413 | int gm20b_pmu_setup_sw(struct gk20a *g); | 409 | int gm20b_pmu_setup_sw(struct gk20a *g); |
414 | int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt); | 410 | int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt); |
415 | int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout_us); | ||
416 | int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout); | ||
417 | int gm20b_init_nspmu_setup_hw1(struct gk20a *g); | 411 | int gm20b_init_nspmu_setup_hw1(struct gk20a *g); |
412 | int acr_ucode_patch_sig(struct gk20a *g, | ||
413 | unsigned int *p_img, | ||
414 | unsigned int *p_prod_sig, | ||
415 | unsigned int *p_dbg_sig, | ||
416 | unsigned int *p_patch_loc, | ||
417 | unsigned int *p_patch_ind); | ||
418 | #endif /*__ACR_GM20B_H_*/ | 418 | #endif /*__ACR_GM20B_H_*/ |
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 84b36232..d5131b7a 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c | |||
@@ -708,6 +708,7 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | |||
708 | u32 err, flags; | 708 | u32 err, flags; |
709 | u32 reg_offset = gr_gpcs_gpccs_falcon_hwcfg_r() - | 709 | u32 reg_offset = gr_gpcs_gpccs_falcon_hwcfg_r() - |
710 | gr_fecs_falcon_hwcfg_r(); | 710 | gr_fecs_falcon_hwcfg_r(); |
711 | u8 falcon_id_mask = 0; | ||
711 | 712 | ||
712 | gk20a_dbg_fn(""); | 713 | gk20a_dbg_fn(""); |
713 | 714 | ||
@@ -747,8 +748,13 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | |||
747 | } else { | 748 | } else { |
748 | /* bind WPR VA inst block */ | 749 | /* bind WPR VA inst block */ |
749 | gr_gk20a_load_falcon_bind_instblk(g); | 750 | gr_gk20a_load_falcon_bind_instblk(g); |
750 | err = g->ops.pmu.load_lsfalcon_ucode(g, | 751 | if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_FECS)) |
751 | (1 << LSF_FALCON_ID_GPCCS)); | 752 | falcon_id_mask |= (1 << LSF_FALCON_ID_FECS); |
753 | if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_GPCCS)) | ||
754 | falcon_id_mask |= (1 << LSF_FALCON_ID_GPCCS); | ||
755 | |||
756 | err = g->ops.pmu.load_lsfalcon_ucode(g, falcon_id_mask); | ||
757 | |||
752 | if (err) { | 758 | if (err) { |
753 | gk20a_err(dev_from_gk20a(g), | 759 | gk20a_err(dev_from_gk20a(g), |
754 | "Unable to boot GPCCS\n"); | 760 | "Unable to boot GPCCS\n"); |