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/module.h>
25 #include <linux/slab.h>
26
27 #include "process_pptables_v1_0.h"
28 #include "ppatomctrl.h"
29 #include "atombios.h"
30 #include "hwmgr.h"
31 #include "cgs_common.h"
32 #include "pptable_v1_0.h"
33
34 /**
35 * set_hw_cap - Private Function used during initialization.
36 * @hwmgr: Pointer to the hardware manager.
37 * @setIt: A flag indication if the capability should be set (TRUE) or reset (FALSE).
38 * @cap: Which capability to set/reset.
39 */
set_hw_cap(struct pp_hwmgr * hwmgr,bool setIt,enum phm_platform_caps cap)40 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap)
41 {
42 if (setIt)
43 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
44 else
45 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
46 }
47
48
49 /**
50 * set_platform_caps - Private Function used during initialization.
51 * @hwmgr: Pointer to the hardware manager.
52 * @powerplay_caps: the bit array (from BIOS) of capability bits.
53 * Exception: the current implementation always returns 1.
54 */
set_platform_caps(struct pp_hwmgr * hwmgr,uint32_t powerplay_caps)55 static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
56 {
57 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____),
58 "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue);
59 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____),
60 "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue);
61 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____),
62 "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue);
63 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____),
64 "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue);
65 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____),
66 "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue);
67
68 set_hw_cap(
69 hwmgr,
70 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY),
71 PHM_PlatformCaps_PowerPlaySupport
72 );
73
74 set_hw_cap(
75 hwmgr,
76 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
77 PHM_PlatformCaps_BiosPowerSourceControl
78 );
79
80 set_hw_cap(
81 hwmgr,
82 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC),
83 PHM_PlatformCaps_AutomaticDCTransition
84 );
85
86 set_hw_cap(
87 hwmgr,
88 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL),
89 PHM_PlatformCaps_EnableMVDDControl
90 );
91
92 set_hw_cap(
93 hwmgr,
94 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL),
95 PHM_PlatformCaps_ControlVDDCI
96 );
97
98 set_hw_cap(
99 hwmgr,
100 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL),
101 PHM_PlatformCaps_ControlVDDGFX
102 );
103
104 set_hw_cap(
105 hwmgr,
106 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO),
107 PHM_PlatformCaps_BACO
108 );
109
110 set_hw_cap(
111 hwmgr,
112 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND),
113 PHM_PlatformCaps_DisableVoltageIsland
114 );
115
116 set_hw_cap(
117 hwmgr,
118 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
119 PHM_PlatformCaps_CombinePCCWithThermalSignal
120 );
121
122 set_hw_cap(
123 hwmgr,
124 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
125 PHM_PlatformCaps_LoadPostProductionFirmware
126 );
127
128 return 0;
129 }
130
131 /*
132 * Private Function to get the PowerPlay Table Address.
133 */
get_powerplay_table(struct pp_hwmgr * hwmgr)134 static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
135 {
136 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
137
138 u16 size;
139 u8 frev, crev;
140 void *table_address = (void *)hwmgr->soft_pp_table;
141
142 if (!table_address) {
143 table_address = (ATOM_Tonga_POWERPLAYTABLE *)
144 smu_atom_get_data_table(hwmgr->adev,
145 index, &size, &frev, &crev);
146 hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/
147 hwmgr->soft_pp_table_size = size;
148 }
149
150 return table_address;
151 }
152
get_vddc_lookup_table(struct pp_hwmgr * hwmgr,phm_ppt_v1_voltage_lookup_table ** lookup_table,const ATOM_Tonga_Voltage_Lookup_Table * vddc_lookup_pp_tables,uint32_t max_levels)153 static int get_vddc_lookup_table(
154 struct pp_hwmgr *hwmgr,
155 phm_ppt_v1_voltage_lookup_table **lookup_table,
156 const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables,
157 uint32_t max_levels
158 )
159 {
160 uint32_t i;
161 phm_ppt_v1_voltage_lookup_table *table;
162 phm_ppt_v1_voltage_lookup_record *record;
163 ATOM_Tonga_Voltage_Lookup_Record *atom_record;
164
165 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
166 "Invalid CAC Leakage PowerPlay Table!", return 1);
167
168 table = kzalloc_flex(*table, entries, max_levels);
169 if (!table)
170 return -ENOMEM;
171
172 table->count = vddc_lookup_pp_tables->ucNumEntries;
173
174 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
175 record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
176 phm_ppt_v1_voltage_lookup_record,
177 entries, table, i);
178 atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
179 ATOM_Tonga_Voltage_Lookup_Record,
180 entries, vddc_lookup_pp_tables, i);
181 record->us_calculated = 0;
182 record->us_vdd = le16_to_cpu(atom_record->usVdd);
183 record->us_cac_low = le16_to_cpu(atom_record->usCACLow);
184 record->us_cac_mid = le16_to_cpu(atom_record->usCACMid);
185 record->us_cac_high = le16_to_cpu(atom_record->usCACHigh);
186 }
187
188 *lookup_table = table;
189
190 return 0;
191 }
192
193 /**
194 * get_platform_power_management_table - Private Function used during initialization.
195 * Initialize Platform Power Management Parameter table
196 * @hwmgr: Pointer to the hardware manager.
197 * @atom_ppm_table: Pointer to PPM table in VBIOS
198 */
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_Tonga_PPM_Table * atom_ppm_table)199 static int get_platform_power_management_table(
200 struct pp_hwmgr *hwmgr,
201 ATOM_Tonga_PPM_Table *atom_ppm_table)
202 {
203 struct phm_ppm_table *ptr = kzalloc_obj(*ptr);
204 struct phm_ppt_v1_information *pp_table_information =
205 (struct phm_ppt_v1_information *)(hwmgr->pptable);
206
207 if (NULL == ptr)
208 return -ENOMEM;
209
210 ptr->ppm_design
211 = atom_ppm_table->ucPpmDesign;
212 ptr->cpu_core_number
213 = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
214 ptr->platform_tdp
215 = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
216 ptr->small_ac_platform_tdp
217 = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
218 ptr->platform_tdc
219 = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
220 ptr->small_ac_platform_tdc
221 = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
222 ptr->apu_tdp
223 = le32_to_cpu(atom_ppm_table->ulApuTDP);
224 ptr->dgpu_tdp
225 = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
226 ptr->dgpu_ulv_power
227 = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
228 ptr->tj_max
229 = le32_to_cpu(atom_ppm_table->ulTjmax);
230
231 pp_table_information->ppm_parameter_table = ptr;
232
233 return 0;
234 }
235
236 /**
237 * init_dpm_2_parameters - Private Function used during initialization.
238 * Initialize TDP limits for DPM2
239 * @hwmgr: Pointer to the hardware manager.
240 * @powerplay_table: Pointer to the PowerPlay Table.
241 */
init_dpm_2_parameters(struct pp_hwmgr * hwmgr,const ATOM_Tonga_POWERPLAYTABLE * powerplay_table)242 static int init_dpm_2_parameters(
243 struct pp_hwmgr *hwmgr,
244 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
245 )
246 {
247 int result = 0;
248 struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
249 ATOM_Tonga_PPM_Table *atom_ppm_table;
250 uint32_t disable_ppm = 0;
251 uint32_t disable_power_control = 0;
252
253 pp_table_information->us_ulv_voltage_offset =
254 le16_to_cpu(powerplay_table->usUlvVoltageOffset);
255
256 pp_table_information->ppm_parameter_table = NULL;
257 pp_table_information->vddc_lookup_table = NULL;
258 pp_table_information->vddgfx_lookup_table = NULL;
259 /* TDP limits */
260 hwmgr->platform_descriptor.TDPODLimit =
261 le16_to_cpu(powerplay_table->usPowerControlLimit);
262 hwmgr->platform_descriptor.TDPAdjustment = 0;
263 hwmgr->platform_descriptor.VidAdjustment = 0;
264 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
265 hwmgr->platform_descriptor.VidMinLimit = 0;
266 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
267 hwmgr->platform_descriptor.VidStep = 6250;
268
269 disable_power_control = 0;
270 if (0 == disable_power_control) {
271 /* enable TDP overdrive (PowerControl) feature as well if supported */
272 if (hwmgr->platform_descriptor.TDPODLimit != 0)
273 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
274 PHM_PlatformCaps_PowerControl);
275 }
276
277 if (0 != powerplay_table->usVddcLookupTableOffset) {
278 const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
279 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
280 le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
281
282 result = get_vddc_lookup_table(hwmgr,
283 &pp_table_information->vddc_lookup_table, pVddcCACTable, 16);
284 }
285
286 if (0 != powerplay_table->usVddgfxLookupTableOffset) {
287 const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
288 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
289 le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
290
291 result = get_vddc_lookup_table(hwmgr,
292 &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16);
293 }
294
295 disable_ppm = 0;
296 if (0 == disable_ppm) {
297 atom_ppm_table = (ATOM_Tonga_PPM_Table *)
298 (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
299
300 if (0 != powerplay_table->usPPMTableOffset) {
301 if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) {
302 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
303 PHM_PlatformCaps_EnablePlatformPowerManagement);
304 }
305 }
306 }
307
308 return result;
309 }
310
get_valid_clk(struct pp_hwmgr * hwmgr,struct phm_clock_array ** clk_table,phm_ppt_v1_clock_voltage_dependency_table const * clk_volt_pp_table)311 static int get_valid_clk(
312 struct pp_hwmgr *hwmgr,
313 struct phm_clock_array **clk_table,
314 phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table
315 )
316 {
317 uint32_t i;
318 struct phm_clock_array *table;
319 phm_ppt_v1_clock_voltage_dependency_record *dep_record;
320
321 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count),
322 "Invalid PowerPlay Table!", return -1);
323
324 table = kzalloc_flex(*table, values, clk_volt_pp_table->count);
325 if (!table)
326 return -ENOMEM;
327
328 table->count = (uint32_t)clk_volt_pp_table->count;
329
330 for (i = 0; i < table->count; i++) {
331 dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
332 phm_ppt_v1_clock_voltage_dependency_record,
333 entries, clk_volt_pp_table, i);
334 table->values[i] = (uint32_t)dep_record->clk;
335 }
336 *clk_table = table;
337
338 return 0;
339 }
340
get_hard_limits(struct pp_hwmgr * hwmgr,struct phm_clock_and_voltage_limits * limits,ATOM_Tonga_Hard_Limit_Table const * limitable)341 static int get_hard_limits(
342 struct pp_hwmgr *hwmgr,
343 struct phm_clock_and_voltage_limits *limits,
344 ATOM_Tonga_Hard_Limit_Table const *limitable
345 )
346 {
347 PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1);
348
349 /* currently we always take entries[0] parameters */
350 limits->sclk = le32_to_cpu(limitable->entries[0].ulSCLKLimit);
351 limits->mclk = le32_to_cpu(limitable->entries[0].ulMCLKLimit);
352 limits->vddc = le16_to_cpu(limitable->entries[0].usVddcLimit);
353 limits->vddci = le16_to_cpu(limitable->entries[0].usVddciLimit);
354 limits->vddgfx = le16_to_cpu(limitable->entries[0].usVddgfxLimit);
355
356 return 0;
357 }
358
get_mclk_voltage_dependency_table(struct pp_hwmgr * hwmgr,phm_ppt_v1_clock_voltage_dependency_table ** pp_tonga_mclk_dep_table,ATOM_Tonga_MCLK_Dependency_Table const * mclk_dep_table)359 static int get_mclk_voltage_dependency_table(
360 struct pp_hwmgr *hwmgr,
361 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table,
362 ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table
363 )
364 {
365 uint32_t i;
366 phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
367 phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record;
368 ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
369
370 PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
371 "Invalid PowerPlay Table!", return -1);
372
373 mclk_table = kzalloc_flex(*mclk_table, entries,
374 mclk_dep_table->ucNumEntries);
375 if (!mclk_table)
376 return -ENOMEM;
377
378 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
379
380 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
381 mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
382 phm_ppt_v1_clock_voltage_dependency_record,
383 entries, mclk_table, i);
384 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
385 ATOM_Tonga_MCLK_Dependency_Record,
386 entries, mclk_dep_table, i);
387 mclk_table_record->vddInd = mclk_dep_record->ucVddcInd;
388 mclk_table_record->vdd_offset = le16_to_cpu(mclk_dep_record->usVddgfxOffset);
389 mclk_table_record->vddci = le16_to_cpu(mclk_dep_record->usVddci);
390 mclk_table_record->mvdd = le16_to_cpu(mclk_dep_record->usMvdd);
391 mclk_table_record->clk = le32_to_cpu(mclk_dep_record->ulMclk);
392 }
393
394 *pp_tonga_mclk_dep_table = mclk_table;
395
396 return 0;
397 }
398
get_sclk_voltage_dependency_table(struct pp_hwmgr * hwmgr,phm_ppt_v1_clock_voltage_dependency_table ** pp_tonga_sclk_dep_table,PPTable_Generic_SubTable_Header const * sclk_dep_table)399 static int get_sclk_voltage_dependency_table(
400 struct pp_hwmgr *hwmgr,
401 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
402 PPTable_Generic_SubTable_Header const *sclk_dep_table
403 )
404 {
405 uint32_t i;
406 phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
407 phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record;
408
409 if (sclk_dep_table->ucRevId < 1) {
410 const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
411 (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
412 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
413
414 PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
415 "Invalid PowerPlay Table!", return -1);
416
417 sclk_table = kzalloc_flex(*sclk_table, entries,
418 tonga_table->ucNumEntries);
419 if (!sclk_table)
420 return -ENOMEM;
421
422 sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
423
424 for (i = 0; i < tonga_table->ucNumEntries; i++) {
425 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
426 ATOM_Tonga_SCLK_Dependency_Record,
427 entries, tonga_table, i);
428 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
429 phm_ppt_v1_clock_voltage_dependency_record,
430 entries, sclk_table, i);
431 sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
432 sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
433 sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
434 sclk_table_record->cks_enable =
435 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
436 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
437 }
438 } else {
439 const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
440 (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
441 ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record;
442
443 PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
444 "Invalid PowerPlay Table!", return -1);
445
446 sclk_table = kzalloc_flex(*sclk_table, entries,
447 polaris_table->ucNumEntries);
448 if (!sclk_table)
449 return -ENOMEM;
450
451 sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
452
453 for (i = 0; i < polaris_table->ucNumEntries; i++) {
454 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
455 ATOM_Polaris_SCLK_Dependency_Record,
456 entries, polaris_table, i);
457 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
458 phm_ppt_v1_clock_voltage_dependency_record,
459 entries, sclk_table, i);
460 sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
461 sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
462 sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
463 sclk_table_record->cks_enable =
464 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
465 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
466 sclk_table_record->sclk_offset = le32_to_cpu(sclk_dep_record->ulSclkOffset);
467 }
468 }
469 *pp_tonga_sclk_dep_table = sclk_table;
470
471 return 0;
472 }
473
get_pcie_table(struct pp_hwmgr * hwmgr,phm_ppt_v1_pcie_table ** pp_tonga_pcie_table,PPTable_Generic_SubTable_Header const * ptable)474 static int get_pcie_table(
475 struct pp_hwmgr *hwmgr,
476 phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
477 PPTable_Generic_SubTable_Header const *ptable
478 )
479 {
480 uint32_t i, pcie_count;
481 phm_ppt_v1_pcie_table *pcie_table;
482 struct phm_ppt_v1_information *pp_table_information =
483 (struct phm_ppt_v1_information *)(hwmgr->pptable);
484 phm_ppt_v1_pcie_record *pcie_record;
485
486 if (ptable->ucRevId < 1) {
487 const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable;
488 ATOM_Tonga_PCIE_Record *atom_pcie_record;
489
490 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
491 "Invalid PowerPlay Table!", return -1);
492
493 pcie_table = kzalloc_flex(*pcie_table, entries,
494 atom_pcie_table->ucNumEntries);
495 if (!pcie_table)
496 return -ENOMEM;
497
498 /*
499 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
500 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
501 */
502 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
503 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
504 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
505 else
506 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
507
508 pcie_table->count = pcie_count;
509 for (i = 0; i < pcie_count; i++) {
510 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
511 phm_ppt_v1_pcie_record,
512 entries, pcie_table, i);
513 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
514 ATOM_Tonga_PCIE_Record,
515 entries, atom_pcie_table, i);
516 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
517 pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
518 }
519
520 *pp_tonga_pcie_table = pcie_table;
521 } else {
522 /* Polaris10/Polaris11 and newer. */
523 const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable;
524 ATOM_Polaris10_PCIE_Record *atom_pcie_record;
525
526 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
527 "Invalid PowerPlay Table!", return -1);
528
529 pcie_table = kzalloc_flex(*pcie_table, entries,
530 atom_pcie_table->ucNumEntries);
531 if (!pcie_table)
532 return -ENOMEM;
533
534 /*
535 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
536 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
537 */
538 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
539 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
540 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
541 else
542 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
543
544 pcie_table->count = pcie_count;
545
546 for (i = 0; i < pcie_count; i++) {
547 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
548 phm_ppt_v1_pcie_record,
549 entries, pcie_table, i);
550 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
551 ATOM_Polaris10_PCIE_Record,
552 entries, atom_pcie_table, i);
553 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
554 pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
555 pcie_record->pcie_sclk = le32_to_cpu(atom_pcie_record->ulPCIE_Sclk);
556 }
557
558 *pp_tonga_pcie_table = pcie_table;
559 }
560
561 return 0;
562 }
563
get_cac_tdp_table(struct pp_hwmgr * hwmgr,struct phm_cac_tdp_table ** cac_tdp_table,const PPTable_Generic_SubTable_Header * table)564 static int get_cac_tdp_table(
565 struct pp_hwmgr *hwmgr,
566 struct phm_cac_tdp_table **cac_tdp_table,
567 const PPTable_Generic_SubTable_Header * table
568 )
569 {
570 uint32_t table_size;
571 struct phm_cac_tdp_table *tdp_table;
572
573 table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
574 tdp_table = kzalloc(table_size, GFP_KERNEL);
575
576 if (NULL == tdp_table)
577 return -ENOMEM;
578
579 hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
580
581 if (NULL == hwmgr->dyn_state.cac_dtp_table) {
582 kfree(tdp_table);
583 return -ENOMEM;
584 }
585
586 if (table->ucRevId < 3) {
587 const ATOM_Tonga_PowerTune_Table *tonga_table =
588 (ATOM_Tonga_PowerTune_Table *)table;
589 tdp_table->usTDP = le16_to_cpu(tonga_table->usTDP);
590 tdp_table->usConfigurableTDP =
591 le16_to_cpu(tonga_table->usConfigurableTDP);
592 tdp_table->usTDC = le16_to_cpu(tonga_table->usTDC);
593 tdp_table->usBatteryPowerLimit =
594 le16_to_cpu(tonga_table->usBatteryPowerLimit);
595 tdp_table->usSmallPowerLimit =
596 le16_to_cpu(tonga_table->usSmallPowerLimit);
597 tdp_table->usLowCACLeakage =
598 le16_to_cpu(tonga_table->usLowCACLeakage);
599 tdp_table->usHighCACLeakage =
600 le16_to_cpu(tonga_table->usHighCACLeakage);
601 tdp_table->usMaximumPowerDeliveryLimit =
602 le16_to_cpu(tonga_table->usMaximumPowerDeliveryLimit);
603 tdp_table->usDefaultTargetOperatingTemp =
604 le16_to_cpu(tonga_table->usTjMax);
605 tdp_table->usTargetOperatingTemp =
606 le16_to_cpu(tonga_table->usTjMax); /*Set the initial temp to the same as default */
607 tdp_table->usPowerTuneDataSetID =
608 le16_to_cpu(tonga_table->usPowerTuneDataSetID);
609 tdp_table->usSoftwareShutdownTemp =
610 le16_to_cpu(tonga_table->usSoftwareShutdownTemp);
611 tdp_table->usClockStretchAmount =
612 le16_to_cpu(tonga_table->usClockStretchAmount);
613 } else if (table->ucRevId < 4) { /* Fiji and newer */
614 const ATOM_Fiji_PowerTune_Table *fijitable =
615 (ATOM_Fiji_PowerTune_Table *)table;
616 tdp_table->usTDP = le16_to_cpu(fijitable->usTDP);
617 tdp_table->usConfigurableTDP = le16_to_cpu(fijitable->usConfigurableTDP);
618 tdp_table->usTDC = le16_to_cpu(fijitable->usTDC);
619 tdp_table->usBatteryPowerLimit = le16_to_cpu(fijitable->usBatteryPowerLimit);
620 tdp_table->usSmallPowerLimit = le16_to_cpu(fijitable->usSmallPowerLimit);
621 tdp_table->usLowCACLeakage = le16_to_cpu(fijitable->usLowCACLeakage);
622 tdp_table->usHighCACLeakage = le16_to_cpu(fijitable->usHighCACLeakage);
623 tdp_table->usMaximumPowerDeliveryLimit =
624 le16_to_cpu(fijitable->usMaximumPowerDeliveryLimit);
625 tdp_table->usDefaultTargetOperatingTemp =
626 le16_to_cpu(fijitable->usTjMax);
627 tdp_table->usTargetOperatingTemp =
628 le16_to_cpu(fijitable->usTjMax); /*Set the initial temp to the same as default */
629 tdp_table->usPowerTuneDataSetID =
630 le16_to_cpu(fijitable->usPowerTuneDataSetID);
631 tdp_table->usSoftwareShutdownTemp =
632 le16_to_cpu(fijitable->usSoftwareShutdownTemp);
633 tdp_table->usClockStretchAmount =
634 le16_to_cpu(fijitable->usClockStretchAmount);
635 tdp_table->usTemperatureLimitHotspot =
636 le16_to_cpu(fijitable->usTemperatureLimitHotspot);
637 tdp_table->usTemperatureLimitLiquid1 =
638 le16_to_cpu(fijitable->usTemperatureLimitLiquid1);
639 tdp_table->usTemperatureLimitLiquid2 =
640 le16_to_cpu(fijitable->usTemperatureLimitLiquid2);
641 tdp_table->usTemperatureLimitVrVddc =
642 le16_to_cpu(fijitable->usTemperatureLimitVrVddc);
643 tdp_table->usTemperatureLimitVrMvdd =
644 le16_to_cpu(fijitable->usTemperatureLimitVrMvdd);
645 tdp_table->usTemperatureLimitPlx =
646 le16_to_cpu(fijitable->usTemperatureLimitPlx);
647 tdp_table->ucLiquid1_I2C_address =
648 fijitable->ucLiquid1_I2C_address;
649 tdp_table->ucLiquid2_I2C_address =
650 fijitable->ucLiquid2_I2C_address;
651 tdp_table->ucLiquid_I2C_Line =
652 fijitable->ucLiquid_I2C_Line;
653 tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address;
654 tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line;
655 tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address;
656 tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line;
657 } else {
658 const ATOM_Polaris_PowerTune_Table *polaristable =
659 (ATOM_Polaris_PowerTune_Table *)table;
660 tdp_table->usTDP = le16_to_cpu(polaristable->usTDP);
661 tdp_table->usConfigurableTDP = le16_to_cpu(polaristable->usConfigurableTDP);
662 tdp_table->usTDC = le16_to_cpu(polaristable->usTDC);
663 tdp_table->usBatteryPowerLimit = le16_to_cpu(polaristable->usBatteryPowerLimit);
664 tdp_table->usSmallPowerLimit = le16_to_cpu(polaristable->usSmallPowerLimit);
665 tdp_table->usLowCACLeakage = le16_to_cpu(polaristable->usLowCACLeakage);
666 tdp_table->usHighCACLeakage = le16_to_cpu(polaristable->usHighCACLeakage);
667 tdp_table->usMaximumPowerDeliveryLimit =
668 le16_to_cpu(polaristable->usMaximumPowerDeliveryLimit);
669 tdp_table->usDefaultTargetOperatingTemp =
670 le16_to_cpu(polaristable->usTjMax);
671 tdp_table->usTargetOperatingTemp =
672 le16_to_cpu(polaristable->usTjMax); /*Set the initial temp to the same as default */
673 tdp_table->usPowerTuneDataSetID =
674 le16_to_cpu(polaristable->usPowerTuneDataSetID);
675 tdp_table->usSoftwareShutdownTemp =
676 le16_to_cpu(polaristable->usSoftwareShutdownTemp);
677 tdp_table->usClockStretchAmount =
678 le16_to_cpu(polaristable->usClockStretchAmount);
679 tdp_table->usTemperatureLimitHotspot =
680 le16_to_cpu(polaristable->usTemperatureLimitHotspot);
681 tdp_table->usTemperatureLimitLiquid1 =
682 le16_to_cpu(polaristable->usTemperatureLimitLiquid1);
683 tdp_table->usTemperatureLimitLiquid2 =
684 le16_to_cpu(polaristable->usTemperatureLimitLiquid2);
685 tdp_table->usTemperatureLimitVrVddc =
686 le16_to_cpu(polaristable->usTemperatureLimitVrVddc);
687 tdp_table->usTemperatureLimitVrMvdd =
688 le16_to_cpu(polaristable->usTemperatureLimitVrMvdd);
689 tdp_table->usTemperatureLimitPlx =
690 le16_to_cpu(polaristable->usTemperatureLimitPlx);
691 tdp_table->ucLiquid1_I2C_address =
692 polaristable->ucLiquid1_I2C_address;
693 tdp_table->ucLiquid2_I2C_address =
694 polaristable->ucLiquid2_I2C_address;
695 tdp_table->ucLiquid_I2C_Line =
696 polaristable->ucLiquid_I2C_Line;
697 tdp_table->ucVr_I2C_address = polaristable->ucVr_I2C_address;
698 tdp_table->ucVr_I2C_Line = polaristable->ucVr_I2C_Line;
699 tdp_table->ucPlx_I2C_address = polaristable->ucPlx_I2C_address;
700 tdp_table->ucPlx_I2C_Line = polaristable->ucPlx_I2C_Line;
701 tdp_table->usBoostPowerLimit = polaristable->usBoostPowerLimit;
702 tdp_table->ucCKS_LDO_REFSEL = polaristable->ucCKS_LDO_REFSEL;
703 tdp_table->ucHotSpotOnly = polaristable->ucHotSpotOnly;
704 }
705
706 *cac_tdp_table = tdp_table;
707
708 return 0;
709 }
710
get_mm_clock_voltage_table(struct pp_hwmgr * hwmgr,phm_ppt_v1_mm_clock_voltage_dependency_table ** tonga_mm_table,const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table)711 static int get_mm_clock_voltage_table(
712 struct pp_hwmgr *hwmgr,
713 phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table,
714 const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table
715 )
716 {
717 uint32_t i;
718 const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
719 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
720 phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record;
721
722 PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
723 "Invalid PowerPlay Table!", return -1);
724 mm_table = kzalloc_flex(*mm_table, entries,
725 mm_dependency_table->ucNumEntries);
726 if (!mm_table)
727 return -ENOMEM;
728
729 mm_table->count = mm_dependency_table->ucNumEntries;
730
731 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
732 mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
733 ATOM_Tonga_MM_Dependency_Record,
734 entries, mm_dependency_table, i);
735 mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
736 phm_ppt_v1_mm_clock_voltage_dependency_record,
737 entries, mm_table, i);
738 mm_table_record->vddcInd = mm_dependency_record->ucVddcInd;
739 mm_table_record->vddgfx_offset = le16_to_cpu(mm_dependency_record->usVddgfxOffset);
740 mm_table_record->aclk = le32_to_cpu(mm_dependency_record->ulAClk);
741 mm_table_record->samclock = le32_to_cpu(mm_dependency_record->ulSAMUClk);
742 mm_table_record->eclk = le32_to_cpu(mm_dependency_record->ulEClk);
743 mm_table_record->vclk = le32_to_cpu(mm_dependency_record->ulVClk);
744 mm_table_record->dclk = le32_to_cpu(mm_dependency_record->ulDClk);
745 }
746
747 *tonga_mm_table = mm_table;
748
749 return 0;
750 }
751
get_gpio_table(struct pp_hwmgr * hwmgr,struct phm_ppt_v1_gpio_table ** pp_tonga_gpio_table,const ATOM_Tonga_GPIO_Table * atom_gpio_table)752 static int get_gpio_table(struct pp_hwmgr *hwmgr,
753 struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table,
754 const ATOM_Tonga_GPIO_Table *atom_gpio_table)
755 {
756 uint32_t table_size;
757 struct phm_ppt_v1_gpio_table *pp_gpio_table;
758 struct phm_ppt_v1_information *pp_table_information =
759 (struct phm_ppt_v1_information *)(hwmgr->pptable);
760
761 table_size = sizeof(struct phm_ppt_v1_gpio_table);
762 pp_gpio_table = kzalloc(table_size, GFP_KERNEL);
763 if (!pp_gpio_table)
764 return -ENOMEM;
765
766 if (pp_table_information->vdd_dep_on_sclk->count <
767 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex)
768 PP_ASSERT_WITH_CODE(false,
769 "SCLK DPM index for VRHot cannot exceed the total sclk level count!",);
770 else
771 pp_gpio_table->vrhot_triggered_sclk_dpm_index =
772 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex;
773
774 *pp_tonga_gpio_table = pp_gpio_table;
775
776 return 0;
777 }
778 /**
779 * init_clock_voltage_dependency - Private Function used during initialization.
780 * Initialize clock voltage dependency
781 * @hwmgr: Pointer to the hardware manager.
782 * @powerplay_table: Pointer to the PowerPlay Table.
783 */
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_Tonga_POWERPLAYTABLE * powerplay_table)784 static int init_clock_voltage_dependency(
785 struct pp_hwmgr *hwmgr,
786 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
787 )
788 {
789 int result = 0;
790 struct phm_ppt_v1_information *pp_table_information =
791 (struct phm_ppt_v1_information *)(hwmgr->pptable);
792
793 const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
794 (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) +
795 le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
796 const PPTable_Generic_SubTable_Header *pPowerTuneTable =
797 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
798 le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
799 const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
800 (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
801 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
802 const PPTable_Generic_SubTable_Header *sclk_dep_table =
803 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
804 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
805 const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
806 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
807 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
808 const PPTable_Generic_SubTable_Header *pcie_table =
809 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
810 le16_to_cpu(powerplay_table->usPCIETableOffset));
811 const ATOM_Tonga_GPIO_Table *gpio_table =
812 (const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) +
813 le16_to_cpu(powerplay_table->usGPIOTableOffset));
814
815 pp_table_information->vdd_dep_on_sclk = NULL;
816 pp_table_information->vdd_dep_on_mclk = NULL;
817 pp_table_information->mm_dep_table = NULL;
818 pp_table_information->pcie_table = NULL;
819 pp_table_information->gpio_table = NULL;
820
821 if (powerplay_table->usMMDependencyTableOffset != 0)
822 result = get_mm_clock_voltage_table(hwmgr,
823 &pp_table_information->mm_dep_table, mm_dependency_table);
824
825 if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
826 result = get_cac_tdp_table(hwmgr,
827 &pp_table_information->cac_dtp_table, pPowerTuneTable);
828
829 if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
830 result = get_sclk_voltage_dependency_table(hwmgr,
831 &pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
832
833 if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
834 result = get_mclk_voltage_dependency_table(hwmgr,
835 &pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
836
837 if (result == 0 && powerplay_table->usPCIETableOffset != 0)
838 result = get_pcie_table(hwmgr,
839 &pp_table_information->pcie_table, pcie_table);
840
841 if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
842 result = get_hard_limits(hwmgr,
843 &pp_table_information->max_clock_voltage_on_dc, pHardLimits);
844
845 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
846 pp_table_information->max_clock_voltage_on_dc.sclk;
847 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
848 pp_table_information->max_clock_voltage_on_dc.mclk;
849 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
850 pp_table_information->max_clock_voltage_on_dc.vddc;
851 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
852 pp_table_information->max_clock_voltage_on_dc.vddci;
853
854 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk)
855 && (0 != pp_table_information->vdd_dep_on_mclk->count))
856 result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values,
857 pp_table_information->vdd_dep_on_mclk);
858
859 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk)
860 && (0 != pp_table_information->vdd_dep_on_sclk->count))
861 result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values,
862 pp_table_information->vdd_dep_on_sclk);
863
864 if (!result && gpio_table)
865 result = get_gpio_table(hwmgr, &pp_table_information->gpio_table,
866 gpio_table);
867
868 return result;
869 }
870
871 /**
872 * init_over_drive_limits - Retrieves the (signed) Overdrive limits from VBIOS.
873 * The max engine clock, memory clock and max temperature come from the firmware info table.
874 *
875 * The information is placed into the platform descriptor.
876 *
877 * @hwmgr: source of the VBIOS table and owner of the platform descriptor to be updated.
878 * @powerplay_table: the address of the PowerPlay table.
879 *
880 * Return: 1 as long as the firmware info table was present and of a supported version.
881 */
init_over_drive_limits(struct pp_hwmgr * hwmgr,const ATOM_Tonga_POWERPLAYTABLE * powerplay_table)882 static int init_over_drive_limits(
883 struct pp_hwmgr *hwmgr,
884 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
885 {
886 hwmgr->platform_descriptor.overdriveLimit.engineClock =
887 le32_to_cpu(powerplay_table->ulMaxODEngineClock);
888 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
889 le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
890
891 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
892 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
893 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
894
895 return 0;
896 }
897
898 /**
899 * init_thermal_controller - Private Function used during initialization.
900 * Inspect the PowerPlay table for obvious signs of corruption.
901 * @hwmgr: Pointer to the hardware manager.
902 * @powerplay_table: Pointer to the PowerPlay Table.
903 * Exception: This implementation always returns 1.
904 */
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_Tonga_POWERPLAYTABLE * powerplay_table)905 static int init_thermal_controller(
906 struct pp_hwmgr *hwmgr,
907 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
908 )
909 {
910 const PPTable_Generic_SubTable_Header *fan_table;
911 ATOM_Tonga_Thermal_Controller *thermal_controller;
912
913 thermal_controller = (ATOM_Tonga_Thermal_Controller *)
914 (((unsigned long)powerplay_table) +
915 le16_to_cpu(powerplay_table->usThermalControllerOffset));
916 PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset),
917 "Thermal controller table not set!", return -1);
918
919 hwmgr->thermal_controller.ucType = thermal_controller->ucType;
920 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
921 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
922
923 hwmgr->thermal_controller.fanInfo.bNoFan =
924 (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN));
925
926 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
927 thermal_controller->ucFanParameters &
928 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
929
930 hwmgr->thermal_controller.fanInfo.ulMinRPM
931 = thermal_controller->ucFanMinRPM * 100UL;
932 hwmgr->thermal_controller.fanInfo.ulMaxRPM
933 = thermal_controller->ucFanMaxRPM * 100UL;
934
935 set_hw_cap(
936 hwmgr,
937 ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
938 PHM_PlatformCaps_ThermalController
939 );
940
941 if (0 == powerplay_table->usFanTableOffset) {
942 hwmgr->thermal_controller.use_hw_fan_control = 1;
943 return 0;
944 }
945
946 fan_table = (const PPTable_Generic_SubTable_Header *)
947 (((unsigned long)powerplay_table) +
948 le16_to_cpu(powerplay_table->usFanTableOffset));
949
950 PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
951 "Fan table not set!", return -1);
952 PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
953 "Unsupported fan table format!", return -1);
954
955 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
956 = 100000;
957 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
958 PHM_PlatformCaps_MicrocodeFanControl);
959
960 if (fan_table->ucRevId < 8) {
961 const ATOM_Tonga_Fan_Table *tonga_fan_table =
962 (ATOM_Tonga_Fan_Table *)fan_table;
963 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
964 = tonga_fan_table->ucTHyst;
965 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
966 = le16_to_cpu(tonga_fan_table->usTMin);
967 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
968 = le16_to_cpu(tonga_fan_table->usTMed);
969 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
970 = le16_to_cpu(tonga_fan_table->usTHigh);
971 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
972 = le16_to_cpu(tonga_fan_table->usPWMMin);
973 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
974 = le16_to_cpu(tonga_fan_table->usPWMMed);
975 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
976 = le16_to_cpu(tonga_fan_table->usPWMHigh);
977 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
978 = le16_to_cpu(tonga_fan_table->usTMax);
979 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
980 = tonga_fan_table->ucFanControlMode;
981 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
982 = le16_to_cpu(tonga_fan_table->usFanPWMMax);
983 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
984 = 4836;
985 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
986 = le16_to_cpu(tonga_fan_table->usFanOutputSensitivity);
987 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
988 = le16_to_cpu(tonga_fan_table->usFanRPMMax);
989 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
990 = (le32_to_cpu(tonga_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
991 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
992 = tonga_fan_table->ucTargetTemperature;
993 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
994 = tonga_fan_table->ucMinimumPWMLimit;
995 } else if (fan_table->ucRevId == 8) {
996 const ATOM_Fiji_Fan_Table *fiji_fan_table =
997 (ATOM_Fiji_Fan_Table *)fan_table;
998 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
999 = fiji_fan_table->ucTHyst;
1000 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
1001 = le16_to_cpu(fiji_fan_table->usTMin);
1002 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
1003 = le16_to_cpu(fiji_fan_table->usTMed);
1004 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
1005 = le16_to_cpu(fiji_fan_table->usTHigh);
1006 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
1007 = le16_to_cpu(fiji_fan_table->usPWMMin);
1008 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
1009 = le16_to_cpu(fiji_fan_table->usPWMMed);
1010 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
1011 = le16_to_cpu(fiji_fan_table->usPWMHigh);
1012 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
1013 = le16_to_cpu(fiji_fan_table->usTMax);
1014 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
1015 = fiji_fan_table->ucFanControlMode;
1016 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
1017 = le16_to_cpu(fiji_fan_table->usFanPWMMax);
1018 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
1019 = 4836;
1020 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
1021 = le16_to_cpu(fiji_fan_table->usFanOutputSensitivity);
1022 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
1023 = le16_to_cpu(fiji_fan_table->usFanRPMMax);
1024 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
1025 = (le32_to_cpu(fiji_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
1026 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
1027 = fiji_fan_table->ucTargetTemperature;
1028 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
1029 = fiji_fan_table->ucMinimumPWMLimit;
1030
1031 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
1032 = le16_to_cpu(fiji_fan_table->usFanGainEdge);
1033 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
1034 = le16_to_cpu(fiji_fan_table->usFanGainHotspot);
1035 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
1036 = le16_to_cpu(fiji_fan_table->usFanGainLiquid);
1037 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
1038 = le16_to_cpu(fiji_fan_table->usFanGainVrVddc);
1039 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
1040 = le16_to_cpu(fiji_fan_table->usFanGainVrMvdd);
1041 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
1042 = le16_to_cpu(fiji_fan_table->usFanGainPlx);
1043 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
1044 = le16_to_cpu(fiji_fan_table->usFanGainHbm);
1045 } else if (fan_table->ucRevId >= 9) {
1046 const ATOM_Polaris_Fan_Table *polaris_fan_table =
1047 (ATOM_Polaris_Fan_Table *)fan_table;
1048 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
1049 = polaris_fan_table->ucTHyst;
1050 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
1051 = le16_to_cpu(polaris_fan_table->usTMin);
1052 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
1053 = le16_to_cpu(polaris_fan_table->usTMed);
1054 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
1055 = le16_to_cpu(polaris_fan_table->usTHigh);
1056 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
1057 = le16_to_cpu(polaris_fan_table->usPWMMin);
1058 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
1059 = le16_to_cpu(polaris_fan_table->usPWMMed);
1060 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
1061 = le16_to_cpu(polaris_fan_table->usPWMHigh);
1062 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
1063 = le16_to_cpu(polaris_fan_table->usTMax);
1064 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
1065 = polaris_fan_table->ucFanControlMode;
1066 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
1067 = le16_to_cpu(polaris_fan_table->usFanPWMMax);
1068 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
1069 = 4836;
1070 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
1071 = le16_to_cpu(polaris_fan_table->usFanOutputSensitivity);
1072 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
1073 = le16_to_cpu(polaris_fan_table->usFanRPMMax);
1074 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
1075 = (le32_to_cpu(polaris_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
1076 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
1077 = polaris_fan_table->ucTargetTemperature;
1078 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
1079 = polaris_fan_table->ucMinimumPWMLimit;
1080
1081 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
1082 = le16_to_cpu(polaris_fan_table->usFanGainEdge);
1083 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
1084 = le16_to_cpu(polaris_fan_table->usFanGainHotspot);
1085 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
1086 = le16_to_cpu(polaris_fan_table->usFanGainLiquid);
1087 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
1088 = le16_to_cpu(polaris_fan_table->usFanGainVrVddc);
1089 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
1090 = le16_to_cpu(polaris_fan_table->usFanGainVrMvdd);
1091 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
1092 = le16_to_cpu(polaris_fan_table->usFanGainPlx);
1093 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
1094 = le16_to_cpu(polaris_fan_table->usFanGainHbm);
1095 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM
1096 = le16_to_cpu(polaris_fan_table->ucEnableZeroRPM);
1097 hwmgr->thermal_controller.advanceFanControlParameters.ucFanStopTemperature
1098 = le16_to_cpu(polaris_fan_table->ucFanStopTemperature);
1099 hwmgr->thermal_controller.advanceFanControlParameters.ucFanStartTemperature
1100 = le16_to_cpu(polaris_fan_table->ucFanStartTemperature);
1101 }
1102
1103 return 0;
1104 }
1105
1106 /**
1107 * check_powerplay_tables - Private Function used during initialization.
1108 * Inspect the PowerPlay table for obvious signs of corruption.
1109 * @hwmgr: Pointer to the hardware manager.
1110 * @powerplay_table: Pointer to the PowerPlay Table.
1111 * Exception: 2 if the powerplay table is incorrect.
1112 */
check_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_Tonga_POWERPLAYTABLE * powerplay_table)1113 static int check_powerplay_tables(
1114 struct pp_hwmgr *hwmgr,
1115 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
1116 )
1117 {
1118 const ATOM_Tonga_State_Array *state_arrays;
1119
1120 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) +
1121 le16_to_cpu(powerplay_table->usStateArrayOffset));
1122
1123 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <=
1124 powerplay_table->sHeader.ucTableFormatRevision),
1125 "Unsupported PPTable format!", return -1);
1126 PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset),
1127 "State table is not set!", return -1);
1128 PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize),
1129 "Invalid PowerPlay Table!", return -1);
1130 PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
1131 "Invalid PowerPlay Table!", return -1);
1132
1133 return 0;
1134 }
1135
pp_tables_v1_0_initialize(struct pp_hwmgr * hwmgr)1136 static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
1137 {
1138 int result = 0;
1139 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
1140
1141 hwmgr->pptable = kzalloc_obj(struct phm_ppt_v1_information);
1142
1143 PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
1144 "Failed to allocate hwmgr->pptable!", return -ENOMEM);
1145
1146 powerplay_table = get_powerplay_table(hwmgr);
1147
1148 PP_ASSERT_WITH_CODE((NULL != powerplay_table),
1149 "Missing PowerPlay Table!", return -1);
1150
1151 result = check_powerplay_tables(hwmgr, powerplay_table);
1152
1153 PP_ASSERT_WITH_CODE((result == 0),
1154 "check_powerplay_tables failed", return result);
1155
1156 result = set_platform_caps(hwmgr,
1157 le32_to_cpu(powerplay_table->ulPlatformCaps));
1158
1159 PP_ASSERT_WITH_CODE((result == 0),
1160 "set_platform_caps failed", return result);
1161
1162 result = init_thermal_controller(hwmgr, powerplay_table);
1163
1164 PP_ASSERT_WITH_CODE((result == 0),
1165 "init_thermal_controller failed", return result);
1166
1167 result = init_over_drive_limits(hwmgr, powerplay_table);
1168
1169 PP_ASSERT_WITH_CODE((result == 0),
1170 "init_over_drive_limits failed", return result);
1171
1172 result = init_clock_voltage_dependency(hwmgr, powerplay_table);
1173
1174 PP_ASSERT_WITH_CODE((result == 0),
1175 "init_clock_voltage_dependency failed", return result);
1176
1177 result = init_dpm_2_parameters(hwmgr, powerplay_table);
1178
1179 PP_ASSERT_WITH_CODE((result == 0),
1180 "init_dpm_2_parameters failed", return result);
1181
1182 return result;
1183 }
1184
pp_tables_v1_0_uninitialize(struct pp_hwmgr * hwmgr)1185 static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
1186 {
1187 struct phm_ppt_v1_information *pp_table_information =
1188 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1189
1190 kfree(pp_table_information->vdd_dep_on_sclk);
1191 pp_table_information->vdd_dep_on_sclk = NULL;
1192
1193 kfree(pp_table_information->vdd_dep_on_mclk);
1194 pp_table_information->vdd_dep_on_mclk = NULL;
1195
1196 kfree(pp_table_information->valid_mclk_values);
1197 pp_table_information->valid_mclk_values = NULL;
1198
1199 kfree(pp_table_information->valid_sclk_values);
1200 pp_table_information->valid_sclk_values = NULL;
1201
1202 kfree(pp_table_information->vddc_lookup_table);
1203 pp_table_information->vddc_lookup_table = NULL;
1204
1205 kfree(pp_table_information->vddgfx_lookup_table);
1206 pp_table_information->vddgfx_lookup_table = NULL;
1207
1208 kfree(pp_table_information->mm_dep_table);
1209 pp_table_information->mm_dep_table = NULL;
1210
1211 kfree(pp_table_information->cac_dtp_table);
1212 pp_table_information->cac_dtp_table = NULL;
1213
1214 kfree(hwmgr->dyn_state.cac_dtp_table);
1215 hwmgr->dyn_state.cac_dtp_table = NULL;
1216
1217 kfree(pp_table_information->ppm_parameter_table);
1218 pp_table_information->ppm_parameter_table = NULL;
1219
1220 kfree(pp_table_information->pcie_table);
1221 pp_table_information->pcie_table = NULL;
1222
1223 kfree(pp_table_information->gpio_table);
1224 pp_table_information->gpio_table = NULL;
1225
1226 kfree(hwmgr->pptable);
1227 hwmgr->pptable = NULL;
1228
1229 return 0;
1230 }
1231
1232 const struct pp_table_func pptable_v1_0_funcs = {
1233 .pptable_init = pp_tables_v1_0_initialize,
1234 .pptable_fini = pp_tables_v1_0_uninitialize,
1235 };
1236
get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr * hwmgr)1237 int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr)
1238 {
1239 ATOM_Tonga_State_Array const *state_arrays;
1240 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1241
1242 PP_ASSERT_WITH_CODE((NULL != pp_table),
1243 "Missing PowerPlay Table!", return -1);
1244 PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >=
1245 ATOM_Tonga_TABLE_REVISION_TONGA),
1246 "Incorrect PowerPlay table revision!", return -1);
1247
1248 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
1249 le16_to_cpu(pp_table->usStateArrayOffset));
1250
1251 return (uint32_t)(state_arrays->ucNumEntries);
1252 }
1253
1254 /*
1255 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1256 */
make_classification_flags(struct pp_hwmgr * hwmgr,uint16_t classification,uint16_t classification2)1257 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
1258 uint16_t classification, uint16_t classification2)
1259 {
1260 uint32_t result = 0;
1261
1262 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
1263 result |= PP_StateClassificationFlag_Boot;
1264
1265 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1266 result |= PP_StateClassificationFlag_Thermal;
1267
1268 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
1269 result |= PP_StateClassificationFlag_LimitedPowerSource;
1270
1271 if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
1272 result |= PP_StateClassificationFlag_Rest;
1273
1274 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
1275 result |= PP_StateClassificationFlag_Forced;
1276
1277 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
1278 result |= PP_StateClassificationFlag_ACPI;
1279
1280 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
1281 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
1282
1283 return result;
1284 }
1285
ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr * hwmgr)1286 static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)
1287 {
1288 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1289 const ATOM_Tonga_VCE_State_Table *vce_state_table;
1290
1291
1292 if (pp_table == NULL)
1293 return 0;
1294
1295 vce_state_table = (void *)pp_table +
1296 le16_to_cpu(pp_table->usVCEStateTableOffset);
1297
1298 return vce_state_table->ucNumEntries;
1299 }
1300
ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr * hwmgr,uint32_t i,struct amd_vce_state * vce_state,void ** clock_info,uint32_t * flag)1301 static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i,
1302 struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag)
1303 {
1304 const ATOM_Tonga_VCE_State_Record *vce_state_record;
1305 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
1306 ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
1307 ATOM_Tonga_MM_Dependency_Record *mm_dep_record;
1308 const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr);
1309 const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable)
1310 + le16_to_cpu(pptable->usVCEStateTableOffset));
1311 const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable)
1312 + le16_to_cpu(pptable->usSclkDependencyTableOffset));
1313 const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable)
1314 + le16_to_cpu(pptable->usMclkDependencyTableOffset));
1315 const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable)
1316 + le16_to_cpu(pptable->usMMDependencyTableOffset));
1317
1318 PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries),
1319 "Requested state entry ID is out of range!",
1320 return -EINVAL);
1321
1322 vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1323 ATOM_Tonga_VCE_State_Record,
1324 entries, vce_state_table, i);
1325 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1326 ATOM_Tonga_SCLK_Dependency_Record,
1327 entries, sclk_dep_table,
1328 vce_state_record->ucSCLKIndex);
1329 mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1330 ATOM_Tonga_MM_Dependency_Record,
1331 entries, mm_dep_table,
1332 vce_state_record->ucVCEClockIndex);
1333 *flag = vce_state_record->ucFlag;
1334
1335 vce_state->evclk = le32_to_cpu(mm_dep_record->ulEClk);
1336 vce_state->ecclk = le32_to_cpu(mm_dep_record->ulEClk);
1337 vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk);
1338
1339 if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries)
1340 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1341 ATOM_Tonga_MCLK_Dependency_Record,
1342 entries, mclk_dep_table,
1343 mclk_dep_table->ucNumEntries - 1);
1344 else
1345 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1346 ATOM_Tonga_MCLK_Dependency_Record,
1347 entries, mclk_dep_table,
1348 vce_state_record->ucMCLKIndex);
1349
1350 vce_state->mclk = le32_to_cpu(mclk_dep_record->ulMclk);
1351 return 0;
1352 }
1353
1354 /**
1355 * get_powerplay_table_entry_v1_0 - Create a Power State out of an entry in the PowerPlay table.
1356 * This function is called by the hardware back-end.
1357 * @hwmgr: Pointer to the hardware manager.
1358 * @entry_index: The index of the entry to be extracted from the table.
1359 * @power_state: The address of the PowerState instance being created.
1360 * @call_back_func: The function to call into to fill power state
1361 * Return: -1 if the entry cannot be retrieved.
1362 */
get_powerplay_table_entry_v1_0(struct pp_hwmgr * hwmgr,uint32_t entry_index,struct pp_power_state * power_state,int (* call_back_func)(struct pp_hwmgr *,void *,struct pp_power_state *,void *,uint32_t))1363 int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr,
1364 uint32_t entry_index, struct pp_power_state *power_state,
1365 int (*call_back_func)(struct pp_hwmgr *, void *,
1366 struct pp_power_state *, void *, uint32_t))
1367 {
1368 int result = 0;
1369 const ATOM_Tonga_State_Array *state_arrays;
1370 const ATOM_Tonga_State *state_entry;
1371 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1372 int i, j;
1373 uint32_t flags = 0;
1374
1375 PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;);
1376 power_state->classification.bios_index = entry_index;
1377
1378 if (pp_table->sHeader.ucTableFormatRevision >=
1379 ATOM_Tonga_TABLE_REVISION_TONGA) {
1380 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
1381 le16_to_cpu(pp_table->usStateArrayOffset));
1382
1383 PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset),
1384 "Invalid PowerPlay Table State Array Offset.", return -1);
1385 PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
1386 "Invalid PowerPlay Table State Array.", return -1);
1387 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
1388 "Invalid PowerPlay Table State Array Entry.", return -1);
1389
1390 state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1391 ATOM_Tonga_State, entries,
1392 state_arrays, entry_index);
1393
1394 result = call_back_func(hwmgr, (void *)state_entry, power_state,
1395 (void *)pp_table,
1396 make_classification_flags(hwmgr,
1397 le16_to_cpu(state_entry->usClassification),
1398 le16_to_cpu(state_entry->usClassification2)));
1399 }
1400
1401 if (!result && (power_state->classification.flags &
1402 PP_StateClassificationFlag_Boot))
1403 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
1404
1405 hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr);
1406
1407 if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) {
1408 for (j = 0; j < i; j++)
1409 ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags);
1410 }
1411
1412 return result;
1413 }
1414
1415