cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

navi10_ih.c (20533B)


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