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