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

ih_v6_0.c (21321B)


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