Merge remote-tracking branch 'battery/for-next'
[deliverable/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / hwmgr.c
CommitLineData
3bace359
JZ
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/delay.h"
24#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/slab.h>
bb06d7ef 27#include <drm/amdgpu_drm.h>
3bace359
JZ
28#include "cgs_common.h"
29#include "power_state.h"
30#include "hwmgr.h"
17c00a2f
RZ
31#include "pppcielanes.h"
32#include "pp_debug.h"
33#include "ppatomctrl.h"
8b41e7a0
RZ
34#include "ppsmc.h"
35
36#define VOLTAGE_SCALE 4
3bace359 37
17c00a2f
RZ
38extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
39extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
aabcb7c1 40extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr);
2cc0c0b5 41extern int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr);
025f8bfb 42extern int iceland_hwmgr_init(struct pp_hwmgr *hwmgr);
aabcb7c1 43
af223dfa
RZ
44static int hwmgr_set_features_platform_caps(struct pp_hwmgr *hwmgr)
45{
46 if (amdgpu_sclk_deep_sleep_en)
47 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
48 PHM_PlatformCaps_SclkDeepSleep);
49 else
50 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
51 PHM_PlatformCaps_SclkDeepSleep);
52
53 if (amdgpu_powercontainment)
54 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
55 PHM_PlatformCaps_PowerContainment);
56 else
57 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
58 PHM_PlatformCaps_PowerContainment);
59
60 return 0;
61}
62
3bace359
JZ
63int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
64{
65 struct pp_hwmgr *hwmgr;
66
67 if ((handle == NULL) || (pp_init == NULL))
68 return -EINVAL;
69
70 hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
71 if (hwmgr == NULL)
72 return -ENOMEM;
73
74 handle->hwmgr = hwmgr;
75 hwmgr->smumgr = handle->smu_mgr;
76 hwmgr->device = pp_init->device;
77 hwmgr->chip_family = pp_init->chip_family;
78 hwmgr->chip_id = pp_init->chip_id;
79 hwmgr->hw_revision = pp_init->rev_id;
6391b6ab
RZ
80 hwmgr->sub_sys_id = pp_init->sub_sys_id;
81 hwmgr->sub_vendor_id = pp_init->sub_vendor_id;
3bace359
JZ
82 hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
83 hwmgr->power_source = PP_PowerSource_AC;
af223dfa
RZ
84
85 hwmgr_set_features_platform_caps(hwmgr);
3bace359
JZ
86
87 switch (hwmgr->chip_family) {
bb06d7ef 88 case AMDGPU_FAMILY_CZ:
bdecc20a
JZ
89 cz_hwmgr_init(hwmgr);
90 break;
bb06d7ef 91 case AMDGPU_FAMILY_VI:
c82baa28 92 switch (hwmgr->chip_id) {
025f8bfb
HR
93 case CHIP_TOPAZ:
94 iceland_hwmgr_init(hwmgr);
95 break;
c82baa28 96 case CHIP_TONGA:
97 tonga_hwmgr_init(hwmgr);
98 break;
aabcb7c1
EH
99 case CHIP_FIJI:
100 fiji_hwmgr_init(hwmgr);
101 break;
2cc0c0b5
FC
102 case CHIP_POLARIS11:
103 case CHIP_POLARIS10:
104 polaris10_hwmgr_init(hwmgr);
b83c4ab9 105 break;
c82baa28 106 default:
107 return -EINVAL;
108 }
109 break;
3bace359
JZ
110 default:
111 return -EINVAL;
112 }
113
114 phm_init_dynamic_caps(hwmgr);
115
116 return 0;
117}
118
119int hwmgr_fini(struct pp_hwmgr *hwmgr)
120{
121 if (hwmgr == NULL || hwmgr->ps == NULL)
122 return -EINVAL;
123
61da601b 124 /* do hwmgr finish*/
4dcf9e6f
EH
125 kfree(hwmgr->hardcode_pp_table);
126
61da601b
ML
127 kfree(hwmgr->backend);
128
129 kfree(hwmgr->start_thermal_controller.function_list);
130
131 kfree(hwmgr->set_temperature_range.function_list);
132
3bace359
JZ
133 kfree(hwmgr->ps);
134 kfree(hwmgr);
135 return 0;
136}
137
138int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
139{
140 int result;
141 unsigned int i;
142 unsigned int table_entries;
143 struct pp_power_state *state;
144 int size;
145
146 if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
147 return -EINVAL;
148
149 if (hwmgr->hwmgr_func->get_power_state_size == NULL)
150 return -EINVAL;
151
152 hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
153
154 hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
155 sizeof(struct pp_power_state);
156
157 hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
158
c15c8d70
RZ
159 if (hwmgr->ps == NULL)
160 return -ENOMEM;
161
3bace359
JZ
162 state = hwmgr->ps;
163
164 for (i = 0; i < table_entries; i++) {
165 result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
17c00a2f 166
3bace359
JZ
167 if (state->classification.flags & PP_StateClassificationFlag_Boot) {
168 hwmgr->boot_ps = state;
169 hwmgr->current_ps = hwmgr->request_ps = state;
170 }
171
172 state->id = i + 1; /* assigned unique num for every power state id */
173
174 if (state->classification.flags & PP_StateClassificationFlag_Uvd)
175 hwmgr->uvd_ps = state;
09b7a986 176 state = (struct pp_power_state *)((unsigned long)state + size);
3bace359
JZ
177 }
178
179 return 0;
180}
181
182
183/**
184 * Returns once the part of the register indicated by the mask has
185 * reached the given value.
186 */
187int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
188 uint32_t value, uint32_t mask)
189{
190 uint32_t i;
191 uint32_t cur_value;
192
193 if (hwmgr == NULL || hwmgr->device == NULL) {
194 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
195 return -EINVAL;
196 }
197
198 for (i = 0; i < hwmgr->usec_timeout; i++) {
199 cur_value = cgs_read_register(hwmgr->device, index);
200 if ((cur_value & mask) == (value & mask))
201 break;
202 udelay(1);
203 }
204
205 /* timeout means wrong logic*/
206 if (i == hwmgr->usec_timeout)
207 return -1;
208 return 0;
209}
210
3bace359 211
3bace359
JZ
212
213
214/**
215 * Returns once the part of the register indicated by the mask has
216 * reached the given value.The indirect space is described by giving
217 * the memory-mapped index of the indirect index register.
218 */
219void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
220 uint32_t indirect_port,
221 uint32_t index,
222 uint32_t value,
223 uint32_t mask)
224{
225 if (hwmgr == NULL || hwmgr->device == NULL) {
226 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
227 return;
228 }
229
230 cgs_write_register(hwmgr->device, indirect_port, index);
231 phm_wait_on_register(hwmgr, indirect_port + 1, mask, value);
232}
233
3bace359 234
28a18bab
RZ
235
236bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
237{
238 return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
239}
240
241bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
242{
243 return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
244}
17c00a2f
RZ
245
246
247int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table)
248{
249 uint32_t i, j;
250 uint16_t vvalue;
251 bool found = false;
252 struct pp_atomctrl_voltage_table *table;
253
254 PP_ASSERT_WITH_CODE((NULL != vol_table),
255 "Voltage Table empty.", return -EINVAL);
256
257 table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
258 GFP_KERNEL);
259
260 if (NULL == table)
261 return -EINVAL;
262
263 table->mask_low = vol_table->mask_low;
264 table->phase_delay = vol_table->phase_delay;
265
266 for (i = 0; i < vol_table->count; i++) {
267 vvalue = vol_table->entries[i].value;
268 found = false;
269
270 for (j = 0; j < table->count; j++) {
271 if (vvalue == table->entries[j].value) {
272 found = true;
273 break;
274 }
275 }
276
277 if (!found) {
278 table->entries[table->count].value = vvalue;
279 table->entries[table->count].smio_low =
280 vol_table->entries[i].smio_low;
281 table->count++;
282 }
283 }
284
285 memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
286 kfree(table);
287
288 return 0;
289}
290
291int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
292 phm_ppt_v1_clock_voltage_dependency_table *dep_table)
293{
294 uint32_t i;
295 int result;
296
297 PP_ASSERT_WITH_CODE((0 != dep_table->count),
298 "Voltage Dependency Table empty.", return -EINVAL);
299
300 PP_ASSERT_WITH_CODE((NULL != vol_table),
301 "vol_table empty.", return -EINVAL);
302
303 vol_table->mask_low = 0;
304 vol_table->phase_delay = 0;
305 vol_table->count = dep_table->count;
306
307 for (i = 0; i < dep_table->count; i++) {
308 vol_table->entries[i].value = dep_table->entries[i].mvdd;
309 vol_table->entries[i].smio_low = 0;
310 }
311
312 result = phm_trim_voltage_table(vol_table);
313 PP_ASSERT_WITH_CODE((0 == result),
314 "Failed to trim MVDD table.", return result);
315
316 return 0;
317}
318
319int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
320 phm_ppt_v1_clock_voltage_dependency_table *dep_table)
321{
322 uint32_t i;
323 int result;
324
325 PP_ASSERT_WITH_CODE((0 != dep_table->count),
326 "Voltage Dependency Table empty.", return -EINVAL);
327
328 PP_ASSERT_WITH_CODE((NULL != vol_table),
329 "vol_table empty.", return -EINVAL);
330
331 vol_table->mask_low = 0;
332 vol_table->phase_delay = 0;
333 vol_table->count = dep_table->count;
334
335 for (i = 0; i < dep_table->count; i++) {
336 vol_table->entries[i].value = dep_table->entries[i].vddci;
337 vol_table->entries[i].smio_low = 0;
338 }
339
340 result = phm_trim_voltage_table(vol_table);
341 PP_ASSERT_WITH_CODE((0 == result),
342 "Failed to trim VDDCI table.", return result);
343
344 return 0;
345}
346
347int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
348 phm_ppt_v1_voltage_lookup_table *lookup_table)
349{
350 int i = 0;
351
352 PP_ASSERT_WITH_CODE((0 != lookup_table->count),
353 "Voltage Lookup Table empty.", return -EINVAL);
354
355 PP_ASSERT_WITH_CODE((NULL != vol_table),
356 "vol_table empty.", return -EINVAL);
357
358 vol_table->mask_low = 0;
359 vol_table->phase_delay = 0;
360
361 vol_table->count = lookup_table->count;
362
363 for (i = 0; i < vol_table->count; i++) {
364 vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
365 vol_table->entries[i].smio_low = 0;
366 }
367
368 return 0;
369}
370
371void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,
372 struct pp_atomctrl_voltage_table *vol_table)
373{
374 unsigned int i, diff;
375
376 if (vol_table->count <= max_vol_steps)
377 return;
378
379 diff = vol_table->count - max_vol_steps;
380
381 for (i = 0; i < max_vol_steps; i++)
382 vol_table->entries[i] = vol_table->entries[i + diff];
383
384 vol_table->count = max_vol_steps;
385
386 return;
387}
388
389int phm_reset_single_dpm_table(void *table,
390 uint32_t count, int max)
391{
392 int i;
393
394 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
395
396 PP_ASSERT_WITH_CODE(count <= max,
397 "Fatal error, can not set up single DPM table entries to exceed max number!",
398 );
399
400 dpm_table->count = count;
401 for (i = 0; i < max; i++)
402 dpm_table->dpm_level[i].enabled = false;
403
404 return 0;
405}
406
407void phm_setup_pcie_table_entry(
408 void *table,
409 uint32_t index, uint32_t pcie_gen,
410 uint32_t pcie_lanes)
411{
412 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
413 dpm_table->dpm_level[index].value = pcie_gen;
414 dpm_table->dpm_level[index].param1 = pcie_lanes;
415 dpm_table->dpm_level[index].enabled = 1;
416}
417
418int32_t phm_get_dpm_level_enable_mask_value(void *table)
419{
420 int32_t i;
421 int32_t mask = 0;
422 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
423
424 for (i = dpm_table->count; i > 0; i--) {
425 mask = mask << 1;
426 if (dpm_table->dpm_level[i - 1].enabled)
427 mask |= 0x1;
428 else
429 mask &= 0xFFFFFFFE;
430 }
431
432 return mask;
433}
434
435uint8_t phm_get_voltage_index(
436 struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
437{
438 uint8_t count = (uint8_t) (lookup_table->count);
439 uint8_t i;
440
441 PP_ASSERT_WITH_CODE((NULL != lookup_table),
442 "Lookup Table empty.", return 0);
443 PP_ASSERT_WITH_CODE((0 != count),
444 "Lookup Table empty.", return 0);
445
446 for (i = 0; i < lookup_table->count; i++) {
447 /* find first voltage equal or bigger than requested */
448 if (lookup_table->entries[i].us_vdd >= voltage)
449 return i;
450 }
451 /* voltage is bigger than max voltage in the table */
452 return i - 1;
453}
454
455uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci)
456{
457 uint32_t i;
458
459 for (i = 0; i < vddci_table->count; i++) {
460 if (vddci_table->entries[i].value >= vddci)
461 return vddci_table->entries[i].value;
462 }
463
464 PP_ASSERT_WITH_CODE(false,
465 "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
d2e31218 466 return vddci_table->entries[i-1].value);
17c00a2f
RZ
467}
468
469int phm_find_boot_level(void *table,
470 uint32_t value, uint32_t *boot_level)
471{
472 int result = -EINVAL;
473 uint32_t i;
474 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
475
476 for (i = 0; i < dpm_table->count; i++) {
477 if (value == dpm_table->dpm_level[i].value) {
478 *boot_level = i;
479 result = 0;
480 }
481 }
482
483 return result;
484}
485
486int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
487 phm_ppt_v1_voltage_lookup_table *lookup_table,
488 uint16_t virtual_voltage_id, int32_t *sclk)
489{
490 uint8_t entryId;
491 uint8_t voltageId;
492 struct phm_ppt_v1_information *table_info =
493 (struct phm_ppt_v1_information *)(hwmgr->pptable);
494
495 PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
496
497 /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
498 for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) {
499 voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd;
500 if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
501 break;
502 }
503
504 PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count,
505 "Can't find requested voltage id in vdd_dep_on_sclk table!",
506 return -EINVAL;
507 );
508
509 *sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk;
510
511 return 0;
512}
513
514/**
515 * Initialize Dynamic State Adjustment Rule Settings
516 *
517 * @param hwmgr the address of the powerplay hardware manager.
518 */
519int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
520{
521 uint32_t table_size;
522 struct phm_clock_voltage_dependency_table *table_clk_vlt;
523 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
524
525 /* initialize vddc_dep_on_dal_pwrl table */
526 table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
5969a8c7 527 table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
17c00a2f
RZ
528
529 if (NULL == table_clk_vlt) {
530 printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
531 return -ENOMEM;
532 } else {
533 table_clk_vlt->count = 4;
534 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
535 table_clk_vlt->entries[0].v = 0;
536 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
537 table_clk_vlt->entries[1].v = 720;
538 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
539 table_clk_vlt->entries[2].v = 810;
540 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
541 table_clk_vlt->entries[3].v = 900;
542 pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
543 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
544 }
545
546 return 0;
547}
548
549int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
550{
551 if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
552 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
553 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
554 }
555
556 if (NULL != hwmgr->backend) {
557 kfree(hwmgr->backend);
558 hwmgr->backend = NULL;
559 }
560
561 return 0;
562}
563
564uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
565{
566 uint32_t level = 0;
567
568 while (0 == (mask & (1 << level)))
569 level++;
570
571 return level;
572}
8b41e7a0
RZ
573
574void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
575{
576 struct phm_ppt_v1_information *table_info =
577 (struct phm_ppt_v1_information *)hwmgr->pptable;
578 struct phm_clock_voltage_dependency_table *table =
579 table_info->vddc_dep_on_dal_pwrl;
580 struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
581 enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
582 uint32_t req_vddc = 0, req_volt, i;
583
584 if (!table || table->count <= 0
585 || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
586 || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
587 return;
588
589 for (i = 0; i < table->count; i++) {
590 if (dal_power_level == table->entries[i].clk) {
591 req_vddc = table->entries[i].v;
592 break;
593 }
594 }
595
596 vddc_table = table_info->vdd_dep_on_sclk;
597 for (i = 0; i < vddc_table->count; i++) {
598 if (req_vddc <= vddc_table->entries[i].vddc) {
599 req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
600 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
601 PPSMC_MSG_VddC_Request, req_volt);
602 return;
603 }
604 }
605 printk(KERN_ERR "DAL requested level can not"
606 " found a available voltage in VDDC DPM Table \n");
607}
This page took 0.113133 seconds and 5 git commands to generate.