Bug Summary

File:dev/pci/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
Warning:line 2945, column 6
Access to field 'disable_edc_leakage_controller' results in a dereference of a null pointer (loaded from variable 'data')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name smu7_hwmgr.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
1/*
2 * Copyright 2015 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 "pp_debug.h"
24#include <linux/delay.h>
25#include <linux/fb.h>
26#include <linux/module.h>
27#include <linux/pci.h>
28#include <linux/slab.h>
29#include <asm/div64.h>
30#if IS_ENABLED(CONFIG_X86_64)1 && defined(__linux__)
31#include <asm/intel-family.h>
32#endif
33#include <drm/amdgpu_drm.h>
34#include "ppatomctrl.h"
35#include "atombios.h"
36#include "pptable_v1_0.h"
37#include "pppcielanes.h"
38#include "amd_pcie_helpers.h"
39#include "hardwaremanager.h"
40#include "process_pptables_v1_0.h"
41#include "cgs_common.h"
42
43#include "smu7_common.h"
44
45#include "hwmgr.h"
46#include "smu7_hwmgr.h"
47#include "smu_ucode_xfer_vi.h"
48#include "smu7_powertune.h"
49#include "smu7_dyn_defaults.h"
50#include "smu7_thermal.h"
51#include "smu7_clockpowergating.h"
52#include "processpptables.h"
53#include "pp_thermal.h"
54#include "smu7_baco.h"
55#include "smu7_smumgr.h"
56#include "polaris10_smumgr.h"
57
58#include "ivsrcid/ivsrcid_vislands30.h"
59
60#define MC_CG_ARB_FREQ_F00x0a 0x0a
61#define MC_CG_ARB_FREQ_F10x0b 0x0b
62#define MC_CG_ARB_FREQ_F20x0c 0x0c
63#define MC_CG_ARB_FREQ_F30x0d 0x0d
64
65#define MC_CG_SEQ_DRAMCONF_S00x05 0x05
66#define MC_CG_SEQ_DRAMCONF_S10x06 0x06
67#define MC_CG_SEQ_YCLK_SUSPEND0x04 0x04
68#define MC_CG_SEQ_YCLK_RESUME0x0a 0x0a
69
70#define SMC_CG_IND_START0xc0030000 0xc0030000
71#define SMC_CG_IND_END0xc0040000 0xc0040000
72
73#define MEM_FREQ_LOW_LATENCY25000 25000
74#define MEM_FREQ_HIGH_LATENCY80000 80000
75
76#define MEM_LATENCY_HIGH45 45
77#define MEM_LATENCY_LOW35 35
78#define MEM_LATENCY_ERR0xFFFF 0xFFFF
79
80#define MC_SEQ_MISC0_GDDR5_SHIFT28 28
81#define MC_SEQ_MISC0_GDDR5_MASK0xf0000000 0xf0000000
82#define MC_SEQ_MISC0_GDDR5_VALUE5 5
83
84#define PCIE_BUS_CLK10000 10000
85#define TCLK(10000 / 10) (PCIE_BUS_CLK10000 / 10)
86
87static struct profile_mode_setting smu7_profiling[7] =
88 {{0, 0, 0, 0, 0, 0, 0, 0},
89 {1, 0, 100, 30, 1, 0, 100, 10},
90 {1, 10, 0, 30, 0, 0, 0, 0},
91 {0, 0, 0, 0, 1, 10, 16, 31},
92 {1, 0, 11, 50, 1, 0, 100, 10},
93 {1, 0, 5, 30, 0, 0, 0, 0},
94 {0, 0, 0, 0, 0, 0, 0, 0},
95 };
96
97#define PPSMC_MSG_SetVBITimeout_VEGAM((uint16_t) 0x310) ((uint16_t) 0x310)
98
99#define ixPWR_SVI2_PLANE1_LOAD0xC0200280 0xC0200280
100#define PWR_SVI2_PLANE1_LOAD__PSI1_MASK0x00000020L 0x00000020L
101#define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK0x00000040L 0x00000040L
102#define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT0x00000005 0x00000005
103#define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT0x00000006 0x00000006
104
105#define STRAP_EVV_REVISION_MSB2211 2211
106#define STRAP_EVV_REVISION_LSB2208 2208
107
108/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
109enum DPM_EVENT_SRC {
110 DPM_EVENT_SRC_ANALOG = 0,
111 DPM_EVENT_SRC_EXTERNAL = 1,
112 DPM_EVENT_SRC_DIGITAL = 2,
113 DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
114 DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4
115};
116
117#define ixDIDT_SQ_EDC_CTRL0x0013 0x0013
118#define ixDIDT_SQ_EDC_THRESHOLD0x0014 0x0014
119#define ixDIDT_SQ_EDC_STALL_PATTERN_1_20x0015 0x0015
120#define ixDIDT_SQ_EDC_STALL_PATTERN_3_40x0016 0x0016
121#define ixDIDT_SQ_EDC_STALL_PATTERN_5_60x0017 0x0017
122#define ixDIDT_SQ_EDC_STALL_PATTERN_70x0018 0x0018
123
124#define ixDIDT_TD_EDC_CTRL0x0053 0x0053
125#define ixDIDT_TD_EDC_THRESHOLD0x0054 0x0054
126#define ixDIDT_TD_EDC_STALL_PATTERN_1_20x0055 0x0055
127#define ixDIDT_TD_EDC_STALL_PATTERN_3_40x0056 0x0056
128#define ixDIDT_TD_EDC_STALL_PATTERN_5_60x0057 0x0057
129#define ixDIDT_TD_EDC_STALL_PATTERN_70x0058 0x0058
130
131#define ixDIDT_TCP_EDC_CTRL0x0073 0x0073
132#define ixDIDT_TCP_EDC_THRESHOLD0x0074 0x0074
133#define ixDIDT_TCP_EDC_STALL_PATTERN_1_20x0075 0x0075
134#define ixDIDT_TCP_EDC_STALL_PATTERN_3_40x0076 0x0076
135#define ixDIDT_TCP_EDC_STALL_PATTERN_5_60x0077 0x0077
136#define ixDIDT_TCP_EDC_STALL_PATTERN_70x0078 0x0078
137
138#define ixDIDT_DB_EDC_CTRL0x0033 0x0033
139#define ixDIDT_DB_EDC_THRESHOLD0x0034 0x0034
140#define ixDIDT_DB_EDC_STALL_PATTERN_1_20x0035 0x0035
141#define ixDIDT_DB_EDC_STALL_PATTERN_3_40x0036 0x0036
142#define ixDIDT_DB_EDC_STALL_PATTERN_5_60x0037 0x0037
143#define ixDIDT_DB_EDC_STALL_PATTERN_70x0038 0x0038
144
145uint32_t DIDTEDCConfig_P12[] = {
146 ixDIDT_SQ_EDC_STALL_PATTERN_1_20x0015,
147 ixDIDT_SQ_EDC_STALL_PATTERN_3_40x0016,
148 ixDIDT_SQ_EDC_STALL_PATTERN_5_60x0017,
149 ixDIDT_SQ_EDC_STALL_PATTERN_70x0018,
150 ixDIDT_SQ_EDC_THRESHOLD0x0014,
151 ixDIDT_SQ_EDC_CTRL0x0013,
152 ixDIDT_TD_EDC_STALL_PATTERN_1_20x0055,
153 ixDIDT_TD_EDC_STALL_PATTERN_3_40x0056,
154 ixDIDT_TD_EDC_STALL_PATTERN_5_60x0057,
155 ixDIDT_TD_EDC_STALL_PATTERN_70x0058,
156 ixDIDT_TD_EDC_THRESHOLD0x0054,
157 ixDIDT_TD_EDC_CTRL0x0053,
158 ixDIDT_TCP_EDC_STALL_PATTERN_1_20x0075,
159 ixDIDT_TCP_EDC_STALL_PATTERN_3_40x0076,
160 ixDIDT_TCP_EDC_STALL_PATTERN_5_60x0077,
161 ixDIDT_TCP_EDC_STALL_PATTERN_70x0078,
162 ixDIDT_TCP_EDC_THRESHOLD0x0074,
163 ixDIDT_TCP_EDC_CTRL0x0073,
164 ixDIDT_DB_EDC_STALL_PATTERN_1_20x0035,
165 ixDIDT_DB_EDC_STALL_PATTERN_3_40x0036,
166 ixDIDT_DB_EDC_STALL_PATTERN_5_60x0037,
167 ixDIDT_DB_EDC_STALL_PATTERN_70x0038,
168 ixDIDT_DB_EDC_THRESHOLD0x0034,
169 ixDIDT_DB_EDC_CTRL0x0033,
170 0xFFFFFFFF // End of list
171};
172
173static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
174static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
175 enum pp_clock_type type, uint32_t mask);
176static int smu7_notify_has_display(struct pp_hwmgr *hwmgr);
177
178static struct smu7_power_state *cast_phw_smu7_power_state(
179 struct pp_hw_power_state *hw_ps)
180{
181 PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
182 "Invalid Powerstate Type!",do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
183 return NULL)do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
;
184
185 return (struct smu7_power_state *)hw_ps;
186}
187
188static const struct smu7_power_state *cast_const_phw_smu7_power_state(
189 const struct pp_hw_power_state *hw_ps)
190{
191 PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
192 "Invalid Powerstate Type!",do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
193 return NULL)do { if (!((PhwVIslands_Magic == hw_ps->magic))) { printk(
"\0014" "amdgpu: " "%s\n", "Invalid Powerstate Type!"); return
((void *)0); } } while (0)
;
194
195 return (const struct smu7_power_state *)hw_ps;
196}
197
198/**
199 * smu7_get_mc_microcode_version - Find the MC microcode version and store it in the HwMgr struct
200 *
201 * @hwmgr: the address of the powerplay hardware manager.
202 * Return: always 0
203 */
204static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
205{
206 cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xa91,0x9F))
;
207
208 hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xa92))
;
209
210 return 0;
211}
212
213static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
214{
215 uint32_t speedCntl = 0;
216
217 /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
218 speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x100100a4))
219 ixPCIE_LC_SPEED_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x100100a4))
;
220 return((uint16_t)PHM_GET_FIELD(speedCntl,(((speedCntl) & 0x6000) >> 0xd)
221 PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)(((speedCntl) & 0x6000) >> 0xd));
222}
223
224static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
225{
226 uint32_t link_width;
227
228 /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
229 link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x100100a2))) & 0x70)
>> 0x4)
230 PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD)((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x100100a2))) & 0x70)
>> 0x4)
;
231
232 PP_ASSERT_WITH_CODE((7 >= link_width),do { if (!((7 >= link_width))) { printk("\0014" "amdgpu: "
"%s\n", "Invalid PCIe lane width!"); return 0; } } while (0)
233 "Invalid PCIe lane width!", return 0)do { if (!((7 >= link_width))) { printk("\0014" "amdgpu: "
"%s\n", "Invalid PCIe lane width!"); return 0; } } while (0)
;
234
235 return decode_pcie_lane_width(link_width);
236}
237
238/**
239 * smu7_enable_smc_voltage_controller - Enable voltage control
240 *
241 * @hwmgr: the address of the powerplay hardware manager.
242 * Return: always PP_Result_OK
243 */
244static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
245{
246 if (hwmgr->chip_id >= CHIP_POLARIS10 &&
247 hwmgr->chip_id <= CHIP_VEGAM) {
248 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200280,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xC0200280))) & ~0x00000020L) | (
0x00000020L & ((0) << 0x00000005)))))
249 CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200280,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xC0200280))) & ~0x00000020L) | (
0x00000020L & ((0) << 0x00000005)))))
;
250 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200280,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xC0200280))) & ~0x00000040L) | (
0x00000040L & ((0) << 0x00000006)))))
251 CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200280,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xC0200280))) & ~0x00000040L) | (
0x00000040L & ((0) << 0x00000006)))))
;
252 }
253
254 if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK)
255 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable((uint16_t) 0x109), NULL((void *)0));
256
257 return 0;
258}
259
260/**
261 * smu7_voltage_control - Checks if we want to support voltage control
262 *
263 * @hwmgr: the address of the powerplay hardware manager.
264 */
265static bool_Bool smu7_voltage_control(const struct pp_hwmgr *hwmgr)
266{
267 const struct smu7_hwmgr *data =
268 (const struct smu7_hwmgr *)(hwmgr->backend);
269
270 return (SMU7_VOLTAGE_CONTROL_NONE0x0 != data->voltage_control);
271}
272
273/**
274 * smu7_enable_voltage_control - Enable voltage control
275 *
276 * @hwmgr: the address of the powerplay hardware manager.
277 * Return: always 0
278 */
279static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr)
280{
281 /* enable voltage control */
282 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x400) | (0x400 &
((1) << 0xa)))))
283 GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x400) | (0x400 &
((1) << 0xa)))))
;
284
285 return 0;
286}
287
288static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table,
289 struct phm_clock_voltage_dependency_table *voltage_dependency_table
290 )
291{
292 uint32_t i;
293
294 PP_ASSERT_WITH_CODE((NULL != voltage_table),do { if (!((((void *)0) != voltage_table))) { printk("\0014" "amdgpu: "
"%s\n", "Voltage Dependency Table empty."); return -22;; } }
while (0)
295 "Voltage Dependency Table empty.", return -EINVAL;)do { if (!((((void *)0) != voltage_table))) { printk("\0014" "amdgpu: "
"%s\n", "Voltage Dependency Table empty."); return -22;; } }
while (0)
;
296
297 voltage_table->mask_low = 0;
298 voltage_table->phase_delay = 0;
299 voltage_table->count = voltage_dependency_table->count;
300
301 for (i = 0; i < voltage_dependency_table->count; i++) {
302 voltage_table->entries[i].value =
303 voltage_dependency_table->entries[i].v;
304 voltage_table->entries[i].smio_low = 0;
305 }
306
307 return 0;
308}
309
310
311/**
312 * smu7_construct_voltage_tables - Create Voltage Tables.
313 *
314 * @hwmgr: the address of the powerplay hardware manager.
315 * Return: always 0
316 */
317static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr)
318{
319 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
320 struct phm_ppt_v1_information *table_info =
321 (struct phm_ppt_v1_information *)hwmgr->pptable;
322 int result = 0;
323 uint32_t tmp;
324
325 if (SMU7_VOLTAGE_CONTROL_BY_GPIO0x1 == data->mvdd_control) {
326 result = atomctrl_get_voltage_table_v3(hwmgr,
327 VOLTAGE_TYPE_MVDDC2, VOLTAGE_OBJ_GPIO_LUT0,
328 &(data->mvdd_voltage_table));
329 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve MVDD table."); return result; } } while
(0)
330 "Failed to retrieve MVDD table.",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve MVDD table."); return result; } } while
(0)
331 return result)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve MVDD table."); return result; } } while
(0)
;
332 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID20x2 == data->mvdd_control) {
333 if (hwmgr->pp_table_version == PP_TABLE_V1)
334 result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table),
335 table_info->vdd_dep_on_mclk);
336 else if (hwmgr->pp_table_version == PP_TABLE_V0)
337 result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table),
338 hwmgr->dyn_state.mvdd_dependency_on_mclk);
339
340 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 MVDD table from dependency table."
); return result;; } } while (0)
341 "Failed to retrieve SVI2 MVDD table from dependency table.",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 MVDD table from dependency table."
); return result;; } } while (0)
342 return result;)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 MVDD table from dependency table."
); return result;; } } while (0)
;
343 }
344
345 if (SMU7_VOLTAGE_CONTROL_BY_GPIO0x1 == data->vddci_control) {
346 result = atomctrl_get_voltage_table_v3(hwmgr,
347 VOLTAGE_TYPE_VDDCI4, VOLTAGE_OBJ_GPIO_LUT0,
348 &(data->vddci_voltage_table));
349 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve VDDCI table."); return result; } } while
(0)
350 "Failed to retrieve VDDCI table.",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve VDDCI table."); return result; } } while
(0)
351 return result)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve VDDCI table."); return result; } } while
(0)
;
352 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID20x2 == data->vddci_control) {
353 if (hwmgr->pp_table_version == PP_TABLE_V1)
354 result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table),
355 table_info->vdd_dep_on_mclk);
356 else if (hwmgr->pp_table_version == PP_TABLE_V0)
357 result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table),
358 hwmgr->dyn_state.vddci_dependency_on_mclk);
359 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDCI table from dependency table."
); return result; } } while (0)
360 "Failed to retrieve SVI2 VDDCI table from dependency table.",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDCI table from dependency table."
); return result; } } while (0)
361 return result)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDCI table from dependency table."
); return result; } } while (0)
;
362 }
363
364 if (SMU7_VOLTAGE_CONTROL_BY_SVID20x2 == data->vdd_gfx_control) {
365 /* VDDGFX has only SVI2 voltage control */
366 result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table),
367 table_info->vddgfx_lookup_table);
368 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDGFX table from lookup table.");
return result;; } } while (0)
369 "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDGFX table from lookup table.");
return result;; } } while (0)
;
370 }
371
372
373 if (SMU7_VOLTAGE_CONTROL_BY_GPIO0x1 == data->voltage_control) {
374 result = atomctrl_get_voltage_table_v3(hwmgr,
375 VOLTAGE_TYPE_VDDC1, VOLTAGE_OBJ_GPIO_LUT0,
376 &data->vddc_voltage_table);
377 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve VDDC table."); return result;; } } while
(0)
378 "Failed to retrieve VDDC table.", return result;)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve VDDC table."); return result;; } } while
(0)
;
379 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID20x2 == data->voltage_control) {
380
381 if (hwmgr->pp_table_version == PP_TABLE_V0)
382 result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table,
383 hwmgr->dyn_state.vddc_dependency_on_mclk);
384 else if (hwmgr->pp_table_version == PP_TABLE_V1)
385 result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table),
386 table_info->vddc_lookup_table);
387
388 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDC table from dependency table."
); return result;; } } while (0)
389 "Failed to retrieve SVI2 VDDC table from dependency table.", return result;)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to retrieve SVI2 VDDC table from dependency table."
); return result;; } } while (0)
;
390 }
391
392 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC);
393 PP_ASSERT_WITH_CODE(do { if (!((data->vddc_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddc_voltage_table)); } } while (0)
394 (data->vddc_voltage_table.count <= tmp),do { if (!((data->vddc_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddc_voltage_table)); } } while (0)
395 "Too many voltage values for VDDC. Trimming to fit state table.",do { if (!((data->vddc_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddc_voltage_table)); } } while (0)
396 phm_trim_voltage_table_to_fit_state_table(tmp,do { if (!((data->vddc_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddc_voltage_table)); } } while (0)
397 &(data->vddc_voltage_table)))do { if (!((data->vddc_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddc_voltage_table)); } } while (0)
;
398
399 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
400 PP_ASSERT_WITH_CODE(do { if (!((data->vddgfx_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddgfx_voltage_table)); } } while (0)
401 (data->vddgfx_voltage_table.count <= tmp),do { if (!((data->vddgfx_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddgfx_voltage_table)); } } while (0)
402 "Too many voltage values for VDDC. Trimming to fit state table.",do { if (!((data->vddgfx_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddgfx_voltage_table)); } } while (0)
403 phm_trim_voltage_table_to_fit_state_table(tmp,do { if (!((data->vddgfx_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddgfx_voltage_table)); } } while (0)
404 &(data->vddgfx_voltage_table)))do { if (!((data->vddgfx_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDC. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddgfx_voltage_table)); } } while (0)
;
405
406 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI);
407 PP_ASSERT_WITH_CODE(do { if (!((data->vddci_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDCI. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddci_voltage_table)); } } while (0)
408 (data->vddci_voltage_table.count <= tmp),do { if (!((data->vddci_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDCI. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddci_voltage_table)); } } while (0)
409 "Too many voltage values for VDDCI. Trimming to fit state table.",do { if (!((data->vddci_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDCI. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddci_voltage_table)); } } while (0)
410 phm_trim_voltage_table_to_fit_state_table(tmp,do { if (!((data->vddci_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDCI. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddci_voltage_table)); } } while (0)
411 &(data->vddci_voltage_table)))do { if (!((data->vddci_voltage_table.count <= tmp))) {
printk("\0014" "amdgpu: " "%s\n", "Too many voltage values for VDDCI. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
vddci_voltage_table)); } } while (0)
;
412
413 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD);
414 PP_ASSERT_WITH_CODE(do { if (!((data->mvdd_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for MVDD. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
mvdd_voltage_table)); } } while (0)
415 (data->mvdd_voltage_table.count <= tmp),do { if (!((data->mvdd_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for MVDD. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
mvdd_voltage_table)); } } while (0)
416 "Too many voltage values for MVDD. Trimming to fit state table.",do { if (!((data->mvdd_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for MVDD. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
mvdd_voltage_table)); } } while (0)
417 phm_trim_voltage_table_to_fit_state_table(tmp,do { if (!((data->mvdd_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for MVDD. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
mvdd_voltage_table)); } } while (0)
418 &(data->mvdd_voltage_table)))do { if (!((data->mvdd_voltage_table.count <= tmp))) { printk
("\0014" "amdgpu: " "%s\n", "Too many voltage values for MVDD. Trimming to fit state table."
); phm_trim_voltage_table_to_fit_state_table(tmp, &(data->
mvdd_voltage_table)); } } while (0)
;
419
420 return 0;
421}
422
423/**
424 * smu7_program_static_screen_threshold_parameters - Programs static screed detection parameters
425 *
426 * @hwmgr: the address of the powerplay hardware manager.
427 * Return: always 0
428 */
429static int smu7_program_static_screen_threshold_parameters(
430 struct pp_hwmgr *hwmgr)
431{
432 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
433
434 /* Set static screen threshold unit */
435 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xf0000) | (0xf0000
& ((data->static_screen_threshold_unit) << 0x10
)))))
436 CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xf0000) | (0xf0000
& ((data->static_screen_threshold_unit) << 0x10
)))))
437 data->static_screen_threshold_unit)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xf0000) | (0xf0000
& ((data->static_screen_threshold_unit) << 0x10
)))))
;
438 /* Set static screen threshold */
439 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xffff) | (0xffff
& ((data->static_screen_threshold) << 0x0)))))
440 CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xffff) | (0xffff
& ((data->static_screen_threshold) << 0x0)))))
441 data->static_screen_threshold)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200044,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200044))) & ~0xffff) | (0xffff
& ((data->static_screen_threshold) << 0x0)))))
;
442
443 return 0;
444}
445
446/**
447 * smu7_enable_display_gap - Setup display gap for glitch free memory clock switching.
448 *
449 * @hwmgr: the address of the powerplay hardware manager.
450 * Return: always 0
451 */
452static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr)
453{
454 uint32_t display_gap =
455 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060))
456 ixCG_DISPLAY_GAP_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060))
;
457
458 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,(((display_gap) & ~0x3) | (0x3 & ((DISPLAY_GAP_IGNORE
) << 0x0)))
459 DISP_GAP, DISPLAY_GAP_IGNORE)(((display_gap) & ~0x3) | (0x3 & ((DISPLAY_GAP_IGNORE
) << 0x0)))
;
460
461 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,(((display_gap) & ~0x3000000) | (0x3000000 & ((DISPLAY_GAP_VBLANK
) << 0x18)))
462 DISP_GAP_MCHG, DISPLAY_GAP_VBLANK)(((display_gap) & ~0x3000000) | (0x3000000 & ((DISPLAY_GAP_VBLANK
) << 0x18)))
;
463
464 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060,display_gap))
465 ixCG_DISPLAY_GAP_CNTL, display_gap)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060,display_gap))
;
466
467 return 0;
468}
469
470/**
471 * smu7_program_voting_clients - Programs activity state transition voting clients
472 *
473 * @hwmgr: the address of the powerplay hardware manager.
474 * Return: always 0
475 */
476static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr)
477{
478 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
479 int i;
480
481 /* Clear reset for voting clients before enabling DPM */
482 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x20) | (0x20 &
((0) << 0x5)))))
483 SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x20) | (0x20 &
((0) << 0x5)))))
;
484 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x10) | (0x10 &
((0) << 0x4)))))
485 SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x10) | (0x10 &
((0) << 0x4)))))
;
486
487 for (i = 0; i < 8; i++)
488 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc02001a8 + i * 4,data->
voting_rights_clients[i]))
489 ixCG_FREQ_TRAN_VOTING_0 + i * 4,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc02001a8 + i * 4,data->
voting_rights_clients[i]))
490 data->voting_rights_clients[i])(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc02001a8 + i * 4,data->
voting_rights_clients[i]))
;
491 return 0;
492}
493
494static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr)
495{
496 int i;
497
498 /* Reset voting clients before disabling DPM */
499 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x20) | (0x20 &
((1) << 0x5)))))
500 SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x20) | (0x20 &
((1) << 0x5)))))
;
501 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x10) | (0x10 &
((1) << 0x4)))))
502 SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x10) | (0x10 &
((1) << 0x4)))))
;
503
504 for (i = 0; i < 8; i++)
505 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc02001a8 + i * 4,0))
506 ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc02001a8 + i * 4,0))
;
507
508 return 0;
509}
510
511/* Copy one arb setting to another and then switch the active set.
512 * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants.
513 */
514static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
515 uint32_t arb_src, uint32_t arb_dest)
516{
517 uint32_t mc_arb_dram_timing;
518 uint32_t mc_arb_dram_timing2;
519 uint32_t burst_time;
520 uint32_t mc_cg_config;
521
522 switch (arb_src) {
523 case MC_CG_ARB_FREQ_F00x0a:
524 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0x9dd))
;
525 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0x9de))
;
526 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0)((((((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xa02))) & 0x1f) >> 0x0)
;
527 break;
528 case MC_CG_ARB_FREQ_F10x0b:
529 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0x9fc))
;
530 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0x9ff))
;
531 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1)((((((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xa02))) & 0x3e0) >> 0x5)
;
532 break;
533 default:
534 return -EINVAL22;
535 }
536
537 switch (arb_dest) {
538 case MC_CG_ARB_FREQ_F00x0a:
539 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x9dd,mc_arb_dram_timing))
;
540 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x9de,mc_arb_dram_timing2))
;
541 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xa02,((((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0xa02))) & ~
0x1f) | (0x1f & ((burst_time) << 0x0)))))
;
542 break;
543 case MC_CG_ARB_FREQ_F10x0b:
544 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x9fc,mc_arb_dram_timing))
;
545 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x9ff,mc_arb_dram_timing2))
;
546 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xa02,((((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0xa02))) & ~
0x3e0) | (0x3e0 & ((burst_time) << 0x5)))))
;
547 break;
548 default:
549 return -EINVAL22;
550 }
551
552 mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0x96f))
;
553 mc_cg_config |= 0x0000000F;
554 cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x96f,mc_cg_config))
;
555 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x9fa,((((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0x9fa))) & ~
0xff) | (0xff & ((arb_dest) << 0x0)))))
;
556
557 return 0;
558}
559
560static int smu7_reset_to_default(struct pp_hwmgr *hwmgr)
561{
562 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults((uint16_t)0x84), NULL((void *)0));
563}
564
565/**
566 * smu7_initial_switch_from_arbf0_to_f1 - Initial switch from ARB F0->F1
567 *
568 * @hwmgr: the address of the powerplay hardware manager.
569 * Return: always 0
570 * This function is to be called from the SetPowerState table.
571 */
572static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
573{
574 return smu7_copy_and_switch_arb_sets(hwmgr,
575 MC_CG_ARB_FREQ_F00x0a, MC_CG_ARB_FREQ_F10x0b);
576}
577
578static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr)
579{
580 uint32_t tmp;
581
582 tmp = (cgs_read_ind_register(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x80000424))
583 CGS_IND_REG__SMC, ixSMC_SCRATCH9)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x80000424))
&
584 0x0000ff00) >> 8;
585
586 if (tmp == MC_CG_ARB_FREQ_F00x0a)
587 return 0;
588
589 return smu7_copy_and_switch_arb_sets(hwmgr,
590 tmp, MC_CG_ARB_FREQ_F00x0a);
591}
592
593static uint16_t smu7_override_pcie_speed(struct pp_hwmgr *hwmgr)
594{
595 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
596 uint16_t pcie_gen = 0;
597
598 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN40x00080000 &&
599 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN40x00000008)
600 pcie_gen = 3;
601 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN30x00040000 &&
602 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN30x00000004)
603 pcie_gen = 2;
604 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN20x00020000 &&
605 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN20x00000002)
606 pcie_gen = 1;
607 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN10x00010000 &&
608 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN10x00000001)
609 pcie_gen = 0;
610
611 return pcie_gen;
612}
613
614static uint16_t smu7_override_pcie_width(struct pp_hwmgr *hwmgr)
615{
616 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
617 uint16_t pcie_width = 0;
618
619 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X160x00200000)
620 pcie_width = 16;
621 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X120x00100000)
622 pcie_width = 12;
623 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X80x00080000)
624 pcie_width = 8;
625 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X40x00040000)
626 pcie_width = 4;
627 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X20x00020000)
628 pcie_width = 2;
629 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X10x00010000)
630 pcie_width = 1;
631
632 return pcie_width;
633}
634
635static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
636{
637 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
638
639 struct phm_ppt_v1_information *table_info =
640 (struct phm_ppt_v1_information *)(hwmgr->pptable);
641 struct phm_ppt_v1_pcie_table *pcie_table = NULL((void *)0);
642
643 uint32_t i, max_entry;
644 uint32_t tmp;
645
646 PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels ||do { if (!((data->use_pcie_performance_levels || data->
use_pcie_power_saving_levels))) { printk("\0014" "amdgpu: " "%s\n"
, "No pcie performance levels!"); return -22; } } while (0)
647 data->use_pcie_power_saving_levels), "No pcie performance levels!",do { if (!((data->use_pcie_performance_levels || data->
use_pcie_power_saving_levels))) { printk("\0014" "amdgpu: " "%s\n"
, "No pcie performance levels!"); return -22; } } while (0)
648 return -EINVAL)do { if (!((data->use_pcie_performance_levels || data->
use_pcie_power_saving_levels))) { printk("\0014" "amdgpu: " "%s\n"
, "No pcie performance levels!"); return -22; } } while (0)
;
649
650 if (table_info != NULL((void *)0))
651 pcie_table = table_info->pcie_table;
652
653 if (data->use_pcie_performance_levels &&
654 !data->use_pcie_power_saving_levels) {
655 data->pcie_gen_power_saving = data->pcie_gen_performance;
656 data->pcie_lane_power_saving = data->pcie_lane_performance;
657 } else if (!data->use_pcie_performance_levels &&
658 data->use_pcie_power_saving_levels) {
659 data->pcie_gen_performance = data->pcie_gen_power_saving;
660 data->pcie_lane_performance = data->pcie_lane_power_saving;
661 }
662 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK);
663 phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table,
664 tmp,
665 MAX_REGULAR_DPM_NUMBER8);
666
667 if (pcie_table != NULL((void *)0)) {
668 /* max_entry is used to make sure we reserve one PCIE level
669 * for boot level (fix for A+A PSPP issue).
670 * If PCIE table from PPTable have ULV entry + 8 entries,
671 * then ignore the last entry.*/
672 max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count;
673 for (i = 1; i < max_entry; i++) {
674 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1,
675 get_pcie_gen_support(data->pcie_gen_cap,
676 pcie_table->entries[i].gen_speed),
677 get_pcie_lane_support(data->pcie_lane_cap,
678 pcie_table->entries[i].lane_width));
679 }
680 data->dpm_table.pcie_speed_table.count = max_entry - 1;
681 smum_update_smc_table(hwmgr, SMU_BIF_TABLE);
682 } else {
683 /* Hardcode Pcie Table */
684 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
685 get_pcie_gen_support(data->pcie_gen_cap,
686 PP_Min_PCIEGenPP_PCIEGen1),
687 get_pcie_lane_support(data->pcie_lane_cap,
688 PP_Max_PCIELane16));
689 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
690 get_pcie_gen_support(data->pcie_gen_cap,
691 PP_Min_PCIEGenPP_PCIEGen1),
692 get_pcie_lane_support(data->pcie_lane_cap,
693 PP_Max_PCIELane16));
694 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
695 get_pcie_gen_support(data->pcie_gen_cap,
696 PP_Max_PCIEGenPP_PCIEGen3),
697 get_pcie_lane_support(data->pcie_lane_cap,
698 PP_Max_PCIELane16));
699 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
700 get_pcie_gen_support(data->pcie_gen_cap,
701 PP_Max_PCIEGenPP_PCIEGen3),
702 get_pcie_lane_support(data->pcie_lane_cap,
703 PP_Max_PCIELane16));
704 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
705 get_pcie_gen_support(data->pcie_gen_cap,
706 PP_Max_PCIEGenPP_PCIEGen3),
707 get_pcie_lane_support(data->pcie_lane_cap,
708 PP_Max_PCIELane16));
709 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
710 get_pcie_gen_support(data->pcie_gen_cap,
711 PP_Max_PCIEGenPP_PCIEGen3),
712 get_pcie_lane_support(data->pcie_lane_cap,
713 PP_Max_PCIELane16));
714
715 data->dpm_table.pcie_speed_table.count = 6;
716 }
717 /* Populate last level for boot PCIE level, but do not increment count. */
718 if (hwmgr->chip_family == AMDGPU_FAMILY_CI120) {
719 for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++)
720 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i,
721 get_pcie_gen_support(data->pcie_gen_cap,
722 PP_Max_PCIEGenPP_PCIEGen3),
723 data->vbios_boot_state.pcie_lane_bootup_value);
724 } else {
725 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
726 data->dpm_table.pcie_speed_table.count,
727 get_pcie_gen_support(data->pcie_gen_cap,
728 PP_Min_PCIEGenPP_PCIEGen1),
729 get_pcie_lane_support(data->pcie_lane_cap,
730 PP_Max_PCIELane16));
731
732 if (data->pcie_dpm_key_disabled)
733 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
734 data->dpm_table.pcie_speed_table.count,
735 smu7_override_pcie_speed(hwmgr), smu7_override_pcie_width(hwmgr));
736 }
737 return 0;
738}
739
740static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr)
741{
742 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
743
744 memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table))__builtin_memset((&(data->dpm_table)), (0x00), (sizeof
(data->dpm_table)))
;
745
746 phm_reset_single_dpm_table(
747 &data->dpm_table.sclk_table,
748 smum_get_mac_definition(hwmgr,
749 SMU_MAX_LEVELS_GRAPHICS),
750 MAX_REGULAR_DPM_NUMBER8);
751 phm_reset_single_dpm_table(
752 &data->dpm_table.mclk_table,
753 smum_get_mac_definition(hwmgr,
754 SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER8);
755
756 phm_reset_single_dpm_table(
757 &data->dpm_table.vddc_table,
758 smum_get_mac_definition(hwmgr,
759 SMU_MAX_LEVELS_VDDC),
760 MAX_REGULAR_DPM_NUMBER8);
761 phm_reset_single_dpm_table(
762 &data->dpm_table.vddci_table,
763 smum_get_mac_definition(hwmgr,
764 SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER8);
765
766 phm_reset_single_dpm_table(
767 &data->dpm_table.mvdd_table,
768 smum_get_mac_definition(hwmgr,
769 SMU_MAX_LEVELS_MVDD),
770 MAX_REGULAR_DPM_NUMBER8);
771 return 0;
772}
773/*
774 * This function is to initialize all DPM state tables
775 * for SMU7 based on the dependency table.
776 * Dynamic state patching function will then trim these
777 * state tables to the allowed range based
778 * on the power policy or external client requests,
779 * such as UVD request, etc.
780 */
781
782static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
783{
784 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
785 struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table =
786 hwmgr->dyn_state.vddc_dependency_on_sclk;
787 struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table =
788 hwmgr->dyn_state.vddc_dependency_on_mclk;
789 struct phm_cac_leakage_table *std_voltage_table =
790 hwmgr->dyn_state.cac_leakage_table;
791 uint32_t i;
792
793 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,do { if (!(allowed_vdd_sclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "SCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
794 "SCLK dependency table is missing. This table is mandatory", return -EINVAL)do { if (!(allowed_vdd_sclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "SCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
;
795 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1,do { if (!(allowed_vdd_sclk_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "SCLK dependency table has to have is missing. This table is mandatory"
); return -22; } } while (0)
796 "SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL)do { if (!(allowed_vdd_sclk_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "SCLK dependency table has to have is missing. This table is mandatory"
); return -22; } } while (0)
;
797
798 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,do { if (!(allowed_vdd_mclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
799 "MCLK dependency table is missing. This table is mandatory", return -EINVAL)do { if (!(allowed_vdd_mclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
;
800 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1,do { if (!(allowed_vdd_mclk_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VMCLK dependency table has to have is missing. This table is mandatory"
); return -22; } } while (0)
801 "VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL)do { if (!(allowed_vdd_mclk_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VMCLK dependency table has to have is missing. This table is mandatory"
); return -22; } } while (0)
;
802
803
804 /* Initialize Sclk DPM table based on allow Sclk values*/
805 data->dpm_table.sclk_table.count = 0;
806
807 for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
808 if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
809 allowed_vdd_sclk_table->entries[i].clk) {
810 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
811 allowed_vdd_sclk_table->entries[i].clk;
812 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0;
813 data->dpm_table.sclk_table.count++;
814 }
815 }
816
817 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,do { if (!(allowed_vdd_mclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
818 "MCLK dependency table is missing. This table is mandatory", return -EINVAL)do { if (!(allowed_vdd_mclk_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table is missing. This table is mandatory"
); return -22; } } while (0)
;
819 /* Initialize Mclk DPM table based on allow Mclk values */
820 data->dpm_table.mclk_table.count = 0;
821 for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
822 if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value !=
823 allowed_vdd_mclk_table->entries[i].clk) {
824 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
825 allowed_vdd_mclk_table->entries[i].clk;
826 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0;
827 data->dpm_table.mclk_table.count++;
828 }
829 }
830
831 /* Initialize Vddc DPM table based on allow Vddc values. And populate corresponding std values. */
832 for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
833 data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
834 data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage;
835 /* param1 is for corresponding std voltage */
836 data->dpm_table.vddc_table.dpm_levels[i].enabled = true1;
837 }
838
839 data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
840 allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
841
842 if (NULL((void *)0) != allowed_vdd_mclk_table) {
843 /* Initialize Vddci DPM table based on allow Mclk values */
844 for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
845 data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
846 data->dpm_table.vddci_table.dpm_levels[i].enabled = true1;
847 }
848 data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count;
849 }
850
851 allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk;
852
853 if (NULL((void *)0) != allowed_vdd_mclk_table) {
854 /*
855 * Initialize MVDD DPM table based on allow Mclk
856 * values
857 */
858 for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
859 data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
860 data->dpm_table.mvdd_table.dpm_levels[i].enabled = true1;
861 }
862 data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
863 }
864
865 return 0;
866}
867
868static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
869{
870 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
871 struct phm_ppt_v1_information *table_info =
872 (struct phm_ppt_v1_information *)(hwmgr->pptable);
873 uint32_t i;
874
875 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
876 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
877
878 if (table_info == NULL((void *)0))
879 return -EINVAL22;
880
881 dep_sclk_table = table_info->vdd_dep_on_sclk;
882 dep_mclk_table = table_info->vdd_dep_on_mclk;
883
884 PP_ASSERT_WITH_CODE(dep_sclk_table != NULL,do { if (!(dep_sclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "SCLK dependency table is missing."); return -22; } }
while (0)
885 "SCLK dependency table is missing.",do { if (!(dep_sclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "SCLK dependency table is missing."); return -22; } }
while (0)
886 return -EINVAL)do { if (!(dep_sclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "SCLK dependency table is missing."); return -22; } }
while (0)
;
887 PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1,do { if (!(dep_sclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "SCLK dependency table count is 0."); return
-22; } } while (0)
888 "SCLK dependency table count is 0.",do { if (!(dep_sclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "SCLK dependency table count is 0."); return
-22; } } while (0)
889 return -EINVAL)do { if (!(dep_sclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "SCLK dependency table count is 0."); return
-22; } } while (0)
;
890
891 PP_ASSERT_WITH_CODE(dep_mclk_table != NULL,do { if (!(dep_mclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "MCLK dependency table is missing."); return -22; } }
while (0)
892 "MCLK dependency table is missing.",do { if (!(dep_mclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "MCLK dependency table is missing."); return -22; } }
while (0)
893 return -EINVAL)do { if (!(dep_mclk_table != ((void *)0))) { printk("\0014" "amdgpu: "
"%s\n", "MCLK dependency table is missing."); return -22; } }
while (0)
;
894 PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,do { if (!(dep_mclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table count is 0"); return
-22; } } while (0)
895 "MCLK dependency table count is 0",do { if (!(dep_mclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table count is 0"); return
-22; } } while (0)
896 return -EINVAL)do { if (!(dep_mclk_table->count >= 1)) { printk("\0014"
"amdgpu: " "%s\n", "MCLK dependency table count is 0"); return
-22; } } while (0)
;
897
898 /* Initialize Sclk DPM table based on allow Sclk values */
899 data->dpm_table.sclk_table.count = 0;
900 for (i = 0; i < dep_sclk_table->count; i++) {
901 if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value !=
902 dep_sclk_table->entries[i].clk) {
903
904 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
905 dep_sclk_table->entries[i].clk;
906
907 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled =
908 (i == 0) ? true1 : false0;
909 data->dpm_table.sclk_table.count++;
910 }
911 }
912 if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
913 hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk;
914 /* Initialize Mclk DPM table based on allow Mclk values */
915 data->dpm_table.mclk_table.count = 0;
916 for (i = 0; i < dep_mclk_table->count; i++) {
917 if (i == 0 || data->dpm_table.mclk_table.dpm_levels
918 [data->dpm_table.mclk_table.count - 1].value !=
919 dep_mclk_table->entries[i].clk) {
920 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
921 dep_mclk_table->entries[i].clk;
922 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled =
923 (i == 0) ? true1 : false0;
924 data->dpm_table.mclk_table.count++;
925 }
926 }
927
928 if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
929 hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk;
930 return 0;
931}
932
933static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
934{
935 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
936 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
937 struct phm_ppt_v1_information *table_info =
938 (struct phm_ppt_v1_information *)(hwmgr->pptable);
939 uint32_t i;
940
941 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
942 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
943 struct phm_odn_performance_level *entries;
944
945 if (table_info == NULL((void *)0))
946 return -EINVAL22;
947
948 dep_sclk_table = table_info->vdd_dep_on_sclk;
949 dep_mclk_table = table_info->vdd_dep_on_mclk;
950
951 odn_table->odn_core_clock_dpm_levels.num_of_pl =
952 data->golden_dpm_table.sclk_table.count;
953 entries = odn_table->odn_core_clock_dpm_levels.entries;
954 for (i=0; i<data->golden_dpm_table.sclk_table.count; i++) {
955 entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value;
956 entries[i].enabled = true1;
957 entries[i].vddc = dep_sclk_table->entries[i].vddc;
958 }
959
960 smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table,
961 (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk));
962
963 odn_table->odn_memory_clock_dpm_levels.num_of_pl =
964 data->golden_dpm_table.mclk_table.count;
965 entries = odn_table->odn_memory_clock_dpm_levels.entries;
966 for (i=0; i<data->golden_dpm_table.mclk_table.count; i++) {
967 entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value;
968 entries[i].enabled = true1;
969 entries[i].vddc = dep_mclk_table->entries[i].vddc;
970 }
971
972 smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table,
973 (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk));
974
975 return 0;
976}
977
978static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr)
979{
980 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
981 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
982 struct phm_ppt_v1_information *table_info =
983 (struct phm_ppt_v1_information *)(hwmgr->pptable);
984 uint32_t min_vddc = 0;
985 uint32_t max_vddc = 0;
986
987 if (!table_info)
988 return;
989
990 dep_sclk_table = table_info->vdd_dep_on_sclk;
991
992 atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc);
993
994 if (min_vddc == 0 || min_vddc > 2000
995 || min_vddc > dep_sclk_table->entries[0].vddc)
996 min_vddc = dep_sclk_table->entries[0].vddc;
997
998 if (max_vddc == 0 || max_vddc > 2000
999 || max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc)
1000 max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc;
1001
1002 data->odn_dpm_table.min_vddc = min_vddc;
1003 data->odn_dpm_table.max_vddc = max_vddc;
1004}
1005
1006static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
1007{
1008 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1009 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
1010 struct phm_ppt_v1_information *table_info =
1011 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1012 uint32_t i;
1013
1014 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1015 struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
1016
1017 if (table_info == NULL((void *)0))
1018 return;
1019
1020 for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1021 if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
1022 data->dpm_table.sclk_table.dpm_levels[i].value) {
1023 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK0x00000001;
1024 break;
1025 }
1026 }
1027
1028 for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
1029 if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
1030 data->dpm_table.mclk_table.dpm_levels[i].value) {
1031 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK0x00000002;
1032 break;
1033 }
1034 }
1035
1036 dep_table = table_info->vdd_dep_on_mclk;
1037 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk);
1038
1039 for (i = 0; i < dep_table->count; i++) {
1040 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
1041 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC0x00000010 | DPMTABLE_OD_UPDATE_MCLK0x00000002;
1042 return;
1043 }
1044 }
1045
1046 dep_table = table_info->vdd_dep_on_sclk;
1047 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk);
1048 for (i = 0; i < dep_table->count; i++) {
1049 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
1050 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC0x00000010 | DPMTABLE_OD_UPDATE_SCLK0x00000001;
1051 return;
1052 }
1053 }
1054 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC0x00000010) {
1055 data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC0x00000010;
1056 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK0x00000001 | DPMTABLE_OD_UPDATE_MCLK0x00000002;
1057 }
1058}
1059
1060static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1061{
1062 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1063
1064 smu7_reset_dpm_tables(hwmgr);
1065
1066 if (hwmgr->pp_table_version == PP_TABLE_V1)
1067 smu7_setup_dpm_tables_v1(hwmgr);
1068 else if (hwmgr->pp_table_version == PP_TABLE_V0)
1069 smu7_setup_dpm_tables_v0(hwmgr);
1070
1071 smu7_setup_default_pcie_table(hwmgr);
1072
1073 /* save a copy of the default DPM table */
1074 memcpy(&(data->golden_dpm_table), &(data->dpm_table),__builtin_memcpy((&(data->golden_dpm_table)), (&(data
->dpm_table)), (sizeof(struct smu7_dpm_table)))
1075 sizeof(struct smu7_dpm_table))__builtin_memcpy((&(data->golden_dpm_table)), (&(data
->dpm_table)), (sizeof(struct smu7_dpm_table)))
;
1076
1077 /* initialize ODN table */
1078 if (hwmgr->od_enabled) {
1079 if (data->odn_dpm_table.max_vddc) {
1080 smu7_check_dpm_table_updated(hwmgr);
1081 } else {
1082 smu7_setup_voltage_range_from_vbios(hwmgr);
1083 smu7_odn_initial_default_setting(hwmgr);
1084 }
1085 }
1086 return 0;
1087}
1088
1089static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr)
1090{
1091
1092 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1093 PHM_PlatformCaps_RegulatorHot))
1094 return smum_send_msg_to_smc(hwmgr,
1095 PPSMC_MSG_EnableVRHotGPIOInterrupt((uint16_t) 0x14a),
1096 NULL((void *)0));
1097
1098 return 0;
1099}
1100
1101static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr)
1102{
1103 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x1) | (0x1 &
((0) << 0x0)))))
1104 SCLK_PWRMGT_OFF, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x1) | (0x1 &
((0) << 0x0)))))
;
1105 return 0;
1106}
1107
1108static int smu7_enable_ulv(struct pp_hwmgr *hwmgr)
1109{
1110 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1111
1112 if (data->ulv_supported)
1113 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV((uint16_t)0x62), NULL((void *)0));
1114
1115 return 0;
1116}
1117
1118static int smu7_disable_ulv(struct pp_hwmgr *hwmgr)
1119{
1120 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1121
1122 if (data->ulv_supported)
1123 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV((uint16_t)0x63), NULL((void *)0));
1124
1125 return 0;
1126}
1127
1128static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1129{
1130 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1131 PHM_PlatformCaps_SclkDeepSleep)) {
1132 if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON((uint16_t) 0x18F), NULL((void *)0)))
1133 PP_ASSERT_WITH_CODE(false,do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to enable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1134 "Attempt to enable Master Deep Sleep switch failed!",do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to enable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1135 return -EINVAL)do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to enable Master Deep Sleep switch failed!"
); return -22; } } while (0)
;
1136 } else {
1137 if (smum_send_msg_to_smc(hwmgr,
1138 PPSMC_MSG_MASTER_DeepSleep_OFF((uint16_t) 0x190),
1139 NULL((void *)0))) {
1140 PP_ASSERT_WITH_CODE(false,do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1141 "Attempt to disable Master Deep Sleep switch failed!",do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1142 return -EINVAL)do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
;
1143 }
1144 }
1145
1146 return 0;
1147}
1148
1149static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1150{
1151 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1152 PHM_PlatformCaps_SclkDeepSleep)) {
1153 if (smum_send_msg_to_smc(hwmgr,
1154 PPSMC_MSG_MASTER_DeepSleep_OFF((uint16_t) 0x190),
1155 NULL((void *)0))) {
1156 PP_ASSERT_WITH_CODE(false,do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1157 "Attempt to disable Master Deep Sleep switch failed!",do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
1158 return -EINVAL)do { if (!(0)) { printk("\0014" "amdgpu: " "%s\n", "Attempt to disable Master Deep Sleep switch failed!"
); return -22; } } while (0)
;
1159 }
1160 }
1161
1162 return 0;
1163}
1164
1165static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr)
1166{
1167 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1168 uint32_t soft_register_value = 0;
1169 uint32_t handshake_disables_offset = data->soft_regs_start
1170 + smum_get_offsetof(hwmgr,
1171 SMU_SoftRegisters, HandshakeDisables);
1172
1173 soft_register_value = cgs_read_ind_register(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset)
)
1174 CGS_IND_REG__SMC, handshake_disables_offset)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset)
)
;
1175 soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE0x00020000;
1176 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset,
soft_register_value))
1177 handshake_disables_offset, soft_register_value)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset,
soft_register_value))
;
1178 return 0;
1179}
1180
1181static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr)
1182{
1183 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1184 uint32_t soft_register_value = 0;
1185 uint32_t handshake_disables_offset = data->soft_regs_start
1186 + smum_get_offsetof(hwmgr,
1187 SMU_SoftRegisters, HandshakeDisables);
1188
1189 soft_register_value = cgs_read_ind_register(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset)
)
1190 CGS_IND_REG__SMC, handshake_disables_offset)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset)
)
;
1191 soft_register_value |= smum_get_mac_definition(hwmgr,
1192 SMU_UVD_MCLK_HANDSHAKE_DISABLE);
1193 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset,
soft_register_value))
1194 handshake_disables_offset, soft_register_value)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,handshake_disables_offset,
soft_register_value))
;
1195 return 0;
1196}
1197
1198static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1199{
1200 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1201
1202 /* enable SCLK dpm */
1203 if (!data->sclk_dpm_key_disabled) {
1204 if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1205 hwmgr->chip_id <= CHIP_VEGAM)
1206 smu7_disable_sclk_vce_handshake(hwmgr);
1207
1208 PP_ASSERT_WITH_CODE(do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x14e
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable SCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1209 (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)),do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x14e
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable SCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1210 "Failed to enable SCLK DPM during DPM Start Function!",do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x14e
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable SCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1211 return -EINVAL)do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x14e
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable SCLK DPM during DPM Start Function!"
); return -22; } } while (0)
;
1212 }
1213
1214 /* enable MCLK dpm */
1215 if (0 == data->mclk_dpm_key_disabled) {
1216 if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK))
1217 smu7_disable_handshake_uvd(hwmgr);
1218
1219 PP_ASSERT_WITH_CODE(do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1220 (0 == smum_send_msg_to_smc(hwmgr,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1221 PPSMC_MSG_MCLKDPM_Enable,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1222 NULL)),do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1223 "Failed to enable MCLK DPM during DPM Start Function!",do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
1224 return -EINVAL)do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x150
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable MCLK DPM during DPM Start Function!"
); return -22; } } while (0)
;
1225
1226 if ((hwmgr->chip_family == AMDGPU_FAMILY_CI120) ||
1227 (hwmgr->chip_id == CHIP_POLARIS10) ||
1228 (hwmgr->chip_id == CHIP_POLARIS11) ||
1229 (hwmgr->chip_id == CHIP_POLARIS12) ||
1230 (hwmgr->chip_id == CHIP_TONGA) ||
1231 (hwmgr->chip_id == CHIP_TOPAZ))
1232 PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xd80,((((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0xd80))) & ~
0x80000000) | (0x80000000 & ((0x1) << 0x1f)))))
;
1233
1234
1235 if (hwmgr->chip_family == AMDGPU_FAMILY_CI120) {
1236 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d30,0x5))
;
1237 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d3c,0x5))
;
1238 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d80,0x100005))
;
1239 udelay(10);
1240 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d30,0x400005))
;
1241 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d3c,0x400005))
;
1242 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400d80,0x500005))
;
1243 } else {
1244 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400130,0x5))
;
1245 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc040013c,0x5))
;
1246 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400160,0x100005))
;
1247 udelay(10);
1248 if (hwmgr->chip_id == CHIP_VEGAM) {
1249 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400130,0x400009))
;
1250 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc040013c,0x400009))
;
1251 } else {
1252 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400130,0x400005))
;
1253 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc040013c,0x400005))
;
1254 }
1255 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0400160,0x500005))
;
1256 }
1257 }
1258
1259 return 0;
1260}
1261
1262static int smu7_start_dpm(struct pp_hwmgr *hwmgr)
1263{
1264 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1265
1266 /*enable general power management */
1267
1268 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x1) | (0x1 &
((1) << 0x0)))))
1269 GLOBAL_PWRMGT_EN, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x1) | (0x1 &
((1) << 0x0)))))
;
1270
1271 /* enable sclk deep sleep */
1272
1273 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x200000) | (0x200000
& ((1) << 0x15)))))
1274 DYNAMIC_PM_EN, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x200000) | (0x200000
& ((1) << 0x15)))))
;
1275
1276 /* prepare for PCIE DPM */
1277
1278 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VoltageChangeTimeout
),0x1000))
1279 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VoltageChangeTimeout
),0x1000))
1280 smum_get_offsetof(hwmgr, SMU_SoftRegisters,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VoltageChangeTimeout
),0x1000))
1281 VoltageChangeTimeout), 0x1000)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VoltageChangeTimeout
),0x1000))
;
1282 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x1400103,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__PCIE,0x1400103))) & ~0x40) | (0x40 &
((0x0) << 0x6)))))
1283 SWRST_COMMAND_1, RESETLC, 0x0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__PCIE,0x1400103,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__PCIE,0x1400103))) & ~0x40) | (0x40 &
((0x0) << 0x6)))))
;
1284
1285 if (hwmgr->chip_family == AMDGPU_FAMILY_CI120)
1286 cgs_write_register(hwmgr->device, 0x1488,(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x1488,((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0x1488)) & ~
0x1)))
1287 (cgs_read_register(hwmgr->device, 0x1488) & ~0x1))(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0x1488,((((struct cgs_device *)hwmgr->device
)->ops->read_register(hwmgr->device,0x1488)) & ~
0x1)))
;
1288
1289 if (smu7_enable_sclk_mclk_dpm(hwmgr)) {
1290 pr_err("Failed to enable Sclk DPM and Mclk DPM!")printk("\0013" "amdgpu: " "Failed to enable Sclk DPM and Mclk DPM!"
)
;
1291 return -EINVAL22;
1292 }
1293
1294 /* enable PCIE dpm */
1295 if (0 == data->pcie_dpm_key_disabled) {
1296 PP_ASSERT_WITH_CODE(do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1297 (0 == smum_send_msg_to_smc(hwmgr,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1298 PPSMC_MSG_PCIeDPM_Enable,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1299 NULL)),do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1300 "Failed to enable pcie DPM during DPM Start Function!",do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1301 return -EINVAL)do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x136
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
;
1302 } else {
1303 PP_ASSERT_WITH_CODE(do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1304 (0 == smum_send_msg_to_smc(hwmgr,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1305 PPSMC_MSG_PCIeDPM_Disable,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1306 NULL)),do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1307 "Failed to disable pcie DPM during DPM Start Function!",do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
1308 return -EINVAL)do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Start Function!"
); return -22; } } while (0)
;
1309 }
1310
1311 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1312 PHM_PlatformCaps_Falcon_QuickTransition)) {
1313 PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x149
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AC DC GPIO Interrupt!"
); ; } } while (0)
1314 PPSMC_MSG_EnableACDCGPIOInterrupt,do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x149
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AC DC GPIO Interrupt!"
); ; } } while (0)
1315 NULL)),do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x149
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AC DC GPIO Interrupt!"
); ; } } while (0)
1316 "Failed to enable AC DC GPIO Interrupt!",do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x149
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AC DC GPIO Interrupt!"
); ; } } while (0)
1317 )do { if (!((0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x149
), ((void *)0))))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AC DC GPIO Interrupt!"
); ; } } while (0)
;
1318 }
1319
1320 return 0;
1321}
1322
1323static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1324{
1325 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1326
1327 /* disable SCLK dpm */
1328 if (!data->sclk_dpm_key_disabled) {
1329 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable SCLK DPM when DPM is disabled"
); return 0; } } while (0)
1330 "Trying to disable SCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable SCLK DPM when DPM is disabled"
); return 0; } } while (0)
1331 return 0)do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable SCLK DPM when DPM is disabled"
); return 0; } } while (0)
;
1332 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable((uint16_t) 0x14f), NULL((void *)0));
1333 }
1334
1335 /* disable MCLK dpm */
1336 if (!data->mclk_dpm_key_disabled) {
1337 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable MCLK DPM when DPM is disabled"
); return 0; } } while (0)
1338 "Trying to disable MCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable MCLK DPM when DPM is disabled"
); return 0; } } while (0)
1339 return 0)do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable MCLK DPM when DPM is disabled"
); return 0; } } while (0)
;
1340 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable((uint16_t) 0x151), NULL((void *)0));
1341 }
1342
1343 return 0;
1344}
1345
1346static int smu7_stop_dpm(struct pp_hwmgr *hwmgr)
1347{
1348 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1349
1350 /* disable general power management */
1351 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x1) | (0x1 &
((0) << 0x0)))))
1352 GLOBAL_PWRMGT_EN, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x1) | (0x1 &
((0) << 0x0)))))
;
1353 /* disable sclk deep sleep */
1354 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x200000) | (0x200000
& ((0) << 0x15)))))
1355 DYNAMIC_PM_EN, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200008,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200008))) & ~0x200000) | (0x200000
& ((0) << 0x15)))))
;
1356
1357 /* disable PCIE dpm */
1358 if (!data->pcie_dpm_key_disabled) {
1359 PP_ASSERT_WITH_CODE(do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
1360 (smum_send_msg_to_smc(hwmgr,do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
1361 PPSMC_MSG_PCIeDPM_Disable,do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
1362 NULL) == 0),do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
1363 "Failed to disable pcie DPM during DPM Stop Function!",do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
1364 return -EINVAL)do { if (!((smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x13d), (
(void *)0)) == 0))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable pcie DPM during DPM Stop Function!"
); return -22; } } while (0)
;
1365 }
1366
1367 smu7_disable_sclk_mclk_dpm(hwmgr);
1368
1369 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable voltage DPM when DPM is disabled"
); return 0; } } while (0)
1370 "Trying to disable voltage DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable voltage DPM when DPM is disabled"
); return 0; } } while (0)
1371 return 0)do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to disable voltage DPM when DPM is disabled"
); return 0; } } while (0)
;
1372
1373 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable((uint16_t) 0x135), NULL((void *)0));
1374
1375 return 0;
1376}
1377
1378static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources)
1379{
1380 bool_Bool protection;
1381 enum DPM_EVENT_SRC src;
1382
1383 switch (sources) {
1384 default:
1385 pr_err("Unknown throttling event sources.")printk("\0013" "amdgpu: " "Unknown throttling event sources."
)
;
1386 fallthroughdo {} while (0);
1387 case 0:
1388 protection = false0;
1389 /* src is unused */
1390 break;
1391 case (1 << PHM_AutoThrottleSource_Thermal):
1392 protection = true1;
1393 src = DPM_EVENT_SRC_DIGITAL;
1394 break;
1395 case (1 << PHM_AutoThrottleSource_External):
1396 protection = true1;
1397 src = DPM_EVENT_SRC_EXTERNAL;
1398 break;
1399 case (1 << PHM_AutoThrottleSource_External) |
1400 (1 << PHM_AutoThrottleSource_Thermal):
1401 protection = true1;
1402 src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
1403 break;
1404 }
1405 /* Order matters - don't enable thermal protection for the wrong source. */
1406 if (protection) {
1407 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0300004,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0300004))) & ~0x7) | (0x7 &
((src) << 0x0)))))
1408 DPM_EVENT_SRC, src)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0300004,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0300004))) & ~0x7) | (0x7 &
((src) << 0x0)))))
;
1409 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps
, PHM_PlatformCaps_ThermalController)) << 0x2)))))
1410 THERMAL_PROTECTION_DIS,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps
, PHM_PlatformCaps_ThermalController)) << 0x2)))))
1411 !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps
, PHM_PlatformCaps_ThermalController)) << 0x2)))))
1412 PHM_PlatformCaps_ThermalController))(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps
, PHM_PlatformCaps_ThermalController)) << 0x2)))))
;
1413 } else
1414 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((1) << 0x2)))))
1415 THERMAL_PROTECTION_DIS, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((1) << 0x2)))))
;
1416}
1417
1418static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1419 PHM_AutoThrottleSource source)
1420{
1421 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1422
1423 if (!(data->active_auto_throttle_sources & (1 << source))) {
1424 data->active_auto_throttle_sources |= 1 << source;
1425 smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1426 }
1427 return 0;
1428}
1429
1430static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1431{
1432 return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1433}
1434
1435static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1436 PHM_AutoThrottleSource source)
1437{
1438 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1439
1440 if (data->active_auto_throttle_sources & (1 << source)) {
1441 data->active_auto_throttle_sources &= ~(1 << source);
1442 smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1443 }
1444 return 0;
1445}
1446
1447static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1448{
1449 return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1450}
1451
1452static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
1453{
1454 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1455 data->pcie_performance_request = true1;
1456
1457 return 0;
1458}
1459
1460static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr,
1461 uint32_t *cac_config_regs,
1462 AtomCtrl_EDCLeakgeTable *edc_leakage_table)
1463{
1464 uint32_t data, i = 0;
1465
1466 while (cac_config_regs[i] != 0xFFFFFFFF) {
1467 data = edc_leakage_table->DIDT_REG[i];
1468 cgs_write_ind_register(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__DIDT,cac_config_regs[i],data))
1469 CGS_IND_REG__DIDT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__DIDT,cac_config_regs[i],data))
1470 cac_config_regs[i],(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__DIDT,cac_config_regs[i],data))
1471 data)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__DIDT,cac_config_regs[i],data))
;
1472 i++;
1473 }
1474
1475 return 0;
1476}
1477
1478static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr)
1479{
1480 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1481 int ret = 0;
1482
1483 if (!data->disable_edc_leakage_controller &&
1484 data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
1485 data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
1486 ret = smu7_program_edc_didt_registers(hwmgr,
1487 DIDTEDCConfig_P12,
1488 &data->edc_leakage_table);
1489 if (ret)
1490 return ret;
1491
1492 ret = smum_send_msg_to_smc(hwmgr,
1493 (PPSMC_Msg)PPSMC_MSG_EnableEDCController((uint16_t) 0x316),
1494 NULL((void *)0));
1495 } else {
1496 ret = smum_send_msg_to_smc(hwmgr,
1497 (PPSMC_Msg)PPSMC_MSG_DisableEDCController((uint16_t) 0x317),
1498 NULL((void *)0));
1499 }
1500
1501 return ret;
1502}
1503
1504static void smu7_populate_umdpstate_clocks(struct pp_hwmgr *hwmgr)
1505{
1506 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1507 struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table;
1508 int32_t tmp_sclk, count, percentage;
1509
1510 if (golden_dpm_table->mclk_table.count == 1) {
1511 percentage = 70;
1512 hwmgr->pstate_mclk = golden_dpm_table->mclk_table.dpm_levels[0].value;
1513 } else {
1514 percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value /
1515 golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
1516 hwmgr->pstate_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value;
1517 }
1518
1519 tmp_sclk = hwmgr->pstate_mclk * percentage / 100;
1520
1521 if (hwmgr->pp_table_version == PP_TABLE_V0) {
1522 struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk =
1523 hwmgr->dyn_state.vddc_dependency_on_sclk;
1524
1525 for (count = vddc_dependency_on_sclk->count - 1; count >= 0; count--) {
1526 if (tmp_sclk >= vddc_dependency_on_sclk->entries[count].clk) {
1527 hwmgr->pstate_sclk = vddc_dependency_on_sclk->entries[count].clk;
1528 break;
1529 }
1530 }
1531 if (count < 0)
1532 hwmgr->pstate_sclk = vddc_dependency_on_sclk->entries[0].clk;
1533
1534 hwmgr->pstate_sclk_peak =
1535 vddc_dependency_on_sclk->entries[vddc_dependency_on_sclk->count - 1].clk;
1536 } else if (hwmgr->pp_table_version == PP_TABLE_V1) {
1537 struct phm_ppt_v1_information *table_info =
1538 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1539 struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk =
1540 table_info->vdd_dep_on_sclk;
1541
1542 for (count = vdd_dep_on_sclk->count - 1; count >= 0; count--) {
1543 if (tmp_sclk >= vdd_dep_on_sclk->entries[count].clk) {
1544 hwmgr->pstate_sclk = vdd_dep_on_sclk->entries[count].clk;
1545 break;
1546 }
1547 }
1548 if (count < 0)
1549 hwmgr->pstate_sclk = vdd_dep_on_sclk->entries[0].clk;
1550
1551 hwmgr->pstate_sclk_peak =
1552 vdd_dep_on_sclk->entries[vdd_dep_on_sclk->count - 1].clk;
1553 }
1554
1555 hwmgr->pstate_mclk_peak =
1556 golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
1557
1558 /* make sure the output is in Mhz */
1559 hwmgr->pstate_sclk /= 100;
1560 hwmgr->pstate_mclk /= 100;
1561 hwmgr->pstate_sclk_peak /= 100;
1562 hwmgr->pstate_mclk_peak /= 100;
1563}
1564
1565static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1566{
1567 int tmp_result = 0;
1568 int result = 0;
1569
1570 if (smu7_voltage_control(hwmgr)) {
1571 tmp_result = smu7_enable_voltage_control(hwmgr);
1572 PP_ASSERT_WITH_CODE(tmp_result == 0,do { if (!(tmp_result == 0)) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable voltage control!"); result = tmp_result; }
} while (0)
1573 "Failed to enable voltage control!",do { if (!(tmp_result == 0)) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable voltage control!"); result = tmp_result; }
} while (0)
1574 result = tmp_result)do { if (!(tmp_result == 0)) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable voltage control!"); result = tmp_result; }
} while (0)
;
1575
1576 tmp_result = smu7_construct_voltage_tables(hwmgr);
1577 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to construct voltage tables!"); result = tmp_result
; } } while (0)
1578 "Failed to construct voltage tables!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to construct voltage tables!"); result = tmp_result
; } } while (0)
1579 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to construct voltage tables!"); result = tmp_result
; } } while (0)
;
1580 }
1581 smum_initialize_mc_reg_table(hwmgr);
1582
1583 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1584 PHM_PlatformCaps_EngineSpreadSpectrumSupport))
1585 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x800000) | (0x800000
& ((1) << 0x17)))))
1586 GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x800000) | (0x800000
& ((1) << 0x17)))))
;
1587
1588 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1589 PHM_PlatformCaps_ThermalController))
1590 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((0) << 0x2)))))
1591 GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((0) << 0x2)))))
;
1592
1593 tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr);
1594 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to program static screen threshold parameters!"); result
= tmp_result; } } while (0)
1595 "Failed to program static screen threshold parameters!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to program static screen threshold parameters!"); result
= tmp_result; } } while (0)
1596 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to program static screen threshold parameters!"); result
= tmp_result; } } while (0)
;
1597
1598 tmp_result = smu7_enable_display_gap(hwmgr);
1599 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable display gap!"); result = tmp_result; } } while
(0)
1600 "Failed to enable display gap!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable display gap!"); result = tmp_result; } } while
(0)
;
1601
1602 tmp_result = smu7_program_voting_clients(hwmgr);
1603 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to program voting clients!"); result = tmp_result; }
} while (0)
1604 "Failed to program voting clients!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to program voting clients!"); result = tmp_result; }
} while (0)
;
1605
1606 tmp_result = smum_process_firmware_header(hwmgr);
1607 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to process firmware header!"); result = tmp_result;
} } while (0)
1608 "Failed to process firmware header!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to process firmware header!"); result = tmp_result;
} } while (0)
;
1609
1610 if (hwmgr->chip_id != CHIP_VEGAM) {
1611 tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr);
1612 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to initialize switch from ArbF0 to F1!"); result = tmp_result
; } } while (0)
1613 "Failed to initialize switch from ArbF0 to F1!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to initialize switch from ArbF0 to F1!"); result = tmp_result
; } } while (0)
1614 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to initialize switch from ArbF0 to F1!"); result = tmp_result
; } } while (0)
;
1615 }
1616
1617 result = smu7_setup_default_dpm_tables(hwmgr);
1618 PP_ASSERT_WITH_CODE(0 == result,do { if (!(0 == result)) { printk("\0014" "amdgpu: " "%s\n", "Failed to setup default DPM tables!"
); return result; } } while (0)
1619 "Failed to setup default DPM tables!", return result)do { if (!(0 == result)) { printk("\0014" "amdgpu: " "%s\n", "Failed to setup default DPM tables!"
); return result; } } while (0)
;
1620
1621 tmp_result = smum_init_smc_table(hwmgr);
1622 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to initialize SMC table!"); result = tmp_result; } }
while (0)
1623 "Failed to initialize SMC table!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to initialize SMC table!"); result = tmp_result; } }
while (0)
;
1624
1625 tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr);
1626 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable VR hot GPIO interrupt!"); result = tmp_result
; } } while (0)
1627 "Failed to enable VR hot GPIO interrupt!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable VR hot GPIO interrupt!"); result = tmp_result
; } } while (0)
;
1628
1629 if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1630 hwmgr->chip_id <= CHIP_VEGAM) {
1631 tmp_result = smu7_notify_has_display(hwmgr);
1632 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable display setting!"); result = tmp_result; }
} while (0)
1633 "Failed to enable display setting!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable display setting!"); result = tmp_result; }
} while (0)
;
1634 } else {
1635 smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay((uint16_t)0x5D), NULL((void *)0));
1636 }
1637
1638 if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1639 hwmgr->chip_id <= CHIP_VEGAM) {
1640 tmp_result = smu7_populate_edc_leakage_registers(hwmgr);
1641 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate edc leakage registers!"); result = tmp_result
; } } while (0)
1642 "Failed to populate edc leakage registers!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate edc leakage registers!"); result = tmp_result
; } } while (0)
;
1643 }
1644
1645 tmp_result = smu7_enable_sclk_control(hwmgr);
1646 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable SCLK control!"); result = tmp_result; } }
while (0)
1647 "Failed to enable SCLK control!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable SCLK control!"); result = tmp_result; } }
while (0)
;
1648
1649 tmp_result = smu7_enable_smc_voltage_controller(hwmgr);
1650 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable voltage control!"); result = tmp_result; }
} while (0)
1651 "Failed to enable voltage control!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable voltage control!"); result = tmp_result; }
} while (0)
;
1652
1653 tmp_result = smu7_enable_ulv(hwmgr);
1654 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable ULV!"); result = tmp_result; } } while (0
)
1655 "Failed to enable ULV!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable ULV!"); result = tmp_result; } } while (0
)
;
1656
1657 tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr);
1658 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable deep sleep master switch!"); result = tmp_result
; } } while (0)
1659 "Failed to enable deep sleep master switch!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable deep sleep master switch!"); result = tmp_result
; } } while (0)
;
1660
1661 tmp_result = smu7_enable_didt_config(hwmgr);
1662 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable deep sleep master switch!"); result = tmp_result
; } } while (0)
1663 "Failed to enable deep sleep master switch!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable deep sleep master switch!"); result = tmp_result
; } } while (0)
;
1664
1665 tmp_result = smu7_start_dpm(hwmgr);
1666 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to start DPM!"); result = tmp_result; } } while (0)
1667 "Failed to start DPM!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to start DPM!"); result = tmp_result; } } while (0)
;
1668
1669 tmp_result = smu7_enable_smc_cac(hwmgr);
1670 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable SMC CAC!"); result = tmp_result; } } while
(0)
1671 "Failed to enable SMC CAC!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable SMC CAC!"); result = tmp_result; } } while
(0)
;
1672
1673 tmp_result = smu7_enable_power_containment(hwmgr);
1674 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable power containment!"); result = tmp_result
; } } while (0)
1675 "Failed to enable power containment!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable power containment!"); result = tmp_result
; } } while (0)
;
1676
1677 tmp_result = smu7_power_control_set_level(hwmgr);
1678 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to power control set level!"); result = tmp_result;
} } while (0)
1679 "Failed to power control set level!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to power control set level!"); result = tmp_result;
} } while (0)
;
1680
1681 tmp_result = smu7_enable_thermal_auto_throttle(hwmgr);
1682 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable thermal auto throttle!"); result = tmp_result
; } } while (0)
1683 "Failed to enable thermal auto throttle!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable thermal auto throttle!"); result = tmp_result
; } } while (0)
;
1684
1685 tmp_result = smu7_pcie_performance_request(hwmgr);
1686 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "pcie performance request failed!"); result = tmp_result; }
} while (0)
1687 "pcie performance request failed!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "pcie performance request failed!"); result = tmp_result; }
} while (0)
;
1688
1689 smu7_populate_umdpstate_clocks(hwmgr);
1690
1691 return 0;
1692}
1693
1694static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool_Bool enable)
1695{
1696 if (!hwmgr->avfs_supported)
1697 return 0;
1698
1699 if (enable) {
1700 if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3f010))) & 0x10000) >>
0x10)
1701 CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3f010))) & 0x10000) >>
0x10)
) {
1702 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26A), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AVFS!"
); return -22; } } while (0)
1703 hwmgr, PPSMC_MSG_EnableAvfs, NULL),do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26A), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AVFS!"
); return -22; } } while (0)
1704 "Failed to enable AVFS!",do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26A), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AVFS!"
); return -22; } } while (0)
1705 return -EINVAL)do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26A), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to enable AVFS!"
); return -22; } } while (0)
;
1706 }
1707 } else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3f010))) & 0x10000) >>
0x10)
1708 CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3f010))) & 0x10000) >>
0x10)
) {
1709 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26B), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable AVFS!"
); return -22; } } while (0)
1710 hwmgr, PPSMC_MSG_DisableAvfs, NULL),do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26B), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable AVFS!"
); return -22; } } while (0)
1711 "Failed to disable AVFS!",do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26B), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable AVFS!"
); return -22; } } while (0)
1712 return -EINVAL)do { if (!(!smum_send_msg_to_smc( hwmgr, ((uint16_t) 0x26B), (
(void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to disable AVFS!"
); return -22; } } while (0)
;
1713 }
1714
1715 return 0;
1716}
1717
1718static int smu7_update_avfs(struct pp_hwmgr *hwmgr)
1719{
1720 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1721
1722 if (!hwmgr->avfs_supported)
1723 return 0;
1724
1725 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC0x00000010) {
1726 smu7_avfs_control(hwmgr, false0);
1727 } else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK0x00000001) {
1728 smu7_avfs_control(hwmgr, false0);
1729 smu7_avfs_control(hwmgr, true1);
1730 } else {
1731 smu7_avfs_control(hwmgr, true1);
1732 }
1733
1734 return 0;
1735}
1736
1737static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
1738{
1739 int tmp_result, result = 0;
1740
1741 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1742 PHM_PlatformCaps_ThermalController))
1743 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((1) << 0x2)))))
1744 GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x4) | (0x4 &
((1) << 0x2)))))
;
1745
1746 tmp_result = smu7_disable_power_containment(hwmgr);
1747 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable power containment!"); result = tmp_result
; } } while (0)
1748 "Failed to disable power containment!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable power containment!"); result = tmp_result
; } } while (0)
;
1749
1750 tmp_result = smu7_disable_smc_cac(hwmgr);
1751 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable SMC CAC!"); result = tmp_result; } } while
(0)
1752 "Failed to disable SMC CAC!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable SMC CAC!"); result = tmp_result; } } while
(0)
;
1753
1754 tmp_result = smu7_disable_didt_config(hwmgr);
1755 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable DIDT!"); result = tmp_result; } } while (
0)
1756 "Failed to disable DIDT!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable DIDT!"); result = tmp_result; } } while (
0)
;
1757
1758 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500164,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0500164))) & ~0x1) | (0x1 &
((0) << 0x0)))))
1759 CG_SPLL_SPREAD_SPECTRUM, SSEN, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500164,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0500164))) & ~0x1) | (0x1 &
((0) << 0x0)))))
;
1760 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x800000) | (0x800000
& ((0) << 0x17)))))
1761 GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x800000) | (0x800000
& ((0) << 0x17)))))
;
1762
1763 tmp_result = smu7_disable_thermal_auto_throttle(hwmgr);
1764 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable thermal auto throttle!"); result = tmp_result
; } } while (0)
1765 "Failed to disable thermal auto throttle!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable thermal auto throttle!"); result = tmp_result
; } } while (0)
;
1766
1767 tmp_result = smu7_avfs_control(hwmgr, false0);
1768 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable AVFS!"); result = tmp_result; } } while (
0)
1769 "Failed to disable AVFS!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable AVFS!"); result = tmp_result; } } while (
0)
;
1770
1771 tmp_result = smu7_stop_dpm(hwmgr);
1772 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to stop DPM!"); result = tmp_result; } } while (0)
1773 "Failed to stop DPM!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to stop DPM!"); result = tmp_result; } } while (0)
;
1774
1775 tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr);
1776 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable deep sleep master switch!"); result = tmp_result
; } } while (0)
1777 "Failed to disable deep sleep master switch!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable deep sleep master switch!"); result = tmp_result
; } } while (0)
;
1778
1779 tmp_result = smu7_disable_ulv(hwmgr);
1780 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable ULV!"); result = tmp_result; } } while (
0)
1781 "Failed to disable ULV!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to disable ULV!"); result = tmp_result; } } while (
0)
;
1782
1783 tmp_result = smu7_clear_voting_clients(hwmgr);
1784 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to clear voting clients!"); result = tmp_result; } }
while (0)
1785 "Failed to clear voting clients!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to clear voting clients!"); result = tmp_result; } }
while (0)
;
1786
1787 tmp_result = smu7_reset_to_default(hwmgr);
1788 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to reset to default!"); result = tmp_result; } } while
(0)
1789 "Failed to reset to default!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to reset to default!"); result = tmp_result; } } while
(0)
;
1790
1791 tmp_result = smum_stop_smc(hwmgr);
1792 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to stop smc!"); result = tmp_result; } } while (0)
1793 "Failed to stop smc!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to stop smc!"); result = tmp_result; } } while (0)
;
1794
1795 tmp_result = smu7_force_switch_to_arbf0(hwmgr);
1796 PP_ASSERT_WITH_CODE((tmp_result == 0),do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to force to switch arbf0!"); result = tmp_result; }
} while (0)
1797 "Failed to force to switch arbf0!", result = tmp_result)do { if (!((tmp_result == 0))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to force to switch arbf0!"); result = tmp_result; }
} while (0)
;
1798
1799 return result;
1800}
1801
1802static bool_Bool intel_core_rkl_chk(void)
1803{
1804#if IS_ENABLED(CONFIG_X86_64)1
1805 struct cpu_info *ci = curcpu()({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})
;
1806
1807 return (ci->ci_family == 6 && ci->ci_model == 0xa7);
1808#else
1809 return false0;
1810#endif
1811}
1812
1813static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
1814{
1815 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1816 struct phm_ppt_v1_information *table_info =
1817 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1818 struct amdgpu_device *adev = hwmgr->adev;
1819 uint8_t tmp1, tmp2;
1820 uint16_t tmp3 = 0;
1821
1822 data->dll_default_on = false0;
1823 data->mclk_dpm0_activity_target = 0xa;
1824 data->vddc_vddgfx_delta = 300;
1825 data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT0x00C8;
1826 data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT0;
1827 data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT00x3FFFC102;
1828 data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT10x000400;
1829 data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT20xC00080;
1830 data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT30xC00200;
1831 data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT40xC01680;
1832 data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT50xC00033;
1833 data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT60xC00033;
1834 data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT70x3FFFC000;
1835
1836 data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false0 : true1;
1837 data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false0 : true1;
1838 data->pcie_dpm_key_disabled =
1839 intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
1840 /* need to set voltage control types before EVV patching */
1841 data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE0x0;
1842 data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE0x0;
1843 data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE0x0;
1844 data->enable_tdc_limit_feature = true1;
1845 data->enable_pkg_pwr_tracking_feature = true1;
1846 data->force_pcie_gen = PP_PCIEGenInvalid0xffff;
1847 data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true1 : false0;
1848 data->current_profile_setting.bupdate_sclk = 1;
1849 data->current_profile_setting.sclk_up_hyst = 0;
1850 data->current_profile_setting.sclk_down_hyst = 100;
1851 data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT30;
1852 data->current_profile_setting.bupdate_mclk = 1;
1853 if (hwmgr->chip_id >= CHIP_POLARIS10) {
1854 if (adev->gmc.vram_width == 256) {
1855 data->current_profile_setting.mclk_up_hyst = 10;
1856 data->current_profile_setting.mclk_down_hyst = 60;
1857 data->current_profile_setting.mclk_activity = 25;
1858 } else if (adev->gmc.vram_width == 128) {
1859 data->current_profile_setting.mclk_up_hyst = 5;
1860 data->current_profile_setting.mclk_down_hyst = 16;
1861 data->current_profile_setting.mclk_activity = 20;
1862 } else if (adev->gmc.vram_width == 64) {
1863 data->current_profile_setting.mclk_up_hyst = 3;
1864 data->current_profile_setting.mclk_down_hyst = 16;
1865 data->current_profile_setting.mclk_activity = 20;
1866 }
1867 } else {
1868 data->current_profile_setting.mclk_up_hyst = 0;
1869 data->current_profile_setting.mclk_down_hyst = 100;
1870 data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT10;
1871 }
1872 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
1873 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1874 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1875
1876 if (hwmgr->chip_id == CHIP_HAWAII) {
1877 data->thermal_temp_setting.temperature_low = 94500;
1878 data->thermal_temp_setting.temperature_high = 95000;
1879 data->thermal_temp_setting.temperature_shutdown = 104000;
1880 } else {
1881 data->thermal_temp_setting.temperature_low = 99500;
1882 data->thermal_temp_setting.temperature_high = 100000;
1883 data->thermal_temp_setting.temperature_shutdown = 104000;
1884 }
1885
1886 data->fast_watermark_threshold = 100;
1887 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1888 VOLTAGE_TYPE_VDDC1, VOLTAGE_OBJ_SVID27))
1889 data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID20x2;
1890 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1891 VOLTAGE_TYPE_VDDC1, VOLTAGE_OBJ_GPIO_LUT0))
1892 data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO0x1;
1893
1894 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1895 PHM_PlatformCaps_ControlVDDGFX)) {
1896 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1897 VOLTAGE_TYPE_VDDGFX5, VOLTAGE_OBJ_SVID27)) {
1898 data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID20x2;
1899 }
1900 }
1901
1902 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1903 PHM_PlatformCaps_EnableMVDDControl)) {
1904 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1905 VOLTAGE_TYPE_MVDDC2, VOLTAGE_OBJ_GPIO_LUT0))
1906 data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO0x1;
1907 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1908 VOLTAGE_TYPE_MVDDC2, VOLTAGE_OBJ_SVID27))
1909 data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID20x2;
1910 }
1911
1912 if (SMU7_VOLTAGE_CONTROL_NONE0x0 == data->vdd_gfx_control)
1913 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1914 PHM_PlatformCaps_ControlVDDGFX);
1915
1916 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1917 PHM_PlatformCaps_ControlVDDCI)) {
1918 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1919 VOLTAGE_TYPE_VDDCI4, VOLTAGE_OBJ_GPIO_LUT0))
1920 data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO0x1;
1921 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1922 VOLTAGE_TYPE_VDDCI4, VOLTAGE_OBJ_SVID27))
1923 data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID20x2;
1924 }
1925
1926 if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE0x0)
1927 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1928 PHM_PlatformCaps_EnableMVDDControl);
1929
1930 if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE0x0)
1931 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1932 PHM_PlatformCaps_ControlVDDCI);
1933
1934 data->vddc_phase_shed_control = 1;
1935 if ((hwmgr->chip_id == CHIP_POLARIS12) ||
1936 ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)(((adev->pdev->device == 0x67DF) && ((adev->
pdev->revision == 0xE3) || (adev->pdev->revision == 0xE4
) || (adev->pdev->revision == 0xE5) || (adev->pdev->
revision == 0xE7) || (adev->pdev->revision == 0xEF))) ||
((adev->pdev->device == 0x6FDF) && ((adev->
pdev->revision == 0xE7) || (adev->pdev->revision == 0xEF
) || (adev->pdev->revision == 0xFF))))
||
1937 ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)(((adev->pdev->device == 0x67EF) && ((adev->
pdev->revision == 0xE0) || (adev->pdev->revision == 0xE5
))) || ((adev->pdev->device == 0x67FF) && ((adev
->pdev->revision == 0xCF) || (adev->pdev->revision
== 0xEF) || (adev->pdev->revision == 0xFF))))
||
1938 ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)((adev->pdev->device == 0x67DF) && ((adev->pdev
->revision == 0xE1) || (adev->pdev->revision == 0xF7
)))
||
1939 ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)((adev->pdev->device == 0x67EF) && ((adev->pdev
->revision == 0xE2)))
) {
1940 if (data->voltage_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
1941 atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC1, &tmp1, &tmp2,
1942 &tmp3);
1943 tmp3 = (tmp3 >> 5) & 0x3;
1944 data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
1945 }
1946 } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI120) {
1947 data->vddc_phase_shed_control = 1;
1948 }
1949
1950 if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
1951 && (table_info->cac_dtp_table->usClockStretchAmount != 0))
1952 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1953 PHM_PlatformCaps_ClockStretcher);
1954
1955 data->pcie_gen_performance.max = PP_PCIEGen1;
1956 data->pcie_gen_performance.min = PP_PCIEGen3;
1957 data->pcie_gen_power_saving.max = PP_PCIEGen1;
1958 data->pcie_gen_power_saving.min = PP_PCIEGen3;
1959 data->pcie_lane_performance.max = 0;
1960 data->pcie_lane_performance.min = 16;
1961 data->pcie_lane_power_saving.max = 0;
1962 data->pcie_lane_power_saving.min = 16;
1963
1964
1965 if (adev->pg_flags & AMD_PG_SUPPORT_UVD(1 << 3))
1966 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1967 PHM_PlatformCaps_UVDPowerGating);
1968 if (adev->pg_flags & AMD_PG_SUPPORT_VCE(1 << 4))
1969 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1970 PHM_PlatformCaps_VCEPowerGating);
1971
1972 data->disable_edc_leakage_controller = true1;
1973 if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) ||
1974 ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) ||
1975 (adev->asic_type == CHIP_POLARIS12) ||
1976 (adev->asic_type == CHIP_VEGAM))
1977 data->disable_edc_leakage_controller = false0;
1978
1979 if (!atomctrl_is_asic_internal_ss_supported(hwmgr)) {
1980 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1981 PHM_PlatformCaps_MemorySpreadSpectrumSupport);
1982 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1983 PHM_PlatformCaps_EngineSpreadSpectrumSupport);
1984 }
1985
1986 if ((adev->pdev->device == 0x699F) &&
1987 (adev->pdev->revision == 0xCF)) {
1988 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1989 PHM_PlatformCaps_PowerContainment);
1990 data->enable_tdc_limit_feature = false0;
1991 data->enable_pkg_pwr_tracking_feature = false0;
1992 data->disable_edc_leakage_controller = true1;
1993 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1994 PHM_PlatformCaps_ClockStretcher);
1995 }
1996}
1997
1998static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr)
1999{
2000 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2001 struct amdgpu_device *adev = hwmgr->adev;
2002 uint32_t asicrev1, evv_revision, max = 0, min = 0;
2003
2004 atomctrl_read_efuse(hwmgr, STRAP_EVV_REVISION_LSB2208, STRAP_EVV_REVISION_MSB2211,
2005 &evv_revision);
2006
2007 atomctrl_read_efuse(hwmgr, 568, 579, &asicrev1);
2008
2009 if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)(((adev->pdev->device == 0x67DF) && ((adev->
pdev->revision == 0xE3) || (adev->pdev->revision == 0xE4
) || (adev->pdev->revision == 0xE5) || (adev->pdev->
revision == 0xE7) || (adev->pdev->revision == 0xEF))) ||
((adev->pdev->device == 0x6FDF) && ((adev->
pdev->revision == 0xE7) || (adev->pdev->revision == 0xEF
) || (adev->pdev->revision == 0xFF))))
||
2010 ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)((adev->pdev->device == 0x67DF) && ((adev->pdev
->revision == 0xE1) || (adev->pdev->revision == 0xF7
)))
) {
2011 min = 1200;
2012 max = 2500;
2013 } else if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)(((adev->pdev->device == 0x67EF) && ((adev->
pdev->revision == 0xE0) || (adev->pdev->revision == 0xE5
))) || ((adev->pdev->device == 0x67FF) && ((adev
->pdev->revision == 0xCF) || (adev->pdev->revision
== 0xEF) || (adev->pdev->revision == 0xFF))))
||
2014 ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)((adev->pdev->device == 0x67EF) && ((adev->pdev
->revision == 0xE2)))
) {
2015 min = 900;
2016 max= 2100;
2017 } else if (hwmgr->chip_id == CHIP_POLARIS10) {
2018 if (adev->pdev->subsystem_vendor == 0x106B) {
2019 min = 1000;
2020 max = 2300;
2021 } else {
2022 if (evv_revision == 0) {
2023 min = 1000;
2024 max = 2300;
2025 } else if (evv_revision == 1) {
2026 if (asicrev1 == 326) {
2027 min = 1200;
2028 max = 2500;
2029 /* TODO: PATCH RO in VBIOS */
2030 } else {
2031 min = 1200;
2032 max = 2000;
2033 }
2034 } else if (evv_revision == 2) {
2035 min = 1200;
2036 max = 2500;
2037 }
2038 }
2039 } else {
2040 min = 1100;
2041 max = 2100;
2042 }
2043
2044 data->ro_range_minimum = min;
2045 data->ro_range_maximum = max;
2046
2047 /* TODO: PATCH RO in VBIOS here */
2048
2049 return 0;
2050}
2051
2052/**
2053 * smu7_get_evv_voltages - Get Leakage VDDC based on leakage ID.
2054 *
2055 * @hwmgr: the address of the powerplay hardware manager.
2056 * Return: always 0
2057 */
2058static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
2059{
2060 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2061 uint16_t vv_id;
2062 uint16_t vddc = 0;
2063 uint16_t vddgfx = 0;
2064 uint16_t i, j;
2065 uint32_t sclk = 0;
2066 struct phm_ppt_v1_information *table_info =
2067 (struct phm_ppt_v1_information *)hwmgr->pptable;
2068 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL((void *)0);
2069
2070 if (hwmgr->chip_id == CHIP_POLARIS10 ||
2071 hwmgr->chip_id == CHIP_POLARIS11 ||
2072 hwmgr->chip_id == CHIP_POLARIS12)
2073 smu7_calculate_ro_range(hwmgr);
2074
2075 for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT8; i++) {
2076 vv_id = ATOM_VIRTUAL_VOLTAGE_ID00xff01 + i;
2077
2078 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
2079 if ((hwmgr->pp_table_version == PP_TABLE_V1)
2080 && !phm_get_sclk_for_voltage_evv(hwmgr,
2081 table_info->vddgfx_lookup_table, vv_id, &sclk)) {
2082 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2083 PHM_PlatformCaps_ClockStretcher)) {
2084 sclk_table = table_info->vdd_dep_on_sclk;
2085
2086 for (j = 1; j < sclk_table->count; j++) {
2087 if (sclk_table->entries[j].clk == sclk &&
2088 sclk_table->entries[j].cks_enable == 0) {
2089 sclk += 5000;
2090 break;
2091 }
2092 }
2093 }
2094 if (0 == atomctrl_get_voltage_evv_on_sclk
2095 (hwmgr, VOLTAGE_TYPE_VDDGFX5, sclk,
2096 vv_id, &vddgfx)) {
2097 /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
2098 PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL)do { if (!((vddgfx < 2000 && vddgfx != 0))) { printk
("\0014" "amdgpu: " "%s\n", "Invalid VDDGFX value!"); return -
22; } } while (0)
;
2099
2100 /* the voltage should not be zero nor equal to leakage ID */
2101 if (vddgfx != 0 && vddgfx != vv_id) {
2102 data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
2103 data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id;
2104 data->vddcgfx_leakage.count++;
2105 }
2106 } else {
2107 pr_info("Error retrieving EVV voltage value!\n")do { } while(0);
2108 }
2109 }
2110 } else {
2111 if ((hwmgr->pp_table_version == PP_TABLE_V0)
2112 || !phm_get_sclk_for_voltage_evv(hwmgr,
2113 table_info->vddc_lookup_table, vv_id, &sclk)) {
2114 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2115 PHM_PlatformCaps_ClockStretcher)) {
2116 if (table_info == NULL((void *)0))
2117 return -EINVAL22;
2118 sclk_table = table_info->vdd_dep_on_sclk;
2119
2120 for (j = 1; j < sclk_table->count; j++) {
2121 if (sclk_table->entries[j].clk == sclk &&
2122 sclk_table->entries[j].cks_enable == 0) {
2123 sclk += 5000;
2124 break;
2125 }
2126 }
2127 }
2128
2129 if (phm_get_voltage_evv_on_sclk(hwmgr,
2130 VOLTAGE_TYPE_VDDC1,
2131 sclk, vv_id, &vddc) == 0) {
2132 if (vddc >= 2000 || vddc == 0)
2133 return -EINVAL22;
2134 } else {
2135 pr_debug("failed to retrieving EVV voltage!\n")do { } while(0);
2136 continue;
2137 }
2138
2139 /* the voltage should not be zero nor equal to leakage ID */
2140 if (vddc != 0 && vddc != vv_id) {
2141 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc);
2142 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
2143 data->vddc_leakage.count++;
2144 }
2145 }
2146 }
2147 }
2148
2149 return 0;
2150}
2151
2152/**
2153 * smu7_patch_ppt_v1_with_vdd_leakage - Change virtual leakage voltage to actual value.
2154 *
2155 * @hwmgr: the address of the powerplay hardware manager.
2156 * @voltage: pointer to changing voltage
2157 * @leakage_table: pointer to leakage table
2158 */
2159static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2160 uint16_t *voltage, struct smu7_leakage_voltage *leakage_table)
2161{
2162 uint32_t index;
2163
2164 /* search for leakage voltage ID 0xff01 ~ 0xff08 */
2165 for (index = 0; index < leakage_table->count; index++) {
2166 /* if this voltage matches a leakage voltage ID */
2167 /* patch with actual leakage voltage */
2168 if (leakage_table->leakage_id[index] == *voltage) {
2169 *voltage = leakage_table->actual_voltage[index];
2170 break;
2171 }
2172 }
2173
2174 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID00xff01)
2175 pr_info("Voltage value looks like a Leakage ID but it's not patched\n")do { } while(0);
2176}
2177
2178/**
2179 * smu7_patch_lookup_table_with_leakage - Patch voltage lookup table by EVV leakages.
2180 *
2181 * @hwmgr: the address of the powerplay hardware manager.
2182 * @lookup_table: pointer to voltage lookup table
2183 * @leakage_table: pointer to leakage table
2184 * Return: always 0
2185 */
2186static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
2187 phm_ppt_v1_voltage_lookup_table *lookup_table,
2188 struct smu7_leakage_voltage *leakage_table)
2189{
2190 uint32_t i;
2191
2192 for (i = 0; i < lookup_table->count; i++)
2193 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2194 &lookup_table->entries[i].us_vdd, leakage_table);
2195
2196 return 0;
2197}
2198
2199static int smu7_patch_clock_voltage_limits_with_vddc_leakage(
2200 struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table,
2201 uint16_t *vddc)
2202{
2203 struct phm_ppt_v1_information *table_info =
2204 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2205 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
2206 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
2207 table_info->max_clock_voltage_on_dc.vddc;
2208 return 0;
2209}
2210
2211static int smu7_patch_voltage_dependency_tables_with_lookup_table(
2212 struct pp_hwmgr *hwmgr)
2213{
2214 uint8_t entry_id;
2215 uint8_t voltage_id;
2216 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2217 struct phm_ppt_v1_information *table_info =
2218 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2219
2220 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
2221 table_info->vdd_dep_on_sclk;
2222 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
2223 table_info->vdd_dep_on_mclk;
2224 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
2225 table_info->mm_dep_table;
2226
2227 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
2228 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2229 voltage_id = sclk_table->entries[entry_id].vddInd;
2230 sclk_table->entries[entry_id].vddgfx =
2231 table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd;
2232 }
2233 } else {
2234 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2235 voltage_id = sclk_table->entries[entry_id].vddInd;
2236 sclk_table->entries[entry_id].vddc =
2237 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2238 }
2239 }
2240
2241 for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2242 voltage_id = mclk_table->entries[entry_id].vddInd;
2243 mclk_table->entries[entry_id].vddc =
2244 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2245 }
2246
2247 for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
2248 voltage_id = mm_table->entries[entry_id].vddcInd;
2249 mm_table->entries[entry_id].vddc =
2250 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2251 }
2252
2253 return 0;
2254
2255}
2256
2257static int phm_add_voltage(struct pp_hwmgr *hwmgr,
2258 phm_ppt_v1_voltage_lookup_table *look_up_table,
2259 phm_ppt_v1_voltage_lookup_record *record)
2260{
2261 uint32_t i;
2262
2263 PP_ASSERT_WITH_CODE((NULL != look_up_table),do { if (!((((void *)0) != look_up_table))) { printk("\0014" "amdgpu: "
"%s\n", "Lookup Table empty."); return -22; } } while (0)
2264 "Lookup Table empty.", return -EINVAL)do { if (!((((void *)0) != look_up_table))) { printk("\0014" "amdgpu: "
"%s\n", "Lookup Table empty."); return -22; } } while (0)
;
2265 PP_ASSERT_WITH_CODE((0 != look_up_table->count),do { if (!((0 != look_up_table->count))) { printk("\0014" "amdgpu: "
"%s\n", "Lookup Table empty."); return -22; } } while (0)
2266 "Lookup Table empty.", return -EINVAL)do { if (!((0 != look_up_table->count))) { printk("\0014" "amdgpu: "
"%s\n", "Lookup Table empty."); return -22; } } while (0)
;
2267
2268 i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
2269 PP_ASSERT_WITH_CODE((i >= look_up_table->count),do { if (!((i >= look_up_table->count))) { printk("\0014"
"amdgpu: " "%s\n", "Lookup Table is full."); return -22; } }
while (0)
2270 "Lookup Table is full.", return -EINVAL)do { if (!((i >= look_up_table->count))) { printk("\0014"
"amdgpu: " "%s\n", "Lookup Table is full."); return -22; } }
while (0)
;
2271
2272 /* This is to avoid entering duplicate calculated records. */
2273 for (i = 0; i < look_up_table->count; i++) {
2274 if (look_up_table->entries[i].us_vdd == record->us_vdd) {
2275 if (look_up_table->entries[i].us_calculated == 1)
2276 return 0;
2277 break;
2278 }
2279 }
2280
2281 look_up_table->entries[i].us_calculated = 1;
2282 look_up_table->entries[i].us_vdd = record->us_vdd;
2283 look_up_table->entries[i].us_cac_low = record->us_cac_low;
2284 look_up_table->entries[i].us_cac_mid = record->us_cac_mid;
2285 look_up_table->entries[i].us_cac_high = record->us_cac_high;
2286 /* Only increment the count when we're appending, not replacing duplicate entry. */
2287 if (i == look_up_table->count)
2288 look_up_table->count++;
2289
2290 return 0;
2291}
2292
2293
2294static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
2295{
2296 uint8_t entry_id;
2297 struct phm_ppt_v1_voltage_lookup_record v_record;
2298 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2299 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2300
2301 phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
2302 phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
2303
2304 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
2305 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2306 if (sclk_table->entries[entry_id].vdd_offset & (1 << 15))
2307 v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2308 sclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2309 else
2310 v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2311 sclk_table->entries[entry_id].vdd_offset;
2312
2313 sclk_table->entries[entry_id].vddc =
2314 v_record.us_cac_low = v_record.us_cac_mid =
2315 v_record.us_cac_high = v_record.us_vdd;
2316
2317 phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record);
2318 }
2319
2320 for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2321 if (mclk_table->entries[entry_id].vdd_offset & (1 << 15))
2322 v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2323 mclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2324 else
2325 v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2326 mclk_table->entries[entry_id].vdd_offset;
2327
2328 mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2329 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2330 phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2331 }
2332 }
2333 return 0;
2334}
2335
2336static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
2337{
2338 uint8_t entry_id;
2339 struct phm_ppt_v1_voltage_lookup_record v_record;
2340 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2341 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2342 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
2343
2344 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
2345 for (entry_id = 0; entry_id < mm_table->count; entry_id++) {
2346 if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15))
2347 v_record.us_vdd = mm_table->entries[entry_id].vddc +
2348 mm_table->entries[entry_id].vddgfx_offset - 0xFFFF;
2349 else
2350 v_record.us_vdd = mm_table->entries[entry_id].vddc +
2351 mm_table->entries[entry_id].vddgfx_offset;
2352
2353 /* Add the calculated VDDGFX to the VDDGFX lookup table */
2354 mm_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2355 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2356 phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2357 }
2358 }
2359 return 0;
2360}
2361
2362static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr,
2363 struct phm_ppt_v1_voltage_lookup_table *lookup_table)
2364{
2365 uint32_t table_size, i, j;
2366 table_size = lookup_table->count;
2367
2368 PP_ASSERT_WITH_CODE(0 != lookup_table->count,do { if (!(0 != lookup_table->count)) { printk("\0014" "amdgpu: "
"%s\n", "Lookup table is empty"); return -22; } } while (0)
2369 "Lookup table is empty", return -EINVAL)do { if (!(0 != lookup_table->count)) { printk("\0014" "amdgpu: "
"%s\n", "Lookup table is empty"); return -22; } } while (0)
;
2370
2371 /* Sorting voltages */
2372 for (i = 0; i < table_size - 1; i++) {
2373 for (j = i + 1; j > 0; j--) {
2374 if (lookup_table->entries[j].us_vdd <
2375 lookup_table->entries[j - 1].us_vdd) {
2376 swap(lookup_table->entries[j - 1],do { __typeof(lookup_table->entries[j - 1]) __tmp = (lookup_table
->entries[j - 1]); (lookup_table->entries[j - 1]) = (lookup_table
->entries[j]); (lookup_table->entries[j]) = __tmp; } while
(0)
2377 lookup_table->entries[j])do { __typeof(lookup_table->entries[j - 1]) __tmp = (lookup_table
->entries[j - 1]); (lookup_table->entries[j - 1]) = (lookup_table
->entries[j]); (lookup_table->entries[j]) = __tmp; } while
(0)
;
2378 }
2379 }
2380 }
2381
2382 return 0;
2383}
2384
2385static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr)
2386{
2387 int result = 0;
2388 int tmp_result;
2389 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2390 struct phm_ppt_v1_information *table_info =
2391 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2392
2393 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID20x2) {
2394 tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2395 table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage));
2396 if (tmp_result != 0)
2397 result = tmp_result;
2398
2399 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2400 &table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage));
2401 } else {
2402
2403 tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2404 table_info->vddc_lookup_table, &(data->vddc_leakage));
2405 if (tmp_result)
2406 result = tmp_result;
2407
2408 tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
2409 &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
2410 if (tmp_result)
2411 result = tmp_result;
2412 }
2413
2414 tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
2415 if (tmp_result)
2416 result = tmp_result;
2417
2418 tmp_result = smu7_calc_voltage_dependency_tables(hwmgr);
2419 if (tmp_result)
2420 result = tmp_result;
2421
2422 tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr);
2423 if (tmp_result)
2424 result = tmp_result;
2425
2426 tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table);
2427 if (tmp_result)
2428 result = tmp_result;
2429
2430 tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
2431 if (tmp_result)
2432 result = tmp_result;
2433
2434 return result;
2435}
2436
2437static int smu7_find_highest_vddc(struct pp_hwmgr *hwmgr)
2438{
2439 struct phm_ppt_v1_information *table_info =
2440 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2441 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2442 table_info->vdd_dep_on_sclk;
2443 struct phm_ppt_v1_voltage_lookup_table *lookup_table =
2444 table_info->vddc_lookup_table;
2445 uint16_t highest_voltage;
2446 uint32_t i;
2447
2448 highest_voltage = allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2449
2450 for (i = 0; i < lookup_table->count; i++) {
2451 if (lookup_table->entries[i].us_vdd < ATOM_VIRTUAL_VOLTAGE_ID00xff01 &&
2452 lookup_table->entries[i].us_vdd > highest_voltage)
2453 highest_voltage = lookup_table->entries[i].us_vdd;
2454 }
2455
2456 return highest_voltage;
2457}
2458
2459static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
2460{
2461 struct phm_ppt_v1_information *table_info =
2462 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2463
2464 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2465 table_info->vdd_dep_on_sclk;
2466 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
2467 table_info->vdd_dep_on_mclk;
2468
2469 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,do { if (!(allowed_sclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on SCLK table is missing."
); return -22; } } while (0)
2470 "VDD dependency on SCLK table is missing.",do { if (!(allowed_sclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on SCLK table is missing."
); return -22; } } while (0)
2471 return -EINVAL)do { if (!(allowed_sclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on SCLK table is missing."
); return -22; } } while (0)
;
2472 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,do { if (!(allowed_sclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on SCLK table has to have is missing."
); return -22; } } while (0)
2473 "VDD dependency on SCLK table has to have is missing.",do { if (!(allowed_sclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on SCLK table has to have is missing."
); return -22; } } while (0)
2474 return -EINVAL)do { if (!(allowed_sclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on SCLK table has to have is missing."
); return -22; } } while (0)
;
2475
2476 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,do { if (!(allowed_mclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on MCLK table is missing"
); return -22; } } while (0)
2477 "VDD dependency on MCLK table is missing",do { if (!(allowed_mclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on MCLK table is missing"
); return -22; } } while (0)
2478 return -EINVAL)do { if (!(allowed_mclk_vdd_table != ((void *)0))) { printk("\0014"
"amdgpu: " "%s\n", "VDD dependency on MCLK table is missing"
); return -22; } } while (0)
;
2479 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,do { if (!(allowed_mclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing."
); return -22; } } while (0)
2480 "VDD dependency on MCLK table has to have is missing.",do { if (!(allowed_mclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing."
); return -22; } } while (0)
2481 return -EINVAL)do { if (!(allowed_mclk_vdd_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing."
); return -22; } } while (0)
;
2482
2483 table_info->max_clock_voltage_on_ac.sclk =
2484 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
2485 table_info->max_clock_voltage_on_ac.mclk =
2486 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
2487 if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
2488 table_info->max_clock_voltage_on_ac.vddc =
2489 smu7_find_highest_vddc(hwmgr);
2490 else
2491 table_info->max_clock_voltage_on_ac.vddc =
2492 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2493 table_info->max_clock_voltage_on_ac.vddci =
2494 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
2495
2496 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk;
2497 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk;
2498 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc;
2499 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci;
2500
2501 return 0;
2502}
2503
2504static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
2505{
2506 struct phm_ppt_v1_information *table_info =
2507 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2508 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
2509 struct phm_ppt_v1_voltage_lookup_table *lookup_table;
2510 uint32_t i;
2511 uint32_t hw_revision, sub_vendor_id, sub_sys_id;
2512 struct amdgpu_device *adev = hwmgr->adev;
2513
2514 if (table_info != NULL((void *)0)) {
2515 dep_mclk_table = table_info->vdd_dep_on_mclk;
2516 lookup_table = table_info->vddc_lookup_table;
2517 } else
2518 return 0;
2519
2520 hw_revision = adev->pdev->revision;
2521 sub_sys_id = adev->pdev->subsystem_device;
2522 sub_vendor_id = adev->pdev->subsystem_vendor;
2523
2524 if (adev->pdev->device == 0x67DF && hw_revision == 0xC7 &&
2525 ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) ||
2526 (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) ||
2527 (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) {
2528
2529 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200350,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200350))) & ~0x78) | (0x78 &
((0x3) << 0x3)))))
2530 CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200350,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200350))) & ~0x78) | (0x78 &
((0x3) << 0x3)))))
2531 PWR_CKS_CNTL,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200350,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200350))) & ~0x78) | (0x78 &
((0x3) << 0x3)))))
2532 CKS_STRETCH_AMOUNT,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200350,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200350))) & ~0x78) | (0x78 &
((0x3) << 0x3)))))
2533 0x3)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200350,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200350))) & ~0x78) | (0x78 &
((0x3) << 0x3)))))
;
2534
2535 if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000)
2536 return 0;
2537
2538 for (i = 0; i < lookup_table->count; i++) {
2539 if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) {
2540 dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i;
2541 return 0;
2542 }
2543 }
2544 }
2545 return 0;
2546}
2547
2548static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr)
2549{
2550 struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2551 uint32_t temp_reg;
2552 struct phm_ppt_v1_information *table_info =
2553 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2554
2555
2556 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID62, &gpio_pin_assignment)) {
2557 temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200004))
;
2558 switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
2559 case 0:
2560 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1)(((temp_reg) & ~0x3) | (0x3 & ((0x1) << 0x0)));
2561 break;
2562 case 1:
2563 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2)(((temp_reg) & ~0x3) | (0x3 & ((0x2) << 0x0)));
2564 break;
2565 case 2:
2566 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1)(((temp_reg) & ~0x4) | (0x4 & ((0x1) << 0x2)));
2567 break;
2568 case 3:
2569 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1)(((temp_reg) & ~0x8) | (0x8 & ((0x1) << 0x3)));
2570 break;
2571 case 4:
2572 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1)(((temp_reg) & ~0x10) | (0x10 & ((0x1) << 0x4))
)
;
2573 break;
2574 default:
2575 break;
2576 }
2577 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200004,temp_reg))
;
2578 }
2579
2580 if (table_info == NULL((void *)0))
2581 return 0;
2582
2583 if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 &&
2584 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) {
2585 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit =
2586 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2587
2588 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit =
2589 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2590
2591 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1;
2592
2593 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100;
2594
2595 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit =
2596 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2597
2598 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1;
2599
2600 table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ?
2601 (table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0;
2602
2603 table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2604 table_info->cac_dtp_table->usOperatingTempStep = 1;
2605 table_info->cac_dtp_table->usOperatingTempHyst = 1;
2606
2607 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM =
2608 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2609
2610 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
2611 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM;
2612
2613 hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit =
2614 table_info->cac_dtp_table->usOperatingTempMinLimit;
2615
2616 hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit =
2617 table_info->cac_dtp_table->usOperatingTempMaxLimit;
2618
2619 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
2620 table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2621
2622 hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep =
2623 table_info->cac_dtp_table->usOperatingTempStep;
2624
2625 hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
2626 table_info->cac_dtp_table->usTargetOperatingTemp;
2627 if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK)
2628 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2629 PHM_PlatformCaps_ODFuzzyFanControlSupport);
2630 }
2631
2632 return 0;
2633}
2634
2635/**
2636 * smu7_patch_ppt_v0_with_vdd_leakage - Change virtual leakage voltage to actual value.
2637 *
2638 * @hwmgr: the address of the powerplay hardware manager.
2639 * @voltage: pointer to changing voltage
2640 * @leakage_table: pointer to leakage table
2641 */
2642static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2643 uint32_t *voltage, struct smu7_leakage_voltage *leakage_table)
2644{
2645 uint32_t index;
2646
2647 /* search for leakage voltage ID 0xff01 ~ 0xff08 */
2648 for (index = 0; index < leakage_table->count; index++) {
2649 /* if this voltage matches a leakage voltage ID */
2650 /* patch with actual leakage voltage */
2651 if (leakage_table->leakage_id[index] == *voltage) {
2652 *voltage = leakage_table->actual_voltage[index];
2653 break;
2654 }
2655 }
2656
2657 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID00xff01)
2658 pr_info("Voltage value looks like a Leakage ID but it's not patched\n")do { } while(0);
2659}
2660
2661
2662static int smu7_patch_vddc(struct pp_hwmgr *hwmgr,
2663 struct phm_clock_voltage_dependency_table *tab)
2664{
2665 uint16_t i;
2666 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2667
2668 if (tab)
2669 for (i = 0; i < tab->count; i++)
2670 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2671 &data->vddc_leakage);
2672
2673 return 0;
2674}
2675
2676static int smu7_patch_vddci(struct pp_hwmgr *hwmgr,
2677 struct phm_clock_voltage_dependency_table *tab)
2678{
2679 uint16_t i;
2680 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2681
2682 if (tab)
2683 for (i = 0; i < tab->count; i++)
2684 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2685 &data->vddci_leakage);
2686
2687 return 0;
2688}
2689
2690static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr,
2691 struct phm_vce_clock_voltage_dependency_table *tab)
2692{
2693 uint16_t i;
2694 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2695
2696 if (tab)
2697 for (i = 0; i < tab->count; i++)
2698 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2699 &data->vddc_leakage);
2700
2701 return 0;
2702}
2703
2704
2705static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr,
2706 struct phm_uvd_clock_voltage_dependency_table *tab)
2707{
2708 uint16_t i;
2709 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2710
2711 if (tab)
2712 for (i = 0; i < tab->count; i++)
2713 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2714 &data->vddc_leakage);
2715
2716 return 0;
2717}
2718
2719static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr,
2720 struct phm_phase_shedding_limits_table *tab)
2721{
2722 uint16_t i;
2723 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2724
2725 if (tab)
2726 for (i = 0; i < tab->count; i++)
2727 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage,
2728 &data->vddc_leakage);
2729
2730 return 0;
2731}
2732
2733static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr,
2734 struct phm_samu_clock_voltage_dependency_table *tab)
2735{
2736 uint16_t i;
2737 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2738
2739 if (tab)
2740 for (i = 0; i < tab->count; i++)
2741 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2742 &data->vddc_leakage);
2743
2744 return 0;
2745}
2746
2747static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr,
2748 struct phm_acp_clock_voltage_dependency_table *tab)
2749{
2750 uint16_t i;
2751 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2752
2753 if (tab)
2754 for (i = 0; i < tab->count; i++)
2755 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2756 &data->vddc_leakage);
2757
2758 return 0;
2759}
2760
2761static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr,
2762 struct phm_clock_and_voltage_limits *tab)
2763{
2764 uint32_t vddc, vddci;
2765 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2766
2767 if (tab) {
2768 vddc = tab->vddc;
2769 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc,
2770 &data->vddc_leakage);
2771 tab->vddc = vddc;
2772 vddci = tab->vddci;
2773 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci,
2774 &data->vddci_leakage);
2775 tab->vddci = vddci;
2776 }
2777
2778 return 0;
2779}
2780
2781static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab)
2782{
2783 uint32_t i;
2784 uint32_t vddc;
2785 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2786
2787 if (tab) {
2788 for (i = 0; i < tab->count; i++) {
2789 vddc = (uint32_t)(tab->entries[i].Vddc);
2790 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage);
2791 tab->entries[i].Vddc = (uint16_t)vddc;
2792 }
2793 }
2794
2795 return 0;
2796}
2797
2798static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
2799{
2800 int tmp;
2801
2802 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk);
2803 if (tmp)
2804 return -EINVAL22;
2805
2806 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk);
2807 if (tmp)
2808 return -EINVAL22;
2809
2810 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2811 if (tmp)
2812 return -EINVAL22;
2813
2814 tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
2815 if (tmp)
2816 return -EINVAL22;
2817
2818 tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table);
2819 if (tmp)
2820 return -EINVAL22;
2821
2822 tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
2823 if (tmp)
2824 return -EINVAL22;
2825
2826 tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table);
2827 if (tmp)
2828 return -EINVAL22;
2829
2830 tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table);
2831 if (tmp)
2832 return -EINVAL22;
2833
2834 tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table);
2835 if (tmp)
2836 return -EINVAL22;
2837
2838 tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac);
2839 if (tmp)
2840 return -EINVAL22;
2841
2842 tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc);
2843 if (tmp)
2844 return -EINVAL22;
2845
2846 tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table);
2847 if (tmp)
2848 return -EINVAL22;
2849
2850 return 0;
2851}
2852
2853
2854static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
2855{
2856 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2857
2858 struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
2859 struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
2860 struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
2861
2862 PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL,do { if (!(allowed_sclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table is missing. This table is mandatory"
); return -22; } } while (0)
2863 "VDDC dependency on SCLK table is missing. This table is mandatory",do { if (!(allowed_sclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table is missing. This table is mandatory"
); return -22; } } while (0)
2864 return -EINVAL)do { if (!(allowed_sclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table is missing. This table is mandatory"
); return -22; } } while (0)
;
2865 PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1,do { if (!(allowed_sclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
2866 "VDDC dependency on SCLK table has to have is missing. This table is mandatory",do { if (!(allowed_sclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
2867 return -EINVAL)do { if (!(allowed_sclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDDC dependency on SCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
;
2868
2869 PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL,do { if (!(allowed_mclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on MCLK table is missing. This table is mandatory"
); return -22; } } while (0)
2870 "VDDC dependency on MCLK table is missing. This table is mandatory",do { if (!(allowed_mclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on MCLK table is missing. This table is mandatory"
); return -22; } } while (0)
2871 return -EINVAL)do { if (!(allowed_mclk_vddc_table != ((void *)0))) { printk(
"\0014" "amdgpu: " "%s\n", "VDDC dependency on MCLK table is missing. This table is mandatory"
); return -22; } } while (0)
;
2872 PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1,do { if (!(allowed_mclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
2873 "VDD dependency on MCLK table has to have is missing. This table is mandatory",do { if (!(allowed_mclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
2874 return -EINVAL)do { if (!(allowed_mclk_vddc_table->count >= 1)) { printk
("\0014" "amdgpu: " "%s\n", "VDD dependency on MCLK table has to have is missing. This table is mandatory"
); return -22; } } while (0)
;
2875
2876 data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v;
2877 data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2878
2879 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
2880 allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk;
2881 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
2882 allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk;
2883 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
2884 allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2885
2886 if (allowed_mclk_vddci_table != NULL((void *)0) && allowed_mclk_vddci_table->count >= 1) {
2887 data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v;
2888 data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v;
2889 }
2890
2891 if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL((void *)0) && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1)
2892 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v;
2893
2894 return 0;
2895}
2896
2897static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
2898{
2899 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2900 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL((void *)0);
2901 kfree(hwmgr->backend);
2902 hwmgr->backend = NULL((void *)0);
11
Null pointer value stored to field 'backend'
2903
2904 return 0;
2905}
2906
2907static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr)
2908{
2909 uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id;
2910 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2911 int i;
2912
2913 if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) {
2914 for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT8; i++) {
2915 virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID00xff01 + i;
2916 if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci,
2917 virtual_voltage_id,
2918 efuse_voltage_id) == 0) {
2919 if (vddc != 0 && vddc != virtual_voltage_id) {
2920 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
2921 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
2922 data->vddc_leakage.count++;
2923 }
2924 if (vddci != 0 && vddci != virtual_voltage_id) {
2925 data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci;
2926 data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id;
2927 data->vddci_leakage.count++;
2928 }
2929 }
2930 }
2931 }
2932 return 0;
2933}
2934
2935#define LEAKAGE_ID_MSB463 463
2936#define LEAKAGE_ID_LSB454 454
2937
2938static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
2939{
2940 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
14
'data' initialized to a null pointer value
2941 uint32_t efuse;
2942 uint16_t offset;
2943 int ret = 0;
2944
2945 if (data->disable_edc_leakage_controller)
15
Access to field 'disable_edc_leakage_controller' results in a dereference of a null pointer (loaded from variable 'data')
2946 return 0;
2947
2948 ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr,
2949 &data->edc_hilo_leakage_offset_from_vbios);
2950 if (ret)
2951 return ret;
2952
2953 if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
2954 data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
2955 atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB454, LEAKAGE_ID_MSB463, &efuse);
2956 if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold)
2957 offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset;
2958 else
2959 offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset;
2960
2961 ret = atomctrl_get_edc_leakage_table(hwmgr,
2962 &data->edc_leakage_table,
2963 offset);
2964 if (ret)
2965 return ret;
2966 }
2967
2968 return ret;
2969}
2970
2971static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
2972{
2973 struct smu7_hwmgr *data;
2974 int result = 0;
2975
2976 data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL(0x0001 | 0x0004));
2977 if (data == NULL((void *)0))
1
Assuming 'data' is not equal to NULL
2
Taking false branch
2978 return -ENOMEM12;
2979
2980 hwmgr->backend = data;
2981 smu7_patch_voltage_workaround(hwmgr);
2982 smu7_init_dpm_defaults(hwmgr);
2983
2984 /* Get leakage voltage based on leakage ID. */
2985 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3
Taking false branch
2986 PHM_PlatformCaps_EVV)) {
2987 result = smu7_get_evv_voltages(hwmgr);
2988 if (result) {
2989 pr_info("Get EVV Voltage Failed. Abort Driver loading!\n")do { } while(0);
2990 return -EINVAL22;
2991 }
2992 } else {
2993 smu7_get_elb_voltages(hwmgr);
2994 }
2995
2996 if (hwmgr->pp_table_version == PP_TABLE_V1) {
4
Assuming field 'pp_table_version' is not equal to PP_TABLE_V1
5
Taking false branch
2997 smu7_complete_dependency_tables(hwmgr);
2998 smu7_set_private_data_based_on_pptable_v1(hwmgr);
2999 } else if (hwmgr->pp_table_version == PP_TABLE_V0) {
6
Assuming field 'pp_table_version' is not equal to PP_TABLE_V0
7
Taking false branch
3000 smu7_patch_dependency_tables_with_leakage(hwmgr);
3001 smu7_set_private_data_based_on_pptable_v0(hwmgr);
3002 }
3003
3004 /* Initalize Dynamic State Adjustment Rule Settings */
3005 result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
3006
3007 if (0 == result) {
8
Assuming 'result' is not equal to 0
9
Taking false branch
3008 struct amdgpu_device *adev = hwmgr->adev;
3009
3010 data->is_tlu_enabled = false0;
3011
3012 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
3013 SMU7_MAX_HARDWARE_POWERLEVELS2;
3014 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
3015 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
3016
3017 data->pcie_gen_cap = adev->pm.pcie_gen_mask;
3018 if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN30x00040000)
3019 data->pcie_spc_cap = 20;
3020 else
3021 data->pcie_spc_cap = 16;
3022 data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
3023
3024 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
3025/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
3026 hwmgr->platform_descriptor.clockStep.engineClock = 500;
3027 hwmgr->platform_descriptor.clockStep.memoryClock = 500;
3028 smu7_thermal_parameter_init(hwmgr);
3029 } else {
3030 /* Ignore return value in here, we are cleaning up a mess. */
3031 smu7_hwmgr_backend_fini(hwmgr);
10
Calling 'smu7_hwmgr_backend_fini'
12
Returning from 'smu7_hwmgr_backend_fini'
3032 }
3033
3034 result = smu7_update_edc_leakage_table(hwmgr);
13
Calling 'smu7_update_edc_leakage_table'
3035 if (result)
3036 return result;
3037
3038 return 0;
3039}
3040
3041static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
3042{
3043 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3044 uint32_t level, tmp;
3045
3046 if (!data->pcie_dpm_key_disabled) {
3047 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3048 level = 0;
3049 tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
3050 while (tmp >>= 1)
3051 level++;
3052
3053 if (level)
3054 smum_send_msg_to_smc_with_parameter(hwmgr,
3055 PPSMC_MSG_PCIeDPM_ForceLevel((uint16_t) 0x147), level,
3056 NULL((void *)0));
3057 }
3058 }
3059
3060 if (!data->sclk_dpm_key_disabled) {
3061 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3062 level = 0;
3063 tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
3064 while (tmp >>= 1)
3065 level++;
3066
3067 if (level)
3068 smum_send_msg_to_smc_with_parameter(hwmgr,
3069 PPSMC_MSG_SCLKDPM_SetEnabledMask((uint16_t) 0x145),
3070 (1 << level),
3071 NULL((void *)0));
3072 }
3073 }
3074
3075 if (!data->mclk_dpm_key_disabled) {
3076 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3077 level = 0;
3078 tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
3079 while (tmp >>= 1)
3080 level++;
3081
3082 if (level)
3083 smum_send_msg_to_smc_with_parameter(hwmgr,
3084 PPSMC_MSG_MCLKDPM_SetEnabledMask((uint16_t) 0x146),
3085 (1 << level),
3086 NULL((void *)0));
3087 }
3088 }
3089
3090 return 0;
3091}
3092
3093static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
3094{
3095 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3096
3097 if (hwmgr->pp_table_version == PP_TABLE_V1)
3098 phm_apply_dal_min_voltage_request(hwmgr);
3099/* TO DO for v0 iceland and Ci*/
3100
3101 if (!data->sclk_dpm_key_disabled) {
3102 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
3103 smum_send_msg_to_smc_with_parameter(hwmgr,
3104 PPSMC_MSG_SCLKDPM_SetEnabledMask((uint16_t) 0x145),
3105 data->dpm_level_enable_mask.sclk_dpm_enable_mask,
3106 NULL((void *)0));
3107 }
3108
3109 if (!data->mclk_dpm_key_disabled) {
3110 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask)
3111 smum_send_msg_to_smc_with_parameter(hwmgr,
3112 PPSMC_MSG_MCLKDPM_SetEnabledMask((uint16_t) 0x146),
3113 data->dpm_level_enable_mask.mclk_dpm_enable_mask,
3114 NULL((void *)0));
3115 }
3116
3117 return 0;
3118}
3119
3120static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
3121{
3122 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3123
3124 if (!smum_is_dpm_running(hwmgr))
3125 return -EINVAL22;
3126
3127 if (!data->pcie_dpm_key_disabled) {
3128 smum_send_msg_to_smc(hwmgr,
3129 PPSMC_MSG_PCIeDPM_UnForceLevel((uint16_t) 0x148),
3130 NULL((void *)0));
3131 }
3132
3133 return smu7_upload_dpm_level_enable_mask(hwmgr);
3134}
3135
3136static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3137{
3138 struct smu7_hwmgr *data =
3139 (struct smu7_hwmgr *)(hwmgr->backend);
3140 uint32_t level;
3141
3142 if (!data->sclk_dpm_key_disabled)
3143 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3144 level = phm_get_lowest_enabled_level(hwmgr,
3145 data->dpm_level_enable_mask.sclk_dpm_enable_mask);
3146 smum_send_msg_to_smc_with_parameter(hwmgr,
3147 PPSMC_MSG_SCLKDPM_SetEnabledMask((uint16_t) 0x145),
3148 (1 << level),
3149 NULL((void *)0));
3150
3151 }
3152
3153 if (!data->mclk_dpm_key_disabled) {
3154 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3155 level = phm_get_lowest_enabled_level(hwmgr,
3156 data->dpm_level_enable_mask.mclk_dpm_enable_mask);
3157 smum_send_msg_to_smc_with_parameter(hwmgr,
3158 PPSMC_MSG_MCLKDPM_SetEnabledMask((uint16_t) 0x146),
3159 (1 << level),
3160 NULL((void *)0));
3161 }
3162 }
3163
3164 if (!data->pcie_dpm_key_disabled) {
3165 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3166 level = phm_get_lowest_enabled_level(hwmgr,
3167 data->dpm_level_enable_mask.pcie_dpm_enable_mask);
3168 smum_send_msg_to_smc_with_parameter(hwmgr,
3169 PPSMC_MSG_PCIeDPM_ForceLevel((uint16_t) 0x147),
3170 (level),
3171 NULL((void *)0));
3172 }
3173 }
3174
3175 return 0;
3176}
3177
3178static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
3179 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask)
3180{
3181 uint32_t percentage;
3182 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3183 struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table;
3184 int32_t tmp_mclk;
3185 int32_t tmp_sclk;
3186 int32_t count;
3187
3188 if (golden_dpm_table->mclk_table.count < 1)
3189 return -EINVAL22;
3190
3191 percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value /
3192 golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3193
3194 if (golden_dpm_table->mclk_table.count == 1) {
3195 percentage = 70;
3196 tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3197 *mclk_mask = golden_dpm_table->mclk_table.count - 1;
3198 } else {
3199 tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value;
3200 *mclk_mask = golden_dpm_table->mclk_table.count - 2;
3201 }
3202
3203 tmp_sclk = tmp_mclk * percentage / 100;
3204
3205 if (hwmgr->pp_table_version == PP_TABLE_V0) {
3206 for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3207 count >= 0; count--) {
3208 if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) {
3209 *sclk_mask = count;
3210 break;
3211 }
3212 }
3213 if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
3214 *sclk_mask = 0;
3215
3216 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3217 *sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3218 } else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3219 struct phm_ppt_v1_information *table_info =
3220 (struct phm_ppt_v1_information *)(hwmgr->pptable);
3221
3222 for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) {
3223 if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) {
3224 *sclk_mask = count;
3225 break;
3226 }
3227 }
3228 if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
3229 *sclk_mask = 0;
3230
3231 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3232 *sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
3233 }
3234
3235 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
3236 *mclk_mask = 0;
3237 else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3238 *mclk_mask = golden_dpm_table->mclk_table.count - 1;
3239
3240 *pcie_mask = data->dpm_table.pcie_speed_table.count - 1;
3241
3242 return 0;
3243}
3244
3245static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
3246 enum amd_dpm_forced_level level)
3247{
3248 int ret = 0;
3249 uint32_t sclk_mask = 0;
3250 uint32_t mclk_mask = 0;
3251 uint32_t pcie_mask = 0;
3252
3253 switch (level) {
3254 case AMD_DPM_FORCED_LEVEL_HIGH:
3255 ret = smu7_force_dpm_highest(hwmgr);
3256 break;
3257 case AMD_DPM_FORCED_LEVEL_LOW:
3258 ret = smu7_force_dpm_lowest(hwmgr);
3259 break;
3260 case AMD_DPM_FORCED_LEVEL_AUTO:
3261 ret = smu7_unforce_dpm_levels(hwmgr);
3262 break;
3263 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
3264 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
3265 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
3266 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
3267 ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask);
3268 if (ret)
3269 return ret;
3270 smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
3271 smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
3272 smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask);
3273 break;
3274 case AMD_DPM_FORCED_LEVEL_MANUAL:
3275 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
3276 default:
3277 break;
3278 }
3279
3280 if (!ret) {
3281 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3282 smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
3283 else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3284 smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
3285 }
3286 return ret;
3287}
3288
3289static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr)
3290{
3291 return sizeof(struct smu7_power_state);
3292}
3293
3294static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
3295 uint32_t vblank_time_us)
3296{
3297 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3298 uint32_t switch_limit_us;
3299
3300 switch (hwmgr->chip_id) {
3301 case CHIP_POLARIS10:
3302 case CHIP_POLARIS11:
3303 case CHIP_POLARIS12:
3304 if (hwmgr->is_kicker || (hwmgr->chip_id == CHIP_POLARIS12))
3305 switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3306 else
3307 switch_limit_us = data->is_memory_gddr5 ? 200 : 150;
3308 break;
3309 case CHIP_VEGAM:
3310 switch_limit_us = 30;
3311 break;
3312 default:
3313 switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3314 break;
3315 }
3316
3317 if (vblank_time_us < switch_limit_us)
3318 return true1;
3319 else
3320 return false0;
3321}
3322
3323static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
3324 struct pp_power_state *request_ps,
3325 const struct pp_power_state *current_ps)
3326{
3327 struct amdgpu_device *adev = hwmgr->adev;
3328 struct smu7_power_state *smu7_ps =
3329 cast_phw_smu7_power_state(&request_ps->hardware);
3330 uint32_t sclk;
3331 uint32_t mclk;
3332 struct PP_Clocks minimum_clocks = {0};
3333 bool_Bool disable_mclk_switching;
3334 bool_Bool disable_mclk_switching_for_frame_lock;
3335 bool_Bool disable_mclk_switching_for_display;
3336 const struct phm_clock_and_voltage_limits *max_limits;
3337 uint32_t i;
3338 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3339 struct phm_ppt_v1_information *table_info =
3340 (struct phm_ppt_v1_information *)(hwmgr->pptable);
3341 int32_t count;
3342 int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
3343 uint32_t latency;
3344 bool_Bool latency_allowed = false0;
3345
3346 data->battery_state = (PP_StateUILabel_Battery ==
3347 request_ps->classification.ui_label);
3348 data->mclk_ignore_signal = false0;
3349
3350 max_limits = adev->pm.ac_power ?
3351 &(hwmgr->dyn_state.max_clock_voltage_on_ac) :
3352 &(hwmgr->dyn_state.max_clock_voltage_on_dc);
3353
3354 /* Cap clock DPM tables at DC MAX if it is in DC. */
3355 if (!adev->pm.ac_power) {
3356 for (i = 0; i < smu7_ps->performance_level_count; i++) {
3357 if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk)
3358 smu7_ps->performance_levels[i].memory_clock = max_limits->mclk;
3359 if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk)
3360 smu7_ps->performance_levels[i].engine_clock = max_limits->sclk;
3361 }
3362 }
3363
3364 minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock;
3365 minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
3366
3367 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3368 PHM_PlatformCaps_StablePState)) {
3369 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
3370 stable_pstate_sclk = (max_limits->sclk * 75) / 100;
3371
3372 for (count = table_info->vdd_dep_on_sclk->count - 1;
3373 count >= 0; count--) {
3374 if (stable_pstate_sclk >=
3375 table_info->vdd_dep_on_sclk->entries[count].clk) {
3376 stable_pstate_sclk =
3377 table_info->vdd_dep_on_sclk->entries[count].clk;
3378 break;
3379 }
3380 }
3381
3382 if (count < 0)
3383 stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
3384
3385 stable_pstate_mclk = max_limits->mclk;
3386
3387 minimum_clocks.engineClock = stable_pstate_sclk;
3388 minimum_clocks.memoryClock = stable_pstate_mclk;
3389 }
3390
3391 disable_mclk_switching_for_frame_lock = phm_cap_enabled(
3392 hwmgr->platform_descriptor.platformCaps,
3393 PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
3394
3395 disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) &&
3396 !hwmgr->display_config->multi_monitor_in_sync) ||
3397 (hwmgr->display_config->num_display &&
3398 smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time));
3399
3400 disable_mclk_switching = disable_mclk_switching_for_frame_lock ||
3401 disable_mclk_switching_for_display;
3402
3403 if (hwmgr->display_config->num_display == 0) {
3404 if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
3405 data->mclk_ignore_signal = true1;
3406 else
3407 disable_mclk_switching = false0;
3408 }
3409
3410 sclk = smu7_ps->performance_levels[0].engine_clock;
3411 mclk = smu7_ps->performance_levels[0].memory_clock;
3412
3413 if (disable_mclk_switching &&
3414 (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3415 hwmgr->chip_id <= CHIP_VEGAM)))
3416 mclk = smu7_ps->performance_levels
3417 [smu7_ps->performance_level_count - 1].memory_clock;
3418
3419 if (sclk < minimum_clocks.engineClock)
3420 sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
3421 max_limits->sclk : minimum_clocks.engineClock;
3422
3423 if (mclk < minimum_clocks.memoryClock)
3424 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
3425 max_limits->mclk : minimum_clocks.memoryClock;
3426
3427 smu7_ps->performance_levels[0].engine_clock = sclk;
3428 smu7_ps->performance_levels[0].memory_clock = mclk;
3429
3430 smu7_ps->performance_levels[1].engine_clock =
3431 (smu7_ps->performance_levels[1].engine_clock >=
3432 smu7_ps->performance_levels[0].engine_clock) ?
3433 smu7_ps->performance_levels[1].engine_clock :
3434 smu7_ps->performance_levels[0].engine_clock;
3435
3436 if (disable_mclk_switching) {
3437 if (mclk < smu7_ps->performance_levels[1].memory_clock)
3438 mclk = smu7_ps->performance_levels[1].memory_clock;
3439
3440 if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) {
3441 if (disable_mclk_switching_for_display) {
3442 /* Find the lowest MCLK frequency that is within
3443 * the tolerable latency defined in DAL
3444 */
3445 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3446 for (i = 0; i < data->mclk_latency_table.count; i++) {
3447 if (data->mclk_latency_table.entries[i].latency <= latency) {
3448 latency_allowed = true1;
3449
3450 if ((data->mclk_latency_table.entries[i].frequency >=
3451 smu7_ps->performance_levels[0].memory_clock) &&
3452 (data->mclk_latency_table.entries[i].frequency <=
3453 smu7_ps->performance_levels[1].memory_clock)) {
3454 mclk = data->mclk_latency_table.entries[i].frequency;
3455 break;
3456 }
3457 }
3458 }
3459 if ((i >= data->mclk_latency_table.count - 1) && !latency_allowed) {
3460 data->mclk_ignore_signal = true1;
3461 } else {
3462 data->mclk_ignore_signal = false0;
3463 }
3464 }
3465
3466 if (disable_mclk_switching_for_frame_lock)
3467 mclk = smu7_ps->performance_levels[1].memory_clock;
3468 }
3469
3470 smu7_ps->performance_levels[0].memory_clock = mclk;
3471
3472 if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3473 hwmgr->chip_id <= CHIP_VEGAM))
3474 smu7_ps->performance_levels[1].memory_clock = mclk;
3475 } else {
3476 if (smu7_ps->performance_levels[1].memory_clock <
3477 smu7_ps->performance_levels[0].memory_clock)
3478 smu7_ps->performance_levels[1].memory_clock =
3479 smu7_ps->performance_levels[0].memory_clock;
3480 }
3481
3482 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3483 PHM_PlatformCaps_StablePState)) {
3484 for (i = 0; i < smu7_ps->performance_level_count; i++) {
3485 smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
3486 smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
3487 smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
3488 smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
3489 }
3490 }
3491 return 0;
3492}
3493
3494
3495static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool_Bool low)
3496{
3497 struct pp_power_state *ps;
3498 struct smu7_power_state *smu7_ps;
3499
3500 if (hwmgr == NULL((void *)0))
3501 return -EINVAL22;
3502
3503 ps = hwmgr->request_ps;
3504
3505 if (ps == NULL((void *)0))
3506 return -EINVAL22;
3507
3508 smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3509
3510 if (low)
3511 return smu7_ps->performance_levels[0].memory_clock;
3512 else
3513 return smu7_ps->performance_levels
3514 [smu7_ps->performance_level_count-1].memory_clock;
3515}
3516
3517static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool_Bool low)
3518{
3519 struct pp_power_state *ps;
3520 struct smu7_power_state *smu7_ps;
3521
3522 if (hwmgr == NULL((void *)0))
3523 return -EINVAL22;
3524
3525 ps = hwmgr->request_ps;
3526
3527 if (ps == NULL((void *)0))
3528 return -EINVAL22;
3529
3530 smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3531
3532 if (low)
3533 return smu7_ps->performance_levels[0].engine_clock;
3534 else
3535 return smu7_ps->performance_levels
3536 [smu7_ps->performance_level_count-1].engine_clock;
3537}
3538
3539static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
3540 struct pp_hw_power_state *hw_ps)
3541{
3542 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3543 struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps;
3544 ATOM_FIRMWARE_INFO_V2_2 *fw_info;
3545 uint16_t size;
3546 uint8_t frev, crev;
3547 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo)(__builtin_offsetof(ATOM_MASTER_LIST_OF_DATA_TABLES, FirmwareInfo
) / sizeof(USHORT))
;
3548
3549 /* First retrieve the Boot clocks and VDDC from the firmware info table.
3550 * We assume here that fw_info is unchanged if this call fails.
3551 */
3552 fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index,
3553 &size, &frev, &crev);
3554 if (!fw_info)
3555 /* During a test, there is no firmware info table. */
3556 return 0;
3557
3558 /* Patch the state. */
3559 data->vbios_boot_state.sclk_bootup_value =
3560 le32_to_cpu(fw_info->ulDefaultEngineClock)((__uint32_t)(fw_info->ulDefaultEngineClock));
3561 data->vbios_boot_state.mclk_bootup_value =
3562 le32_to_cpu(fw_info->ulDefaultMemoryClock)((__uint32_t)(fw_info->ulDefaultMemoryClock));
3563 data->vbios_boot_state.mvdd_bootup_value =
3564 le16_to_cpu(fw_info->usBootUpMVDDCVoltage)((__uint16_t)(fw_info->usBootUpMVDDCVoltage));
3565 data->vbios_boot_state.vddc_bootup_value =
3566 le16_to_cpu(fw_info->usBootUpVDDCVoltage)((__uint16_t)(fw_info->usBootUpVDDCVoltage));
3567 data->vbios_boot_state.vddci_bootup_value =
3568 le16_to_cpu(fw_info->usBootUpVDDCIVoltage)((__uint16_t)(fw_info->usBootUpVDDCIVoltage));
3569 data->vbios_boot_state.pcie_gen_bootup_value =
3570 smu7_get_current_pcie_speed(hwmgr);
3571
3572 data->vbios_boot_state.pcie_lane_bootup_value =
3573 (uint16_t)smu7_get_current_pcie_lane_number(hwmgr);
3574
3575 /* set boot power state */
3576 ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
3577 ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
3578 ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
3579 ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
3580
3581 return 0;
3582}
3583
3584static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
3585{
3586 int result;
3587 unsigned long ret = 0;
3588
3589 if (hwmgr->pp_table_version == PP_TABLE_V0) {
3590 result = pp_tables_get_num_of_entries(hwmgr, &ret);
3591 return result ? 0 : ret;
3592 } else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3593 result = get_number_of_powerplay_table_entries_v1_0(hwmgr);
3594 return result;
3595 }
3596 return 0;
3597}
3598
3599static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr,
3600 void *state, struct pp_power_state *power_state,
3601 void *pp_table, uint32_t classification_flag)
3602{
3603 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3604 struct smu7_power_state *smu7_power_state =
3605 (struct smu7_power_state *)(&(power_state->hardware));
3606 struct smu7_performance_level *performance_level;
3607 ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
3608 ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
3609 (ATOM_Tonga_POWERPLAYTABLE *)pp_table;
3610 PPTable_Generic_SubTable_Header *sclk_dep_table =
3611 (PPTable_Generic_SubTable_Header *)
3612 (((unsigned long)powerplay_table) +
3613 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)((__uint16_t)(powerplay_table->usSclkDependencyTableOffset
))
);
3614
3615 ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
3616 (ATOM_Tonga_MCLK_Dependency_Table *)
3617 (((unsigned long)powerplay_table) +
3618 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)((__uint16_t)(powerplay_table->usMclkDependencyTableOffset
))
);
3619
3620 /* The following fields are not initialized here: id orderedList allStatesList */
3621 power_state->classification.ui_label =
3622 (le16_to_cpu(state_entry->usClassification)((__uint16_t)(state_entry->usClassification)) &
3623 ATOM_PPLIB_CLASSIFICATION_UI_MASK0x0007) >>
3624 ATOM_PPLIB_CLASSIFICATION_UI_SHIFT0;
3625 power_state->classification.flags = classification_flag;
3626 /* NOTE: There is a classification2 flag in BIOS that is not being used right now */
3627
3628 power_state->classification.temporary_state = false0;
3629 power_state->classification.to_be_deleted = false0;
3630
3631 power_state->validation.disallowOnDC =
3632 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings)((__uint32_t)(state_entry->ulCapsAndSettings)) &
3633 ATOM_Tonga_DISALLOW_ON_DC0x00004000));
3634
3635 power_state->pcie.lanes = 0;
3636
3637 power_state->display.disableFrameModulation = false0;
3638 power_state->display.limitRefreshrate = false0;
3639 power_state->display.enableVariBright =
3640 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings)((__uint32_t)(state_entry->ulCapsAndSettings)) &
3641 ATOM_Tonga_ENABLE_VARIBRIGHT0x00008000));
3642
3643 power_state->validation.supportedPowerLevels = 0;
3644 power_state->uvd_clocks.VCLK = 0;
3645 power_state->uvd_clocks.DCLK = 0;
3646 power_state->temperatures.min = 0;
3647 power_state->temperatures.max = 0;
3648
3649 performance_level = &(smu7_power_state->performance_levels
3650 [smu7_power_state->performance_level_count++]);
3651
3652 PP_ASSERT_WITH_CODE(do { if (!((smu7_power_state->performance_level_count <
smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) {
printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds SMC limit!"
); return -22; } } while (0)
3653 (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),do { if (!((smu7_power_state->performance_level_count <
smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) {
printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds SMC limit!"
); return -22; } } while (0)
3654 "Performance levels exceeds SMC limit!",do { if (!((smu7_power_state->performance_level_count <
smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) {
printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds SMC limit!"
); return -22; } } while (0)
3655 return -EINVAL)do { if (!((smu7_power_state->performance_level_count <
smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) {
printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds SMC limit!"
); return -22; } } while (0)
;
3656
3657 PP_ASSERT_WITH_CODE(do { if (!((smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels
))) { printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds Driver limit!"
); return -22; } } while (0)
3658 (smu7_power_state->performance_level_count <do { if (!((smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels
))) { printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds Driver limit!"
); return -22; } } while (0)
3659 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),do { if (!((smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels
))) { printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds Driver limit!"
); return -22; } } while (0)
3660 "Performance levels exceeds Driver limit!",do { if (!((smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels
))) { printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds Driver limit!"
); return -22; } } while (0)
3661 return -EINVAL)do { if (!((smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels
))) { printk("\0014" "amdgpu: " "%s\n", "Performance levels exceeds Driver limit!"
); return -22; } } while (0)
;
3662
3663 /* Performance levels are arranged from low to high. */
3664 performance_level->memory_clock = mclk_dep_table->entries
3665 [state_entry->ucMemoryClockIndexLow].ulMclk;
3666 if (sclk_dep_table->ucRevId == 0)
3667 performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3668 [state_entry->ucEngineClockIndexLow].ulSclk;
3669 else if (sclk_dep_table->ucRevId == 1)
3670 performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3671 [state_entry->ucEngineClockIndexLow].ulSclk;
3672 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3673 state_entry->ucPCIEGenLow);
3674 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3675 state_entry->ucPCIELaneLow);
3676
3677 performance_level = &(smu7_power_state->performance_levels
3678 [smu7_power_state->performance_level_count++]);
3679 performance_level->memory_clock = mclk_dep_table->entries
3680 [state_entry->ucMemoryClockIndexHigh].ulMclk;
3681
3682 if (sclk_dep_table->ucRevId == 0)
3683 performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3684 [state_entry->ucEngineClockIndexHigh].ulSclk;
3685 else if (sclk_dep_table->ucRevId == 1)
3686 performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3687 [state_entry->ucEngineClockIndexHigh].ulSclk;
3688
3689 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3690 state_entry->ucPCIEGenHigh);
3691 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3692 state_entry->ucPCIELaneHigh);
3693
3694 return 0;
3695}
3696
3697static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr,
3698 unsigned long entry_index, struct pp_power_state *state)
3699{
3700 int result;
3701 struct smu7_power_state *ps;
3702 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3703 struct phm_ppt_v1_information *table_info =
3704 (struct phm_ppt_v1_information *)(hwmgr->pptable);
3705 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
3706 table_info->vdd_dep_on_mclk;
3707
3708 state->hardware.magic = PHM_VIslands_Magic;
3709
3710 ps = (struct smu7_power_state *)(&state->hardware);
3711
3712 result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state,
3713 smu7_get_pp_table_entry_callback_func_v1);
3714
3715 /* This is the earliest time we have all the dependency table and the VBIOS boot state
3716 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
3717 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
3718 */
3719 if (dep_mclk_table != NULL((void *)0) && dep_mclk_table->count == 1) {
3720 if (dep_mclk_table->entries[0].clk !=
3721 data->vbios_boot_state.mclk_bootup_value)
3722 pr_debug("Single MCLK entry VDDCI/MCLK dependency table "do { } while(0)
3723 "does not match VBIOS boot MCLK level")do { } while(0);
3724 if (dep_mclk_table->entries[0].vddci !=
3725 data->vbios_boot_state.vddci_bootup_value)
3726 pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "do { } while(0)
3727 "does not match VBIOS boot VDDCI level")do { } while(0);
3728 }
3729
3730 /* set DC compatible flag if this state supports DC */
3731 if (!state->validation.disallowOnDC)
3732 ps->dc_compatible = true1;
3733
3734 if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3735 data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3736
3737 ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3738 ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3739
3740 if (!result) {
3741 uint32_t i;
3742
3743 switch (state->classification.ui_label) {
3744 case PP_StateUILabel_Performance:
3745 data->use_pcie_performance_levels = true1;
3746 for (i = 0; i < ps->performance_level_count; i++) {
3747 if (data->pcie_gen_performance.max <
3748 ps->performance_levels[i].pcie_gen)
3749 data->pcie_gen_performance.max =
3750 ps->performance_levels[i].pcie_gen;
3751
3752 if (data->pcie_gen_performance.min >
3753 ps->performance_levels[i].pcie_gen)
3754 data->pcie_gen_performance.min =
3755 ps->performance_levels[i].pcie_gen;
3756
3757 if (data->pcie_lane_performance.max <
3758 ps->performance_levels[i].pcie_lane)
3759 data->pcie_lane_performance.max =
3760 ps->performance_levels[i].pcie_lane;
3761 if (data->pcie_lane_performance.min >
3762 ps->performance_levels[i].pcie_lane)
3763 data->pcie_lane_performance.min =
3764 ps->performance_levels[i].pcie_lane;
3765 }
3766 break;
3767 case PP_StateUILabel_Battery:
3768 data->use_pcie_power_saving_levels = true1;
3769
3770 for (i = 0; i < ps->performance_level_count; i++) {
3771 if (data->pcie_gen_power_saving.max <
3772 ps->performance_levels[i].pcie_gen)
3773 data->pcie_gen_power_saving.max =
3774 ps->performance_levels[i].pcie_gen;
3775
3776 if (data->pcie_gen_power_saving.min >
3777 ps->performance_levels[i].pcie_gen)
3778 data->pcie_gen_power_saving.min =
3779 ps->performance_levels[i].pcie_gen;
3780
3781 if (data->pcie_lane_power_saving.max <
3782 ps->performance_levels[i].pcie_lane)
3783 data->pcie_lane_power_saving.max =
3784 ps->performance_levels[i].pcie_lane;
3785
3786 if (data->pcie_lane_power_saving.min >
3787 ps->performance_levels[i].pcie_lane)
3788 data->pcie_lane_power_saving.min =
3789 ps->performance_levels[i].pcie_lane;
3790 }
3791 break;
3792 default:
3793 break;
3794 }
3795 }
3796 return 0;
3797}
3798
3799static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr,
3800 struct pp_hw_power_state *power_state,
3801 unsigned int index, const void *clock_info)
3802{
3803 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3804 struct smu7_power_state *ps = cast_phw_smu7_power_state(power_state);
3805 const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info;
3806 struct smu7_performance_level *performance_level;
3807 uint32_t engine_clock, memory_clock;
3808 uint16_t pcie_gen_from_bios;
3809
3810 engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow;
3811 memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow;
3812
3813 if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE1) && memory_clock > data->highest_mclk)
3814 data->highest_mclk = memory_clock;
3815
3816 PP_ASSERT_WITH_CODE(do { if (!((ps->performance_level_count < smum_get_mac_definition
(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds SMC limit!"); return -22
; } } while (0)
3817 (ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),do { if (!((ps->performance_level_count < smum_get_mac_definition
(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds SMC limit!"); return -22
; } } while (0)
3818 "Performance levels exceeds SMC limit!",do { if (!((ps->performance_level_count < smum_get_mac_definition
(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds SMC limit!"); return -22
; } } while (0)
3819 return -EINVAL)do { if (!((ps->performance_level_count < smum_get_mac_definition
(hwmgr, SMU_MAX_LEVELS_GRAPHICS)))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds SMC limit!"); return -22
; } } while (0)
;
3820
3821 PP_ASSERT_WITH_CODE(do { if (!((ps->performance_level_count < hwmgr->platform_descriptor
.hardwareActivityPerformanceLevels))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds Driver limit, Skip!"); return
0; } } while (0)
3822 (ps->performance_level_count <do { if (!((ps->performance_level_count < hwmgr->platform_descriptor
.hardwareActivityPerformanceLevels))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds Driver limit, Skip!"); return
0; } } while (0)
3823 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),do { if (!((ps->performance_level_count < hwmgr->platform_descriptor
.hardwareActivityPerformanceLevels))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds Driver limit, Skip!"); return
0; } } while (0)
3824 "Performance levels exceeds Driver limit, Skip!",do { if (!((ps->performance_level_count < hwmgr->platform_descriptor
.hardwareActivityPerformanceLevels))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds Driver limit, Skip!"); return
0; } } while (0)
3825 return 0)do { if (!((ps->performance_level_count < hwmgr->platform_descriptor
.hardwareActivityPerformanceLevels))) { printk("\0014" "amdgpu: "
"%s\n", "Performance levels exceeds Driver limit, Skip!"); return
0; } } while (0)
;
3826
3827 performance_level = &(ps->performance_levels
3828 [ps->performance_level_count++]);
3829
3830 /* Performance levels are arranged from low to high. */
3831 performance_level->memory_clock = memory_clock;
3832 performance_level->engine_clock = engine_clock;
3833
3834 pcie_gen_from_bios = visland_clk_info->ucPCIEGen;
3835
3836 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios);
3837 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane);
3838
3839 return 0;
3840}
3841
3842static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr,
3843 unsigned long entry_index, struct pp_power_state *state)
3844{
3845 int result;
3846 struct smu7_power_state *ps;
3847 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3848 struct phm_clock_voltage_dependency_table *dep_mclk_table =
3849 hwmgr->dyn_state.vddci_dependency_on_mclk;
3850
3851 memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state))__builtin_memset((&state->hardware), (0x00), (sizeof(struct
pp_hw_power_state)))
;
3852
3853 state->hardware.magic = PHM_VIslands_Magic;
3854
3855 ps = (struct smu7_power_state *)(&state->hardware);
3856
3857 result = pp_tables_get_entry(hwmgr, entry_index, state,
3858 smu7_get_pp_table_entry_callback_func_v0);
3859
3860 /*
3861 * This is the earliest time we have all the dependency table
3862 * and the VBIOS boot state as
3863 * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot
3864 * state if there is only one VDDCI/MCLK level, check if it's
3865 * the same as VBIOS boot state
3866 */
3867 if (dep_mclk_table != NULL((void *)0) && dep_mclk_table->count == 1) {
3868 if (dep_mclk_table->entries[0].clk !=
3869 data->vbios_boot_state.mclk_bootup_value)
3870 pr_debug("Single MCLK entry VDDCI/MCLK dependency table "do { } while(0)
3871 "does not match VBIOS boot MCLK level")do { } while(0);
3872 if (dep_mclk_table->entries[0].v !=
3873 data->vbios_boot_state.vddci_bootup_value)
3874 pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "do { } while(0)
3875 "does not match VBIOS boot VDDCI level")do { } while(0);
3876 }
3877
3878 /* set DC compatible flag if this state supports DC */
3879 if (!state->validation.disallowOnDC)
3880 ps->dc_compatible = true1;
3881
3882 if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3883 data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3884
3885 ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3886 ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3887
3888 if (!result) {
3889 uint32_t i;
3890
3891 switch (state->classification.ui_label) {
3892 case PP_StateUILabel_Performance:
3893 data->use_pcie_performance_levels = true1;
3894
3895 for (i = 0; i < ps->performance_level_count; i++) {
3896 if (data->pcie_gen_performance.max <
3897 ps->performance_levels[i].pcie_gen)
3898 data->pcie_gen_performance.max =
3899 ps->performance_levels[i].pcie_gen;
3900
3901 if (data->pcie_gen_performance.min >
3902 ps->performance_levels[i].pcie_gen)
3903 data->pcie_gen_performance.min =
3904 ps->performance_levels[i].pcie_gen;
3905
3906 if (data->pcie_lane_performance.max <
3907 ps->performance_levels[i].pcie_lane)
3908 data->pcie_lane_performance.max =
3909 ps->performance_levels[i].pcie_lane;
3910
3911 if (data->pcie_lane_performance.min >
3912 ps->performance_levels[i].pcie_lane)
3913 data->pcie_lane_performance.min =
3914 ps->performance_levels[i].pcie_lane;
3915 }
3916 break;
3917 case PP_StateUILabel_Battery:
3918 data->use_pcie_power_saving_levels = true1;
3919
3920 for (i = 0; i < ps->performance_level_count; i++) {
3921 if (data->pcie_gen_power_saving.max <
3922 ps->performance_levels[i].pcie_gen)
3923 data->pcie_gen_power_saving.max =
3924 ps->performance_levels[i].pcie_gen;
3925
3926 if (data->pcie_gen_power_saving.min >
3927 ps->performance_levels[i].pcie_gen)
3928 data->pcie_gen_power_saving.min =
3929 ps->performance_levels[i].pcie_gen;
3930
3931 if (data->pcie_lane_power_saving.max <
3932 ps->performance_levels[i].pcie_lane)
3933 data->pcie_lane_power_saving.max =
3934 ps->performance_levels[i].pcie_lane;
3935
3936 if (data->pcie_lane_power_saving.min >
3937 ps->performance_levels[i].pcie_lane)
3938 data->pcie_lane_power_saving.min =
3939 ps->performance_levels[i].pcie_lane;
3940 }
3941 break;
3942 default:
3943 break;
3944 }
3945 }
3946 return 0;
3947}
3948
3949static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr,
3950 unsigned long entry_index, struct pp_power_state *state)
3951{
3952 if (hwmgr->pp_table_version == PP_TABLE_V0)
3953 return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state);
3954 else if (hwmgr->pp_table_version == PP_TABLE_V1)
3955 return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state);
3956
3957 return 0;
3958}
3959
3960static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query)
3961{
3962 struct amdgpu_device *adev = hwmgr->adev;
3963 int i;
3964 u32 tmp = 0;
3965
3966 if (!query)
3967 return -EINVAL22;
3968
3969 /*
3970 * PPSMC_MSG_GetCurrPkgPwr is not supported on:
3971 * - Hawaii
3972 * - Bonaire
3973 * - Fiji
3974 * - Tonga
3975 */
3976 if ((adev->asic_type != CHIP_HAWAII) &&
3977 (adev->asic_type != CHIP_BONAIRE) &&
3978 (adev->asic_type != CHIP_FIJI) &&
3979 (adev->asic_type != CHIP_TONGA)) {
3980 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr((uint16_t) 0x282), 0, &tmp);
3981 *query = tmp;
3982
3983 if (tmp != 0)
3984 return 0;
3985 }
3986
3987 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart((uint16_t) 0x170), NULL((void *)0));
3988 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3ff7c,0))
3989 ixSMU_PM_STATUS_95, 0)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3ff7c,0))
;
3990
3991 for (i = 0; i < 10; i++) {
3992 drm_msleep(500)mdelay(500);
3993 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample((uint16_t) 0x171), NULL((void *)0));
3994 tmp = cgs_read_ind_register(hwmgr->device,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3ff7c))
3995 CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3ff7c))
3996 ixSMU_PM_STATUS_95)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0x3ff7c))
;
3997 if (tmp != 0)
3998 break;
3999 }
4000 *query = tmp;
4001
4002 return 0;
4003}
4004
4005static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx,
4006 void *value, int *size)
4007{
4008 uint32_t sclk, mclk, activity_percent;
4009 uint32_t offset, val_vid;
4010 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4011
4012 /* size must be at least 4 bytes for all sensors */
4013 if (*size < 4)
4014 return -EINVAL22;
4015
4016 switch (idx) {
4017 case AMDGPU_PP_SENSOR_GFX_SCLK:
4018 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency((uint16_t) 0x200), &sclk);
4019 *((uint32_t *)value) = sclk;
4020 *size = 4;
4021 return 0;
4022 case AMDGPU_PP_SENSOR_GFX_MCLK:
4023 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency((uint16_t) 0x201), &mclk);
4024 *((uint32_t *)value) = mclk;
4025 *size = 4;
4026 return 0;
4027 case AMDGPU_PP_SENSOR_GPU_LOAD:
4028 case AMDGPU_PP_SENSOR_MEM_LOAD:
4029 offset = data->soft_regs_start + smum_get_offsetof(hwmgr,
4030 SMU_SoftRegisters,
4031 (idx == AMDGPU_PP_SENSOR_GPU_LOAD) ?
4032 AverageGraphicsActivity:
4033 AverageMemoryActivity);
4034
4035 activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,offset))
;
4036 activity_percent += 0x80;
4037 activity_percent >>= 8;
4038 *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
4039 *size = 4;
4040 return 0;
4041 case AMDGPU_PP_SENSOR_GPU_TEMP:
4042 *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr);
4043 *size = 4;
4044 return 0;
4045 case AMDGPU_PP_SENSOR_UVD_POWER:
4046 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
4047 *size = 4;
4048 return 0;
4049 case AMDGPU_PP_SENSOR_VCE_POWER:
4050 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
4051 *size = 4;
4052 return 0;
4053 case AMDGPU_PP_SENSOR_GPU_POWER:
4054 return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
4055 case AMDGPU_PP_SENSOR_VDDGFX:
4056 if ((data->vr_config & VRCONF_VDDGFX_MASK0x0000FF00) ==
4057 (VR_SVI2_PLANE_22 << VRCONF_VDDGFX_SHIFT8))
4058 val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200294))) & 0x0000ff00
) >> 0x00000008)
4059 CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID)((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200294))) & 0x0000ff00
) >> 0x00000008)
;
4060 else
4061 val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200294))) & 0x000000ff
) >> 0x00000000)
4062 CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID)((((((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xC0200294))) & 0x000000ff
) >> 0x00000000)
;
4063
4064 *((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid);
4065 return 0;
4066 default:
4067 return -EOPNOTSUPP45;
4068 }
4069}
4070
4071static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
4072{
4073 const struct phm_set_power_state_input *states =
4074 (const struct phm_set_power_state_input *)input;
4075 const struct smu7_power_state *smu7_ps =
4076 cast_const_phw_smu7_power_state(states->pnew_state);
4077 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4078 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4079 uint32_t sclk = smu7_ps->performance_levels
4080 [smu7_ps->performance_level_count - 1].engine_clock;
4081 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
4082 uint32_t mclk = smu7_ps->performance_levels
4083 [smu7_ps->performance_level_count - 1].memory_clock;
4084 struct PP_Clocks min_clocks = {0};
4085 uint32_t i;
4086
4087 for (i = 0; i < sclk_table->count; i++) {
4088 if (sclk == sclk_table->dpm_levels[i].value)
4089 break;
4090 }
4091
4092 if (i >= sclk_table->count) {
4093 if (sclk > sclk_table->dpm_levels[i-1].value) {
4094 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK0x00000001;
4095 sclk_table->dpm_levels[i-1].value = sclk;
4096 }
4097 } else {
4098 /* TODO: Check SCLK in DAL's minimum clocks
4099 * in case DeepSleep divider update is required.
4100 */
4101 if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR &&
4102 (min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK2500 ||
4103 data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK2500))
4104 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK0x00000004;
4105 }
4106
4107 for (i = 0; i < mclk_table->count; i++) {
4108 if (mclk == mclk_table->dpm_levels[i].value)
4109 break;
4110 }
4111
4112 if (i >= mclk_table->count) {
4113 if (mclk > mclk_table->dpm_levels[i-1].value) {
4114 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK0x00000002;
4115 mclk_table->dpm_levels[i-1].value = mclk;
4116 }
4117 }
4118
4119 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4120 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK0x00000008;
4121
4122 return 0;
4123}
4124
4125static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr,
4126 const struct smu7_power_state *smu7_ps)
4127{
4128 uint32_t i;
4129 uint32_t sclk, max_sclk = 0;
4130 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4131 struct smu7_dpm_table *dpm_table = &data->dpm_table;
4132
4133 for (i = 0; i < smu7_ps->performance_level_count; i++) {
4134 sclk = smu7_ps->performance_levels[i].engine_clock;
4135 if (max_sclk < sclk)
4136 max_sclk = sclk;
4137 }
4138
4139 for (i = 0; i < dpm_table->sclk_table.count; i++) {
4140 if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk)
4141 return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ?
4142 dpm_table->pcie_speed_table.dpm_levels
4143 [dpm_table->pcie_speed_table.count - 1].value :
4144 dpm_table->pcie_speed_table.dpm_levels[i].value);
4145 }
4146
4147 return 0;
4148}
4149
4150static int smu7_request_link_speed_change_before_state_change(
4151 struct pp_hwmgr *hwmgr, const void *input)
4152{
4153 const struct phm_set_power_state_input *states =
4154 (const struct phm_set_power_state_input *)input;
4155 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4156 const struct smu7_power_state *smu7_nps =
4157 cast_const_phw_smu7_power_state(states->pnew_state);
4158 const struct smu7_power_state *polaris10_cps =
4159 cast_const_phw_smu7_power_state(states->pcurrent_state);
4160
4161 uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps);
4162 uint16_t current_link_speed;
4163
4164 if (data->force_pcie_gen == PP_PCIEGenInvalid0xffff)
4165 current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps);
4166 else
4167 current_link_speed = data->force_pcie_gen;
4168
4169 data->force_pcie_gen = PP_PCIEGenInvalid0xffff;
4170 data->pspp_notify_required = false0;
4171
4172 if (target_link_speed > current_link_speed) {
4173 switch (target_link_speed) {
4174#ifdef CONFIG_ACPI1
4175 case PP_PCIEGen3:
4176 if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN34, false0))
4177 break;
4178 data->force_pcie_gen = PP_PCIEGen2;
4179 if (current_link_speed == PP_PCIEGen2)
4180 break;
4181 fallthroughdo {} while (0);
4182 case PP_PCIEGen2:
4183 if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN23, false0))
4184 break;
4185 fallthroughdo {} while (0);
4186#endif
4187 default:
4188 data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr);
4189 break;
4190 }
4191 } else {
4192 if (target_link_speed < current_link_speed)
4193 data->pspp_notify_required = true1;
4194 }
4195
4196 return 0;
4197}
4198
4199static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4200{
4201 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4202
4203 if (0 == data->need_update_smu7_dpm_table)
4204 return 0;
4205
4206 if ((0 == data->sclk_dpm_key_disabled) &&
4207 (data->need_update_smu7_dpm_table &
4208 (DPMTABLE_OD_UPDATE_SCLK0x00000001 + DPMTABLE_UPDATE_SCLK0x00000004))) {
4209 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze SCLK DPM when DPM is disabled"
); ; } } while (0)
4210 "Trying to freeze SCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze SCLK DPM when DPM is disabled"
); ; } } while (0)
4211 )do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze SCLK DPM when DPM is disabled"
); ; } } while (0)
;
4212 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x189
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4213 PPSMC_MSG_SCLKDPM_FreezeLevel,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x189
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4214 NULL),do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x189
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4215 "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x189
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4216 return -EINVAL)do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x189
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
;
4217 }
4218
4219 if ((0 == data->mclk_dpm_key_disabled) &&
4220 !data->mclk_ignore_signal &&
4221 (data->need_update_smu7_dpm_table &
4222 DPMTABLE_OD_UPDATE_MCLK0x00000002)) {
4223 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze MCLK DPM when DPM is disabled"
); ; } } while (0)
4224 "Trying to freeze MCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze MCLK DPM when DPM is disabled"
); ; } } while (0)
4225 )do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to freeze MCLK DPM when DPM is disabled"
); ; } } while (0)
;
4226 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18B
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4227 PPSMC_MSG_MCLKDPM_FreezeLevel,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18B
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4228 NULL),do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18B
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4229 "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18B
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4230 return -EINVAL)do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18B
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!"
); return -22; } } while (0)
;
4231 }
4232
4233 return 0;
4234}
4235
4236static int smu7_populate_and_upload_sclk_mclk_dpm_levels(
4237 struct pp_hwmgr *hwmgr, const void *input)
4238{
4239 int result = 0;
4240 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4241 struct smu7_dpm_table *dpm_table = &data->dpm_table;
4242 uint32_t count;
4243 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4244 struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4245 struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4246
4247 if (0 == data->need_update_smu7_dpm_table)
4248 return 0;
4249
4250 if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK0x00000001) {
4251 for (count = 0; count < dpm_table->sclk_table.count; count++) {
4252 dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled;
4253 dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock;
4254 }
4255 }
4256
4257 if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK0x00000002) {
4258 for (count = 0; count < dpm_table->mclk_table.count; count++) {
4259 dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled;
4260 dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock;
4261 }
4262 }
4263
4264 if (data->need_update_smu7_dpm_table &
4265 (DPMTABLE_OD_UPDATE_SCLK0x00000001 + DPMTABLE_UPDATE_SCLK0x00000004)) {
4266 result = smum_populate_all_graphic_levels(hwmgr);
4267 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate SCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
4268 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate SCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
4269 return result)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate SCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
;
4270 }
4271
4272 if (data->need_update_smu7_dpm_table &
4273 (DPMTABLE_OD_UPDATE_MCLK0x00000002 + DPMTABLE_UPDATE_MCLK0x00000008)) {
4274 /*populate MCLK dpm table to SMU7 */
4275 result = smum_populate_all_memory_levels(hwmgr);
4276 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate MCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
4277 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate MCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
4278 return result)do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate MCLK during PopulateNewDPMClocksStates Function!"
); return result; } } while (0)
;
4279 }
4280
4281 return result;
4282}
4283
4284static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
4285 struct smu7_single_dpm_table *dpm_table,
4286 uint32_t low_limit, uint32_t high_limit)
4287{
4288 uint32_t i;
4289
4290 /* force the trim if mclk_switching is disabled to prevent flicker */
4291 bool_Bool force_trim = (low_limit == high_limit);
4292 for (i = 0; i < dpm_table->count; i++) {
4293 /*skip the trim if od is enabled*/
4294 if ((!hwmgr->od_enabled || force_trim)
4295 && (dpm_table->dpm_levels[i].value < low_limit
4296 || dpm_table->dpm_levels[i].value > high_limit))
4297 dpm_table->dpm_levels[i].enabled = false0;
4298 else
4299 dpm_table->dpm_levels[i].enabled = true1;
4300 }
4301
4302 return 0;
4303}
4304
4305static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr,
4306 const struct smu7_power_state *smu7_ps)
4307{
4308 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4309 uint32_t high_limit_count;
4310
4311 PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1),do { if (!((smu7_ps->performance_level_count >= 1))) { printk
("\0014" "amdgpu: " "%s\n", "power state did not have any performance level"
); return -22; } } while (0)
4312 "power state did not have any performance level",do { if (!((smu7_ps->performance_level_count >= 1))) { printk
("\0014" "amdgpu: " "%s\n", "power state did not have any performance level"
); return -22; } } while (0)
4313 return -EINVAL)do { if (!((smu7_ps->performance_level_count >= 1))) { printk
("\0014" "amdgpu: " "%s\n", "power state did not have any performance level"
); return -22; } } while (0)
;
4314
4315 high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1;
4316
4317 smu7_trim_single_dpm_states(hwmgr,
4318 &(data->dpm_table.sclk_table),
4319 smu7_ps->performance_levels[0].engine_clock,
4320 smu7_ps->performance_levels[high_limit_count].engine_clock);
4321
4322 smu7_trim_single_dpm_states(hwmgr,
4323 &(data->dpm_table.mclk_table),
4324 smu7_ps->performance_levels[0].memory_clock,
4325 smu7_ps->performance_levels[high_limit_count].memory_clock);
4326
4327 return 0;
4328}
4329
4330static int smu7_generate_dpm_level_enable_mask(
4331 struct pp_hwmgr *hwmgr, const void *input)
4332{
4333 int result = 0;
4334 const struct phm_set_power_state_input *states =
4335 (const struct phm_set_power_state_input *)input;
4336 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4337 const struct smu7_power_state *smu7_ps =
4338 cast_const_phw_smu7_power_state(states->pnew_state);
4339
4340
4341 result = smu7_trim_dpm_states(hwmgr, smu7_ps);
4342 if (result)
4343 return result;
4344
4345 data->dpm_level_enable_mask.sclk_dpm_enable_mask =
4346 phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
4347 data->dpm_level_enable_mask.mclk_dpm_enable_mask =
4348 phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
4349 data->dpm_level_enable_mask.pcie_dpm_enable_mask =
4350 phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
4351
4352 return 0;
4353}
4354
4355static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4356{
4357 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4358
4359 if (0 == data->need_update_smu7_dpm_table)
4360 return 0;
4361
4362 if ((0 == data->sclk_dpm_key_disabled) &&
4363 (data->need_update_smu7_dpm_table &
4364 (DPMTABLE_OD_UPDATE_SCLK0x00000001 + DPMTABLE_UPDATE_SCLK0x00000004))) {
4365
4366 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze SCLK DPM when DPM is disabled"
); ; } } while (0)
4367 "Trying to Unfreeze SCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze SCLK DPM when DPM is disabled"
); ; } } while (0)
4368 )do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze SCLK DPM when DPM is disabled"
); ; } } while (0)
;
4369 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18A
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4370 PPSMC_MSG_SCLKDPM_UnfreezeLevel,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18A
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4371 NULL),do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18A
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4372 "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18A
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4373 return -EINVAL)do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18A
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
;
4374 }
4375
4376 if ((0 == data->mclk_dpm_key_disabled) &&
4377 !data->mclk_ignore_signal &&
4378 (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK0x00000002)) {
4379
4380 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze MCLK DPM when DPM is disabled"
); ; } } while (0)
4381 "Trying to Unfreeze MCLK DPM when DPM is disabled",do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze MCLK DPM when DPM is disabled"
); ; } } while (0)
4382 )do { if (!(1 == smum_is_dpm_running(hwmgr))) { printk("\0014"
"amdgpu: " "%s\n", "Trying to Unfreeze MCLK DPM when DPM is disabled"
); ; } } while (0)
;
4383 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18C
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4384 PPSMC_MSG_MCLKDPM_UnfreezeLevel,do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18C
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4385 NULL),do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18C
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4386 "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18C
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
4387 return -EINVAL)do { if (!(0 == smum_send_msg_to_smc(hwmgr, ((uint16_t) 0x18C
), ((void *)0)))) { printk("\0014" "amdgpu: " "%s\n", "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!"
); return -22; } } while (0)
;
4388 }
4389
4390 data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC0x00000010;
4391
4392 return 0;
4393}
4394
4395static int smu7_notify_link_speed_change_after_state_change(
4396 struct pp_hwmgr *hwmgr, const void *input)
4397{
4398 const struct phm_set_power_state_input *states =
4399 (const struct phm_set_power_state_input *)input;
4400 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4401 const struct smu7_power_state *smu7_ps =
4402 cast_const_phw_smu7_power_state(states->pnew_state);
4403 uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps);
4404 uint8_t request;
4405
4406 if (data->pspp_notify_required) {
4407 if (target_link_speed == PP_PCIEGen3)
4408 request = PCIE_PERF_REQ_GEN34;
4409 else if (target_link_speed == PP_PCIEGen2)
4410 request = PCIE_PERF_REQ_GEN23;
4411 else
4412 request = PCIE_PERF_REQ_GEN12;
4413
4414 if (request == PCIE_PERF_REQ_GEN12 &&
4415 smu7_get_current_pcie_speed(hwmgr) > 0)
4416 return 0;
4417
4418#ifdef CONFIG_ACPI1
4419 if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false0)) {
4420 if (PP_PCIEGen2 == target_link_speed)
4421 pr_info("PSPP request to switch to Gen2 from Gen3 Failed!")do { } while(0);
4422 else
4423 pr_info("PSPP request to switch to Gen1 from Gen2 Failed!")do { } while(0);
4424 }
4425#endif
4426 }
4427
4428 return 0;
4429}
4430
4431static int smu7_notify_no_display(struct pp_hwmgr *hwmgr)
4432{
4433 return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay((uint16_t)0x5D), NULL((void *)0)) == 0) ? 0 : -EINVAL22;
4434}
4435
4436static int smu7_notify_has_display(struct pp_hwmgr *hwmgr)
4437{
4438 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4439
4440 if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) {
4441 if (hwmgr->chip_id == CHIP_VEGAM)
4442 smum_send_msg_to_smc_with_parameter(hwmgr,
4443 (PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM((uint16_t) 0x310), data->frame_time_x2,
4444 NULL((void *)0));
4445 else
4446 smum_send_msg_to_smc_with_parameter(hwmgr,
4447 (PPSMC_Msg)PPSMC_MSG_SetVBITimeout((uint16_t) 0x306), data->frame_time_x2,
4448 NULL((void *)0));
4449 data->last_sent_vbi_timeout = data->frame_time_x2;
4450 }
4451
4452 return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay((uint16_t)0x5E), NULL((void *)0)) == 0) ? 0 : -EINVAL22;
4453}
4454
4455static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
4456{
4457 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4458 int result = 0;
4459
4460 if (data->mclk_ignore_signal)
4461 result = smu7_notify_no_display(hwmgr);
4462 else
4463 result = smu7_notify_has_display(hwmgr);
4464
4465 return result;
4466}
4467
4468static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
4469{
4470 int tmp_result, result = 0;
4471 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4472
4473 tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
4474 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to find DPM states clocks in DPM table!"); result =
tmp_result; } } while (0)
4475 "Failed to find DPM states clocks in DPM table!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to find DPM states clocks in DPM table!"); result =
tmp_result; } } while (0)
4476 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to find DPM states clocks in DPM table!"); result =
tmp_result; } } while (0)
;
4477
4478 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4479 PHM_PlatformCaps_PCIEPerformanceRequest)) {
4480 tmp_result =
4481 smu7_request_link_speed_change_before_state_change(hwmgr, input);
4482 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to request link speed change before state change!")
; result = tmp_result; } } while (0)
4483 "Failed to request link speed change before state change!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to request link speed change before state change!")
; result = tmp_result; } } while (0)
4484 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to request link speed change before state change!")
; result = tmp_result; } } while (0)
;
4485 }
4486
4487 tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr);
4488 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to freeze SCLK MCLK DPM!"); result = tmp_result; } }
while (0)
4489 "Failed to freeze SCLK MCLK DPM!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to freeze SCLK MCLK DPM!"); result = tmp_result; } }
while (0)
;
4490
4491 tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
4492 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate and upload SCLK MCLK DPM levels!"); result
= tmp_result; } } while (0)
4493 "Failed to populate and upload SCLK MCLK DPM levels!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate and upload SCLK MCLK DPM levels!"); result
= tmp_result; } } while (0)
4494 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to populate and upload SCLK MCLK DPM levels!"); result
= tmp_result; } } while (0)
;
4495
4496 /*
4497 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
4498 * That effectively disables AVFS feature.
4499 */
4500 if (hwmgr->hardcode_pp_table != NULL((void *)0))
4501 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC0x00000010;
4502
4503 tmp_result = smu7_update_avfs(hwmgr);
4504 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update avfs voltages!"); result = tmp_result; } }
while (0)
4505 "Failed to update avfs voltages!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update avfs voltages!"); result = tmp_result; } }
while (0)
4506 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update avfs voltages!"); result = tmp_result; } }
while (0)
;
4507
4508 tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input);
4509 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to generate DPM level enabled mask!"); result = tmp_result
; } } while (0)
4510 "Failed to generate DPM level enabled mask!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to generate DPM level enabled mask!"); result = tmp_result
; } } while (0)
4511 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to generate DPM level enabled mask!"); result = tmp_result
; } } while (0)
;
4512
4513 tmp_result = smum_update_sclk_threshold(hwmgr);
4514 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update SCLK threshold!"); result = tmp_result; }
} while (0)
4515 "Failed to update SCLK threshold!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update SCLK threshold!"); result = tmp_result; }
} while (0)
4516 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to update SCLK threshold!"); result = tmp_result; }
} while (0)
;
4517
4518 tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr);
4519 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to unfreeze SCLK MCLK DPM!"); result = tmp_result; }
} while (0)
4520 "Failed to unfreeze SCLK MCLK DPM!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to unfreeze SCLK MCLK DPM!"); result = tmp_result; }
} while (0)
4521 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to unfreeze SCLK MCLK DPM!"); result = tmp_result; }
} while (0)
;
4522
4523 tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr);
4524 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to upload DPM level enabled mask!"); result = tmp_result
; } } while (0)
4525 "Failed to upload DPM level enabled mask!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to upload DPM level enabled mask!"); result = tmp_result
; } } while (0)
4526 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to upload DPM level enabled mask!"); result = tmp_result
; } } while (0)
;
4527
4528 tmp_result = smu7_notify_smc_display(hwmgr);
4529 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify smc display settings!"); result = tmp_result
; } } while (0)
4530 "Failed to notify smc display settings!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify smc display settings!"); result = tmp_result
; } } while (0)
4531 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify smc display settings!"); result = tmp_result
; } } while (0)
;
4532
4533 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4534 PHM_PlatformCaps_PCIEPerformanceRequest)) {
4535 tmp_result =
4536 smu7_notify_link_speed_change_after_state_change(hwmgr, input);
4537 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify link speed change after state change!"); result
= tmp_result; } } while (0)
4538 "Failed to notify link speed change after state change!",do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify link speed change after state change!"); result
= tmp_result; } } while (0)
4539 result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to notify link speed change after state change!"); result
= tmp_result; } } while (0)
;
4540 }
4541 data->apply_optimized_settings = false0;
4542 return result;
4543}
4544
4545static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
4546{
4547 hwmgr->thermal_controller.
4548 advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
4549
4550 return smum_send_msg_to_smc_with_parameter(hwmgr,
4551 PPSMC_MSG_SetFanPwmMax((uint16_t) 0x19A), us_max_fan_pwm,
4552 NULL((void *)0));
4553}
4554
4555static int
4556smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
4557{
4558 return 0;
4559}
4560
4561/**
4562 * smu7_program_display_gap - Programs the display gap
4563 *
4564 * @hwmgr: the address of the powerplay hardware manager.
4565 * Return: always OK
4566 */
4567static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
4568{
4569 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4570 uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060))
;
4571 uint32_t display_gap2;
4572 uint32_t pre_vbi_time_in_us;
4573 uint32_t frame_time_in_us;
4574 uint32_t ref_clock, refresh_rate;
4575
4576 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE)(((display_gap) & ~0x3) | (0x3 & (((hwmgr->display_config
->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE
) << 0x0)))
;
4577 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200060,display_gap))
;
4578
4579 ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev)((struct amdgpu_device *)hwmgr->adev)->asic_funcs->get_xclk
(((struct amdgpu_device *)hwmgr->adev))
;
4580 refresh_rate = hwmgr->display_config->vrefresh;
4581
4582 if (0 == refresh_rate)
4583 refresh_rate = 60;
4584
4585 frame_time_in_us = 1000000 / refresh_rate;
4586
4587 pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time;
4588
4589 data->frame_time_x2 = frame_time_in_us * 2 / 100;
4590
4591 if (data->frame_time_x2 < 280) {
4592 pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2)do { } while(0);
4593 data->frame_time_x2 = 280;
4594 }
4595
4596 display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
4597
4598 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200230,display_gap2))
;
4599
4600 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, PreVBlankGap),0x64
))
4601 data->soft_regs_start + smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, PreVBlankGap),0x64
))
4602 SMU_SoftRegisters,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, PreVBlankGap),0x64
))
4603 PreVBlankGap), 0x64)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, PreVBlankGap),0x64
))
;
4604
4605 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout),(
frame_time_in_us - pre_vbi_time_in_us)))
4606 data->soft_regs_start + smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout),(
frame_time_in_us - pre_vbi_time_in_us)))
4607 SMU_SoftRegisters,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout),(
frame_time_in_us - pre_vbi_time_in_us)))
4608 VBlankTimeout),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout),(
frame_time_in_us - pre_vbi_time_in_us)))
4609 (frame_time_in_us - pre_vbi_time_in_us))(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout),(
frame_time_in_us - pre_vbi_time_in_us)))
;
4610
4611 return 0;
4612}
4613
4614static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4615{
4616 return smu7_program_display_gap(hwmgr);
4617}
4618
4619/**
4620 * smu7_set_max_fan_rpm_output - Set maximum target operating fan output RPM
4621 *
4622 * @hwmgr: the address of the powerplay hardware manager.
4623 * @us_max_fan_rpm: max operating fan RPM value.
4624 * Return: The response that came from the SMC.
4625 */
4626static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm)
4627{
4628 hwmgr->thermal_controller.
4629 advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm;
4630
4631 return smum_send_msg_to_smc_with_parameter(hwmgr,
4632 PPSMC_MSG_SetFanRpmMax((uint16_t) 0x205), us_max_fan_rpm,
4633 NULL((void *)0));
4634}
4635
4636static const struct amdgpu_irq_src_funcs smu7_irq_funcs = {
4637 .process = phm_irq_process,
4638};
4639
4640static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr)
4641{
4642 struct amdgpu_irq_src *source =
4643 kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL(0x0001 | 0x0004));
4644
4645 if (!source)
4646 return -ENOMEM12;
4647
4648 source->funcs = &smu7_irq_funcs;
4649
4650 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4651 AMDGPU_IRQ_CLIENTID_LEGACY0,
4652 VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH0x000000e6,
4653 source);
4654 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4655 AMDGPU_IRQ_CLIENTID_LEGACY0,
4656 VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW0x000000e7,
4657 source);
4658
4659 /* Register CTF(GPIO_19) interrupt */
4660 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4661 AMDGPU_IRQ_CLIENTID_LEGACY0,
4662 VISLANDS30_IV_SRCID_GPIO_190x00000053,
4663 source);
4664
4665 return 0;
4666}
4667
4668static bool_Bool
4669smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4670{
4671 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4672 bool_Bool is_update_required = false0;
4673
4674 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4675 is_update_required = true1;
4676
4677 if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh)
4678 is_update_required = true1;
4679
4680 if (hwmgr->chip_id >= CHIP_POLARIS10 &&
4681 hwmgr->chip_id <= CHIP_VEGAM &&
4682 data->last_sent_vbi_timeout != data->frame_time_x2)
4683 is_update_required = true1;
4684
4685 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
4686 if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr &&
4687 (data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK2500 ||
4688 hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK2500))
4689 is_update_required = true1;
4690 }
4691 return is_update_required;
4692}
4693
4694static inline bool_Bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1,
4695 const struct smu7_performance_level *pl2)
4696{
4697 return ((pl1->memory_clock == pl2->memory_clock) &&
4698 (pl1->engine_clock == pl2->engine_clock) &&
4699 (pl1->pcie_gen == pl2->pcie_gen) &&
4700 (pl1->pcie_lane == pl2->pcie_lane));
4701}
4702
4703static int smu7_check_states_equal(struct pp_hwmgr *hwmgr,
4704 const struct pp_hw_power_state *pstate1,
4705 const struct pp_hw_power_state *pstate2, bool_Bool *equal)
4706{
4707 const struct smu7_power_state *psa;
4708 const struct smu7_power_state *psb;
4709 int i;
4710 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4711
4712 if (pstate1 == NULL((void *)0) || pstate2 == NULL((void *)0) || equal == NULL((void *)0))
4713 return -EINVAL22;
4714
4715 psa = cast_const_phw_smu7_power_state(pstate1);
4716 psb = cast_const_phw_smu7_power_state(pstate2);
4717 /* If the two states don't even have the same number of performance levels they cannot be the same state. */
4718 if (psa->performance_level_count != psb->performance_level_count) {
4719 *equal = false0;
4720 return 0;
4721 }
4722
4723 for (i = 0; i < psa->performance_level_count; i++) {
4724 if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4725 /* If we have found even one performance level pair that is different the states are different. */
4726 *equal = false0;
4727 return 0;
4728 }
4729 }
4730
4731 /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4732 *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4733 *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4734 *equal &= (psa->sclk_threshold == psb->sclk_threshold);
4735 /* For OD call, set value based on flag */
4736 *equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK0x00000001 |
4737 DPMTABLE_OD_UPDATE_MCLK0x00000002 |
4738 DPMTABLE_OD_UPDATE_VDDC0x00000010));
4739
4740 return 0;
4741}
4742
4743static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr)
4744{
4745 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4746
4747 uint32_t tmp;
4748
4749 /* Read MC indirect register offset 0x9F bits [3:0] to see
4750 * if VBIOS has already loaded a full version of MC ucode
4751 * or not.
4752 */
4753
4754 smu7_get_mc_microcode_version(hwmgr);
4755
4756 data->need_long_memory_training = false0;
4757
4758 cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX,(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xa91,0xd))
4759 ixMC_IO_DEBUG_UP_13)(((struct cgs_device *)hwmgr->device)->ops->write_register
(hwmgr->device,0xa91,0xd))
;
4760 tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xa92))
;
4761
4762 if (tmp & (1 << 23)) {
4763 data->mem_latency_high = MEM_LATENCY_HIGH45;
4764 data->mem_latency_low = MEM_LATENCY_LOW35;
4765 if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4766 (hwmgr->chip_id == CHIP_POLARIS11) ||
4767 (hwmgr->chip_id == CHIP_POLARIS12))
4768 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC((uint16_t) 0x307), NULL((void *)0));
4769 } else {
4770 data->mem_latency_high = 330;
4771 data->mem_latency_low = 330;
4772 if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4773 (hwmgr->chip_id == CHIP_POLARIS11) ||
4774 (hwmgr->chip_id == CHIP_POLARIS12))
4775 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC((uint16_t) 0x308), NULL((void *)0));
4776 }
4777
4778 return 0;
4779}
4780
4781static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr)
4782{
4783 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4784
4785 data->clock_registers.vCG_SPLL_FUNC_CNTL =
4786 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500140))
;
4787 data->clock_registers.vCG_SPLL_FUNC_CNTL_2 =
4788 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500144))
;
4789 data->clock_registers.vCG_SPLL_FUNC_CNTL_3 =
4790 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500148))
;
4791 data->clock_registers.vCG_SPLL_FUNC_CNTL_4 =
4792 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc050014c))
;
4793 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM =
4794 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500164))
;
4795 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
4796 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2)(((struct cgs_device *)hwmgr->device)->ops->read_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0500168))
;
4797 data->clock_registers.vDLL_CNTL =
4798 cgs_read_register(hwmgr->device, mmDLL_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xae9))
;
4799 data->clock_registers.vMCLK_PWRMGT_CNTL =
4800 cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xae8))
;
4801 data->clock_registers.vMPLL_AD_FUNC_CNTL =
4802 cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaf0))
;
4803 data->clock_registers.vMPLL_DQ_FUNC_CNTL =
4804 cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaf1))
;
4805 data->clock_registers.vMPLL_FUNC_CNTL =
4806 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaed))
;
4807 data->clock_registers.vMPLL_FUNC_CNTL_1 =
4808 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaee))
;
4809 data->clock_registers.vMPLL_FUNC_CNTL_2 =
4810 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaef))
;
4811 data->clock_registers.vMPLL_SS1 =
4812 cgs_read_register(hwmgr->device, mmMPLL_SS1)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaf3))
;
4813 data->clock_registers.vMPLL_SS2 =
4814 cgs_read_register(hwmgr->device, mmMPLL_SS2)(((struct cgs_device *)hwmgr->device)->ops->read_register
(hwmgr->device,0xaf4))
;
4815 return 0;
4816
4817}
4818
4819/**
4820 * smu7_get_memory_type - Find out if memory is GDDR5.
4821 *
4822 * @hwmgr: the address of the powerplay hardware manager.
4823 * Return: always 0
4824 */
4825static int smu7_get_memory_type(struct pp_hwmgr *hwmgr)
4826{
4827 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4828 struct amdgpu_device *adev = hwmgr->adev;
4829
4830 data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR55);
4831
4832 return 0;
4833}
4834
4835/**
4836 * smu7_enable_acpi_power_management - Enables Dynamic Power Management by SMC
4837 *
4838 * @hwmgr: the address of the powerplay hardware manager.
4839 * Return: always 0
4840 */
4841static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
4842{
4843 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x2) | (0x2 &
((1) << 0x1)))))
4844 GENERAL_PWRMGT, STATIC_PM_EN, 1)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,0xc0200000,((((((struct cgs_device
*)hwmgr->device)->ops->read_ind_register(hwmgr->
device,CGS_IND_REG__SMC,0xc0200000))) & ~0x2) | (0x2 &
((1) << 0x1)))))
;
4845
4846 return 0;
4847}
4848
4849/**
4850 * smu7_init_power_gate_state - Initialize PowerGating States for different engines
4851 *
4852 * @hwmgr: the address of the powerplay hardware manager.
4853 * Return: always 0
4854 */
4855static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr)
4856{
4857 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4858
4859 data->uvd_power_gated = false0;
4860 data->vce_power_gated = false0;
4861
4862 return 0;
4863}
4864
4865static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr)
4866{
4867 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4868
4869 data->low_sclk_interrupt_threshold = 0;
4870 return 0;
4871}
4872
4873static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
4874{
4875 int tmp_result, result = 0;
4876
4877 smu7_check_mc_firmware(hwmgr);
4878
4879 tmp_result = smu7_read_clock_registers(hwmgr);
4880 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to read clock registers!"); result = tmp_result; } }
while (0)
4881 "Failed to read clock registers!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to read clock registers!"); result = tmp_result; } }
while (0)
;
4882
4883 tmp_result = smu7_get_memory_type(hwmgr);
4884 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to get memory type!"); result = tmp_result; } } while
(0)
4885 "Failed to get memory type!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to get memory type!"); result = tmp_result; } } while
(0)
;
4886
4887 tmp_result = smu7_enable_acpi_power_management(hwmgr);
4888 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable ACPI power management!"); result = tmp_result
; } } while (0)
4889 "Failed to enable ACPI power management!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to enable ACPI power management!"); result = tmp_result
; } } while (0)
;
4890
4891 tmp_result = smu7_init_power_gate_state(hwmgr);
4892 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to init power gate state!"); result = tmp_result; }
} while (0)
4893 "Failed to init power gate state!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to init power gate state!"); result = tmp_result; }
} while (0)
;
4894
4895 tmp_result = smu7_get_mc_microcode_version(hwmgr);
4896 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to get MC microcode version!"); result = tmp_result
; } } while (0)
4897 "Failed to get MC microcode version!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to get MC microcode version!"); result = tmp_result
; } } while (0)
;
4898
4899 tmp_result = smu7_init_sclk_threshold(hwmgr);
4900 PP_ASSERT_WITH_CODE((0 == tmp_result),do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to init sclk threshold!"); result = tmp_result; } }
while (0)
4901 "Failed to init sclk threshold!", result = tmp_result)do { if (!((0 == tmp_result))) { printk("\0014" "amdgpu: " "%s\n"
, "Failed to init sclk threshold!"); result = tmp_result; } }
while (0)
;
4902
4903 return result;
4904}
4905
4906static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
4907 enum pp_clock_type type, uint32_t mask)
4908{
4909 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4910
4911 if (mask == 0)
4912 return -EINVAL22;
4913
4914 switch (type) {
4915 case PP_SCLK:
4916 if (!data->sclk_dpm_key_disabled)
4917 smum_send_msg_to_smc_with_parameter(hwmgr,
4918 PPSMC_MSG_SCLKDPM_SetEnabledMask((uint16_t) 0x145),
4919 data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask,
4920 NULL((void *)0));
4921 break;
4922 case PP_MCLK:
4923 if (!data->mclk_dpm_key_disabled)
4924 smum_send_msg_to_smc_with_parameter(hwmgr,
4925 PPSMC_MSG_MCLKDPM_SetEnabledMask((uint16_t) 0x146),
4926 data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask,
4927 NULL((void *)0));
4928 break;
4929 case PP_PCIE:
4930 {
4931 uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
4932
4933 if (!data->pcie_dpm_key_disabled) {
4934 if (fls(tmp) != ffs(tmp))
4935 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel((uint16_t) 0x148),
4936 NULL((void *)0));
4937 else
4938 smum_send_msg_to_smc_with_parameter(hwmgr,
4939 PPSMC_MSG_PCIeDPM_ForceLevel((uint16_t) 0x147),
4940 fls(tmp) - 1,
4941 NULL((void *)0));
4942 }
4943 break;
4944 }
4945 default:
4946 break;
4947 }
4948
4949 return 0;
4950}
4951
4952static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
4953 enum pp_clock_type type, char *buf)
4954{
4955 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4956 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4957 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
4958 struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table);
4959 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4960 struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4961 struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4962 int size = 0;
4963 uint32_t i, now, clock, pcie_speed;
4964
4965 switch (type) {
4966 case PP_SCLK:
4967 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency((uint16_t) 0x200), &clock);
4968
4969 for (i = 0; i < sclk_table->count; i++) {
4970 if (clock > sclk_table->dpm_levels[i].value)
4971 continue;
4972 break;
4973 }
4974 now = i;
4975
4976 for (i = 0; i < sclk_table->count; i++)
4977 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%d: %uMhz %s\n",
4978 i, sclk_table->dpm_levels[i].value / 100,
4979 (i == now) ? "*" : "");
4980 break;
4981 case PP_MCLK:
4982 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency((uint16_t) 0x201), &clock);
4983
4984 for (i = 0; i < mclk_table->count; i++) {
4985 if (clock > mclk_table->dpm_levels[i].value)
4986 continue;
4987 break;
4988 }
4989 now = i;
4990
4991 for (i = 0; i < mclk_table->count; i++)
4992 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%d: %uMhz %s\n",
4993 i, mclk_table->dpm_levels[i].value / 100,
4994 (i == now) ? "*" : "");
4995 break;
4996 case PP_PCIE:
4997 pcie_speed = smu7_get_current_pcie_speed(hwmgr);
4998 for (i = 0; i < pcie_table->count; i++) {
4999 if (pcie_speed != pcie_table->dpm_levels[i].value)
5000 continue;
5001 break;
5002 }
5003 now = i;
5004
5005 for (i = 0; i < pcie_table->count; i++)
5006 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%d: %s %s\n", i,
5007 (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" :
5008 (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" :
5009 (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "",
5010 (i == now) ? "*" : "");
5011 break;
5012 case OD_SCLK:
5013 if (hwmgr->od_enabled) {
5014 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%s:\n", "OD_SCLK");
5015 for (i = 0; i < odn_sclk_table->num_of_pl; i++)
5016 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%d: %10uMHz %10umV\n",
5017 i, odn_sclk_table->entries[i].clock/100,
5018 odn_sclk_table->entries[i].vddc);
5019 }
5020 break;
5021 case OD_MCLK:
5022 if (hwmgr->od_enabled) {
5023 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%s:\n", "OD_MCLK");
5024 for (i = 0; i < odn_mclk_table->num_of_pl; i++)
5025 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%d: %10uMHz %10umV\n",
5026 i, odn_mclk_table->entries[i].clock/100,
5027 odn_mclk_table->entries[i].vddc);
5028 }
5029 break;
5030 case OD_RANGE:
5031 if (hwmgr->od_enabled) {
5032 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "%s:\n", "OD_RANGE");
5033 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "SCLK: %7uMHz %10uMHz\n",
5034 data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
5035 hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
5036 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "MCLK: %7uMHz %10uMHz\n",
5037 data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
5038 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
5039 size += snprintf(buf + size, PAGE_SIZE(1 << 12) - size, "VDDC: %7umV %11umV\n",
5040 data->odn_dpm_table.min_vddc,
5041 data->odn_dpm_table.max_vddc);
5042 }
5043 break;
5044 default:
5045 break;
5046 }
5047 return size;
5048}
5049
5050static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
5051{
5052 switch (mode) {
5053 case AMD_FAN_CTRL_NONE:
5054 smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
5055 break;
5056 case AMD_FAN_CTRL_MANUAL:
5057 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
5058 PHM_PlatformCaps_MicrocodeFanControl))
5059 smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
5060 break;
5061 case AMD_FAN_CTRL_AUTO:
5062 if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode))
5063 smu7_fan_ctrl_start_smc_fan_control(hwmgr);
5064 break;
5065 default:
5066 break;
5067 }
5068}
5069
5070static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr)
5071{
5072 return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL;
5073}
5074
5075static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
5076{
5077 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5078 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
5079 struct smu7_single_dpm_table *golden_sclk_table =
5080 &(data->golden_dpm_table.sclk_table);
5081 int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
5082 int golden_value = golden_sclk_table->dpm_levels
5083 [golden_sclk_table->count - 1].value;
5084
5085 value -= golden_value;
5086 value = DIV_ROUND_UP(value * 100, golden_value)(((value * 100) + ((golden_value) - 1)) / (golden_value));
5087
5088 return value;
5089}
5090
5091static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
5092{
5093 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5094 struct smu7_single_dpm_table *golden_sclk_table =
5095 &(data->golden_dpm_table.sclk_table);
5096 struct pp_power_state *ps;
5097 struct smu7_power_state *smu7_ps;
5098
5099 if (value > 20)
5100 value = 20;
5101
5102 ps = hwmgr->request_ps;
5103
5104 if (ps == NULL((void *)0))
5105 return -EINVAL22;
5106
5107 smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
5108
5109 smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock =
5110 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value *
5111 value / 100 +
5112 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
5113
5114 return 0;
5115}
5116
5117static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
5118{
5119 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5120 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5121 struct smu7_single_dpm_table *golden_mclk_table =
5122 &(data->golden_dpm_table.mclk_table);
5123 int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
5124 int golden_value = golden_mclk_table->dpm_levels
5125 [golden_mclk_table->count - 1].value;
5126
5127 value -= golden_value;
5128 value = DIV_ROUND_UP(value * 100, golden_value)(((value * 100) + ((golden_value) - 1)) / (golden_value));
5129
5130 return value;
5131}
5132
5133static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
5134{
5135 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5136 struct smu7_single_dpm_table *golden_mclk_table =
5137 &(data->golden_dpm_table.mclk_table);
5138 struct pp_power_state *ps;
5139 struct smu7_power_state *smu7_ps;
5140
5141 if (value > 20)
5142 value = 20;
5143
5144 ps = hwmgr->request_ps;
5145
5146 if (ps == NULL((void *)0))
5147 return -EINVAL22;
5148
5149 smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
5150
5151 smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock =
5152 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value *
5153 value / 100 +
5154 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
5155
5156 return 0;
5157}
5158
5159
5160static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5161{
5162 struct phm_ppt_v1_information *table_info =
5163 (struct phm_ppt_v1_information *)hwmgr->pptable;
5164 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL((void *)0);
5165 struct phm_clock_voltage_dependency_table *sclk_table;
5166 int i;
5167
5168 if (hwmgr->pp_table_version == PP_TABLE_V1) {
5169 if (table_info == NULL((void *)0) || table_info->vdd_dep_on_sclk == NULL((void *)0))
5170 return -EINVAL22;
5171 dep_sclk_table = table_info->vdd_dep_on_sclk;
5172 for (i = 0; i < dep_sclk_table->count; i++)
5173 clocks->clock[i] = dep_sclk_table->entries[i].clk * 10;
5174 clocks->count = dep_sclk_table->count;
5175 } else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5176 sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
5177 for (i = 0; i < sclk_table->count; i++)
5178 clocks->clock[i] = sclk_table->entries[i].clk * 10;
5179 clocks->count = sclk_table->count;
5180 }
5181
5182 return 0;
5183}
5184
5185static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk)
5186{
5187 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5188
5189 if (clk >= MEM_FREQ_LOW_LATENCY25000 && clk < MEM_FREQ_HIGH_LATENCY80000)
5190 return data->mem_latency_high;
5191 else if (clk >= MEM_FREQ_HIGH_LATENCY80000)
5192 return data->mem_latency_low;
5193 else
5194 return MEM_LATENCY_ERR0xFFFF;
5195}
5196
5197static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5198{
5199 struct phm_ppt_v1_information *table_info =
5200 (struct phm_ppt_v1_information *)hwmgr->pptable;
5201 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
5202 int i;
5203 struct phm_clock_voltage_dependency_table *mclk_table;
5204
5205 if (hwmgr->pp_table_version == PP_TABLE_V1) {
5206 if (table_info == NULL((void *)0))
5207 return -EINVAL22;
5208 dep_mclk_table = table_info->vdd_dep_on_mclk;
5209 for (i = 0; i < dep_mclk_table->count; i++) {
5210 clocks->clock[i] = dep_mclk_table->entries[i].clk * 10;
5211 clocks->latency[i] = smu7_get_mem_latency(hwmgr,
5212 dep_mclk_table->entries[i].clk);
5213 }
5214 clocks->count = dep_mclk_table->count;
5215 } else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5216 mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
5217 for (i = 0; i < mclk_table->count; i++)
5218 clocks->clock[i] = mclk_table->entries[i].clk * 10;
5219 clocks->count = mclk_table->count;
5220 }
5221 return 0;
5222}
5223
5224static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type,
5225 struct amd_pp_clocks *clocks)
5226{
5227 switch (type) {
5228 case amd_pp_sys_clock:
5229 smu7_get_sclks(hwmgr, clocks);
5230 break;
5231 case amd_pp_mem_clock:
5232 smu7_get_mclks(hwmgr, clocks);
5233 break;
5234 default:
5235 return -EINVAL22;
5236 }
5237
5238 return 0;
5239}
5240
5241static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr,
5242 struct pp_clock_levels_with_latency *clocks)
5243{
5244 struct phm_ppt_v1_information *table_info =
5245 (struct phm_ppt_v1_information *)hwmgr->pptable;
5246 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5247 table_info->vdd_dep_on_sclk;
5248 int i;
5249
5250 clocks->num_levels = 0;
5251 for (i = 0; i < dep_sclk_table->count; i++) {
5252 if (dep_sclk_table->entries[i].clk) {
5253 clocks->data[clocks->num_levels].clocks_in_khz =
5254 dep_sclk_table->entries[i].clk * 10;
5255 clocks->num_levels++;
5256 }
5257 }
5258
5259 return 0;
5260}
5261
5262static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr,
5263 struct pp_clock_levels_with_latency *clocks)
5264{
5265 struct phm_ppt_v1_information *table_info =
5266 (struct phm_ppt_v1_information *)hwmgr->pptable;
5267 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5268 table_info->vdd_dep_on_mclk;
5269 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5270 int i;
5271
5272 clocks->num_levels = 0;
5273 data->mclk_latency_table.count = 0;
5274 for (i = 0; i < dep_mclk_table->count; i++) {
5275 if (dep_mclk_table->entries[i].clk) {
5276 clocks->data[clocks->num_levels].clocks_in_khz =
5277 dep_mclk_table->entries[i].clk * 10;
5278 data->mclk_latency_table.entries[data->mclk_latency_table.count].frequency =
5279 dep_mclk_table->entries[i].clk;
5280 clocks->data[clocks->num_levels].latency_in_us =
5281 data->mclk_latency_table.entries[data->mclk_latency_table.count].latency =
5282 smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk);
5283 clocks->num_levels++;
5284 data->mclk_latency_table.count++;
5285 }
5286 }
5287
5288 return 0;
5289}
5290
5291static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
5292 enum amd_pp_clock_type type,
5293 struct pp_clock_levels_with_latency *clocks)
5294{
5295 if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5296 hwmgr->chip_id <= CHIP_VEGAM))
5297 return -EINVAL22;
5298
5299 switch (type) {
5300 case amd_pp_sys_clock:
5301 smu7_get_sclks_with_latency(hwmgr, clocks);
5302 break;
5303 case amd_pp_mem_clock:
5304 smu7_get_mclks_with_latency(hwmgr, clocks);
5305 break;
5306 default:
5307 return -EINVAL22;
5308 }
5309
5310 return 0;
5311}
5312
5313static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
5314 void *clock_range)
5315{
5316 struct phm_ppt_v1_information *table_info =
5317 (struct phm_ppt_v1_information *)hwmgr->pptable;
5318 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5319 table_info->vdd_dep_on_mclk;
5320 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5321 table_info->vdd_dep_on_sclk;
5322 struct polaris10_smumgr *smu_data =
5323 (struct polaris10_smumgr *)(hwmgr->smu_backend);
5324 SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
5325 struct dm_pp_wm_sets_with_clock_ranges *watermarks =
5326 (struct dm_pp_wm_sets_with_clock_ranges *)clock_range;
5327 uint32_t i, j, k;
5328 bool_Bool valid_entry;
5329
5330 if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5331 hwmgr->chip_id <= CHIP_VEGAM))
5332 return -EINVAL22;
5333
5334 for (i = 0; i < dep_mclk_table->count; i++) {
5335 for (j = 0; j < dep_sclk_table->count; j++) {
5336 valid_entry = false0;
5337 for (k = 0; k < watermarks->num_wm_sets; k++) {
5338 if (dep_sclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz / 10 &&
5339 dep_sclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz / 10 &&
5340 dep_mclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz / 10 &&
5341 dep_mclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz / 10) {
5342 valid_entry = true1;
5343 table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
5344 break;
5345 }
5346 }
5347 PP_ASSERT_WITH_CODE(valid_entry,do { if (!(valid_entry)) { printk("\0014" "amdgpu: " "%s\n", "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set."
); table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges
[k - 1].wm_set_id; } } while (0)
5348 "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set.",do { if (!(valid_entry)) { printk("\0014" "amdgpu: " "%s\n", "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set."
); table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges
[k - 1].wm_set_id; } } while (0)
5349 table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k - 1].wm_set_id)do { if (!(valid_entry)) { printk("\0014" "amdgpu: " "%s\n", "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set."
); table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges
[k - 1].wm_set_id; } } while (0)
;
5350 }
5351 }
5352
5353 return smu7_copy_bytes_to_smc(hwmgr,
5354 smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, DisplayWatermark)__builtin_offsetof(SMU74_Discrete_DpmTable, DisplayWatermark),
5355 (uint8_t *)table->DisplayWatermark,
5356 sizeof(uint8_t) * SMU74_MAX_LEVELS_MEMORY4 * SMU74_MAX_LEVELS_GRAPHICS8,
5357 SMC_RAM_END0x40000);
5358}
5359
5360static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
5361 uint32_t virtual_addr_low,
5362 uint32_t virtual_addr_hi,
5363 uint32_t mc_addr_low,
5364 uint32_t mc_addr_hi,
5365 uint32_t size)
5366{
5367 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5368
5369 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_H)
,mc_addr_hi))
5370 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_H)
,mc_addr_hi))
5371 smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_H)
,mc_addr_hi))
5372 SMU_SoftRegisters, DRAM_LOG_ADDR_H),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_H)
,mc_addr_hi))
5373 mc_addr_hi)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_H)
,mc_addr_hi))
;
5374
5375 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_L)
,mc_addr_low))
5376 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_L)
,mc_addr_low))
5377 smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_L)
,mc_addr_low))
5378 SMU_SoftRegisters, DRAM_LOG_ADDR_L),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_L)
,mc_addr_low))
5379 mc_addr_low)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_ADDR_L)
,mc_addr_low))
;
5380
5381 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H
),virtual_addr_hi))
5382 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H
),virtual_addr_hi))
5383 smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H
),virtual_addr_hi))
5384 SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H
),virtual_addr_hi))
5385 virtual_addr_hi)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H
),virtual_addr_hi))
;
5386
5387 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L
),virtual_addr_low))
5388 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L
),virtual_addr_low))
5389 smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L
),virtual_addr_low))
5390 SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L
),virtual_addr_low))
5391 virtual_addr_low)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L
),virtual_addr_low))
;
5392
5393 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE
),size))
5394 data->soft_regs_start +(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE
),size))
5395 smum_get_offsetof(hwmgr,(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE
),size))
5396 SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE),(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE
),size))
5397 size)(((struct cgs_device *)hwmgr->device)->ops->write_ind_register
(hwmgr->device,CGS_IND_REG__SMC,data->soft_regs_start +
smum_get_offsetof(hwmgr, SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE
),size))
;
5398 return 0;
5399}
5400
5401static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr,
5402 struct amd_pp_simple_clock_info *clocks)
5403{
5404 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5405 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
5406 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5407
5408 if (clocks == NULL((void *)0))
5409 return -EINVAL22;
5410
5411 clocks->memory_max_clock = mclk_table->count > 1 ?
5412 mclk_table->dpm_levels[mclk_table->count-1].value :
5413 mclk_table->dpm_levels[0].value;
5414 clocks->engine_max_clock = sclk_table->count > 1 ?
5415 sclk_table->dpm_levels[sclk_table->count-1].value :
5416 sclk_table->dpm_levels[0].value;
5417 return 0;
5418}
5419
5420static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
5421 struct PP_TemperatureRange *thermal_data)
5422{
5423 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5424 struct phm_ppt_v1_information *table_info =
5425 (struct phm_ppt_v1_information *)hwmgr->pptable;
5426
5427 memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange))__builtin_memcpy((thermal_data), (&SMU7ThermalPolicy[0]),
(sizeof(struct PP_TemperatureRange)))
;
5428
5429 if (hwmgr->pp_table_version == PP_TABLE_V1)
5430 thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp *
5431 PP_TEMPERATURE_UNITS_PER_CENTIGRADES1000;
5432 else if (hwmgr->pp_table_version == PP_TABLE_V0)
5433 thermal_data->max = data->thermal_temp_setting.temperature_shutdown *
5434 PP_TEMPERATURE_UNITS_PER_CENTIGRADES1000;
5435
5436 thermal_data->sw_ctf_threshold = thermal_data->max;
5437
5438 return 0;
5439}
5440
5441static bool_Bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
5442 enum PP_OD_DPM_TABLE_COMMAND type,
5443 uint32_t clk,
5444 uint32_t voltage)
5445{
5446 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5447
5448 if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) {
5449 pr_info("OD voltage is out of range [%d - %d] mV\n",do { } while(0)
5450 data->odn_dpm_table.min_vddc,do { } while(0)
5451 data->odn_dpm_table.max_vddc)do { } while(0);
5452 return false0;
5453 }
5454
5455 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
5456 if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk ||
5457 hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
5458 pr_info("OD engine clock is out of range [%d - %d] MHz\n",do { } while(0)
5459 data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,do { } while(0)
5460 hwmgr->platform_descriptor.overdriveLimit.engineClock/100)do { } while(0);
5461 return false0;
5462 }
5463 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
5464 if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk ||
5465 hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
5466 pr_info("OD memory clock is out of range [%d - %d] MHz\n",do { } while(0)
5467 data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,do { } while(0)
5468 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100)do { } while(0);
5469 return false0;
5470 }
5471 } else {
5472 return false0;
5473 }
5474
5475 return true1;
5476}
5477
5478static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
5479 enum PP_OD_DPM_TABLE_COMMAND type,
5480 long *input, uint32_t size)
5481{
5482 uint32_t i;
5483 struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL((void *)0);
5484 struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL((void *)0);
5485 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5486
5487 uint32_t input_clk;
5488 uint32_t input_vol;
5489 uint32_t input_level;
5490
5491 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",do { if (!(input)) { printk("\0014" "amdgpu: " "%s\n", "NULL user input for clock and voltage"
); return -22; } } while (0)
5492 return -EINVAL)do { if (!(input)) { printk("\0014" "amdgpu: " "%s\n", "NULL user input for clock and voltage"
); return -22; } } while (0)
;
5493
5494 if (!hwmgr->od_enabled) {
5495 pr_info("OverDrive feature not enabled\n")do { } while(0);
5496 return -EINVAL22;
5497 }
5498
5499 if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
5500 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels;
5501 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk;
5502 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN SCLK and Voltage tables"
); return -22; } } while (0)
5503 "Failed to get ODN SCLK and Voltage tables",do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN SCLK and Voltage tables"
); return -22; } } while (0)
5504 return -EINVAL)do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN SCLK and Voltage tables"
); return -22; } } while (0)
;
5505 } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
5506 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels;
5507 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk;
5508
5509 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN MCLK and Voltage tables"
); return -22; } } while (0)
5510 "Failed to get ODN MCLK and Voltage tables",do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN MCLK and Voltage tables"
); return -22; } } while (0)
5511 return -EINVAL)do { if (!((podn_dpm_table_in_backend && podn_vdd_dep_in_backend
))) { printk("\0014" "amdgpu: " "%s\n", "Failed to get ODN MCLK and Voltage tables"
); return -22; } } while (0)
;
5512 } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
5513 smu7_odn_initial_default_setting(hwmgr);
5514 return 0;
5515 } else if (PP_OD_COMMIT_DPM_TABLE == type) {
5516 smu7_check_dpm_table_updated(hwmgr);
5517 return 0;
5518 } else {
5519 return -EINVAL22;
5520 }
5521
5522 for (i = 0; i < size; i += 3) {
5523 if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) {
5524 pr_info("invalid clock voltage input \n")do { } while(0);
5525 return 0;
5526 }
5527 input_level = input[i];
5528 input_clk = input[i+1] * 100;
5529 input_vol = input[i+2];
5530
5531 if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
5532 podn_dpm_table_in_backend->entries[input_level].clock = input_clk;
5533 podn_vdd_dep_in_backend->entries[input_level].clk = input_clk;
5534 podn_dpm_table_in_backend->entries[input_level].vddc = input_vol;
5535 podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol;
5536 podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol;
5537 } else {
5538 return -EINVAL22;
5539 }
5540 }
5541
5542 return 0;
5543}
5544
5545static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
5546{
5547 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5548 uint32_t i, size = 0;
5549 uint32_t len;
5550
5551 static const char *title[8] = {"NUM",
5552 "MODE_NAME",
5553 "SCLK_UP_HYST",
5554 "SCLK_DOWN_HYST",
5555 "SCLK_ACTIVE_LEVEL",
5556 "MCLK_UP_HYST",
5557 "MCLK_DOWN_HYST",
5558 "MCLK_ACTIVE_LEVEL"};
5559
5560 if (!buf)
5561 return -EINVAL22;
5562
5563 phm_get_sysfs_buf(&buf, &size);
5564
5565 size += sysfs_emit_at(buf, size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
5566 title[0], title[1], title[2], title[3],
5567 title[4], title[5], title[6], title[7]);
5568
5569 len = ARRAY_SIZE(smu7_profiling)(sizeof((smu7_profiling)) / sizeof((smu7_profiling)[0]));
5570
5571 for (i = 0; i < len; i++) {
5572 if (i == hwmgr->power_profile_mode) {
5573 size += sysfs_emit_at(buf, size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
5574 i, amdgpu_pp_profile_name[i], "*",
5575 data->current_profile_setting.sclk_up_hyst,
5576 data->current_profile_setting.sclk_down_hyst,
5577 data->current_profile_setting.sclk_activity,
5578 data->current_profile_setting.mclk_up_hyst,
5579 data->current_profile_setting.mclk_down_hyst,
5580 data->current_profile_setting.mclk_activity);
5581 continue;
5582 }
5583 if (smu7_profiling[i].bupdate_sclk)
5584 size += sysfs_emit_at(buf, size, "%3d %16s: %8d %16d %16d ",
5585 i, amdgpu_pp_profile_name[i], smu7_profiling[i].sclk_up_hyst,
5586 smu7_profiling[i].sclk_down_hyst,
5587 smu7_profiling[i].sclk_activity);
5588 else
5589 size += sysfs_emit_at(buf, size, "%3d %16s: %8s %16s %16s ",
5590 i, amdgpu_pp_profile_name[i], "-", "-", "-");
5591
5592 if (smu7_profiling[i].bupdate_mclk)
5593 size += sysfs_emit_at(buf, size, "%16d %16d %16d\n",
5594 smu7_profiling[i].mclk_up_hyst,
5595 smu7_profiling[i].mclk_down_hyst,
5596 smu7_profiling[i].mclk_activity);
5597 else
5598 size += sysfs_emit_at(buf, size, "%16s %16s %16s\n",
5599 "-", "-", "-");
5600 }
5601
5602 return size;
5603}
5604
5605static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr,
5606 enum PP_SMC_POWER_PROFILE requst)
5607{
5608 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5609 uint32_t tmp, level;
5610
5611 if (requst == PP_SMC_POWER_PROFILE_COMPUTE) {
5612 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
5613 level = 0;
5614 tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
5615 while (tmp >>= 1)
5616 level++;
5617 if (level > 0)
5618 smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1));
5619 }
5620 } else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) {
5621 smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask);
5622 }
5623}
5624
5625static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
5626{
5627 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5628 struct profile_mode_setting tmp;
5629 enum PP_SMC_POWER_PROFILE mode;
5630
5631 if (input == NULL((void *)0))
5632 return -EINVAL22;
5633
5634 mode = input[size];
5635 switch (mode) {
5636 case PP_SMC_POWER_PROFILE_CUSTOM:
5637 if (size < 8 && size != 0)
5638 return -EINVAL22;
5639 /* If only CUSTOM is passed in, use the saved values. Check
5640 * that we actually have a CUSTOM profile by ensuring that
5641 * the "use sclk" or the "use mclk" bits are set
5642 */
5643 tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM];
5644 if (size == 0) {
5645 if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0)
5646 return -EINVAL22;
5647 } else {
5648 tmp.bupdate_sclk = input[0];
5649 tmp.sclk_up_hyst = input[1];
5650 tmp.sclk_down_hyst = input[2];
5651 tmp.sclk_activity = input[3];
5652 tmp.bupdate_mclk = input[4];
5653 tmp.mclk_up_hyst = input[5];
5654 tmp.mclk_down_hyst = input[6];
5655 tmp.mclk_activity = input[7];
5656 smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp;
5657 }
5658 if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5659 memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting))__builtin_memcpy((&data->current_profile_setting), (&
tmp), (sizeof(struct profile_mode_setting)))
;
5660 hwmgr->power_profile_mode = mode;
5661 }
5662 break;
5663 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
5664 case PP_SMC_POWER_PROFILE_POWERSAVING:
5665 case PP_SMC_POWER_PROFILE_VIDEO:
5666 case PP_SMC_POWER_PROFILE_VR:
5667 case PP_SMC_POWER_PROFILE_COMPUTE:
5668 if (mode == hwmgr->power_profile_mode)
5669 return 0;
5670
5671 memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting))__builtin_memcpy((&tmp), (&smu7_profiling[mode]), (sizeof
(struct profile_mode_setting)))
;
5672 if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5673 if (tmp.bupdate_sclk) {
5674 data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk;
5675 data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst;
5676 data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst;
5677 data->current_profile_setting.sclk_activity = tmp.sclk_activity;
5678 }
5679 if (tmp.bupdate_mclk) {
5680 data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk;
5681 data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst;
5682 data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst;
5683 data->current_profile_setting.mclk_activity = tmp.mclk_activity;
5684 }
5685 smu7_patch_compute_profile_mode(hwmgr, mode);
5686 hwmgr->power_profile_mode = mode;
5687 }
5688 break;
5689 default:
5690 return -EINVAL22;
5691 }
5692
5693 return 0;
5694}
5695
5696static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
5697 PHM_PerformanceLevelDesignation designation, uint32_t index,
5698 PHM_PerformanceLevel *level)
5699{
5700 const struct smu7_power_state *ps;
5701 uint32_t i;
5702
5703 if (level == NULL((void *)0) || hwmgr == NULL((void *)0) || state == NULL((void *)0))
5704 return -EINVAL22;
5705
5706 ps = cast_const_phw_smu7_power_state(state);
5707
5708 i = index > ps->performance_level_count - 1 ?
5709 ps->performance_level_count - 1 : index;
5710
5711 level->coreClock = ps->performance_levels[i].engine_clock;
5712 level->memory_clock = ps->performance_levels[i].memory_clock;
5713
5714 return 0;
5715}
5716
5717static int smu7_power_off_asic(struct pp_hwmgr *hwmgr)
5718{
5719 int result;
5720
5721 result = smu7_disable_dpm_tasks(hwmgr);
5722 PP_ASSERT_WITH_CODE((0 == result),do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "[disable_dpm_tasks] Failed to disable DPM!"); ; } } while (
0)
5723 "[disable_dpm_tasks] Failed to disable DPM!",do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "[disable_dpm_tasks] Failed to disable DPM!"); ; } } while (
0)
5724 )do { if (!((0 == result))) { printk("\0014" "amdgpu: " "%s\n"
, "[disable_dpm_tasks] Failed to disable DPM!"); ; } } while (
0)
;
5725
5726 return result;
5727}
5728
5729static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
5730 .backend_init = &smu7_hwmgr_backend_init,
5731 .backend_fini = &smu7_hwmgr_backend_fini,
5732 .asic_setup = &smu7_setup_asic_task,
5733 .dynamic_state_management_enable = &smu7_enable_dpm_tasks,
5734 .apply_state_adjust_rules = smu7_apply_state_adjust_rules,
5735 .force_dpm_level = &smu7_force_dpm_level,
5736 .power_state_set = smu7_set_power_state_tasks,
5737 .get_power_state_size = smu7_get_power_state_size,
5738 .get_mclk = smu7_dpm_get_mclk,
5739 .get_sclk = smu7_dpm_get_sclk,
5740 .patch_boot_state = smu7_dpm_patch_boot_state,
5741 .get_pp_table_entry = smu7_get_pp_table_entry,
5742 .get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries,
5743 .powerdown_uvd = smu7_powerdown_uvd,
5744 .powergate_uvd = smu7_powergate_uvd,
5745 .powergate_vce = smu7_powergate_vce,
5746 .disable_clock_power_gating = smu7_disable_clock_power_gating,
5747 .update_clock_gatings = smu7_update_clock_gatings,
5748 .notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment,
5749 .display_config_changed = smu7_display_configuration_changed_task,
5750 .set_max_fan_pwm_output = smu7_set_max_fan_pwm_output,
5751 .set_max_fan_rpm_output = smu7_set_max_fan_rpm_output,
5752 .stop_thermal_controller = smu7_thermal_stop_thermal_controller,
5753 .get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info,
5754 .get_fan_speed_pwm = smu7_fan_ctrl_get_fan_speed_pwm,
5755 .set_fan_speed_pwm = smu7_fan_ctrl_set_fan_speed_pwm,
5756 .reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default,
5757 .get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm,
5758 .set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm,
5759 .uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller,
5760 .register_irq_handlers = smu7_register_irq_handlers,
5761 .check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration,
5762 .check_states_equal = smu7_check_states_equal,
5763 .set_fan_control_mode = smu7_set_fan_control_mode,
5764 .get_fan_control_mode = smu7_get_fan_control_mode,
5765 .force_clock_level = smu7_force_clock_level,
5766 .print_clock_levels = smu7_print_clock_levels,
5767 .powergate_gfx = smu7_powergate_gfx,
5768 .get_sclk_od = smu7_get_sclk_od,
5769 .set_sclk_od = smu7_set_sclk_od,
5770 .get_mclk_od = smu7_get_mclk_od,
5771 .set_mclk_od = smu7_set_mclk_od,
5772 .get_clock_by_type = smu7_get_clock_by_type,
5773 .get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency,
5774 .set_watermarks_for_clocks_ranges = smu7_set_watermarks_for_clocks_ranges,
5775 .read_sensor = smu7_read_sensor,
5776 .dynamic_state_management_disable = smu7_disable_dpm_tasks,
5777 .avfs_control = smu7_avfs_control,
5778 .disable_smc_firmware_ctf = smu7_thermal_disable_alert,
5779 .start_thermal_controller = smu7_start_thermal_controller,
5780 .notify_cac_buffer_info = smu7_notify_cac_buffer_info,
5781 .get_max_high_clocks = smu7_get_max_high_clocks,
5782 .get_thermal_temperature_range = smu7_get_thermal_temperature_range,
5783 .odn_edit_dpm_table = smu7_odn_edit_dpm_table,
5784 .set_power_limit = smu7_set_power_limit,
5785 .get_power_profile_mode = smu7_get_power_profile_mode,
5786 .set_power_profile_mode = smu7_set_power_profile_mode,
5787 .get_performance_level = smu7_get_performance_level,
5788 .get_asic_baco_capability = smu7_baco_get_capability,
5789 .get_asic_baco_state = smu7_baco_get_state,
5790 .set_asic_baco_state = smu7_baco_set_state,
5791 .power_off_asic = smu7_power_off_asic,
5792};
5793
5794uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
5795 uint32_t clock_insr)
5796{
5797 uint8_t i;
5798 uint32_t temp;
5799 uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK)(((clock_insr)>((uint32_t)2500))?(clock_insr):((uint32_t)2500
))
;
5800
5801 PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0)do { if (!((clock >= min))) { printk("\0014" "amdgpu: " "%s\n"
, "Engine clock can't satisfy stutter requirement!"); return 0
; } } while (0)
;
5802 for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID5; ; i--) {
5803 temp = clock >> i;
5804
5805 if (temp >= min || i == 0)
5806 break;
5807 }
5808 return i;
5809}
5810
5811int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
5812{
5813 hwmgr->hwmgr_func = &smu7_hwmgr_funcs;
5814 if (hwmgr->pp_table_version == PP_TABLE_V0)
5815 hwmgr->pptable_func = &pptable_funcs;
5816 else if (hwmgr->pp_table_version == PP_TABLE_V1)
5817 hwmgr->pptable_func = &pptable_v1_0_funcs;
5818
5819 return 0;
5820}