diff options
Diffstat (limited to 'drivers/macintosh/windfarm_smu_sat.c')
-rw-r--r-- | drivers/macintosh/windfarm_smu_sat.c | 109 |
1 files changed, 63 insertions, 46 deletions
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 7847e981ac33..5da729e58f99 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c | |||
@@ -39,7 +39,7 @@ struct wf_sat { | |||
39 | struct mutex mutex; | 39 | struct mutex 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 | ||
@@ -54,18 +54,6 @@ struct wf_sat_sensor { | |||
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) | ||
58 | |||
59 | static int wf_sat_attach(struct i2c_adapter *adapter); | ||
60 | static int wf_sat_detach(struct i2c_client *client); | ||
61 | |||
62 | static struct i2c_driver wf_sat_driver = { | ||
63 | .driver = { | ||
64 | .name = "wf_smu_sat", | ||
65 | }, | ||
66 | .attach_adapter = wf_sat_attach, | ||
67 | .detach_client = wf_sat_detach, | ||
68 | }; | ||
69 | 57 | ||
70 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | 58 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, |
71 | unsigned int *size) | 59 | unsigned int *size) |
@@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
81 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) | 69 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) |
82 | return NULL; | 70 | return NULL; |
83 | 71 | ||
84 | err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); | 72 | err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8); |
85 | if (err) { | 73 | if (err) { |
86 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); | 74 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); |
87 | return NULL; | 75 | return NULL; |
88 | } | 76 | } |
89 | 77 | ||
90 | err = i2c_smbus_read_word_data(&sat->i2c, 9); | 78 | err = i2c_smbus_read_word_data(sat->i2c, 9); |
91 | if (err < 0) { | 79 | if (err < 0) { |
92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); | 80 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); |
93 | return NULL; | 81 | return NULL; |
@@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
105 | return NULL; | 93 | return NULL; |
106 | 94 | ||
107 | for (i = 0; i < len; i += 4) { | 95 | for (i = 0; i < len; i += 4) { |
108 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); | 96 | err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data); |
109 | if (err < 0) { | 97 | if (err < 0) { |
110 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", | 98 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", |
111 | err); | 99 | err); |
@@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_sat *sat) | |||
138 | { | 126 | { |
139 | int err; | 127 | int err; |
140 | 128 | ||
141 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); | 129 | err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache); |
142 | if (err < 0) | 130 | if (err < 0) |
143 | return err; | 131 | return err; |
144 | sat->last_read = jiffies; | 132 | sat->last_read = jiffies; |
@@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value) | |||
161 | int i, err; | 149 | int i, err; |
162 | s32 val; | 150 | s32 val; |
163 | 151 | ||
164 | if (sat->i2c.adapter == NULL) | 152 | if (sat->i2c == NULL) |
165 | return -ENODEV; | 153 | return -ENODEV; |
166 | 154 | ||
167 | mutex_lock(&sat->mutex); | 155 | mutex_lock(&sat->mutex); |
@@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sensor *sr) | |||
193 | struct wf_sat *sat = sens->sat; | 181 | struct wf_sat *sat = sens->sat; |
194 | 182 | ||
195 | if (atomic_dec_and_test(&sat->refcnt)) { | 183 | if (atomic_dec_and_test(&sat->refcnt)) { |
196 | if (sat->i2c.adapter) { | ||
197 | i2c_detach_client(&sat->i2c); | ||
198 | sat->i2c.adapter = NULL; | ||
199 | } | ||
200 | if (sat->nr >= 0) | 184 | if (sat->nr >= 0) |
201 | sats[sat->nr] = NULL; | 185 | sats[sat->nr] = NULL; |
202 | kfree(sat); | 186 | kfree(sat); |
@@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = { | |||
212 | 196 | ||
213 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | 197 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) |
214 | { | 198 | { |
199 | struct i2c_board_info info; | ||
200 | struct i2c_client *client; | ||
201 | const u32 *reg; | ||
202 | u8 addr; | ||
203 | |||
204 | reg = of_get_property(dev, "reg", NULL); | ||
205 | if (reg == NULL) | ||
206 | return; | ||
207 | addr = *reg; | ||
208 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | ||
209 | |||
210 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
211 | info.addr = (addr >> 1) & 0x7f; | ||
212 | info.platform_data = dev; | ||
213 | strlcpy(info.type, "wf_sat", I2C_NAME_SIZE); | ||
214 | |||
215 | client = i2c_new_device(adapter, &info); | ||
216 | if (client == NULL) { | ||
217 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Let i2c-core delete that device on driver removal. | ||
223 | * This is safe because i2c-core holds the core_lock mutex for us. | ||
224 | */ | ||
225 | list_add_tail(&client->detected, &client->driver->clients); | ||
226 | } | ||
227 | |||
228 | static int wf_sat_probe(struct i2c_client *client, | ||
229 | const struct i2c_device_id *id) | ||
230 | { | ||
231 | struct device_node *dev = client->dev.platform_data; | ||
215 | struct wf_sat *sat; | 232 | struct wf_sat *sat; |
216 | struct wf_sat_sensor *sens; | 233 | struct wf_sat_sensor *sens; |
217 | const u32 *reg; | 234 | const u32 *reg; |
218 | const char *loc, *type; | 235 | const char *loc, *type; |
219 | u8 addr, chip, core; | 236 | u8 chip, core; |
220 | struct device_node *child; | 237 | struct device_node *child; |
221 | int shift, cpu, index; | 238 | int shift, cpu, index; |
222 | char *name; | 239 | char *name; |
223 | int vsens[2], isens[2]; | 240 | int vsens[2], isens[2]; |
224 | 241 | ||
225 | reg = of_get_property(dev, "reg", NULL); | ||
226 | if (reg == NULL) | ||
227 | return; | ||
228 | addr = *reg; | ||
229 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | ||
230 | |||
231 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); | 242 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); |
232 | if (sat == NULL) | 243 | if (sat == NULL) |
233 | return; | 244 | return -ENOMEM; |
234 | sat->nr = -1; | 245 | sat->nr = -1; |
235 | sat->node = of_node_get(dev); | 246 | sat->node = of_node_get(dev); |
236 | atomic_set(&sat->refcnt, 0); | 247 | atomic_set(&sat->refcnt, 0); |
237 | mutex_init(&sat->mutex); | 248 | mutex_init(&sat->mutex); |
238 | sat->i2c.addr = (addr >> 1) & 0x7f; | 249 | sat->i2c = client; |
239 | sat->i2c.adapter = adapter; | 250 | i2c_set_clientdata(client, sat); |
240 | sat->i2c.driver = &wf_sat_driver; | ||
241 | strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); | ||
242 | |||
243 | if (i2c_attach_client(&sat->i2c)) { | ||
244 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | ||
245 | goto fail; | ||
246 | } | ||
247 | 251 | ||
248 | vsens[0] = vsens[1] = -1; | 252 | vsens[0] = vsens[1] = -1; |
249 | isens[0] = isens[1] = -1; | 253 | isens[0] = isens[1] = -1; |
@@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | |||
344 | if (sat->nr >= 0) | 348 | if (sat->nr >= 0) |
345 | sats[sat->nr] = sat; | 349 | sats[sat->nr] = sat; |
346 | 350 | ||
347 | return; | 351 | return 0; |
348 | |||
349 | fail: | ||
350 | kfree(sat); | ||
351 | } | 352 | } |
352 | 353 | ||
353 | static int wf_sat_attach(struct i2c_adapter *adapter) | 354 | static int wf_sat_attach(struct i2c_adapter *adapter) |
@@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adapter *adapter) | |||
366 | return 0; | 367 | return 0; |
367 | } | 368 | } |
368 | 369 | ||
369 | static int wf_sat_detach(struct i2c_client *client) | 370 | static int wf_sat_remove(struct i2c_client *client) |
370 | { | 371 | { |
371 | struct wf_sat *sat = i2c_to_sat(client); | 372 | struct wf_sat *sat = i2c_get_clientdata(client); |
372 | 373 | ||
373 | /* XXX TODO */ | 374 | /* XXX TODO */ |
374 | 375 | ||
375 | sat->i2c.adapter = NULL; | 376 | sat->i2c = NULL; |
377 | i2c_set_clientdata(client, NULL); | ||
376 | return 0; | 378 | return 0; |
377 | } | 379 | } |
378 | 380 | ||
381 | static const struct i2c_device_id wf_sat_id[] = { | ||
382 | { "wf_sat", 0 }, | ||
383 | { } | ||
384 | }; | ||
385 | |||
386 | static struct i2c_driver wf_sat_driver = { | ||
387 | .driver = { | ||
388 | .name = "wf_smu_sat", | ||
389 | }, | ||
390 | .attach_adapter = wf_sat_attach, | ||
391 | .probe = wf_sat_probe, | ||
392 | .remove = wf_sat_remove, | ||
393 | .id_table = wf_sat_id, | ||
394 | }; | ||
395 | |||
379 | static int __init sat_sensors_init(void) | 396 | static int __init sat_sensors_init(void) |
380 | { | 397 | { |
381 | return i2c_add_driver(&wf_sat_driver); | 398 | return i2c_add_driver(&wf_sat_driver); |