@@ -579,6 +579,8 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu)
579
579
{
580
580
/* Disable GMU WB/RB buffer */
581
581
gmu_write (gmu , REG_A6XX_GMU_SYS_BUS_CONFIG , 0x1 );
582
+ gmu_write (gmu , REG_A6XX_GMU_ICACHE_CONFIG , 0x1 );
583
+ gmu_write (gmu , REG_A6XX_GMU_DCACHE_CONFIG , 0x1 );
582
584
583
585
gmu_write (gmu , REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL , 0x9c40400 );
584
586
@@ -608,14 +610,95 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu)
608
610
A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE );
609
611
}
610
612
613
+ struct block_header {
614
+ u32 addr ;
615
+ u32 size ;
616
+ u32 type ;
617
+ u32 value ;
618
+ u32 data [];
619
+ };
620
+
621
+ /* this should be a general kernel helper */
622
+ static int in_range (u32 addr , u32 start , u32 size )
623
+ {
624
+ return addr >= start && addr < start + size ;
625
+ }
626
+
627
+ static bool fw_block_mem (struct a6xx_gmu_bo * bo , const struct block_header * blk )
628
+ {
629
+ if (!in_range (blk -> addr , bo -> iova , bo -> size ))
630
+ return false;
631
+
632
+ memcpy (bo -> virt + blk -> addr - bo -> iova , blk -> data , blk -> size );
633
+ return true;
634
+ }
635
+
636
+ static int a6xx_gmu_fw_load (struct a6xx_gmu * gmu )
637
+ {
638
+ struct a6xx_gpu * a6xx_gpu = container_of (gmu , struct a6xx_gpu , gmu );
639
+ struct adreno_gpu * adreno_gpu = & a6xx_gpu -> base ;
640
+ const struct firmware * fw_image = adreno_gpu -> fw [ADRENO_FW_GMU ];
641
+ const struct block_header * blk ;
642
+ u32 reg_offset ;
643
+
644
+ u32 itcm_base = 0x00000000 ;
645
+ u32 dtcm_base = 0x00040000 ;
646
+
647
+ if (adreno_is_a650 (adreno_gpu ))
648
+ dtcm_base = 0x10004000 ;
649
+
650
+ if (gmu -> legacy ) {
651
+ /* Sanity check the size of the firmware that was loaded */
652
+ if (fw_image -> size > 0x8000 ) {
653
+ DRM_DEV_ERROR (gmu -> dev ,
654
+ "GMU firmware is bigger than the available region\n" );
655
+ return - EINVAL ;
656
+ }
657
+
658
+ gmu_write_bulk (gmu , REG_A6XX_GMU_CM3_ITCM_START ,
659
+ (u32 * ) fw_image -> data , fw_image -> size );
660
+ return 0 ;
661
+ }
662
+
663
+
664
+ for (blk = (const struct block_header * ) fw_image -> data ;
665
+ (const u8 * ) blk < fw_image -> data + fw_image -> size ;
666
+ blk = (const struct block_header * ) & blk -> data [blk -> size >> 2 ]) {
667
+ if (blk -> size == 0 )
668
+ continue ;
669
+
670
+ if (in_range (blk -> addr , itcm_base , SZ_16K )) {
671
+ reg_offset = (blk -> addr - itcm_base ) >> 2 ;
672
+ gmu_write_bulk (gmu ,
673
+ REG_A6XX_GMU_CM3_ITCM_START + reg_offset ,
674
+ blk -> data , blk -> size );
675
+ } else if (in_range (blk -> addr , dtcm_base , SZ_16K )) {
676
+ reg_offset = (blk -> addr - dtcm_base ) >> 2 ;
677
+ gmu_write_bulk (gmu ,
678
+ REG_A6XX_GMU_CM3_DTCM_START + reg_offset ,
679
+ blk -> data , blk -> size );
680
+ } else if (!fw_block_mem (& gmu -> icache , blk ) &&
681
+ !fw_block_mem (& gmu -> dcache , blk ) &&
682
+ !fw_block_mem (& gmu -> dummy , blk )) {
683
+ DRM_DEV_ERROR (gmu -> dev ,
684
+ "failed to match fw block (addr=%.8x size=%d data[0]=%.8x)\n" ,
685
+ blk -> addr , blk -> size , blk -> data [0 ]);
686
+ }
687
+ }
688
+
689
+ return 0 ;
690
+ }
691
+
611
692
static int a6xx_gmu_fw_start (struct a6xx_gmu * gmu , unsigned int state )
612
693
{
613
694
static bool rpmh_init ;
614
695
struct a6xx_gpu * a6xx_gpu = container_of (gmu , struct a6xx_gpu , gmu );
615
696
struct adreno_gpu * adreno_gpu = & a6xx_gpu -> base ;
616
- int i , ret ;
697
+ int ret ;
617
698
u32 chipid ;
618
- u32 * image ;
699
+
700
+ if (adreno_is_a650 (adreno_gpu ))
701
+ gmu_write (gmu , REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF , 1 );
619
702
620
703
if (state == GMU_WARM_BOOT ) {
621
704
ret = a6xx_rpmh_start (gmu );
@@ -626,13 +709,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
626
709
"GMU firmware is not loaded\n" ))
627
710
return - ENOENT ;
628
711
629
- /* Sanity check the size of the firmware that was loaded */
630
- if (adreno_gpu -> fw [ADRENO_FW_GMU ]-> size > 0x8000 ) {
631
- DRM_DEV_ERROR (gmu -> dev ,
632
- "GMU firmware is bigger than the available region\n" );
633
- return - EINVAL ;
634
- }
635
-
636
712
/* Turn on register retention */
637
713
gmu_write (gmu , REG_A6XX_GMU_GENERAL_7 , 1 );
638
714
@@ -646,11 +722,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
646
722
return ret ;
647
723
}
648
724
649
- image = (u32 * ) adreno_gpu -> fw [ADRENO_FW_GMU ]-> data ;
650
-
651
- for (i = 0 ; i < adreno_gpu -> fw [ADRENO_FW_GMU ]-> size >> 2 ; i ++ )
652
- gmu_write (gmu , REG_A6XX_GMU_CM3_ITCM_START + i ,
653
- image [i ]);
725
+ ret = a6xx_gmu_fw_load (gmu );
726
+ if (ret )
727
+ return ret ;
654
728
}
655
729
656
730
gmu_write (gmu , REG_A6XX_GMU_CM3_FW_INIT_RESULT , 0 );
@@ -783,6 +857,13 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
783
857
status = gmu_read (gmu , REG_A6XX_GMU_GENERAL_7 ) == 1 ?
784
858
GMU_WARM_BOOT : GMU_COLD_BOOT ;
785
859
860
+ /*
861
+ * Warm boot path does not work on newer GPUs
862
+ * Presumably this is because icache/dcache regions must be restored
863
+ */
864
+ if (!gmu -> legacy )
865
+ status = GMU_COLD_BOOT ;
866
+
786
867
ret = a6xx_gmu_fw_start (gmu , status );
787
868
if (ret )
788
869
goto out ;
@@ -965,6 +1046,9 @@ static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu)
965
1046
{
966
1047
msm_gem_kernel_put (gmu -> hfi .obj , gmu -> aspace , false);
967
1048
msm_gem_kernel_put (gmu -> debug .obj , gmu -> aspace , false);
1049
+ msm_gem_kernel_put (gmu -> icache .obj , gmu -> aspace , false);
1050
+ msm_gem_kernel_put (gmu -> dcache .obj , gmu -> aspace , false);
1051
+ msm_gem_kernel_put (gmu -> dummy .obj , gmu -> aspace , false);
968
1052
969
1053
gmu -> aspace -> mmu -> funcs -> detach (gmu -> aspace -> mmu );
970
1054
msm_gem_address_space_put (gmu -> aspace );
@@ -982,12 +1066,14 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo,
982
1066
size = PAGE_ALIGN (size );
983
1067
if (!iova ) {
984
1068
/* no fixed address - use GMU's uncached range */
985
- range_start = 0x60000000 ;
1069
+ range_start = 0x60000000 + PAGE_SIZE ; /* skip dummy page */
986
1070
range_end = 0x80000000 ;
987
1071
} else {
988
1072
/* range for fixed address */
989
1073
range_start = iova ;
990
1074
range_end = iova + size ;
1075
+ /* use IOMMU_PRIV for icache/dcache */
1076
+ flags |= MSM_BO_MAP_PRIV ;
991
1077
}
992
1078
993
1079
bo -> obj = msm_gem_new (dev , size , flags );
@@ -1328,7 +1414,27 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
1328
1414
if (ret )
1329
1415
goto err_put_device ;
1330
1416
1331
- if (!adreno_is_a640 (adreno_gpu ) && !adreno_is_a650 (adreno_gpu )) {
1417
+ /* Allocate memory for the GMU dummy page */
1418
+ ret = a6xx_gmu_memory_alloc (gmu , & gmu -> dummy , SZ_4K , 0x60000000 );
1419
+ if (ret )
1420
+ goto err_memory ;
1421
+
1422
+ if (adreno_is_a650 (adreno_gpu )) {
1423
+ ret = a6xx_gmu_memory_alloc (gmu , & gmu -> icache ,
1424
+ SZ_16M - SZ_16K , 0x04000 );
1425
+ if (ret )
1426
+ goto err_memory ;
1427
+ } else if (adreno_is_a640 (adreno_gpu )) {
1428
+ ret = a6xx_gmu_memory_alloc (gmu , & gmu -> icache ,
1429
+ SZ_256K - SZ_16K , 0x04000 );
1430
+ if (ret )
1431
+ goto err_memory ;
1432
+
1433
+ ret = a6xx_gmu_memory_alloc (gmu , & gmu -> dcache ,
1434
+ SZ_256K - SZ_16K , 0x44000 );
1435
+ if (ret )
1436
+ goto err_memory ;
1437
+ } else {
1332
1438
/* HFI v1, has sptprac */
1333
1439
gmu -> legacy = true;
1334
1440
0 commit comments