This source file includes following definitions.
- tonga_ih_enable_interrupts
- tonga_ih_disable_interrupts
- tonga_ih_irq_init
- tonga_ih_irq_disable
- tonga_ih_get_wptr
- tonga_ih_decode_iv
- tonga_ih_set_rptr
- tonga_ih_early_init
- tonga_ih_sw_init
- tonga_ih_sw_fini
- tonga_ih_hw_init
- tonga_ih_hw_fini
- tonga_ih_suspend
- tonga_ih_resume
- tonga_ih_is_idle
- tonga_ih_wait_for_idle
- tonga_ih_check_soft_reset
- tonga_ih_pre_soft_reset
- tonga_ih_post_soft_reset
- tonga_ih_soft_reset
- tonga_ih_set_clockgating_state
- tonga_ih_set_powergating_state
- tonga_ih_set_interrupt_funcs
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 #include <linux/pci.h>
  25 
  26 #include "amdgpu.h"
  27 #include "amdgpu_ih.h"
  28 #include "vid.h"
  29 
  30 #include "oss/oss_3_0_d.h"
  31 #include "oss/oss_3_0_sh_mask.h"
  32 
  33 #include "bif/bif_5_1_d.h"
  34 #include "bif/bif_5_1_sh_mask.h"
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 static void tonga_ih_set_interrupt_funcs(struct amdgpu_device *adev);
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 static void tonga_ih_enable_interrupts(struct amdgpu_device *adev)
  61 {
  62         u32 ih_rb_cntl = RREG32(mmIH_RB_CNTL);
  63 
  64         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 1);
  65         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
  66         WREG32(mmIH_RB_CNTL, ih_rb_cntl);
  67         adev->irq.ih.enabled = true;
  68 }
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 static void tonga_ih_disable_interrupts(struct amdgpu_device *adev)
  78 {
  79         u32 ih_rb_cntl = RREG32(mmIH_RB_CNTL);
  80 
  81         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 0);
  82         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 0);
  83         WREG32(mmIH_RB_CNTL, ih_rb_cntl);
  84         
  85         WREG32(mmIH_RB_RPTR, 0);
  86         WREG32(mmIH_RB_WPTR, 0);
  87         adev->irq.ih.enabled = false;
  88         adev->irq.ih.rptr = 0;
  89 }
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 static int tonga_ih_irq_init(struct amdgpu_device *adev)
 103 {
 104         u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr;
 105         struct amdgpu_ih_ring *ih = &adev->irq.ih;
 106         int rb_bufsz;
 107 
 108         
 109         tonga_ih_disable_interrupts(adev);
 110 
 111         
 112         WREG32(mmINTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
 113         interrupt_cntl = RREG32(mmINTERRUPT_CNTL);
 114         
 115 
 116 
 117         interrupt_cntl = REG_SET_FIELD(interrupt_cntl, INTERRUPT_CNTL, IH_DUMMY_RD_OVERRIDE, 0);
 118         
 119         interrupt_cntl = REG_SET_FIELD(interrupt_cntl, INTERRUPT_CNTL, IH_REQ_NONSNOOP_EN, 0);
 120         WREG32(mmINTERRUPT_CNTL, interrupt_cntl);
 121 
 122         
 123         WREG32(mmIH_RB_BASE, ih->gpu_addr >> 8);
 124 
 125         rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
 126         ih_rb_cntl = REG_SET_FIELD(0, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
 127         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
 128         
 129         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
 130         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
 131 
 132         if (adev->irq.msi_enabled)
 133                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
 134 
 135         WREG32(mmIH_RB_CNTL, ih_rb_cntl);
 136 
 137         
 138         WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
 139         WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
 140 
 141         
 142         WREG32(mmIH_RB_RPTR, 0);
 143         WREG32(mmIH_RB_WPTR, 0);
 144 
 145         ih_doorbell_rtpr = RREG32(mmIH_DOORBELL_RPTR);
 146         if (adev->irq.ih.use_doorbell) {
 147                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
 148                                                  OFFSET, adev->irq.ih.doorbell_index);
 149                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
 150                                                  ENABLE, 1);
 151         } else {
 152                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
 153                                                  ENABLE, 0);
 154         }
 155         WREG32(mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
 156 
 157         pci_set_master(adev->pdev);
 158 
 159         
 160         tonga_ih_enable_interrupts(adev);
 161 
 162         return 0;
 163 }
 164 
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 static void tonga_ih_irq_disable(struct amdgpu_device *adev)
 173 {
 174         tonga_ih_disable_interrupts(adev);
 175 
 176         
 177         mdelay(1);
 178 }
 179 
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 
 191 static u32 tonga_ih_get_wptr(struct amdgpu_device *adev,
 192                              struct amdgpu_ih_ring *ih)
 193 {
 194         u32 wptr, tmp;
 195 
 196         wptr = le32_to_cpu(*ih->wptr_cpu);
 197 
 198         if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
 199                 wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
 200                 
 201 
 202 
 203 
 204                 dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
 205                          wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
 206                 ih->rptr = (wptr + 16) & ih->ptr_mask;
 207                 tmp = RREG32(mmIH_RB_CNTL);
 208                 tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
 209                 WREG32(mmIH_RB_CNTL, tmp);
 210         }
 211         return (wptr & ih->ptr_mask);
 212 }
 213 
 214 
 215 
 216 
 217 
 218 
 219 
 220 
 221 
 222 static void tonga_ih_decode_iv(struct amdgpu_device *adev,
 223                                struct amdgpu_ih_ring *ih,
 224                                struct amdgpu_iv_entry *entry)
 225 {
 226         
 227         u32 ring_index = ih->rptr >> 2;
 228         uint32_t dw[4];
 229 
 230         dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
 231         dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
 232         dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
 233         dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 234 
 235         entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
 236         entry->src_id = dw[0] & 0xff;
 237         entry->src_data[0] = dw[1] & 0xfffffff;
 238         entry->ring_id = dw[2] & 0xff;
 239         entry->vmid = (dw[2] >> 8) & 0xff;
 240         entry->pasid = (dw[2] >> 16) & 0xffff;
 241 
 242         
 243         ih->rptr += 16;
 244 }
 245 
 246 
 247 
 248 
 249 
 250 
 251 
 252 
 253 static void tonga_ih_set_rptr(struct amdgpu_device *adev,
 254                               struct amdgpu_ih_ring *ih)
 255 {
 256         if (ih->use_doorbell) {
 257                 
 258                 *ih->rptr_cpu = ih->rptr;
 259                 WDOORBELL32(ih->doorbell_index, ih->rptr);
 260         } else {
 261                 WREG32(mmIH_RB_RPTR, ih->rptr);
 262         }
 263 }
 264 
 265 static int tonga_ih_early_init(void *handle)
 266 {
 267         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 268         int ret;
 269 
 270         ret = amdgpu_irq_add_domain(adev);
 271         if (ret)
 272                 return ret;
 273 
 274         tonga_ih_set_interrupt_funcs(adev);
 275 
 276         return 0;
 277 }
 278 
 279 static int tonga_ih_sw_init(void *handle)
 280 {
 281         int r;
 282         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 283 
 284         r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, true);
 285         if (r)
 286                 return r;
 287 
 288         adev->irq.ih.use_doorbell = true;
 289         adev->irq.ih.doorbell_index = adev->doorbell_index.ih;
 290 
 291         r = amdgpu_irq_init(adev);
 292 
 293         return r;
 294 }
 295 
 296 static int tonga_ih_sw_fini(void *handle)
 297 {
 298         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 299 
 300         amdgpu_irq_fini(adev);
 301         amdgpu_ih_ring_fini(adev, &adev->irq.ih);
 302         amdgpu_irq_remove_domain(adev);
 303 
 304         return 0;
 305 }
 306 
 307 static int tonga_ih_hw_init(void *handle)
 308 {
 309         int r;
 310         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 311 
 312         r = tonga_ih_irq_init(adev);
 313         if (r)
 314                 return r;
 315 
 316         return 0;
 317 }
 318 
 319 static int tonga_ih_hw_fini(void *handle)
 320 {
 321         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 322 
 323         tonga_ih_irq_disable(adev);
 324 
 325         return 0;
 326 }
 327 
 328 static int tonga_ih_suspend(void *handle)
 329 {
 330         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 331 
 332         return tonga_ih_hw_fini(adev);
 333 }
 334 
 335 static int tonga_ih_resume(void *handle)
 336 {
 337         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 338 
 339         return tonga_ih_hw_init(adev);
 340 }
 341 
 342 static bool tonga_ih_is_idle(void *handle)
 343 {
 344         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 345         u32 tmp = RREG32(mmSRBM_STATUS);
 346 
 347         if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY))
 348                 return false;
 349 
 350         return true;
 351 }
 352 
 353 static int tonga_ih_wait_for_idle(void *handle)
 354 {
 355         unsigned i;
 356         u32 tmp;
 357         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 358 
 359         for (i = 0; i < adev->usec_timeout; i++) {
 360                 
 361                 tmp = RREG32(mmSRBM_STATUS);
 362                 if (!REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY))
 363                         return 0;
 364                 udelay(1);
 365         }
 366         return -ETIMEDOUT;
 367 }
 368 
 369 static bool tonga_ih_check_soft_reset(void *handle)
 370 {
 371         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 372         u32 srbm_soft_reset = 0;
 373         u32 tmp = RREG32(mmSRBM_STATUS);
 374 
 375         if (tmp & SRBM_STATUS__IH_BUSY_MASK)
 376                 srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET,
 377                                                 SOFT_RESET_IH, 1);
 378 
 379         if (srbm_soft_reset) {
 380                 adev->irq.srbm_soft_reset = srbm_soft_reset;
 381                 return true;
 382         } else {
 383                 adev->irq.srbm_soft_reset = 0;
 384                 return false;
 385         }
 386 }
 387 
 388 static int tonga_ih_pre_soft_reset(void *handle)
 389 {
 390         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 391 
 392         if (!adev->irq.srbm_soft_reset)
 393                 return 0;
 394 
 395         return tonga_ih_hw_fini(adev);
 396 }
 397 
 398 static int tonga_ih_post_soft_reset(void *handle)
 399 {
 400         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 401 
 402         if (!adev->irq.srbm_soft_reset)
 403                 return 0;
 404 
 405         return tonga_ih_hw_init(adev);
 406 }
 407 
 408 static int tonga_ih_soft_reset(void *handle)
 409 {
 410         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 411         u32 srbm_soft_reset;
 412 
 413         if (!adev->irq.srbm_soft_reset)
 414                 return 0;
 415         srbm_soft_reset = adev->irq.srbm_soft_reset;
 416 
 417         if (srbm_soft_reset) {
 418                 u32 tmp;
 419 
 420                 tmp = RREG32(mmSRBM_SOFT_RESET);
 421                 tmp |= srbm_soft_reset;
 422                 dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
 423                 WREG32(mmSRBM_SOFT_RESET, tmp);
 424                 tmp = RREG32(mmSRBM_SOFT_RESET);
 425 
 426                 udelay(50);
 427 
 428                 tmp &= ~srbm_soft_reset;
 429                 WREG32(mmSRBM_SOFT_RESET, tmp);
 430                 tmp = RREG32(mmSRBM_SOFT_RESET);
 431 
 432                 
 433                 udelay(50);
 434         }
 435 
 436         return 0;
 437 }
 438 
 439 static int tonga_ih_set_clockgating_state(void *handle,
 440                                           enum amd_clockgating_state state)
 441 {
 442         return 0;
 443 }
 444 
 445 static int tonga_ih_set_powergating_state(void *handle,
 446                                           enum amd_powergating_state state)
 447 {
 448         return 0;
 449 }
 450 
 451 static const struct amd_ip_funcs tonga_ih_ip_funcs = {
 452         .name = "tonga_ih",
 453         .early_init = tonga_ih_early_init,
 454         .late_init = NULL,
 455         .sw_init = tonga_ih_sw_init,
 456         .sw_fini = tonga_ih_sw_fini,
 457         .hw_init = tonga_ih_hw_init,
 458         .hw_fini = tonga_ih_hw_fini,
 459         .suspend = tonga_ih_suspend,
 460         .resume = tonga_ih_resume,
 461         .is_idle = tonga_ih_is_idle,
 462         .wait_for_idle = tonga_ih_wait_for_idle,
 463         .check_soft_reset = tonga_ih_check_soft_reset,
 464         .pre_soft_reset = tonga_ih_pre_soft_reset,
 465         .soft_reset = tonga_ih_soft_reset,
 466         .post_soft_reset = tonga_ih_post_soft_reset,
 467         .set_clockgating_state = tonga_ih_set_clockgating_state,
 468         .set_powergating_state = tonga_ih_set_powergating_state,
 469 };
 470 
 471 static const struct amdgpu_ih_funcs tonga_ih_funcs = {
 472         .get_wptr = tonga_ih_get_wptr,
 473         .decode_iv = tonga_ih_decode_iv,
 474         .set_rptr = tonga_ih_set_rptr
 475 };
 476 
 477 static void tonga_ih_set_interrupt_funcs(struct amdgpu_device *adev)
 478 {
 479         adev->irq.ih_funcs = &tonga_ih_funcs;
 480 }
 481 
 482 const struct amdgpu_ip_block_version tonga_ih_ip_block =
 483 {
 484         .type = AMD_IP_BLOCK_TYPE_IH,
 485         .major = 3,
 486         .minor = 0,
 487         .rev = 0,
 488         .funcs = &tonga_ih_ip_funcs,
 489 };