1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "vega10_thermal.h"
25#include "vega10_hwmgr.h"
26#include "vega10_ppsmc.h"
27#include "vega10_inc.h"
28#include "pp_soc15.h"
29#include "pp_debug.h"
30
31static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
32{
33 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm);
34 *current_rpm = smum_get_argument(hwmgr);
35 return 0;
36}
37
38int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
39 struct phm_fan_speed_info *fan_speed_info)
40{
41
42 if (hwmgr->thermal_controller.fanInfo.bNoFan)
43 return 0;
44
45 fan_speed_info->supports_percent_read = true;
46 fan_speed_info->supports_percent_write = true;
47 fan_speed_info->min_percent = 0;
48 fan_speed_info->max_percent = 100;
49
50 if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
51 hwmgr->thermal_controller.fanInfo.
52 ucTachometerPulsesPerRevolution) {
53 fan_speed_info->supports_rpm_read = true;
54 fan_speed_info->supports_rpm_write = true;
55 fan_speed_info->min_rpm =
56 hwmgr->thermal_controller.fanInfo.ulMinRPM;
57 fan_speed_info->max_rpm =
58 hwmgr->thermal_controller.fanInfo.ulMaxRPM;
59 } else {
60 fan_speed_info->min_rpm = 0;
61 fan_speed_info->max_rpm = 0;
62 }
63
64 return 0;
65}
66
67int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
68 uint32_t *speed)
69{
70 uint32_t current_rpm;
71 uint32_t percent = 0;
72
73 if (hwmgr->thermal_controller.fanInfo.bNoFan)
74 return 0;
75
76 if (vega10_get_current_rpm(hwmgr, ¤t_rpm))
77 return -1;
78
79 if (hwmgr->thermal_controller.
80 advanceFanControlParameters.usMaxFanRPM != 0)
81 percent = current_rpm * 100 /
82 hwmgr->thermal_controller.
83 advanceFanControlParameters.usMaxFanRPM;
84
85 *speed = percent > 100 ? 100 : percent;
86
87 return 0;
88}
89
90int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
91{
92 struct vega10_hwmgr *data = hwmgr->backend;
93 uint32_t tach_period;
94 uint32_t crystal_clock_freq;
95 int result = 0;
96
97 if (hwmgr->thermal_controller.fanInfo.bNoFan)
98 return -1;
99
100 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
101 result = vega10_get_current_rpm(hwmgr, speed);
102 } else {
103 uint32_t reg = soc15_get_register_offset(THM_HWID, 0,
104 mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS);
105 tach_period =
106 CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
107 CG_TACH_STATUS,
108 TACH_PERIOD);
109
110 if (tach_period == 0)
111 return -EINVAL;
112
113 crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
114
115 *speed = 60 * crystal_clock_freq * 10000 / tach_period;
116 }
117
118 return result;
119}
120
121
122
123
124
125
126
127
128int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
129{
130 uint32_t reg;
131
132 reg = soc15_get_register_offset(THM_HWID, 0,
133 mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
134
135 if (hwmgr->fan_ctrl_is_in_default_mode) {
136 hwmgr->fan_ctrl_default_mode =
137 CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
138 CG_FDO_CTRL2, FDO_PWM_MODE);
139 hwmgr->tmin =
140 CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
141 CG_FDO_CTRL2, TMIN);
142 hwmgr->fan_ctrl_is_in_default_mode = false;
143 }
144
145 cgs_write_register(hwmgr->device, reg,
146 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
147 CG_FDO_CTRL2, TMIN, 0));
148 cgs_write_register(hwmgr->device, reg,
149 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
150 CG_FDO_CTRL2, FDO_PWM_MODE, mode));
151
152 return 0;
153}
154
155
156
157
158
159
160int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
161{
162 uint32_t reg;
163
164 reg = soc15_get_register_offset(THM_HWID, 0,
165 mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
166
167 if (!hwmgr->fan_ctrl_is_in_default_mode) {
168 cgs_write_register(hwmgr->device, reg,
169 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
170 CG_FDO_CTRL2, FDO_PWM_MODE,
171 hwmgr->fan_ctrl_default_mode));
172 cgs_write_register(hwmgr->device, reg,
173 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
174 CG_FDO_CTRL2, TMIN,
175 hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT));
176 hwmgr->fan_ctrl_is_in_default_mode = true;
177 }
178
179 return 0;
180}
181
182
183
184
185
186
187
188
189static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
190{
191 struct vega10_hwmgr *data = hwmgr->backend;
192
193 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
194 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
195 hwmgr, true,
196 data->smu_features[GNLD_FAN_CONTROL].
197 smu_feature_bitmap),
198 "Attempt to Enable FAN CONTROL feature Failed!",
199 return -1);
200 data->smu_features[GNLD_FAN_CONTROL].enabled = true;
201 }
202
203 return 0;
204}
205
206static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
207{
208 struct vega10_hwmgr *data = hwmgr->backend;
209
210 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
211 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
212 hwmgr, false,
213 data->smu_features[GNLD_FAN_CONTROL].
214 smu_feature_bitmap),
215 "Attempt to Enable FAN CONTROL feature Failed!",
216 return -1);
217 data->smu_features[GNLD_FAN_CONTROL].enabled = false;
218 }
219
220 return 0;
221}
222
223int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
224{
225 if (hwmgr->thermal_controller.fanInfo.bNoFan)
226 return -1;
227
228 PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr),
229 "Attempt to Enable SMC FAN CONTROL Feature Failed!",
230 return -1);
231
232 return 0;
233}
234
235
236int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
237{
238 struct vega10_hwmgr *data = hwmgr->backend;
239
240 if (hwmgr->thermal_controller.fanInfo.bNoFan)
241 return -1;
242
243 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
244 PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr),
245 "Attempt to Disable SMC FAN CONTROL Feature Failed!",
246 return -1);
247 }
248 return 0;
249}
250
251
252
253
254
255
256
257int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
258 uint32_t speed)
259{
260 uint32_t duty100;
261 uint32_t duty;
262 uint64_t tmp64;
263 uint32_t reg;
264
265 if (hwmgr->thermal_controller.fanInfo.bNoFan)
266 return 0;
267
268 if (speed > 100)
269 speed = 100;
270
271 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
272 vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
273
274 reg = soc15_get_register_offset(THM_HWID, 0,
275 mmCG_FDO_CTRL1_BASE_IDX, mmCG_FDO_CTRL1);
276
277 duty100 = CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
278 CG_FDO_CTRL1, FMAX_DUTY100);
279
280 if (duty100 == 0)
281 return -EINVAL;
282
283 tmp64 = (uint64_t)speed * duty100;
284 do_div(tmp64, 100);
285 duty = (uint32_t)tmp64;
286
287 reg = soc15_get_register_offset(THM_HWID, 0,
288 mmCG_FDO_CTRL0_BASE_IDX, mmCG_FDO_CTRL0);
289 cgs_write_register(hwmgr->device, reg,
290 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
291 CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
292
293 return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
294}
295
296
297
298
299
300
301int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
302{
303 if (hwmgr->thermal_controller.fanInfo.bNoFan)
304 return 0;
305
306 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
307 return vega10_fan_ctrl_start_smc_fan_control(hwmgr);
308 else
309 return vega10_fan_ctrl_set_default_mode(hwmgr);
310}
311
312
313
314
315
316
317
318int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
319{
320 uint32_t tach_period;
321 uint32_t crystal_clock_freq;
322 int result = 0;
323 uint32_t reg;
324
325 if (hwmgr->thermal_controller.fanInfo.bNoFan ||
326 (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
327 (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
328 return -1;
329
330 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
331 result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
332
333 if (!result) {
334 crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
335 tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
336 reg = soc15_get_register_offset(THM_HWID, 0,
337 mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS);
338 cgs_write_register(hwmgr->device, reg,
339 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
340 CG_TACH_STATUS, TACH_PERIOD,
341 tach_period));
342 }
343 return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
344}
345
346
347
348
349
350
351int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
352{
353 int temp;
354 uint32_t reg;
355
356 reg = soc15_get_register_offset(THM_HWID, 0,
357 mmCG_MULT_THERMAL_STATUS_BASE_IDX, mmCG_MULT_THERMAL_STATUS);
358
359 temp = cgs_read_register(hwmgr->device, reg);
360
361 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
362 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
363
364 temp = temp & 0x1ff;
365
366 temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
367
368 return temp;
369}
370
371
372
373
374
375
376
377
378
379static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
380 struct PP_TemperatureRange *range)
381{
382 int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP *
383 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
384 int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP *
385 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
386 uint32_t val, reg;
387
388 if (low < range->min)
389 low = range->min;
390 if (high > range->max)
391 high = range->max;
392
393 if (low > high)
394 return -EINVAL;
395
396 reg = soc15_get_register_offset(THM_HWID, 0,
397 mmTHM_THERMAL_INT_CTRL_BASE_IDX, mmTHM_THERMAL_INT_CTRL);
398
399 val = cgs_read_register(hwmgr->device, reg);
400
401 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
402 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
403 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
404 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
405 val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) &
406 (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) &
407 (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
408
409 cgs_write_register(hwmgr->device, reg, val);
410
411 return 0;
412}
413
414
415
416
417
418
419static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr)
420{
421 uint32_t reg;
422
423 if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
424 reg = soc15_get_register_offset(THM_HWID, 0,
425 mmCG_TACH_CTRL_BASE_IDX, mmCG_TACH_CTRL);
426 cgs_write_register(hwmgr->device, reg,
427 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
428 CG_TACH_CTRL, EDGE_PER_REV,
429 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1));
430 }
431
432 reg = soc15_get_register_offset(THM_HWID, 0,
433 mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
434 cgs_write_register(hwmgr->device, reg,
435 CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
436 CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28));
437
438 return 0;
439}
440
441
442
443
444
445
446static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
447{
448 struct vega10_hwmgr *data = hwmgr->backend;
449 uint32_t val = 0;
450 uint32_t reg;
451
452 if (data->smu_features[GNLD_FW_CTF].supported) {
453 if (data->smu_features[GNLD_FW_CTF].enabled)
454 printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n");
455
456 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
457 true,
458 data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
459 "Attempt to Enable FW CTF feature Failed!",
460 return -1);
461 data->smu_features[GNLD_FW_CTF].enabled = true;
462 }
463
464 val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
465 val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
466 val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
467
468 reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
469 cgs_write_register(hwmgr->device, reg, val);
470
471 return 0;
472}
473
474
475
476
477
478int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
479{
480 struct vega10_hwmgr *data = hwmgr->backend;
481 uint32_t reg;
482
483 if (data->smu_features[GNLD_FW_CTF].supported) {
484 if (!data->smu_features[GNLD_FW_CTF].enabled)
485 printk("[Thermal_EnableAlert] FW CTF Already disabled!\n");
486
487
488 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
489 false,
490 data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
491 "Attempt to disable FW CTF feature Failed!",
492 return -1);
493 data->smu_features[GNLD_FW_CTF].enabled = false;
494 }
495
496 reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
497 cgs_write_register(hwmgr->device, reg, 0);
498
499 return 0;
500}
501
502
503
504
505
506
507int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
508{
509 int result = vega10_thermal_disable_alert(hwmgr);
510
511 if (!hwmgr->thermal_controller.fanInfo.bNoFan)
512 vega10_fan_ctrl_set_default_mode(hwmgr);
513
514 return result;
515}
516
517
518
519
520
521
522
523
524
525
526int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
527{
528 int ret;
529 struct vega10_hwmgr *data = hwmgr->backend;
530 PPTable_t *table = &(data->smc_state_table.pp_table);
531
532 if (!data->smu_features[GNLD_FAN_CONTROL].supported)
533 return 0;
534
535 table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller.
536 advanceFanControlParameters.usMaxFanRPM;
537 table->FanThrottlingRpm = hwmgr->thermal_controller.
538 advanceFanControlParameters.usFanRPMMaxLimit;
539 table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller.
540 advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
541 table->FanTargetTemperature = hwmgr->thermal_controller.
542 advanceFanControlParameters.usTMax;
543
544 smum_send_msg_to_smc_with_parameter(hwmgr,
545 PPSMC_MSG_SetFanTemperatureTarget,
546 (uint32_t)table->FanTargetTemperature);
547
548 table->FanPwmMin = hwmgr->thermal_controller.
549 advanceFanControlParameters.usPWMMin * 255 / 100;
550 table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller.
551 advanceFanControlParameters.ulTargetGfxClk);
552 table->FanGainEdge = hwmgr->thermal_controller.
553 advanceFanControlParameters.usFanGainEdge;
554 table->FanGainHotspot = hwmgr->thermal_controller.
555 advanceFanControlParameters.usFanGainHotspot;
556 table->FanGainLiquid = hwmgr->thermal_controller.
557 advanceFanControlParameters.usFanGainLiquid;
558 table->FanGainVrVddc = hwmgr->thermal_controller.
559 advanceFanControlParameters.usFanGainVrVddc;
560 table->FanGainVrMvdd = hwmgr->thermal_controller.
561 advanceFanControlParameters.usFanGainVrMvdd;
562 table->FanGainPlx = hwmgr->thermal_controller.
563 advanceFanControlParameters.usFanGainPlx;
564 table->FanGainHbm = hwmgr->thermal_controller.
565 advanceFanControlParameters.usFanGainHbm;
566 table->FanZeroRpmEnable = hwmgr->thermal_controller.
567 advanceFanControlParameters.ucEnableZeroRPM;
568 table->FanStopTemp = hwmgr->thermal_controller.
569 advanceFanControlParameters.usZeroRPMStopTemperature;
570 table->FanStartTemp = hwmgr->thermal_controller.
571 advanceFanControlParameters.usZeroRPMStartTemperature;
572
573 ret = smum_smc_table_manager(hwmgr,
574 (uint8_t *)(&(data->smc_state_table.pp_table)),
575 PPTABLE, false);
576 if (ret)
577 pr_info("Failed to update Fan Control Table in PPTable!");
578
579 return ret;
580}
581
582
583
584
585
586
587
588
589
590
591int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
592{
593
594
595
596
597
598 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
599 vega10_fan_ctrl_start_smc_fan_control(hwmgr);
600
601 return 0;
602}
603
604
605int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
606 struct PP_TemperatureRange *range)
607{
608 int ret = 0;
609
610 if (range == NULL)
611 return -EINVAL;
612
613 vega10_thermal_initialize(hwmgr);
614 ret = vega10_thermal_set_temperature_range(hwmgr, range);
615 if (ret)
616 return -EINVAL;
617
618 vega10_thermal_enable_alert(hwmgr);
619
620
621
622
623
624 ret = vega10_thermal_setup_fan_table(hwmgr);
625 if (ret)
626 return -EINVAL;
627
628 vega10_thermal_start_smc_fan_control(hwmgr);
629
630 return 0;
631};
632
633
634
635
636int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
637{
638 if (!hwmgr->thermal_controller.fanInfo.bNoFan) {
639 vega10_fan_ctrl_set_default_mode(hwmgr);
640 vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
641 }
642 return 0;
643}
644