diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 112 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 86 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/hal_gm20b.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/pmu_gm20b.c | 11 |
8 files changed, 173 insertions, 54 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index ce8d1d62..67a6123e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -377,15 +377,15 @@ struct gpu_ops { | |||
377 | int (*pmu_setup_hw_and_bootstrap)(struct gk20a *g); | 377 | int (*pmu_setup_hw_and_bootstrap)(struct gk20a *g); |
378 | int (*pmu_setup_elpg)(struct gk20a *g); | 378 | int (*pmu_setup_elpg)(struct gk20a *g); |
379 | int (*init_wpr_region)(struct gk20a *g); | 379 | int (*init_wpr_region)(struct gk20a *g); |
380 | bool lspmuwprinitdone; | 380 | u32 lspmuwprinitdone; |
381 | bool fecsbootstrapdone; | 381 | bool fecsbootstrapdone; |
382 | u32 fecsrecoveryinprogress; | ||
383 | } pmu; | 382 | } pmu; |
384 | struct { | 383 | struct { |
385 | int (*init_clk_support)(struct gk20a *g); | 384 | int (*init_clk_support)(struct gk20a *g); |
386 | int (*suspend_clk_support)(struct gk20a *g); | 385 | int (*suspend_clk_support)(struct gk20a *g); |
387 | } clk; | 386 | } clk; |
388 | bool privsecurity; | 387 | bool privsecurity; |
388 | bool securegpccs; | ||
389 | struct { | 389 | struct { |
390 | const struct regop_offset_range* ( | 390 | const struct regop_offset_range* ( |
391 | *get_global_whitelist_ranges)(void); | 391 | *get_global_whitelist_ranges)(void); |
diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 5a9c38ea..b8268e1f 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c | |||
@@ -52,6 +52,7 @@ int gk20a_init_hal(struct gk20a *g) | |||
52 | 52 | ||
53 | *gops = gk20a_ops; | 53 | *gops = gk20a_ops; |
54 | gops->privsecurity = 0; | 54 | gops->privsecurity = 0; |
55 | gops->securegpccs = 0; | ||
55 | gk20a_init_mc(gops); | 56 | gk20a_init_mc(gops); |
56 | gk20a_init_ltc(gops); | 57 | gk20a_init_ltc(gops); |
57 | gk20a_init_gr_ops(gops); | 58 | gk20a_init_gr_ops(gops); |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 6313b9d5..2456c784 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -3333,12 +3333,16 @@ int pmu_wait_message_cond(struct pmu_gk20a *pmu, u32 timeout, | |||
3333 | struct gk20a *g = gk20a_from_pmu(pmu); | 3333 | struct gk20a *g = gk20a_from_pmu(pmu); |
3334 | unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); | 3334 | unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); |
3335 | unsigned long delay = GR_IDLE_CHECK_DEFAULT; | 3335 | unsigned long delay = GR_IDLE_CHECK_DEFAULT; |
3336 | u32 servicedpmuint; | ||
3336 | 3337 | ||
3338 | servicedpmuint = pwr_falcon_irqstat_halt_true_f() | | ||
3339 | pwr_falcon_irqstat_exterr_true_f() | | ||
3340 | pwr_falcon_irqstat_swgen0_true_f(); | ||
3337 | do { | 3341 | do { |
3338 | if (*var == val) | 3342 | if (*var == val) |
3339 | return 0; | 3343 | return 0; |
3340 | 3344 | ||
3341 | if (gk20a_readl(g, pwr_falcon_irqstat_r())) | 3345 | if (gk20a_readl(g, pwr_falcon_irqstat_r()) & servicedpmuint) |
3342 | gk20a_pmu_isr(g); | 3346 | gk20a_pmu_isr(g); |
3343 | 3347 | ||
3344 | usleep_range(delay, delay * 2); | 3348 | usleep_range(delay, delay * 2); |
@@ -4042,8 +4046,6 @@ int gk20a_pmu_destroy(struct gk20a *g) | |||
4042 | pmu->zbc_ready = false; | 4046 | pmu->zbc_ready = false; |
4043 | g->ops.pmu.lspmuwprinitdone = false; | 4047 | g->ops.pmu.lspmuwprinitdone = false; |
4044 | g->ops.pmu.fecsbootstrapdone = false; | 4048 | g->ops.pmu.fecsbootstrapdone = false; |
4045 | g->ops.pmu.fecsrecoveryinprogress = 0; | ||
4046 | |||
4047 | 4049 | ||
4048 | gk20a_dbg_fn("done"); | 4050 | gk20a_dbg_fn("done"); |
4049 | return 0; | 4051 | return 0; |
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index 2e33c3f0..ba47d235 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c | |||
@@ -57,6 +57,7 @@ static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm); | |||
57 | static get_ucode_details pmu_acr_supp_ucode_list[] = { | 57 | static get_ucode_details pmu_acr_supp_ucode_list[] = { |
58 | pmu_ucode_details, | 58 | pmu_ucode_details, |
59 | fecs_ucode_details, | 59 | fecs_ucode_details, |
60 | gpccs_ucode_details, | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | /*Once is LS mode, cpuctl_alias is only accessible*/ | 63 | /*Once is LS mode, cpuctl_alias is only accessible*/ |
@@ -209,6 +210,77 @@ rel_sig: | |||
209 | release_firmware(fecs_sig); | 210 | release_firmware(fecs_sig); |
210 | return err; | 211 | return err; |
211 | } | 212 | } |
213 | int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | ||
214 | { | ||
215 | struct lsf_ucode_desc *lsf_desc; | ||
216 | const struct firmware *gpccs_sig; | ||
217 | int err; | ||
218 | |||
219 | if (g->ops.securegpccs == false) | ||
220 | return -ENOENT; | ||
221 | |||
222 | gpccs_sig = gk20a_request_firmware(g, GM20B_FECS_UCODE_SIG); | ||
223 | if (!gpccs_sig) { | ||
224 | gk20a_err(dev_from_gk20a(g), "failed to load gpccs sig"); | ||
225 | return -ENOENT; | ||
226 | } | ||
227 | lsf_desc = kzalloc(sizeof(struct lsf_ucode_desc), GFP_KERNEL); | ||
228 | if (!lsf_desc) { | ||
229 | err = -ENOMEM; | ||
230 | goto rel_sig; | ||
231 | } | ||
232 | memcpy(lsf_desc, (void *)gpccs_sig->data, | ||
233 | sizeof(struct lsf_ucode_desc)); | ||
234 | lsf_desc->falcon_id = LSF_FALCON_ID_GPCCS; | ||
235 | |||
236 | p_img->desc = kzalloc(sizeof(struct pmu_ucode_desc), GFP_KERNEL); | ||
237 | if (p_img->desc == NULL) { | ||
238 | err = -ENOMEM; | ||
239 | goto free_lsf_desc; | ||
240 | } | ||
241 | |||
242 | p_img->desc->bootloader_start_offset = | ||
243 | 0; | ||
244 | p_img->desc->bootloader_size = | ||
245 | ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256); | ||
246 | p_img->desc->bootloader_imem_offset = | ||
247 | g->ctxsw_ucode_info.gpccs.boot_imem_offset; | ||
248 | p_img->desc->bootloader_entry_point = | ||
249 | g->ctxsw_ucode_info.gpccs.boot_entry; | ||
250 | |||
251 | p_img->desc->image_size = | ||
252 | ALIGN(g->ctxsw_ucode_info.gpccs.boot.size, 256) + | ||
253 | ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256) + | ||
254 | ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256); | ||
255 | p_img->desc->app_size = ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256) | ||
256 | + ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256); | ||
257 | p_img->desc->app_start_offset = p_img->desc->bootloader_size; | ||
258 | p_img->desc->app_imem_offset = 0; | ||
259 | p_img->desc->app_imem_entry = 0; | ||
260 | p_img->desc->app_dmem_offset = 0; | ||
261 | p_img->desc->app_resident_code_offset = 0; | ||
262 | p_img->desc->app_resident_code_size = | ||
263 | ALIGN(g->ctxsw_ucode_info.gpccs.code.size, 256); | ||
264 | p_img->desc->app_resident_data_offset = | ||
265 | ALIGN(g->ctxsw_ucode_info.gpccs.data.offset, 256) - | ||
266 | ALIGN(g->ctxsw_ucode_info.gpccs.code.offset, 256); | ||
267 | p_img->desc->app_resident_data_size = | ||
268 | ALIGN(g->ctxsw_ucode_info.gpccs.data.size, 256); | ||
269 | p_img->data = (u32 *)((u8 *)g->ctxsw_ucode_info.surface_desc.cpu_va + | ||
270 | g->ctxsw_ucode_info.gpccs.boot.offset); | ||
271 | p_img->data_size = ALIGN(p_img->desc->image_size, 256); | ||
272 | p_img->fw_ver = NULL; | ||
273 | p_img->header = NULL; | ||
274 | p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc; | ||
275 | gm20b_dbg_pmu("gpccs fw loaded\n"); | ||
276 | release_firmware(gpccs_sig); | ||
277 | return 0; | ||
278 | free_lsf_desc: | ||
279 | kfree(lsf_desc); | ||
280 | rel_sig: | ||
281 | release_firmware(gpccs_sig); | ||
282 | return err; | ||
283 | } | ||
212 | 284 | ||
213 | int prepare_ucode_blob(struct gk20a *g) | 285 | int prepare_ucode_blob(struct gk20a *g) |
214 | { | 286 | { |
@@ -571,6 +643,18 @@ static int lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm, | |||
571 | gm20b_dbg_pmu("bl_data_size :%x %x\n", | 643 | gm20b_dbg_pmu("bl_data_size :%x %x\n", |
572 | pnode->lsb_header.bl_data_size, | 644 | pnode->lsb_header.bl_data_size, |
573 | lsb_hdr->bl_data_size); | 645 | lsb_hdr->bl_data_size); |
646 | gm20b_dbg_pmu("app_code_off :%x %x\n", | ||
647 | pnode->lsb_header.app_code_off, | ||
648 | lsb_hdr->app_code_off); | ||
649 | gm20b_dbg_pmu("app_code_size :%x %x\n", | ||
650 | pnode->lsb_header.app_code_size, | ||
651 | lsb_hdr->app_code_size); | ||
652 | gm20b_dbg_pmu("app_data_off :%x %x\n", | ||
653 | pnode->lsb_header.app_data_off, | ||
654 | lsb_hdr->app_data_off); | ||
655 | gm20b_dbg_pmu("app_data_size :%x %x\n", | ||
656 | pnode->lsb_header.app_data_size, | ||
657 | lsb_hdr->app_data_size); | ||
574 | gm20b_dbg_pmu("flags :%x %x\n", | 658 | gm20b_dbg_pmu("flags :%x %x\n", |
575 | pnode->lsb_header.flags, lsb_hdr->flags); | 659 | pnode->lsb_header.flags, lsb_hdr->flags); |
576 | 660 | ||
@@ -702,16 +786,6 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g, | |||
702 | VA range */ | 786 | VA range */ |
703 | pnode->lsb_header.bl_imem_off = | 787 | pnode->lsb_header.bl_imem_off = |
704 | pnode->ucode_img.desc->bootloader_imem_offset; | 788 | pnode->ucode_img.desc->bootloader_imem_offset; |
705 | pnode->lsb_header.app_code_off = | ||
706 | pnode->ucode_img.desc->app_start_offset + | ||
707 | pnode->ucode_img.desc->app_resident_code_offset; | ||
708 | pnode->lsb_header.app_code_size = | ||
709 | pnode->ucode_img.desc->app_resident_code_size; | ||
710 | pnode->lsb_header.app_data_off = | ||
711 | pnode->ucode_img.desc->app_start_offset + | ||
712 | pnode->ucode_img.desc->app_resident_data_offset; | ||
713 | pnode->lsb_header.app_data_size = | ||
714 | pnode->ucode_img.desc->app_resident_data_size; | ||
715 | 789 | ||
716 | /* TODO: OBJFLCN should export properties using which the below | 790 | /* TODO: OBJFLCN should export properties using which the below |
717 | flags should be populated.*/ | 791 | flags should be populated.*/ |
@@ -721,6 +795,10 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g, | |||
721 | data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE; | 795 | data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE; |
722 | pnode->lsb_header.flags = data; | 796 | pnode->lsb_header.flags = data; |
723 | } | 797 | } |
798 | if (falcon_id == LSF_FALCON_ID_GPCCS) { | ||
799 | pnode->lsb_header.flags |= | ||
800 | NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE; | ||
801 | } | ||
724 | } | 802 | } |
725 | } | 803 | } |
726 | 804 | ||
@@ -742,6 +820,9 @@ static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, | |||
742 | pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT; | 820 | pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT; |
743 | pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY; | 821 | pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY; |
744 | 822 | ||
823 | if (falcon_id == LSF_FALCON_ID_GPCCS) | ||
824 | pnode->wpr_header.lazy_bootstrap = 1; | ||
825 | |||
745 | /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by | 826 | /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by |
746 | Android */ | 827 | Android */ |
747 | /* Fill in static LSB header info elsewhere */ | 828 | /* Fill in static LSB header info elsewhere */ |
@@ -854,6 +935,17 @@ static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm) | |||
854 | /* Finally, update ucode surface size to include updates */ | 935 | /* Finally, update ucode surface size to include updates */ |
855 | pnode->full_ucode_size = wpr_offset - | 936 | pnode->full_ucode_size = wpr_offset - |
856 | pnode->lsb_header.ucode_off; | 937 | pnode->lsb_header.ucode_off; |
938 | if (pnode->wpr_header.falcon_id != LSF_FALCON_ID_PMU) { | ||
939 | pnode->lsb_header.app_code_off = | ||
940 | pnode->lsb_header.bl_code_size; | ||
941 | pnode->lsb_header.app_code_size = | ||
942 | pnode->lsb_header.ucode_size - | ||
943 | pnode->lsb_header.bl_code_size; | ||
944 | pnode->lsb_header.app_data_off = | ||
945 | pnode->lsb_header.ucode_size; | ||
946 | pnode->lsb_header.app_data_size = | ||
947 | pnode->lsb_header.data_size; | ||
948 | } | ||
857 | pnode = pnode->next; | 949 | pnode = pnode->next; |
858 | } | 950 | } |
859 | plsfm->wpr_size = wpr_offset; | 951 | plsfm->wpr_size = wpr_offset; |
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h index c279d797..3a5fa7d0 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h | |||
@@ -21,7 +21,7 @@ | |||
21 | /*Defines*/ | 21 | /*Defines*/ |
22 | 22 | ||
23 | /*chip specific defines*/ | 23 | /*chip specific defines*/ |
24 | #define MAX_SUPPORTED_LSFM 2 /*PMU, FECS, GPCCS*/ | 24 | #define MAX_SUPPORTED_LSFM 3 /*PMU, FECS, GPCCS*/ |
25 | #define LSF_UCODE_DATA_ALIGNMENT 4096 | 25 | #define LSF_UCODE_DATA_ALIGNMENT 4096 |
26 | 26 | ||
27 | #define GM20B_PMU_UCODE_IMAGE "gpmu_ucode_image.bin" | 27 | #define GM20B_PMU_UCODE_IMAGE "gpmu_ucode_image.bin" |
@@ -75,6 +75,8 @@ | |||
75 | #define NV_FLCN_ACR_LSF_FLAG_LOAD_CODE_AT_0_TRUE 1 | 75 | #define NV_FLCN_ACR_LSF_FLAG_LOAD_CODE_AT_0_TRUE 1 |
76 | #define NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_FALSE 0 | 76 | #define NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_FALSE 0 |
77 | #define NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE 4 | 77 | #define NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE 4 |
78 | #define NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE 8 | ||
79 | #define NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_FALSE 0 | ||
78 | 80 | ||
79 | /*! | 81 | /*! |
80 | * Light Secure WPR Content Alignments | 82 | * Light Secure WPR Content Alignments |
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 55a21c98..1fa1eb24 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c | |||
@@ -710,6 +710,10 @@ static int gr_gm20b_ctx_wait_lsf_ready(struct gk20a *g, u32 timeout, u32 val) | |||
710 | static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | 710 | static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) |
711 | { | 711 | { |
712 | u32 err; | 712 | u32 err; |
713 | unsigned long timeout = gk20a_get_gr_idle_timeout(g); | ||
714 | u32 reg_offset = gr_gpcs_gpccs_falcon_hwcfg_r() - | ||
715 | gr_fecs_falcon_hwcfg_r(); | ||
716 | |||
713 | gk20a_dbg_fn(""); | 717 | gk20a_dbg_fn(""); |
714 | 718 | ||
715 | if (tegra_platform_is_linsim()) { | 719 | if (tegra_platform_is_linsim()) { |
@@ -719,50 +723,68 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | |||
719 | gr_gpccs_ctxsw_mailbox_value_f(0xc0de7777)); | 723 | gr_gpccs_ctxsw_mailbox_value_f(0xc0de7777)); |
720 | } | 724 | } |
721 | 725 | ||
722 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | 726 | if (g->ops.pmu.fecsbootstrapdone) { |
723 | gm20b_pmu_load_lsf(g, LSF_FALCON_ID_FECS); | 727 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); |
724 | 728 | gm20b_pmu_load_lsf(g, LSF_FALCON_ID_FECS); | |
725 | gr_gm20b_load_gpccs_with_bootloader(g); | ||
726 | |||
727 | if (g->ops.pmu.fecsrecoveryinprogress) { | ||
728 | unsigned long timeout = gk20a_get_gr_idle_timeout(g); | ||
729 | err = gr_gm20b_ctx_wait_lsf_ready(g, timeout, 0x55AA55AA); | 729 | err = gr_gm20b_ctx_wait_lsf_ready(g, timeout, 0x55AA55AA); |
730 | if (err) { | 730 | if (err) { |
731 | gk20a_err(dev_from_gk20a(g), "Unable to recover FECS"); | 731 | gk20a_err(dev_from_gk20a(g), "Unable to recover FECS"); |
732 | return err; | 732 | return err; |
733 | } else { | 733 | } else { |
734 | g->ops.pmu.fecsrecoveryinprogress = 0; | 734 | if (!g->ops.securegpccs) { |
735 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | 735 | gr_gm20b_load_gpccs_with_bootloader(g); |
736 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | 736 | gk20a_writel(g, gr_gpccs_dmactl_r(), |
737 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), | ||
738 | 0xffffffff); | ||
739 | |||
740 | gk20a_writel(g, gr_gpccs_dmactl_r(), | ||
741 | gr_gpccs_dmactl_require_ctx_f(0)); | 737 | gr_gpccs_dmactl_require_ctx_f(0)); |
742 | gk20a_writel(g, gr_gpccs_cpuctl_r(), | 738 | gk20a_writel(g, gr_gpccs_cpuctl_r(), |
743 | gr_gpccs_cpuctl_startcpu_f(1)); | 739 | gr_gpccs_cpuctl_startcpu_f(1)); |
744 | 740 | } else { | |
745 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), | 741 | gk20a_writel(g, |
746 | gr_fecs_cpuctl_startcpu_f(1)); | 742 | gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); |
743 | gm20b_pmu_load_lsf(g, LSF_FALCON_ID_GPCCS); | ||
744 | err = gr_gm20b_ctx_wait_lsf_ready(g, timeout, | ||
745 | 0x55AA55AA); | ||
746 | gk20a_writel(g, reg_offset + | ||
747 | gr_fecs_cpuctl_alias_r(), | ||
748 | gr_gpccs_cpuctl_startcpu_f(1)); | ||
749 | } | ||
747 | } | 750 | } |
748 | } | 751 | } else { |
749 | |||
750 | |||
751 | if (!g->ops.pmu.fecsbootstrapdone) { | ||
752 | g->ops.pmu.fecsbootstrapdone = true; | 752 | g->ops.pmu.fecsbootstrapdone = true; |
753 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | 753 | if (!g->ops.securegpccs) { |
754 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | 754 | gr_gm20b_load_gpccs_with_bootloader(g); |
755 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), 0xffffffff); | 755 | gk20a_writel(g, gr_gpccs_dmactl_r(), |
756 | 756 | gr_gpccs_dmactl_require_ctx_f(0)); | |
757 | gk20a_writel(g, gr_gpccs_dmactl_r(), | 757 | gk20a_writel(g, gr_gpccs_cpuctl_r(), |
758 | gr_gpccs_dmactl_require_ctx_f(0)); | 758 | gr_gpccs_cpuctl_startcpu_f(1)); |
759 | gk20a_writel(g, gr_gpccs_cpuctl_r(), | 759 | } else { |
760 | pmu_wait_message_cond(&g->pmu, | ||
761 | gk20a_get_gr_idle_timeout(g), | ||
762 | &g->ops.pmu.lspmuwprinitdone, 1); | ||
763 | if (!g->ops.pmu.lspmuwprinitdone) { | ||
764 | gk20a_err(dev_from_gk20a(g), | ||
765 | "PMU WPR needed but not ready yet"); | ||
766 | return -ETIMEDOUT; | ||
767 | } | ||
768 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | ||
769 | gm20b_pmu_load_lsf(g, LSF_FALCON_ID_GPCCS); | ||
770 | err = gr_gm20b_ctx_wait_lsf_ready(g, timeout, | ||
771 | 0x55AA55AA); | ||
772 | if (err) { | ||
773 | gk20a_err(dev_from_gk20a(g), | ||
774 | "Unable to boot GPCCS\n"); | ||
775 | return err; | ||
776 | } | ||
777 | gk20a_writel(g, reg_offset + | ||
778 | gr_fecs_cpuctl_alias_r(), | ||
760 | gr_gpccs_cpuctl_startcpu_f(1)); | 779 | gr_gpccs_cpuctl_startcpu_f(1)); |
761 | 780 | } | |
762 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), | ||
763 | gr_fecs_cpuctl_startcpu_f(1)); | ||
764 | } | 781 | } |
765 | 782 | ||
783 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | ||
784 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | ||
785 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), 0xffffffff); | ||
786 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), | ||
787 | gr_fecs_cpuctl_startcpu_f(1)); | ||
766 | gk20a_dbg_fn("done"); | 788 | gk20a_dbg_fn("done"); |
767 | 789 | ||
768 | return 0; | 790 | return 0; |
diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index d5a6e422..1ab65836 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c | |||
@@ -91,6 +91,7 @@ int gm20b_init_hal(struct gk20a *g) | |||
91 | struct nvgpu_gpu_characteristics *c = &g->gpu_characteristics; | 91 | struct nvgpu_gpu_characteristics *c = &g->gpu_characteristics; |
92 | 92 | ||
93 | *gops = gm20b_ops; | 93 | *gops = gm20b_ops; |
94 | gops->securegpccs = false; | ||
94 | #ifdef CONFIG_TEGRA_ACR | 95 | #ifdef CONFIG_TEGRA_ACR |
95 | if (tegra_platform_is_linsim()) { | 96 | if (tegra_platform_is_linsim()) { |
96 | gops->privsecurity = 1; | 97 | gops->privsecurity = 1; |
diff --git a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c index c25d2d56..28b40b1c 100644 --- a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c | |||
@@ -161,7 +161,7 @@ static void pmu_handle_acr_init_wpr_msg(struct gk20a *g, struct pmu_msg *msg, | |||
161 | gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_INIT_WPR_REGION"); | 161 | gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_INIT_WPR_REGION"); |
162 | 162 | ||
163 | if (msg->msg.acr.acrmsg.errorcode == PMU_ACR_SUCCESS) | 163 | if (msg->msg.acr.acrmsg.errorcode == PMU_ACR_SUCCESS) |
164 | g->ops.pmu.lspmuwprinitdone = true; | 164 | g->ops.pmu.lspmuwprinitdone = 1; |
165 | gk20a_dbg_fn("done"); | 165 | gk20a_dbg_fn("done"); |
166 | } | 166 | } |
167 | 167 | ||
@@ -213,7 +213,7 @@ void gm20b_pmu_load_lsf(struct gk20a *g, u8 falcon_id) | |||
213 | gk20a_dbg_fn(""); | 213 | gk20a_dbg_fn(""); |
214 | 214 | ||
215 | gm20b_dbg_pmu("wprinit status = %x\n", g->ops.pmu.lspmuwprinitdone); | 215 | gm20b_dbg_pmu("wprinit status = %x\n", g->ops.pmu.lspmuwprinitdone); |
216 | if (g->ops.pmu.lspmuwprinitdone && g->ops.pmu.fecsbootstrapdone) { | 216 | if (g->ops.pmu.lspmuwprinitdone) { |
217 | /* send message to load FECS falcon */ | 217 | /* send message to load FECS falcon */ |
218 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 218 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
219 | cmd.hdr.unit_id = PMU_UNIT_ACR; | 219 | cmd.hdr.unit_id = PMU_UNIT_ACR; |
@@ -224,8 +224,8 @@ void gm20b_pmu_load_lsf(struct gk20a *g, u8 falcon_id) | |||
224 | cmd.cmd.acr.bootstrap_falcon.flags = | 224 | cmd.cmd.acr.bootstrap_falcon.flags = |
225 | PMU_ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; | 225 | PMU_ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; |
226 | cmd.cmd.acr.bootstrap_falcon.falconid = falcon_id; | 226 | cmd.cmd.acr.bootstrap_falcon.falconid = falcon_id; |
227 | gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_BOOTSTRAP_FALCON"); | 227 | gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_BOOTSTRAP_FALCON: %x\n", |
228 | g->ops.pmu.fecsrecoveryinprogress = 1; | 228 | falcon_id); |
229 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ, | 229 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ, |
230 | pmu_handle_fecs_boot_acr_msg, pmu, &seq, ~0); | 230 | pmu_handle_fecs_boot_acr_msg, pmu, &seq, ~0); |
231 | } | 231 | } |
@@ -244,7 +244,6 @@ void gm20b_init_pmu_ops(struct gpu_ops *gops) | |||
244 | gops->pmu.init_wpr_region = NULL; | 244 | gops->pmu.init_wpr_region = NULL; |
245 | } | 245 | } |
246 | gops->pmu.pmu_setup_elpg = gm20b_pmu_setup_elpg; | 246 | gops->pmu.pmu_setup_elpg = gm20b_pmu_setup_elpg; |
247 | gops->pmu.lspmuwprinitdone = false; | 247 | gops->pmu.lspmuwprinitdone = 0; |
248 | gops->pmu.fecsbootstrapdone = false; | 248 | gops->pmu.fecsbootstrapdone = false; |
249 | gops->pmu.fecsrecoveryinprogress = 0; | ||
250 | } | 249 | } |