diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:17 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:17 -0400 |
commit | 31d5d275a118527a2b9b0f68613428f176efbb8f (patch) | |
tree | 94920b64729e7785aa3afd843e47062d6f1496b6 /drivers/hwmon/w83792d.c | |
parent | cb0c1af37996f3016e34e9c709e5f727646f7207 (diff) |
hwmon: (w83792d) Convert to a new-style i2c driver
The new-style w83792d driver implements the optional detect()
callback to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83792d.c')
-rw-r--r-- | drivers/hwmon/w83792d.c | 214 |
1 files changed, 72 insertions, 142 deletions
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 299629d47ed6..cf94c5b0c879 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -267,9 +267,7 @@ DIV_TO_REG(long val) | |||
267 | } | 267 | } |
268 | 268 | ||
269 | struct w83792d_data { | 269 | struct w83792d_data { |
270 | struct i2c_client client; | ||
271 | struct device *hwmon_dev; | 270 | struct device *hwmon_dev; |
272 | enum chips type; | ||
273 | 271 | ||
274 | struct mutex update_lock; | 272 | struct mutex update_lock; |
275 | char valid; /* !=0 if following fields are valid */ | 273 | char valid; /* !=0 if following fields are valid */ |
@@ -299,9 +297,11 @@ struct w83792d_data { | |||
299 | u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ | 297 | u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ |
300 | }; | 298 | }; |
301 | 299 | ||
302 | static int w83792d_attach_adapter(struct i2c_adapter *adapter); | 300 | static int w83792d_probe(struct i2c_client *client, |
303 | static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); | 301 | const struct i2c_device_id *id); |
304 | static int w83792d_detach_client(struct i2c_client *client); | 302 | static int w83792d_detect(struct i2c_client *client, int kind, |
303 | struct i2c_board_info *info); | ||
304 | static int w83792d_remove(struct i2c_client *client); | ||
305 | static struct w83792d_data *w83792d_update_device(struct device *dev); | 305 | static struct w83792d_data *w83792d_update_device(struct device *dev); |
306 | 306 | ||
307 | #ifdef DEBUG | 307 | #ifdef DEBUG |
@@ -310,12 +310,22 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); | |||
310 | 310 | ||
311 | static void w83792d_init_client(struct i2c_client *client); | 311 | static void w83792d_init_client(struct i2c_client *client); |
312 | 312 | ||
313 | static const struct i2c_device_id w83792d_id[] = { | ||
314 | { "w83792d", w83792d }, | ||
315 | { } | ||
316 | }; | ||
317 | MODULE_DEVICE_TABLE(i2c, w83792d_id); | ||
318 | |||
313 | static struct i2c_driver w83792d_driver = { | 319 | static struct i2c_driver w83792d_driver = { |
320 | .class = I2C_CLASS_HWMON, | ||
314 | .driver = { | 321 | .driver = { |
315 | .name = "w83792d", | 322 | .name = "w83792d", |
316 | }, | 323 | }, |
317 | .attach_adapter = w83792d_attach_adapter, | 324 | .probe = w83792d_probe, |
318 | .detach_client = w83792d_detach_client, | 325 | .remove = w83792d_remove, |
326 | .id_table = w83792d_id, | ||
327 | .detect = w83792d_detect, | ||
328 | .address_data = &addr_data, | ||
319 | }; | 329 | }; |
320 | 330 | ||
321 | static inline long in_count_from_reg(int nr, struct w83792d_data *data) | 331 | static inline long in_count_from_reg(int nr, struct w83792d_data *data) |
@@ -864,53 +874,14 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, | |||
864 | return count; | 874 | return count; |
865 | } | 875 | } |
866 | 876 | ||
867 | /* This function is called when: | ||
868 | * w83792d_driver is inserted (when this module is loaded), for each | ||
869 | available adapter | ||
870 | * when a new adapter is inserted (and w83792d_driver is still present) */ | ||
871 | static int | ||
872 | w83792d_attach_adapter(struct i2c_adapter *adapter) | ||
873 | { | ||
874 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
875 | return 0; | ||
876 | return i2c_probe(adapter, &addr_data, w83792d_detect); | ||
877 | } | ||
878 | |||
879 | |||
880 | static int | ||
881 | w83792d_create_subclient(struct i2c_adapter *adapter, | ||
882 | struct i2c_client *new_client, int addr, | ||
883 | struct i2c_client **sub_cli) | ||
884 | { | ||
885 | int err; | ||
886 | struct i2c_client *sub_client; | ||
887 | |||
888 | (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
889 | if (!(sub_client)) { | ||
890 | return -ENOMEM; | ||
891 | } | ||
892 | sub_client->addr = 0x48 + addr; | ||
893 | i2c_set_clientdata(sub_client, NULL); | ||
894 | sub_client->adapter = adapter; | ||
895 | sub_client->driver = &w83792d_driver; | ||
896 | sub_client->flags = 0; | ||
897 | strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE); | ||
898 | if ((err = i2c_attach_client(sub_client))) { | ||
899 | dev_err(&new_client->dev, "subclient registration " | ||
900 | "at address 0x%x failed\n", sub_client->addr); | ||
901 | kfree(sub_client); | ||
902 | return err; | ||
903 | } | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | 877 | ||
908 | static int | 878 | static int |
909 | w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | 879 | w83792d_detect_subclients(struct i2c_client *new_client) |
910 | struct i2c_client *new_client) | ||
911 | { | 880 | { |
912 | int i, id, err; | 881 | int i, id, err; |
882 | int address = new_client->addr; | ||
913 | u8 val; | 883 | u8 val; |
884 | struct i2c_adapter *adapter = new_client->adapter; | ||
914 | struct w83792d_data *data = i2c_get_clientdata(new_client); | 885 | struct w83792d_data *data = i2c_get_clientdata(new_client); |
915 | 886 | ||
916 | id = i2c_adapter_id(adapter); | 887 | id = i2c_adapter_id(adapter); |
@@ -932,10 +903,7 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | |||
932 | 903 | ||
933 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); | 904 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); |
934 | if (!(val & 0x08)) { | 905 | if (!(val & 0x08)) { |
935 | err = w83792d_create_subclient(adapter, new_client, val & 0x7, | 906 | data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); |
936 | &data->lm75[0]); | ||
937 | if (err < 0) | ||
938 | goto ERROR_SC_0; | ||
939 | } | 907 | } |
940 | if (!(val & 0x80)) { | 908 | if (!(val & 0x80)) { |
941 | if ((data->lm75[0] != NULL) && | 909 | if ((data->lm75[0] != NULL) && |
@@ -945,10 +913,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | |||
945 | err = -ENODEV; | 913 | err = -ENODEV; |
946 | goto ERROR_SC_1; | 914 | goto ERROR_SC_1; |
947 | } | 915 | } |
948 | err = w83792d_create_subclient(adapter, new_client, | 916 | data->lm75[1] = i2c_new_dummy(adapter, |
949 | (val >> 4) & 0x7, &data->lm75[1]); | 917 | 0x48 + ((val >> 4) & 0x7)); |
950 | if (err < 0) | ||
951 | goto ERROR_SC_1; | ||
952 | } | 918 | } |
953 | 919 | ||
954 | return 0; | 920 | return 0; |
@@ -956,10 +922,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | |||
956 | /* Undo inits in case of errors */ | 922 | /* Undo inits in case of errors */ |
957 | 923 | ||
958 | ERROR_SC_1: | 924 | ERROR_SC_1: |
959 | if (data->lm75[0] != NULL) { | 925 | if (data->lm75[0] != NULL) |
960 | i2c_detach_client(data->lm75[0]); | 926 | i2c_unregister_device(data->lm75[0]); |
961 | kfree(data->lm75[0]); | ||
962 | } | ||
963 | ERROR_SC_0: | 927 | ERROR_SC_0: |
964 | return err; | 928 | return err; |
965 | } | 929 | } |
@@ -1294,47 +1258,25 @@ static const struct attribute_group w83792d_group = { | |||
1294 | .attrs = w83792d_attributes, | 1258 | .attrs = w83792d_attributes, |
1295 | }; | 1259 | }; |
1296 | 1260 | ||
1261 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
1297 | static int | 1262 | static int |
1298 | w83792d_detect(struct i2c_adapter *adapter, int address, int kind) | 1263 | w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) |
1299 | { | 1264 | { |
1300 | int i = 0, val1 = 0, val2; | 1265 | struct i2c_adapter *adapter = client->adapter; |
1301 | struct i2c_client *client; | 1266 | int val1, val2; |
1302 | struct device *dev; | 1267 | unsigned short address = client->addr; |
1303 | struct w83792d_data *data; | ||
1304 | int err = 0; | ||
1305 | const char *client_name = ""; | ||
1306 | 1268 | ||
1307 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1269 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1308 | goto ERROR0; | 1270 | return -ENODEV; |
1309 | } | ||
1310 | |||
1311 | /* OK. For now, we presume we have a valid client. We now create the | ||
1312 | client structure, even though we cannot fill it completely yet. | ||
1313 | But it allows us to access w83792d_{read,write}_value. */ | ||
1314 | |||
1315 | if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) { | ||
1316 | err = -ENOMEM; | ||
1317 | goto ERROR0; | ||
1318 | } | 1271 | } |
1319 | 1272 | ||
1320 | client = &data->client; | ||
1321 | dev = &client->dev; | ||
1322 | i2c_set_clientdata(client, data); | ||
1323 | client->addr = address; | ||
1324 | client->adapter = adapter; | ||
1325 | client->driver = &w83792d_driver; | ||
1326 | client->flags = 0; | ||
1327 | |||
1328 | /* Now, we do the remaining detection. */ | ||
1329 | |||
1330 | /* The w83792d may be stuck in some other bank than bank 0. This may | 1273 | /* The w83792d may be stuck in some other bank than bank 0. This may |
1331 | make reading other information impossible. Specify a force=... or | 1274 | make reading other information impossible. Specify a force=... or |
1332 | force_*=... parameter, and the Winbond will be reset to the right | 1275 | force_*=... parameter, and the Winbond will be reset to the right |
1333 | bank. */ | 1276 | bank. */ |
1334 | if (kind < 0) { | 1277 | if (kind < 0) { |
1335 | if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { | 1278 | if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { |
1336 | dev_dbg(dev, "Detection failed at step 1\n"); | 1279 | return -ENODEV; |
1337 | goto ERROR1; | ||
1338 | } | 1280 | } |
1339 | val1 = w83792d_read_value(client, W83792D_REG_BANK); | 1281 | val1 = w83792d_read_value(client, W83792D_REG_BANK); |
1340 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); | 1282 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); |
@@ -1342,16 +1284,14 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1342 | if (!(val1 & 0x07)) { /* is Bank0 */ | 1284 | if (!(val1 & 0x07)) { /* is Bank0 */ |
1343 | if (((!(val1 & 0x80)) && (val2 != 0xa3)) || | 1285 | if (((!(val1 & 0x80)) && (val2 != 0xa3)) || |
1344 | ((val1 & 0x80) && (val2 != 0x5c))) { | 1286 | ((val1 & 0x80) && (val2 != 0x5c))) { |
1345 | dev_dbg(dev, "Detection failed at step 2\n"); | 1287 | return -ENODEV; |
1346 | goto ERROR1; | ||
1347 | } | 1288 | } |
1348 | } | 1289 | } |
1349 | /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR | 1290 | /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR |
1350 | should match */ | 1291 | should match */ |
1351 | if (w83792d_read_value(client, | 1292 | if (w83792d_read_value(client, |
1352 | W83792D_REG_I2C_ADDR) != address) { | 1293 | W83792D_REG_I2C_ADDR) != address) { |
1353 | dev_dbg(dev, "Detection failed at step 3\n"); | 1294 | return -ENODEV; |
1354 | goto ERROR1; | ||
1355 | } | 1295 | } |
1356 | } | 1296 | } |
1357 | 1297 | ||
@@ -1367,45 +1307,48 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1367 | /* get vendor ID */ | 1307 | /* get vendor ID */ |
1368 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); | 1308 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); |
1369 | if (val2 != 0x5c) { /* the vendor is NOT Winbond */ | 1309 | if (val2 != 0x5c) { /* the vendor is NOT Winbond */ |
1370 | goto ERROR1; | 1310 | return -ENODEV; |
1371 | } | 1311 | } |
1372 | val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); | 1312 | val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); |
1373 | if (val1 == 0x7a) { | 1313 | if (val1 == 0x7a) { |
1374 | kind = w83792d; | 1314 | kind = w83792d; |
1375 | } else { | 1315 | } else { |
1376 | if (kind == 0) | 1316 | if (kind == 0) |
1377 | dev_warn(dev, | 1317 | dev_warn(&adapter->dev, |
1378 | "w83792d: Ignoring 'force' parameter for" | 1318 | "w83792d: Ignoring 'force' parameter for" |
1379 | " unknown chip at adapter %d, address" | 1319 | " unknown chip at adapter %d, address" |
1380 | " 0x%02x\n", i2c_adapter_id(adapter), | 1320 | " 0x%02x\n", i2c_adapter_id(adapter), |
1381 | address); | 1321 | address); |
1382 | goto ERROR1; | 1322 | return -ENODEV; |
1383 | } | 1323 | } |
1384 | } | 1324 | } |
1385 | 1325 | ||
1386 | if (kind == w83792d) { | 1326 | strlcpy(info->type, "w83792d", I2C_NAME_SIZE); |
1387 | client_name = "w83792d"; | 1327 | |
1388 | } else { | 1328 | return 0; |
1389 | dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n", | 1329 | } |
1390 | kind); | 1330 | |
1391 | goto ERROR1; | 1331 | static int |
1392 | } | 1332 | w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) |
1333 | { | ||
1334 | struct w83792d_data *data; | ||
1335 | struct device *dev = &client->dev; | ||
1336 | int i, val1, err; | ||
1393 | 1337 | ||
1394 | /* Fill in the remaining client fields and put into the global list */ | 1338 | data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL); |
1395 | strlcpy(client->name, client_name, I2C_NAME_SIZE); | 1339 | if (!data) { |
1396 | data->type = kind; | 1340 | err = -ENOMEM; |
1341 | goto ERROR0; | ||
1342 | } | ||
1397 | 1343 | ||
1344 | i2c_set_clientdata(client, data); | ||
1398 | data->valid = 0; | 1345 | data->valid = 0; |
1399 | mutex_init(&data->update_lock); | 1346 | mutex_init(&data->update_lock); |
1400 | 1347 | ||
1401 | /* Tell the I2C layer a new client has arrived */ | 1348 | err = w83792d_detect_subclients(client); |
1402 | if ((err = i2c_attach_client(client))) | 1349 | if (err) |
1403 | goto ERROR1; | 1350 | goto ERROR1; |
1404 | 1351 | ||
1405 | if ((err = w83792d_detect_subclients(adapter, address, | ||
1406 | kind, client))) | ||
1407 | goto ERROR2; | ||
1408 | |||
1409 | /* Initialize the chip */ | 1352 | /* Initialize the chip */ |
1410 | w83792d_init_client(client); | 1353 | w83792d_init_client(client); |
1411 | 1354 | ||
@@ -1457,16 +1400,10 @@ exit_remove_files: | |||
1457 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) | 1400 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) |
1458 | sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); | 1401 | sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); |
1459 | ERROR3: | 1402 | ERROR3: |
1460 | if (data->lm75[0] != NULL) { | 1403 | if (data->lm75[0] != NULL) |
1461 | i2c_detach_client(data->lm75[0]); | 1404 | i2c_unregister_device(data->lm75[0]); |
1462 | kfree(data->lm75[0]); | 1405 | if (data->lm75[1] != NULL) |
1463 | } | 1406 | i2c_unregister_device(data->lm75[1]); |
1464 | if (data->lm75[1] != NULL) { | ||
1465 | i2c_detach_client(data->lm75[1]); | ||
1466 | kfree(data->lm75[1]); | ||
1467 | } | ||
1468 | ERROR2: | ||
1469 | i2c_detach_client(client); | ||
1470 | ERROR1: | 1407 | ERROR1: |
1471 | kfree(data); | 1408 | kfree(data); |
1472 | ERROR0: | 1409 | ERROR0: |
@@ -1474,30 +1411,23 @@ ERROR0: | |||
1474 | } | 1411 | } |
1475 | 1412 | ||
1476 | static int | 1413 | static int |
1477 | w83792d_detach_client(struct i2c_client *client) | 1414 | w83792d_remove(struct i2c_client *client) |
1478 | { | 1415 | { |
1479 | struct w83792d_data *data = i2c_get_clientdata(client); | 1416 | struct w83792d_data *data = i2c_get_clientdata(client); |
1480 | int err, i; | 1417 | int i; |
1481 | |||
1482 | /* main client */ | ||
1483 | if (data) { | ||
1484 | hwmon_device_unregister(data->hwmon_dev); | ||
1485 | sysfs_remove_group(&client->dev.kobj, &w83792d_group); | ||
1486 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) | ||
1487 | sysfs_remove_group(&client->dev.kobj, | ||
1488 | &w83792d_group_fan[i]); | ||
1489 | } | ||
1490 | 1418 | ||
1491 | if ((err = i2c_detach_client(client))) | 1419 | hwmon_device_unregister(data->hwmon_dev); |
1492 | return err; | 1420 | sysfs_remove_group(&client->dev.kobj, &w83792d_group); |
1421 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) | ||
1422 | sysfs_remove_group(&client->dev.kobj, | ||
1423 | &w83792d_group_fan[i]); | ||
1493 | 1424 | ||
1494 | /* main client */ | 1425 | if (data->lm75[0] != NULL) |
1495 | if (data) | 1426 | i2c_unregister_device(data->lm75[0]); |
1496 | kfree(data); | 1427 | if (data->lm75[1] != NULL) |
1497 | /* subclient */ | 1428 | i2c_unregister_device(data->lm75[1]); |
1498 | else | ||
1499 | kfree(client); | ||
1500 | 1429 | ||
1430 | kfree(data); | ||
1501 | return 0; | 1431 | return 0; |
1502 | } | 1432 | } |
1503 | 1433 | ||