aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-29 11:42:27 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-30 01:37:25 -0400
commit6cd3209967469f6e89d329deda6bb0b4700e7b62 (patch)
tree35f099b364bf811b44fa11c7d71eaa7b22d264a1
parenta78a4a03a75466ff859d989a1a00110ebd0165b0 (diff)
powerpc/powermac: New windfarm driver for PowerMac G5 (AGP) and Xserve G5
This replaces the old therm_pm72 using the same windfarm infrastructure that was used for other PowerMac G5 models. The fan speeds and sensors should now be visible in the same location in sysfs. The driver is split into separate core modules for PowerMac7,2 (and 7,3) and RackMac3,1, with a lot of the shared code now in the separate sensor and control modules. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--drivers/macintosh/Kconfig23
-rw-r--r--drivers/macintosh/Makefile14
-rw-r--r--drivers/macintosh/windfarm.h3
-rw-r--r--drivers/macintosh/windfarm_core.c10
-rw-r--r--drivers/macintosh/windfarm_cpufreq_clamp.c6
-rw-r--r--drivers/macintosh/windfarm_fcu_controls.c10
-rw-r--r--drivers/macintosh/windfarm_mpu.h105
-rw-r--r--drivers/macintosh/windfarm_pm72.c847
-rw-r--r--drivers/macintosh/windfarm_rm31.c740
9 files changed, 1736 insertions, 22 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index fa51af11c6f1..a555da64224e 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -204,11 +204,14 @@ config THERM_ADT746X
204 better fan behaviour by default, and some manual control. 204 better fan behaviour by default, and some manual control.
205 205
206config THERM_PM72 206config THERM_PM72
207 tristate "Support for thermal management on PowerMac G5" 207 tristate "Support for thermal management on PowerMac G5 (AGP)"
208 depends on I2C && I2C_POWERMAC && PPC_PMAC64 208 depends on I2C && I2C_POWERMAC && PPC_PMAC64
209 default n
209 help 210 help
210 This driver provides thermostat and fan control for the desktop 211 This driver provides thermostat and fan control for the desktop
211 G5 machines. 212 G5 machines.
213
214 This is deprecated, use windfarm instead.
212 215
213config WINDFARM 216config WINDFARM
214 tristate "New PowerMac thermal control infrastructure" 217 tristate "New PowerMac thermal control infrastructure"
@@ -221,6 +224,22 @@ config WINDFARM_PM81
221 help 224 help
222 This driver provides thermal control for the iMacG5 225 This driver provides thermal control for the iMacG5
223 226
227config WINDFARM_PM72
228 tristate "Support for thermal management on PowerMac G5 (AGP)"
229 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
230 select I2C_POWERMAC
231 help
232 This driver provides thermal control for the PowerMac G5
233 "AGP" variants (PowerMac 7,2 and 7,3)
234
235config WINDFARM_RM31
236 tristate "Support for thermal management on Xserve G5"
237 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
238 select I2C_POWERMAC
239 help
240 This driver provides thermal control for the Xserve G5
241 (RackMac3,1)
242
224config WINDFARM_PM91 243config WINDFARM_PM91
225 tristate "Support for thermal management on PowerMac9,1" 244 tristate "Support for thermal management on PowerMac9,1"
226 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU 245 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6652a6ebb6fa..6753b65f8ede 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -29,6 +29,20 @@ obj-$(CONFIG_THERM_PM72) += therm_pm72.o
29obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o 29obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o
30obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o 30obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o
31obj-$(CONFIG_WINDFARM) += windfarm_core.o 31obj-$(CONFIG_WINDFARM) += windfarm_core.o
32obj-$(CONFIG_WINDFARM_PM72) += windfarm_fcu_controls.o \
33 windfarm_ad7417_sensor.o \
34 windfarm_lm75_sensor.o \
35 windfarm_max6690_sensor.o \
36 windfarm_pid.o \
37 windfarm_cpufreq_clamp.o \
38 windfarm_pm72.o
39obj-$(CONFIG_WINDFARM_RM31) += windfarm_fcu_controls.o \
40 windfarm_ad7417_sensor.o \
41 windfarm_lm75_sensor.o \
42 windfarm_lm87_sensor.o \
43 windfarm_pid.o \
44 windfarm_cpufreq_clamp.o \
45 windfarm_rm31.o
32obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \ 46obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \
33 windfarm_smu_sensors.o \ 47 windfarm_smu_sensors.o \
34 windfarm_lm75_sensor.o windfarm_pid.o \ 48 windfarm_lm75_sensor.o windfarm_pid.o \
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index a9e385ee359e..028cdac2d33d 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -17,7 +17,7 @@
17#include <linux/device.h> 17#include <linux/device.h>
18 18
19/* Display a 16.16 fixed point value */ 19/* Display a 16.16 fixed point value */
20#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) 20#define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16)
21 21
22/* 22/*
23 * Control objects 23 * Control objects
@@ -41,6 +41,7 @@ struct wf_control {
41 int type; 41 int type;
42 struct kref ref; 42 struct kref ref;
43 struct device_attribute attr; 43 struct device_attribute attr;
44 void *priv;
44}; 45};
45 46
46#define WF_CONTROL_TYPE_GENERIC 0 47#define WF_CONTROL_TYPE_GENERIC 0
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index ebafc2543d5f..3ee198b65843 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -169,8 +169,11 @@ static ssize_t wf_show_control(struct device *dev,
169 int err; 169 int err;
170 170
171 err = ctrl->ops->get_value(ctrl, &val); 171 err = ctrl->ops->get_value(ctrl, &val);
172 if (err < 0) 172 if (err < 0) {
173 if (err == -EFAULT)
174 return sprintf(buf, "<HW FAULT>\n");
173 return err; 175 return err;
176 }
174 switch(ctrl->type) { 177 switch(ctrl->type) {
175 case WF_CONTROL_RPM_FAN: 178 case WF_CONTROL_RPM_FAN:
176 typestr = " RPM"; 179 typestr = " RPM";
@@ -481,11 +484,6 @@ static int __init windfarm_core_init(void)
481{ 484{
482 DBG("wf: core loaded\n"); 485 DBG("wf: core loaded\n");
483 486
484 /* Don't register on old machines that use therm_pm72 for now */
485 if (of_machine_is_compatible("PowerMac7,2") ||
486 of_machine_is_compatible("PowerMac7,3") ||
487 of_machine_is_compatible("RackMac3,1"))
488 return -ENODEV;
489 platform_device_register(&wf_platform_device); 487 platform_device_register(&wf_platform_device);
490 return 0; 488 return 0;
491} 489}
diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c
index 1a77a7c97d0e..72d1fdfe02a5 100644
--- a/drivers/macintosh/windfarm_cpufreq_clamp.c
+++ b/drivers/macintosh/windfarm_cpufreq_clamp.c
@@ -75,12 +75,6 @@ static int __init wf_cpufreq_clamp_init(void)
75{ 75{
76 struct wf_control *clamp; 76 struct wf_control *clamp;
77 77
78 /* Don't register on old machines that use therm_pm72 for now */
79 if (of_machine_is_compatible("PowerMac7,2") ||
80 of_machine_is_compatible("PowerMac7,3") ||
81 of_machine_is_compatible("RackMac3,1"))
82 return -ENODEV;
83
84 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); 78 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
85 if (clamp == NULL) 79 if (clamp == NULL)
86 return -ENOMEM; 80 return -ENOMEM;
diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c
index 871f8b4cf367..b3411edb324b 100644
--- a/drivers/macintosh/windfarm_fcu_controls.c
+++ b/drivers/macintosh/windfarm_fcu_controls.c
@@ -41,10 +41,10 @@
41 * applied to the setpoint RPM speed, that is basically the 41 * applied to the setpoint RPM speed, that is basically the
42 * speed we proviously "asked" for. 42 * speed we proviously "asked" for.
43 * 43 *
44 * I'm not sure which of these Apple's algorithm is supposed 44 * I'm using 0 for now which is what therm_pm72 used to do and
45 * to use 45 * what Darwin -apparently- does based on observed behaviour.
46 */ 46 */
47#define RPM_PID_USE_ACTUAL_SPEED 1 47#define RPM_PID_USE_ACTUAL_SPEED 0
48 48
49/* Default min/max for pumps */ 49/* Default min/max for pumps */
50#define CPU_PUMP_OUTPUT_MAX 3200 50#define CPU_PUMP_OUTPUT_MAX 3200
@@ -154,8 +154,6 @@ static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value)
154 if (value > fan->max) 154 if (value > fan->max)
155 value = fan->max; 155 value = fan->max;
156 156
157 if (fan->target && fan->target == value)
158 return 0;
159 fan->target = value; 157 fan->target = value;
160 158
161 buf[0] = value >> (8 - shift); 159 buf[0] = value >> (8 - shift);
@@ -213,8 +211,6 @@ static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value)
213 if (value > fan->max) 211 if (value > fan->max)
214 value = fan->max; 212 value = fan->max;
215 213
216 if (fan->target && fan->target == value)
217 return 0;
218 fan->target = value; 214 fan->target = value;
219 215
220 value = (value * 2559) / 1000; 216 value = (value * 2559) / 1000;
diff --git a/drivers/macintosh/windfarm_mpu.h b/drivers/macintosh/windfarm_mpu.h
new file mode 100644
index 000000000000..046edc8c2ec5
--- /dev/null
+++ b/drivers/macintosh/windfarm_mpu.h
@@ -0,0 +1,105 @@
1/*
2 * Windfarm PowerMac thermal control
3 *
4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
5 *
6 * Released under the term of the GNU GPL v2.
7 */
8
9#ifndef __WINDFARM_MPU_H
10#define __WINDFARM_MPU_H
11
12typedef unsigned short fu16;
13typedef int fs32;
14typedef short fs16;
15
16/* Definition of the MPU data structure which contains per CPU
17 * calibration information (among others) for the G5 machines
18 */
19struct mpu_data
20{
21 u8 signature; /* 0x00 - EEPROM sig. */
22 u8 bytes_used; /* 0x01 - Bytes used in eeprom (160 ?) */
23 u8 size; /* 0x02 - EEPROM size (256 ?) */
24 u8 version; /* 0x03 - EEPROM version */
25 u32 data_revision; /* 0x04 - Dataset revision */
26 u8 processor_bin_code[3]; /* 0x08 - Processor BIN code */
27 u8 bin_code_expansion; /* 0x0b - ??? (padding ?) */
28 u8 processor_num; /* 0x0c - Number of CPUs on this MPU */
29 u8 input_mul_bus_div; /* 0x0d - Clock input multiplier/bus divider */
30 u8 reserved1[2]; /* 0x0e - */
31 u32 input_clk_freq_high; /* 0x10 - Input clock frequency high */
32 u8 cpu_nb_target_cycles; /* 0x14 - ??? */
33 u8 cpu_statlat; /* 0x15 - ??? */
34 u8 cpu_snooplat; /* 0x16 - ??? */
35 u8 cpu_snoopacc; /* 0x17 - ??? */
36 u8 nb_paamwin; /* 0x18 - ??? */
37 u8 nb_statlat; /* 0x19 - ??? */
38 u8 nb_snooplat; /* 0x1a - ??? */
39 u8 nb_snoopwin; /* 0x1b - ??? */
40 u8 api_bus_mode; /* 0x1c - ??? */
41 u8 reserved2[3]; /* 0x1d - */
42 u32 input_clk_freq_low; /* 0x20 - Input clock frequency low */
43 u8 processor_card_slot; /* 0x24 - Processor card slot number */
44 u8 reserved3[2]; /* 0x25 - */
45 u8 padjmax; /* 0x27 - Max power adjustment (Not in OF!) */
46 u8 ttarget; /* 0x28 - Target temperature */
47 u8 tmax; /* 0x29 - Max temperature */
48 u8 pmaxh; /* 0x2a - Max power */
49 u8 tguardband; /* 0x2b - Guardband temp ??? Hist. len in OSX */
50 fs32 pid_gp; /* 0x2c - PID proportional gain */
51 fs32 pid_gr; /* 0x30 - PID reset gain */
52 fs32 pid_gd; /* 0x34 - PID derivative gain */
53 fu16 voph; /* 0x38 - Vop High */
54 fu16 vopl; /* 0x3a - Vop Low */
55 fs16 nactual_die; /* 0x3c - nActual Die */
56 fs16 nactual_heatsink; /* 0x3e - nActual Heatsink */
57 fs16 nactual_system; /* 0x40 - nActual System */
58 u16 calibration_flags; /* 0x42 - Calibration flags */
59 fu16 mdiode; /* 0x44 - Diode M value (scaling factor) */
60 fs16 bdiode; /* 0x46 - Diode B value (offset) */
61 fs32 theta_heat_sink; /* 0x48 - Theta heat sink */
62 u16 rminn_intake_fan; /* 0x4c - Intake fan min RPM */
63 u16 rmaxn_intake_fan; /* 0x4e - Intake fan max RPM */
64 u16 rminn_exhaust_fan; /* 0x50 - Exhaust fan min RPM */
65 u16 rmaxn_exhaust_fan; /* 0x52 - Exhaust fan max RPM */
66 u8 processor_part_num[8]; /* 0x54 - Processor part number XX pumps min/max */
67 u32 processor_lot_num; /* 0x5c - Processor lot number */
68 u8 orig_card_sernum[0x10]; /* 0x60 - Card original serial number */
69 u8 curr_card_sernum[0x10]; /* 0x70 - Card current serial number */
70 u8 mlb_sernum[0x18]; /* 0x80 - MLB serial number */
71 u32 checksum1; /* 0x98 - */
72 u32 checksum2; /* 0x9c - */
73}; /* Total size = 0xa0 */
74
75static inline const struct mpu_data *wf_get_mpu(int cpu)
76{
77 struct device_node *np;
78 char nodename[64];
79 const void *data;
80 int len;
81
82 /*
83 * prom.c routine for finding a node by path is a bit brain dead
84 * and requires exact @xxx unit numbers. This is a bit ugly but
85 * will work for these machines
86 */
87 sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
88 np = of_find_node_by_path(nodename);
89 if (!np)
90 return NULL;
91 data = of_get_property(np, "cpuid", &len);
92 of_node_put(np);
93 if (!data)
94 return NULL;
95
96 /*
97 * We are naughty, we have dropped the reference to the device
98 * node and still return a pointer to the content. We know we
99 * can do that though as this is only ever called on PowerMac
100 * which cannot remove those nodes
101 */
102 return data;
103}
104
105#endif /* __WINDFARM_MPU_H */
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
new file mode 100644
index 000000000000..84ac913d7e3a
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -0,0 +1,847 @@
1/*
2 * Windfarm PowerMac thermal control.
3 * Control loops for PowerMac7,2 and 7,3
4 *
5 * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
6 *
7 * Use and redistribute under the terms of the GNU GPL v2.
8 */
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/platform_device.h>
14#include <linux/reboot.h>
15#include <asm/prom.h>
16#include <asm/smu.h>
17
18#include "windfarm.h"
19#include "windfarm_pid.h"
20#include "windfarm_mpu.h"
21
22#define VERSION "1.0"
23
24#undef DEBUG
25#undef LOTSA_DEBUG
26
27#ifdef DEBUG
28#define DBG(args...) printk(args)
29#else
30#define DBG(args...) do { } while(0)
31#endif
32
33#ifdef LOTSA_DEBUG
34#define DBG_LOTS(args...) printk(args)
35#else
36#define DBG_LOTS(args...) do { } while(0)
37#endif
38
39/* define this to force CPU overtemp to 60 degree, useful for testing
40 * the overtemp code
41 */
42#undef HACKED_OVERTEMP
43
44/* We currently only handle 2 chips */
45#define NR_CHIPS 2
46#define NR_CPU_FANS 3 * NR_CHIPS
47
48/* Controls and sensors */
49static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
50static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
51static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
52static struct wf_sensor *backside_temp;
53static struct wf_sensor *drives_temp;
54
55static struct wf_control *cpu_front_fans[NR_CHIPS];
56static struct wf_control *cpu_rear_fans[NR_CHIPS];
57static struct wf_control *cpu_pumps[NR_CHIPS];
58static struct wf_control *backside_fan;
59static struct wf_control *drives_fan;
60static struct wf_control *slots_fan;
61static struct wf_control *cpufreq_clamp;
62
63/* We keep a temperature history for average calculation of 180s */
64#define CPU_TEMP_HIST_SIZE 180
65
66/* Fixed speed for slot fan */
67#define SLOTS_FAN_DEFAULT_PWM 40
68
69/* Scale value for CPU intake fans */
70#define CPU_INTAKE_SCALE 0x0000f852
71
72/* PID loop state */
73static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
74static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
75static bool cpu_pid_combined;
76static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
77static int cpu_thist_pt;
78static s64 cpu_thist_total;
79static s32 cpu_all_tmax = 100 << 16;
80static struct wf_pid_state backside_pid;
81static int backside_tick;
82static struct wf_pid_state drives_pid;
83static int drives_tick;
84
85static int nr_chips;
86static bool have_all_controls;
87static bool have_all_sensors;
88static bool started;
89
90static int failure_state;
91#define FAILURE_SENSOR 1
92#define FAILURE_FAN 2
93#define FAILURE_PERM 4
94#define FAILURE_LOW_OVERTEMP 8
95#define FAILURE_HIGH_OVERTEMP 16
96
97/* Overtemp values */
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)
104
105
106static void cpu_max_all_fans(void)
107{
108 int i;
109
110 /* We max all CPU fans in case of a sensor error. We also do the
111 * cpufreq clamping now, even if it's supposedly done later by the
112 * generic code anyway, we do it earlier here to react faster
113 */
114 if (cpufreq_clamp)
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]);
121 if (cpu_pumps[i])
122 wf_control_set_max(cpu_pumps[i]);
123 }
124}
125
126static int cpu_check_overtemp(s32 temp)
127{
128 int new_state = 0;
129 s32 t_avg, t_old;
130 static bool first = true;
131
132 /* First check for immediate overtemps */
133 if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
134 new_state |= FAILURE_LOW_OVERTEMP;
135 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
136 printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
137 " temperature !\n");
138 }
139 if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
140 new_state |= FAILURE_HIGH_OVERTEMP;
141 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
142 printk(KERN_ERR "windfarm: Critical overtemp due to"
143 " immediate CPU temperature !\n");
144 }
145
146 /*
147 * The first time around, initialize the array with the first
148 * temperature reading
149 */
150 if (first) {
151 int i;
152
153 cpu_thist_total = 0;
154 for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
155 cpu_thist[i] = temp;
156 cpu_thist_total += temp;
157 }
158 first = false;
159 }
160
161 /*
162 * We calculate a history of max temperatures and use that for the
163 * overtemp management
164 */
165 t_old = cpu_thist[cpu_thist_pt];
166 cpu_thist[cpu_thist_pt] = temp;
167 cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
168 cpu_thist_total -= t_old;
169 cpu_thist_total += temp;
170 t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
171
172 DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
173 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
174
175 /* Now check for average overtemps */
176 if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
177 new_state |= FAILURE_LOW_OVERTEMP;
178 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
179 printk(KERN_ERR "windfarm: Overtemp due to average CPU"
180 " temperature !\n");
181 }
182 if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
183 new_state |= FAILURE_HIGH_OVERTEMP;
184 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
185 printk(KERN_ERR "windfarm: Critical overtemp due to"
186 " average CPU temperature !\n");
187 }
188
189 /* Now handle overtemp conditions. We don't currently use the windfarm
190 * overtemp handling core as it's not fully suited to the needs of those
191 * new machine. This will be fixed later.
192 */
193 if (new_state) {
194 /* High overtemp -> immediate shutdown */
195 if (new_state & FAILURE_HIGH_OVERTEMP)
196 machine_power_off();
197 if ((failure_state & new_state) != new_state)
198 cpu_max_all_fans();
199 failure_state |= new_state;
200 } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
201 (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
202 printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
203 failure_state &= ~FAILURE_LOW_OVERTEMP;
204 }
205
206 return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
207}
208
209static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
210{
211 s32 dtemp, volts, amps;
212 int rc;
213
214 /* Get diode temperature */
215 rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
216 if (rc) {
217 DBG(" CPU%d: temp reading error !\n", cpu);
218 return -EIO;
219 }
220 DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
221 *temp = dtemp;
222
223 /* Get voltage */
224 rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
225 if (rc) {
226 DBG(" CPU%d, volts reading error !\n", cpu);
227 return -EIO;
228 }
229 DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
230
231 /* Get current */
232 rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
233 if (rc) {
234 DBG(" CPU%d, current reading error !\n", cpu);
235 return -EIO;
236 }
237 DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
238
239 /* Calculate power */
240
241 /* Scale voltage and current raw sensor values according to fixed scales
242 * obtained in Darwin and calculate power from I and V
243 */
244 *power = (((u64)volts) * ((u64)amps)) >> 16;
245
246 DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
247
248 return 0;
249
250}
251
252static void cpu_fans_tick_split(void)
253{
254 int err, cpu;
255 s32 intake, temp, power, t_max = 0;
256
257 DBG_LOTS("* cpu fans_tick_split()\n");
258
259 for (cpu = 0; cpu < nr_chips; ++cpu) {
260 struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
261
262 /* Read current speed */
263 wf_control_get(cpu_rear_fans[cpu], &sp->target);
264
265 DBG_LOTS(" CPU%d: cur_target = %d RPM\n", cpu, sp->target);
266
267 err = read_one_cpu_vals(cpu, &temp, &power);
268 if (err) {
269 failure_state |= FAILURE_SENSOR;
270 cpu_max_all_fans();
271 return;
272 }
273
274 /* Keep track of highest temp */
275 t_max = max(t_max, temp);
276
277 /* Handle possible overtemps */
278 if (cpu_check_overtemp(t_max))
279 return;
280
281 /* Run PID */
282 wf_cpu_pid_run(sp, power, temp);
283
284 DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
285
286 /* Apply result directly to exhaust fan */
287 err = wf_control_set(cpu_rear_fans[cpu], sp->target);
288 if (err) {
289 pr_warning("wf_pm72: Fan %s reports error %d\n",
290 cpu_rear_fans[cpu]->name, err);
291 failure_state |= FAILURE_FAN;
292 break;
293 }
294
295 /* Scale result for intake fan */
296 intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
297 DBG_LOTS(" CPU%d: intake = %d RPM\n", cpu, intake);
298 err = wf_control_set(cpu_front_fans[cpu], intake);
299 if (err) {
300 pr_warning("wf_pm72: Fan %s reports error %d\n",
301 cpu_front_fans[cpu]->name, err);
302 failure_state |= FAILURE_FAN;
303 break;
304 }
305 }
306}
307
308static void cpu_fans_tick_combined(void)
309{
310 s32 temp0, power0, temp1, power1, t_max = 0;
311 s32 temp, power, intake, pump;
312 struct wf_control *pump0, *pump1;
313 struct wf_cpu_pid_state *sp = &cpu_pid[0];
314 int err, cpu;
315
316 DBG_LOTS("* cpu fans_tick_combined()\n");
317
318 /* Read current speed from cpu 0 */
319 wf_control_get(cpu_rear_fans[0], &sp->target);
320
321 DBG_LOTS(" CPUs: cur_target = %d RPM\n", sp->target);
322
323 /* Read values for both CPUs */
324 err = read_one_cpu_vals(0, &temp0, &power0);
325 if (err) {
326 failure_state |= FAILURE_SENSOR;
327 cpu_max_all_fans();
328 return;
329 }
330 err = read_one_cpu_vals(1, &temp1, &power1);
331 if (err) {
332 failure_state |= FAILURE_SENSOR;
333 cpu_max_all_fans();
334 return;
335 }
336
337 /* Keep track of highest temp */
338 t_max = max(t_max, max(temp0, temp1));
339
340 /* Handle possible overtemps */
341 if (cpu_check_overtemp(t_max))
342 return;
343
344 /* Use the max temp & power of both */
345 temp = max(temp0, temp1);
346 power = max(power0, power1);
347
348 /* Run PID */
349 wf_cpu_pid_run(sp, power, temp);
350
351 /* Scale result for intake fan */
352 intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
353
354 /* Same deal with pump speed */
355 pump0 = cpu_pumps[0];
356 pump1 = cpu_pumps[1];
357 if (!pump0) {
358 pump0 = pump1;
359 pump1 = NULL;
360 }
361 pump = (sp->target * wf_control_get_max(pump0)) /
362 cpu_mpu_data[0]->rmaxn_exhaust_fan;
363
364 DBG_LOTS(" CPUs: target = %d RPM\n", sp->target);
365 DBG_LOTS(" CPUs: intake = %d RPM\n", intake);
366 DBG_LOTS(" CPUs: pump = %d RPM\n", pump);
367
368 for (cpu = 0; cpu < nr_chips; cpu++) {
369 err = wf_control_set(cpu_rear_fans[cpu], sp->target);
370 if (err) {
371 pr_warning("wf_pm72: Fan %s reports error %d\n",
372 cpu_rear_fans[cpu]->name, err);
373 failure_state |= FAILURE_FAN;
374 }
375 err = wf_control_set(cpu_front_fans[cpu], intake);
376 if (err) {
377 pr_warning("wf_pm72: Fan %s reports error %d\n",
378 cpu_front_fans[cpu]->name, err);
379 failure_state |= FAILURE_FAN;
380 }
381 err = 0;
382 if (cpu_pumps[cpu])
383 err = wf_control_set(cpu_pumps[cpu], pump);
384 if (err) {
385 pr_warning("wf_pm72: Pump %s reports error %d\n",
386 cpu_pumps[cpu]->name, err);
387 failure_state |= FAILURE_FAN;
388 }
389 }
390}
391
392/* Implementation... */
393static int cpu_setup_pid(int cpu)
394{
395 struct wf_cpu_pid_param pid;
396 const struct mpu_data *mpu = cpu_mpu_data[cpu];
397 s32 tmax, ttarget, ptarget;
398 int fmin, fmax, hsize;
399
400 /* Get PID params from the appropriate MPU EEPROM */
401 tmax = mpu->tmax << 16;
402 ttarget = mpu->ttarget << 16;
403 ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
404
405 DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
406 cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
407
408 /* We keep a global tmax for overtemp calculations */
409 if (tmax < cpu_all_tmax)
410 cpu_all_tmax = tmax;
411
412 /* Set PID min/max by using the rear fan min/max */
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);
416
417 /* History size */
418 hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
419 DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
420
421 /* Initialize PID loop */
422 pid.interval = 1; /* seconds */
423 pid.history_len = hsize;
424 pid.gd = mpu->pid_gd;
425 pid.gp = mpu->pid_gp;
426 pid.gr = mpu->pid_gr;
427 pid.tmax = tmax;
428 pid.ttarget = ttarget;
429 pid.pmaxadj = ptarget;
430 pid.min = fmin;
431 pid.max = fmax;
432
433 wf_cpu_pid_init(&cpu_pid[cpu], &pid);
434 cpu_pid[cpu].target = 1000;
435
436 return 0;
437}
438
439/* Backside/U3 fan */
440static struct wf_pid_param backside_u3_param = {
441 .interval = 5,
442 .history_len = 2,
443 .gd = 40 << 20,
444 .gp = 5 << 20,
445 .gr = 0,
446 .itarget = 65 << 16,
447 .additive = 1,
448 .min = 20,
449 .max = 100,
450};
451
452static struct wf_pid_param backside_u3h_param = {
453 .interval = 5,
454 .history_len = 2,
455 .gd = 20 << 20,
456 .gp = 5 << 20,
457 .gr = 0,
458 .itarget = 75 << 16,
459 .additive = 1,
460 .min = 20,
461 .max = 100,
462};
463
464static void backside_fan_tick(void)
465{
466 s32 temp;
467 int speed;
468 int err;
469
470 if (!backside_fan || !backside_temp || !backside_tick)
471 return;
472 if (--backside_tick > 0)
473 return;
474 backside_tick = backside_pid.param.interval;
475
476 DBG_LOTS("* backside fans tick\n");
477
478 /* Update fan speed from actual fans */
479 err = wf_control_get(backside_fan, &speed);
480 if (!err)
481 backside_pid.target = speed;
482
483 err = wf_sensor_get(backside_temp, &temp);
484 if (err) {
485 printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
486 err);
487 failure_state |= FAILURE_SENSOR;
488 wf_control_set_max(backside_fan);
489 return;
490 }
491 speed = wf_pid_run(&backside_pid, temp);
492
493 DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
494 FIX32TOPRINT(temp), speed);
495
496 err = wf_control_set(backside_fan, speed);
497 if (err) {
498 printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
499 failure_state |= FAILURE_FAN;
500 }
501}
502
503static void backside_setup_pid(void)
504{
505 /* first time initialize things */
506 s32 fmin = wf_control_get_min(backside_fan);
507 s32 fmax = wf_control_get_max(backside_fan);
508 struct wf_pid_param param;
509 struct device_node *u3;
510 int u3h = 1; /* conservative by default */
511
512 u3 = of_find_node_by_path("/u3@0,f8000000");
513 if (u3 != NULL) {
514 const u32 *vers = of_get_property(u3, "device-rev", NULL);
515 if (vers)
516 if (((*vers) & 0x3f) < 0x34)
517 u3h = 0;
518 of_node_put(u3);
519 }
520
521 param = u3h ? backside_u3h_param : backside_u3_param;
522
523 param.min = max(param.min, fmin);
524 param.max = min(param.max, fmax);
525 wf_pid_init(&backside_pid, &param);
526 backside_tick = 1;
527
528 pr_info("wf_pm72: Backside control loop started.\n");
529}
530
531/* Drive bay fan */
532static const struct wf_pid_param drives_param = {
533 .interval = 5,
534 .history_len = 2,
535 .gd = 30 << 20,
536 .gp = 5 << 20,
537 .gr = 0,
538 .itarget = 40 << 16,
539 .additive = 1,
540 .min = 300,
541 .max = 4000,
542};
543
544static void drives_fan_tick(void)
545{
546 s32 temp;
547 int speed;
548 int err;
549
550 if (!drives_fan || !drives_temp || !drives_tick)
551 return;
552 if (--drives_tick > 0)
553 return;
554 drives_tick = drives_pid.param.interval;
555
556 DBG_LOTS("* drives fans tick\n");
557
558 /* Update fan speed from actual fans */
559 err = wf_control_get(drives_fan, &speed);
560 if (!err)
561 drives_pid.target = speed;
562
563 err = wf_sensor_get(drives_temp, &temp);
564 if (err) {
565 pr_warning("wf_pm72: drive bay temp sensor error %d\n", err);
566 failure_state |= FAILURE_SENSOR;
567 wf_control_set_max(drives_fan);
568 return;
569 }
570 speed = wf_pid_run(&drives_pid, temp);
571
572 DBG_LOTS("drives PID temp=%d.%.3d speed=%d\n",
573 FIX32TOPRINT(temp), speed);
574
575 err = wf_control_set(drives_fan, speed);
576 if (err) {
577 printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
578 failure_state |= FAILURE_FAN;
579 }
580}
581
582static void drives_setup_pid(void)
583{
584 /* first time initialize things */
585 s32 fmin = wf_control_get_min(drives_fan);
586 s32 fmax = wf_control_get_max(drives_fan);
587 struct wf_pid_param param = drives_param;
588
589 param.min = max(param.min, fmin);
590 param.max = min(param.max, fmax);
591 wf_pid_init(&drives_pid, &param);
592 drives_tick = 1;
593
594 pr_info("wf_pm72: Drive bay control loop started.\n");
595}
596
597static void set_fail_state(void)
598{
599 cpu_max_all_fans();
600
601 if (backside_fan)
602 wf_control_set_max(backside_fan);
603 if (slots_fan)
604 wf_control_set_max(slots_fan);
605 if (drives_fan)
606 wf_control_set_max(drives_fan);
607}
608
609static void pm72_tick(void)
610{
611 int i, last_failure;
612
613 if (!started) {
614 started = 1;
615 printk(KERN_INFO "windfarm: CPUs control loops started.\n");
616 for (i = 0; i < nr_chips; ++i) {
617 if (cpu_setup_pid(i) < 0) {
618 failure_state = FAILURE_PERM;
619 set_fail_state();
620 break;
621 }
622 }
623 DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
624
625 backside_setup_pid();
626 drives_setup_pid();
627
628 /*
629 * We don't have the right stuff to drive the PCI fan
630 * so we fix it to a default value
631 */
632 wf_control_set(slots_fan, SLOTS_FAN_DEFAULT_PWM);
633
634#ifdef HACKED_OVERTEMP
635 cpu_all_tmax = 60 << 16;
636#endif
637 }
638
639 /* Permanent failure, bail out */
640 if (failure_state & FAILURE_PERM)
641 return;
642
643 /*
644 * Clear all failure bits except low overtemp which will be eventually
645 * cleared by the control loop itself
646 */
647 last_failure = failure_state;
648 failure_state &= FAILURE_LOW_OVERTEMP;
649 if (cpu_pid_combined)
650 cpu_fans_tick_combined();
651 else
652 cpu_fans_tick_split();
653 backside_fan_tick();
654 drives_fan_tick();
655
656 DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
657 last_failure, failure_state);
658
659 /* Check for failures. Any failure causes cpufreq clamping */
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);
664
665 /* That's it for now, we might want to deal with other failures
666 * differently in the future though
667 */
668}
669
670static void pm72_new_control(struct wf_control *ct)
671{
672 bool all_controls;
673 bool had_pump = cpu_pumps[0] || cpu_pumps[1];
674
675 if (!strcmp(ct->name, "cpu-front-fan-0"))
676 cpu_front_fans[0] = ct;
677 else if (!strcmp(ct->name, "cpu-front-fan-1"))
678 cpu_front_fans[1] = ct;
679 else if (!strcmp(ct->name, "cpu-rear-fan-0"))
680 cpu_rear_fans[0] = ct;
681 else if (!strcmp(ct->name, "cpu-rear-fan-1"))
682 cpu_rear_fans[1] = ct;
683 else if (!strcmp(ct->name, "cpu-pump-0"))
684 cpu_pumps[0] = ct;
685 else if (!strcmp(ct->name, "cpu-pump-1"))
686 cpu_pumps[1] = ct;
687 else if (!strcmp(ct->name, "backside-fan"))
688 backside_fan = ct;
689 else if (!strcmp(ct->name, "slots-fan"))
690 slots_fan = ct;
691 else if (!strcmp(ct->name, "drive-bay-fan"))
692 drives_fan = ct;
693 else if (!strcmp(ct->name, "cpufreq-clamp"))
694 cpufreq_clamp = ct;
695
696 all_controls =
697 cpu_front_fans[0] &&
698 cpu_rear_fans[0] &&
699 backside_fan &&
700 slots_fan &&
701 drives_fan;
702 if (nr_chips > 1)
703 all_controls &=
704 cpu_front_fans[1] &&
705 cpu_rear_fans[1];
706 have_all_controls = all_controls;
707
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;
712 }
713}
714
715
716static void pm72_new_sensor(struct wf_sensor *sr)
717{
718 bool all_sensors;
719
720 if (!strcmp(sr->name, "cpu-diode-temp-0"))
721 sens_cpu_temp[0] = sr;
722 else if (!strcmp(sr->name, "cpu-diode-temp-1"))
723 sens_cpu_temp[1] = sr;
724 else if (!strcmp(sr->name, "cpu-voltage-0"))
725 sens_cpu_volts[0] = sr;
726 else if (!strcmp(sr->name, "cpu-voltage-1"))
727 sens_cpu_volts[1] = sr;
728 else if (!strcmp(sr->name, "cpu-current-0"))
729 sens_cpu_amps[0] = sr;
730 else if (!strcmp(sr->name, "cpu-current-1"))
731 sens_cpu_amps[1] = sr;
732 else if (!strcmp(sr->name, "backside-temp"))
733 backside_temp = sr;
734 else if (!strcmp(sr->name, "hd-temp"))
735 drives_temp = sr;
736
737 all_sensors =
738 sens_cpu_temp[0] &&
739 sens_cpu_volts[0] &&
740 sens_cpu_amps[0] &&
741 backside_temp &&
742 drives_temp;
743 if (nr_chips > 1)
744 all_sensors &=
745 sens_cpu_temp[1] &&
746 sens_cpu_volts[1] &&
747 sens_cpu_amps[1];
748
749 have_all_sensors = all_sensors;
750}
751
752static int pm72_wf_notify(struct notifier_block *self,
753 unsigned long event, void *data)
754{
755 switch (event) {
756 case WF_EVENT_NEW_SENSOR:
757 pm72_new_sensor(data);
758 break;
759 case WF_EVENT_NEW_CONTROL:
760 pm72_new_control(data);
761 break;
762 case WF_EVENT_TICK:
763 if (have_all_controls && have_all_sensors)
764 pm72_tick();
765 }
766 return 0;
767}
768
769static struct notifier_block pm72_events = {
770 .notifier_call = pm72_wf_notify,
771};
772
773static int wf_pm72_probe(struct platform_device *dev)
774{
775 wf_register_client(&pm72_events);
776 return 0;
777}
778
779static int __devexit wf_pm72_remove(struct platform_device *dev)
780{
781 wf_unregister_client(&pm72_events);
782
783 /* should release all sensors and controls */
784 return 0;
785}
786
787static struct platform_driver wf_pm72_driver = {
788 .probe = wf_pm72_probe,
789 .remove = wf_pm72_remove,
790 .driver = {
791 .name = "windfarm",
792 .owner = THIS_MODULE,
793 },
794};
795
796static int __init wf_pm72_init(void)
797{
798 struct device_node *cpu;
799 int i;
800
801 if (!of_machine_is_compatible("PowerMac7,2") &&
802 !of_machine_is_compatible("PowerMac7,3"))
803 return -ENODEV;
804
805 /* Count the number of CPU cores */
806 nr_chips = 0;
807 for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
808 ++nr_chips;
809 if (nr_chips > NR_CHIPS)
810 nr_chips = NR_CHIPS;
811
812 pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
813 nr_chips);
814
815 /* Get MPU data for each CPU */
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);
820 return -ENXIO;
821 }
822 }
823
824#ifdef MODULE
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");
830#endif /* MODULE */
831
832 platform_driver_register(&wf_pm72_driver);
833 return 0;
834}
835
836static void __exit wf_pm72_exit(void)
837{
838 platform_driver_unregister(&wf_pm72_driver);
839}
840
841module_init(wf_pm72_init);
842module_exit(wf_pm72_exit);
843
844MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
845MODULE_DESCRIPTION("Thermal control for AGP PowerMac G5s");
846MODULE_LICENSE("GPL");
847MODULE_ALIAS("platform:windfarm");
diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c
new file mode 100644
index 000000000000..3eca6d4b52fc
--- /dev/null
+++ b/drivers/macintosh/windfarm_rm31.c
@@ -0,0 +1,740 @@
1/*
2 * Windfarm PowerMac thermal control.
3 * Control loops for RackMack3,1 (Xserve G5)
4 *
5 * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
6 *
7 * Use and redistribute under the terms of the GNU GPL v2.
8 */
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/platform_device.h>
14#include <linux/reboot.h>
15#include <asm/prom.h>
16#include <asm/smu.h>
17
18#include "windfarm.h"
19#include "windfarm_pid.h"
20#include "windfarm_mpu.h"
21
22#define VERSION "1.0"
23
24#undef DEBUG
25#undef LOTSA_DEBUG
26
27#ifdef DEBUG
28#define DBG(args...) printk(args)
29#else
30#define DBG(args...) do { } while(0)
31#endif
32
33#ifdef LOTSA_DEBUG
34#define DBG_LOTS(args...) printk(args)
35#else
36#define DBG_LOTS(args...) do { } while(0)
37#endif
38
39/* define this to force CPU overtemp to 60 degree, useful for testing
40 * the overtemp code
41 */
42#undef HACKED_OVERTEMP
43
44/* We currently only handle 2 chips */
45#define NR_CHIPS 2
46#define NR_CPU_FANS 3 * NR_CHIPS
47
48/* Controls and sensors */
49static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
50static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
51static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
52static struct wf_sensor *backside_temp;
53static struct wf_sensor *slots_temp;
54static struct wf_sensor *dimms_temp;
55
56static struct wf_control *cpu_fans[NR_CHIPS][3];
57static struct wf_control *backside_fan;
58static struct wf_control *slots_fan;
59static struct wf_control *cpufreq_clamp;
60
61/* We keep a temperature history for average calculation of 180s */
62#define CPU_TEMP_HIST_SIZE 180
63
64/* PID loop state */
65static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
66static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
67static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
68static int cpu_thist_pt;
69static s64 cpu_thist_total;
70static s32 cpu_all_tmax = 100 << 16;
71static struct wf_pid_state backside_pid;
72static int backside_tick;
73static struct wf_pid_state slots_pid;
74static int slots_tick;
75static int slots_speed;
76static struct wf_pid_state dimms_pid;
77static int dimms_output_clamp;
78
79static int nr_chips;
80static bool have_all_controls;
81static bool have_all_sensors;
82static bool started;
83
84static int failure_state;
85#define FAILURE_SENSOR 1
86#define FAILURE_FAN 2
87#define FAILURE_PERM 4
88#define FAILURE_LOW_OVERTEMP 8
89#define FAILURE_HIGH_OVERTEMP 16
90
91/* Overtemp values */
92#define LOW_OVER_AVERAGE 0
93#define LOW_OVER_IMMEDIATE (10 << 16)
94#define LOW_OVER_CLEAR ((-10) << 16)
95#define HIGH_OVER_IMMEDIATE (14 << 16)
96#define HIGH_OVER_AVERAGE (10 << 16)
97#define HIGH_OVER_IMMEDIATE (14 << 16)
98
99
100static void cpu_max_all_fans(void)
101{
102 int i;
103
104 /* We max all CPU fans in case of a sensor error. We also do the
105 * cpufreq clamping now, even if it's supposedly done later by the
106 * generic code anyway, we do it earlier here to react faster
107 */
108 if (cpufreq_clamp)
109 wf_control_set_max(cpufreq_clamp);
110 for (i = 0; i < nr_chips; i++) {
111 if (cpu_fans[i][0])
112 wf_control_set_max(cpu_fans[i][0]);
113 if (cpu_fans[i][1])
114 wf_control_set_max(cpu_fans[i][1]);
115 if (cpu_fans[i][2])
116 wf_control_set_max(cpu_fans[i][2]);
117 }
118}
119
120static int cpu_check_overtemp(s32 temp)
121{
122 int new_state = 0;
123 s32 t_avg, t_old;
124 static bool first = true;
125
126 /* First check for immediate overtemps */
127 if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
128 new_state |= FAILURE_LOW_OVERTEMP;
129 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
130 printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
131 " temperature !\n");
132 }
133 if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
134 new_state |= FAILURE_HIGH_OVERTEMP;
135 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
136 printk(KERN_ERR "windfarm: Critical overtemp due to"
137 " immediate CPU temperature !\n");
138 }
139
140 /*
141 * The first time around, initialize the array with the first
142 * temperature reading
143 */
144 if (first) {
145 int i;
146
147 cpu_thist_total = 0;
148 for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
149 cpu_thist[i] = temp;
150 cpu_thist_total += temp;
151 }
152 first = false;
153 }
154
155 /*
156 * We calculate a history of max temperatures and use that for the
157 * overtemp management
158 */
159 t_old = cpu_thist[cpu_thist_pt];
160 cpu_thist[cpu_thist_pt] = temp;
161 cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
162 cpu_thist_total -= t_old;
163 cpu_thist_total += temp;
164 t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
165
166 DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
167 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
168
169 /* Now check for average overtemps */
170 if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
171 new_state |= FAILURE_LOW_OVERTEMP;
172 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
173 printk(KERN_ERR "windfarm: Overtemp due to average CPU"
174 " temperature !\n");
175 }
176 if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
177 new_state |= FAILURE_HIGH_OVERTEMP;
178 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
179 printk(KERN_ERR "windfarm: Critical overtemp due to"
180 " average CPU temperature !\n");
181 }
182
183 /* Now handle overtemp conditions. We don't currently use the windfarm
184 * overtemp handling core as it's not fully suited to the needs of those
185 * new machine. This will be fixed later.
186 */
187 if (new_state) {
188 /* High overtemp -> immediate shutdown */
189 if (new_state & FAILURE_HIGH_OVERTEMP)
190 machine_power_off();
191 if ((failure_state & new_state) != new_state)
192 cpu_max_all_fans();
193 failure_state |= new_state;
194 } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
195 (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
196 printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
197 failure_state &= ~FAILURE_LOW_OVERTEMP;
198 }
199
200 return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
201}
202
203static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
204{
205 s32 dtemp, volts, amps;
206 int rc;
207
208 /* Get diode temperature */
209 rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
210 if (rc) {
211 DBG(" CPU%d: temp reading error !\n", cpu);
212 return -EIO;
213 }
214 DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
215 *temp = dtemp;
216
217 /* Get voltage */
218 rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
219 if (rc) {
220 DBG(" CPU%d, volts reading error !\n", cpu);
221 return -EIO;
222 }
223 DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
224
225 /* Get current */
226 rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
227 if (rc) {
228 DBG(" CPU%d, current reading error !\n", cpu);
229 return -EIO;
230 }
231 DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
232
233 /* Calculate power */
234
235 /* Scale voltage and current raw sensor values according to fixed scales
236 * obtained in Darwin and calculate power from I and V
237 */
238 *power = (((u64)volts) * ((u64)amps)) >> 16;
239
240 DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
241
242 return 0;
243
244}
245
246static void cpu_fans_tick(void)
247{
248 int err, cpu, i;
249 s32 speed, temp, power, t_max = 0;
250
251 DBG_LOTS("* cpu fans_tick_split()\n");
252
253 for (cpu = 0; cpu < nr_chips; ++cpu) {
254 struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
255
256 /* Read current speed */
257 wf_control_get(cpu_fans[cpu][0], &sp->target);
258
259 err = read_one_cpu_vals(cpu, &temp, &power);
260 if (err) {
261 failure_state |= FAILURE_SENSOR;
262 cpu_max_all_fans();
263 return;
264 }
265
266 /* Keep track of highest temp */
267 t_max = max(t_max, temp);
268
269 /* Handle possible overtemps */
270 if (cpu_check_overtemp(t_max))
271 return;
272
273 /* Run PID */
274 wf_cpu_pid_run(sp, power, temp);
275
276 DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
277
278 /* Apply DIMMs clamp */
279 speed = max(sp->target, dimms_output_clamp);
280
281 /* Apply result to all cpu fans */
282 for (i = 0; i < 3; i++) {
283 err = wf_control_set(cpu_fans[cpu][i], speed);
284 if (err) {
285 pr_warning("wf_rm31: Fan %s reports error %d\n",
286 cpu_fans[cpu][i]->name, err);
287 failure_state |= FAILURE_FAN;
288 }
289 }
290 }
291}
292
293/* Implementation... */
294static int cpu_setup_pid(int cpu)
295{
296 struct wf_cpu_pid_param pid;
297 const struct mpu_data *mpu = cpu_mpu_data[cpu];
298 s32 tmax, ttarget, ptarget;
299 int fmin, fmax, hsize;
300
301 /* Get PID params from the appropriate MPU EEPROM */
302 tmax = mpu->tmax << 16;
303 ttarget = mpu->ttarget << 16;
304 ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
305
306 DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
307 cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
308
309 /* We keep a global tmax for overtemp calculations */
310 if (tmax < cpu_all_tmax)
311 cpu_all_tmax = tmax;
312
313 /* Set PID min/max by using the rear fan min/max */
314 fmin = wf_control_get_min(cpu_fans[cpu][0]);
315 fmax = wf_control_get_max(cpu_fans[cpu][0]);
316 DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
317
318 /* History size */
319 hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
320 DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
321
322 /* Initialize PID loop */
323 pid.interval = 1; /* seconds */
324 pid.history_len = hsize;
325 pid.gd = mpu->pid_gd;
326 pid.gp = mpu->pid_gp;
327 pid.gr = mpu->pid_gr;
328 pid.tmax = tmax;
329 pid.ttarget = ttarget;
330 pid.pmaxadj = ptarget;
331 pid.min = fmin;
332 pid.max = fmax;
333
334 wf_cpu_pid_init(&cpu_pid[cpu], &pid);
335 cpu_pid[cpu].target = 4000;
336
337 return 0;
338}
339
340/* Backside/U3 fan */
341static struct wf_pid_param backside_param = {
342 .interval = 1,
343 .history_len = 2,
344 .gd = 0x00500000,
345 .gp = 0x0004cccc,
346 .gr = 0,
347 .itarget = 70 << 16,
348 .additive = 0,
349 .min = 20,
350 .max = 100,
351};
352
353/* DIMMs temperature (clamp the backside fan) */
354static struct wf_pid_param dimms_param = {
355 .interval = 1,
356 .history_len = 20,
357 .gd = 0,
358 .gp = 0,
359 .gr = 0x06553600,
360 .itarget = 50 << 16,
361 .additive = 0,
362 .min = 4000,
363 .max = 14000,
364};
365
366static void backside_fan_tick(void)
367{
368 s32 temp, dtemp;
369 int speed, dspeed, fan_min;
370 int err;
371
372 if (!backside_fan || !backside_temp || !dimms_temp || !backside_tick)
373 return;
374 if (--backside_tick > 0)
375 return;
376 backside_tick = backside_pid.param.interval;
377
378 DBG_LOTS("* backside fans tick\n");
379
380 /* Update fan speed from actual fans */
381 err = wf_control_get(backside_fan, &speed);
382 if (!err)
383 backside_pid.target = speed;
384
385 err = wf_sensor_get(backside_temp, &temp);
386 if (err) {
387 printk(KERN_WARNING "windfarm: U3 temp sensor error %d\n",
388 err);
389 failure_state |= FAILURE_SENSOR;
390 wf_control_set_max(backside_fan);
391 return;
392 }
393 speed = wf_pid_run(&backside_pid, temp);
394
395 DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
396 FIX32TOPRINT(temp), speed);
397
398 err = wf_sensor_get(dimms_temp, &dtemp);
399 if (err) {
400 printk(KERN_WARNING "windfarm: DIMMs temp sensor error %d\n",
401 err);
402 failure_state |= FAILURE_SENSOR;
403 wf_control_set_max(backside_fan);
404 return;
405 }
406 dspeed = wf_pid_run(&dimms_pid, dtemp);
407 dimms_output_clamp = dspeed;
408
409 fan_min = (dspeed * 100) / 14000;
410 fan_min = max(fan_min, backside_param.min);
411 speed = max(speed, fan_min);
412
413 err = wf_control_set(backside_fan, speed);
414 if (err) {
415 printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
416 failure_state |= FAILURE_FAN;
417 }
418}
419
420static void backside_setup_pid(void)
421{
422 /* first time initialize things */
423 s32 fmin = wf_control_get_min(backside_fan);
424 s32 fmax = wf_control_get_max(backside_fan);
425 struct wf_pid_param param;
426
427 param = backside_param;
428 param.min = max(param.min, fmin);
429 param.max = min(param.max, fmax);
430 wf_pid_init(&backside_pid, &param);
431
432 param = dimms_param;
433 wf_pid_init(&dimms_pid, &param);
434
435 backside_tick = 1;
436
437 pr_info("wf_rm31: Backside control loop started.\n");
438}
439
440/* Slots fan */
441static const struct wf_pid_param slots_param = {
442 .interval = 5,
443 .history_len = 2,
444 .gd = 30 << 20,
445 .gp = 5 << 20,
446 .gr = 0,
447 .itarget = 40 << 16,
448 .additive = 1,
449 .min = 300,
450 .max = 4000,
451};
452
453static void slots_fan_tick(void)
454{
455 s32 temp;
456 int speed;
457 int err;
458
459 if (!slots_fan || !slots_temp || !slots_tick)
460 return;
461 if (--slots_tick > 0)
462 return;
463 slots_tick = slots_pid.param.interval;
464
465 DBG_LOTS("* slots fans tick\n");
466
467 err = wf_sensor_get(slots_temp, &temp);
468 if (err) {
469 pr_warning("wf_rm31: slots temp sensor error %d\n", err);
470 failure_state |= FAILURE_SENSOR;
471 wf_control_set_max(slots_fan);
472 return;
473 }
474 speed = wf_pid_run(&slots_pid, temp);
475
476 DBG_LOTS("slots PID temp=%d.%.3d speed=%d\n",
477 FIX32TOPRINT(temp), speed);
478
479 slots_speed = speed;
480 err = wf_control_set(slots_fan, speed);
481 if (err) {
482 printk(KERN_WARNING "windfarm: slots bay fan error %d\n", err);
483 failure_state |= FAILURE_FAN;
484 }
485}
486
487static void slots_setup_pid(void)
488{
489 /* first time initialize things */
490 s32 fmin = wf_control_get_min(slots_fan);
491 s32 fmax = wf_control_get_max(slots_fan);
492 struct wf_pid_param param = slots_param;
493
494 param.min = max(param.min, fmin);
495 param.max = min(param.max, fmax);
496 wf_pid_init(&slots_pid, &param);
497 slots_tick = 1;
498
499 pr_info("wf_rm31: Slots control loop started.\n");
500}
501
502static void set_fail_state(void)
503{
504 cpu_max_all_fans();
505
506 if (backside_fan)
507 wf_control_set_max(backside_fan);
508 if (slots_fan)
509 wf_control_set_max(slots_fan);
510}
511
512static void rm31_tick(void)
513{
514 int i, last_failure;
515
516 if (!started) {
517 started = 1;
518 printk(KERN_INFO "windfarm: CPUs control loops started.\n");
519 for (i = 0; i < nr_chips; ++i) {
520 if (cpu_setup_pid(i) < 0) {
521 failure_state = FAILURE_PERM;
522 set_fail_state();
523 break;
524 }
525 }
526 DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
527
528 backside_setup_pid();
529 slots_setup_pid();
530
531#ifdef HACKED_OVERTEMP
532 cpu_all_tmax = 60 << 16;
533#endif
534 }
535
536 /* Permanent failure, bail out */
537 if (failure_state & FAILURE_PERM)
538 return;
539
540 /*
541 * Clear all failure bits except low overtemp which will be eventually
542 * cleared by the control loop itself
543 */
544 last_failure = failure_state;
545 failure_state &= FAILURE_LOW_OVERTEMP;
546 backside_fan_tick();
547 slots_fan_tick();
548
549 /* We do CPUs last because they can be clamped high by
550 * DIMM temperature
551 */
552 cpu_fans_tick();
553
554 DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
555 last_failure, failure_state);
556
557 /* Check for failures. Any failure causes cpufreq clamping */
558 if (failure_state && last_failure == 0 && cpufreq_clamp)
559 wf_control_set_max(cpufreq_clamp);
560 if (failure_state == 0 && last_failure && cpufreq_clamp)
561 wf_control_set_min(cpufreq_clamp);
562
563 /* That's it for now, we might want to deal with other failures
564 * differently in the future though
565 */
566}
567
568static void rm31_new_control(struct wf_control *ct)
569{
570 bool all_controls;
571
572 if (!strcmp(ct->name, "cpu-fan-a-0"))
573 cpu_fans[0][0] = ct;
574 else if (!strcmp(ct->name, "cpu-fan-b-0"))
575 cpu_fans[0][1] = ct;
576 else if (!strcmp(ct->name, "cpu-fan-c-0"))
577 cpu_fans[0][2] = ct;
578 else if (!strcmp(ct->name, "cpu-fan-a-1"))
579 cpu_fans[1][0] = ct;
580 else if (!strcmp(ct->name, "cpu-fan-b-1"))
581 cpu_fans[1][1] = ct;
582 else if (!strcmp(ct->name, "cpu-fan-c-1"))
583 cpu_fans[1][2] = ct;
584 else if (!strcmp(ct->name, "backside-fan"))
585 backside_fan = ct;
586 else if (!strcmp(ct->name, "slots-fan"))
587 slots_fan = ct;
588 else if (!strcmp(ct->name, "cpufreq-clamp"))
589 cpufreq_clamp = ct;
590
591 all_controls =
592 cpu_fans[0][0] &&
593 cpu_fans[0][1] &&
594 cpu_fans[0][2] &&
595 backside_fan &&
596 slots_fan;
597 if (nr_chips > 1)
598 all_controls &=
599 cpu_fans[1][0] &&
600 cpu_fans[1][1] &&
601 cpu_fans[1][2];
602 have_all_controls = all_controls;
603}
604
605
606static void rm31_new_sensor(struct wf_sensor *sr)
607{
608 bool all_sensors;
609
610 if (!strcmp(sr->name, "cpu-diode-temp-0"))
611 sens_cpu_temp[0] = sr;
612 else if (!strcmp(sr->name, "cpu-diode-temp-1"))
613 sens_cpu_temp[1] = sr;
614 else if (!strcmp(sr->name, "cpu-voltage-0"))
615 sens_cpu_volts[0] = sr;
616 else if (!strcmp(sr->name, "cpu-voltage-1"))
617 sens_cpu_volts[1] = sr;
618 else if (!strcmp(sr->name, "cpu-current-0"))
619 sens_cpu_amps[0] = sr;
620 else if (!strcmp(sr->name, "cpu-current-1"))
621 sens_cpu_amps[1] = sr;
622 else if (!strcmp(sr->name, "backside-temp"))
623 backside_temp = sr;
624 else if (!strcmp(sr->name, "slots-temp"))
625 slots_temp = sr;
626 else if (!strcmp(sr->name, "dimms-temp"))
627 dimms_temp = sr;
628
629 all_sensors =
630 sens_cpu_temp[0] &&
631 sens_cpu_volts[0] &&
632 sens_cpu_amps[0] &&
633 backside_temp &&
634 slots_temp &&
635 dimms_temp;
636 if (nr_chips > 1)
637 all_sensors &=
638 sens_cpu_temp[1] &&
639 sens_cpu_volts[1] &&
640 sens_cpu_amps[1];
641
642 have_all_sensors = all_sensors;
643}
644
645static int rm31_wf_notify(struct notifier_block *self,
646 unsigned long event, void *data)
647{
648 switch (event) {
649 case WF_EVENT_NEW_SENSOR:
650 rm31_new_sensor(data);
651 break;
652 case WF_EVENT_NEW_CONTROL:
653 rm31_new_control(data);
654 break;
655 case WF_EVENT_TICK:
656 if (have_all_controls && have_all_sensors)
657 rm31_tick();
658 }
659 return 0;
660}
661
662static struct notifier_block rm31_events = {
663 .notifier_call = rm31_wf_notify,
664};
665
666static int wf_rm31_probe(struct platform_device *dev)
667{
668 wf_register_client(&rm31_events);
669 return 0;
670}
671
672static int __devexit wf_rm31_remove(struct platform_device *dev)
673{
674 wf_unregister_client(&rm31_events);
675
676 /* should release all sensors and controls */
677 return 0;
678}
679
680static struct platform_driver wf_rm31_driver = {
681 .probe = wf_rm31_probe,
682 .remove = wf_rm31_remove,
683 .driver = {
684 .name = "windfarm",
685 .owner = THIS_MODULE,
686 },
687};
688
689static int __init wf_rm31_init(void)
690{
691 struct device_node *cpu;
692 int i;
693
694 if (!of_machine_is_compatible("RackMac3,1"))
695 return -ENODEV;
696
697 /* Count the number of CPU cores */
698 nr_chips = 0;
699 for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
700 ++nr_chips;
701 if (nr_chips > NR_CHIPS)
702 nr_chips = NR_CHIPS;
703
704 pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
705 nr_chips);
706
707 /* Get MPU data for each CPU */
708 for (i = 0; i < nr_chips; i++) {
709 cpu_mpu_data[i] = wf_get_mpu(i);
710 if (!cpu_mpu_data[i]) {
711 pr_err("wf_rm31: Failed to find MPU data for CPU %d\n", i);
712 return -ENXIO;
713 }
714 }
715
716#ifdef MODULE
717 request_module("windfarm_fcu_controls");
718 request_module("windfarm_lm75_sensor");
719 request_module("windfarm_lm87_sensor");
720 request_module("windfarm_ad7417_sensor");
721 request_module("windfarm_max6690_sensor");
722 request_module("windfarm_cpufreq_clamp");
723#endif /* MODULE */
724
725 platform_driver_register(&wf_rm31_driver);
726 return 0;
727}
728
729static void __exit wf_rm31_exit(void)
730{
731 platform_driver_unregister(&wf_rm31_driver);
732}
733
734module_init(wf_rm31_init);
735module_exit(wf_rm31_exit);
736
737MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
738MODULE_DESCRIPTION("Thermal control for Xserve G5");
739MODULE_LICENSE("GPL");
740MODULE_ALIAS("platform:windfarm");