diff options
| author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:13 -0400 |
|---|---|---|
| committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:13 -0400 |
| commit | a189dd62d328db7bf8ba68de6a948fdbc93dca25 (patch) | |
| tree | 00a53527cbec8ce5aaef2eb5d4c6b698514554af | |
| parent | d5957be2f1535b1a6c77eabba0781ec7245c5dea (diff) | |
hwmon: (lm77) Convert to a new-style i2c driver
The new-style lm77 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Andras Bali <drewie@freemail.hu>
| -rw-r--r-- | drivers/hwmon/lm77.c | 102 |
1 files changed, 45 insertions, 57 deletions
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 36d5a8c3ad8c..866b401ab6e8 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
| @@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77); | |||
| 52 | 52 | ||
| 53 | /* Each client has this additional data */ | 53 | /* Each client has this additional data */ |
| 54 | struct lm77_data { | 54 | struct lm77_data { |
| 55 | struct i2c_client client; | ||
| 56 | struct device *hwmon_dev; | 55 | struct device *hwmon_dev; |
| 57 | struct mutex update_lock; | 56 | struct mutex update_lock; |
| 58 | char valid; | 57 | char valid; |
| @@ -65,23 +64,35 @@ struct lm77_data { | |||
| 65 | u8 alarms; | 64 | u8 alarms; |
| 66 | }; | 65 | }; |
| 67 | 66 | ||
| 68 | static int lm77_attach_adapter(struct i2c_adapter *adapter); | 67 | static int lm77_probe(struct i2c_client *client, |
| 69 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); | 68 | const struct i2c_device_id *id); |
| 69 | static int lm77_detect(struct i2c_client *client, int kind, | ||
| 70 | struct i2c_board_info *info); | ||
| 70 | static void lm77_init_client(struct i2c_client *client); | 71 | static void lm77_init_client(struct i2c_client *client); |
| 71 | static int lm77_detach_client(struct i2c_client *client); | 72 | static int lm77_remove(struct i2c_client *client); |
| 72 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); | 73 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); |
| 73 | static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); | 74 | static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); |
| 74 | 75 | ||
| 75 | static struct lm77_data *lm77_update_device(struct device *dev); | 76 | static struct lm77_data *lm77_update_device(struct device *dev); |
| 76 | 77 | ||
| 77 | 78 | ||
| 79 | static const struct i2c_device_id lm77_id[] = { | ||
| 80 | { "lm77", lm77 }, | ||
| 81 | { } | ||
| 82 | }; | ||
| 83 | MODULE_DEVICE_TABLE(i2c, lm77_id); | ||
| 84 | |||
| 78 | /* This is the driver that will be inserted */ | 85 | /* This is the driver that will be inserted */ |
| 79 | static struct i2c_driver lm77_driver = { | 86 | static struct i2c_driver lm77_driver = { |
| 87 | .class = I2C_CLASS_HWMON, | ||
| 80 | .driver = { | 88 | .driver = { |
| 81 | .name = "lm77", | 89 | .name = "lm77", |
| 82 | }, | 90 | }, |
| 83 | .attach_adapter = lm77_attach_adapter, | 91 | .probe = lm77_probe, |
| 84 | .detach_client = lm77_detach_client, | 92 | .remove = lm77_remove, |
| 93 | .id_table = lm77_id, | ||
| 94 | .detect = lm77_detect, | ||
| 95 | .address_data = &addr_data, | ||
| 85 | }; | 96 | }; |
| 86 | 97 | ||
| 87 | /* straight from the datasheet */ | 98 | /* straight from the datasheet */ |
| @@ -215,13 +226,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); | |||
| 215 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); | 226 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); |
| 216 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); | 227 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); |
| 217 | 228 | ||
| 218 | static int lm77_attach_adapter(struct i2c_adapter *adapter) | ||
| 219 | { | ||
| 220 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
| 221 | return 0; | ||
| 222 | return i2c_probe(adapter, &addr_data, lm77_detect); | ||
| 223 | } | ||
| 224 | |||
| 225 | static struct attribute *lm77_attributes[] = { | 229 | static struct attribute *lm77_attributes[] = { |
| 226 | &dev_attr_temp1_input.attr, | 230 | &dev_attr_temp1_input.attr, |
| 227 | &dev_attr_temp1_crit.attr, | 231 | &dev_attr_temp1_crit.attr, |
| @@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = { | |||
| 240 | .attrs = lm77_attributes, | 244 | .attrs = lm77_attributes, |
| 241 | }; | 245 | }; |
| 242 | 246 | ||
| 243 | /* This function is called by i2c_probe */ | 247 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 244 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | 248 | static int lm77_detect(struct i2c_client *new_client, int kind, |
| 249 | struct i2c_board_info *info) | ||
| 245 | { | 250 | { |
| 246 | struct i2c_client *new_client; | 251 | struct i2c_adapter *adapter = new_client->adapter; |
| 247 | struct lm77_data *data; | ||
| 248 | int err = 0; | ||
| 249 | const char *name = ""; | ||
| 250 | 252 | ||
| 251 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | 253 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
| 252 | I2C_FUNC_SMBUS_WORD_DATA)) | 254 | I2C_FUNC_SMBUS_WORD_DATA)) |
| 253 | goto exit; | 255 | return -ENODEV; |
| 254 | |||
| 255 | /* OK. For now, we presume we have a valid client. We now create the | ||
| 256 | client structure, even though we cannot fill it completely yet. | ||
| 257 | But it allows us to access lm77_{read,write}_value. */ | ||
| 258 | if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) { | ||
| 259 | err = -ENOMEM; | ||
| 260 | goto exit; | ||
| 261 | } | ||
| 262 | |||
| 263 | new_client = &data->client; | ||
| 264 | i2c_set_clientdata(new_client, data); | ||
| 265 | new_client->addr = address; | ||
| 266 | new_client->adapter = adapter; | ||
| 267 | new_client->driver = &lm77_driver; | ||
| 268 | new_client->flags = 0; | ||
| 269 | 256 | ||
| 270 | /* Here comes the remaining detection. Since the LM77 has no | 257 | /* Here comes the remaining detection. Since the LM77 has no |
| 271 | register dedicated to identification, we have to rely on the | 258 | register dedicated to identification, we have to rely on the |
| @@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 294 | || i2c_smbus_read_word_data(new_client, i + 3) != crit | 281 | || i2c_smbus_read_word_data(new_client, i + 3) != crit |
| 295 | || i2c_smbus_read_word_data(new_client, i + 4) != min | 282 | || i2c_smbus_read_word_data(new_client, i + 4) != min |
| 296 | || i2c_smbus_read_word_data(new_client, i + 5) != max) | 283 | || i2c_smbus_read_word_data(new_client, i + 5) != max) |
| 297 | goto exit_free; | 284 | return -ENODEV; |
| 298 | 285 | ||
| 299 | /* sign bits */ | 286 | /* sign bits */ |
| 300 | if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) | 287 | if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) |
| @@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 302 | || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) | 289 | || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) |
| 303 | || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) | 290 | || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) |
| 304 | || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) | 291 | || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) |
| 305 | goto exit_free; | 292 | return -ENODEV; |
| 306 | 293 | ||
| 307 | /* unused bits */ | 294 | /* unused bits */ |
| 308 | if (conf & 0xe0) | 295 | if (conf & 0xe0) |
| 309 | goto exit_free; | 296 | return -ENODEV; |
| 310 | 297 | ||
| 311 | /* 0x06 and 0x07 return the last read value */ | 298 | /* 0x06 and 0x07 return the last read value */ |
| 312 | cur = i2c_smbus_read_word_data(new_client, 0); | 299 | cur = i2c_smbus_read_word_data(new_client, 0); |
| 313 | if (i2c_smbus_read_word_data(new_client, 6) != cur | 300 | if (i2c_smbus_read_word_data(new_client, 6) != cur |
| 314 | || i2c_smbus_read_word_data(new_client, 7) != cur) | 301 | || i2c_smbus_read_word_data(new_client, 7) != cur) |
| 315 | goto exit_free; | 302 | return -ENODEV; |
| 316 | hyst = i2c_smbus_read_word_data(new_client, 2); | 303 | hyst = i2c_smbus_read_word_data(new_client, 2); |
| 317 | if (i2c_smbus_read_word_data(new_client, 6) != hyst | 304 | if (i2c_smbus_read_word_data(new_client, 6) != hyst |
| 318 | || i2c_smbus_read_word_data(new_client, 7) != hyst) | 305 | || i2c_smbus_read_word_data(new_client, 7) != hyst) |
| 319 | goto exit_free; | 306 | return -ENODEV; |
| 320 | min = i2c_smbus_read_word_data(new_client, 4); | 307 | min = i2c_smbus_read_word_data(new_client, 4); |
| 321 | if (i2c_smbus_read_word_data(new_client, 6) != min | 308 | if (i2c_smbus_read_word_data(new_client, 6) != min |
| 322 | || i2c_smbus_read_word_data(new_client, 7) != min) | 309 | || i2c_smbus_read_word_data(new_client, 7) != min) |
| 323 | goto exit_free; | 310 | return -ENODEV; |
| 324 | 311 | ||
| 325 | } | 312 | } |
| 326 | 313 | ||
| 327 | /* Determine the chip type - only one kind supported! */ | 314 | strlcpy(info->type, "lm77", I2C_NAME_SIZE); |
| 328 | if (kind <= 0) | ||
| 329 | kind = lm77; | ||
| 330 | 315 | ||
| 331 | if (kind == lm77) { | 316 | return 0; |
| 332 | name = "lm77"; | 317 | } |
| 318 | |||
| 319 | static int lm77_probe(struct i2c_client *new_client, | ||
| 320 | const struct i2c_device_id *id) | ||
| 321 | { | ||
| 322 | struct lm77_data *data; | ||
| 323 | int err; | ||
| 324 | |||
| 325 | data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL); | ||
| 326 | if (!data) { | ||
| 327 | err = -ENOMEM; | ||
| 328 | goto exit; | ||
| 333 | } | 329 | } |
| 334 | 330 | ||
| 335 | /* Fill in the remaining client fields and put it into the global list */ | 331 | i2c_set_clientdata(new_client, data); |
| 336 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | ||
| 337 | data->valid = 0; | 332 | data->valid = 0; |
| 338 | mutex_init(&data->update_lock); | 333 | mutex_init(&data->update_lock); |
| 339 | 334 | ||
| 340 | /* Tell the I2C layer a new client has arrived */ | ||
| 341 | if ((err = i2c_attach_client(new_client))) | ||
| 342 | goto exit_free; | ||
| 343 | |||
| 344 | /* Initialize the LM77 chip */ | 335 | /* Initialize the LM77 chip */ |
| 345 | lm77_init_client(new_client); | 336 | lm77_init_client(new_client); |
| 346 | 337 | ||
| 347 | /* Register sysfs hooks */ | 338 | /* Register sysfs hooks */ |
| 348 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) | 339 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) |
| 349 | goto exit_detach; | 340 | goto exit_free; |
| 350 | 341 | ||
| 351 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | 342 | data->hwmon_dev = hwmon_device_register(&new_client->dev); |
| 352 | if (IS_ERR(data->hwmon_dev)) { | 343 | if (IS_ERR(data->hwmon_dev)) { |
| @@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 358 | 349 | ||
| 359 | exit_remove: | 350 | exit_remove: |
| 360 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); | 351 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); |
| 361 | exit_detach: | ||
| 362 | i2c_detach_client(new_client); | ||
| 363 | exit_free: | 352 | exit_free: |
| 364 | kfree(data); | 353 | kfree(data); |
| 365 | exit: | 354 | exit: |
| 366 | return err; | 355 | return err; |
| 367 | } | 356 | } |
| 368 | 357 | ||
| 369 | static int lm77_detach_client(struct i2c_client *client) | 358 | static int lm77_remove(struct i2c_client *client) |
| 370 | { | 359 | { |
| 371 | struct lm77_data *data = i2c_get_clientdata(client); | 360 | struct lm77_data *data = i2c_get_clientdata(client); |
| 372 | hwmon_device_unregister(data->hwmon_dev); | 361 | hwmon_device_unregister(data->hwmon_dev); |
| 373 | sysfs_remove_group(&client->dev.kobj, &lm77_group); | 362 | sysfs_remove_group(&client->dev.kobj, &lm77_group); |
| 374 | i2c_detach_client(client); | ||
| 375 | kfree(data); | 363 | kfree(data); |
| 376 | return 0; | 364 | return 0; |
| 377 | } | 365 | } |
