diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/acr_gm20b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index be05a8a8..87f3ef54 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c | |||
@@ -70,18 +70,6 @@ static get_ucode_details pmu_acr_supp_ucode_list[] = { | |||
70 | gpccs_ucode_details, | 70 | gpccs_ucode_details, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | /*Once is LS mode, cpuctl_alias is only accessible*/ | ||
74 | static void start_gm20b_pmu(struct gk20a *g) | ||
75 | { | ||
76 | /*disable irqs for hs falcon booting as we will poll for halt*/ | ||
77 | nvgpu_mutex_acquire(&g->pmu.isr_mutex); | ||
78 | g->ops.pmu.pmu_enable_irq(&g->pmu, true); | ||
79 | g->pmu.isr_enabled = true; | ||
80 | nvgpu_mutex_release(&g->pmu.isr_mutex); | ||
81 | gk20a_writel(g, pwr_falcon_cpuctl_alias_r(), | ||
82 | pwr_falcon_cpuctl_startcpu_f(1)); | ||
83 | } | ||
84 | |||
85 | void gm20b_wpr_info(struct gk20a *g, struct wpr_carveout_info *inf) | 73 | void gm20b_wpr_info(struct gk20a *g, struct wpr_carveout_info *inf) |
86 | { | 74 | { |
87 | g->ops.fb.read_wpr_info(g, inf); | 75 | g->ops.fb.read_wpr_info(g, inf); |
@@ -1024,123 +1012,6 @@ static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm) | |||
1024 | return 0; | 1012 | return 0; |
1025 | } | 1013 | } |
1026 | 1014 | ||
1027 | /*Loads ACR bin to FB mem and bootstraps PMU with bootloader code | ||
1028 | * start and end are addresses of ucode blob in non-WPR region*/ | ||
1029 | int gm20b_bootstrap_hs_flcn(struct gk20a *g) | ||
1030 | { | ||
1031 | struct mm_gk20a *mm = &g->mm; | ||
1032 | struct vm_gk20a *vm = mm->pmu.vm; | ||
1033 | int err = 0; | ||
1034 | u64 *acr_dmem; | ||
1035 | u32 img_size_in_bytes = 0; | ||
1036 | u32 status, size; | ||
1037 | u64 start; | ||
1038 | struct acr_desc *acr = &g->acr; | ||
1039 | struct nvgpu_firmware *acr_fw = acr->acr_fw; | ||
1040 | struct flcn_bl_dmem_desc *bl_dmem_desc = &acr->bl_dmem_desc; | ||
1041 | u32 *acr_ucode_header_t210_load; | ||
1042 | u32 *acr_ucode_data_t210_load; | ||
1043 | |||
1044 | start = nvgpu_mem_get_addr(g, &acr->ucode_blob); | ||
1045 | size = acr->ucode_blob.size; | ||
1046 | |||
1047 | nvgpu_pmu_dbg(g, " "); | ||
1048 | |||
1049 | if (!acr_fw) { | ||
1050 | /*First time init case*/ | ||
1051 | acr_fw = nvgpu_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE, 0); | ||
1052 | if (!acr_fw) { | ||
1053 | nvgpu_err(g, "pmu ucode get fail"); | ||
1054 | return -ENOENT; | ||
1055 | } | ||
1056 | acr->acr_fw = acr_fw; | ||
1057 | acr->hsbin_hdr = (struct bin_hdr *)acr_fw->data; | ||
1058 | acr->fw_hdr = (struct acr_fw_header *)(acr_fw->data + | ||
1059 | acr->hsbin_hdr->header_offset); | ||
1060 | acr_ucode_data_t210_load = (u32 *)(acr_fw->data + | ||
1061 | acr->hsbin_hdr->data_offset); | ||
1062 | acr_ucode_header_t210_load = (u32 *)(acr_fw->data + | ||
1063 | acr->fw_hdr->hdr_offset); | ||
1064 | img_size_in_bytes = ALIGN((acr->hsbin_hdr->data_size), 256); | ||
1065 | |||
1066 | /* Lets patch the signatures first.. */ | ||
1067 | if (acr_ucode_patch_sig(g, acr_ucode_data_t210_load, | ||
1068 | (u32 *)(acr_fw->data + | ||
1069 | acr->fw_hdr->sig_prod_offset), | ||
1070 | (u32 *)(acr_fw->data + | ||
1071 | acr->fw_hdr->sig_dbg_offset), | ||
1072 | (u32 *)(acr_fw->data + | ||
1073 | acr->fw_hdr->patch_loc), | ||
1074 | (u32 *)(acr_fw->data + | ||
1075 | acr->fw_hdr->patch_sig)) < 0) { | ||
1076 | nvgpu_err(g, "patch signatures fail"); | ||
1077 | err = -1; | ||
1078 | goto err_release_acr_fw; | ||
1079 | } | ||
1080 | err = nvgpu_dma_alloc_map_sys(vm, img_size_in_bytes, | ||
1081 | &acr->acr_ucode); | ||
1082 | if (err) { | ||
1083 | err = -ENOMEM; | ||
1084 | goto err_release_acr_fw; | ||
1085 | } | ||
1086 | |||
1087 | acr_dmem = (u64 *) | ||
1088 | &(((u8 *)acr_ucode_data_t210_load)[ | ||
1089 | acr_ucode_header_t210_load[2]]); | ||
1090 | acr->acr_dmem_desc = (struct flcn_acr_desc *)((u8 *)( | ||
1091 | acr->acr_ucode.cpu_va) + acr_ucode_header_t210_load[2]); | ||
1092 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_start = | ||
1093 | start; | ||
1094 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_size = | ||
1095 | size; | ||
1096 | ((struct flcn_acr_desc *)acr_dmem)->regions.no_regions = 2; | ||
1097 | ((struct flcn_acr_desc *)acr_dmem)->wpr_offset = 0; | ||
1098 | |||
1099 | nvgpu_mem_wr_n(g, &acr->acr_ucode, 0, | ||
1100 | acr_ucode_data_t210_load, img_size_in_bytes); | ||
1101 | /* | ||
1102 | * In order to execute this binary, we will be using | ||
1103 | * a bootloader which will load this image into PMU IMEM/DMEM. | ||
1104 | * Fill up the bootloader descriptor for PMU HAL to use.. | ||
1105 | * TODO: Use standard descriptor which the generic bootloader is | ||
1106 | * checked in. | ||
1107 | */ | ||
1108 | |||
1109 | bl_dmem_desc->signature[0] = 0; | ||
1110 | bl_dmem_desc->signature[1] = 0; | ||
1111 | bl_dmem_desc->signature[2] = 0; | ||
1112 | bl_dmem_desc->signature[3] = 0; | ||
1113 | bl_dmem_desc->ctx_dma = GK20A_PMU_DMAIDX_VIRT; | ||
1114 | bl_dmem_desc->code_dma_base = | ||
1115 | (unsigned int)(((u64)acr->acr_ucode.gpu_va >> 8)); | ||
1116 | bl_dmem_desc->code_dma_base1 = 0x0; | ||
1117 | bl_dmem_desc->non_sec_code_off = acr_ucode_header_t210_load[0]; | ||
1118 | bl_dmem_desc->non_sec_code_size = acr_ucode_header_t210_load[1]; | ||
1119 | bl_dmem_desc->sec_code_off = acr_ucode_header_t210_load[5]; | ||
1120 | bl_dmem_desc->sec_code_size = acr_ucode_header_t210_load[6]; | ||
1121 | bl_dmem_desc->code_entry_point = 0; /* Start at 0th offset */ | ||
1122 | bl_dmem_desc->data_dma_base = | ||
1123 | bl_dmem_desc->code_dma_base + | ||
1124 | ((acr_ucode_header_t210_load[2]) >> 8); | ||
1125 | bl_dmem_desc->data_dma_base1 = 0x0; | ||
1126 | bl_dmem_desc->data_size = acr_ucode_header_t210_load[3]; | ||
1127 | } else { | ||
1128 | acr->acr_dmem_desc->nonwpr_ucode_blob_size = 0; | ||
1129 | } | ||
1130 | status = pmu_exec_gen_bl(g, bl_dmem_desc, 1); | ||
1131 | if (status != 0) { | ||
1132 | err = status; | ||
1133 | goto err_free_ucode_map; | ||
1134 | } | ||
1135 | return 0; | ||
1136 | err_free_ucode_map: | ||
1137 | nvgpu_dma_unmap_free(vm, &acr->acr_ucode); | ||
1138 | err_release_acr_fw: | ||
1139 | nvgpu_release_firmware(g, acr_fw); | ||
1140 | acr->acr_fw = NULL; | ||
1141 | return err; | ||
1142 | } | ||
1143 | |||
1144 | /* | 1015 | /* |
1145 | * @brief Patch signatures into ucode image | 1016 | * @brief Patch signatures into ucode image |
1146 | */ | 1017 | */ |
@@ -1172,33 +1043,6 @@ int acr_ucode_patch_sig(struct gk20a *g, | |||
1172 | return 0; | 1043 | return 0; |
1173 | } | 1044 | } |
1174 | 1045 | ||
1175 | static int bl_bootstrap(struct nvgpu_pmu *pmu, | ||
1176 | struct flcn_bl_dmem_desc *pbl_desc, u32 bl_sz) | ||
1177 | { | ||
1178 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
1179 | struct mm_gk20a *mm = &g->mm; | ||
1180 | struct nvgpu_falcon_bl_info bl_info; | ||
1181 | |||
1182 | nvgpu_log_fn(g, " "); | ||
1183 | gk20a_writel(g, pwr_falcon_itfen_r(), | ||
1184 | gk20a_readl(g, pwr_falcon_itfen_r()) | | ||
1185 | pwr_falcon_itfen_ctxen_enable_f()); | ||
1186 | gk20a_writel(g, pwr_pmu_new_instblk_r(), | ||
1187 | pwr_pmu_new_instblk_ptr_f( | ||
1188 | nvgpu_inst_block_addr(g, &mm->pmu.inst_block) >> 12) | | ||
1189 | pwr_pmu_new_instblk_valid_f(1) | | ||
1190 | pwr_pmu_new_instblk_target_sys_coh_f()); | ||
1191 | |||
1192 | bl_info.bl_src = g->acr.hsbl_ucode.cpu_va; | ||
1193 | bl_info.bl_desc = (u8 *)pbl_desc; | ||
1194 | bl_info.bl_desc_size = sizeof(struct flcn_bl_dmem_desc); | ||
1195 | bl_info.bl_size = bl_sz; | ||
1196 | bl_info.bl_start_tag = g->acr.pmu_hsbl_desc->bl_start_tag; | ||
1197 | nvgpu_flcn_bl_bootstrap(&g->pmu_flcn, &bl_info); | ||
1198 | |||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | int gm20b_init_nspmu_setup_hw1(struct gk20a *g) | 1046 | int gm20b_init_nspmu_setup_hw1(struct gk20a *g) |
1203 | { | 1047 | { |
1204 | struct nvgpu_pmu *pmu = &g->pmu; | 1048 | struct nvgpu_pmu *pmu = &g->pmu; |
@@ -1268,202 +1112,3 @@ void gm20b_update_lspmu_cmdline_args(struct gk20a *g) | |||
1268 | (u8 *)(g->ops.pmu_ver.get_pmu_cmdline_args_ptr(pmu)), | 1112 | (u8 *)(g->ops.pmu_ver.get_pmu_cmdline_args_ptr(pmu)), |
1269 | g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu), 0); | 1113 | g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu), 0); |
1270 | } | 1114 | } |
1271 | |||
1272 | int gm20b_init_pmu_setup_hw1(struct gk20a *g, | ||
1273 | void *desc, u32 bl_sz) | ||
1274 | { | ||
1275 | |||
1276 | struct nvgpu_pmu *pmu = &g->pmu; | ||
1277 | int err; | ||
1278 | |||
1279 | nvgpu_log_fn(g, " "); | ||
1280 | |||
1281 | nvgpu_mutex_acquire(&pmu->isr_mutex); | ||
1282 | nvgpu_flcn_reset(pmu->flcn); | ||
1283 | pmu->isr_enabled = true; | ||
1284 | nvgpu_mutex_release(&pmu->isr_mutex); | ||
1285 | |||
1286 | if (g->ops.pmu.setup_apertures) { | ||
1287 | g->ops.pmu.setup_apertures(g); | ||
1288 | } | ||
1289 | if (g->ops.pmu.update_lspmu_cmdline_args) { | ||
1290 | g->ops.pmu.update_lspmu_cmdline_args(g); | ||
1291 | } | ||
1292 | |||
1293 | /*disable irqs for hs falcon booting as we will poll for halt*/ | ||
1294 | nvgpu_mutex_acquire(&pmu->isr_mutex); | ||
1295 | g->ops.pmu.pmu_enable_irq(pmu, false); | ||
1296 | pmu->isr_enabled = false; | ||
1297 | nvgpu_mutex_release(&pmu->isr_mutex); | ||
1298 | /*Clearing mailbox register used to reflect capabilities*/ | ||
1299 | gk20a_writel(g, pwr_falcon_mailbox1_r(), 0); | ||
1300 | err = bl_bootstrap(pmu, desc, bl_sz); | ||
1301 | if (err) { | ||
1302 | return err; | ||
1303 | } | ||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * Executes a generic bootloader and wait for PMU to halt. | ||
1309 | * This BL will be used for those binaries that are loaded | ||
1310 | * and executed at times other than RM PMU Binary execution. | ||
1311 | * | ||
1312 | * @param[in] g gk20a pointer | ||
1313 | * @param[in] desc Bootloader descriptor | ||
1314 | * @param[in] dma_idx DMA Index | ||
1315 | * @param[in] b_wait_for_halt Wait for PMU to HALT | ||
1316 | */ | ||
1317 | int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | ||
1318 | { | ||
1319 | struct mm_gk20a *mm = &g->mm; | ||
1320 | struct vm_gk20a *vm = mm->pmu.vm; | ||
1321 | int err = 0; | ||
1322 | u32 bl_sz; | ||
1323 | struct acr_desc *acr = &g->acr; | ||
1324 | struct nvgpu_firmware *hsbl_fw = acr->hsbl_fw; | ||
1325 | struct hsflcn_bl_desc *pmu_bl_gm10x_desc; | ||
1326 | u32 *pmu_bl_gm10x = NULL; | ||
1327 | nvgpu_pmu_dbg(g, " "); | ||
1328 | |||
1329 | if (!hsbl_fw) { | ||
1330 | hsbl_fw = nvgpu_request_firmware(g, | ||
1331 | GM20B_HSBIN_PMU_BL_UCODE_IMAGE, 0); | ||
1332 | if (!hsbl_fw) { | ||
1333 | nvgpu_err(g, "pmu ucode load fail"); | ||
1334 | return -ENOENT; | ||
1335 | } | ||
1336 | acr->hsbl_fw = hsbl_fw; | ||
1337 | acr->bl_bin_hdr = (struct bin_hdr *)hsbl_fw->data; | ||
1338 | acr->pmu_hsbl_desc = (struct hsflcn_bl_desc *)(hsbl_fw->data + | ||
1339 | acr->bl_bin_hdr->header_offset); | ||
1340 | pmu_bl_gm10x_desc = acr->pmu_hsbl_desc; | ||
1341 | pmu_bl_gm10x = (u32 *)(hsbl_fw->data + | ||
1342 | acr->bl_bin_hdr->data_offset); | ||
1343 | bl_sz = ALIGN(pmu_bl_gm10x_desc->bl_img_hdr.bl_code_size, | ||
1344 | 256); | ||
1345 | acr->hsbl_ucode.size = bl_sz; | ||
1346 | nvgpu_pmu_dbg(g, "Executing Generic Bootloader\n"); | ||
1347 | |||
1348 | /*TODO in code verify that enable PMU is done, | ||
1349 | scrubbing etc is done*/ | ||
1350 | /*TODO in code verify that gmmu vm init is done*/ | ||
1351 | err = nvgpu_dma_alloc_sys(g, bl_sz, &acr->hsbl_ucode); | ||
1352 | if (err) { | ||
1353 | nvgpu_err(g, "failed to allocate memory"); | ||
1354 | goto err_done; | ||
1355 | } | ||
1356 | |||
1357 | acr->hsbl_ucode.gpu_va = nvgpu_gmmu_map(vm, | ||
1358 | &acr->hsbl_ucode, | ||
1359 | bl_sz, | ||
1360 | 0, /* flags */ | ||
1361 | gk20a_mem_flag_read_only, false, | ||
1362 | acr->hsbl_ucode.aperture); | ||
1363 | if (!acr->hsbl_ucode.gpu_va) { | ||
1364 | nvgpu_err(g, "failed to map pmu ucode memory!!"); | ||
1365 | goto err_free_ucode; | ||
1366 | } | ||
1367 | |||
1368 | nvgpu_mem_wr_n(g, &acr->hsbl_ucode, 0, pmu_bl_gm10x, bl_sz); | ||
1369 | nvgpu_pmu_dbg(g, "Copied bl ucode to bl_cpuva\n"); | ||
1370 | } | ||
1371 | /* | ||
1372 | * Disable interrupts to avoid kernel hitting breakpoint due | ||
1373 | * to PMU halt | ||
1374 | */ | ||
1375 | |||
1376 | if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, | ||
1377 | gk20a_get_gr_idle_timeout(g))) { | ||
1378 | goto err_unmap_bl; | ||
1379 | } | ||
1380 | |||
1381 | nvgpu_pmu_dbg(g, "phys sec reg %x\n", gk20a_readl(g, | ||
1382 | pwr_falcon_mmu_phys_sec_r())); | ||
1383 | nvgpu_pmu_dbg(g, "sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); | ||
1384 | |||
1385 | g->ops.pmu.init_falcon_setup_hw(g, desc, acr->hsbl_ucode.size); | ||
1386 | |||
1387 | /* Poll for HALT */ | ||
1388 | if (b_wait_for_halt) { | ||
1389 | err = g->ops.pmu.falcon_wait_for_halt(g, | ||
1390 | ACR_COMPLETION_TIMEOUT_MS); | ||
1391 | if (err == 0) { | ||
1392 | /* Clear the HALT interrupt */ | ||
1393 | if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, | ||
1394 | gk20a_get_gr_idle_timeout(g))) { | ||
1395 | goto err_unmap_bl; | ||
1396 | } | ||
1397 | } else { | ||
1398 | goto err_unmap_bl; | ||
1399 | } | ||
1400 | } | ||
1401 | nvgpu_pmu_dbg(g, "after waiting for halt, err %x\n", err); | ||
1402 | nvgpu_pmu_dbg(g, "phys sec reg %x\n", gk20a_readl(g, | ||
1403 | pwr_falcon_mmu_phys_sec_r())); | ||
1404 | nvgpu_pmu_dbg(g, "sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); | ||
1405 | start_gm20b_pmu(g); | ||
1406 | return 0; | ||
1407 | err_unmap_bl: | ||
1408 | nvgpu_gmmu_unmap(vm, &acr->hsbl_ucode, acr->hsbl_ucode.gpu_va); | ||
1409 | err_free_ucode: | ||
1410 | nvgpu_dma_free(g, &acr->hsbl_ucode); | ||
1411 | err_done: | ||
1412 | nvgpu_release_firmware(g, hsbl_fw); | ||
1413 | return err; | ||
1414 | } | ||
1415 | |||
1416 | /*! | ||
1417 | * Wait for PMU to halt | ||
1418 | * @param[in] g GPU object pointer | ||
1419 | * @param[in] timeout_ms Timeout in msec for PMU to halt | ||
1420 | * @return '0' if PMU halts | ||
1421 | */ | ||
1422 | int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout_ms) | ||
1423 | { | ||
1424 | struct nvgpu_pmu *pmu = &g->pmu; | ||
1425 | u32 data = 0; | ||
1426 | int ret = 0; | ||
1427 | |||
1428 | ret = nvgpu_flcn_wait_for_halt(pmu->flcn, timeout_ms); | ||
1429 | if (ret) { | ||
1430 | nvgpu_err(g, "ACR boot timed out"); | ||
1431 | goto exit; | ||
1432 | } | ||
1433 | |||
1434 | g->acr.capabilities = gk20a_readl(g, pwr_falcon_mailbox1_r()); | ||
1435 | nvgpu_pmu_dbg(g, "ACR capabilities %x\n", g->acr.capabilities); | ||
1436 | data = gk20a_readl(g, pwr_falcon_mailbox0_r()); | ||
1437 | if (data) { | ||
1438 | nvgpu_err(g, "ACR boot failed, err %x", data); | ||
1439 | ret = -EAGAIN; | ||
1440 | goto exit; | ||
1441 | } | ||
1442 | |||
1443 | exit: | ||
1444 | if (ret) { | ||
1445 | nvgpu_kill_task_pg_init(g); | ||
1446 | nvgpu_pmu_state_change(g, PMU_STATE_OFF, false); | ||
1447 | nvgpu_flcn_dump_stats(pmu->flcn); | ||
1448 | } | ||
1449 | |||
1450 | return ret; | ||
1451 | } | ||
1452 | |||
1453 | /*! | ||
1454 | * Wait for PMU halt interrupt status to be cleared | ||
1455 | * @param[in] g GPU object pointer | ||
1456 | * @param[in] timeout_ms Timeout in msec for halt to clear | ||
1457 | * @return '0' if PMU halt irq status is clear | ||
1458 | */ | ||
1459 | int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout_ms) | ||
1460 | { | ||
1461 | struct nvgpu_pmu *pmu = &g->pmu; | ||
1462 | int status = 0; | ||
1463 | |||
1464 | if (nvgpu_flcn_clear_halt_intr_status(pmu->flcn, timeout_ms)) { | ||
1465 | status = -EBUSY; | ||
1466 | } | ||
1467 | |||
1468 | return status; | ||
1469 | } | ||