9 #include <linux/types.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/device.h>
14 #include <linux/reboot.h>
28 #define DBG(args...) printk(args)
30 #define DBG(args...) do { } while(0)
34 #define DBG_LOTS(args...) printk(args)
36 #define DBG_LOTS(args...) do { } while(0)
42 #undef HACKED_OVERTEMP
46 #define NR_CPU_FANS 3 * NR_CHIPS
64 #define CPU_TEMP_HIST_SIZE 180
67 #define SLOTS_FAN_DEFAULT_PWM 40
70 #define CPU_INTAKE_SCALE 0x0000f852
75 static bool cpu_pid_combined;
77 static int cpu_thist_pt;
78 static s64 cpu_thist_total;
79 static s32 cpu_all_tmax = 100 << 16;
81 static int backside_tick;
83 static int drives_tick;
86 static bool have_all_controls;
87 static bool have_all_sensors;
90 static int failure_state;
91 #define FAILURE_SENSOR 1
93 #define FAILURE_PERM 4
94 #define FAILURE_LOW_OVERTEMP 8
95 #define FAILURE_HIGH_OVERTEMP 16
98 #define LOW_OVER_AVERAGE 0
99 #define LOW_OVER_IMMEDIATE (10 << 16)
100 #define LOW_OVER_CLEAR ((-10) << 16)
101 #define HIGH_OVER_IMMEDIATE (14 << 16)
102 #define HIGH_OVER_AVERAGE (10 << 16)
103 #define HIGH_OVER_IMMEDIATE (14 << 16)
106 static void cpu_max_all_fans(
void)
115 wf_control_set_max(cpufreq_clamp);
116 for (i = 0; i < nr_chips; i++) {
117 if (cpu_front_fans[i])
118 wf_control_set_max(cpu_front_fans[i]);
119 if (cpu_rear_fans[i])
120 wf_control_set_max(cpu_rear_fans[i]);
122 wf_control_set_max(cpu_pumps[i]);
126 static int cpu_check_overtemp(
s32 temp)
130 static bool first =
true;
143 " immediate CPU temperature !\n");
156 cpu_thist_total +=
temp;
165 t_old = cpu_thist[cpu_thist_pt];
166 cpu_thist[cpu_thist_pt] =
temp;
168 cpu_thist_total -= t_old;
169 cpu_thist_total +=
temp;
172 DBG_LOTS(
" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
186 " average CPU temperature !\n");
197 if ((failure_state & new_state) != new_state)
203 failure_state &= ~FAILURE_LOW_OVERTEMP;
209 static int read_one_cpu_vals(
int cpu,
s32 *temp,
s32 *power)
211 s32 dtemp, volts, amps;
215 rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
217 DBG(
" CPU%d: temp reading error !\n", cpu);
224 rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
226 DBG(
" CPU%d, volts reading error !\n", cpu);
232 rc = wf_sensor_get(sens_cpu_amps[cpu], &s);
234 DBG(
" CPU%d, current reading error !\n", cpu);
244 *power = (((
u64)volts) * ((
u64)amps)) >> 16;
252 static void cpu_fans_tick_split(
void)
255 s32 intake,
temp, power, t_max = 0;
257 DBG_LOTS(
"* cpu fans_tick_split()\n");
259 for (cpu = 0; cpu < nr_chips; ++
cpu) {
263 wf_control_get(cpu_rear_fans[cpu], &sp->
target);
267 err = read_one_cpu_vals(cpu, &temp, &power);
275 t_max =
max(t_max, temp);
278 if (cpu_check_overtemp(t_max))
287 err = wf_control_set(cpu_rear_fans[cpu], sp->
target);
289 pr_warning(
"wf_pm72: Fan %s reports error %d\n",
290 cpu_rear_fans[cpu]->
name, err);
297 DBG_LOTS(
" CPU%d: intake = %d RPM\n", cpu, intake);
298 err = wf_control_set(cpu_front_fans[cpu], intake);
300 pr_warning(
"wf_pm72: Fan %s reports error %d\n",
301 cpu_front_fans[cpu]->
name, err);
308 static void cpu_fans_tick_combined(
void)
316 DBG_LOTS(
"* cpu fans_tick_combined()\n");
319 wf_control_get(cpu_rear_fans[0], &sp->
target);
324 err = read_one_cpu_vals(0, &temp0, &power0);
330 err = read_one_cpu_vals(1, &temp1, &power1);
338 t_max =
max(t_max,
max(temp0, temp1));
341 if (cpu_check_overtemp(t_max))
345 temp =
max(temp0, temp1);
346 power =
max(power0, power1);
355 pump0 = cpu_pumps[0];
356 pump1 = cpu_pumps[1];
361 pump = (sp->
target * wf_control_get_max(pump0)) /
362 cpu_mpu_data[0]->rmaxn_exhaust_fan;
365 DBG_LOTS(
" CPUs: intake = %d RPM\n", intake);
366 DBG_LOTS(
" CPUs: pump = %d RPM\n", pump);
368 for (cpu = 0; cpu < nr_chips; cpu++) {
369 err = wf_control_set(cpu_rear_fans[cpu], sp->
target);
371 pr_warning(
"wf_pm72: Fan %s reports error %d\n",
372 cpu_rear_fans[cpu]->
name, err);
375 err = wf_control_set(cpu_front_fans[cpu], intake);
377 pr_warning(
"wf_pm72: Fan %s reports error %d\n",
378 cpu_front_fans[cpu]->
name, err);
383 err = wf_control_set(cpu_pumps[cpu], pump);
385 pr_warning(
"wf_pm72: Pump %s reports error %d\n",
386 cpu_pumps[cpu]->
name, err);
393 static int cpu_setup_pid(
int cpu)
398 int fmin, fmax,
hsize;
401 tmax = mpu->
tmax << 16;
405 DBG(
"wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
409 if (tmax < cpu_all_tmax)
413 fmin = wf_control_get_min(cpu_rear_fans[cpu]);
414 fmax = wf_control_get_max(cpu_rear_fans[cpu]);
415 DBG(
"wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
419 DBG(
"wf_72: CPU%d history size = %d\n", cpu, hsize);
429 pid.pmaxadj = ptarget;
434 cpu_pid[
cpu].target = 1000;
464 static void backside_fan_tick(
void)
470 if (!backside_fan || !backside_temp || !backside_tick)
472 if (--backside_tick > 0)
474 backside_tick = backside_pid.param.interval;
479 err = wf_control_get(backside_fan, &speed);
481 backside_pid.target = speed;
483 err = wf_sensor_get(backside_temp, &temp);
488 wf_control_set_max(backside_fan);
493 DBG_LOTS(
"backside PID temp=%d.%.3d speed=%d\n",
496 err = wf_control_set(backside_fan, speed);
503 static void backside_setup_pid(
void)
506 s32 fmin = wf_control_get_min(backside_fan);
507 s32 fmax = wf_control_get_max(backside_fan);
516 if (((*vers) & 0x3f) < 0x34)
521 param = u3h ? backside_u3h_param : backside_u3_param;
528 pr_info(
"wf_pm72: Backside control loop started.\n");
544 static void drives_fan_tick(
void)
550 if (!drives_fan || !drives_temp || !drives_tick)
552 if (--drives_tick > 0)
554 drives_tick = drives_pid.param.interval;
559 err = wf_control_get(drives_fan, &speed);
561 drives_pid.target = speed;
563 err = wf_sensor_get(drives_temp, &temp);
565 pr_warning(
"wf_pm72: drive bay temp sensor error %d\n", err);
567 wf_control_set_max(drives_fan);
572 DBG_LOTS(
"drives PID temp=%d.%.3d speed=%d\n",
575 err = wf_control_set(drives_fan, speed);
582 static void drives_setup_pid(
void)
585 s32 fmin = wf_control_get_min(drives_fan);
586 s32 fmax = wf_control_get_max(drives_fan);
594 pr_info(
"wf_pm72: Drive bay control loop started.\n");
597 static void set_fail_state(
void)
602 wf_control_set_max(backside_fan);
604 wf_control_set_max(slots_fan);
606 wf_control_set_max(drives_fan);
609 static void pm72_tick(
void)
616 for (i = 0; i < nr_chips; ++
i) {
617 if (cpu_setup_pid(i) < 0) {
625 backside_setup_pid();
634 #ifdef HACKED_OVERTEMP
635 cpu_all_tmax = 60 << 16;
647 last_failure = failure_state;
649 if (cpu_pid_combined)
650 cpu_fans_tick_combined();
652 cpu_fans_tick_split();
656 DBG_LOTS(
" last_failure: 0x%x, failure_state: %x\n",
657 last_failure, failure_state);
660 if (failure_state && last_failure == 0 && cpufreq_clamp)
661 wf_control_set_max(cpufreq_clamp);
662 if (failure_state == 0 && last_failure && cpufreq_clamp)
663 wf_control_set_min(cpufreq_clamp);
673 bool had_pump = cpu_pumps[0] || cpu_pumps[1];
676 cpu_front_fans[0] =
ct;
677 else if (!
strcmp(ct->
name,
"cpu-front-fan-1"))
678 cpu_front_fans[1] =
ct;
680 cpu_rear_fans[0] =
ct;
682 cpu_rear_fans[1] =
ct;
706 have_all_controls = all_controls;
708 if ((cpu_pumps[0] || cpu_pumps[1]) && !had_pump) {
709 pr_info(
"wf_pm72: Liquid cooling pump(s) detected,"
710 " using new algorithm !\n");
711 cpu_pid_combined =
true;
721 sens_cpu_temp[0] =
sr;
722 else if (!
strcmp(sr->
name,
"cpu-diode-temp-1"))
723 sens_cpu_temp[1] =
sr;
725 sens_cpu_volts[0] =
sr;
727 sens_cpu_volts[1] =
sr;
729 sens_cpu_amps[0] =
sr;
731 sens_cpu_amps[1] =
sr;
749 have_all_sensors = all_sensors;
757 pm72_new_sensor(data);
760 pm72_new_control(data);
763 if (have_all_controls && have_all_sensors)
770 .notifier_call = pm72_wf_notify,
788 .probe = wf_pm72_probe,
789 .remove = wf_pm72_remove,
796 static int __init wf_pm72_init(
void)
812 pr_info(
"windfarm: Initializing for desktop G5 with %d chips\n",
816 for (i = 0; i < nr_chips; i++) {
817 cpu_mpu_data[
i] = wf_get_mpu(i);
818 if (!cpu_mpu_data[i]) {
819 pr_err(
"wf_pm72: Failed to find MPU data for CPU %d\n", i);
825 request_module(
"windfarm_fcu_controls");
826 request_module(
"windfarm_lm75_sensor");
827 request_module(
"windfarm_ad7417_sensor");
828 request_module(
"windfarm_max6690_sensor");
829 request_module(
"windfarm_cpufreq_clamp");
836 static void __exit wf_pm72_exit(
void)