2 * Copyright 2016 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include <linux/module.h>
24 #include <linux/pci.h>
25 #include <linux/slab.h>
28 #include "vega10_processpptables.h"
29 #include "ppatomfwctrl.h"
30 #include "atomfirmware.h"
32 #include "cgs_common.h"
33 #include "vega10_pptable.h"
35 #define NUM_DSPCLK_LEVELS 8
36 #define VEGA10_ENGINECLOCK_HARDMAX 198000
38 static void set_hw_cap(struct pp_hwmgr
*hwmgr
, bool enable
,
39 enum phm_platform_caps cap
)
42 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
, cap
);
44 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
, cap
);
47 static const void *get_powerplay_table(struct pp_hwmgr
*hwmgr
)
49 int index
= GetIndexIntoMasterDataTable(powerplayinfo
);
53 const void *table_address
= hwmgr
->soft_pp_table
;
56 table_address
= (ATOM_Vega10_POWERPLAYTABLE
*)
57 smu_atom_get_data_table(hwmgr
->adev
, index
,
60 hwmgr
->soft_pp_table
= table_address
; /*Cache the result in RAM.*/
61 hwmgr
->soft_pp_table_size
= size
;
67 static int check_powerplay_tables(
68 struct pp_hwmgr
*hwmgr
,
69 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
)
71 const ATOM_Vega10_State_Array
*state_arrays
;
73 state_arrays
= (ATOM_Vega10_State_Array
*)(((unsigned long)powerplay_table
) +
74 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
76 PP_ASSERT_WITH_CODE((powerplay_table
->sHeader
.format_revision
>=
77 ATOM_Vega10_TABLE_REVISION_VEGA10
),
78 "Unsupported PPTable format!", return -1);
79 PP_ASSERT_WITH_CODE(powerplay_table
->usStateArrayOffset
,
80 "State table is not set!", return -1);
81 PP_ASSERT_WITH_CODE(powerplay_table
->sHeader
.structuresize
> 0,
82 "Invalid PowerPlay Table!", return -1);
83 PP_ASSERT_WITH_CODE(state_arrays
->ucNumEntries
> 0,
84 "Invalid PowerPlay Table!", return -1);
89 static int set_platform_caps(struct pp_hwmgr
*hwmgr
, uint32_t powerplay_caps
)
93 0 != (powerplay_caps
& ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY
),
94 PHM_PlatformCaps_PowerPlaySupport
);
98 0 != (powerplay_caps
& ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE
),
99 PHM_PlatformCaps_BiosPowerSourceControl
);
103 0 != (powerplay_caps
& ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC
),
104 PHM_PlatformCaps_AutomaticDCTransition
);
108 0 != (powerplay_caps
& ATOM_VEGA10_PP_PLATFORM_CAP_BACO
),
109 PHM_PlatformCaps_BACO
);
113 0 != (powerplay_caps
& ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL
),
114 PHM_PlatformCaps_CombinePCCWithThermalSignal
);
119 static int init_thermal_controller(
120 struct pp_hwmgr
*hwmgr
,
121 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
)
123 const ATOM_Vega10_Thermal_Controller
*thermal_controller
;
124 const Vega10_PPTable_Generic_SubTable_Header
*header
;
125 const ATOM_Vega10_Fan_Table
*fan_table_v1
;
126 const ATOM_Vega10_Fan_Table_V2
*fan_table_v2
;
127 const ATOM_Vega10_Fan_Table_V3
*fan_table_v3
;
129 thermal_controller
= (ATOM_Vega10_Thermal_Controller
*)
130 (((unsigned long)powerplay_table
) +
131 le16_to_cpu(powerplay_table
->usThermalControllerOffset
));
133 PP_ASSERT_WITH_CODE((powerplay_table
->usThermalControllerOffset
!= 0),
134 "Thermal controller table not set!", return -EINVAL
);
136 hwmgr
->thermal_controller
.ucType
= thermal_controller
->ucType
;
137 hwmgr
->thermal_controller
.ucI2cLine
= thermal_controller
->ucI2cLine
;
138 hwmgr
->thermal_controller
.ucI2cAddress
= thermal_controller
->ucI2cAddress
;
140 hwmgr
->thermal_controller
.fanInfo
.bNoFan
=
141 (0 != (thermal_controller
->ucFanParameters
&
142 ATOM_VEGA10_PP_FANPARAMETERS_NOFAN
));
144 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
145 thermal_controller
->ucFanParameters
&
146 ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
148 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
=
149 thermal_controller
->ucFanMinRPM
* 100UL;
150 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
=
151 thermal_controller
->ucFanMaxRPM
* 100UL;
153 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
158 ATOM_VEGA10_PP_THERMALCONTROLLER_NONE
!= hwmgr
->thermal_controller
.ucType
,
159 PHM_PlatformCaps_ThermalController
);
161 if (!powerplay_table
->usFanTableOffset
)
164 header
= (const Vega10_PPTable_Generic_SubTable_Header
*)
165 (((unsigned long)powerplay_table
) +
166 le16_to_cpu(powerplay_table
->usFanTableOffset
));
168 if (header
->ucRevId
== 10) {
169 fan_table_v1
= (ATOM_Vega10_Fan_Table
*)header
;
171 PP_ASSERT_WITH_CODE((fan_table_v1
->ucRevId
>= 8),
172 "Invalid Input Fan Table!", return -EINVAL
);
174 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
175 PHM_PlatformCaps_MicrocodeFanControl
);
177 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
=
178 le16_to_cpu(fan_table_v1
->usFanOutputSensitivity
);
179 hwmgr
->thermal_controller
.advanceFanControlParameters
.usMaxFanRPM
=
180 le16_to_cpu(fan_table_v1
->usFanRPMMax
);
181 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanRPMMaxLimit
=
182 le16_to_cpu(fan_table_v1
->usThrottlingRPM
);
183 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
=
184 le16_to_cpu(fan_table_v1
->usFanAcousticLimit
);
185 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
=
186 le16_to_cpu(fan_table_v1
->usTargetTemperature
);
187 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
=
188 le16_to_cpu(fan_table_v1
->usMinimumPWMLimit
);
189 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulTargetGfxClk
=
190 le16_to_cpu(fan_table_v1
->usTargetGfxClk
);
191 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
=
192 le16_to_cpu(fan_table_v1
->usFanGainEdge
);
193 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
=
194 le16_to_cpu(fan_table_v1
->usFanGainHotspot
);
195 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
=
196 le16_to_cpu(fan_table_v1
->usFanGainLiquid
);
197 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
=
198 le16_to_cpu(fan_table_v1
->usFanGainVrVddc
);
199 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
=
200 le16_to_cpu(fan_table_v1
->usFanGainVrMvdd
);
201 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
=
202 le16_to_cpu(fan_table_v1
->usFanGainPlx
);
203 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
=
204 le16_to_cpu(fan_table_v1
->usFanGainHbm
);
206 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucEnableZeroRPM
=
207 fan_table_v1
->ucEnableZeroRPM
;
208 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStopTemperature
=
209 le16_to_cpu(fan_table_v1
->usFanStopTemperature
);
210 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStartTemperature
=
211 le16_to_cpu(fan_table_v1
->usFanStartTemperature
);
212 } else if (header
->ucRevId
== 0xb) {
213 fan_table_v2
= (ATOM_Vega10_Fan_Table_V2
*)header
;
215 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
216 fan_table_v2
->ucFanParameters
& ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
217 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
= fan_table_v2
->ucFanMinRPM
* 100UL;
218 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
= fan_table_v2
->ucFanMaxRPM
* 100UL;
219 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
220 PHM_PlatformCaps_MicrocodeFanControl
);
221 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
=
222 le16_to_cpu(fan_table_v2
->usFanOutputSensitivity
);
223 hwmgr
->thermal_controller
.advanceFanControlParameters
.usMaxFanRPM
=
224 fan_table_v2
->ucFanMaxRPM
* 100UL;
225 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanRPMMaxLimit
=
226 le16_to_cpu(fan_table_v2
->usThrottlingRPM
);
227 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
=
228 le16_to_cpu(fan_table_v2
->usFanAcousticLimitRpm
);
229 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
=
230 le16_to_cpu(fan_table_v2
->usTargetTemperature
);
231 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
=
232 le16_to_cpu(fan_table_v2
->usMinimumPWMLimit
);
233 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulTargetGfxClk
=
234 le16_to_cpu(fan_table_v2
->usTargetGfxClk
);
235 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
=
236 le16_to_cpu(fan_table_v2
->usFanGainEdge
);
237 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
=
238 le16_to_cpu(fan_table_v2
->usFanGainHotspot
);
239 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
=
240 le16_to_cpu(fan_table_v2
->usFanGainLiquid
);
241 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
=
242 le16_to_cpu(fan_table_v2
->usFanGainVrVddc
);
243 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
=
244 le16_to_cpu(fan_table_v2
->usFanGainVrMvdd
);
245 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
=
246 le16_to_cpu(fan_table_v2
->usFanGainPlx
);
247 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
=
248 le16_to_cpu(fan_table_v2
->usFanGainHbm
);
250 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucEnableZeroRPM
=
251 fan_table_v2
->ucEnableZeroRPM
;
252 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStopTemperature
=
253 le16_to_cpu(fan_table_v2
->usFanStopTemperature
);
254 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStartTemperature
=
255 le16_to_cpu(fan_table_v2
->usFanStartTemperature
);
256 } else if (header
->ucRevId
> 0xb) {
257 fan_table_v3
= (ATOM_Vega10_Fan_Table_V3
*)header
;
259 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
260 fan_table_v3
->ucFanParameters
& ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
261 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
= fan_table_v3
->ucFanMinRPM
* 100UL;
262 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
= fan_table_v3
->ucFanMaxRPM
* 100UL;
263 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
264 PHM_PlatformCaps_MicrocodeFanControl
);
265 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
=
266 le16_to_cpu(fan_table_v3
->usFanOutputSensitivity
);
267 hwmgr
->thermal_controller
.advanceFanControlParameters
.usMaxFanRPM
=
268 fan_table_v3
->ucFanMaxRPM
* 100UL;
269 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanRPMMaxLimit
=
270 le16_to_cpu(fan_table_v3
->usThrottlingRPM
);
271 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
=
272 le16_to_cpu(fan_table_v3
->usFanAcousticLimitRpm
);
273 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
=
274 le16_to_cpu(fan_table_v3
->usTargetTemperature
);
275 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
=
276 le16_to_cpu(fan_table_v3
->usMinimumPWMLimit
);
277 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulTargetGfxClk
=
278 le16_to_cpu(fan_table_v3
->usTargetGfxClk
);
279 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
=
280 le16_to_cpu(fan_table_v3
->usFanGainEdge
);
281 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
=
282 le16_to_cpu(fan_table_v3
->usFanGainHotspot
);
283 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
=
284 le16_to_cpu(fan_table_v3
->usFanGainLiquid
);
285 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
=
286 le16_to_cpu(fan_table_v3
->usFanGainVrVddc
);
287 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
=
288 le16_to_cpu(fan_table_v3
->usFanGainVrMvdd
);
289 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
=
290 le16_to_cpu(fan_table_v3
->usFanGainPlx
);
291 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
=
292 le16_to_cpu(fan_table_v3
->usFanGainHbm
);
294 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucEnableZeroRPM
=
295 fan_table_v3
->ucEnableZeroRPM
;
296 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStopTemperature
=
297 le16_to_cpu(fan_table_v3
->usFanStopTemperature
);
298 hwmgr
->thermal_controller
.advanceFanControlParameters
.usZeroRPMStartTemperature
=
299 le16_to_cpu(fan_table_v3
->usFanStartTemperature
);
300 hwmgr
->thermal_controller
.advanceFanControlParameters
.usMGpuThrottlingRPMLimit
=
301 le16_to_cpu(fan_table_v3
->usMGpuThrottlingRPM
);
307 static int init_over_drive_limits(
308 struct pp_hwmgr
*hwmgr
,
309 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
)
311 const ATOM_Vega10_GFXCLK_Dependency_Table
*gfxclk_dep_table
=
312 (const ATOM_Vega10_GFXCLK_Dependency_Table
*)
313 (((unsigned long) powerplay_table
) +
314 le16_to_cpu(powerplay_table
->usGfxclkDependencyTableOffset
));
315 bool is_acg_enabled
= false;
316 ATOM_Vega10_GFXCLK_Dependency_Record_V2
*patom_record_v2
;
318 if (gfxclk_dep_table
->ucRevId
== 1) {
320 (ATOM_Vega10_GFXCLK_Dependency_Record_V2
*)gfxclk_dep_table
->entries
;
322 (bool)patom_record_v2
[gfxclk_dep_table
->ucNumEntries
-1].ucACGEnable
;
325 if (powerplay_table
->ulMaxODEngineClock
> VEGA10_ENGINECLOCK_HARDMAX
&&
327 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
328 VEGA10_ENGINECLOCK_HARDMAX
;
330 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
331 le32_to_cpu(powerplay_table
->ulMaxODEngineClock
);
332 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
333 le32_to_cpu(powerplay_table
->ulMaxODMemoryClock
);
335 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
336 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
337 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
342 static int get_mm_clock_voltage_table(
343 struct pp_hwmgr
*hwmgr
,
344 phm_ppt_v1_mm_clock_voltage_dependency_table
**vega10_mm_table
,
345 const ATOM_Vega10_MM_Dependency_Table
*mm_dependency_table
)
347 uint32_t table_size
, i
;
348 const ATOM_Vega10_MM_Dependency_Record
*mm_dependency_record
;
349 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
;
351 PP_ASSERT_WITH_CODE((mm_dependency_table
->ucNumEntries
!= 0),
352 "Invalid PowerPlay Table!", return -1);
354 table_size
= sizeof(uint32_t) +
355 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record
) *
356 mm_dependency_table
->ucNumEntries
;
357 mm_table
= kzalloc(table_size
, GFP_KERNEL
);
362 mm_table
->count
= mm_dependency_table
->ucNumEntries
;
364 for (i
= 0; i
< mm_dependency_table
->ucNumEntries
; i
++) {
365 mm_dependency_record
= &mm_dependency_table
->entries
[i
];
366 mm_table
->entries
[i
].vddcInd
= mm_dependency_record
->ucVddcInd
;
367 mm_table
->entries
[i
].samclock
=
368 le32_to_cpu(mm_dependency_record
->ulPSPClk
);
369 mm_table
->entries
[i
].eclk
= le32_to_cpu(mm_dependency_record
->ulEClk
);
370 mm_table
->entries
[i
].vclk
= le32_to_cpu(mm_dependency_record
->ulVClk
);
371 mm_table
->entries
[i
].dclk
= le32_to_cpu(mm_dependency_record
->ulDClk
);
374 *vega10_mm_table
= mm_table
;
379 static void get_scl_sda_value(uint8_t line
, uint8_t *scl
, uint8_t* sda
)
382 case Vega10_I2CLineID_DDC1
:
383 *scl
= Vega10_I2C_DDC1CLK
;
384 *sda
= Vega10_I2C_DDC1DATA
;
386 case Vega10_I2CLineID_DDC2
:
387 *scl
= Vega10_I2C_DDC2CLK
;
388 *sda
= Vega10_I2C_DDC2DATA
;
390 case Vega10_I2CLineID_DDC3
:
391 *scl
= Vega10_I2C_DDC3CLK
;
392 *sda
= Vega10_I2C_DDC3DATA
;
394 case Vega10_I2CLineID_DDC4
:
395 *scl
= Vega10_I2C_DDC4CLK
;
396 *sda
= Vega10_I2C_DDC4DATA
;
398 case Vega10_I2CLineID_DDC5
:
399 *scl
= Vega10_I2C_DDC5CLK
;
400 *sda
= Vega10_I2C_DDC5DATA
;
402 case Vega10_I2CLineID_DDC6
:
403 *scl
= Vega10_I2C_DDC6CLK
;
404 *sda
= Vega10_I2C_DDC6DATA
;
406 case Vega10_I2CLineID_SCLSDA
:
407 *scl
= Vega10_I2C_SCL
;
408 *sda
= Vega10_I2C_SDA
;
410 case Vega10_I2CLineID_DDCVGA
:
411 *scl
= Vega10_I2C_DDCVGACLK
;
412 *sda
= Vega10_I2C_DDCVGADATA
;
421 static int get_tdp_table(
422 struct pp_hwmgr
*hwmgr
,
423 struct phm_tdp_table
**info_tdp_table
,
424 const Vega10_PPTable_Generic_SubTable_Header
*table
)
427 struct phm_tdp_table
*tdp_table
;
430 const ATOM_Vega10_PowerTune_Table
*power_tune_table
;
431 const ATOM_Vega10_PowerTune_Table_V2
*power_tune_table_v2
;
432 const ATOM_Vega10_PowerTune_Table_V3
*power_tune_table_v3
;
434 table_size
= sizeof(uint32_t) + sizeof(struct phm_tdp_table
);
436 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
441 if (table
->ucRevId
== 5) {
442 power_tune_table
= (ATOM_Vega10_PowerTune_Table
*)table
;
443 tdp_table
->usMaximumPowerDeliveryLimit
= le16_to_cpu(power_tune_table
->usSocketPowerLimit
);
444 tdp_table
->usTDC
= le16_to_cpu(power_tune_table
->usTdcLimit
);
445 tdp_table
->usEDCLimit
= le16_to_cpu(power_tune_table
->usEdcLimit
);
446 tdp_table
->usSoftwareShutdownTemp
=
447 le16_to_cpu(power_tune_table
->usSoftwareShutdownTemp
);
448 tdp_table
->usTemperatureLimitTedge
=
449 le16_to_cpu(power_tune_table
->usTemperatureLimitTedge
);
450 tdp_table
->usTemperatureLimitHotspot
=
451 le16_to_cpu(power_tune_table
->usTemperatureLimitHotSpot
);
452 tdp_table
->usTemperatureLimitLiquid1
=
453 le16_to_cpu(power_tune_table
->usTemperatureLimitLiquid1
);
454 tdp_table
->usTemperatureLimitLiquid2
=
455 le16_to_cpu(power_tune_table
->usTemperatureLimitLiquid2
);
456 tdp_table
->usTemperatureLimitHBM
=
457 le16_to_cpu(power_tune_table
->usTemperatureLimitHBM
);
458 tdp_table
->usTemperatureLimitVrVddc
=
459 le16_to_cpu(power_tune_table
->usTemperatureLimitVrSoc
);
460 tdp_table
->usTemperatureLimitVrMvdd
=
461 le16_to_cpu(power_tune_table
->usTemperatureLimitVrMem
);
462 tdp_table
->usTemperatureLimitPlx
=
463 le16_to_cpu(power_tune_table
->usTemperatureLimitPlx
);
464 tdp_table
->ucLiquid1_I2C_address
= power_tune_table
->ucLiquid1_I2C_address
;
465 tdp_table
->ucLiquid2_I2C_address
= power_tune_table
->ucLiquid2_I2C_address
;
466 tdp_table
->ucLiquid_I2C_Line
= power_tune_table
->ucLiquid_I2C_LineSCL
;
467 tdp_table
->ucLiquid_I2C_LineSDA
= power_tune_table
->ucLiquid_I2C_LineSDA
;
468 tdp_table
->ucVr_I2C_address
= power_tune_table
->ucVr_I2C_address
;
469 tdp_table
->ucVr_I2C_Line
= power_tune_table
->ucVr_I2C_LineSCL
;
470 tdp_table
->ucVr_I2C_LineSDA
= power_tune_table
->ucVr_I2C_LineSDA
;
471 tdp_table
->ucPlx_I2C_address
= power_tune_table
->ucPlx_I2C_address
;
472 tdp_table
->ucPlx_I2C_Line
= power_tune_table
->ucPlx_I2C_LineSCL
;
473 tdp_table
->ucPlx_I2C_LineSDA
= power_tune_table
->ucPlx_I2C_LineSDA
;
474 hwmgr
->platform_descriptor
.LoadLineSlope
= le16_to_cpu(power_tune_table
->usLoadLineResistance
);
475 } else if (table
->ucRevId
== 6) {
476 power_tune_table_v2
= (ATOM_Vega10_PowerTune_Table_V2
*)table
;
477 tdp_table
->usMaximumPowerDeliveryLimit
= le16_to_cpu(power_tune_table_v2
->usSocketPowerLimit
);
478 tdp_table
->usTDC
= le16_to_cpu(power_tune_table_v2
->usTdcLimit
);
479 tdp_table
->usEDCLimit
= le16_to_cpu(power_tune_table_v2
->usEdcLimit
);
480 tdp_table
->usSoftwareShutdownTemp
=
481 le16_to_cpu(power_tune_table_v2
->usSoftwareShutdownTemp
);
482 tdp_table
->usTemperatureLimitTedge
=
483 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitTedge
);
484 tdp_table
->usTemperatureLimitHotspot
=
485 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitHotSpot
);
486 tdp_table
->usTemperatureLimitLiquid1
=
487 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitLiquid1
);
488 tdp_table
->usTemperatureLimitLiquid2
=
489 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitLiquid2
);
490 tdp_table
->usTemperatureLimitHBM
=
491 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitHBM
);
492 tdp_table
->usTemperatureLimitVrVddc
=
493 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitVrSoc
);
494 tdp_table
->usTemperatureLimitVrMvdd
=
495 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitVrMem
);
496 tdp_table
->usTemperatureLimitPlx
=
497 le16_to_cpu(power_tune_table_v2
->usTemperatureLimitPlx
);
498 tdp_table
->ucLiquid1_I2C_address
= power_tune_table_v2
->ucLiquid1_I2C_address
;
499 tdp_table
->ucLiquid2_I2C_address
= power_tune_table_v2
->ucLiquid2_I2C_address
;
501 get_scl_sda_value(power_tune_table_v2
->ucLiquid_I2C_Line
, &scl
, &sda
);
503 tdp_table
->ucLiquid_I2C_Line
= scl
;
504 tdp_table
->ucLiquid_I2C_LineSDA
= sda
;
506 tdp_table
->ucVr_I2C_address
= power_tune_table_v2
->ucVr_I2C_address
;
508 get_scl_sda_value(power_tune_table_v2
->ucVr_I2C_Line
, &scl
, &sda
);
510 tdp_table
->ucVr_I2C_Line
= scl
;
511 tdp_table
->ucVr_I2C_LineSDA
= sda
;
512 tdp_table
->ucPlx_I2C_address
= power_tune_table_v2
->ucPlx_I2C_address
;
514 get_scl_sda_value(power_tune_table_v2
->ucPlx_I2C_Line
, &scl
, &sda
);
516 tdp_table
->ucPlx_I2C_Line
= scl
;
517 tdp_table
->ucPlx_I2C_LineSDA
= sda
;
519 hwmgr
->platform_descriptor
.LoadLineSlope
=
520 le16_to_cpu(power_tune_table_v2
->usLoadLineResistance
);
522 power_tune_table_v3
= (ATOM_Vega10_PowerTune_Table_V3
*)table
;
523 tdp_table
->usMaximumPowerDeliveryLimit
= le16_to_cpu(power_tune_table_v3
->usSocketPowerLimit
);
524 tdp_table
->usTDC
= le16_to_cpu(power_tune_table_v3
->usTdcLimit
);
525 tdp_table
->usEDCLimit
= le16_to_cpu(power_tune_table_v3
->usEdcLimit
);
526 tdp_table
->usSoftwareShutdownTemp
= le16_to_cpu(power_tune_table_v3
->usSoftwareShutdownTemp
);
527 tdp_table
->usTemperatureLimitTedge
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitTedge
);
528 tdp_table
->usTemperatureLimitHotspot
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitHotSpot
);
529 tdp_table
->usTemperatureLimitLiquid1
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitLiquid1
);
530 tdp_table
->usTemperatureLimitLiquid2
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitLiquid2
);
531 tdp_table
->usTemperatureLimitHBM
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitHBM
);
532 tdp_table
->usTemperatureLimitVrVddc
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitVrSoc
);
533 tdp_table
->usTemperatureLimitVrMvdd
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitVrMem
);
534 tdp_table
->usTemperatureLimitPlx
= le16_to_cpu(power_tune_table_v3
->usTemperatureLimitPlx
);
535 tdp_table
->ucLiquid1_I2C_address
= power_tune_table_v3
->ucLiquid1_I2C_address
;
536 tdp_table
->ucLiquid2_I2C_address
= power_tune_table_v3
->ucLiquid2_I2C_address
;
537 tdp_table
->usBoostStartTemperature
= le16_to_cpu(power_tune_table_v3
->usBoostStartTemperature
);
538 tdp_table
->usBoostStopTemperature
= le16_to_cpu(power_tune_table_v3
->usBoostStopTemperature
);
539 tdp_table
->ulBoostClock
= le32_to_cpu(power_tune_table_v3
->ulBoostClock
);
541 get_scl_sda_value(power_tune_table_v3
->ucLiquid_I2C_Line
, &scl
, &sda
);
543 tdp_table
->ucLiquid_I2C_Line
= scl
;
544 tdp_table
->ucLiquid_I2C_LineSDA
= sda
;
546 tdp_table
->ucVr_I2C_address
= power_tune_table_v3
->ucVr_I2C_address
;
548 get_scl_sda_value(power_tune_table_v3
->ucVr_I2C_Line
, &scl
, &sda
);
550 tdp_table
->ucVr_I2C_Line
= scl
;
551 tdp_table
->ucVr_I2C_LineSDA
= sda
;
553 tdp_table
->ucPlx_I2C_address
= power_tune_table_v3
->ucPlx_I2C_address
;
555 get_scl_sda_value(power_tune_table_v3
->ucPlx_I2C_Line
, &scl
, &sda
);
557 tdp_table
->ucPlx_I2C_Line
= scl
;
558 tdp_table
->ucPlx_I2C_LineSDA
= sda
;
560 hwmgr
->platform_descriptor
.LoadLineSlope
=
561 le16_to_cpu(power_tune_table_v3
->usLoadLineResistance
);
564 *info_tdp_table
= tdp_table
;
569 static int get_socclk_voltage_dependency_table(
570 struct pp_hwmgr
*hwmgr
,
571 phm_ppt_v1_clock_voltage_dependency_table
**pp_vega10_clk_dep_table
,
572 const ATOM_Vega10_SOCCLK_Dependency_Table
*clk_dep_table
)
574 uint32_t table_size
, i
;
575 phm_ppt_v1_clock_voltage_dependency_table
*clk_table
;
577 PP_ASSERT_WITH_CODE(clk_dep_table
->ucNumEntries
,
578 "Invalid PowerPlay Table!", return -1);
580 table_size
= sizeof(uint32_t) +
581 sizeof(phm_ppt_v1_clock_voltage_dependency_record
) *
582 clk_dep_table
->ucNumEntries
;
584 clk_table
= kzalloc(table_size
, GFP_KERNEL
);
589 clk_table
->count
= (uint32_t)clk_dep_table
->ucNumEntries
;
591 for (i
= 0; i
< clk_dep_table
->ucNumEntries
; i
++) {
592 clk_table
->entries
[i
].vddInd
=
593 clk_dep_table
->entries
[i
].ucVddInd
;
594 clk_table
->entries
[i
].clk
=
595 le32_to_cpu(clk_dep_table
->entries
[i
].ulClk
);
598 *pp_vega10_clk_dep_table
= clk_table
;
603 static int get_mclk_voltage_dependency_table(
604 struct pp_hwmgr
*hwmgr
,
605 phm_ppt_v1_clock_voltage_dependency_table
**pp_vega10_mclk_dep_table
,
606 const ATOM_Vega10_MCLK_Dependency_Table
*mclk_dep_table
)
608 uint32_t table_size
, i
;
609 phm_ppt_v1_clock_voltage_dependency_table
*mclk_table
;
611 PP_ASSERT_WITH_CODE(mclk_dep_table
->ucNumEntries
,
612 "Invalid PowerPlay Table!", return -1);
614 table_size
= sizeof(uint32_t) +
615 sizeof(phm_ppt_v1_clock_voltage_dependency_record
) *
616 mclk_dep_table
->ucNumEntries
;
618 mclk_table
= kzalloc(table_size
, GFP_KERNEL
);
623 mclk_table
->count
= (uint32_t)mclk_dep_table
->ucNumEntries
;
625 for (i
= 0; i
< mclk_dep_table
->ucNumEntries
; i
++) {
626 mclk_table
->entries
[i
].vddInd
=
627 mclk_dep_table
->entries
[i
].ucVddInd
;
628 mclk_table
->entries
[i
].vddciInd
=
629 mclk_dep_table
->entries
[i
].ucVddciInd
;
630 mclk_table
->entries
[i
].mvddInd
=
631 mclk_dep_table
->entries
[i
].ucVddMemInd
;
632 mclk_table
->entries
[i
].clk
=
633 le32_to_cpu(mclk_dep_table
->entries
[i
].ulMemClk
);
636 *pp_vega10_mclk_dep_table
= mclk_table
;
641 static int get_gfxclk_voltage_dependency_table(
642 struct pp_hwmgr
*hwmgr
,
643 struct phm_ppt_v1_clock_voltage_dependency_table
644 **pp_vega10_clk_dep_table
,
645 const ATOM_Vega10_GFXCLK_Dependency_Table
*clk_dep_table
)
647 uint32_t table_size
, i
;
648 struct phm_ppt_v1_clock_voltage_dependency_table
650 ATOM_Vega10_GFXCLK_Dependency_Record_V2
*patom_record_v2
;
652 PP_ASSERT_WITH_CODE((clk_dep_table
->ucNumEntries
!= 0),
653 "Invalid PowerPlay Table!", return -1);
655 table_size
= sizeof(uint32_t) +
656 sizeof(phm_ppt_v1_clock_voltage_dependency_record
) *
657 clk_dep_table
->ucNumEntries
;
659 clk_table
= kzalloc(table_size
, GFP_KERNEL
);
664 clk_table
->count
= clk_dep_table
->ucNumEntries
;
666 if (clk_dep_table
->ucRevId
== 0) {
667 for (i
= 0; i
< clk_table
->count
; i
++) {
668 clk_table
->entries
[i
].vddInd
=
669 clk_dep_table
->entries
[i
].ucVddInd
;
670 clk_table
->entries
[i
].clk
=
671 le32_to_cpu(clk_dep_table
->entries
[i
].ulClk
);
672 clk_table
->entries
[i
].cks_enable
=
673 (((le16_to_cpu(clk_dep_table
->entries
[i
].usCKSVOffsetandDisable
) & 0x8000)
674 >> 15) == 0) ? 1 : 0;
675 clk_table
->entries
[i
].cks_voffset
=
676 le16_to_cpu(clk_dep_table
->entries
[i
].usCKSVOffsetandDisable
) & 0x7F;
677 clk_table
->entries
[i
].sclk_offset
=
678 le16_to_cpu(clk_dep_table
->entries
[i
].usAVFSOffset
);
680 } else if (clk_dep_table
->ucRevId
== 1) {
681 patom_record_v2
= (ATOM_Vega10_GFXCLK_Dependency_Record_V2
*)clk_dep_table
->entries
;
682 for (i
= 0; i
< clk_table
->count
; i
++) {
683 clk_table
->entries
[i
].vddInd
=
684 patom_record_v2
->ucVddInd
;
685 clk_table
->entries
[i
].clk
=
686 le32_to_cpu(patom_record_v2
->ulClk
);
687 clk_table
->entries
[i
].cks_enable
=
688 (((le16_to_cpu(patom_record_v2
->usCKSVOffsetandDisable
) & 0x8000)
689 >> 15) == 0) ? 1 : 0;
690 clk_table
->entries
[i
].cks_voffset
=
691 le16_to_cpu(patom_record_v2
->usCKSVOffsetandDisable
) & 0x7F;
692 clk_table
->entries
[i
].sclk_offset
=
693 le16_to_cpu(patom_record_v2
->usAVFSOffset
);
698 PP_ASSERT_WITH_CODE(false,
699 "Unsupported GFXClockDependencyTable Revision!",
703 *pp_vega10_clk_dep_table
= clk_table
;
708 static int get_pix_clk_voltage_dependency_table(
709 struct pp_hwmgr
*hwmgr
,
710 struct phm_ppt_v1_clock_voltage_dependency_table
711 **pp_vega10_clk_dep_table
,
712 const ATOM_Vega10_PIXCLK_Dependency_Table
*clk_dep_table
)
714 uint32_t table_size
, i
;
715 struct phm_ppt_v1_clock_voltage_dependency_table
718 PP_ASSERT_WITH_CODE((clk_dep_table
->ucNumEntries
!= 0),
719 "Invalid PowerPlay Table!", return -1);
721 table_size
= sizeof(uint32_t) +
722 sizeof(phm_ppt_v1_clock_voltage_dependency_record
) *
723 clk_dep_table
->ucNumEntries
;
725 clk_table
= kzalloc(table_size
, GFP_KERNEL
);
730 clk_table
->count
= clk_dep_table
->ucNumEntries
;
732 for (i
= 0; i
< clk_table
->count
; i
++) {
733 clk_table
->entries
[i
].vddInd
=
734 clk_dep_table
->entries
[i
].ucVddInd
;
735 clk_table
->entries
[i
].clk
=
736 le32_to_cpu(clk_dep_table
->entries
[i
].ulClk
);
739 *pp_vega10_clk_dep_table
= clk_table
;
744 static int get_dcefclk_voltage_dependency_table(
745 struct pp_hwmgr
*hwmgr
,
746 struct phm_ppt_v1_clock_voltage_dependency_table
747 **pp_vega10_clk_dep_table
,
748 const ATOM_Vega10_DCEFCLK_Dependency_Table
*clk_dep_table
)
750 uint32_t table_size
, i
;
752 struct phm_ppt_v1_clock_voltage_dependency_table
756 struct amdgpu_device
*adev
= hwmgr
->adev
;
758 PP_ASSERT_WITH_CODE((clk_dep_table
->ucNumEntries
!= 0),
759 "Invalid PowerPlay Table!", return -1);
762 * workaround needed to add another DPM level for pioneer cards
763 * as VBIOS is locked down.
764 * This DPM level was added to support 3DPM monitors @ 4K120Hz
767 dev_id
= adev
->pdev
->device
;
768 rev_id
= adev
->pdev
->revision
;
770 if (dev_id
== 0x6863 && rev_id
== 0 &&
771 clk_dep_table
->entries
[clk_dep_table
->ucNumEntries
- 1].ulClk
< 90000)
772 num_entries
= clk_dep_table
->ucNumEntries
+ 1 > NUM_DSPCLK_LEVELS
?
773 NUM_DSPCLK_LEVELS
: clk_dep_table
->ucNumEntries
+ 1;
775 num_entries
= clk_dep_table
->ucNumEntries
;
778 table_size
= sizeof(uint32_t) +
779 sizeof(phm_ppt_v1_clock_voltage_dependency_record
) *
782 clk_table
= kzalloc(table_size
, GFP_KERNEL
);
787 clk_table
->count
= (uint32_t)num_entries
;
789 for (i
= 0; i
< clk_dep_table
->ucNumEntries
; i
++) {
790 clk_table
->entries
[i
].vddInd
=
791 clk_dep_table
->entries
[i
].ucVddInd
;
792 clk_table
->entries
[i
].clk
=
793 le32_to_cpu(clk_dep_table
->entries
[i
].ulClk
);
796 if (i
< num_entries
) {
797 clk_table
->entries
[i
].vddInd
= clk_dep_table
->entries
[i
-1].ucVddInd
;
798 clk_table
->entries
[i
].clk
= 90000;
801 *pp_vega10_clk_dep_table
= clk_table
;
806 static int get_pcie_table(struct pp_hwmgr
*hwmgr
,
807 struct phm_ppt_v1_pcie_table
**vega10_pcie_table
,
808 const Vega10_PPTable_Generic_SubTable_Header
*table
)
810 uint32_t table_size
, i
, pcie_count
;
811 struct phm_ppt_v1_pcie_table
*pcie_table
;
812 struct phm_ppt_v2_information
*table_info
=
813 (struct phm_ppt_v2_information
*)(hwmgr
->pptable
);
814 const ATOM_Vega10_PCIE_Table
*atom_pcie_table
=
815 (ATOM_Vega10_PCIE_Table
*)table
;
817 PP_ASSERT_WITH_CODE(atom_pcie_table
->ucNumEntries
,
818 "Invalid PowerPlay Table!",
821 table_size
= sizeof(uint32_t) +
822 sizeof(struct phm_ppt_v1_pcie_record
) *
823 atom_pcie_table
->ucNumEntries
;
825 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
830 pcie_count
= table_info
->vdd_dep_on_sclk
->count
;
831 if (atom_pcie_table
->ucNumEntries
<= pcie_count
)
832 pcie_count
= atom_pcie_table
->ucNumEntries
;
834 pr_info("Number of Pcie Entries exceed the number of"
835 " GFXCLK Dpm Levels!"
836 " Disregarding the excess entries...\n");
838 pcie_table
->count
= pcie_count
;
840 for (i
= 0; i
< pcie_count
; i
++) {
841 pcie_table
->entries
[i
].gen_speed
=
842 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
843 pcie_table
->entries
[i
].lane_width
=
844 atom_pcie_table
->entries
[i
].ucPCIELaneWidth
;
845 pcie_table
->entries
[i
].pcie_sclk
=
846 atom_pcie_table
->entries
[i
].ulLCLK
;
849 *vega10_pcie_table
= pcie_table
;
854 static int get_hard_limits(
855 struct pp_hwmgr
*hwmgr
,
856 struct phm_clock_and_voltage_limits
*limits
,
857 const ATOM_Vega10_Hard_Limit_Table
*limit_table
)
859 PP_ASSERT_WITH_CODE(limit_table
->ucNumEntries
,
860 "Invalid PowerPlay Table!", return -1);
862 /* currently we always take entries[0] parameters */
863 limits
->sclk
= le32_to_cpu(limit_table
->entries
[0].ulSOCCLKLimit
);
864 limits
->mclk
= le32_to_cpu(limit_table
->entries
[0].ulMCLKLimit
);
865 limits
->gfxclk
= le32_to_cpu(limit_table
->entries
[0].ulGFXCLKLimit
);
866 limits
->vddc
= le16_to_cpu(limit_table
->entries
[0].usVddcLimit
);
867 limits
->vddci
= le16_to_cpu(limit_table
->entries
[0].usVddciLimit
);
868 limits
->vddmem
= le16_to_cpu(limit_table
->entries
[0].usVddMemLimit
);
873 static int get_valid_clk(
874 struct pp_hwmgr
*hwmgr
,
875 struct phm_clock_array
**clk_table
,
876 const phm_ppt_v1_clock_voltage_dependency_table
*clk_volt_pp_table
)
878 uint32_t table_size
, i
;
879 struct phm_clock_array
*table
;
881 PP_ASSERT_WITH_CODE(clk_volt_pp_table
->count
,
882 "Invalid PowerPlay Table!", return -1);
884 table_size
= sizeof(uint32_t) +
885 sizeof(uint32_t) * clk_volt_pp_table
->count
;
887 table
= kzalloc(table_size
, GFP_KERNEL
);
892 table
->count
= (uint32_t)clk_volt_pp_table
->count
;
894 for (i
= 0; i
< table
->count
; i
++)
895 table
->values
[i
] = (uint32_t)clk_volt_pp_table
->entries
[i
].clk
;
902 static int init_powerplay_extended_tables(
903 struct pp_hwmgr
*hwmgr
,
904 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
)
907 struct phm_ppt_v2_information
*pp_table_info
=
908 (struct phm_ppt_v2_information
*)(hwmgr
->pptable
);
910 const ATOM_Vega10_MM_Dependency_Table
*mm_dependency_table
=
911 (const ATOM_Vega10_MM_Dependency_Table
*)
912 (((unsigned long) powerplay_table
) +
913 le16_to_cpu(powerplay_table
->usMMDependencyTableOffset
));
914 const Vega10_PPTable_Generic_SubTable_Header
*power_tune_table
=
915 (const Vega10_PPTable_Generic_SubTable_Header
*)
916 (((unsigned long) powerplay_table
) +
917 le16_to_cpu(powerplay_table
->usPowerTuneTableOffset
));
918 const ATOM_Vega10_SOCCLK_Dependency_Table
*socclk_dep_table
=
919 (const ATOM_Vega10_SOCCLK_Dependency_Table
*)
920 (((unsigned long) powerplay_table
) +
921 le16_to_cpu(powerplay_table
->usSocclkDependencyTableOffset
));
922 const ATOM_Vega10_GFXCLK_Dependency_Table
*gfxclk_dep_table
=
923 (const ATOM_Vega10_GFXCLK_Dependency_Table
*)
924 (((unsigned long) powerplay_table
) +
925 le16_to_cpu(powerplay_table
->usGfxclkDependencyTableOffset
));
926 const ATOM_Vega10_DCEFCLK_Dependency_Table
*dcefclk_dep_table
=
927 (const ATOM_Vega10_DCEFCLK_Dependency_Table
*)
928 (((unsigned long) powerplay_table
) +
929 le16_to_cpu(powerplay_table
->usDcefclkDependencyTableOffset
));
930 const ATOM_Vega10_MCLK_Dependency_Table
*mclk_dep_table
=
931 (const ATOM_Vega10_MCLK_Dependency_Table
*)
932 (((unsigned long) powerplay_table
) +
933 le16_to_cpu(powerplay_table
->usMclkDependencyTableOffset
));
934 const ATOM_Vega10_Hard_Limit_Table
*hard_limits
=
935 (const ATOM_Vega10_Hard_Limit_Table
*)
936 (((unsigned long) powerplay_table
) +
937 le16_to_cpu(powerplay_table
->usHardLimitTableOffset
));
938 const Vega10_PPTable_Generic_SubTable_Header
*pcie_table
=
939 (const Vega10_PPTable_Generic_SubTable_Header
*)
940 (((unsigned long) powerplay_table
) +
941 le16_to_cpu(powerplay_table
->usPCIETableOffset
));
942 const ATOM_Vega10_PIXCLK_Dependency_Table
*pixclk_dep_table
=
943 (const ATOM_Vega10_PIXCLK_Dependency_Table
*)
944 (((unsigned long) powerplay_table
) +
945 le16_to_cpu(powerplay_table
->usPixclkDependencyTableOffset
));
946 const ATOM_Vega10_PHYCLK_Dependency_Table
*phyclk_dep_table
=
947 (const ATOM_Vega10_PHYCLK_Dependency_Table
*)
948 (((unsigned long) powerplay_table
) +
949 le16_to_cpu(powerplay_table
->usPhyClkDependencyTableOffset
));
950 const ATOM_Vega10_DISPCLK_Dependency_Table
*dispclk_dep_table
=
951 (const ATOM_Vega10_DISPCLK_Dependency_Table
*)
952 (((unsigned long) powerplay_table
) +
953 le16_to_cpu(powerplay_table
->usDispClkDependencyTableOffset
));
955 pp_table_info
->vdd_dep_on_socclk
= NULL
;
956 pp_table_info
->vdd_dep_on_sclk
= NULL
;
957 pp_table_info
->vdd_dep_on_mclk
= NULL
;
958 pp_table_info
->vdd_dep_on_dcefclk
= NULL
;
959 pp_table_info
->mm_dep_table
= NULL
;
960 pp_table_info
->tdp_table
= NULL
;
961 pp_table_info
->vdd_dep_on_pixclk
= NULL
;
962 pp_table_info
->vdd_dep_on_phyclk
= NULL
;
963 pp_table_info
->vdd_dep_on_dispclk
= NULL
;
965 if (powerplay_table
->usMMDependencyTableOffset
)
966 result
= get_mm_clock_voltage_table(hwmgr
,
967 &pp_table_info
->mm_dep_table
,
968 mm_dependency_table
);
970 if (!result
&& powerplay_table
->usPowerTuneTableOffset
)
971 result
= get_tdp_table(hwmgr
,
972 &pp_table_info
->tdp_table
,
975 if (!result
&& powerplay_table
->usSocclkDependencyTableOffset
)
976 result
= get_socclk_voltage_dependency_table(hwmgr
,
977 &pp_table_info
->vdd_dep_on_socclk
,
980 if (!result
&& powerplay_table
->usGfxclkDependencyTableOffset
)
981 result
= get_gfxclk_voltage_dependency_table(hwmgr
,
982 &pp_table_info
->vdd_dep_on_sclk
,
985 if (!result
&& powerplay_table
->usPixclkDependencyTableOffset
)
986 result
= get_pix_clk_voltage_dependency_table(hwmgr
,
987 &pp_table_info
->vdd_dep_on_pixclk
,
988 (const ATOM_Vega10_PIXCLK_Dependency_Table
*)
991 if (!result
&& powerplay_table
->usPhyClkDependencyTableOffset
)
992 result
= get_pix_clk_voltage_dependency_table(hwmgr
,
993 &pp_table_info
->vdd_dep_on_phyclk
,
994 (const ATOM_Vega10_PIXCLK_Dependency_Table
*)
997 if (!result
&& powerplay_table
->usDispClkDependencyTableOffset
)
998 result
= get_pix_clk_voltage_dependency_table(hwmgr
,
999 &pp_table_info
->vdd_dep_on_dispclk
,
1000 (const ATOM_Vega10_PIXCLK_Dependency_Table
*)
1003 if (!result
&& powerplay_table
->usDcefclkDependencyTableOffset
)
1004 result
= get_dcefclk_voltage_dependency_table(hwmgr
,
1005 &pp_table_info
->vdd_dep_on_dcefclk
,
1008 if (!result
&& powerplay_table
->usMclkDependencyTableOffset
)
1009 result
= get_mclk_voltage_dependency_table(hwmgr
,
1010 &pp_table_info
->vdd_dep_on_mclk
,
1013 if (!result
&& powerplay_table
->usPCIETableOffset
)
1014 result
= get_pcie_table(hwmgr
,
1015 &pp_table_info
->pcie_table
,
1018 if (!result
&& powerplay_table
->usHardLimitTableOffset
)
1019 result
= get_hard_limits(hwmgr
,
1020 &pp_table_info
->max_clock_voltage_on_dc
,
1023 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.sclk
=
1024 pp_table_info
->max_clock_voltage_on_dc
.sclk
;
1025 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.mclk
=
1026 pp_table_info
->max_clock_voltage_on_dc
.mclk
;
1027 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddc
=
1028 pp_table_info
->max_clock_voltage_on_dc
.vddc
;
1029 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddci
=
1030 pp_table_info
->max_clock_voltage_on_dc
.vddci
;
1033 pp_table_info
->vdd_dep_on_socclk
&&
1034 pp_table_info
->vdd_dep_on_socclk
->count
)
1035 result
= get_valid_clk(hwmgr
,
1036 &pp_table_info
->valid_socclk_values
,
1037 pp_table_info
->vdd_dep_on_socclk
);
1040 pp_table_info
->vdd_dep_on_sclk
&&
1041 pp_table_info
->vdd_dep_on_sclk
->count
)
1042 result
= get_valid_clk(hwmgr
,
1043 &pp_table_info
->valid_sclk_values
,
1044 pp_table_info
->vdd_dep_on_sclk
);
1047 pp_table_info
->vdd_dep_on_dcefclk
&&
1048 pp_table_info
->vdd_dep_on_dcefclk
->count
)
1049 result
= get_valid_clk(hwmgr
,
1050 &pp_table_info
->valid_dcefclk_values
,
1051 pp_table_info
->vdd_dep_on_dcefclk
);
1054 pp_table_info
->vdd_dep_on_mclk
&&
1055 pp_table_info
->vdd_dep_on_mclk
->count
)
1056 result
= get_valid_clk(hwmgr
,
1057 &pp_table_info
->valid_mclk_values
,
1058 pp_table_info
->vdd_dep_on_mclk
);
1063 static int get_vddc_lookup_table(
1064 struct pp_hwmgr
*hwmgr
,
1065 phm_ppt_v1_voltage_lookup_table
**lookup_table
,
1066 const ATOM_Vega10_Voltage_Lookup_Table
*vddc_lookup_pp_tables
,
1067 uint32_t max_levels
)
1069 uint32_t table_size
, i
;
1070 phm_ppt_v1_voltage_lookup_table
*table
;
1072 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables
->ucNumEntries
!= 0),
1073 "Invalid SOC_VDDD Lookup Table!", return 1);
1075 table_size
= sizeof(uint32_t) +
1076 sizeof(phm_ppt_v1_voltage_lookup_record
) * max_levels
;
1078 table
= kzalloc(table_size
, GFP_KERNEL
);
1083 table
->count
= vddc_lookup_pp_tables
->ucNumEntries
;
1085 for (i
= 0; i
< vddc_lookup_pp_tables
->ucNumEntries
; i
++)
1086 table
->entries
[i
].us_vdd
=
1087 le16_to_cpu(vddc_lookup_pp_tables
->entries
[i
].usVdd
);
1089 *lookup_table
= table
;
1094 static int init_dpm_2_parameters(
1095 struct pp_hwmgr
*hwmgr
,
1096 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
)
1099 struct phm_ppt_v2_information
*pp_table_info
=
1100 (struct phm_ppt_v2_information
*)(hwmgr
->pptable
);
1101 uint32_t disable_power_control
= 0;
1103 pp_table_info
->us_ulv_voltage_offset
=
1104 le16_to_cpu(powerplay_table
->usUlvVoltageOffset
);
1106 pp_table_info
->us_ulv_smnclk_did
=
1107 le16_to_cpu(powerplay_table
->usUlvSmnclkDid
);
1108 pp_table_info
->us_ulv_mp1clk_did
=
1109 le16_to_cpu(powerplay_table
->usUlvMp1clkDid
);
1110 pp_table_info
->us_ulv_gfxclk_bypass
=
1111 le16_to_cpu(powerplay_table
->usUlvGfxclkBypass
);
1112 pp_table_info
->us_gfxclk_slew_rate
=
1113 le16_to_cpu(powerplay_table
->usGfxclkSlewRate
);
1114 pp_table_info
->uc_gfx_dpm_voltage_mode
=
1115 le16_to_cpu(powerplay_table
->ucGfxVoltageMode
);
1116 pp_table_info
->uc_soc_dpm_voltage_mode
=
1117 le16_to_cpu(powerplay_table
->ucSocVoltageMode
);
1118 pp_table_info
->uc_uclk_dpm_voltage_mode
=
1119 le16_to_cpu(powerplay_table
->ucUclkVoltageMode
);
1120 pp_table_info
->uc_uvd_dpm_voltage_mode
=
1121 le16_to_cpu(powerplay_table
->ucUvdVoltageMode
);
1122 pp_table_info
->uc_vce_dpm_voltage_mode
=
1123 le16_to_cpu(powerplay_table
->ucVceVoltageMode
);
1124 pp_table_info
->uc_mp0_dpm_voltage_mode
=
1125 le16_to_cpu(powerplay_table
->ucMp0VoltageMode
);
1126 pp_table_info
->uc_dcef_dpm_voltage_mode
=
1127 le16_to_cpu(powerplay_table
->ucDcefVoltageMode
);
1129 pp_table_info
->ppm_parameter_table
= NULL
;
1130 pp_table_info
->vddc_lookup_table
= NULL
;
1131 pp_table_info
->vddmem_lookup_table
= NULL
;
1132 pp_table_info
->vddci_lookup_table
= NULL
;
1135 hwmgr
->platform_descriptor
.TDPODLimit
=
1136 le16_to_cpu(powerplay_table
->usPowerControlLimit
);
1137 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
1138 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
1139 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
1140 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
1141 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
1142 hwmgr
->platform_descriptor
.VidStep
= 6250;
1144 disable_power_control
= 0;
1145 if (!disable_power_control
) {
1146 /* enable TDP overdrive (PowerControl) feature as well if supported */
1147 if (hwmgr
->platform_descriptor
.TDPODLimit
)
1148 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
1149 PHM_PlatformCaps_PowerControl
);
1152 if (powerplay_table
->usVddcLookupTableOffset
) {
1153 const ATOM_Vega10_Voltage_Lookup_Table
*vddc_table
=
1154 (ATOM_Vega10_Voltage_Lookup_Table
*)
1155 (((unsigned long)powerplay_table
) +
1156 le16_to_cpu(powerplay_table
->usVddcLookupTableOffset
));
1157 result
= get_vddc_lookup_table(hwmgr
,
1158 &pp_table_info
->vddc_lookup_table
, vddc_table
, 8);
1161 if (powerplay_table
->usVddmemLookupTableOffset
) {
1162 const ATOM_Vega10_Voltage_Lookup_Table
*vdd_mem_table
=
1163 (ATOM_Vega10_Voltage_Lookup_Table
*)
1164 (((unsigned long)powerplay_table
) +
1165 le16_to_cpu(powerplay_table
->usVddmemLookupTableOffset
));
1166 result
= get_vddc_lookup_table(hwmgr
,
1167 &pp_table_info
->vddmem_lookup_table
, vdd_mem_table
, 4);
1170 if (powerplay_table
->usVddciLookupTableOffset
) {
1171 const ATOM_Vega10_Voltage_Lookup_Table
*vddci_table
=
1172 (ATOM_Vega10_Voltage_Lookup_Table
*)
1173 (((unsigned long)powerplay_table
) +
1174 le16_to_cpu(powerplay_table
->usVddciLookupTableOffset
));
1175 result
= get_vddc_lookup_table(hwmgr
,
1176 &pp_table_info
->vddci_lookup_table
, vddci_table
, 4);
1182 int vega10_pp_tables_initialize(struct pp_hwmgr
*hwmgr
)
1185 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
;
1187 hwmgr
->pptable
= kzalloc(sizeof(struct phm_ppt_v2_information
), GFP_KERNEL
);
1189 PP_ASSERT_WITH_CODE((hwmgr
->pptable
!= NULL
),
1190 "Failed to allocate hwmgr->pptable!", return -ENOMEM
);
1192 powerplay_table
= get_powerplay_table(hwmgr
);
1194 PP_ASSERT_WITH_CODE((powerplay_table
!= NULL
),
1195 "Missing PowerPlay Table!", return -1);
1197 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
1199 PP_ASSERT_WITH_CODE((result
== 0),
1200 "check_powerplay_tables failed", return result
);
1202 result
= set_platform_caps(hwmgr
,
1203 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
1205 PP_ASSERT_WITH_CODE((result
== 0),
1206 "set_platform_caps failed", return result
);
1208 result
= init_thermal_controller(hwmgr
, powerplay_table
);
1210 PP_ASSERT_WITH_CODE((result
== 0),
1211 "init_thermal_controller failed", return result
);
1213 result
= init_over_drive_limits(hwmgr
, powerplay_table
);
1215 PP_ASSERT_WITH_CODE((result
== 0),
1216 "init_over_drive_limits failed", return result
);
1218 result
= init_powerplay_extended_tables(hwmgr
, powerplay_table
);
1220 PP_ASSERT_WITH_CODE((result
== 0),
1221 "init_powerplay_extended_tables failed", return result
);
1223 result
= init_dpm_2_parameters(hwmgr
, powerplay_table
);
1225 PP_ASSERT_WITH_CODE((result
== 0),
1226 "init_dpm_2_parameters failed", return result
);
1231 static int vega10_pp_tables_uninitialize(struct pp_hwmgr
*hwmgr
)
1233 struct phm_ppt_v2_information
*pp_table_info
=
1234 (struct phm_ppt_v2_information
*)(hwmgr
->pptable
);
1236 kfree(pp_table_info
->vdd_dep_on_sclk
);
1237 pp_table_info
->vdd_dep_on_sclk
= NULL
;
1239 kfree(pp_table_info
->vdd_dep_on_mclk
);
1240 pp_table_info
->vdd_dep_on_mclk
= NULL
;
1242 kfree(pp_table_info
->valid_mclk_values
);
1243 pp_table_info
->valid_mclk_values
= NULL
;
1245 kfree(pp_table_info
->valid_sclk_values
);
1246 pp_table_info
->valid_sclk_values
= NULL
;
1248 kfree(pp_table_info
->vddc_lookup_table
);
1249 pp_table_info
->vddc_lookup_table
= NULL
;
1251 kfree(pp_table_info
->vddmem_lookup_table
);
1252 pp_table_info
->vddmem_lookup_table
= NULL
;
1254 kfree(pp_table_info
->vddci_lookup_table
);
1255 pp_table_info
->vddci_lookup_table
= NULL
;
1257 kfree(pp_table_info
->ppm_parameter_table
);
1258 pp_table_info
->ppm_parameter_table
= NULL
;
1260 kfree(pp_table_info
->mm_dep_table
);
1261 pp_table_info
->mm_dep_table
= NULL
;
1263 kfree(pp_table_info
->cac_dtp_table
);
1264 pp_table_info
->cac_dtp_table
= NULL
;
1266 kfree(hwmgr
->dyn_state
.cac_dtp_table
);
1267 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1269 kfree(pp_table_info
->tdp_table
);
1270 pp_table_info
->tdp_table
= NULL
;
1272 kfree(hwmgr
->pptable
);
1273 hwmgr
->pptable
= NULL
;
1278 const struct pp_table_func vega10_pptable_funcs
= {
1279 .pptable_init
= vega10_pp_tables_initialize
,
1280 .pptable_fini
= vega10_pp_tables_uninitialize
,
1283 int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr
*hwmgr
)
1285 const ATOM_Vega10_State_Array
*state_arrays
;
1286 const ATOM_Vega10_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1288 PP_ASSERT_WITH_CODE((pp_table
!= NULL
),
1289 "Missing PowerPlay Table!", return -1);
1290 PP_ASSERT_WITH_CODE((pp_table
->sHeader
.format_revision
>=
1291 ATOM_Vega10_TABLE_REVISION_VEGA10
),
1292 "Incorrect PowerPlay table revision!", return -1);
1294 state_arrays
= (ATOM_Vega10_State_Array
*)(((unsigned long)pp_table
) +
1295 le16_to_cpu(pp_table
->usStateArrayOffset
));
1297 return (uint32_t)(state_arrays
->ucNumEntries
);
1300 static uint32_t make_classification_flags(struct pp_hwmgr
*hwmgr
,
1301 uint16_t classification
, uint16_t classification2
)
1303 uint32_t result
= 0;
1305 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
1306 result
|= PP_StateClassificationFlag_Boot
;
1308 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
1309 result
|= PP_StateClassificationFlag_Thermal
;
1311 if (classification
& ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
1312 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
1314 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
1315 result
|= PP_StateClassificationFlag_Rest
;
1317 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
1318 result
|= PP_StateClassificationFlag_Forced
;
1320 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
1321 result
|= PP_StateClassificationFlag_ACPI
;
1323 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
1324 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
1329 int vega10_get_powerplay_table_entry(struct pp_hwmgr
*hwmgr
,
1330 uint32_t entry_index
, struct pp_power_state
*power_state
,
1331 int (*call_back_func
)(struct pp_hwmgr
*, void *,
1332 struct pp_power_state
*, void *, uint32_t))
1335 const ATOM_Vega10_State_Array
*state_arrays
;
1336 const ATOM_Vega10_State
*state_entry
;
1337 const ATOM_Vega10_POWERPLAYTABLE
*pp_table
=
1338 get_powerplay_table(hwmgr
);
1340 PP_ASSERT_WITH_CODE(pp_table
, "Missing PowerPlay Table!",
1342 power_state
->classification
.bios_index
= entry_index
;
1344 if (pp_table
->sHeader
.format_revision
>=
1345 ATOM_Vega10_TABLE_REVISION_VEGA10
) {
1346 state_arrays
= (ATOM_Vega10_State_Array
*)
1347 (((unsigned long)pp_table
) +
1348 le16_to_cpu(pp_table
->usStateArrayOffset
));
1350 PP_ASSERT_WITH_CODE(pp_table
->usStateArrayOffset
> 0,
1351 "Invalid PowerPlay Table State Array Offset.",
1353 PP_ASSERT_WITH_CODE(state_arrays
->ucNumEntries
> 0,
1354 "Invalid PowerPlay Table State Array.",
1356 PP_ASSERT_WITH_CODE((entry_index
<= state_arrays
->ucNumEntries
),
1357 "Invalid PowerPlay Table State Array Entry.",
1360 state_entry
= &(state_arrays
->states
[entry_index
]);
1362 result
= call_back_func(hwmgr
, (void *)state_entry
, power_state
,
1364 make_classification_flags(hwmgr
,
1365 le16_to_cpu(state_entry
->usClassification
),
1366 le16_to_cpu(state_entry
->usClassification2
)));
1369 if (!result
&& (power_state
->classification
.flags
&
1370 PP_StateClassificationFlag_Boot
))
1371 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(power_state
->hardware
));
1376 int vega10_baco_set_cap(struct pp_hwmgr
*hwmgr
)
1380 const ATOM_Vega10_POWERPLAYTABLE
*powerplay_table
;
1382 powerplay_table
= get_powerplay_table(hwmgr
);
1384 PP_ASSERT_WITH_CODE((powerplay_table
!= NULL
),
1385 "Missing PowerPlay Table!", return -1);
1387 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
1389 PP_ASSERT_WITH_CODE((result
== 0),
1390 "check_powerplay_tables failed", return result
);
1394 0 != (le32_to_cpu(powerplay_table
->ulPlatformCaps
) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO
),
1395 PHM_PlatformCaps_BACO
);