Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #include <linux/pci.h>
0025 
0026 #include "amdgpu.h"
0027 #include "amdgpu_ih.h"
0028 #include "soc15.h"
0029 
0030 #include "oss/osssys_4_0_offset.h"
0031 #include "oss/osssys_4_0_sh_mask.h"
0032 
0033 #include "soc15_common.h"
0034 #include "vega10_ih.h"
0035 
0036 #define MAX_REARM_RETRY 10
0037 
0038 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
0039 
0040 /**
0041  * vega10_ih_init_register_offset - Initialize register offset for ih rings
0042  *
0043  * @adev: amdgpu_device pointer
0044  *
0045  * Initialize register offset ih rings (VEGA10).
0046  */
0047 static void vega10_ih_init_register_offset(struct amdgpu_device *adev)
0048 {
0049     struct amdgpu_ih_regs *ih_regs;
0050 
0051     if (adev->irq.ih.ring_size) {
0052         ih_regs = &adev->irq.ih.ih_regs;
0053         ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE);
0054         ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI);
0055         ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
0056         ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
0057         ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
0058         ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR);
0059         ih_regs->ih_rb_wptr_addr_lo = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO);
0060         ih_regs->ih_rb_wptr_addr_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI);
0061         ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL;
0062     }
0063 
0064     if (adev->irq.ih1.ring_size) {
0065         ih_regs = &adev->irq.ih1.ih_regs;
0066         ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_RING1);
0067         ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI_RING1);
0068         ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
0069         ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
0070         ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
0071         ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1);
0072         ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL_RING1;
0073     }
0074 
0075     if (adev->irq.ih2.ring_size) {
0076         ih_regs = &adev->irq.ih2.ih_regs;
0077         ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_RING2);
0078         ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI_RING2);
0079         ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
0080         ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
0081         ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
0082         ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2);
0083         ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL_RING2;
0084     }
0085 }
0086 
0087 /**
0088  * vega10_ih_toggle_ring_interrupts - toggle the interrupt ring buffer
0089  *
0090  * @adev: amdgpu_device pointer
0091  * @ih: amdgpu_ih_ring pointet
0092  * @enable: true - enable the interrupts, false - disable the interrupts
0093  *
0094  * Toggle the interrupt ring buffer (VEGA10)
0095  */
0096 static int vega10_ih_toggle_ring_interrupts(struct amdgpu_device *adev,
0097                         struct amdgpu_ih_ring *ih,
0098                         bool enable)
0099 {
0100     struct amdgpu_ih_regs *ih_regs;
0101     uint32_t tmp;
0102 
0103     ih_regs = &ih->ih_regs;
0104 
0105     tmp = RREG32(ih_regs->ih_rb_cntl);
0106     tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0));
0107     tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_GPU_TS_ENABLE, 1);
0108     /* enable_intr field is only valid in ring0 */
0109     if (ih == &adev->irq.ih)
0110         tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0));
0111     if (amdgpu_sriov_vf(adev)) {
0112         if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
0113             dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n");
0114             return -ETIMEDOUT;
0115         }
0116     } else {
0117         WREG32(ih_regs->ih_rb_cntl, tmp);
0118     }
0119 
0120     if (enable) {
0121         ih->enabled = true;
0122     } else {
0123         /* set rptr, wptr to 0 */
0124         WREG32(ih_regs->ih_rb_rptr, 0);
0125         WREG32(ih_regs->ih_rb_wptr, 0);
0126         ih->enabled = false;
0127         ih->rptr = 0;
0128     }
0129 
0130     return 0;
0131 }
0132 
0133 /**
0134  * vega10_ih_toggle_interrupts - Toggle all the available interrupt ring buffers
0135  *
0136  * @adev: amdgpu_device pointer
0137  * @enable: enable or disable interrupt ring buffers
0138  *
0139  * Toggle all the available interrupt ring buffers (VEGA10).
0140  */
0141 static int vega10_ih_toggle_interrupts(struct amdgpu_device *adev, bool enable)
0142 {
0143     struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2};
0144     int i;
0145     int r;
0146 
0147     for (i = 0; i < ARRAY_SIZE(ih); i++) {
0148         if (ih[i]->ring_size) {
0149             r = vega10_ih_toggle_ring_interrupts(adev, ih[i], enable);
0150             if (r)
0151                 return r;
0152         }
0153     }
0154 
0155     return 0;
0156 }
0157 
0158 static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
0159 {
0160     int rb_bufsz = order_base_2(ih->ring_size / 4);
0161 
0162     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
0163                    MC_SPACE, ih->use_bus_addr ? 1 : 4);
0164     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
0165                    WPTR_OVERFLOW_CLEAR, 1);
0166     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
0167                    WPTR_OVERFLOW_ENABLE, 1);
0168     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
0169     /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
0170      * value is written to memory
0171      */
0172     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
0173                    WPTR_WRITEBACK_ENABLE, 1);
0174     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
0175     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
0176     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
0177 
0178     return ih_rb_cntl;
0179 }
0180 
0181 static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
0182 {
0183     u32 ih_doorbell_rtpr = 0;
0184 
0185     if (ih->use_doorbell) {
0186         ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
0187                          IH_DOORBELL_RPTR, OFFSET,
0188                          ih->doorbell_index);
0189         ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
0190                          IH_DOORBELL_RPTR,
0191                          ENABLE, 1);
0192     } else {
0193         ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
0194                          IH_DOORBELL_RPTR,
0195                          ENABLE, 0);
0196     }
0197     return ih_doorbell_rtpr;
0198 }
0199 
0200 /**
0201  * vega10_ih_enable_ring - enable an ih ring buffer
0202  *
0203  * @adev: amdgpu_device pointer
0204  * @ih: amdgpu_ih_ring pointer
0205  *
0206  * Enable an ih ring buffer (VEGA10)
0207  */
0208 static int vega10_ih_enable_ring(struct amdgpu_device *adev,
0209                  struct amdgpu_ih_ring *ih)
0210 {
0211     struct amdgpu_ih_regs *ih_regs;
0212     uint32_t tmp;
0213 
0214     ih_regs = &ih->ih_regs;
0215 
0216     /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
0217     WREG32(ih_regs->ih_rb_base, ih->gpu_addr >> 8);
0218     WREG32(ih_regs->ih_rb_base_hi, (ih->gpu_addr >> 40) & 0xff);
0219 
0220     tmp = RREG32(ih_regs->ih_rb_cntl);
0221     tmp = vega10_ih_rb_cntl(ih, tmp);
0222     if (ih == &adev->irq.ih)
0223         tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled);
0224     if (ih == &adev->irq.ih1)
0225         tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1);
0226     if (amdgpu_sriov_vf(adev)) {
0227         if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
0228             dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n");
0229             return -ETIMEDOUT;
0230         }
0231     } else {
0232         WREG32(ih_regs->ih_rb_cntl, tmp);
0233     }
0234 
0235     if (ih == &adev->irq.ih) {
0236         /* set the ih ring 0 writeback address whether it's enabled or not */
0237         WREG32(ih_regs->ih_rb_wptr_addr_lo, lower_32_bits(ih->wptr_addr));
0238         WREG32(ih_regs->ih_rb_wptr_addr_hi, upper_32_bits(ih->wptr_addr) & 0xFFFF);
0239     }
0240 
0241     /* set rptr, wptr to 0 */
0242     WREG32(ih_regs->ih_rb_wptr, 0);
0243     WREG32(ih_regs->ih_rb_rptr, 0);
0244 
0245     WREG32(ih_regs->ih_doorbell_rptr, vega10_ih_doorbell_rptr(ih));
0246 
0247     return 0;
0248 }
0249 
0250 /**
0251  * vega10_ih_irq_init - init and enable the interrupt ring
0252  *
0253  * @adev: amdgpu_device pointer
0254  *
0255  * Allocate a ring buffer for the interrupt controller,
0256  * enable the RLC, disable interrupts, enable the IH
0257  * ring buffer and enable it (VI).
0258  * Called at device load and reume.
0259  * Returns 0 for success, errors for failure.
0260  */
0261 static int vega10_ih_irq_init(struct amdgpu_device *adev)
0262 {
0263     struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2};
0264     u32 ih_chicken;
0265     int ret;
0266     int i;
0267 
0268     /* disable irqs */
0269     ret = vega10_ih_toggle_interrupts(adev, false);
0270     if (ret)
0271         return ret;
0272 
0273     adev->nbio.funcs->ih_control(adev);
0274 
0275     if (adev->asic_type == CHIP_RENOIR) {
0276         ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
0277         if (adev->irq.ih.use_bus_addr) {
0278             ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
0279                            MC_SPACE_GPA_ENABLE, 1);
0280         }
0281         WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);
0282     }
0283 
0284     for (i = 0; i < ARRAY_SIZE(ih); i++) {
0285         if (ih[i]->ring_size) {
0286             ret = vega10_ih_enable_ring(adev, ih[i]);
0287             if (ret)
0288                 return ret;
0289         }
0290     }
0291 
0292     if (!amdgpu_sriov_vf(adev))
0293         adev->nbio.funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
0294                             adev->irq.ih.doorbell_index);
0295 
0296     pci_set_master(adev->pdev);
0297 
0298     /* enable interrupts */
0299     ret = vega10_ih_toggle_interrupts(adev, true);
0300     if (ret)
0301         return ret;
0302 
0303     if (adev->irq.ih_soft.ring_size)
0304         adev->irq.ih_soft.enabled = true;
0305 
0306     return 0;
0307 }
0308 
0309 /**
0310  * vega10_ih_irq_disable - disable interrupts
0311  *
0312  * @adev: amdgpu_device pointer
0313  *
0314  * Disable interrupts on the hw (VEGA10).
0315  */
0316 static void vega10_ih_irq_disable(struct amdgpu_device *adev)
0317 {
0318     vega10_ih_toggle_interrupts(adev, false);
0319 
0320     /* Wait and acknowledge irq */
0321     mdelay(1);
0322 }
0323 
0324 /**
0325  * vega10_ih_get_wptr - get the IH ring buffer wptr
0326  *
0327  * @adev: amdgpu_device pointer
0328  * @ih: IH ring buffer to fetch wptr
0329  *
0330  * Get the IH ring buffer wptr from either the register
0331  * or the writeback memory buffer (VEGA10).  Also check for
0332  * ring buffer overflow and deal with it.
0333  * Returns the value of the wptr.
0334  */
0335 static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
0336                   struct amdgpu_ih_ring *ih)
0337 {
0338     u32 wptr, tmp;
0339     struct amdgpu_ih_regs *ih_regs;
0340 
0341     if (ih == &adev->irq.ih || ih == &adev->irq.ih_soft) {
0342         /* Only ring0 supports writeback. On other rings fall back
0343          * to register-based code with overflow checking below.
0344          * ih_soft ring doesn't have any backing hardware registers,
0345          * update wptr and return.
0346          */
0347         wptr = le32_to_cpu(*ih->wptr_cpu);
0348 
0349         if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
0350             goto out;
0351     }
0352 
0353     ih_regs = &ih->ih_regs;
0354 
0355     /* Double check that the overflow wasn't already cleared. */
0356     wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr);
0357     if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
0358         goto out;
0359 
0360     wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
0361 
0362     /* When a ring buffer overflow happen start parsing interrupt
0363      * from the last not overwritten vector (wptr + 32). Hopefully
0364      * this should allow us to catchup.
0365      */
0366     tmp = (wptr + 32) & ih->ptr_mask;
0367     dev_warn(adev->dev, "IH ring buffer overflow "
0368          "(0x%08X, 0x%08X, 0x%08X)\n",
0369          wptr, ih->rptr, tmp);
0370     ih->rptr = tmp;
0371 
0372     tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl);
0373     tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
0374     WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
0375 
0376 out:
0377     return (wptr & ih->ptr_mask);
0378 }
0379 
0380 /**
0381  * vega10_ih_irq_rearm - rearm IRQ if lost
0382  *
0383  * @adev: amdgpu_device pointer
0384  * @ih: IH ring to match
0385  *
0386  */
0387 static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
0388                    struct amdgpu_ih_ring *ih)
0389 {
0390     uint32_t v = 0;
0391     uint32_t i = 0;
0392     struct amdgpu_ih_regs *ih_regs;
0393 
0394     ih_regs = &ih->ih_regs;
0395     /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
0396     for (i = 0; i < MAX_REARM_RETRY; i++) {
0397         v = RREG32_NO_KIQ(ih_regs->ih_rb_rptr);
0398         if ((v < ih->ring_size) && (v != ih->rptr))
0399             WDOORBELL32(ih->doorbell_index, ih->rptr);
0400         else
0401             break;
0402     }
0403 }
0404 
0405 /**
0406  * vega10_ih_set_rptr - set the IH ring buffer rptr
0407  *
0408  * @adev: amdgpu_device pointer
0409  * @ih: IH ring buffer to set rptr
0410  *
0411  * Set the IH ring buffer rptr.
0412  */
0413 static void vega10_ih_set_rptr(struct amdgpu_device *adev,
0414                    struct amdgpu_ih_ring *ih)
0415 {
0416     struct amdgpu_ih_regs *ih_regs;
0417 
0418     if (ih == &adev->irq.ih_soft)
0419         return;
0420 
0421     if (ih->use_doorbell) {
0422         /* XXX check if swapping is necessary on BE */
0423         *ih->rptr_cpu = ih->rptr;
0424         WDOORBELL32(ih->doorbell_index, ih->rptr);
0425 
0426         if (amdgpu_sriov_vf(adev))
0427             vega10_ih_irq_rearm(adev, ih);
0428     } else {
0429         ih_regs = &ih->ih_regs;
0430         WREG32(ih_regs->ih_rb_rptr, ih->rptr);
0431     }
0432 }
0433 
0434 /**
0435  * vega10_ih_self_irq - dispatch work for ring 1 and 2
0436  *
0437  * @adev: amdgpu_device pointer
0438  * @source: irq source
0439  * @entry: IV with WPTR update
0440  *
0441  * Update the WPTR from the IV and schedule work to handle the entries.
0442  */
0443 static int vega10_ih_self_irq(struct amdgpu_device *adev,
0444                   struct amdgpu_irq_src *source,
0445                   struct amdgpu_iv_entry *entry)
0446 {
0447     switch (entry->ring_id) {
0448     case 1:
0449         schedule_work(&adev->irq.ih1_work);
0450         break;
0451     case 2:
0452         schedule_work(&adev->irq.ih2_work);
0453         break;
0454     default: break;
0455     }
0456     return 0;
0457 }
0458 
0459 static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
0460     .process = vega10_ih_self_irq,
0461 };
0462 
0463 static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
0464 {
0465     adev->irq.self_irq.num_types = 0;
0466     adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
0467 }
0468 
0469 static int vega10_ih_early_init(void *handle)
0470 {
0471     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0472 
0473     vega10_ih_set_interrupt_funcs(adev);
0474     vega10_ih_set_self_irq_funcs(adev);
0475     return 0;
0476 }
0477 
0478 static int vega10_ih_sw_init(void *handle)
0479 {
0480     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0481     int r;
0482 
0483     r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
0484                   &adev->irq.self_irq);
0485     if (r)
0486         return r;
0487 
0488     r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
0489     if (r)
0490         return r;
0491 
0492     adev->irq.ih.use_doorbell = true;
0493     adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
0494 
0495     if (!(adev->flags & AMD_IS_APU)) {
0496         r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
0497         if (r)
0498             return r;
0499 
0500         adev->irq.ih1.use_doorbell = true;
0501         adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
0502 
0503         r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
0504         if (r)
0505             return r;
0506 
0507         adev->irq.ih2.use_doorbell = true;
0508         adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
0509     }
0510     /* initialize ih control registers offset */
0511     vega10_ih_init_register_offset(adev);
0512 
0513     r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
0514     if (r)
0515         return r;
0516 
0517     r = amdgpu_irq_init(adev);
0518 
0519     return r;
0520 }
0521 
0522 static int vega10_ih_sw_fini(void *handle)
0523 {
0524     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0525 
0526     amdgpu_irq_fini_sw(adev);
0527 
0528     return 0;
0529 }
0530 
0531 static int vega10_ih_hw_init(void *handle)
0532 {
0533     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0534 
0535     return vega10_ih_irq_init(adev);
0536 }
0537 
0538 static int vega10_ih_hw_fini(void *handle)
0539 {
0540     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0541 
0542     vega10_ih_irq_disable(adev);
0543 
0544     return 0;
0545 }
0546 
0547 static int vega10_ih_suspend(void *handle)
0548 {
0549     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0550 
0551     return vega10_ih_hw_fini(adev);
0552 }
0553 
0554 static int vega10_ih_resume(void *handle)
0555 {
0556     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0557 
0558     return vega10_ih_hw_init(adev);
0559 }
0560 
0561 static bool vega10_ih_is_idle(void *handle)
0562 {
0563     /* todo */
0564     return true;
0565 }
0566 
0567 static int vega10_ih_wait_for_idle(void *handle)
0568 {
0569     /* todo */
0570     return -ETIMEDOUT;
0571 }
0572 
0573 static int vega10_ih_soft_reset(void *handle)
0574 {
0575     /* todo */
0576 
0577     return 0;
0578 }
0579 
0580 static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
0581                            bool enable)
0582 {
0583     uint32_t data, def, field_val;
0584 
0585     if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
0586         def = data = RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL);
0587         field_val = enable ? 0 : 1;
0588         /**
0589          * Vega10/12 and RAVEN don't have IH_BUFFER_MEM_CLK_SOFT_OVERRIDE field.
0590          */
0591         if (adev->asic_type == CHIP_RENOIR)
0592             data = REG_SET_FIELD(data, IH_CLK_CTRL,
0593                      IH_BUFFER_MEM_CLK_SOFT_OVERRIDE, field_val);
0594 
0595         data = REG_SET_FIELD(data, IH_CLK_CTRL,
0596                      DBUS_MUX_CLK_SOFT_OVERRIDE, field_val);
0597         data = REG_SET_FIELD(data, IH_CLK_CTRL,
0598                      OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
0599         data = REG_SET_FIELD(data, IH_CLK_CTRL,
0600                      LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
0601         data = REG_SET_FIELD(data, IH_CLK_CTRL,
0602                      DYN_CLK_SOFT_OVERRIDE, field_val);
0603         data = REG_SET_FIELD(data, IH_CLK_CTRL,
0604                      REG_CLK_SOFT_OVERRIDE, field_val);
0605         if (def != data)
0606             WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
0607     }
0608 }
0609 
0610 static int vega10_ih_set_clockgating_state(void *handle,
0611                       enum amd_clockgating_state state)
0612 {
0613     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0614 
0615     vega10_ih_update_clockgating_state(adev,
0616                 state == AMD_CG_STATE_GATE);
0617     return 0;
0618 
0619 }
0620 
0621 static int vega10_ih_set_powergating_state(void *handle,
0622                       enum amd_powergating_state state)
0623 {
0624     return 0;
0625 }
0626 
0627 const struct amd_ip_funcs vega10_ih_ip_funcs = {
0628     .name = "vega10_ih",
0629     .early_init = vega10_ih_early_init,
0630     .late_init = NULL,
0631     .sw_init = vega10_ih_sw_init,
0632     .sw_fini = vega10_ih_sw_fini,
0633     .hw_init = vega10_ih_hw_init,
0634     .hw_fini = vega10_ih_hw_fini,
0635     .suspend = vega10_ih_suspend,
0636     .resume = vega10_ih_resume,
0637     .is_idle = vega10_ih_is_idle,
0638     .wait_for_idle = vega10_ih_wait_for_idle,
0639     .soft_reset = vega10_ih_soft_reset,
0640     .set_clockgating_state = vega10_ih_set_clockgating_state,
0641     .set_powergating_state = vega10_ih_set_powergating_state,
0642 };
0643 
0644 static const struct amdgpu_ih_funcs vega10_ih_funcs = {
0645     .get_wptr = vega10_ih_get_wptr,
0646     .decode_iv = amdgpu_ih_decode_iv_helper,
0647     .decode_iv_ts = amdgpu_ih_decode_iv_ts_helper,
0648     .set_rptr = vega10_ih_set_rptr
0649 };
0650 
0651 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
0652 {
0653     adev->irq.ih_funcs = &vega10_ih_funcs;
0654 }
0655 
0656 const struct amdgpu_ip_block_version vega10_ih_ip_block =
0657 {
0658     .type = AMD_IP_BLOCK_TYPE_IH,
0659     .major = 4,
0660     .minor = 0,
0661     .rev = 0,
0662     .funcs = &vega10_ih_ip_funcs,
0663 };