File Index
Files and directories
Sign in
FILE

hdp_v5_0.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c C
  1/*
  2 * Copyright 2020 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#include "amdgpu.h"
 24#include "hdp_v5_0.h"
 25
 26#include "hdp/hdp_5_0_0_offset.h"
 27#include "hdp/hdp_5_0_0_sh_mask.h"
 28#include <uapi/linux/kfd_ioctl.h>
 29
 30static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev,
 31				    struct amdgpu_ring *ring)
 32{
 33	if (!ring || !ring->funcs->emit_wreg) {
 34		WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
 35		RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE);
 36	} else {
 37		amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
 38					HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
 39	}
 40}
 41
 42static void hdp_v5_0_update_mem_power_gating(struct amdgpu_device *adev,
 43					  bool enable)
 44{
 45	uint32_t hdp_clk_cntl, hdp_clk_cntl1;
 46	uint32_t hdp_mem_pwr_cntl;
 47
 48	if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS |
 49				AMD_CG_SUPPORT_HDP_DS |
 50				AMD_CG_SUPPORT_HDP_SD)))
 51		return;
 52
 53	hdp_clk_cntl = hdp_clk_cntl1 = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
 54	hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
 55
 56	/* Before doing clock/power mode switch,
 57	 * forced on IPH & RC clock */
 58	hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
 59				     IPH_MEM_CLK_SOFT_OVERRIDE, 1);
 60	hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
 61				     RC_MEM_CLK_SOFT_OVERRIDE, 1);
 62	WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
 63
 64	/* HDP 5.0 doesn't support dynamic power mode switch,
 65	 * disable clock and power gating before any changing */
 66	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 67					 IPH_MEM_POWER_CTRL_EN, 0);
 68	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 69					 IPH_MEM_POWER_LS_EN, 0);
 70	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 71					 IPH_MEM_POWER_DS_EN, 0);
 72	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 73					 IPH_MEM_POWER_SD_EN, 0);
 74	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 75					 RC_MEM_POWER_CTRL_EN, 0);
 76	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 77					 RC_MEM_POWER_LS_EN, 0);
 78	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 79					 RC_MEM_POWER_DS_EN, 0);
 80	hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
 81					 RC_MEM_POWER_SD_EN, 0);
 82	WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
 83
 84	/* Already disabled above. The actions below are for "enabled" only */
 85	if (enable) {
 86		/* only one clock gating mode (LS/DS/SD) can be enabled */
 87		if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
 88			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
 89							 HDP_MEM_POWER_CTRL,
 90							 IPH_MEM_POWER_LS_EN, 1);
 91			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
 92							 HDP_MEM_POWER_CTRL,
 93							 RC_MEM_POWER_LS_EN, 1);
 94		} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
 95			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
 96							 HDP_MEM_POWER_CTRL,
 97							 IPH_MEM_POWER_DS_EN, 1);
 98			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
 99							 HDP_MEM_POWER_CTRL,
100							 RC_MEM_POWER_DS_EN, 1);
101		} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
102			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
103							 HDP_MEM_POWER_CTRL,
104							 IPH_MEM_POWER_SD_EN, 1);
105			/* RC should not use shut down mode, fallback to ds  or ls if allowed */
106			if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS)
107				hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
108								 HDP_MEM_POWER_CTRL,
109								 RC_MEM_POWER_DS_EN, 1);
110			else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)
111				hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
112								 HDP_MEM_POWER_CTRL,
113								 RC_MEM_POWER_LS_EN, 1);
114		}
115
116		/* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to
117		 * be set for SRAM LS/DS/SD */
118		if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS |
119				      AMD_CG_SUPPORT_HDP_SD)) {
120			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
121							 IPH_MEM_POWER_CTRL_EN, 1);
122			hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
123							 RC_MEM_POWER_CTRL_EN, 1);
124			WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
125		}
126	}
127
128	/* disable IPH & RC clock override after clock/power mode changing */
129	hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
130				     IPH_MEM_CLK_SOFT_OVERRIDE, 0);
131	hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
132				     RC_MEM_CLK_SOFT_OVERRIDE, 0);
133	WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
134}
135
136static void hdp_v5_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
137						      bool enable)
138{
139	uint32_t hdp_clk_cntl;
140
141	if (!(adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
142		return;
143
144	hdp_clk_cntl = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
145
146	if (enable) {
147		hdp_clk_cntl &=
148			~(uint32_t)
149			(HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
150			 HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
151			 HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
152			 HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
153			 HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
154			 HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK);
155	} else {
156		hdp_clk_cntl |= HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
157			HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
158			HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
159			HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
160			HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
161			HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK;
162	}
163
164	WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
165}
166
167static void hdp_v5_0_update_clock_gating(struct amdgpu_device *adev,
168					      bool enable)
169{
170	hdp_v5_0_update_mem_power_gating(adev, enable);
171	hdp_v5_0_update_medium_grain_clock_gating(adev, enable);
172}
173
174static void hdp_v5_0_get_clockgating_state(struct amdgpu_device *adev,
175					    u64 *flags)
176{
177	uint32_t tmp;
178
179	/* AMD_CG_SUPPORT_HDP_MGCG */
180	tmp = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
181	if (!(tmp & (HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
182		     HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
183		     HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
184		     HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
185		     HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
186		     HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK)))
187		*flags |= AMD_CG_SUPPORT_HDP_MGCG;
188
189	/* AMD_CG_SUPPORT_HDP_LS/DS/SD */
190	tmp = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
191	if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK)
192		*flags |= AMD_CG_SUPPORT_HDP_LS;
193	else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_DS_EN_MASK)
194		*flags |= AMD_CG_SUPPORT_HDP_DS;
195	else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_SD_EN_MASK)
196		*flags |= AMD_CG_SUPPORT_HDP_SD;
197}
198
199static void hdp_v5_0_init_registers(struct amdgpu_device *adev)
200{
201	u32 tmp;
202
203	tmp = RREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL);
204	tmp |= HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE_MASK;
205	WREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL, tmp);
206}
207
208const struct amdgpu_hdp_funcs hdp_v5_0_funcs = {
209	.flush_hdp = amdgpu_hdp_generic_flush,
210	.invalidate_hdp = hdp_v5_0_invalidate_hdp,
211	.update_clock_gating = hdp_v5_0_update_clock_gating,
212	.get_clock_gating_state = hdp_v5_0_get_clockgating_state,
213	.init_registers = hdp_v5_0_init_registers,
214};
~/ Read-only file preview.