mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 02:22:34 +03:00
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>
This commit is contained in:
committed by
Terje Bergstrom
parent
ad24c028db
commit
e9d5e7dfca
@@ -534,6 +534,25 @@ struct gpu_ops {
|
||||
(struct gk20a *g, u32 mask);
|
||||
void (*dump_secure_fuses)(struct gk20a *g);
|
||||
int (*reset)(struct gk20a *g);
|
||||
int (*falcon_wait_for_halt)(struct gk20a *g,
|
||||
unsigned int timeout);
|
||||
int (*falcon_clear_halt_interrupt_status)(struct gk20a *g,
|
||||
unsigned int timeout);
|
||||
int (*init_falcon_setup_hw)(struct gk20a *g,
|
||||
struct flcn_bl_dmem_desc *desc, u32 bl_sz);
|
||||
bool (*is_lazy_bootstrap)(u32 falcon_id);
|
||||
bool (*is_priv_load)(u32 falcon_id);
|
||||
void (*get_wpr)(struct gk20a *g, u64 *base, u64 *size);
|
||||
int (*alloc_blob_space)(struct gk20a *g,
|
||||
size_t size, struct mem_desc *mem);
|
||||
int (*pmu_populate_loader_cfg)(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc,
|
||||
u32 *p_bl_gen_desc_size);
|
||||
int (*flcn_populate_bl_dmem_desc)(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc,
|
||||
u32 *p_bl_gen_desc_size, u32 falconid);
|
||||
u32 lspmuwprinitdone;
|
||||
u32 lsfloadedfalconid;
|
||||
bool fecsbootstrapdone;
|
||||
|
||||
@@ -2758,9 +2758,12 @@ static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr)
|
||||
|
||||
int gk20a_pmu_reset(struct gk20a *g)
|
||||
{
|
||||
gk20a_reset(g, mc_enable_pwr_enabled_f());
|
||||
int err;
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
|
||||
return 0;
|
||||
err = pmu_reset(pmu);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void gk20a_init_pmu_ops(struct gpu_ops *gops)
|
||||
@@ -2776,6 +2779,12 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops)
|
||||
gops->pmu.pmu_pg_grinit_param = NULL;
|
||||
gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = NULL;
|
||||
gops->pmu.dump_secure_fuses = NULL;
|
||||
gops->pmu.is_lazy_bootstrap = NULL;
|
||||
gops->pmu.is_priv_load = NULL;
|
||||
gops->pmu.get_wpr = NULL;
|
||||
gops->pmu.alloc_blob_space = NULL;
|
||||
gops->pmu.pmu_populate_loader_cfg = NULL;
|
||||
gops->pmu.flcn_populate_bl_dmem_desc = NULL;
|
||||
gops->pmu.reset = gk20a_pmu_reset;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,14 @@ typedef int (*get_ucode_details)(struct gk20a *g, struct flcn_ucode_img *udata);
|
||||
/*Externs*/
|
||||
|
||||
/*Forwards*/
|
||||
static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
static int gm20b_bootstrap_hs_flcn(struct gk20a *g);
|
||||
static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout);
|
||||
static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout);
|
||||
static int gm20b_init_pmu_setup_hw1(struct gk20a *g,
|
||||
struct flcn_bl_dmem_desc *desc, u32 bl_sz);
|
||||
static int lsfm_discover_ucode_images(struct gk20a *g,
|
||||
struct ls_flcn_mgr *plsfm);
|
||||
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);
|
||||
static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm);
|
||||
static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm,
|
||||
struct mem_desc *nonwpr);
|
||||
static int acr_ucode_patch_sig(struct gk20a *g,
|
||||
unsigned int *p_img,
|
||||
unsigned int *p_prod_sig,
|
||||
unsigned int *p_dbg_sig,
|
||||
unsigned int *p_patch_loc,
|
||||
unsigned int *p_patch_ind);
|
||||
static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm);
|
||||
static int gm20b_pmu_populate_loader_cfg(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size);
|
||||
static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size,
|
||||
u32 falconid);
|
||||
static int gm20b_alloc_blob_space(struct gk20a *g,
|
||||
size_t size, struct mem_desc *mem);
|
||||
static bool gm20b_is_priv_load(u32 falcon_id);
|
||||
static bool gm20b_is_lazy_bootstrap(u32 falcon_id);
|
||||
|
||||
/*Globals*/
|
||||
static get_ucode_details pmu_acr_supp_ucode_list[] = {
|
||||
@@ -72,14 +85,33 @@ static void start_gm20b_pmu(struct gk20a *g)
|
||||
pwr_falcon_cpuctl_startcpu_f(1));
|
||||
}
|
||||
|
||||
void gm20b_wpr_info(struct gk20a *g, u64 *base, u64 *size)
|
||||
{
|
||||
struct mc_carveout_info inf;
|
||||
|
||||
mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2);
|
||||
*base = inf.base;
|
||||
*size = inf.size;
|
||||
}
|
||||
|
||||
void gm20b_init_secure_pmu(struct gpu_ops *gops)
|
||||
{
|
||||
gops->pmu.prepare_ucode = prepare_ucode_blob;
|
||||
gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn;
|
||||
gops->pmu.is_lazy_bootstrap = gm20b_is_lazy_bootstrap;
|
||||
gops->pmu.is_priv_load = gm20b_is_priv_load;
|
||||
gops->pmu.get_wpr = gm20b_wpr_info;
|
||||
gops->pmu.alloc_blob_space = gm20b_alloc_blob_space;
|
||||
gops->pmu.pmu_populate_loader_cfg = gm20b_pmu_populate_loader_cfg;
|
||||
gops->pmu.flcn_populate_bl_dmem_desc = gm20b_flcn_populate_bl_dmem_desc;
|
||||
gops->pmu.falcon_wait_for_halt = pmu_wait_for_halt;
|
||||
gops->pmu.falcon_clear_halt_interrupt_status =
|
||||
clear_halt_interrupt_status;
|
||||
gops->pmu.init_falcon_setup_hw = gm20b_init_pmu_setup_hw1;
|
||||
}
|
||||
/* TODO - check if any free blob res needed*/
|
||||
|
||||
int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
{
|
||||
const struct firmware *pmu_fw, *pmu_desc, *pmu_sig;
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
@@ -143,7 +175,7 @@ release_img_fw:
|
||||
return err;
|
||||
}
|
||||
|
||||
int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
{
|
||||
struct lsf_ucode_desc *lsf_desc;
|
||||
const struct firmware *fecs_sig;
|
||||
@@ -210,7 +242,7 @@ rel_sig:
|
||||
release_firmware(fecs_sig);
|
||||
return err;
|
||||
}
|
||||
int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
|
||||
{
|
||||
struct lsf_ucode_desc *lsf_desc;
|
||||
const struct firmware *gpccs_sig;
|
||||
@@ -282,6 +314,52 @@ rel_sig:
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool gm20b_is_lazy_bootstrap(u32 falcon_id)
|
||||
{
|
||||
bool enable_status = false;
|
||||
|
||||
switch (falcon_id) {
|
||||
case LSF_FALCON_ID_FECS:
|
||||
enable_status = false;
|
||||
break;
|
||||
case LSF_FALCON_ID_GPCCS:
|
||||
enable_status = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return enable_status;
|
||||
}
|
||||
|
||||
static bool gm20b_is_priv_load(u32 falcon_id)
|
||||
{
|
||||
bool enable_status = false;
|
||||
|
||||
switch (falcon_id) {
|
||||
case LSF_FALCON_ID_FECS:
|
||||
enable_status = false;
|
||||
break;
|
||||
case LSF_FALCON_ID_GPCCS:
|
||||
enable_status = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return enable_status;
|
||||
}
|
||||
|
||||
static int gm20b_alloc_blob_space(struct gk20a *g,
|
||||
size_t size, struct mem_desc *mem)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gk20a_gmmu_alloc(g, size, mem);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int prepare_ucode_blob(struct gk20a *g)
|
||||
{
|
||||
|
||||
@@ -312,11 +390,12 @@ int prepare_ucode_blob(struct gk20a *g)
|
||||
gm20b_mm_mmu_vpr_info_fetch(g);
|
||||
gr_gk20a_init_ctxsw_ucode(g);
|
||||
|
||||
mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2);
|
||||
gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base);
|
||||
g->ops.pmu.get_wpr(g, &inf.base, &inf.size);
|
||||
wpr_addr = (phys_addr_t)inf.base;
|
||||
gm20b_dbg_pmu("wpr carveout size :%llx\n", inf.size);
|
||||
wprsize = (u32)inf.size;
|
||||
gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base);
|
||||
gm20b_dbg_pmu("wpr carveout size :%x\n", wprsize);
|
||||
|
||||
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
|
||||
if (!sgt) {
|
||||
gk20a_err(dev_from_gk20a(g), "failed to allocate memory\n");
|
||||
@@ -349,7 +428,8 @@ int prepare_ucode_blob(struct gk20a *g)
|
||||
goto free_sgt;
|
||||
|
||||
/*Alloc memory to hold ucode blob contents*/
|
||||
err = gk20a_gmmu_alloc(g, plsfm->wpr_size, &g->acr.ucode_blob);
|
||||
err = g->ops.pmu.alloc_blob_space(g, plsfm->wpr_size
|
||||
, &g->acr.ucode_blob);
|
||||
if (err)
|
||||
goto free_sgt;
|
||||
|
||||
@@ -458,7 +538,7 @@ static int lsfm_discover_ucode_images(struct gk20a *g,
|
||||
}
|
||||
|
||||
|
||||
static int pmu_populate_loader_cfg(struct gk20a *g,
|
||||
static int gm20b_pmu_populate_loader_cfg(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size)
|
||||
{
|
||||
@@ -485,7 +565,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g,
|
||||
physical addresses of each respective segment.
|
||||
*/
|
||||
addr_base = lsfm->lsb_header.ucode_off;
|
||||
mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2);
|
||||
g->ops.pmu.get_wpr(g, &inf.base, &inf.size);
|
||||
addr_base += inf.base;
|
||||
gm20b_dbg_pmu("pmu loader cfg u32 addrbase %x\n", (u32)addr_base);
|
||||
/*From linux*/
|
||||
@@ -530,7 +610,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flcn_populate_bl_dmem_desc(struct gk20a *g,
|
||||
static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g,
|
||||
struct lsfm_managed_ucode_img *lsfm,
|
||||
union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size,
|
||||
u32 falconid)
|
||||
@@ -557,13 +637,13 @@ static int flcn_populate_bl_dmem_desc(struct gk20a *g,
|
||||
physical addresses of each respective segment.
|
||||
*/
|
||||
addr_base = lsfm->lsb_header.ucode_off;
|
||||
mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2);
|
||||
g->ops.pmu.get_wpr(g, &inf.base, &inf.size);
|
||||
if (falconid == LSF_FALCON_ID_GPCCS)
|
||||
addr_base += g->pmu.wpr_buf.gpu_va;
|
||||
else
|
||||
addr_base += inf.base;
|
||||
gm20b_dbg_pmu("gen loader cfg %x u32 addrbase %x ID\n", (u32)addr_base,
|
||||
lsfm->wpr_header.falcon_id);
|
||||
lsfm->wpr_header.falcon_id);
|
||||
addr_code = u64_lo32((addr_base +
|
||||
desc->app_start_offset +
|
||||
desc->app_resident_code_offset) >> 8);
|
||||
@@ -595,16 +675,17 @@ static int lsfm_fill_flcn_bl_gen_desc(struct gk20a *g,
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
if (pnode->wpr_header.falcon_id != pmu->falcon_id) {
|
||||
gm20b_dbg_pmu("non pmu. write flcn bl gen desc\n");
|
||||
flcn_populate_bl_dmem_desc(g, pnode, &pnode->bl_gen_desc,
|
||||
&pnode->bl_gen_desc_size,
|
||||
pnode->wpr_header.falcon_id);
|
||||
g->ops.pmu.flcn_populate_bl_dmem_desc(g,
|
||||
pnode, &pnode->bl_gen_desc,
|
||||
&pnode->bl_gen_desc_size,
|
||||
pnode->wpr_header.falcon_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pmu->pmu_mode & PMU_LSFM_MANAGED) {
|
||||
gm20b_dbg_pmu("pmu write flcn bl gen desc\n");
|
||||
if (pnode->wpr_header.falcon_id == pmu->falcon_id)
|
||||
return pmu_populate_loader_cfg(g, pnode,
|
||||
return g->ops.pmu.pmu_populate_loader_cfg(g, pnode,
|
||||
&pnode->bl_gen_desc, &pnode->bl_gen_desc_size);
|
||||
}
|
||||
|
||||
@@ -808,7 +889,8 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
|
||||
data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE;
|
||||
pnode->lsb_header.flags = data;
|
||||
}
|
||||
if (falcon_id == LSF_FALCON_ID_GPCCS) {
|
||||
|
||||
if (g->ops.pmu.is_priv_load(falcon_id)) {
|
||||
pnode->lsb_header.flags |=
|
||||
NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE;
|
||||
}
|
||||
@@ -833,8 +915,8 @@ static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm,
|
||||
pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT;
|
||||
pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY;
|
||||
|
||||
if (falcon_id == LSF_FALCON_ID_GPCCS)
|
||||
pnode->wpr_header.lazy_bootstrap = 1;
|
||||
pnode->wpr_header.lazy_bootstrap =
|
||||
g->ops.pmu.is_lazy_bootstrap(falcon_id);
|
||||
|
||||
/*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by
|
||||
Android */
|
||||
@@ -1090,8 +1172,7 @@ static u8 pmu_is_debug_mode_en(struct gk20a *g)
|
||||
/*
|
||||
* @brief Patch signatures into ucode image
|
||||
*/
|
||||
static int
|
||||
acr_ucode_patch_sig(struct gk20a *g,
|
||||
int acr_ucode_patch_sig(struct gk20a *g,
|
||||
unsigned int *p_img,
|
||||
unsigned int *p_prod_sig,
|
||||
unsigned int *p_dbg_sig,
|
||||
@@ -1231,7 +1312,7 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g,
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
mutex_lock(&pmu->isr_mutex);
|
||||
pmu_reset(pmu);
|
||||
g->ops.pmu.reset(g);
|
||||
pmu->isr_enabled = true;
|
||||
mutex_unlock(&pmu->isr_mutex);
|
||||
|
||||
@@ -1346,20 +1427,24 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt)
|
||||
* to PMU halt
|
||||
*/
|
||||
|
||||
if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g)))
|
||||
if (g->ops.pmu.falcon_clear_halt_interrupt_status(g,
|
||||
gk20a_get_gr_idle_timeout(g)))
|
||||
goto err_unmap_bl;
|
||||
|
||||
gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g,
|
||||
pwr_falcon_mmu_phys_sec_r()));
|
||||
gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r()));
|
||||
|
||||
gm20b_init_pmu_setup_hw1(g, desc, acr->hsbl_ucode.size);
|
||||
g->ops.pmu.init_falcon_setup_hw(g, desc, acr->hsbl_ucode.size);
|
||||
|
||||
/* Poll for HALT */
|
||||
if (b_wait_for_halt) {
|
||||
err = pmu_wait_for_halt(g, ACR_COMPLETION_TIMEOUT_MS);
|
||||
err = g->ops.pmu.falcon_wait_for_halt(g,
|
||||
ACR_COMPLETION_TIMEOUT_MS);
|
||||
if (err == 0) {
|
||||
/* Clear the HALT interrupt */
|
||||
if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g)))
|
||||
if (g->ops.pmu.falcon_clear_halt_interrupt_status(g,
|
||||
gk20a_get_gr_idle_timeout(g)))
|
||||
goto err_unmap_bl;
|
||||
}
|
||||
else
|
||||
@@ -1387,7 +1472,7 @@ err_done:
|
||||
* @param[in] timeout Timeout in msec for PMU to halt
|
||||
* @return '0' if PMU halts
|
||||
*/
|
||||
int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout)
|
||||
static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout)
|
||||
{
|
||||
u32 data = 0;
|
||||
int completion = -EBUSY;
|
||||
@@ -1424,7 +1509,7 @@ int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout)
|
||||
* @param[in] timeout_us Timeout in msec for halt to clear
|
||||
* @return '0' if PMU halt irq status is clear
|
||||
*/
|
||||
int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout)
|
||||
static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout)
|
||||
{
|
||||
u32 data = 0;
|
||||
unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout);
|
||||
|
||||
@@ -406,13 +406,13 @@ struct acr_gm20b {
|
||||
|
||||
void gm20b_init_secure_pmu(struct gpu_ops *gops);
|
||||
int prepare_ucode_blob(struct gk20a *g);
|
||||
int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img);
|
||||
int gm20b_bootstrap_hs_flcn(struct gk20a *g);
|
||||
int gm20b_pmu_setup_sw(struct gk20a *g);
|
||||
int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt);
|
||||
int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout_us);
|
||||
int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout);
|
||||
int gm20b_init_nspmu_setup_hw1(struct gk20a *g);
|
||||
int acr_ucode_patch_sig(struct gk20a *g,
|
||||
unsigned int *p_img,
|
||||
unsigned int *p_prod_sig,
|
||||
unsigned int *p_dbg_sig,
|
||||
unsigned int *p_patch_loc,
|
||||
unsigned int *p_patch_ind);
|
||||
#endif /*__ACR_GM20B_H_*/
|
||||
|
||||
@@ -708,6 +708,7 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g)
|
||||
u32 err, flags;
|
||||
u32 reg_offset = gr_gpcs_gpccs_falcon_hwcfg_r() -
|
||||
gr_fecs_falcon_hwcfg_r();
|
||||
u8 falcon_id_mask = 0;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
@@ -747,8 +748,13 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g)
|
||||
} else {
|
||||
/* bind WPR VA inst block */
|
||||
gr_gk20a_load_falcon_bind_instblk(g);
|
||||
err = g->ops.pmu.load_lsfalcon_ucode(g,
|
||||
(1 << LSF_FALCON_ID_GPCCS));
|
||||
if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_FECS))
|
||||
falcon_id_mask |= (1 << LSF_FALCON_ID_FECS);
|
||||
if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_GPCCS))
|
||||
falcon_id_mask |= (1 << LSF_FALCON_ID_GPCCS);
|
||||
|
||||
err = g->ops.pmu.load_lsfalcon_ucode(g, falcon_id_mask);
|
||||
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"Unable to boot GPCCS\n");
|
||||
|
||||
Reference in New Issue
Block a user