diff options
Diffstat (limited to 'drivers/hwmon/smsc47b397.c')
-rw-r--r-- | drivers/hwmon/smsc47b397.c | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index fdeeb3ab6f2f..7fe71576dea4 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c | |||
@@ -31,23 +31,14 @@ | |||
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
34 | #include <linux/i2c-sensor.h> | 34 | #include <linux/i2c-isa.h> |
35 | #include <linux/hwmon.h> | ||
36 | #include <linux/err.h> | ||
35 | #include <linux/init.h> | 37 | #include <linux/init.h> |
36 | #include <asm/io.h> | 38 | #include <asm/io.h> |
37 | 39 | ||
38 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
39 | /* Address is autodetected, there is no default value */ | 40 | /* Address is autodetected, there is no default value */ |
40 | static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END }; | 41 | static unsigned short address; |
41 | static struct i2c_force_data forces[] = {{NULL}}; | ||
42 | |||
43 | enum chips { any_chip, smsc47b397 }; | ||
44 | static struct i2c_address_data addr_data = { | ||
45 | .normal_i2c = normal_i2c, | ||
46 | .normal_isa = normal_isa, | ||
47 | .probe = normal_i2c, /* cheat */ | ||
48 | .ignore = normal_i2c, /* cheat */ | ||
49 | .forces = forces, | ||
50 | }; | ||
51 | 42 | ||
52 | /* Super-I/0 registers and commands */ | 43 | /* Super-I/0 registers and commands */ |
53 | 44 | ||
@@ -100,6 +91,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; | |||
100 | 91 | ||
101 | struct smsc47b397_data { | 92 | struct smsc47b397_data { |
102 | struct i2c_client client; | 93 | struct i2c_client client; |
94 | struct class_device *class_dev; | ||
103 | struct semaphore lock; | 95 | struct semaphore lock; |
104 | 96 | ||
105 | struct semaphore update_lock; | 97 | struct semaphore update_lock; |
@@ -215,52 +207,40 @@ sysfs_fan(4); | |||
215 | #define device_create_file_fan(client, num) \ | 207 | #define device_create_file_fan(client, num) \ |
216 | device_create_file(&client->dev, &dev_attr_fan##num##_input) | 208 | device_create_file(&client->dev, &dev_attr_fan##num##_input) |
217 | 209 | ||
218 | static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind); | ||
219 | |||
220 | static int smsc47b397_attach_adapter(struct i2c_adapter *adapter) | ||
221 | { | ||
222 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
223 | return 0; | ||
224 | return i2c_detect(adapter, &addr_data, smsc47b397_detect); | ||
225 | } | ||
226 | |||
227 | static int smsc47b397_detach_client(struct i2c_client *client) | 210 | static int smsc47b397_detach_client(struct i2c_client *client) |
228 | { | 211 | { |
212 | struct smsc47b397_data *data = i2c_get_clientdata(client); | ||
229 | int err; | 213 | int err; |
230 | 214 | ||
231 | if ((err = i2c_detach_client(client))) { | 215 | hwmon_device_unregister(data->class_dev); |
232 | dev_err(&client->dev, "Client deregistration failed, " | 216 | |
233 | "client not detached.\n"); | 217 | if ((err = i2c_detach_client(client))) |
234 | return err; | 218 | return err; |
235 | } | ||
236 | 219 | ||
237 | release_region(client->addr, SMSC_EXTENT); | 220 | release_region(client->addr, SMSC_EXTENT); |
238 | kfree(i2c_get_clientdata(client)); | 221 | kfree(data); |
239 | 222 | ||
240 | return 0; | 223 | return 0; |
241 | } | 224 | } |
242 | 225 | ||
226 | static int smsc47b397_detect(struct i2c_adapter *adapter); | ||
227 | |||
243 | static struct i2c_driver smsc47b397_driver = { | 228 | static struct i2c_driver smsc47b397_driver = { |
244 | .owner = THIS_MODULE, | 229 | .owner = THIS_MODULE, |
245 | .name = "smsc47b397", | 230 | .name = "smsc47b397", |
246 | .id = I2C_DRIVERID_SMSC47B397, | 231 | .attach_adapter = smsc47b397_detect, |
247 | .flags = I2C_DF_NOTIFY, | ||
248 | .attach_adapter = smsc47b397_attach_adapter, | ||
249 | .detach_client = smsc47b397_detach_client, | 232 | .detach_client = smsc47b397_detach_client, |
250 | }; | 233 | }; |
251 | 234 | ||
252 | static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) | 235 | static int smsc47b397_detect(struct i2c_adapter *adapter) |
253 | { | 236 | { |
254 | struct i2c_client *new_client; | 237 | struct i2c_client *new_client; |
255 | struct smsc47b397_data *data; | 238 | struct smsc47b397_data *data; |
256 | int err = 0; | 239 | int err = 0; |
257 | 240 | ||
258 | if (!i2c_is_isa_adapter(adapter)) { | 241 | if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) { |
259 | return 0; | 242 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", |
260 | } | 243 | address); |
261 | |||
262 | if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) { | ||
263 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr); | ||
264 | return -EBUSY; | 244 | return -EBUSY; |
265 | } | 245 | } |
266 | 246 | ||
@@ -272,7 +252,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) | |||
272 | 252 | ||
273 | new_client = &data->client; | 253 | new_client = &data->client; |
274 | i2c_set_clientdata(new_client, data); | 254 | i2c_set_clientdata(new_client, data); |
275 | new_client->addr = addr; | 255 | new_client->addr = address; |
276 | init_MUTEX(&data->lock); | 256 | init_MUTEX(&data->lock); |
277 | new_client->adapter = adapter; | 257 | new_client->adapter = adapter; |
278 | new_client->driver = &smsc47b397_driver; | 258 | new_client->driver = &smsc47b397_driver; |
@@ -285,6 +265,12 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) | |||
285 | if ((err = i2c_attach_client(new_client))) | 265 | if ((err = i2c_attach_client(new_client))) |
286 | goto error_free; | 266 | goto error_free; |
287 | 267 | ||
268 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
269 | if (IS_ERR(data->class_dev)) { | ||
270 | err = PTR_ERR(data->class_dev); | ||
271 | goto error_detach; | ||
272 | } | ||
273 | |||
288 | device_create_file_temp(new_client, 1); | 274 | device_create_file_temp(new_client, 1); |
289 | device_create_file_temp(new_client, 2); | 275 | device_create_file_temp(new_client, 2); |
290 | device_create_file_temp(new_client, 3); | 276 | device_create_file_temp(new_client, 3); |
@@ -297,14 +283,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) | |||
297 | 283 | ||
298 | return 0; | 284 | return 0; |
299 | 285 | ||
286 | error_detach: | ||
287 | i2c_detach_client(new_client); | ||
300 | error_free: | 288 | error_free: |
301 | kfree(data); | 289 | kfree(data); |
302 | error_release: | 290 | error_release: |
303 | release_region(addr, SMSC_EXTENT); | 291 | release_region(address, SMSC_EXTENT); |
304 | return err; | 292 | return err; |
305 | } | 293 | } |
306 | 294 | ||
307 | static int __init smsc47b397_find(unsigned int *addr) | 295 | static int __init smsc47b397_find(unsigned short *addr) |
308 | { | 296 | { |
309 | u8 id, rev; | 297 | u8 id, rev; |
310 | 298 | ||
@@ -333,15 +321,15 @@ static int __init smsc47b397_init(void) | |||
333 | { | 321 | { |
334 | int ret; | 322 | int ret; |
335 | 323 | ||
336 | if ((ret = smsc47b397_find(normal_isa))) | 324 | if ((ret = smsc47b397_find(&address))) |
337 | return ret; | 325 | return ret; |
338 | 326 | ||
339 | return i2c_add_driver(&smsc47b397_driver); | 327 | return i2c_isa_add_driver(&smsc47b397_driver); |
340 | } | 328 | } |
341 | 329 | ||
342 | static void __exit smsc47b397_exit(void) | 330 | static void __exit smsc47b397_exit(void) |
343 | { | 331 | { |
344 | i2c_del_driver(&smsc47b397_driver); | 332 | i2c_isa_del_driver(&smsc47b397_driver); |
345 | } | 333 | } |
346 | 334 | ||
347 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); | 335 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); |