aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-02-08 00:42:51 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-08 01:05:14 -0500
commitac171c46667c1cb2ee9e22312291df6ed78e1b6e (patch)
tree86ca722abc1ddceb0887b3ed6a195d77bb200dc2
parent746f956beb534ddf73da4346de81f2941c8573f8 (diff)
[PATCH] powerpc: Thermal control for dual core G5s
This patch adds a windfarm module, windfarm_pm112, for the dual core G5s (both 2 and 4 core models), keeping the machine from getting into vacuum-cleaner mode ;) For proper credits, the patch was initially written by Paul Mackerras, and slightly reworked by me to add overtemp handling among others. The patch also removes the sysfs attributes from windfarm_pm81 and windfarm_pm91 and instead adds code to the windfarm core to automagically expose attributes for sensor & controls. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/macintosh/Kconfig8
-rw-r--r--drivers/macintosh/Makefile5
-rw-r--r--drivers/macintosh/windfarm.h3
-rw-r--r--drivers/macintosh/windfarm_core.c69
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c169
-rw-r--r--drivers/macintosh/windfarm_pid.c8
-rw-r--r--drivers/macintosh/windfarm_pid.h1
-rw-r--r--drivers/macintosh/windfarm_pm112.c698
-rw-r--r--drivers/macintosh/windfarm_pm81.c87
-rw-r--r--drivers/macintosh/windfarm_pm91.c95
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c69
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c418
-rw-r--r--drivers/macintosh/windfarm_smu_sensors.c43
-rw-r--r--include/asm-powerpc/smu.h5
14 files changed, 1479 insertions, 199 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 7d4a0ac28c06..b11cd31d8d27 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -187,6 +187,14 @@ config WINDFARM_PM91
187 This driver provides thermal control for the PowerMac9,1 187 This driver provides thermal control for the PowerMac9,1
188 which is the recent (SMU based) single CPU desktop G5 188 which is the recent (SMU based) single CPU desktop G5
189 189
190config WINDFARM_PM112
191 tristate "Support for thermal management on PowerMac11,2"
192 depends on WINDFARM && I2C && PMAC_SMU
193 select I2C_PMAC_SMU
194 help
195 This driver provides thermal control for the PowerMac11,2
196 which are the recent dual and quad G5 machines using the
197 970MP dual-core processor.
190 198
191config ANSLCD 199config ANSLCD
192 tristate "Support for ANS LCD display" 200 tristate "Support for ANS LCD display"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index f4657aa81fb0..6081acdea404 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \
35 windfarm_smu_sensors.o \ 35 windfarm_smu_sensors.o \
36 windfarm_lm75_sensor.o windfarm_pid.o \ 36 windfarm_lm75_sensor.o windfarm_pid.o \
37 windfarm_cpufreq_clamp.o windfarm_pm91.o 37 windfarm_cpufreq_clamp.o windfarm_pm91.o
38obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
39 windfarm_smu_controls.o \
40 windfarm_smu_sensors.o \
41 windfarm_max6690_sensor.o \
42 windfarm_lm75_sensor.o windfarm_pid.o
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 3f0cb0312ea3..7a2482cc26a7 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -14,6 +14,7 @@
14#include <linux/list.h> 14#include <linux/list.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/notifier.h> 16#include <linux/notifier.h>
17#include <linux/device.h>
17 18
18/* Display a 16.16 fixed point value */ 19/* Display a 16.16 fixed point value */
19#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) 20#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
@@ -39,6 +40,7 @@ struct wf_control {
39 char *name; 40 char *name;
40 int type; 41 int type;
41 struct kref ref; 42 struct kref ref;
43 struct device_attribute attr;
42}; 44};
43 45
44#define WF_CONTROL_TYPE_GENERIC 0 46#define WF_CONTROL_TYPE_GENERIC 0
@@ -87,6 +89,7 @@ struct wf_sensor {
87 struct wf_sensor_ops *ops; 89 struct wf_sensor_ops *ops;
88 char *name; 90 char *name;
89 struct kref ref; 91 struct kref ref;
92 struct device_attribute attr;
90}; 93};
91 94
92/* Same lifetime rules as controls */ 95/* Same lifetime rules as controls */
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 32d466441ac2..bb8d5efe19bf 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -56,6 +56,10 @@ static unsigned int wf_overtemp;
56static unsigned int wf_overtemp_counter; 56static unsigned int wf_overtemp_counter;
57struct task_struct *wf_thread; 57struct task_struct *wf_thread;
58 58
59static struct platform_device wf_platform_device = {
60 .name = "windfarm",
61};
62
59/* 63/*
60 * Utilities & tick thread 64 * Utilities & tick thread
61 */ 65 */
@@ -157,6 +161,40 @@ static void wf_control_release(struct kref *kref)
157 kfree(ct); 161 kfree(ct);
158} 162}
159 163
164static ssize_t wf_show_control(struct device *dev,
165 struct device_attribute *attr, char *buf)
166{
167 struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
168 s32 val = 0;
169 int err;
170
171 err = ctrl->ops->get_value(ctrl, &val);
172 if (err < 0)
173 return err;
174 return sprintf(buf, "%d\n", val);
175}
176
177/* This is really only for debugging... */
178static ssize_t wf_store_control(struct device *dev,
179 struct device_attribute *attr,
180 const char *buf, size_t count)
181{
182 struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
183 int val;
184 int err;
185 char *endp;
186
187 val = simple_strtoul(buf, &endp, 0);
188 while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
189 ++endp;
190 if (endp - buf < count)
191 return -EINVAL;
192 err = ctrl->ops->set_value(ctrl, val);
193 if (err < 0)
194 return err;
195 return count;
196}
197
160int wf_register_control(struct wf_control *new_ct) 198int wf_register_control(struct wf_control *new_ct)
161{ 199{
162 struct wf_control *ct; 200 struct wf_control *ct;
@@ -173,6 +211,13 @@ int wf_register_control(struct wf_control *new_ct)
173 kref_init(&new_ct->ref); 211 kref_init(&new_ct->ref);
174 list_add(&new_ct->link, &wf_controls); 212 list_add(&new_ct->link, &wf_controls);
175 213
214 new_ct->attr.attr.name = new_ct->name;
215 new_ct->attr.attr.owner = THIS_MODULE;
216 new_ct->attr.attr.mode = 0644;
217 new_ct->attr.show = wf_show_control;
218 new_ct->attr.store = wf_store_control;
219 device_create_file(&wf_platform_device.dev, &new_ct->attr);
220
176 DBG("wf: Registered control %s\n", new_ct->name); 221 DBG("wf: Registered control %s\n", new_ct->name);
177 222
178 wf_notify(WF_EVENT_NEW_CONTROL, new_ct); 223 wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
@@ -247,6 +292,19 @@ static void wf_sensor_release(struct kref *kref)
247 kfree(sr); 292 kfree(sr);
248} 293}
249 294
295static ssize_t wf_show_sensor(struct device *dev,
296 struct device_attribute *attr, char *buf)
297{
298 struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
299 s32 val = 0;
300 int err;
301
302 err = sens->ops->get_value(sens, &val);
303 if (err < 0)
304 return err;
305 return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
306}
307
250int wf_register_sensor(struct wf_sensor *new_sr) 308int wf_register_sensor(struct wf_sensor *new_sr)
251{ 309{
252 struct wf_sensor *sr; 310 struct wf_sensor *sr;
@@ -263,6 +321,13 @@ int wf_register_sensor(struct wf_sensor *new_sr)
263 kref_init(&new_sr->ref); 321 kref_init(&new_sr->ref);
264 list_add(&new_sr->link, &wf_sensors); 322 list_add(&new_sr->link, &wf_sensors);
265 323
324 new_sr->attr.attr.name = new_sr->name;
325 new_sr->attr.attr.owner = THIS_MODULE;