204 #include <linux/types.h>
205 #include <linux/errno.h>
206 #include <linux/kernel.h>
208 #include <linux/slab.h>
211 #include <linux/wait.h>
213 #include <linux/device.h>
215 #include <asm/prom.h>
216 #include <asm/machdep.h>
218 #include <asm/sections.h>
224 #define VERSION "0.3"
226 static int pm121_mach_model;
229 static struct wf_sensor *sensor_cpu_power;
230 static struct wf_sensor *sensor_cpu_temp;
231 static struct wf_sensor *sensor_cpu_voltage;
232 static struct wf_sensor *sensor_cpu_current;
233 static struct wf_sensor *sensor_gpu_temp;
234 static struct wf_sensor *sensor_north_bridge_temp;
235 static struct wf_sensor *sensor_hard_drive_temp;
236 static struct wf_sensor *sensor_optical_drive_temp;
237 static struct wf_sensor *sensor_incoming_air_temp;
249 static int pm121_all_controls_ok, pm121_all_sensors_ok, pm121_started;
268 static const char *loop_names[
N_LOOPS] = {
275 #define PM121_NUM_CONFIGS 2
277 static unsigned int pm121_failure_state;
278 static int pm121_readjust, pm121_skipping;
279 static s32 average_power;
290 { .offset = -19563152,
294 { .offset = -15650652,
301 { .offset = -15650652,
305 { .offset = -19563152,
312 { .offset = -25431900,
316 { .offset = -15650652,
333 { .offset = -32768000,
340 { .offset = -32768000,
372 .sensor = &sensor_gpu_temp,
378 .sensor = &sensor_gpu_temp,
387 .sensor = &sensor_hard_drive_temp,
393 .sensor = &sensor_hard_drive_temp,
402 .sensor = &sensor_north_bridge_temp,
408 .sensor = &sensor_north_bridge_temp,
417 .sensor = &sensor_optical_drive_temp,
423 .sensor = &sensor_optical_drive_temp,
432 #define PM121_SYS_GD 0x00000000
433 #define PM121_SYS_GR 0x00019999
434 #define PM121_SYS_HISTORY_SIZE 2
435 #define PM121_SYS_INTERVAL 5
452 #define PM121_CPU_INTERVAL 1
472 static s32 pm121_correct(
s32 new_setpoint,
473 unsigned int control_id,
478 correction = &corrections[control_id][pm121_mach_model - 2];
480 new_min = (average_power * correction->
slope) >> 16;
481 new_min += correction->
offset;
482 new_min = (new_min >> 16) + min;
484 return max3(new_setpoint, new_min, 0);
487 static s32 pm121_connect(
unsigned int control_id,
s32 setpoint)
491 if (pm121_connection->
control_id == control_id) {
492 controls[control_id]->
ops->get_value(controls[control_id],
494 new_min = value * pm121_connection->
correction.slope;
495 new_min += pm121_connection->
correction.offset;
497 new_setpoint =
max(setpoint, (new_min >> 16));
498 if (new_setpoint != setpoint) {
499 pr_debug(
"pm121: %s depending on %s, "
500 "corrected from %d to %d RPM\n",
501 controls[control_id]->
name,
503 (
int) setpoint, (
int) new_setpoint);
506 new_setpoint = setpoint;
510 new_setpoint = setpoint;
516 static void pm121_create_sys_fans(
int loop_id)
525 if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
526 param = &(pm121_sys_all_params[loop_id][
i]);
534 " for this machine model\n",
535 loop_names[loop_id]);
542 pm121_sys_state[loop_id] =
kmalloc(
sizeof(
struct pm121_sys_state),
544 if (pm121_sys_state[loop_id] ==
NULL) {
548 pm121_sys_state[loop_id]->
ticks = 1;
552 pid_param.gp = param->
gp;
556 pid_param.itarget = param->
itarget;
557 pid_param.min = control->
ops->get_min(control);
558 pid_param.max = control->
ops->get_max(control);
562 pr_debug(
"pm121: %s Fan control loop initialized.\n"
563 " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
565 pid_param.min, pid_param.max);
572 "setting \"%s\" to max speed.\n",
573 loop_names[loop_id], control->
name);
576 wf_control_set_max(control);
579 static void pm121_sys_fans_tick(
int loop_id)
582 struct pm121_sys_state *
st;
588 param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
589 st = pm121_sys_state[loop_id];
590 sensor = *(param->
sensor);
593 if (--st->
ticks != 0) {
600 rc = sensor->
ops->get_value(sensor, &temp);
608 pr_debug(
"pm121: %s Fan tick ! %s: %d.%03d\n",
609 loop_names[loop_id], sensor->
name,
615 new_setpoint = pm121_correct(new_setpoint,
619 new_setpoint = pm121_connect(param->
control_id, new_setpoint);
624 pr_debug(
"pm121: %s corrected setpoint: %d RPM\n",
625 control->
name, (
int)new_setpoint);
627 if (control && pm121_failure_state == 0) {
628 rc = control->
ops->set_value(control, st->
setpoint);
639 static void pm121_create_cpu_fans(
void)
646 s32 tmax, tdelta, maxpow, powadj;
669 pm121_cpu_state =
kmalloc(
sizeof(
struct pm121_cpu_state),
671 if (pm121_cpu_state ==
NULL)
673 pm121_cpu_state->
ticks = 1;
683 pid_param.gd = piddata->
gd;
684 pid_param.gp = piddata->
gp;
685 pid_param.gr = piddata->
gr / pid_param.history_len;
691 pid_param.tmax = tmax;
692 pid_param.ttarget = tmax - tdelta;
693 pid_param.pmaxadj = maxpow - powadj;
695 pid_param.min = fan_cpu->
ops->get_min(fan_cpu);
696 pid_param.max = fan_cpu->
ops->get_max(fan_cpu);
700 pr_debug(
"pm121: CPU Fan control initialized.\n");
701 pr_debug(
" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
703 pid_param.min, pid_param.max);
711 wf_control_set_max(controls[CPUFREQ]);
713 wf_control_set_max(fan_cpu);
717 static void pm121_cpu_fans_tick(
struct pm121_cpu_state *st)
723 if (--st->
ticks != 0) {
732 rc = sensor_cpu_temp->
ops->get_value(sensor_cpu_temp, &temp);
740 rc = sensor_cpu_power->
ops->get_value(sensor_cpu_power, &power);
748 pr_debug(
"pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
751 if (temp > st->
pid.param.tmax)
757 new_setpoint = pm121_correct(new_setpoint,
762 new_setpoint = pm121_connect(
FAN_CPU, new_setpoint);
767 pr_debug(
"pm121: CPU corrected setpoint: %d RPM\n", (
int)new_setpoint);
770 if (fan_cpu && pm121_failure_state == 0) {
771 rc = fan_cpu->
ops->set_value(fan_cpu, st->
setpoint);
785 static void pm121_tick(
void)
787 unsigned int last_failure = pm121_failure_state;
788 unsigned int new_failure;
792 if (!pm121_started) {
793 pr_debug(
"pm121: creating control loops !\n");
795 pm121_create_sys_fans(i);
797 pm121_create_cpu_fans();
802 if (pm121_skipping && --pm121_skipping)
807 for (i = 0; i < pm121_cpu_state->
pid.param.history_len; i++)
808 total_power += pm121_cpu_state->
pid.powers[i];
810 average_power = total_power / pm121_cpu_state->
pid.param.history_len;
813 pm121_failure_state = 0;
815 if (pm121_sys_state[i])
816 pm121_sys_fans_tick(i);
820 pm121_cpu_fans_tick(pm121_cpu_state);
823 new_failure = pm121_failure_state & ~last_failure;
828 if (pm121_failure_state && !last_failure) {
831 wf_control_set_max(controls[i]);
838 if (!pm121_failure_state && last_failure) {
839 if (controls[CPUFREQ])
840 wf_control_set_min(controls[CPUFREQ]);
858 if (new_failure == 0 && last_failure & FAILURE_OVERTEMP)
874 static void pm121_new_control(
struct wf_control *ct)
878 if (pm121_all_controls_ok)
881 all = pm121_register_control(ct,
"optical-drive-fan",
FAN_OD) && all;
882 all = pm121_register_control(ct,
"hard-drive-fan",
FAN_HD) && all;
883 all = pm121_register_control(ct,
"cpu-fan",
FAN_CPU) && all;
884 all = pm121_register_control(ct,
"cpufreq-clamp", CPUFREQ) && all;
887 pm121_all_controls_ok = 1;
908 if (pm121_all_sensors_ok)
911 all = pm121_register_sensor(sr,
"cpu-temp",
912 &sensor_cpu_temp) && all;
913 all = pm121_register_sensor(sr,
"cpu-current",
914 &sensor_cpu_current) && all;
915 all = pm121_register_sensor(sr,
"cpu-voltage",
916 &sensor_cpu_voltage) && all;
917 all = pm121_register_sensor(sr,
"cpu-power",
918 &sensor_cpu_power) && all;
919 all = pm121_register_sensor(sr,
"hard-drive-temp",
920 &sensor_hard_drive_temp) && all;
921 all = pm121_register_sensor(sr,
"optical-drive-temp",
922 &sensor_optical_drive_temp) && all;
923 all = pm121_register_sensor(sr,
"incoming-air-temp",
924 &sensor_incoming_air_temp) && all;
925 all = pm121_register_sensor(sr,
"north-bridge-temp",
926 &sensor_north_bridge_temp) && all;
927 all = pm121_register_sensor(sr,
"gpu-temp",
928 &sensor_gpu_temp) && all;
931 pm121_all_sensors_ok = 1;
941 pr_debug(
"pm121: new control %s detected\n",
943 pm121_new_control(data);
946 pr_debug(
"pm121: new sensor %s detected\n",
948 pm121_new_sensor(data);
951 if (pm121_all_controls_ok && pm121_all_sensors_ok)
960 .notifier_call = pm121_notify,
963 static int pm121_init_pm(
void)
974 pm121_connection = &pm121_connections[pm121_mach_model - 2];
976 printk(
KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
997 .probe = pm121_probe,
1006 static int __init pm121_init(
void)
1011 rc = pm121_init_pm();
1014 request_module(
"windfarm_smu_controls");
1015 request_module(
"windfarm_smu_sensors");
1016 request_module(
"windfarm_smu_sat");
1017 request_module(
"windfarm_lm75_sensor");
1018 request_module(
"windfarm_max6690_sensor");
1019 request_module(
"windfarm_cpufreq_clamp");
1026 static void __exit pm121_exit(
void)