summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gv100/nvlink_gv100.c242
1 files changed, 164 insertions, 78 deletions
diff --git a/drivers/gpu/nvgpu/gv100/nvlink_gv100.c b/drivers/gpu/nvgpu/gv100/nvlink_gv100.c
index 9d99242f..10e7b149 100644
--- a/drivers/gpu/nvgpu/gv100/nvlink_gv100.c
+++ b/drivers/gpu/nvgpu/gv100/nvlink_gv100.c
@@ -95,19 +95,6 @@
95 minion_falcon_irqdest_target_swgen0_host_normal_f() | \ 95 minion_falcon_irqdest_target_swgen0_host_normal_f() | \
96 minion_falcon_irqdest_target_swgen1_host_normal_f()) 96 minion_falcon_irqdest_target_swgen1_host_normal_f())
97 97
98/* Minion FW header format */
99union gv100_minion_hdr {
100 struct {
101 u32 os_code_offset;
102 u32 os_code_size;
103 u32 os_data_offset;
104 u32 os_data_size;
105 u32 num_apps;
106 u32 app_0_code_start;
107 };
108 u8 raw_data[256];
109};
110
111struct __nvlink_reginit { 98struct __nvlink_reginit {
112 u32 addr; 99 u32 addr;
113 u32 value; 100 u32 value;
@@ -443,20 +430,35 @@ static bool gv100_nvlink_minion_isr(struct gk20a *g) {
443 return (intr == 0); 430 return (intr == 0);
444} 431}
445 432
433/* Extract a WORD from the MINION ucode */
434static inline u32 minion_extract_word(struct nvgpu_firmware *fw, u32 idx)
435{
436 u32 out_data = 0;
437 u8 byte = 0;
438 u32 i = 0;
439
440 for (i = 0; i < 4; i++) {
441 byte = fw->data[idx + i];
442 out_data |= ((u32)byte) << (8 * i);
443 }
444
445 return out_data;
446}
447
446/* 448/*
447 * Load minion FW and set up bootstrap 449 * Load minion FW and set up bootstrap
448 */ 450 */
449static u32 gv100_nvlink_minion_load(struct gk20a *g) 451static u32 gv100_nvlink_minion_load(struct gk20a *g)
450{ 452{
451 struct bin_hdr *hdr = NULL;
452 struct nvgpu_firmware *minion_fw = NULL;
453 union gv100_minion_hdr *minion_hdr;
454 u32 *minion_ucode = NULL;
455 u32 err = 0; 453 u32 err = 0;
454 struct nvlink_device *ndev = (struct nvlink_device *) g->nvlink.priv;
455 struct nvgpu_firmware *nvgpu_minion_fw = NULL;
456 struct minion_hdr *minion_hdr = &ndev->minion_hdr;
457 u32 data_idx = 0;
458 u32 app = 0;
456 struct nvgpu_timeout timeout; 459 struct nvgpu_timeout timeout;
457 u32 delay = GR_IDLE_CHECK_DEFAULT; 460 u32 delay = GR_IDLE_CHECK_DEFAULT;
458 u32 reg; 461 u32 reg;
459 u32 app;
460 462
461 nvgpu_log_fn(g, " "); 463 nvgpu_log_fn(g, " ");
462 464
@@ -464,8 +466,8 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g)
464 return 0; 466 return 0;
465 467
466 /* get mem unlock ucode binary */ 468 /* get mem unlock ucode binary */
467 minion_fw = nvgpu_request_firmware(g, "minion.bin", 0); 469 nvgpu_minion_fw = nvgpu_request_firmware(g, "minion.bin", 0);
468 if (!minion_fw) { 470 if (!nvgpu_minion_fw) {
469 nvgpu_err(g, "minion ucode get fail"); 471 nvgpu_err(g, "minion ucode get fail");
470 err = -ENOENT; 472 err = -ENOENT;
471 goto exit; 473 goto exit;
@@ -474,24 +476,125 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g)
474 /* nvdec falcon reset */ 476 /* nvdec falcon reset */
475 nvgpu_flcn_reset(&g->minion_flcn); 477 nvgpu_flcn_reset(&g->minion_flcn);
476 478
477 hdr = (struct bin_hdr *) minion_fw->data; 479 /* Read ucode header */
478 480 minion_hdr->os_code_offset = minion_extract_word(nvgpu_minion_fw,
479 minion_hdr = (union gv100_minion_hdr *) (minion_fw->data + 481 data_idx);
480 hdr->header_offset); 482 data_idx += 4;
481 minion_ucode = (u32 *) (minion_fw->data + hdr->data_offset); 483 minion_hdr->os_code_size = minion_extract_word(nvgpu_minion_fw,
484 data_idx);
485 data_idx += 4;
486 minion_hdr->os_data_offset = minion_extract_word(nvgpu_minion_fw,
487 data_idx);
488 data_idx += 4;
489 minion_hdr->os_data_size = minion_extract_word(nvgpu_minion_fw,
490 data_idx);
491 data_idx += 4;
492 minion_hdr->num_apps = minion_extract_word(nvgpu_minion_fw,
493 data_idx);
494 data_idx += 4;
482 495
483 nvgpu_log(g, gpu_dbg_nvlink, 496 nvgpu_log(g, gpu_dbg_nvlink,
484 "os_code_offset: 0x%x", minion_hdr->os_code_offset); 497 "MINION Ucode Header Info:");
498 nvgpu_log(g, gpu_dbg_nvlink,
499 "-------------------------");
485 nvgpu_log(g, gpu_dbg_nvlink, 500 nvgpu_log(g, gpu_dbg_nvlink,
486 "os_code_size: 0x%x", minion_hdr->os_code_size); 501 " - OS Code Offset = %u", minion_hdr->os_code_offset);
487 nvgpu_log(g, gpu_dbg_nvlink, 502 nvgpu_log(g, gpu_dbg_nvlink,
488 "os_data_offset: 0x%x", minion_hdr->os_data_offset); 503 " - OS Code Size = %u", minion_hdr->os_code_size);
504 nvgpu_log(g, gpu_dbg_nvlink,
505 " - OS Data Offset = %u", minion_hdr->os_data_offset);
506 nvgpu_log(g, gpu_dbg_nvlink,
507 " - OS Data Size = %u", minion_hdr->os_data_size);
508 nvgpu_log(g, gpu_dbg_nvlink,
509 " - Num Apps = %u", minion_hdr->num_apps);
510
511 /* Allocate offset/size arrays for all the ucode apps */
512 minion_hdr->app_code_offsets = nvgpu_kcalloc(g,
513 minion_hdr->num_apps,
514 sizeof(u32));
515 if (!minion_hdr->app_code_offsets) {
516 nvgpu_err(g, "Couldn't allocate MINION app_code_offsets array");
517 err = -ENOMEM;
518 goto exit;
519 }
520
521 minion_hdr->app_code_sizes = nvgpu_kcalloc(g,
522 minion_hdr->num_apps,
523 sizeof(u32));
524 if (!minion_hdr->app_code_sizes) {
525 nvgpu_err(g, "Couldn't allocate MINION app_code_sizes array");
526 err = -ENOMEM;
527 goto exit;
528 }
529
530 minion_hdr->app_data_offsets = nvgpu_kcalloc(g,
531 minion_hdr->num_apps,
532 sizeof(u32));
533 if (!minion_hdr->app_data_offsets) {
534 nvgpu_err(g, "Couldn't allocate MINION app_data_offsets array");
535 err = -ENOMEM;
536 goto exit;
537 }
538
539 minion_hdr->app_data_sizes = nvgpu_kcalloc(g,
540 minion_hdr->num_apps,
541 sizeof(u32));
542 if (!minion_hdr->app_data_sizes) {
543 nvgpu_err(g, "Couldn't allocate MINION app_data_sizes array");
544 err = -ENOMEM;
545 goto exit;
546 }
547
548 /* Get app code offsets and sizes */
549 for (app = 0; app < minion_hdr->num_apps; app++) {
550 minion_hdr->app_code_offsets[app] =
551 minion_extract_word(nvgpu_minion_fw, data_idx);
552 data_idx += 4;
553 minion_hdr->app_code_sizes[app] =
554 minion_extract_word(nvgpu_minion_fw, data_idx);
555 data_idx += 4;
556
557 nvgpu_log(g, gpu_dbg_nvlink,
558 " - App Code:");
559 nvgpu_log(g, gpu_dbg_nvlink,
560 " - App #%d: Code Offset = %u, Code Size = %u",
561 app,
562 minion_hdr->app_code_offsets[app],
563 minion_hdr->app_code_sizes[app]);
564 }
565
566 /* Get app data offsets and sizes */
567 for (app = 0; app < minion_hdr->num_apps; app++) {
568 minion_hdr->app_data_offsets[app] =
569 minion_extract_word(nvgpu_minion_fw, data_idx);
570 data_idx += 4;
571 minion_hdr->app_data_sizes[app] =
572 minion_extract_word(nvgpu_minion_fw, data_idx);
573 data_idx += 4;
574
575 nvgpu_log(g, gpu_dbg_nvlink,
576 " - App Data:");
577 nvgpu_log(g, gpu_dbg_nvlink,
578 " - App #%d: Data Offset = %u, Data Size = %u",
579 app,
580 minion_hdr->app_data_offsets[app],
581 minion_hdr->app_data_sizes[app]);
582 }
583
584 minion_hdr->ovl_offset = minion_extract_word(nvgpu_minion_fw, data_idx);
585 data_idx += 4;
586 minion_hdr->ovl_size = minion_extract_word(nvgpu_minion_fw, data_idx);
587 data_idx += 4;
588
589 ndev->minion_img = &(nvgpu_minion_fw->data[data_idx]);
590 minion_hdr->ucode_data_size = nvgpu_minion_fw->size - data_idx;
591
489 nvgpu_log(g, gpu_dbg_nvlink, 592 nvgpu_log(g, gpu_dbg_nvlink,
490 "os_data_size: 0x%x", minion_hdr->os_data_size); 593 " - Overlay Offset = %u", minion_hdr->ovl_offset);
491 nvgpu_log(g, gpu_dbg_nvlink, 594 nvgpu_log(g, gpu_dbg_nvlink,
492 "num_apps: 0x%x", minion_hdr->num_apps); 595 " - Overlay Size = %u", minion_hdr->ovl_size);
493 nvgpu_log(g, gpu_dbg_nvlink, 596 nvgpu_log(g, gpu_dbg_nvlink,
494 "app_0_code_start: 0x%x", minion_hdr->app_0_code_start); 597 " - Ucode Data Size = %u", minion_hdr->ucode_data_size);
495 598
496 /* Clear interrupts */ 599 /* Clear interrupts */
497 nvgpu_flcn_set_irq(&g->minion_flcn, true, MINION_FALCON_INTR_MASK, 600 nvgpu_flcn_set_irq(&g->minion_flcn, true, MINION_FALCON_INTR_MASK,
@@ -499,58 +602,34 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g)
499 602
500 /* Copy Non Secure IMEM code */ 603 /* Copy Non Secure IMEM code */
501 nvgpu_flcn_copy_to_imem(&g->minion_flcn, 0, 604 nvgpu_flcn_copy_to_imem(&g->minion_flcn, 0,
502 (u8 *)&minion_ucode[minion_hdr->os_code_offset >> 2], 605 (u8 *)&ndev->minion_img[minion_hdr->os_code_offset],
503 minion_hdr->os_code_size, 0, false, 606 minion_hdr->os_code_size, 0, false,
504 GET_IMEM_TAG(minion_hdr->os_code_offset)); 607 GET_IMEM_TAG(minion_hdr->os_code_offset));
505 608
506 /* Copy Non Secure DMEM code */ 609 /* Copy Non Secure DMEM code */
507 nvgpu_flcn_copy_to_dmem(&g->minion_flcn, 0, 610 nvgpu_flcn_copy_to_dmem(&g->minion_flcn, 0,
508 (u8 *)&minion_ucode[minion_hdr->os_data_offset >> 2], 611 (u8 *)&ndev->minion_img[minion_hdr->os_data_offset],
509 minion_hdr->os_data_size, 0); 612 minion_hdr->os_data_size, 0);
510 613
511 /* If apps are there load them securely */ 614 /* Load the apps securely */
512 if (minion_hdr->num_apps) { 615 for (app = 0; app < minion_hdr->num_apps; app++) {
513 for (app = 0; app < minion_hdr->num_apps; app++) { 616 u32 app_code_start = minion_hdr->app_code_offsets[app];
514 u32 app_code_start, app_code_size; 617 u32 app_code_size = minion_hdr->app_code_sizes[app];
515 u32 app_data_start, app_data_size; 618 u32 app_data_start = minion_hdr->app_data_offsets[app];
516 619 u32 app_data_size = minion_hdr->app_data_sizes[app];
517 app_code_start = 620
518 *((u32 *) &minion_hdr->app_0_code_start + 621 if (app_code_size)
519 2*app); 622 nvgpu_flcn_copy_to_imem(&g->minion_flcn,
520 app_code_size = 623 app_code_start,
521 *((u32 *) &minion_hdr->app_0_code_start + 624 (u8 *)&ndev->minion_img[app_code_start],
522 2*app + 1); 625 app_code_size, 0, true,
523 app_data_start = 626 GET_IMEM_TAG(app_code_start));
524 *((u32 *) &minion_hdr->app_0_code_start + 627
525 2*minion_hdr->num_apps + 2*app); 628 if (app_data_size)
526 app_data_size = 629 nvgpu_flcn_copy_to_dmem(&g->minion_flcn,
527 *((u32 *) &minion_hdr->app_0_code_start + 630 app_data_start,
528 2*minion_hdr->num_apps + 2*app + 1); 631 (u8 *)&ndev->minion_img[app_data_start],
529 632 app_data_size, 0);
530 nvgpu_log(g, gpu_dbg_nvlink,
531 " app %d code_offset 0x%x", app, app_code_start);
532 nvgpu_log(g, gpu_dbg_nvlink,
533 " app %d code_size 0x%x", app, app_code_size);
534 nvgpu_log(g, gpu_dbg_nvlink,
535 " app %d data_offset 0x%x", app, app_data_start);
536 nvgpu_log(g, gpu_dbg_nvlink,
537 " app %d data_size 0x%x", app, app_data_size);
538
539 if (app_code_size)
540 nvgpu_flcn_copy_to_imem(&g->minion_flcn,
541 app_code_start,
542 (u8 *)&minion_ucode[
543 app_code_start >> 2],
544 app_code_size, 0, true,
545 GET_IMEM_TAG(app_code_start));
546
547 if (app_data_size)
548 nvgpu_flcn_copy_to_dmem(&g->minion_flcn,
549 app_data_start,
550 (u8 *)&minion_ucode[
551 app_data_start >> 2],
552 app_data_size, 0);
553 }
554 } 633 }
555 634
556 /* set BOOTVEC to start of non-secure code */ 635 /* set BOOTVEC to start of non-secure code */
@@ -595,8 +674,15 @@ static u32 gv100_nvlink_minion_load(struct gk20a *g)
595 gv100_nvlink_initialize_minion(g); 674 gv100_nvlink_initialize_minion(g);
596 675
597exit: 676exit:
598 if (minion_fw) 677 nvgpu_kfree(g, minion_hdr->app_code_offsets);
599 nvgpu_release_firmware(g, minion_fw); 678 nvgpu_kfree(g, minion_hdr->app_code_sizes);
679 nvgpu_kfree(g, minion_hdr->app_data_offsets);
680 nvgpu_kfree(g, minion_hdr->app_data_sizes);
681
682 if (nvgpu_minion_fw) {
683 nvgpu_release_firmware(g, nvgpu_minion_fw);
684 ndev->minion_img = NULL;
685 }
600 686
601 return err; 687 return err;
602} 688}