1 /* 2 * Copyright 2025 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 #include "nbio/nbio_6_3_2_offset.h" 24 #include "nbio/nbio_6_3_2_sh_mask.h" 25 26 #include "amdgpu.h" 27 #include "nbio_v6_3_2.h" 28 29 static u32 nbio_v6_3_2_get_pcie_index_offset(struct amdgpu_device *adev) 30 { 31 return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_INDEX2); 32 } 33 34 static u32 nbio_v6_3_2_get_pcie_data_offset(struct amdgpu_device *adev) 35 { 36 return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_DATA2); 37 } 38 39 static u32 nbio_v6_3_2_get_pcie_index_hi_offset(struct amdgpu_device *adev) 40 { 41 return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_INDEX2_HI); 42 } 43 44 static u32 nbio_v6_3_2_get_rev_id(struct amdgpu_device *adev) 45 { 46 u32 tmp; 47 48 /* TODO: RCC_STRAP0_RCC_DEV0_EPF0_STRAP0 is not accessible from 49 * guest side. It requires bootloader to update specific fields 50 * in ip discovery table to identify soc revision id. 51 * Return 0 when the function is called from guest side until 52 * bootloader change is available. 53 */ 54 if (amdgpu_sriov_vf(adev)) 55 return 0; 56 57 tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0); 58 tmp = REG_GET_FIELD(tmp, RCC_STRAP0_RCC_DEV0_EPF0_STRAP0, 59 STRAP_ATI_REV_ID_DEV0_F0); 60 61 return tmp; 62 } 63 64 static void nbio_v6_3_2_mc_access_enable(struct amdgpu_device *adev, 65 bool enable) 66 { 67 if (enable) 68 WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 69 BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK | BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK); 70 else 71 WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0); 72 } 73 74 static void nbio_v6_3_2_init_registers(struct amdgpu_device *adev) 75 { 76 WREG32_SOC15(NBIO, 0, regXCD_DOORBELL_FENCE_1, 77 (0xff & ~(adev->gfx.xcc_mask)) << 78 XCD_DOORBELL_FENCE_1__XCD_0_DOORBELL_DISABLE__SHIFT); 79 } 80 81 static u32 nbio_v6_3_2_get_memsize(struct amdgpu_device *adev) 82 { 83 return RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF0_RCC_CONFIG_MEMSIZE); 84 } 85 86 static void nbio_v6_3_2_enable_doorbell_aperture(struct amdgpu_device *adev, 87 bool enable) 88 { 89 /* Enable to allow doorbell pass thru on pre-silicon bare-metal */ 90 WREG32_SOC15(NBIO, 0, regGDC0_DOORBELL_ACCESS_EN_PF, 0xfffff); 91 WREG32_FIELD15_PREREG(NBIO, 0, RCC_DEV0_EPF0_RCC_DOORBELL_APER_EN, 92 BIF_DOORBELL_APER_EN, enable ? 1 : 0); 93 } 94 95 static void nbio_v6_3_2_enable_doorbell_selfring_aperture(struct amdgpu_device *adev, 96 bool enable) 97 { 98 u32 tmp = 0; 99 100 if (enable) { 101 tmp = REG_SET_FIELD(tmp, BIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL, 102 DOORBELL_SELFRING_GPA_APER_EN, 1) | 103 REG_SET_FIELD(tmp, BIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL, 104 DOORBELL_SELFRING_GPA_APER_MODE, 1) | 105 REG_SET_FIELD(tmp, BIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL, 106 DOORBELL_SELFRING_GPA_APER_SIZE, 0); 107 108 WREG32_SOC15(NBIO, 0, regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW, 109 lower_32_bits(adev->doorbell.base)); 110 WREG32_SOC15(NBIO, 0, regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH, 111 upper_32_bits(adev->doorbell.base)); 112 } 113 114 WREG32_SOC15(NBIO, 0, regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL, tmp); 115 } 116 117 static void nbio_v6_3_2_enable_doorbell_interrupt(struct amdgpu_device *adev, 118 bool enable) 119 { 120 WREG32_FIELD15_PREREG(NBIO, 0, BIF_BX0_BIF_DOORBELL_INT_CNTL, 121 DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); 122 } 123 124 static void nbio_v6_3_2_ih_control(struct amdgpu_device *adev) 125 { 126 u32 interrupt_cntl; 127 128 /* setup interrupt control */ 129 WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2, adev->dummy_page_addr >> 8); 130 131 interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL); 132 /* 133 * BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi 134 * BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN 135 */ 136 interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX0_INTERRUPT_CNTL, 137 IH_DUMMY_RD_OVERRIDE, 0); 138 139 /* BIF_BX0_INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK=1 if ring is in non-cacheable memory, e.g., vram */ 140 interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX0_INTERRUPT_CNTL, 141 IH_REQ_NONSNOOP_EN, 0); 142 143 WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL, interrupt_cntl); 144 } 145 146 static void nbio_v6_3_2_ih_doorbell_range(struct amdgpu_device *adev, 147 bool use_doorbell, int doorbell_index) 148 { 149 u32 ih_doorbell_range = 0; 150 u32 ih_doorbell_range1 = 0; 151 152 if (use_doorbell) { 153 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, 154 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, 155 S2A_DOORBELL_PORT1_ENABLE, 156 0x1); 157 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, 158 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, 159 S2A_DOORBELL_PORT1_AWID, 160 0x0); 161 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, 162 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, 163 S2A_DOORBELL_PORT1_RANGE_OFFSET, 164 doorbell_index); 165 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, 166 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, 167 S2A_DOORBELL_PORT1_RANGE_SIZE, 168 8); 169 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, 170 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, 171 S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE, 172 0x0); 173 ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1, 174 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1, 175 S2A_DOORBELL_PORT1_TARGET_PORT_TYPE, 176 0x3); 177 ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1, 178 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1, 179 S2A_DOORBELL_PORT1_TARGET_DIEID, 180 0x0); 181 ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1, 182 GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1, 183 S2A_DOORBELL_PORT1_TARGET_PORT_ID, 184 0x0); 185 } 186 187 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, ih_doorbell_range); 188 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1, ih_doorbell_range1); 189 } 190 191 static void nbio_v6_3_2_gc_doorbell_init(struct amdgpu_device *adev) 192 { 193 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL, 0x30000007); 194 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1, 0x3); 195 } 196 197 static void nbio_v6_3_2_sdma_doorbell_range(struct amdgpu_device *adev, 198 int instance, bool use_doorbell, 199 int doorbell_index, 200 int doorbell_size) 201 { 202 if (instance == 0) { 203 u32 doorbell_range = 0; 204 u32 doorbell_range1 = 0; 205 206 if (use_doorbell) { 207 doorbell_range = REG_SET_FIELD(doorbell_range, 208 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, 209 S2A_DOORBELL_PORT6_ENABLE, 210 0x1); 211 doorbell_range = REG_SET_FIELD(doorbell_range, 212 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, 213 S2A_DOORBELL_PORT6_AWID, 214 0xe); 215 doorbell_range = REG_SET_FIELD(doorbell_range, 216 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, 217 S2A_DOORBELL_PORT6_RANGE_OFFSET, 218 doorbell_index); 219 doorbell_range = REG_SET_FIELD(doorbell_range, 220 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, 221 S2A_DOORBELL_PORT6_RANGE_SIZE, 222 doorbell_size); 223 doorbell_range = REG_SET_FIELD(doorbell_range, 224 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, 225 S2A_DOORBELL_PORT6_AWADDR_31_28_VALUE, 226 0xe); 227 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 228 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1, 229 S2A_DOORBELL_PORT6_TARGET_PORT_TYPE, 230 0x3); 231 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 232 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1, 233 S2A_DOORBELL_PORT6_TARGET_DIEID, 234 0x0); 235 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 236 GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1, 237 S2A_DOORBELL_PORT6_TARGET_PORT_ID, 238 0x0); 239 } 240 241 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, doorbell_range); 242 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1, doorbell_range1); 243 } 244 } 245 246 static void nbio_v6_3_2_vcn_doorbell_range(struct amdgpu_device *adev, 247 bool use_doorbell, int doorbell_index, 248 int instance) 249 { 250 u32 doorbell_range = 0; 251 u32 doorbell_range1 = 0; 252 253 if (use_doorbell) { 254 doorbell_range = REG_SET_FIELD(doorbell_range, 255 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, 256 S2A_DOORBELL_PORT2_ENABLE, 257 0x1); 258 doorbell_range = REG_SET_FIELD(doorbell_range, 259 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, 260 S2A_DOORBELL_PORT2_AWID, 261 (instance % adev->vcn.num_inst_per_aid) ? 0x7 : 0x4); 262 doorbell_range = REG_SET_FIELD(doorbell_range, 263 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, 264 S2A_DOORBELL_PORT2_RANGE_OFFSET, 265 doorbell_index); 266 doorbell_range = REG_SET_FIELD(doorbell_range, 267 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, 268 S2A_DOORBELL_PORT2_RANGE_SIZE, 269 8); 270 doorbell_range = REG_SET_FIELD(doorbell_range, 271 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, 272 S2A_DOORBELL_PORT2_AWADDR_31_28_VALUE, 273 (instance % adev->vcn.num_inst_per_aid) ? 0x7 : 0x4); 274 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 275 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1, 276 S2A_DOORBELL_PORT2_TARGET_PORT_TYPE, 277 0x3); 278 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 279 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1, 280 S2A_DOORBELL_PORT2_TARGET_DIEID, 281 (instance / adev->vcn.num_inst_per_aid) ? 0x3 : 0x0); 282 doorbell_range1 = REG_SET_FIELD(doorbell_range1, 283 GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1, 284 S2A_DOORBELL_PORT2_TARGET_PORT_ID, 285 0x0); 286 } 287 288 switch (instance) { 289 case 0: 290 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, doorbell_range); 291 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1, doorbell_range1); 292 break; 293 case 1: 294 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL, doorbell_range); 295 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1, doorbell_range1); 296 break; 297 case 2: 298 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL, doorbell_range); 299 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1, doorbell_range1); 300 break; 301 case 3: 302 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL, doorbell_range); 303 WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1, doorbell_range1); 304 break; 305 default: 306 dev_err(adev->dev, 307 "amdgpu: invalid vcn instance set when program doorbell range\n"); 308 break; 309 } 310 } 311 312 static int nbio_v6_3_2_get_compute_partition_mode(struct amdgpu_device *adev) 313 { 314 u32 tmp, px; 315 316 tmp = RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_COMPUTE_STATUS); 317 px = REG_GET_FIELD(tmp, BIF_BX_PF0_PARTITION_COMPUTE_STATUS, 318 PARTITION_MODE); 319 320 return px; 321 } 322 323 static bool nbio_v6_3_2_is_nps_switch_requested(struct amdgpu_device *adev) 324 { 325 u32 tmp; 326 327 tmp = RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_MEM_STATUS); 328 tmp = REG_GET_FIELD(tmp, BIF_BX_PF0_PARTITION_MEM_STATUS, 329 CHANGE_STATUS); 330 331 /* 0x8 - NPS switch requested */ 332 return (tmp == 0x8); 333 } 334 static u32 nbio_v6_3_2_get_memory_partition_mode(struct amdgpu_device *adev, 335 u32 *supp_modes) 336 { 337 u32 tmp; 338 339 tmp = RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_MEM_STATUS); 340 tmp = REG_GET_FIELD(tmp, BIF_BX_PF0_PARTITION_MEM_STATUS, NPS_MODE); 341 342 if (supp_modes) { 343 *supp_modes = 344 RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_MEM_CAP); 345 } 346 347 return ffs(tmp); 348 } 349 350 const struct amdgpu_nbio_funcs nbio_v6_3_2_funcs = { 351 .get_pcie_index_offset = nbio_v6_3_2_get_pcie_index_offset, 352 .get_pcie_data_offset = nbio_v6_3_2_get_pcie_data_offset, 353 .get_pcie_index_hi_offset = nbio_v6_3_2_get_pcie_index_hi_offset, 354 .get_rev_id = nbio_v6_3_2_get_rev_id, 355 .mc_access_enable = nbio_v6_3_2_mc_access_enable, 356 .get_memsize = nbio_v6_3_2_get_memsize, 357 .enable_doorbell_aperture = nbio_v6_3_2_enable_doorbell_aperture, 358 .enable_doorbell_selfring_aperture = nbio_v6_3_2_enable_doorbell_selfring_aperture, 359 .enable_doorbell_interrupt = nbio_v6_3_2_enable_doorbell_interrupt, 360 .get_compute_partition_mode = nbio_v6_3_2_get_compute_partition_mode, 361 .get_memory_partition_mode = nbio_v6_3_2_get_memory_partition_mode, 362 .is_nps_switch_requested = nbio_v6_3_2_is_nps_switch_requested, 363 .ih_control = nbio_v6_3_2_ih_control, 364 .ih_doorbell_range = nbio_v6_3_2_ih_doorbell_range, 365 .gc_doorbell_init = nbio_v6_3_2_gc_doorbell_init, 366 .sdma_doorbell_range = nbio_v6_3_2_sdma_doorbell_range, 367 .vcn_doorbell_range = nbio_v6_3_2_vcn_doorbell_range, 368 .init_registers = nbio_v6_3_2_init_registers, 369 }; 370