root/drivers/gpu/drm/amd/amdgpu/vega10_ih.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vega10_ih_enable_interrupts
  2. vega10_ih_disable_interrupts
  3. vega10_ih_rb_cntl
  4. vega10_ih_doorbell_rptr
  5. vega10_ih_irq_init
  6. vega10_ih_irq_disable
  7. vega10_ih_get_wptr
  8. vega10_ih_decode_iv
  9. vega10_ih_irq_rearm
  10. vega10_ih_set_rptr
  11. vega10_ih_self_irq
  12. vega10_ih_set_self_irq_funcs
  13. vega10_ih_early_init
  14. vega10_ih_sw_init
  15. vega10_ih_sw_fini
  16. vega10_ih_hw_init
  17. vega10_ih_hw_fini
  18. vega10_ih_suspend
  19. vega10_ih_resume
  20. vega10_ih_is_idle
  21. vega10_ih_wait_for_idle
  22. vega10_ih_soft_reset
  23. vega10_ih_set_clockgating_state
  24. vega10_ih_set_powergating_state
  25. vega10_ih_set_interrupt_funcs

   1 /*
   2  * Copyright 2016 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 
  24 #include <linux/pci.h>
  25 
  26 #include "amdgpu.h"
  27 #include "amdgpu_ih.h"
  28 #include "soc15.h"
  29 
  30 #include "oss/osssys_4_0_offset.h"
  31 #include "oss/osssys_4_0_sh_mask.h"
  32 
  33 #include "soc15_common.h"
  34 #include "vega10_ih.h"
  35 
  36 #define MAX_REARM_RETRY 10
  37 
  38 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
  39 
  40 /**
  41  * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
  42  *
  43  * @adev: amdgpu_device pointer
  44  *
  45  * Enable the interrupt ring buffer (VEGA10).
  46  */
  47 static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
  48 {
  49         u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
  50 
  51         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 1);
  52         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
  53         if (amdgpu_sriov_vf(adev)) {
  54                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
  55                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
  56                         return;
  57                 }
  58         } else {
  59                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
  60         }
  61         adev->irq.ih.enabled = true;
  62 
  63         if (adev->irq.ih1.ring_size) {
  64                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
  65                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
  66                                            RB_ENABLE, 1);
  67                 if (amdgpu_sriov_vf(adev)) {
  68                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
  69                                                 ih_rb_cntl)) {
  70                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
  71                                 return;
  72                         }
  73                 } else {
  74                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
  75                 }
  76                 adev->irq.ih1.enabled = true;
  77         }
  78 
  79         if (adev->irq.ih2.ring_size) {
  80                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
  81                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
  82                                            RB_ENABLE, 1);
  83                 if (amdgpu_sriov_vf(adev)) {
  84                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
  85                                                 ih_rb_cntl)) {
  86                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
  87                                 return;
  88                         }
  89                 } else {
  90                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
  91                 }
  92                 adev->irq.ih2.enabled = true;
  93         }
  94 }
  95 
  96 /**
  97  * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
  98  *
  99  * @adev: amdgpu_device pointer
 100  *
 101  * Disable the interrupt ring buffer (VEGA10).
 102  */
 103 static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
 104 {
 105         u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
 106 
 107         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 0);
 108         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 0);
 109         if (amdgpu_sriov_vf(adev)) {
 110                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
 111                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
 112                         return;
 113                 }
 114         } else {
 115                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 116         }
 117 
 118         /* set rptr, wptr to 0 */
 119         WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
 120         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
 121         adev->irq.ih.enabled = false;
 122         adev->irq.ih.rptr = 0;
 123 
 124         if (adev->irq.ih1.ring_size) {
 125                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
 126                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
 127                                            RB_ENABLE, 0);
 128                 if (amdgpu_sriov_vf(adev)) {
 129                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
 130                                                 ih_rb_cntl)) {
 131                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
 132                                 return;
 133                         }
 134                 } else {
 135                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
 136                 }
 137                 /* set rptr, wptr to 0 */
 138                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
 139                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
 140                 adev->irq.ih1.enabled = false;
 141                 adev->irq.ih1.rptr = 0;
 142         }
 143 
 144         if (adev->irq.ih2.ring_size) {
 145                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
 146                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
 147                                            RB_ENABLE, 0);
 148                 if (amdgpu_sriov_vf(adev)) {
 149                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
 150                                                 ih_rb_cntl)) {
 151                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
 152                                 return;
 153                         }
 154                 } else {
 155                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
 156                 }
 157 
 158                 /* set rptr, wptr to 0 */
 159                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
 160                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
 161                 adev->irq.ih2.enabled = false;
 162                 adev->irq.ih2.rptr = 0;
 163         }
 164 }
 165 
 166 static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
 167 {
 168         int rb_bufsz = order_base_2(ih->ring_size / 4);
 169 
 170         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 171                                    MC_SPACE, ih->use_bus_addr ? 1 : 4);
 172         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 173                                    WPTR_OVERFLOW_CLEAR, 1);
 174         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 175                                    WPTR_OVERFLOW_ENABLE, 1);
 176         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
 177         /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
 178          * value is written to memory
 179          */
 180         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 181                                    WPTR_WRITEBACK_ENABLE, 1);
 182         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
 183         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
 184         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
 185 
 186         return ih_rb_cntl;
 187 }
 188 
 189 static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
 190 {
 191         u32 ih_doorbell_rtpr = 0;
 192 
 193         if (ih->use_doorbell) {
 194                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
 195                                                  IH_DOORBELL_RPTR, OFFSET,
 196                                                  ih->doorbell_index);
 197                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
 198                                                  IH_DOORBELL_RPTR,
 199                                                  ENABLE, 1);
 200         } else {
 201                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
 202                                                  IH_DOORBELL_RPTR,
 203                                                  ENABLE, 0);
 204         }
 205         return ih_doorbell_rtpr;
 206 }
 207 
 208 /**
 209  * vega10_ih_irq_init - init and enable the interrupt ring
 210  *
 211  * @adev: amdgpu_device pointer
 212  *
 213  * Allocate a ring buffer for the interrupt controller,
 214  * enable the RLC, disable interrupts, enable the IH
 215  * ring buffer and enable it (VI).
 216  * Called at device load and reume.
 217  * Returns 0 for success, errors for failure.
 218  */
 219 static int vega10_ih_irq_init(struct amdgpu_device *adev)
 220 {
 221         struct amdgpu_ih_ring *ih;
 222         u32 ih_rb_cntl, ih_chicken;
 223         int ret = 0;
 224         u32 tmp;
 225 
 226         /* disable irqs */
 227         vega10_ih_disable_interrupts(adev);
 228 
 229         adev->nbio_funcs->ih_control(adev);
 230 
 231         ih = &adev->irq.ih;
 232         /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
 233         WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
 234         WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
 235 
 236         ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
 237         ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
 238         ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
 239         if (adev->irq.ih.use_bus_addr) {
 240                 ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN, MC_SPACE_GPA_ENABLE, 1);
 241         } else {
 242                 ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN, MC_SPACE_FBPA_ENABLE, 1);
 243         }
 244         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
 245                                    !!adev->irq.msi_enabled);
 246 
 247         if (amdgpu_sriov_vf(adev)) {
 248                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
 249                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
 250                         return -ETIMEDOUT;
 251                 }
 252         } else {
 253                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 254         }
 255 
 256         if ((adev->asic_type == CHIP_ARCTURUS
 257                 && adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)
 258                 || adev->asic_type == CHIP_RENOIR)
 259                 WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);
 260 
 261         /* set the writeback address whether it's enabled or not */
 262         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
 263                      lower_32_bits(ih->wptr_addr));
 264         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
 265                      upper_32_bits(ih->wptr_addr) & 0xFFFF);
 266 
 267         /* set rptr, wptr to 0 */
 268         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
 269         WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
 270 
 271         WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
 272                      vega10_ih_doorbell_rptr(ih));
 273 
 274         ih = &adev->irq.ih1;
 275         if (ih->ring_size) {
 276                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
 277                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
 278                              (ih->gpu_addr >> 40) & 0xff);
 279 
 280                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
 281                 ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
 282                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 283                                            WPTR_OVERFLOW_ENABLE, 0);
 284                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
 285                                            RB_FULL_DRAIN_ENABLE, 1);
 286                 if (amdgpu_sriov_vf(adev)) {
 287                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
 288                                                 ih_rb_cntl)) {
 289                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
 290                                 return -ETIMEDOUT;
 291                         }
 292                 } else {
 293                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
 294                 }
 295 
 296                 /* set rptr, wptr to 0 */
 297                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
 298                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
 299 
 300                 WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
 301                              vega10_ih_doorbell_rptr(ih));
 302         }
 303 
 304         ih = &adev->irq.ih2;
 305         if (ih->ring_size) {
 306                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
 307                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
 308                              (ih->gpu_addr >> 40) & 0xff);
 309 
 310                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
 311                 ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
 312 
 313                 if (amdgpu_sriov_vf(adev)) {
 314                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
 315                                                 ih_rb_cntl)) {
 316                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
 317                                 return -ETIMEDOUT;
 318                         }
 319                 } else {
 320                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
 321                 }
 322 
 323                 /* set rptr, wptr to 0 */
 324                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
 325                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
 326 
 327                 WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
 328                              vega10_ih_doorbell_rptr(ih));
 329         }
 330 
 331         tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
 332         tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
 333                             CLIENT18_IS_STORM_CLIENT, 1);
 334         WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp);
 335 
 336         tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL);
 337         tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1);
 338         WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp);
 339 
 340         pci_set_master(adev->pdev);
 341 
 342         /* enable interrupts */
 343         vega10_ih_enable_interrupts(adev);
 344 
 345         return ret;
 346 }
 347 
 348 /**
 349  * vega10_ih_irq_disable - disable interrupts
 350  *
 351  * @adev: amdgpu_device pointer
 352  *
 353  * Disable interrupts on the hw (VEGA10).
 354  */
 355 static void vega10_ih_irq_disable(struct amdgpu_device *adev)
 356 {
 357         vega10_ih_disable_interrupts(adev);
 358 
 359         /* Wait and acknowledge irq */
 360         mdelay(1);
 361 }
 362 
 363 /**
 364  * vega10_ih_get_wptr - get the IH ring buffer wptr
 365  *
 366  * @adev: amdgpu_device pointer
 367  *
 368  * Get the IH ring buffer wptr from either the register
 369  * or the writeback memory buffer (VEGA10).  Also check for
 370  * ring buffer overflow and deal with it.
 371  * Returns the value of the wptr.
 372  */
 373 static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
 374                               struct amdgpu_ih_ring *ih)
 375 {
 376         u32 wptr, reg, tmp;
 377 
 378         wptr = le32_to_cpu(*ih->wptr_cpu);
 379 
 380         if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
 381                 goto out;
 382 
 383         /* Double check that the overflow wasn't already cleared. */
 384 
 385         if (ih == &adev->irq.ih)
 386                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
 387         else if (ih == &adev->irq.ih1)
 388                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
 389         else if (ih == &adev->irq.ih2)
 390                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
 391         else
 392                 BUG();
 393 
 394         wptr = RREG32_NO_KIQ(reg);
 395         if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
 396                 goto out;
 397 
 398         wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
 399 
 400         /* When a ring buffer overflow happen start parsing interrupt
 401          * from the last not overwritten vector (wptr + 32). Hopefully
 402          * this should allow us to catchup.
 403          */
 404         tmp = (wptr + 32) & ih->ptr_mask;
 405         dev_warn(adev->dev, "IH ring buffer overflow "
 406                  "(0x%08X, 0x%08X, 0x%08X)\n",
 407                  wptr, ih->rptr, tmp);
 408         ih->rptr = tmp;
 409 
 410         if (ih == &adev->irq.ih)
 411                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
 412         else if (ih == &adev->irq.ih1)
 413                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
 414         else if (ih == &adev->irq.ih2)
 415                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
 416         else
 417                 BUG();
 418 
 419         tmp = RREG32_NO_KIQ(reg);
 420         tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
 421         WREG32_NO_KIQ(reg, tmp);
 422 
 423 out:
 424         return (wptr & ih->ptr_mask);
 425 }
 426 
 427 /**
 428  * vega10_ih_decode_iv - decode an interrupt vector
 429  *
 430  * @adev: amdgpu_device pointer
 431  *
 432  * Decodes the interrupt vector at the current rptr
 433  * position and also advance the position.
 434  */
 435 static void vega10_ih_decode_iv(struct amdgpu_device *adev,
 436                                 struct amdgpu_ih_ring *ih,
 437                                 struct amdgpu_iv_entry *entry)
 438 {
 439         /* wptr/rptr are in bytes! */
 440         u32 ring_index = ih->rptr >> 2;
 441         uint32_t dw[8];
 442 
 443         dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
 444         dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
 445         dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
 446         dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 447         dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
 448         dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
 449         dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
 450         dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
 451 
 452         entry->client_id = dw[0] & 0xff;
 453         entry->src_id = (dw[0] >> 8) & 0xff;
 454         entry->ring_id = (dw[0] >> 16) & 0xff;
 455         entry->vmid = (dw[0] >> 24) & 0xf;
 456         entry->vmid_src = (dw[0] >> 31);
 457         entry->timestamp = dw[1] | ((u64)(dw[2] & 0xffff) << 32);
 458         entry->timestamp_src = dw[2] >> 31;
 459         entry->pasid = dw[3] & 0xffff;
 460         entry->pasid_src = dw[3] >> 31;
 461         entry->src_data[0] = dw[4];
 462         entry->src_data[1] = dw[5];
 463         entry->src_data[2] = dw[6];
 464         entry->src_data[3] = dw[7];
 465 
 466         /* wptr/rptr are in bytes! */
 467         ih->rptr += 32;
 468 }
 469 
 470 /**
 471  * vega10_ih_irq_rearm - rearm IRQ if lost
 472  *
 473  * @adev: amdgpu_device pointer
 474  *
 475  */
 476 static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
 477                                struct amdgpu_ih_ring *ih)
 478 {
 479         uint32_t reg_rptr = 0;
 480         uint32_t v = 0;
 481         uint32_t i = 0;
 482 
 483         if (ih == &adev->irq.ih)
 484                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
 485         else if (ih == &adev->irq.ih1)
 486                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
 487         else if (ih == &adev->irq.ih2)
 488                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
 489         else
 490                 return;
 491 
 492         /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
 493         for (i = 0; i < MAX_REARM_RETRY; i++) {
 494                 v = RREG32_NO_KIQ(reg_rptr);
 495                 if ((v < ih->ring_size) && (v != ih->rptr))
 496                         WDOORBELL32(ih->doorbell_index, ih->rptr);
 497                 else
 498                         break;
 499         }
 500 }
 501 
 502 /**
 503  * vega10_ih_set_rptr - set the IH ring buffer rptr
 504  *
 505  * @adev: amdgpu_device pointer
 506  *
 507  * Set the IH ring buffer rptr.
 508  */
 509 static void vega10_ih_set_rptr(struct amdgpu_device *adev,
 510                                struct amdgpu_ih_ring *ih)
 511 {
 512         if (ih->use_doorbell) {
 513                 /* XXX check if swapping is necessary on BE */
 514                 *ih->rptr_cpu = ih->rptr;
 515                 WDOORBELL32(ih->doorbell_index, ih->rptr);
 516 
 517                 if (amdgpu_sriov_vf(adev))
 518                         vega10_ih_irq_rearm(adev, ih);
 519         } else if (ih == &adev->irq.ih) {
 520                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
 521         } else if (ih == &adev->irq.ih1) {
 522                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
 523         } else if (ih == &adev->irq.ih2) {
 524                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
 525         }
 526 }
 527 
 528 /**
 529  * vega10_ih_self_irq - dispatch work for ring 1 and 2
 530  *
 531  * @adev: amdgpu_device pointer
 532  * @source: irq source
 533  * @entry: IV with WPTR update
 534  *
 535  * Update the WPTR from the IV and schedule work to handle the entries.
 536  */
 537 static int vega10_ih_self_irq(struct amdgpu_device *adev,
 538                               struct amdgpu_irq_src *source,
 539                               struct amdgpu_iv_entry *entry)
 540 {
 541         uint32_t wptr = cpu_to_le32(entry->src_data[0]);
 542 
 543         switch (entry->ring_id) {
 544         case 1:
 545                 *adev->irq.ih1.wptr_cpu = wptr;
 546                 schedule_work(&adev->irq.ih1_work);
 547                 break;
 548         case 2:
 549                 *adev->irq.ih2.wptr_cpu = wptr;
 550                 schedule_work(&adev->irq.ih2_work);
 551                 break;
 552         default: break;
 553         }
 554         return 0;
 555 }
 556 
 557 static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
 558         .process = vega10_ih_self_irq,
 559 };
 560 
 561 static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
 562 {
 563         adev->irq.self_irq.num_types = 0;
 564         adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
 565 }
 566 
 567 static int vega10_ih_early_init(void *handle)
 568 {
 569         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 570 
 571         vega10_ih_set_interrupt_funcs(adev);
 572         vega10_ih_set_self_irq_funcs(adev);
 573         return 0;
 574 }
 575 
 576 static int vega10_ih_sw_init(void *handle)
 577 {
 578         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 579         int r;
 580 
 581         r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
 582                               &adev->irq.self_irq);
 583         if (r)
 584                 return r;
 585 
 586         r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
 587         if (r)
 588                 return r;
 589 
 590         adev->irq.ih.use_doorbell = true;
 591         adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
 592 
 593         r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
 594         if (r)
 595                 return r;
 596 
 597         adev->irq.ih1.use_doorbell = true;
 598         adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
 599 
 600         r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
 601         if (r)
 602                 return r;
 603 
 604         adev->irq.ih2.use_doorbell = true;
 605         adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
 606 
 607         r = amdgpu_irq_init(adev);
 608 
 609         return r;
 610 }
 611 
 612 static int vega10_ih_sw_fini(void *handle)
 613 {
 614         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 615 
 616         amdgpu_irq_fini(adev);
 617         amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
 618         amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
 619         amdgpu_ih_ring_fini(adev, &adev->irq.ih);
 620 
 621         return 0;
 622 }
 623 
 624 static int vega10_ih_hw_init(void *handle)
 625 {
 626         int r;
 627         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 628 
 629         r = vega10_ih_irq_init(adev);
 630         if (r)
 631                 return r;
 632 
 633         return 0;
 634 }
 635 
 636 static int vega10_ih_hw_fini(void *handle)
 637 {
 638         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 639 
 640         vega10_ih_irq_disable(adev);
 641 
 642         return 0;
 643 }
 644 
 645 static int vega10_ih_suspend(void *handle)
 646 {
 647         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 648 
 649         return vega10_ih_hw_fini(adev);
 650 }
 651 
 652 static int vega10_ih_resume(void *handle)
 653 {
 654         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 655 
 656         return vega10_ih_hw_init(adev);
 657 }
 658 
 659 static bool vega10_ih_is_idle(void *handle)
 660 {
 661         /* todo */
 662         return true;
 663 }
 664 
 665 static int vega10_ih_wait_for_idle(void *handle)
 666 {
 667         /* todo */
 668         return -ETIMEDOUT;
 669 }
 670 
 671 static int vega10_ih_soft_reset(void *handle)
 672 {
 673         /* todo */
 674 
 675         return 0;
 676 }
 677 
 678 static int vega10_ih_set_clockgating_state(void *handle,
 679                                           enum amd_clockgating_state state)
 680 {
 681         return 0;
 682 }
 683 
 684 static int vega10_ih_set_powergating_state(void *handle,
 685                                           enum amd_powergating_state state)
 686 {
 687         return 0;
 688 }
 689 
 690 const struct amd_ip_funcs vega10_ih_ip_funcs = {
 691         .name = "vega10_ih",
 692         .early_init = vega10_ih_early_init,
 693         .late_init = NULL,
 694         .sw_init = vega10_ih_sw_init,
 695         .sw_fini = vega10_ih_sw_fini,
 696         .hw_init = vega10_ih_hw_init,
 697         .hw_fini = vega10_ih_hw_fini,
 698         .suspend = vega10_ih_suspend,
 699         .resume = vega10_ih_resume,
 700         .is_idle = vega10_ih_is_idle,
 701         .wait_for_idle = vega10_ih_wait_for_idle,
 702         .soft_reset = vega10_ih_soft_reset,
 703         .set_clockgating_state = vega10_ih_set_clockgating_state,
 704         .set_powergating_state = vega10_ih_set_powergating_state,
 705 };
 706 
 707 static const struct amdgpu_ih_funcs vega10_ih_funcs = {
 708         .get_wptr = vega10_ih_get_wptr,
 709         .decode_iv = vega10_ih_decode_iv,
 710         .set_rptr = vega10_ih_set_rptr
 711 };
 712 
 713 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
 714 {
 715         adev->irq.ih_funcs = &vega10_ih_funcs;
 716 }
 717 
 718 const struct amdgpu_ip_block_version vega10_ih_ip_block =
 719 {
 720         .type = AMD_IP_BLOCK_TYPE_IH,
 721         .major = 4,
 722         .minor = 0,
 723         .rev = 0,
 724         .funcs = &vega10_ih_ip_funcs,
 725 };

/* [<][>][^][v][top][bottom][index][help] */