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