Commit a05afe9146f7611d40a58be34ee8442727a6af1f
Committed by
Paul Mackerras
1 parent
e8ff0646e5
Exists in
master
and in
7 other branches
[POWERPC] Comment out a currently unused function
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Showing 1 changed file with 2 additions and 0 deletions Inline Diff
drivers/macintosh/windfarm_smu_sat.c
1 | /* | 1 | /* |
2 | * Windfarm PowerMac thermal control. SMU "satellite" controller sensors. | 2 | * Windfarm PowerMac thermal control. SMU "satellite" controller sensors. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> | 4 | * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> |
5 | * | 5 | * |
6 | * Released under the terms of the GNU GPL v2. | 6 | * Released under the terms of the GNU GPL v2. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
16 | #include <asm/semaphore.h> | 16 | #include <asm/semaphore.h> |
17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
18 | #include <asm/smu.h> | 18 | #include <asm/smu.h> |
19 | #include <asm/pmac_low_i2c.h> | 19 | #include <asm/pmac_low_i2c.h> |
20 | 20 | ||
21 | #include "windfarm.h" | 21 | #include "windfarm.h" |
22 | 22 | ||
23 | #define VERSION "0.2" | 23 | #define VERSION "0.2" |
24 | 24 | ||
25 | #define DEBUG | 25 | #define DEBUG |
26 | 26 | ||
27 | #ifdef DEBUG | 27 | #ifdef DEBUG |
28 | #define DBG(args...) printk(args) | 28 | #define DBG(args...) printk(args) |
29 | #else | 29 | #else |
30 | #define DBG(args...) do { } while(0) | 30 | #define DBG(args...) do { } while(0) |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | /* If the cache is older than 800ms we'll refetch it */ | 33 | /* If the cache is older than 800ms we'll refetch it */ |
34 | #define MAX_AGE msecs_to_jiffies(800) | 34 | #define MAX_AGE msecs_to_jiffies(800) |
35 | 35 | ||
36 | struct wf_sat { | 36 | struct wf_sat { |
37 | int nr; | 37 | int nr; |
38 | atomic_t refcnt; | 38 | atomic_t refcnt; |
39 | struct semaphore mutex; | 39 | struct semaphore mutex; |
40 | unsigned long last_read; /* jiffies when cache last updated */ | 40 | unsigned long last_read; /* jiffies when cache last updated */ |
41 | u8 cache[16]; | 41 | u8 cache[16]; |
42 | struct i2c_client i2c; | 42 | struct i2c_client i2c; |
43 | struct device_node *node; | 43 | struct device_node *node; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct wf_sat *sats[2]; | 46 | static struct wf_sat *sats[2]; |
47 | 47 | ||
48 | struct wf_sat_sensor { | 48 | struct wf_sat_sensor { |
49 | int index; | 49 | int index; |
50 | int index2; /* used for power sensors */ | 50 | int index2; /* used for power sensors */ |
51 | int shift; | 51 | int shift; |
52 | struct wf_sat *sat; | 52 | struct wf_sat *sat; |
53 | struct wf_sensor sens; | 53 | struct wf_sensor sens; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) | 56 | #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) |
57 | #define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) | 57 | #define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) |
58 | 58 | ||
59 | static int wf_sat_attach(struct i2c_adapter *adapter); | 59 | static int wf_sat_attach(struct i2c_adapter *adapter); |
60 | static int wf_sat_detach(struct i2c_client *client); | 60 | static int wf_sat_detach(struct i2c_client *client); |
61 | 61 | ||
62 | static struct i2c_driver wf_sat_driver = { | 62 | static struct i2c_driver wf_sat_driver = { |
63 | .driver = { | 63 | .driver = { |
64 | .name = "wf_smu_sat", | 64 | .name = "wf_smu_sat", |
65 | }, | 65 | }, |
66 | .attach_adapter = wf_sat_attach, | 66 | .attach_adapter = wf_sat_attach, |
67 | .detach_client = wf_sat_detach, | 67 | .detach_client = wf_sat_detach, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | 70 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, |
71 | unsigned int *size) | 71 | unsigned int *size) |
72 | { | 72 | { |
73 | struct wf_sat *sat; | 73 | struct wf_sat *sat; |
74 | int err; | 74 | int err; |
75 | unsigned int i, len; | 75 | unsigned int i, len; |
76 | u8 *buf; | 76 | u8 *buf; |
77 | u8 data[4]; | 77 | u8 data[4]; |
78 | 78 | ||
79 | /* TODO: Add the resulting partition to the device-tree */ | 79 | /* TODO: Add the resulting partition to the device-tree */ |
80 | 80 | ||
81 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) | 81 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) |
82 | return NULL; | 82 | return NULL; |
83 | 83 | ||
84 | err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); | 84 | err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); |
85 | if (err) { | 85 | if (err) { |
86 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); | 86 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); |
87 | return NULL; | 87 | return NULL; |
88 | } | 88 | } |
89 | 89 | ||
90 | len = i2c_smbus_read_word_data(&sat->i2c, 9); | 90 | len = i2c_smbus_read_word_data(&sat->i2c, 9); |
91 | if (len < 0) { | 91 | if (len < 0) { |
92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); | 92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); |
93 | return NULL; | 93 | return NULL; |
94 | } | 94 | } |
95 | if (len == 0) { | 95 | if (len == 0) { |
96 | printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); | 96 | printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); |
97 | return NULL; | 97 | return NULL; |
98 | } | 98 | } |
99 | 99 | ||
100 | len = le16_to_cpu(len); | 100 | len = le16_to_cpu(len); |
101 | len = (len + 3) & ~3; | 101 | len = (len + 3) & ~3; |
102 | buf = kmalloc(len, GFP_KERNEL); | 102 | buf = kmalloc(len, GFP_KERNEL); |
103 | if (buf == NULL) | 103 | if (buf == NULL) |
104 | return NULL; | 104 | return NULL; |
105 | 105 | ||
106 | for (i = 0; i < len; i += 4) { | 106 | for (i = 0; i < len; i += 4) { |
107 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); | 107 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); |
108 | if (err < 0) { | 108 | if (err < 0) { |
109 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", | 109 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", |
110 | err); | 110 | err); |
111 | goto fail; | 111 | goto fail; |
112 | } | 112 | } |
113 | buf[i] = data[1]; | 113 | buf[i] = data[1]; |
114 | buf[i+1] = data[0]; | 114 | buf[i+1] = data[0]; |
115 | buf[i+2] = data[3]; | 115 | buf[i+2] = data[3]; |
116 | buf[i+3] = data[2]; | 116 | buf[i+3] = data[2]; |
117 | } | 117 | } |
118 | #ifdef DEBUG | 118 | #ifdef DEBUG |
119 | DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id); | 119 | DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id); |
120 | for (i = 0; i < len; ++i) | 120 | for (i = 0; i < len; ++i) |
121 | DBG(" %x", buf[i]); | 121 | DBG(" %x", buf[i]); |
122 | DBG("\n"); | 122 | DBG("\n"); |
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | if (size) | 125 | if (size) |
126 | *size = len; | 126 | *size = len; |
127 | return (struct smu_sdbp_header *) buf; | 127 | return (struct smu_sdbp_header *) buf; |
128 | 128 | ||
129 | fail: | 129 | fail: |
130 | kfree(buf); | 130 | kfree(buf); |
131 | return NULL; | 131 | return NULL; |
132 | } | 132 | } |
133 | EXPORT_SYMBOL_GPL(smu_sat_get_sdb_partition); | 133 | EXPORT_SYMBOL_GPL(smu_sat_get_sdb_partition); |
134 | 134 | ||
135 | /* refresh the cache */ | 135 | /* refresh the cache */ |
136 | static int wf_sat_read_cache(struct wf_sat *sat) | 136 | static int wf_sat_read_cache(struct wf_sat *sat) |
137 | { | 137 | { |
138 | int err; | 138 | int err; |
139 | 139 | ||
140 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); | 140 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); |
141 | if (err < 0) | 141 | if (err < 0) |
142 | return err; | 142 | return err; |
143 | sat->last_read = jiffies; | 143 | sat->last_read = jiffies; |
144 | #ifdef LOTSA_DEBUG | 144 | #ifdef LOTSA_DEBUG |
145 | { | 145 | { |
146 | int i; | 146 | int i; |
147 | DBG(KERN_DEBUG "wf_sat_get: data is"); | 147 | DBG(KERN_DEBUG "wf_sat_get: data is"); |
148 | for (i = 0; i < 16; ++i) | 148 | for (i = 0; i < 16; ++i) |
149 | DBG(" %.2x", sat->cache[i]); | 149 | DBG(" %.2x", sat->cache[i]); |
150 | DBG("\n"); | 150 | DBG("\n"); |
151 | } | 151 | } |
152 | #endif | 152 | #endif |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static int wf_sat_get(struct wf_sensor *sr, s32 *value) | 156 | static int wf_sat_get(struct wf_sensor *sr, s32 *value) |
157 | { | 157 | { |
158 | struct wf_sat_sensor *sens = wf_to_sat(sr); | 158 | struct wf_sat_sensor *sens = wf_to_sat(sr); |
159 | struct wf_sat *sat = sens->sat; | 159 | struct wf_sat *sat = sens->sat; |
160 | int i, err; | 160 | int i, err; |
161 | s32 val; | 161 | s32 val; |
162 | 162 | ||
163 | if (sat->i2c.adapter == NULL) | 163 | if (sat->i2c.adapter == NULL) |
164 | return -ENODEV; | 164 | return -ENODEV; |
165 | 165 | ||
166 | down(&sat->mutex); | 166 | down(&sat->mutex); |
167 | if (time_after(jiffies, (sat->last_read + MAX_AGE))) { | 167 | if (time_after(jiffies, (sat->last_read + MAX_AGE))) { |
168 | err = wf_sat_read_cache(sat); | 168 | err = wf_sat_read_cache(sat); |
169 | if (err) | 169 | if (err) |
170 | goto fail; | 170 | goto fail; |
171 | } | 171 | } |
172 | 172 | ||
173 | i = sens->index * 2; | 173 | i = sens->index * 2; |
174 | val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift; | 174 | val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift; |
175 | if (sens->index2 >= 0) { | 175 | if (sens->index2 >= 0) { |
176 | i = sens->index2 * 2; | 176 | i = sens->index2 * 2; |
177 | /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */ | 177 | /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */ |
178 | val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4; | 178 | val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4; |
179 | } | 179 | } |
180 | 180 | ||
181 | *value = val; | 181 | *value = val; |
182 | err = 0; | 182 | err = 0; |
183 | 183 | ||
184 | fail: | 184 | fail: |
185 | up(&sat->mutex); | 185 | up(&sat->mutex); |
186 | return err; | 186 | return err; |
187 | } | 187 | } |
188 | 188 | ||
189 | static void wf_sat_release(struct wf_sensor *sr) | 189 | static void wf_sat_release(struct wf_sensor *sr) |
190 | { | 190 | { |
191 | struct wf_sat_sensor *sens = wf_to_sat(sr); | 191 | struct wf_sat_sensor *sens = wf_to_sat(sr); |
192 | struct wf_sat *sat = sens->sat; | 192 | struct wf_sat *sat = sens->sat; |
193 | 193 | ||
194 | if (atomic_dec_and_test(&sat->refcnt)) { | 194 | if (atomic_dec_and_test(&sat->refcnt)) { |
195 | if (sat->i2c.adapter) { | 195 | if (sat->i2c.adapter) { |
196 | i2c_detach_client(&sat->i2c); | 196 | i2c_detach_client(&sat->i2c); |
197 | sat->i2c.adapter = NULL; | 197 | sat->i2c.adapter = NULL; |
198 | } | 198 | } |
199 | if (sat->nr >= 0) | 199 | if (sat->nr >= 0) |
200 | sats[sat->nr] = NULL; | 200 | sats[sat->nr] = NULL; |
201 | kfree(sat); | 201 | kfree(sat); |
202 | } | 202 | } |
203 | kfree(sens); | 203 | kfree(sens); |
204 | } | 204 | } |
205 | 205 | ||
206 | static struct wf_sensor_ops wf_sat_ops = { | 206 | static struct wf_sensor_ops wf_sat_ops = { |
207 | .get_value = wf_sat_get, | 207 | .get_value = wf_sat_get, |
208 | .release = wf_sat_release, | 208 | .release = wf_sat_release, |
209 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
210 | }; | 210 | }; |
211 | 211 | ||
212 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | 212 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) |
213 | { | 213 | { |
214 | struct wf_sat *sat; | 214 | struct wf_sat *sat; |
215 | struct wf_sat_sensor *sens; | 215 | struct wf_sat_sensor *sens; |
216 | const u32 *reg; | 216 | const u32 *reg; |
217 | const char *loc, *type; | 217 | const char *loc, *type; |
218 | u8 addr, chip, core; | 218 | u8 addr, chip, core; |
219 | struct device_node *child; | 219 | struct device_node *child; |
220 | int shift, cpu, index; | 220 | int shift, cpu, index; |
221 | char *name; | 221 | char *name; |
222 | int vsens[2], isens[2]; | 222 | int vsens[2], isens[2]; |
223 | 223 | ||
224 | reg = of_get_property(dev, "reg", NULL); | 224 | reg = of_get_property(dev, "reg", NULL); |
225 | if (reg == NULL) | 225 | if (reg == NULL) |
226 | return; | 226 | return; |
227 | addr = *reg; | 227 | addr = *reg; |
228 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | 228 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); |
229 | 229 | ||
230 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); | 230 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); |
231 | if (sat == NULL) | 231 | if (sat == NULL) |
232 | return; | 232 | return; |
233 | sat->nr = -1; | 233 | sat->nr = -1; |
234 | sat->node = of_node_get(dev); | 234 | sat->node = of_node_get(dev); |
235 | atomic_set(&sat->refcnt, 0); | 235 | atomic_set(&sat->refcnt, 0); |
236 | init_MUTEX(&sat->mutex); | 236 | init_MUTEX(&sat->mutex); |
237 | sat->i2c.addr = (addr >> 1) & 0x7f; | 237 | sat->i2c.addr = (addr >> 1) & 0x7f; |
238 | sat->i2c.adapter = adapter; | 238 | sat->i2c.adapter = adapter; |
239 | sat->i2c.driver = &wf_sat_driver; | 239 | sat->i2c.driver = &wf_sat_driver; |
240 | strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); | 240 | strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); |
241 | 241 | ||
242 | if (i2c_attach_client(&sat->i2c)) { | 242 | if (i2c_attach_client(&sat->i2c)) { |
243 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | 243 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); |
244 | goto fail; | 244 | goto fail; |
245 | } | 245 | } |
246 | 246 | ||
247 | vsens[0] = vsens[1] = -1; | 247 | vsens[0] = vsens[1] = -1; |
248 | isens[0] = isens[1] = -1; | 248 | isens[0] = isens[1] = -1; |
249 | child = NULL; | 249 | child = NULL; |
250 | while ((child = of_get_next_child(dev, child)) != NULL) { | 250 | while ((child = of_get_next_child(dev, child)) != NULL) { |
251 | reg = of_get_property(child, "reg", NULL); | 251 | reg = of_get_property(child, "reg", NULL); |
252 | type = of_get_property(child, "device_type", NULL); | 252 | type = of_get_property(child, "device_type", NULL); |
253 | loc = of_get_property(child, "location", NULL); | 253 | loc = of_get_property(child, "location", NULL); |
254 | if (reg == NULL || loc == NULL) | 254 | if (reg == NULL || loc == NULL) |
255 | continue; | 255 | continue; |
256 | 256 | ||
257 | /* the cooked sensors are between 0x30 and 0x37 */ | 257 | /* the cooked sensors are between 0x30 and 0x37 */ |
258 | if (*reg < 0x30 || *reg > 0x37) | 258 | if (*reg < 0x30 || *reg > 0x37) |
259 | continue; | 259 | continue; |
260 | index = *reg - 0x30; | 260 | index = *reg - 0x30; |
261 | 261 | ||
262 | /* expect location to be CPU [AB][01] ... */ | 262 | /* expect location to be CPU [AB][01] ... */ |
263 | if (strncmp(loc, "CPU ", 4) != 0) | 263 | if (strncmp(loc, "CPU ", 4) != 0) |
264 | continue; | 264 | continue; |
265 | chip = loc[4] - 'A'; | 265 | chip = loc[4] - 'A'; |
266 | core = loc[5] - '0'; | 266 | core = loc[5] - '0'; |
267 | if (chip > 1 || core > 1) { | 267 | if (chip > 1 || core > 1) { |
268 | printk(KERN_ERR "wf_sat_create: don't understand " | 268 | printk(KERN_ERR "wf_sat_create: don't understand " |
269 | "location %s for %s\n", loc, child->full_name); | 269 | "location %s for %s\n", loc, child->full_name); |
270 | continue; | 270 | continue; |
271 | } | 271 | } |
272 | cpu = 2 * chip + core; | 272 | cpu = 2 * chip + core; |
273 | if (sat->nr < 0) | 273 | if (sat->nr < 0) |
274 | sat->nr = chip; | 274 | sat->nr = chip; |
275 | else if (sat->nr != chip) { | 275 | else if (sat->nr != chip) { |
276 | printk(KERN_ERR "wf_sat_create: can't cope with " | 276 | printk(KERN_ERR "wf_sat_create: can't cope with " |
277 | "multiple CPU chips on one SAT (%s)\n", loc); | 277 | "multiple CPU chips on one SAT (%s)\n", loc); |
278 | continue; | 278 | continue; |
279 | } | 279 | } |
280 | 280 | ||
281 | if (strcmp(type, "voltage-sensor") == 0) { | 281 | if (strcmp(type, "voltage-sensor") == 0) { |
282 | name = "cpu-voltage"; | 282 | name = "cpu-voltage"; |
283 | shift = 4; | 283 | shift = 4; |
284 | vsens[core] = index; | 284 | vsens[core] = index; |
285 | } else if (strcmp(type, "current-sensor") == 0) { | 285 | } else if (strcmp(type, "current-sensor") == 0) { |
286 | name = "cpu-current"; | 286 | name = "cpu-current"; |
287 | shift = 8; | 287 | shift = 8; |
288 | isens[core] = index; | 288 | isens[core] = index; |
289 | } else if (strcmp(type, "temp-sensor") == 0) { | 289 | } else if (strcmp(type, "temp-sensor") == 0) { |
290 | name = "cpu-temp"; | 290 | name = "cpu-temp"; |
291 | shift = 10; | 291 | shift = 10; |
292 | } else | 292 | } else |
293 | continue; /* hmmm shouldn't happen */ | 293 | continue; /* hmmm shouldn't happen */ |
294 | 294 | ||
295 | /* the +16 is enough for "cpu-voltage-n" */ | 295 | /* the +16 is enough for "cpu-voltage-n" */ |
296 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); | 296 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); |
297 | if (sens == NULL) { | 297 | if (sens == NULL) { |
298 | printk(KERN_ERR "wf_sat_create: couldn't create " | 298 | printk(KERN_ERR "wf_sat_create: couldn't create " |
299 | "%s sensor %d (no memory)\n", name, cpu); | 299 | "%s sensor %d (no memory)\n", name, cpu); |
300 | continue; | 300 | continue; |
301 | } | 301 | } |
302 | sens->index = index; | 302 | sens->index = index; |
303 | sens->index2 = -1; | 303 | sens->index2 = -1; |
304 | sens->shift = shift; | 304 | sens->shift = shift; |
305 | sens->sat = sat; | 305 | sens->sat = sat; |
306 | atomic_inc(&sat->refcnt); | 306 | atomic_inc(&sat->refcnt); |
307 | sens->sens.ops = &wf_sat_ops; | 307 | sens->sens.ops = &wf_sat_ops; |
308 | sens->sens.name = (char *) (sens + 1); | 308 | sens->sens.name = (char *) (sens + 1); |
309 | snprintf(sens->sens.name, 16, "%s-%d", name, cpu); | 309 | snprintf(sens->sens.name, 16, "%s-%d", name, cpu); |
310 | 310 | ||
311 | if (wf_register_sensor(&sens->sens)) { | 311 | if (wf_register_sensor(&sens->sens)) { |
312 | atomic_dec(&sat->refcnt); | 312 | atomic_dec(&sat->refcnt); |
313 | kfree(sens); | 313 | kfree(sens); |
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | /* make the power sensors */ | 317 | /* make the power sensors */ |
318 | for (core = 0; core < 2; ++core) { | 318 | for (core = 0; core < 2; ++core) { |
319 | if (vsens[core] < 0 || isens[core] < 0) | 319 | if (vsens[core] < 0 || isens[core] < 0) |
320 | continue; | 320 | continue; |
321 | cpu = 2 * sat->nr + core; | 321 | cpu = 2 * sat->nr + core; |
322 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); | 322 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); |
323 | if (sens == NULL) { | 323 | if (sens == NULL) { |
324 | printk(KERN_ERR "wf_sat_create: couldn't create power " | 324 | printk(KERN_ERR "wf_sat_create: couldn't create power " |
325 | "sensor %d (no memory)\n", cpu); | 325 | "sensor %d (no memory)\n", cpu); |
326 | continue; | 326 | continue; |
327 | } | 327 | } |
328 | sens->index = vsens[core]; | 328 | sens->index = vsens[core]; |
329 | sens->index2 = isens[core]; | 329 | sens->index2 = isens[core]; |
330 | sens->shift = 0; | 330 | sens->shift = 0; |
331 | sens->sat = sat; | 331 | sens->sat = sat; |
332 | atomic_inc(&sat->refcnt); | 332 | atomic_inc(&sat->refcnt); |
333 | sens->sens.ops = &wf_sat_ops; | 333 | sens->sens.ops = &wf_sat_ops; |
334 | sens->sens.name = (char *) (sens + 1); | 334 | sens->sens.name = (char *) (sens + 1); |
335 | snprintf(sens->sens.name, 16, "cpu-power-%d", cpu); | 335 | snprintf(sens->sens.name, 16, "cpu-power-%d", cpu); |
336 | 336 | ||
337 | if (wf_register_sensor(&sens->sens)) { | 337 | if (wf_register_sensor(&sens->sens)) { |
338 | atomic_dec(&sat->refcnt); | 338 | atomic_dec(&sat->refcnt); |
339 | kfree(sens); | 339 | kfree(sens); |
340 | } | 340 | } |
341 | } | 341 | } |
342 | 342 | ||
343 | if (sat->nr >= 0) | 343 | if (sat->nr >= 0) |
344 | sats[sat->nr] = sat; | 344 | sats[sat->nr] = sat; |
345 | 345 | ||
346 | return; | 346 | return; |
347 | 347 | ||
348 | fail: | 348 | fail: |
349 | kfree(sat); | 349 | kfree(sat); |
350 | } | 350 | } |
351 | 351 | ||
352 | static int wf_sat_attach(struct i2c_adapter *adapter) | 352 | static int wf_sat_attach(struct i2c_adapter *adapter) |
353 | { | 353 | { |
354 | struct device_node *busnode, *dev = NULL; | 354 | struct device_node *busnode, *dev = NULL; |
355 | struct pmac_i2c_bus *bus; | 355 | struct pmac_i2c_bus *bus; |
356 | 356 | ||
357 | bus = pmac_i2c_adapter_to_bus(adapter); | 357 | bus = pmac_i2c_adapter_to_bus(adapter); |
358 | if (bus == NULL) | 358 | if (bus == NULL) |
359 | return -ENODEV; | 359 | return -ENODEV; |
360 | busnode = pmac_i2c_get_bus_node(bus); | 360 | busnode = pmac_i2c_get_bus_node(bus); |
361 | 361 | ||
362 | while ((dev = of_get_next_child(busnode, dev)) != NULL) | 362 | while ((dev = of_get_next_child(busnode, dev)) != NULL) |
363 | if (of_device_is_compatible(dev, "smu-sat")) | 363 | if (of_device_is_compatible(dev, "smu-sat")) |
364 | wf_sat_create(adapter, dev); | 364 | wf_sat_create(adapter, dev); |
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | static int wf_sat_detach(struct i2c_client *client) | 368 | static int wf_sat_detach(struct i2c_client *client) |
369 | { | 369 | { |
370 | struct wf_sat *sat = i2c_to_sat(client); | 370 | struct wf_sat *sat = i2c_to_sat(client); |
371 | 371 | ||
372 | /* XXX TODO */ | 372 | /* XXX TODO */ |
373 | 373 | ||
374 | sat->i2c.adapter = NULL; | 374 | sat->i2c.adapter = NULL; |
375 | return 0; | 375 | return 0; |
376 | } | 376 | } |
377 | 377 | ||
378 | static int __init sat_sensors_init(void) | 378 | static int __init sat_sensors_init(void) |
379 | { | 379 | { |
380 | return i2c_add_driver(&wf_sat_driver); | 380 | return i2c_add_driver(&wf_sat_driver); |
381 | } | 381 | } |
382 | 382 | ||
383 | #if 0 /* uncomment when module_exit() below is uncommented */ | ||
383 | static void __exit sat_sensors_exit(void) | 384 | static void __exit sat_sensors_exit(void) |
384 | { | 385 | { |
385 | i2c_del_driver(&wf_sat_driver); | 386 | i2c_del_driver(&wf_sat_driver); |
386 | } | 387 | } |
388 | #endif | ||
387 | 389 | ||
388 | module_init(sat_sensors_init); | 390 | module_init(sat_sensors_init); |
389 | /*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */ | 391 | /*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */ |
390 | 392 | ||
391 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); | 393 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); |
392 | MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control"); | 394 | MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control"); |
393 | MODULE_LICENSE("GPL"); | 395 | MODULE_LICENSE("GPL"); |
394 | 396 |