96 #include <linux/types.h>
97 #include <linux/errno.h>
98 #include <linux/kernel.h>
100 #include <linux/slab.h>
103 #include <linux/wait.h>
105 #include <linux/device.h>
107 #include <asm/prom.h>
108 #include <asm/machdep.h>
110 #include <asm/sections.h>
116 #define VERSION "0.4"
121 #define DBG(args...) printk(args)
123 #define DBG(args...) do { } while(0)
129 #undef HACKED_OVERTEMP
131 static int wf_smu_mach_model;
134 static struct wf_sensor *sensor_cpu_power;
135 static struct wf_sensor *sensor_cpu_temp;
143 static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok, wf_smu_started;
146 #define FAILURE_FAN 0x01
147 #define FAILURE_SENSOR 0x02
148 #define FAILURE_OVERTEMP 0x04
150 static unsigned int wf_smu_failure_state;
151 static int wf_smu_readjust, wf_smu_skipping;
173 #define WF_SMU_SYS_FANS_INTERVAL 5
174 #define WF_SMU_SYS_FANS_HISTORY_SIZE 2
230 #define WF_SMU_SYS_FANS_NUM_CONFIGS ARRAY_SIZE(wf_smu_sys_all_params)
240 #define WF_SMU_CPU_FANS_INTERVAL 1
241 #define WF_SMU_CPU_FANS_MAX_HISTORY 16
242 #define WF_SMU_CPU_FANS_SIBLING_SCALE 0x00001000
243 #define WF_SMU_CPU_FANS_SIBLING_OFFSET 0xfffffb50
264 static void wf_smu_create_sys_fans(
void)
272 if (wf_smu_sys_all_params[i].model_id == wf_smu_mach_model) {
273 param = &wf_smu_sys_all_params[
i];
280 "for this machine model, max fan speed\n");
287 if (wf_smu_sys_fans ==
NULL) {
292 wf_smu_sys_fans->
ticks = 1;
299 pid_param.gd = param->
gd;
300 pid_param.gp = param->
gp;
301 pid_param.gr = param->
gr;
304 pid_param.itarget = param->
itarget;
305 pid_param.min = wf_control_get_min(fan_system);
306 pid_param.max = wf_control_get_max(fan_system);
309 max(pid_param.min, wf_control_get_min(fan_hd));
311 min(pid_param.max, wf_control_get_max(fan_hd));
315 DBG(
"wf: System Fan control initialized.\n");
316 DBG(
" itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
317 FIX32TOPRINT(pid_param.itarget), pid_param.min, pid_param.max);
323 wf_control_set_max(fan_system);
325 wf_control_set_max(fan_hd);
333 if (--st->
ticks != 0) {
340 rc = wf_sensor_get(sensor_hd_temp, &temp);
348 DBG(
"wf_smu: System Fans tick ! HD temp: %d.%03d\n",
351 if (temp > (st->
pid.param.itarget + 0x50000))
356 DBG(
"wf_smu: new_setpoint: %d RPM\n", (
int)new_setpoint);
360 DBG(
"wf_smu: scaled setpoint: %d RPM\n", (
int)
scaled);
362 cputarget = wf_smu_cpu_fans ? wf_smu_cpu_fans->
pid.target : 0;
364 scaled =
max(scaled, cputarget);
365 scaled =
max(scaled, st->
pid.param.min);
366 scaled =
min(scaled, st->
pid.param.max);
368 DBG(
"wf_smu: adjusted setpoint: %d RPM\n", (
int)scaled);
375 if (fan_system && wf_smu_failure_state == 0) {
383 if (fan_hd && wf_smu_failure_state == 0) {
393 static void wf_smu_create_cpu_fans(
void)
399 s32 tmax, tdelta, maxpow, powadj;
423 if (wf_smu_cpu_fans ==
NULL)
425 wf_smu_cpu_fans->
ticks = 1;
438 pid_param.gd = piddata->
gd;
439 pid_param.gp = piddata->
gp;
440 pid_param.gr = piddata->
gr / pid_param.history_len;
446 pid_param.tmax = tmax;
447 pid_param.ttarget = tmax - tdelta;
448 pid_param.pmaxadj = maxpow - powadj;
450 pid_param.min = wf_control_get_min(fan_cpu_main);
451 pid_param.max = wf_control_get_max(fan_cpu_main);
455 DBG(
"wf: CPU Fan control initialized.\n");
456 DBG(
" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n",
458 pid_param.min, pid_param.max);
464 "for this machine model, max fan speed\n");
467 wf_control_set_max(cpufreq_clamp);
469 wf_control_set_max(fan_cpu_main);
474 s32 new_setpoint,
temp, power, systarget;
477 if (--st->
ticks != 0) {
484 rc = wf_sensor_get(sensor_cpu_temp, &temp);
492 rc = wf_sensor_get(sensor_cpu_power, &power);
500 DBG(
"wf_smu: CPU Fans tick ! CPU temp: %d.%03d, power: %d.%03d\n",
503 #ifdef HACKED_OVERTEMP
507 if (temp > st->
pid.param.tmax)
512 DBG(
"wf_smu: new_setpoint: %d RPM\n", (
int)new_setpoint);
514 systarget = wf_smu_sys_fans ? wf_smu_sys_fans->
pid.target : 0;
515 systarget = ((((
s64)systarget) * (
s64)st->
scale) >> 12)
517 new_setpoint =
max(new_setpoint, systarget);
518 new_setpoint =
max(new_setpoint, st->
pid.param.min);
519 new_setpoint =
min(new_setpoint, st->
pid.param.max);
521 DBG(
"wf_smu: adjusted setpoint: %d RPM\n", (
int)new_setpoint);
527 if (fan_cpu_main && wf_smu_failure_state == 0) {
542 static void wf_smu_tick(
void)
544 unsigned int last_failure = wf_smu_failure_state;
545 unsigned int new_failure;
547 if (!wf_smu_started) {
548 DBG(
"wf: creating control loops !\n");
549 wf_smu_create_sys_fans();
550 wf_smu_create_cpu_fans();
555 if (wf_smu_skipping && --wf_smu_skipping)
558 wf_smu_failure_state = 0;
560 wf_smu_sys_fans_tick(wf_smu_sys_fans);
562 wf_smu_cpu_fans_tick(wf_smu_cpu_fans);
565 new_failure = wf_smu_failure_state & ~last_failure;
570 if (wf_smu_failure_state && !last_failure) {
572 wf_control_set_max(cpufreq_clamp);
574 wf_control_set_max(fan_system);
576 wf_control_set_max(fan_cpu_main);
578 wf_control_set_max(fan_hd);
584 if (!wf_smu_failure_state && last_failure) {
586 wf_control_set_min(cpufreq_clamp);
604 if (new_failure == 0 && last_failure & FAILURE_OVERTEMP)
610 if (wf_smu_all_controls_ok)
623 if (cpufreq_clamp ==
NULL && !
strcmp(ct->
name,
"cpufreq-clamp")) {
632 if (wf_smu_mach_model > 3) {
633 if (fan_system && fan_cpu_main && cpufreq_clamp)
634 wf_smu_all_controls_ok = 1;
643 if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp)
644 wf_smu_all_controls_ok = 1;
647 static void wf_smu_new_sensor(
struct wf_sensor *
sr)
649 if (wf_smu_all_sensors_ok)
654 sensor_cpu_power =
sr;
659 sensor_cpu_temp =
sr;
667 if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp)
668 wf_smu_all_sensors_ok = 1;
677 DBG(
"wf: new control %s detected\n",
679 wf_smu_new_control(data);
683 DBG(
"wf: new sensor %s detected\n",
685 wf_smu_new_sensor(data);
688 if (wf_smu_all_controls_ok && wf_smu_all_sensors_ok)
696 .notifier_call = wf_smu_notify,
699 static int wf_init_pm(
void)
740 if (sensor_cpu_power)
758 kfree(wf_smu_sys_fans);
759 kfree(wf_smu_cpu_fans);
765 .probe = wf_smu_probe,
774 static int __init wf_smu_init(
void)
784 request_module(
"windfarm_smu_controls");
785 request_module(
"windfarm_smu_sensors");
786 request_module(
"windfarm_lm75_sensor");
787 request_module(
"windfarm_cpufreq_clamp");
796 static void __exit wf_smu_exit(
void)