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