2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include "ppatomfwctrl.h"
25 #include "atomfirmware.h"
29 static const union atom_voltage_object_v4
*pp_atomfwctrl_lookup_voltage_type_v4(
30 const struct atom_voltage_objects_info_v4_1
*voltage_object_info_table
,
31 uint8_t voltage_type
, uint8_t voltage_mode
)
33 unsigned int size
= le16_to_cpu(
34 voltage_object_info_table
->table_header
.structuresize
);
36 offsetof(struct atom_voltage_objects_info_v4_1
, voltage_object
[0]);
37 unsigned long start
= (unsigned long)voltage_object_info_table
;
39 while (offset
< size
) {
40 const union atom_voltage_object_v4
*voltage_object
=
41 (const union atom_voltage_object_v4
*)(start
+ offset
);
43 if (voltage_type
== voltage_object
->gpio_voltage_obj
.header
.voltage_type
&&
44 voltage_mode
== voltage_object
->gpio_voltage_obj
.header
.voltage_mode
)
45 return voltage_object
;
47 offset
+= le16_to_cpu(voltage_object
->gpio_voltage_obj
.header
.object_size
);
54 static struct atom_voltage_objects_info_v4_1
*pp_atomfwctrl_get_voltage_info_table(
55 struct pp_hwmgr
*hwmgr
)
57 const void *table_address
;
60 idx
= GetIndexIntoMasterDataTable(voltageobject_info
);
61 table_address
= cgs_atom_get_data_table(hwmgr
->device
,
62 idx
, NULL
, NULL
, NULL
);
66 "Error retrieving BIOS Table Address!",
69 return (struct atom_voltage_objects_info_v4_1
*)table_address
;
73 * Returns TRUE if the given voltage type is controlled by GPIO pins.
74 * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ.
75 * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE
77 bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr
*hwmgr
,
78 uint8_t voltage_type
, uint8_t voltage_mode
)
80 struct atom_voltage_objects_info_v4_1
*voltage_info
=
81 (struct atom_voltage_objects_info_v4_1
*)
82 pp_atomfwctrl_get_voltage_info_table(hwmgr
);
85 /* If we cannot find the table do NOT try to control this voltage. */
86 PP_ASSERT_WITH_CODE(voltage_info
,
87 "Could not find Voltage Table in BIOS.",
90 ret
= (pp_atomfwctrl_lookup_voltage_type_v4(voltage_info
,
91 voltage_type
, voltage_mode
)) ? true : false;
96 int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr
*hwmgr
,
97 uint8_t voltage_type
, uint8_t voltage_mode
,
98 struct pp_atomfwctrl_voltage_table
*voltage_table
)
100 struct atom_voltage_objects_info_v4_1
*voltage_info
=
101 (struct atom_voltage_objects_info_v4_1
*)
102 pp_atomfwctrl_get_voltage_info_table(hwmgr
);
103 const union atom_voltage_object_v4
*voltage_object
;
107 PP_ASSERT_WITH_CODE(voltage_info
,
108 "Could not find Voltage Table in BIOS.",
111 voltage_object
= pp_atomfwctrl_lookup_voltage_type_v4(voltage_info
,
112 voltage_type
, voltage_mode
);
117 voltage_table
->count
= 0;
118 if (voltage_mode
== VOLTAGE_OBJ_GPIO_LUT
) {
120 (voltage_object
->gpio_voltage_obj
.gpio_entry_num
<=
121 PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES
),
122 "Too many voltage entries!",
126 for (i
= 0; i
< voltage_object
->gpio_voltage_obj
.
127 gpio_entry_num
; i
++) {
128 voltage_table
->entries
[i
].value
=
129 le16_to_cpu(voltage_object
->gpio_voltage_obj
.
130 voltage_gpio_lut
[i
].voltage_level_mv
);
131 voltage_table
->entries
[i
].smio_low
=
132 le32_to_cpu(voltage_object
->gpio_voltage_obj
.
133 voltage_gpio_lut
[i
].voltage_gpio_reg_val
);
135 voltage_table
->count
=
136 voltage_object
->gpio_voltage_obj
.gpio_entry_num
;
137 voltage_table
->mask_low
=
139 voltage_object
->gpio_voltage_obj
.gpio_mask_val
);
140 voltage_table
->phase_delay
=
141 voltage_object
->gpio_voltage_obj
.phase_delay_us
;
143 } else if (voltage_mode
== VOLTAGE_OBJ_SVID2
) {
144 voltage_table
->psi1_enable
=
145 voltage_object
->svid2_voltage_obj
.loadline_psi1
& 0x1;
146 voltage_table
->psi0_enable
=
147 voltage_object
->svid2_voltage_obj
.psi0_enable
& 0x1;
148 voltage_table
->max_vid_step
=
149 voltage_object
->svid2_voltage_obj
.maxvstep
;
150 voltage_table
->telemetry_offset
=
151 voltage_object
->svid2_voltage_obj
.telemetry_offset
;
152 voltage_table
->telemetry_slope
=
153 voltage_object
->svid2_voltage_obj
.telemetry_gain
;
155 PP_ASSERT_WITH_CODE(false,
156 "Unsupported Voltage Object Mode!",
163 static struct atom_gpio_pin_lut_v2_1
*pp_atomfwctrl_get_gpio_lookup_table(
164 struct pp_hwmgr
*hwmgr
)
166 const void *table_address
;
169 idx
= GetIndexIntoMasterDataTable(gpio_pin_lut
);
170 table_address
= cgs_atom_get_data_table(hwmgr
->device
,
171 idx
, NULL
, NULL
, NULL
);
172 PP_ASSERT_WITH_CODE(table_address
,
173 "Error retrieving BIOS Table Address!",
176 return (struct atom_gpio_pin_lut_v2_1
*)table_address
;
179 static bool pp_atomfwctrl_lookup_gpio_pin(
180 struct atom_gpio_pin_lut_v2_1
*gpio_lookup_table
,
181 const uint32_t pin_id
,
182 struct pp_atomfwctrl_gpio_pin_assignment
*gpio_pin_assignment
)
184 unsigned int size
= le16_to_cpu(
185 gpio_lookup_table
->table_header
.structuresize
);
186 unsigned int offset
=
187 offsetof(struct atom_gpio_pin_lut_v2_1
, gpio_pin
[0]);
188 unsigned long start
= (unsigned long)gpio_lookup_table
;
190 while (offset
< size
) {
191 const struct atom_gpio_pin_assignment
*pin_assignment
=
192 (const struct atom_gpio_pin_assignment
*)(start
+ offset
);
194 if (pin_id
== pin_assignment
->gpio_id
) {
195 gpio_pin_assignment
->uc_gpio_pin_bit_shift
=
196 pin_assignment
->gpio_bitshift
;
197 gpio_pin_assignment
->us_gpio_pin_aindex
=
198 le16_to_cpu(pin_assignment
->data_a_reg_index
);
201 offset
+= offsetof(struct atom_gpio_pin_assignment
, gpio_id
) + 1;
207 * Returns TRUE if the given pin id find in lookup table.
209 bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr
*hwmgr
,
210 const uint32_t pin_id
,
211 struct pp_atomfwctrl_gpio_pin_assignment
*gpio_pin_assignment
)
214 struct atom_gpio_pin_lut_v2_1
*gpio_lookup_table
=
215 pp_atomfwctrl_get_gpio_lookup_table(hwmgr
);
217 /* If we cannot find the table do NOT try to control this voltage. */
218 PP_ASSERT_WITH_CODE(gpio_lookup_table
,
219 "Could not find GPIO lookup Table in BIOS.",
222 ret
= pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table
,
223 pin_id
, gpio_pin_assignment
);
229 * Enter to SelfRefresh mode.
232 int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr
*hwmgr
)
235 * 1 - leave power to video memory always on
240 /** pp_atomfwctrl_get_gpu_pll_dividers_vega10().
242 * @param hwmgr input parameter: pointer to HwMgr
243 * @param clock_type input parameter: Clock type: 1 - GFXCLK, 2 - UCLK, 0 - All other clocks
244 * @param clock_value input parameter: Clock
245 * @param dividers output parameter:Clock dividers
247 int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr
*hwmgr
,
248 uint32_t clock_type
, uint32_t clock_value
,
249 struct pp_atomfwctrl_clock_dividers_soc15
*dividers
)
251 struct compute_gpu_clock_input_parameter_v1_8 pll_parameters
;
252 struct compute_gpu_clock_output_parameter_v1_8
*pll_output
;
256 pll_parameters
.gpuclock_10khz
= (uint32_t)clock_value
;
257 pll_parameters
.gpu_clock_type
= clock_type
;
259 idx
= GetIndexIntoMasterCmdTable(computegpuclockparam
);
260 result
= cgs_atom_exec_cmd_table(hwmgr
->device
, idx
, &pll_parameters
);
263 pll_output
= (struct compute_gpu_clock_output_parameter_v1_8
*)
265 dividers
->ulClock
= le32_to_cpu(pll_output
->gpuclock_10khz
);
266 dividers
->ulDid
= le32_to_cpu(pll_output
->dfs_did
);
267 dividers
->ulPll_fb_mult
= le32_to_cpu(pll_output
->pll_fb_mult
);
268 dividers
->ulPll_ss_fbsmult
= le32_to_cpu(pll_output
->pll_ss_fbsmult
);
269 dividers
->usPll_ss_slew_frac
= le16_to_cpu(pll_output
->pll_ss_slew_frac
);
270 dividers
->ucPll_ss_enable
= pll_output
->pll_ss_enable
;
275 int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr
*hwmgr
,
276 struct pp_atomfwctrl_avfs_parameters
*param
)
279 struct atom_asic_profiling_info_v4_1
*profile
;
281 idx
= GetIndexIntoMasterDataTable(asic_profiling_info
);
282 profile
= (struct atom_asic_profiling_info_v4_1
*)
283 cgs_atom_get_data_table(hwmgr
->device
,
284 idx
, NULL
, NULL
, NULL
);
289 param
->ulMaxVddc
= le32_to_cpu(profile
->maxvddc
);
290 param
->ulMinVddc
= le32_to_cpu(profile
->minvddc
);
291 param
->ulMeanNsigmaAcontant0
=
292 le32_to_cpu(profile
->avfs_meannsigma_acontant0
);
293 param
->ulMeanNsigmaAcontant1
=
294 le32_to_cpu(profile
->avfs_meannsigma_acontant1
);
295 param
->ulMeanNsigmaAcontant2
=
296 le32_to_cpu(profile
->avfs_meannsigma_acontant2
);
297 param
->usMeanNsigmaDcTolSigma
=
298 le16_to_cpu(profile
->avfs_meannsigma_dc_tol_sigma
);
299 param
->usMeanNsigmaPlatformMean
=
300 le16_to_cpu(profile
->avfs_meannsigma_platform_mean
);
301 param
->usMeanNsigmaPlatformSigma
=
302 le16_to_cpu(profile
->avfs_meannsigma_platform_sigma
);
303 param
->ulGbVdroopTableCksoffA0
=
304 le32_to_cpu(profile
->gb_vdroop_table_cksoff_a0
);
305 param
->ulGbVdroopTableCksoffA1
=
306 le32_to_cpu(profile
->gb_vdroop_table_cksoff_a1
);
307 param
->ulGbVdroopTableCksoffA2
=
308 le32_to_cpu(profile
->gb_vdroop_table_cksoff_a2
);
309 param
->ulGbVdroopTableCksonA0
=
310 le32_to_cpu(profile
->gb_vdroop_table_ckson_a0
);
311 param
->ulGbVdroopTableCksonA1
=
312 le32_to_cpu(profile
->gb_vdroop_table_ckson_a1
);
313 param
->ulGbVdroopTableCksonA2
=
314 le32_to_cpu(profile
->gb_vdroop_table_ckson_a2
);
315 param
->ulGbFuseTableCksoffM1
=
316 le32_to_cpu(profile
->avfsgb_fuse_table_cksoff_m1
);
317 param
->usGbFuseTableCksoffM2
=
318 le16_to_cpu(profile
->avfsgb_fuse_table_cksoff_m2
);
319 param
->ulGbFuseTableCksoffB
=
320 le32_to_cpu(profile
->avfsgb_fuse_table_cksoff_b
);
321 param
->ulGbFuseTableCksonM1
=
322 le32_to_cpu(profile
->avfsgb_fuse_table_ckson_m1
);
323 param
->usGbFuseTableCksonM2
=
324 le16_to_cpu(profile
->avfsgb_fuse_table_ckson_m2
);
325 param
->ulGbFuseTableCksonB
=
326 le32_to_cpu(profile
->avfsgb_fuse_table_ckson_b
);
327 param
->usMaxVoltage025mv
=
328 le16_to_cpu(profile
->max_voltage_0_25mv
);
329 param
->ucEnableGbVdroopTableCksoff
=
330 profile
->enable_gb_vdroop_table_cksoff
;
331 param
->ucEnableGbVdroopTableCkson
=
332 profile
->enable_gb_vdroop_table_ckson
;
333 param
->ucEnableGbFuseTableCksoff
=
334 profile
->enable_gb_fuse_table_cksoff
;
335 param
->ucEnableGbFuseTableCkson
=
336 profile
->enable_gb_fuse_table_ckson
;
337 param
->usPsmAgeComfactor
=
338 le16_to_cpu(profile
->psm_age_comfactor
);
339 param
->ucEnableApplyAvfsCksoffVoltage
=
340 profile
->enable_apply_avfs_cksoff_voltage
;
342 param
->ulDispclk2GfxclkM1
=
343 le32_to_cpu(profile
->dispclk2gfxclk_a
);
344 param
->usDispclk2GfxclkM2
=
345 le16_to_cpu(profile
->dispclk2gfxclk_b
);
346 param
->ulDispclk2GfxclkB
=
347 le32_to_cpu(profile
->dispclk2gfxclk_c
);
348 param
->ulDcefclk2GfxclkM1
=
349 le32_to_cpu(profile
->dcefclk2gfxclk_a
);
350 param
->usDcefclk2GfxclkM2
=
351 le16_to_cpu(profile
->dcefclk2gfxclk_b
);
352 param
->ulDcefclk2GfxclkB
=
353 le32_to_cpu(profile
->dcefclk2gfxclk_c
);
354 param
->ulPixelclk2GfxclkM1
=
355 le32_to_cpu(profile
->pixclk2gfxclk_a
);
356 param
->usPixelclk2GfxclkM2
=
357 le16_to_cpu(profile
->pixclk2gfxclk_b
);
358 param
->ulPixelclk2GfxclkB
=
359 le32_to_cpu(profile
->pixclk2gfxclk_c
);
360 param
->ulPhyclk2GfxclkM1
=
361 le32_to_cpu(profile
->phyclk2gfxclk_a
);
362 param
->usPhyclk2GfxclkM2
=
363 le16_to_cpu(profile
->phyclk2gfxclk_b
);
364 param
->ulPhyclk2GfxclkB
=
365 le32_to_cpu(profile
->phyclk2gfxclk_c
);
370 int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr
*hwmgr
,
371 struct pp_atomfwctrl_gpio_parameters
*param
)
373 struct atom_smu_info_v3_1
*info
;
376 idx
= GetIndexIntoMasterDataTable(smu_info
);
377 info
= (struct atom_smu_info_v3_1
*)
378 cgs_atom_get_data_table(hwmgr
->device
,
379 idx
, NULL
, NULL
, NULL
);
382 pr_info("Error retrieving BIOS smu_info Table Address!");
386 param
->ucAcDcGpio
= info
->ac_dc_gpio_bit
;
387 param
->ucAcDcPolarity
= info
->ac_dc_polarity
;
388 param
->ucVR0HotGpio
= info
->vr0hot_gpio_bit
;
389 param
->ucVR0HotPolarity
= info
->vr0hot_polarity
;
390 param
->ucVR1HotGpio
= info
->vr1hot_gpio_bit
;
391 param
->ucVR1HotPolarity
= info
->vr1hot_polarity
;
392 param
->ucFwCtfGpio
= info
->fw_ctf_gpio_bit
;
393 param
->ucFwCtfPolarity
= info
->fw_ctf_polarity
;