aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/windfarm_max6690_sensor.c
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 /drivers/macintosh/windfarm_max6690_sensor.c
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>
Diffstat (limited to 'drivers/macintosh/windfarm_max6690_sensor.c')
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
new file mode 100644
index 000000000000..5b9ad6ca7cba
--- /dev/null
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -0,0 +1,169 @@
1/*
2 * Windfarm PowerMac thermal control. MAX6690 sensor.
3 *
4 * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
5 *
6 * Use and redistribute under the terms of the GNU GPL v2.
7 */
8#include <linux/types.h>
9#include <linux/errno.h>
10#include <linux/kernel.h>
11#include <linux/init.h>
12#include <linux/slab.h>
13#include <linux/i2c.h>
14#include <linux/i2c-dev.h>
15#include <asm/prom.h>
16#include <asm/pmac_low_i2c.h>
17
18#include "windfarm.h"
19
20#define VERSION "0.1"
21
22/* This currently only exports the external temperature sensor,
23 since that's all the control loops need. */
24
25/* Some MAX6690 register numbers */
26#define MAX6690_INTERNAL_TEMP 0
27#define MAX6690_EXTERNAL_TEMP 1
28
29struct wf_6690_sensor {
30 struct i2c_client i2c;
31 struct wf_sensor sens;
32};
33
34#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
35#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)
36
37static int wf_max6690_attach(struct i2c_adapter *adapter);
38static int wf_max6690_detach(struct i2c_client *client);
39
40static struct i2c_driver wf_max6690_driver = {
41 .driver = {
42 .name = "wf_max6690",
43 },
44 .attach_adapter = wf_max6690_attach,
45 .detach_client = wf_max6690_detach,
46};
47
48static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
49{
50 struct wf_6690_sensor *max = wf_to_6690(sr);
51 s32 data;
52
53 if (max->i2c.adapter == NULL)
54 return -ENODEV;
55
56 /* chip gets initialized by firmware */
57 data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
58 if (data < 0)
59 return data;
60 *value = data << 16;
61 return 0;
62}
63
64static void wf_max6690_release(struct wf_sensor *sr)
65{
66 struct wf_6690_sensor *max = wf_to_6690(sr);
67
68 if (max->i2c.adapter) {
69 i2c_detach_client(&max->i2c);
70 max->i2c.adapter = NULL;
71 }
72 kfree(max);
73}
74
75static struct wf_sensor_ops wf_max6690_ops = {
76 .get_value = wf_max6690_get,
77 .release = wf_max6690_release,
78 .owner = THIS_MODULE,
79};
80
81static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
82{
83 struct wf_6690_sensor *max;
84 char *name = "u4-temp";
85
86 max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
87 if (max == NULL) {
88 printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
89 "no memory\n", name);
90 return;
91 }
92
93 max->sens.ops = &wf_max6690_ops;
94 max->sens.name = name;
95 max->i2c.addr = addr >> 1;
96 max->i2c.adapter = adapter;
97 max->i2c.driver = &wf_max6690_driver;
98 strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
99
100 if (i2c_attach_client(&max->i2c)) {
101 printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
102 goto fail;
103 }
104
105 if (wf_register_sensor(&max->sens)) {
106 i2c_detach_client(&max->i2c);
107 goto fail;
108 }
109
110 return;
111
112 fail:
113 kfree(max);
114}
115
116static int wf_max6690_attach(struct i2c_adapter *adapter)
117{
118 struct device_node *busnode, *dev = NULL;
119 struct pmac_i2c_bus *bus;
120 const char *loc;
121 u32 *reg;
122
123 bus = pmac_i2c_adapter_to_bus(adapter);
124 if (bus == NULL)
125 return -ENODEV;
126 busnode = pmac_i2c_get_bus_node(bus);
127
128 while ((dev = of_get_next_child(busnode, dev)) != NULL) {
129 if (!device_is_compatible(dev, "max6690"))
130 continue;
131 loc = get_property(dev, "hwsensor-location", NULL);
132 reg = (u32 *) get_property(dev, "reg", NULL);
133 if (!loc || !reg)
134 continue;
135 printk("found max6690, loc=%s reg=%x\n", loc, *reg);
136 if (strcmp(loc, "BACKSIDE"))
137 continue;
138 wf_max6690_create(adapter, *reg);
139 }
140
141 return 0;
142}
143
144static int wf_max6690_detach(struct i2c_client *client)
145{
146 struct wf_6690_sensor *max = i2c_to_6690(client);
147
148 max->i2c.adapter = NULL;
149 wf_unregister_sensor(&max->sens);
150
151 return 0;
152}
153
154static int __init wf_max6690_sensor_init(void)
155{
156 return i2c_add_driver(&wf_max6690_driver);
157}
158
159static void __exit wf_max6690_sensor_exit(void)
160{
161 i2c_del_driver(&wf_max6690_driver);
162}
163
164module_init(wf_max6690_sensor_init);
165module_exit(wf_max6690_sensor_exit);
166
167MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
168MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
169MODULE_LICENSE("GPL");