summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijayakumar <vsubbu@nvidia.com>2015-04-09 07:17:13 -0400
committerIshan Mittal <imittal@nvidia.com>2015-05-18 02:03:44 -0400
commitd65a93b80c60bb677fbc13b7180e0f31b7f97f84 (patch)
treeda92083e7565c8d82f4f8bd7d06dab20b4f61e1a
parent6a5cc111713cec1d0e1edf9b8a1e64eb17105d9c (diff)
gpu: nvgpu: add secure gpccs boot support
bug 200080684 keeping it disabled by default also trimming the code by removing redundant variable to check recovery. pmu quick wait now checks only for irqs which are serviced by kernel. requests pmu to bit bang gpccs ucode. Change-Id: I12ef23d6d59b507e86a129b69eab65b21d0438c6 Signed-off-by: Vijayakumar <vsubbu@nvidia.com> Reviewed-on: http://git-master/r/729622 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h4
-rw-r--r--drivers/gpu/nvgpu/gk20a/hal_gk20a.c1
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c8
-rw-r--r--drivers/gpu/nvgpu/gm20b/acr_gm20b.c112
-rw-r--r--drivers/gpu/nvgpu/gm20b/acr_gm20b.h4
-rw-r--r--drivers/gpu/nvgpu/gm20b/gr_gm20b.c86
-rw-r--r--drivers/gpu/nvgpu/gm20b/hal_gm20b.c1
-rw-r--r--drivers/gpu/nvgpu/gm20b/pmu_gm20b.c11
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);
57static get_ucode_details pmu_acr_supp_ucode_list[] = { 57static 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}
213int 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;
278free_lsf_desc:
279 kfree(lsf_desc);
280rel_sig:
281 release_firmware(gpccs_sig);
282 return err;
283}
212 284
213int prepare_ucode_blob(struct gk20a *g) 285int 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)
710static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) 710static 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}