diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-02-08 00:42:51 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-08 01:05:14 -0500 |
| commit | ac171c46667c1cb2ee9e22312291df6ed78e1b6e (patch) | |
| tree | 86ca722abc1ddceb0887b3ed6a195d77bb200dc2 | |
| parent | 746f956beb534ddf73da4346de81f2941c8573f8 (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/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/macintosh/Makefile | 5 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm.h | 3 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_core.c | 69 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_max6690_sensor.c | 169 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_pid.c | 8 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_pid.h | 1 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_pm112.c | 698 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_pm81.c | 87 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_pm91.c | 95 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_smu_controls.c | 69 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_smu_sat.c | 418 | ||||
| -rw-r--r-- | drivers/macintosh/windfarm_smu_sensors.c | 43 | ||||
| -rw-r--r-- | include/asm-powerpc/smu.h | 5 |
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 | ||
| 190 | config 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 | ||
| 191 | config ANSLCD | 199 | config 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 |
| 38 | obj-$(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; | |||
| 56 | static unsigned int wf_overtemp_counter; | 56 | static unsigned int wf_overtemp_counter; |
| 57 | struct task_struct *wf_thread; | 57 | struct task_struct *wf_thread; |
| 58 | 58 | ||
| 59 | static 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 | ||
| 164 | static 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... */ | ||
| 178 | static 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 | |||
| 160 | int wf_register_control(struct wf_control *new_ct) | 198 | int 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 | ||
| 295 | static 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 | |||
| 250 | int wf_register_sensor(struct wf_sensor *new_sr) | 308 | int 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; | ||
