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