1 /* $NetBSD: amdgpu_si_ih.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $ */ 2 3 /* 4 * Copyright 2015 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_si_ih.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $"); 28 29 #include <linux/pci.h> 30 31 #include "amdgpu.h" 32 #include "amdgpu_ih.h" 33 #include "sid.h" 34 #include "si_ih.h" 35 36 static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev); 37 38 static void si_ih_enable_interrupts(struct amdgpu_device *adev) 39 { 40 u32 ih_cntl = RREG32(IH_CNTL); 41 u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 42 43 ih_cntl |= ENABLE_INTR; 44 ih_rb_cntl |= IH_RB_ENABLE; 45 WREG32(IH_CNTL, ih_cntl); 46 WREG32(IH_RB_CNTL, ih_rb_cntl); 47 adev->irq.ih.enabled = true; 48 } 49 50 static void si_ih_disable_interrupts(struct amdgpu_device *adev) 51 { 52 u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 53 u32 ih_cntl = RREG32(IH_CNTL); 54 55 ih_rb_cntl &= ~IH_RB_ENABLE; 56 ih_cntl &= ~ENABLE_INTR; 57 WREG32(IH_RB_CNTL, ih_rb_cntl); 58 WREG32(IH_CNTL, ih_cntl); 59 WREG32(IH_RB_RPTR, 0); 60 WREG32(IH_RB_WPTR, 0); 61 adev->irq.ih.enabled = false; 62 adev->irq.ih.rptr = 0; 63 } 64 65 static int si_ih_irq_init(struct amdgpu_device *adev) 66 { 67 struct amdgpu_ih_ring *ih = &adev->irq.ih; 68 int rb_bufsz; 69 u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 70 71 si_ih_disable_interrupts(adev); 72 /* set dummy read address to dummy page address */ 73 WREG32(INTERRUPT_CNTL2, adev->dummy_page_addr >> 8); 74 interrupt_cntl = RREG32(INTERRUPT_CNTL); 75 interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; 76 interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; 77 WREG32(INTERRUPT_CNTL, interrupt_cntl); 78 79 WREG32(IH_RB_BASE, adev->irq.ih.gpu_addr >> 8); 80 rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); 81 82 ih_rb_cntl = IH_WPTR_OVERFLOW_ENABLE | 83 IH_WPTR_OVERFLOW_CLEAR | 84 (rb_bufsz << 1) | 85 IH_WPTR_WRITEBACK_ENABLE; 86 87 WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 88 WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 89 WREG32(IH_RB_CNTL, ih_rb_cntl); 90 WREG32(IH_RB_RPTR, 0); 91 WREG32(IH_RB_WPTR, 0); 92 93 ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0); 94 if (adev->irq.msi_enabled) 95 ih_cntl |= RPTR_REARM; 96 WREG32(IH_CNTL, ih_cntl); 97 98 pci_set_master(adev->pdev); 99 si_ih_enable_interrupts(adev); 100 101 return 0; 102 } 103 104 static void si_ih_irq_disable(struct amdgpu_device *adev) 105 { 106 si_ih_disable_interrupts(adev); 107 mdelay(1); 108 } 109 110 static u32 si_ih_get_wptr(struct amdgpu_device *adev, 111 struct amdgpu_ih_ring *ih) 112 { 113 u32 wptr, tmp; 114 115 wptr = le32_to_cpu(*ih->wptr_cpu); 116 117 if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { 118 wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; 119 dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", 120 wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); 121 ih->rptr = (wptr + 16) & ih->ptr_mask; 122 tmp = RREG32(IH_RB_CNTL); 123 tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; 124 WREG32(IH_RB_CNTL, tmp); 125 } 126 return (wptr & ih->ptr_mask); 127 } 128 129 static void si_ih_decode_iv(struct amdgpu_device *adev, 130 struct amdgpu_ih_ring *ih, 131 struct amdgpu_iv_entry *entry) 132 { 133 u32 ring_index = ih->rptr >> 2; 134 uint32_t dw[4]; 135 136 dw[0] = le32_to_cpu(ih->ring[ring_index + 0]); 137 dw[1] = le32_to_cpu(ih->ring[ring_index + 1]); 138 dw[2] = le32_to_cpu(ih->ring[ring_index + 2]); 139 dw[3] = le32_to_cpu(ih->ring[ring_index + 3]); 140 141 entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; 142 entry->src_id = dw[0] & 0xff; 143 entry->src_data[0] = dw[1] & 0xfffffff; 144 entry->ring_id = dw[2] & 0xff; 145 entry->vmid = (dw[2] >> 8) & 0xff; 146 147 ih->rptr += 16; 148 } 149 150 static void si_ih_set_rptr(struct amdgpu_device *adev, 151 struct amdgpu_ih_ring *ih) 152 { 153 WREG32(IH_RB_RPTR, ih->rptr); 154 } 155 156 static int si_ih_early_init(void *handle) 157 { 158 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 159 160 si_ih_set_interrupt_funcs(adev); 161 162 return 0; 163 } 164 165 static int si_ih_sw_init(void *handle) 166 { 167 int r; 168 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 169 170 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, false); 171 if (r) 172 return r; 173 174 return amdgpu_irq_init(adev); 175 } 176 177 static int si_ih_sw_fini(void *handle) 178 { 179 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 180 181 amdgpu_irq_fini(adev); 182 amdgpu_ih_ring_fini(adev, &adev->irq.ih); 183 184 return 0; 185 } 186 187 static int si_ih_hw_init(void *handle) 188 { 189 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 190 191 return si_ih_irq_init(adev); 192 } 193 194 static int si_ih_hw_fini(void *handle) 195 { 196 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 197 198 si_ih_irq_disable(adev); 199 200 return 0; 201 } 202 203 static int si_ih_suspend(void *handle) 204 { 205 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 206 207 return si_ih_hw_fini(adev); 208 } 209 210 static int si_ih_resume(void *handle) 211 { 212 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 213 214 return si_ih_hw_init(adev); 215 } 216 217 static bool si_ih_is_idle(void *handle) 218 { 219 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 220 u32 tmp = RREG32(SRBM_STATUS); 221 222 if (tmp & SRBM_STATUS__IH_BUSY_MASK) 223 return false; 224 225 return true; 226 } 227 228 static int si_ih_wait_for_idle(void *handle) 229 { 230 unsigned i; 231 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 232 233 for (i = 0; i < adev->usec_timeout; i++) { 234 if (si_ih_is_idle(handle)) 235 return 0; 236 udelay(1); 237 } 238 return -ETIMEDOUT; 239 } 240 241 static int si_ih_soft_reset(void *handle) 242 { 243 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 244 245 u32 srbm_soft_reset = 0; 246 u32 tmp = RREG32(SRBM_STATUS); 247 248 if (tmp & SRBM_STATUS__IH_BUSY_MASK) 249 srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_IH_MASK; 250 251 if (srbm_soft_reset) { 252 tmp = RREG32(SRBM_SOFT_RESET); 253 tmp |= srbm_soft_reset; 254 dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); 255 WREG32(SRBM_SOFT_RESET, tmp); 256 tmp = RREG32(SRBM_SOFT_RESET); 257 258 udelay(50); 259 260 tmp &= ~srbm_soft_reset; 261 WREG32(SRBM_SOFT_RESET, tmp); 262 tmp = RREG32(SRBM_SOFT_RESET); 263 264 udelay(50); 265 } 266 267 return 0; 268 } 269 270 static int si_ih_set_clockgating_state(void *handle, 271 enum amd_clockgating_state state) 272 { 273 return 0; 274 } 275 276 static int si_ih_set_powergating_state(void *handle, 277 enum amd_powergating_state state) 278 { 279 return 0; 280 } 281 282 static const struct amd_ip_funcs si_ih_ip_funcs = { 283 .name = "si_ih", 284 .early_init = si_ih_early_init, 285 .late_init = NULL, 286 .sw_init = si_ih_sw_init, 287 .sw_fini = si_ih_sw_fini, 288 .hw_init = si_ih_hw_init, 289 .hw_fini = si_ih_hw_fini, 290 .suspend = si_ih_suspend, 291 .resume = si_ih_resume, 292 .is_idle = si_ih_is_idle, 293 .wait_for_idle = si_ih_wait_for_idle, 294 .soft_reset = si_ih_soft_reset, 295 .set_clockgating_state = si_ih_set_clockgating_state, 296 .set_powergating_state = si_ih_set_powergating_state, 297 }; 298 299 static const struct amdgpu_ih_funcs si_ih_funcs = { 300 .get_wptr = si_ih_get_wptr, 301 .decode_iv = si_ih_decode_iv, 302 .set_rptr = si_ih_set_rptr 303 }; 304 305 static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev) 306 { 307 adev->irq.ih_funcs = &si_ih_funcs; 308 } 309 310 const struct amdgpu_ip_block_version si_ih_ip_block = 311 { 312 .type = AMD_IP_BLOCK_TYPE_IH, 313 .major = 1, 314 .minor = 0, 315 .rev = 0, 316 .funcs = &si_ih_ip_funcs, 317 }; 318