1 // SPDX-License-Identifier: GPL-2.0 or MIT 2 /* Copyright 2025 ARM Limited. All rights reserved. */ 3 4 #include <drm/drm_print.h> 5 6 #include "panthor_device.h" 7 #include "panthor_gpu.h" 8 #include "panthor_hw.h" 9 #include "panthor_pwr.h" 10 #include "panthor_regs.h" 11 12 #define GPU_PROD_ID_MAKE(arch_major, prod_major) \ 13 (((arch_major) << 24) | (prod_major)) 14 15 /** struct panthor_hw_entry - HW arch major to panthor_hw binding entry */ 16 struct panthor_hw_entry { 17 /** @arch_min: Minimum supported architecture major value (inclusive) */ 18 u8 arch_min; 19 20 /** @arch_max: Maximum supported architecture major value (inclusive) */ 21 u8 arch_max; 22 23 /** @hwdev: Pointer to panthor_hw structure */ 24 struct panthor_hw *hwdev; 25 }; 26 27 static struct panthor_hw panthor_hw_arch_v10 = { 28 .ops = { 29 .soft_reset = panthor_gpu_soft_reset, 30 .l2_power_off = panthor_gpu_l2_power_off, 31 .l2_power_on = panthor_gpu_l2_power_on, 32 }, 33 }; 34 35 static struct panthor_hw panthor_hw_arch_v14 = { 36 .ops = { 37 .soft_reset = panthor_pwr_reset_soft, 38 .l2_power_off = panthor_pwr_l2_power_off, 39 .l2_power_on = panthor_pwr_l2_power_on, 40 }, 41 }; 42 43 static struct panthor_hw_entry panthor_hw_match[] = { 44 { 45 .arch_min = 10, 46 .arch_max = 13, 47 .hwdev = &panthor_hw_arch_v10, 48 }, 49 { 50 .arch_min = 14, 51 .arch_max = 14, 52 .hwdev = &panthor_hw_arch_v14, 53 }, 54 }; 55 56 static char *get_gpu_model_name(struct panthor_device *ptdev) 57 { 58 const u32 gpu_id = ptdev->gpu_info.gpu_id; 59 const u32 product_id = GPU_PROD_ID_MAKE(GPU_ARCH_MAJOR(gpu_id), 60 GPU_PROD_MAJOR(gpu_id)); 61 const bool ray_intersection = !!(ptdev->gpu_info.gpu_features & 62 GPU_FEATURES_RAY_INTERSECTION); 63 const u8 shader_core_count = hweight64(ptdev->gpu_info.shader_present); 64 65 switch (product_id) { 66 case GPU_PROD_ID_MAKE(10, 2): 67 return "Mali-G710"; 68 case GPU_PROD_ID_MAKE(10, 3): 69 return "Mali-G510"; 70 case GPU_PROD_ID_MAKE(10, 4): 71 return "Mali-G310"; 72 case GPU_PROD_ID_MAKE(10, 7): 73 return "Mali-G610"; 74 case GPU_PROD_ID_MAKE(11, 2): 75 if (shader_core_count > 10 && ray_intersection) 76 return "Mali-G715-Immortalis"; 77 else if (shader_core_count >= 7) 78 return "Mali-G715"; 79 80 fallthrough; 81 case GPU_PROD_ID_MAKE(11, 3): 82 return "Mali-G615"; 83 case GPU_PROD_ID_MAKE(12, 0): 84 if (shader_core_count >= 10 && ray_intersection) 85 return "Mali-G720-Immortalis"; 86 else if (shader_core_count >= 6) 87 return "Mali-G720"; 88 89 fallthrough; 90 case GPU_PROD_ID_MAKE(12, 1): 91 return "Mali-G620"; 92 case GPU_PROD_ID_MAKE(13, 0): 93 if (shader_core_count >= 10 && ray_intersection) 94 return "Mali-G925-Immortalis"; 95 else if (shader_core_count >= 6) 96 return "Mali-G725"; 97 98 fallthrough; 99 case GPU_PROD_ID_MAKE(13, 1): 100 return "Mali-G625"; 101 case GPU_PROD_ID_MAKE(14, 0): 102 return "Mali-G1-Ultra"; 103 case GPU_PROD_ID_MAKE(14, 1): 104 return "Mali-G1-Premium"; 105 case GPU_PROD_ID_MAKE(14, 3): 106 return "Mali-G1-Pro"; 107 } 108 109 return "(Unknown Mali GPU)"; 110 } 111 112 static void panthor_gpu_info_init(struct panthor_device *ptdev) 113 { 114 unsigned int i; 115 116 ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); 117 ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); 118 ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); 119 ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); 120 ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); 121 ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); 122 ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); 123 ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); 124 ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); 125 ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); 126 ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); 127 ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); 128 for (i = 0; i < 4; i++) 129 ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); 130 131 ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); 132 133 /* Introduced in arch 11.x */ 134 ptdev->gpu_info.gpu_features = gpu_read64(ptdev, GPU_FEATURES); 135 136 if (panthor_hw_has_pwr_ctrl(ptdev)) { 137 /* Introduced in arch 14.x */ 138 ptdev->gpu_info.l2_present = gpu_read64(ptdev, PWR_L2_PRESENT); 139 ptdev->gpu_info.tiler_present = gpu_read64(ptdev, PWR_TILER_PRESENT); 140 ptdev->gpu_info.shader_present = gpu_read64(ptdev, PWR_SHADER_PRESENT); 141 } else { 142 ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT); 143 ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT); 144 ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT); 145 } 146 } 147 148 static void panthor_hw_info_init(struct panthor_device *ptdev) 149 { 150 u32 major, minor, status; 151 152 panthor_gpu_info_init(ptdev); 153 154 major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); 155 minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); 156 status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); 157 158 drm_info(&ptdev->base, 159 "%s id 0x%x major 0x%x minor 0x%x status 0x%x", 160 get_gpu_model_name(ptdev), ptdev->gpu_info.gpu_id >> 16, 161 major, minor, status); 162 163 drm_info(&ptdev->base, 164 "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", 165 ptdev->gpu_info.l2_features, 166 ptdev->gpu_info.tiler_features, 167 ptdev->gpu_info.mem_features, 168 ptdev->gpu_info.mmu_features, 169 ptdev->gpu_info.as_present); 170 171 drm_info(&ptdev->base, 172 "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", 173 ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, 174 ptdev->gpu_info.tiler_present); 175 } 176 177 static int panthor_hw_bind_device(struct panthor_device *ptdev) 178 { 179 struct panthor_hw *hdev = NULL; 180 const u32 arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id); 181 int i = 0; 182 183 for (i = 0; i < ARRAY_SIZE(panthor_hw_match); i++) { 184 struct panthor_hw_entry *entry = &panthor_hw_match[i]; 185 186 if (arch_major >= entry->arch_min && arch_major <= entry->arch_max) { 187 hdev = entry->hwdev; 188 break; 189 } 190 } 191 192 if (!hdev) 193 return -EOPNOTSUPP; 194 195 ptdev->hw = hdev; 196 197 return 0; 198 } 199 200 static int panthor_hw_gpu_id_init(struct panthor_device *ptdev) 201 { 202 ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); 203 if (!ptdev->gpu_info.gpu_id) 204 return -ENXIO; 205 206 return 0; 207 } 208 209 int panthor_hw_init(struct panthor_device *ptdev) 210 { 211 int ret = 0; 212 213 ret = panthor_hw_gpu_id_init(ptdev); 214 if (ret) 215 return ret; 216 217 ret = panthor_hw_bind_device(ptdev); 218 if (ret) 219 return ret; 220 221 panthor_hw_info_init(ptdev); 222 223 return 0; 224 } 225