diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2008-10-17 11:51:18 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-10-17 11:51:18 -0400 |
commit | 443850ce5880b24583d2be9d4b146e471fdf3dad (patch) | |
tree | 68ead39304fd70e387408ab5ad2edf2479807e2c /drivers/hwmon/w83781d.c | |
parent | 10c08f937d832e1d5a77e65767a6e2c05bc25c69 (diff) |
hwmon: (w83781d) Make ISA interface depend on CONFIG_ISA
Probing the ISA bus on systems without ISA bus may hang the system.
This patch makes the ISA bus related code depend on the kernel
configuration parameter CONFIG_ISA. It moves ISA bus related code
into one #ifdef CONFIG_ISA ... #endif block and adds some helper
function.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83781d.c')
-rw-r--r-- | drivers/hwmon/w83781d.c | 673 |
1 files changed, 393 insertions, 280 deletions
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 1c00d9f7c14d..1a729a749277 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -38,25 +38,24 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/jiffies.h> | 39 | #include <linux/jiffies.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/platform_device.h> | ||
42 | #include <linux/ioport.h> | ||
43 | #include <linux/hwmon.h> | 41 | #include <linux/hwmon.h> |
44 | #include <linux/hwmon-vid.h> | 42 | #include <linux/hwmon-vid.h> |
45 | #include <linux/hwmon-sysfs.h> | 43 | #include <linux/hwmon-sysfs.h> |
46 | #include <linux/sysfs.h> | 44 | #include <linux/sysfs.h> |
47 | #include <linux/err.h> | 45 | #include <linux/err.h> |
48 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | |||
48 | #ifdef CONFIG_ISA | ||
49 | #include <linux/platform_device.h> | ||
50 | #include <linux/ioport.h> | ||
49 | #include <asm/io.h> | 51 | #include <asm/io.h> |
50 | #include "lm75.h" | 52 | #endif |
51 | 53 | ||
52 | /* ISA device, if found */ | 54 | #include "lm75.h" |
53 | static struct platform_device *pdev; | ||
54 | 55 | ||
55 | /* Addresses to scan */ | 56 | /* Addresses to scan */ |
56 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | 57 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, |
57 | 0x2e, 0x2f, I2C_CLIENT_END }; | 58 | 0x2e, 0x2f, I2C_CLIENT_END }; |
58 | static unsigned short isa_address = 0x290; | ||
59 | |||
60 | /* Insmod parameters */ | 59 | /* Insmod parameters */ |
61 | I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); | 60 | I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); |
62 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 61 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " |
@@ -245,13 +244,13 @@ struct w83781d_data { | |||
245 | u8 vrm; | 244 | u8 vrm; |
246 | }; | 245 | }; |
247 | 246 | ||
247 | static struct w83781d_data *w83781d_data_if_isa(void); | ||
248 | static int w83781d_alias_detect(struct i2c_client *client, u8 chipid); | ||
249 | |||
248 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); | 250 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); |
249 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); | 251 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); |
250 | static int w83781d_detach_client(struct i2c_client *client); | 252 | static int w83781d_detach_client(struct i2c_client *client); |
251 | 253 | ||
252 | static int __devinit w83781d_isa_probe(struct platform_device *pdev); | ||
253 | static int __devexit w83781d_isa_remove(struct platform_device *pdev); | ||
254 | |||
255 | static int w83781d_read_value(struct w83781d_data *data, u16 reg); | 254 | static int w83781d_read_value(struct w83781d_data *data, u16 reg); |
256 | static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); | 255 | static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); |
257 | static struct w83781d_data *w83781d_update_device(struct device *dev); | 256 | static struct w83781d_data *w83781d_update_device(struct device *dev); |
@@ -265,16 +264,6 @@ static struct i2c_driver w83781d_driver = { | |||
265 | .detach_client = w83781d_detach_client, | 264 | .detach_client = w83781d_detach_client, |
266 | }; | 265 | }; |
267 | 266 | ||
268 | static struct platform_driver w83781d_isa_driver = { | ||
269 | .driver = { | ||
270 | .owner = THIS_MODULE, | ||
271 | .name = "w83781d", | ||
272 | }, | ||
273 | .probe = w83781d_isa_probe, | ||
274 | .remove = w83781d_isa_remove, | ||
275 | }; | ||
276 | |||
277 | |||
278 | /* following are the sysfs callback functions */ | 267 | /* following are the sysfs callback functions */ |
279 | #define show_in_reg(reg) \ | 268 | #define show_in_reg(reg) \ |
280 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ | 269 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
@@ -836,16 +825,6 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, | |||
836 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, | 825 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, |
837 | show_sensor, store_sensor, 2); | 826 | show_sensor, store_sensor, 2); |
838 | 827 | ||
839 | /* I2C devices get this name attribute automatically, but for ISA devices | ||
840 | we must create it by ourselves. */ | ||
841 | static ssize_t | ||
842 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | ||
843 | { | ||
844 | struct w83781d_data *data = dev_get_drvdata(dev); | ||
845 | return sprintf(buf, "%s\n", data->client.name); | ||
846 | } | ||
847 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
848 | |||
849 | /* This function is called when: | 828 | /* This function is called when: |
850 | * w83781d_driver is inserted (when this module is loaded), for each | 829 | * w83781d_driver is inserted (when this module is loaded), for each |
851 | available adapter | 830 | available adapter |
@@ -855,13 +834,12 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |||
855 | static int | 834 | static int |
856 | w83781d_attach_adapter(struct i2c_adapter *adapter) | 835 | w83781d_attach_adapter(struct i2c_adapter *adapter) |
857 | { | 836 | { |
858 | struct w83781d_data *data; | 837 | struct w83781d_data *data = w83781d_data_if_isa(); |
859 | int err; | 838 | int err; |
860 | 839 | ||
861 | if (!(adapter->class & I2C_CLASS_HWMON)) | 840 | if (!(adapter->class & I2C_CLASS_HWMON)) |
862 | return 0; | 841 | return 0; |
863 | 842 | ||
864 | data = pdev ? platform_get_drvdata(pdev) : NULL; | ||
865 | if (data) | 843 | if (data) |
866 | mutex_lock(&data->update_lock); | 844 | mutex_lock(&data->update_lock); |
867 | err = i2c_probe(adapter, &addr_data, w83781d_detect); | 845 | err = i2c_probe(adapter, &addr_data, w83781d_detect); |
@@ -1037,40 +1015,6 @@ static const struct attribute_group w83781d_group_opt = { | |||
1037 | .attrs = w83781d_attributes_opt, | 1015 | .attrs = w83781d_attributes_opt, |
1038 | }; | 1016 | }; |
1039 | 1017 | ||
1040 | /* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ | ||
1041 | static int w83781d_alias_detect(struct i2c_client *client, u8 chipid) | ||
1042 | { | ||
1043 | struct w83781d_data *i2c, *isa; | ||
1044 | int i; | ||
1045 | |||
1046 | if (!pdev) /* No ISA chip */ | ||
1047 | return 0; | ||
1048 | |||
1049 | i2c = i2c_get_clientdata(client); | ||
1050 | isa = platform_get_drvdata(pdev); | ||
1051 | |||
1052 | if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr) | ||
1053 | return 0; /* Address doesn't match */ | ||
1054 | if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid) | ||
1055 | return 0; /* Chip type doesn't match */ | ||
1056 | |||
1057 | /* We compare all the limit registers, the config register and the | ||
1058 | * interrupt mask registers */ | ||
1059 | for (i = 0x2b; i <= 0x3d; i++) { | ||
1060 | if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i)) | ||
1061 | return 0; | ||
1062 | } | ||
1063 | if (w83781d_read_value(isa, W83781D_REG_CONFIG) != | ||
1064 | w83781d_read_value(i2c, W83781D_REG_CONFIG)) | ||
1065 | return 0; | ||
1066 | for (i = 0x43; i <= 0x46; i++) { | ||
1067 | if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i)) | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | return 1; | ||
1072 | } | ||
1073 | |||
1074 | /* No clean up is done on error, it's up to the caller */ | 1018 | /* No clean up is done on error, it's up to the caller */ |
1075 | static int | 1019 | static int |
1076 | w83781d_create_files(struct device *dev, int kind, int is_isa) | 1020 | w83781d_create_files(struct device *dev, int kind, int is_isa) |
@@ -1167,12 +1111,6 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) | |||
1167 | } | 1111 | } |
1168 | } | 1112 | } |
1169 | 1113 | ||
1170 | if (is_isa) { | ||
1171 | err = device_create_file(&pdev->dev, &dev_attr_name); | ||
1172 | if (err) | ||
1173 | return err; | ||
1174 | } | ||
1175 | |||
1176 | return 0; | 1114 | return 0; |
1177 | } | 1115 | } |
1178 | 1116 | ||
@@ -1381,221 +1319,80 @@ w83781d_detach_client(struct i2c_client *client) | |||
1381 | return 0; | 1319 | return 0; |
1382 | } | 1320 | } |
1383 | 1321 | ||
1384 | static int __devinit | ||
1385 | w83781d_isa_probe(struct platform_device *pdev) | ||
1386 | { | ||
1387 | int err, reg; | ||
1388 | struct w83781d_data *data; | ||
1389 | struct resource *res; | ||
1390 | const char *name; | ||
1391 | |||
1392 | /* Reserve the ISA region */ | ||
1393 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1394 | if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2, | ||
1395 | "w83781d")) { | ||
1396 | err = -EBUSY; | ||
1397 | goto exit; | ||
1398 | } | ||
1399 | |||
1400 | if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) { | ||
1401 | err = -ENOMEM; | ||
1402 | goto exit_release_region; | ||
1403 | } | ||
1404 | mutex_init(&data->lock); | ||
1405 | data->client.addr = res->start; | ||
1406 | i2c_set_clientdata(&data->client, data); | ||
1407 | platform_set_drvdata(pdev, data); | ||
1408 | |||
1409 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); | ||
1410 | switch (reg) { | ||
1411 | case 0x30: | ||
1412 | data->type = w83782d; | ||
1413 | name = "w83782d"; | ||
1414 | break; | ||
1415 | default: | ||
1416 | data->type = w83781d; | ||
1417 | name = "w83781d"; | ||
1418 | } | ||
1419 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
1420 | |||
1421 | /* Initialize the W83781D chip */ | ||
1422 | w83781d_init_device(&pdev->dev); | ||
1423 | |||
1424 | /* Register sysfs hooks */ | ||
1425 | err = w83781d_create_files(&pdev->dev, data->type, 1); | ||
1426 | if (err) | ||
1427 | goto exit_remove_files; | ||
1428 | |||
1429 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | ||
1430 | if (IS_ERR(data->hwmon_dev)) { | ||
1431 | err = PTR_ERR(data->hwmon_dev); | ||
1432 | goto exit_remove_files; | ||
1433 | } | ||
1434 | |||
1435 | return 0; | ||
1436 | |||
1437 | exit_remove_files: | ||
1438 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1439 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1440 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1441 | kfree(data); | ||
1442 | exit_release_region: | ||
1443 | release_region(res->start + W83781D_ADDR_REG_OFFSET, 2); | ||
1444 | exit: | ||
1445 | return err; | ||
1446 | } | ||
1447 | |||
1448 | static int __devexit | ||
1449 | w83781d_isa_remove(struct platform_device *pdev) | ||
1450 | { | ||
1451 | struct w83781d_data *data = platform_get_drvdata(pdev); | ||
1452 | |||
1453 | hwmon_device_unregister(data->hwmon_dev); | ||
1454 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1455 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1456 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1457 | release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2); | ||
1458 | kfree(data); | ||
1459 | |||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | /* The SMBus locks itself, usually, but nothing may access the Winbond between | ||
1464 | bank switches. ISA access must always be locked explicitly! | ||
1465 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | ||
1466 | would slow down the W83781D access and should not be necessary. | ||
1467 | There are some ugly typecasts here, but the good news is - they should | ||
1468 | nowhere else be necessary! */ | ||
1469 | static int | 1322 | static int |
1470 | w83781d_read_value(struct w83781d_data *data, u16 reg) | 1323 | w83781d_read_value_i2c(struct w83781d_data *data, u16 reg) |
1471 | { | 1324 | { |
1472 | struct i2c_client *client = &data->client; | 1325 | struct i2c_client *client = &data->client; |
1473 | int res, word_sized, bank; | 1326 | int res, bank; |
1474 | struct i2c_client *cl; | 1327 | struct i2c_client *cl; |
1475 | 1328 | ||
1476 | mutex_lock(&data->lock); | 1329 | bank = (reg >> 8) & 0x0f; |
1477 | if (!client->driver) { /* ISA device */ | 1330 | if (bank > 2) |
1478 | word_sized = (((reg & 0xff00) == 0x100) | 1331 | /* switch banks */ |
1479 | || ((reg & 0xff00) == 0x200)) | 1332 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, |
1480 | && (((reg & 0x00ff) == 0x50) | 1333 | bank); |
1481 | || ((reg & 0x00ff) == 0x53) | 1334 | if (bank == 0 || bank > 2) { |
1482 | || ((reg & 0x00ff) == 0x55)); | 1335 | res = i2c_smbus_read_byte_data(client, reg & 0xff); |
1483 | if (reg & 0xff00) { | ||
1484 | outb_p(W83781D_REG_BANK, | ||
1485 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1486 | outb_p(reg >> 8, | ||
1487 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1488 | } | ||
1489 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | ||
1490 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); | ||
1491 | if (word_sized) { | ||
1492 | outb_p((reg & 0xff) + 1, | ||
1493 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1494 | res = | ||
1495 | (res << 8) + inb_p(client->addr + | ||
1496 | W83781D_DATA_REG_OFFSET); | ||
1497 | } | ||
1498 | if (reg & 0xff00) { | ||
1499 | outb_p(W83781D_REG_BANK, | ||
1500 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1501 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | ||
1502 | } | ||
1503 | } else { | 1336 | } else { |
1504 | bank = (reg >> 8) & 0x0f; | 1337 | /* switch to subclient */ |
1505 | if (bank > 2) | 1338 | cl = data->lm75[bank - 1]; |
1506 | /* switch banks */ | 1339 | /* convert from ISA to LM75 I2C addresses */ |
1507 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, | 1340 | switch (reg & 0xff) { |
1508 | bank); | 1341 | case 0x50: /* TEMP */ |
1509 | if (bank == 0 || bank > 2) { | 1342 | res = swab16(i2c_smbus_read_word_data(cl, 0)); |
1510 | res = i2c_smbus_read_byte_data(client, reg & 0xff); | 1343 | break; |
1511 | } else { | 1344 | case 0x52: /* CONFIG */ |
1512 | /* switch to subclient */ | 1345 | res = i2c_smbus_read_byte_data(cl, 1); |
1513 | cl = data->lm75[bank - 1]; | 1346 | break; |
1514 | /* convert from ISA to LM75 I2C addresses */ | 1347 | case 0x53: /* HYST */ |
1515 | switch (reg & 0xff) { | 1348 | res = swab16(i2c_smbus_read_word_data(cl, 2)); |
1516 | case 0x50: /* TEMP */ | 1349 | break; |
1517 | res = swab16(i2c_smbus_read_word_data(cl, 0)); | 1350 | case 0x55: /* OVER */ |
1518 | break; | 1351 | default: |
1519 | case 0x52: /* CONFIG */ | 1352 | res = swab16(i2c_smbus_read_word_data(cl, 3)); |
1520 | res = i2c_smbus_read_byte_data(cl, 1); | 1353 | break; |
1521 | break; | ||
1522 | case 0x53: /* HYST */ | ||
1523 | res = swab16(i2c_smbus_read_word_data(cl, 2)); | ||
1524 | break; | ||
1525 | case 0x55: /* OVER */ | ||
1526 | default: | ||
1527 | res = swab16(i2c_smbus_read_word_data(cl, 3)); | ||
1528 | break; | ||
1529 | } | ||
1530 | } | 1354 | } |
1531 | if (bank > 2) | ||
1532 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); | ||
1533 | } | 1355 | } |
1534 | mutex_unlock(&data->lock); | 1356 | if (bank > 2) |
1357 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); | ||
1358 | |||
1535 | return res; | 1359 | return res; |
1536 | } | 1360 | } |
1537 | 1361 | ||
1538 | static int | 1362 | static int |
1539 | w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) | 1363 | w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value) |
1540 | { | 1364 | { |
1541 | struct i2c_client *client = &data->client; | 1365 | struct i2c_client *client = &data->client; |
1542 | int word_sized, bank; | 1366 | int bank; |
1543 | struct i2c_client *cl; | 1367 | struct i2c_client *cl; |
1544 | 1368 | ||
1545 | mutex_lock(&data->lock); | 1369 | bank = (reg >> 8) & 0x0f; |
1546 | if (!client->driver) { /* ISA device */ | 1370 | if (bank > 2) |
1547 | word_sized = (((reg & 0xff00) == 0x100) | 1371 | /* switch banks */ |
1548 | || ((reg & 0xff00) == 0x200)) | 1372 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, |
1549 | && (((reg & 0x00ff) == 0x53) | 1373 | bank); |
1550 | || ((reg & 0x00ff) == 0x55)); | 1374 | if (bank == 0 || bank > 2) { |
1551 | if (reg & 0xff00) { | 1375 | i2c_smbus_write_byte_data(client, reg & 0xff, |
1552 | outb_p(W83781D_REG_BANK, | 1376 | value & 0xff); |
1553 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1554 | outb_p(reg >> 8, | ||
1555 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1556 | } | ||
1557 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | ||
1558 | if (word_sized) { | ||
1559 | outb_p(value >> 8, | ||
1560 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1561 | outb_p((reg & 0xff) + 1, | ||
1562 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1563 | } | ||
1564 | outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET); | ||
1565 | if (reg & 0xff00) { | ||
1566 | outb_p(W83781D_REG_BANK, | ||
1567 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1568 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | ||
1569 | } | ||
1570 | } else { | 1377 | } else { |
1571 | bank = (reg >> 8) & 0x0f; | 1378 | /* switch to subclient */ |
1572 | if (bank > 2) | 1379 | cl = data->lm75[bank - 1]; |
1573 | /* switch banks */ | 1380 | /* convert from ISA to LM75 I2C addresses */ |
1574 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, | 1381 | switch (reg & 0xff) { |
1575 | bank); | 1382 | case 0x52: /* CONFIG */ |
1576 | if (bank == 0 || bank > 2) { | 1383 | i2c_smbus_write_byte_data(cl, 1, value & 0xff); |
1577 | i2c_smbus_write_byte_data(client, reg & 0xff, | 1384 | break; |
1578 | value & 0xff); | 1385 | case 0x53: /* HYST */ |
1579 | } else { | 1386 | i2c_smbus_write_word_data(cl, 2, swab16(value)); |
1580 | /* switch to subclient */ | 1387 | break; |
1581 | cl = data->lm75[bank - 1]; | 1388 | case 0x55: /* OVER */ |
1582 | /* convert from ISA to LM75 I2C addresses */ | 1389 | i2c_smbus_write_word_data(cl, 3, swab16(value)); |
1583 | switch (reg & 0xff) { | 1390 | break; |
1584 | case 0x52: /* CONFIG */ | ||
1585 | i2c_smbus_write_byte_data(cl, 1, value & 0xff); | ||
1586 | break; | ||
1587 | case 0x53: /* HYST */ | ||
1588 | i2c_smbus_write_word_data(cl, 2, swab16(value)); | ||
1589 | break; | ||
1590 | case 0x55: /* OVER */ | ||
1591 | i2c_smbus_write_word_data(cl, 3, swab16(value)); | ||
1592 | break; | ||
1593 | } | ||
1594 | } | 1391 | } |
1595 | if (bank > 2) | ||
1596 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); | ||
1597 | } | 1392 | } |
1598 | mutex_unlock(&data->lock); | 1393 | if (bank > 2) |
1394 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); | ||
1395 | |||
1599 | return 0; | 1396 | return 0; |
1600 | } | 1397 | } |
1601 | 1398 | ||
@@ -1815,6 +1612,255 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
1815 | return data; | 1612 | return data; |
1816 | } | 1613 | } |
1817 | 1614 | ||
1615 | #ifdef CONFIG_ISA | ||
1616 | |||
1617 | /* ISA device, if found */ | ||
1618 | static struct platform_device *pdev; | ||
1619 | |||
1620 | static unsigned short isa_address = 0x290; | ||
1621 | |||
1622 | /* I2C devices get this name attribute automatically, but for ISA devices | ||
1623 | we must create it by ourselves. */ | ||
1624 | static ssize_t | ||
1625 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | ||
1626 | { | ||
1627 | struct w83781d_data *data = dev_get_drvdata(dev); | ||
1628 | return sprintf(buf, "%s\n", data->client.name); | ||
1629 | } | ||
1630 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
1631 | |||
1632 | static struct w83781d_data *w83781d_data_if_isa(void) | ||
1633 | { | ||
1634 | return pdev ? platform_get_drvdata(pdev) : NULL; | ||
1635 | } | ||
1636 | |||
1637 | /* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ | ||
1638 | static int w83781d_alias_detect(struct i2c_client *client, u8 chipid) | ||
1639 | { | ||
1640 | struct w83781d_data *i2c, *isa; | ||
1641 | int i; | ||
1642 | |||
1643 | if (!pdev) /* No ISA chip */ | ||
1644 | return 0; | ||
1645 | |||
1646 | i2c = i2c_get_clientdata(client); | ||
1647 | isa = platform_get_drvdata(pdev); | ||
1648 | |||
1649 | if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr) | ||
1650 | return 0; /* Address doesn't match */ | ||
1651 | if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid) | ||
1652 | return 0; /* Chip type doesn't match */ | ||
1653 | |||
1654 | /* We compare all the limit registers, the config register and the | ||
1655 | * interrupt mask registers */ | ||
1656 | for (i = 0x2b; i <= 0x3d; i++) { | ||
1657 | if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i)) | ||
1658 | return 0; | ||
1659 | } | ||
1660 | if (w83781d_read_value(isa, W83781D_REG_CONFIG) != | ||
1661 | w83781d_read_value(i2c, W83781D_REG_CONFIG)) | ||
1662 | return 0; | ||
1663 | for (i = 0x43; i <= 0x46; i++) { | ||
1664 | if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i)) | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | return 1; | ||
1669 | } | ||
1670 | |||
1671 | static int | ||
1672 | w83781d_read_value_isa(struct w83781d_data *data, u16 reg) | ||
1673 | { | ||
1674 | struct i2c_client *client = &data->client; | ||
1675 | int word_sized, res; | ||
1676 | |||
1677 | word_sized = (((reg & 0xff00) == 0x100) | ||
1678 | || ((reg & 0xff00) == 0x200)) | ||
1679 | && (((reg & 0x00ff) == 0x50) | ||
1680 | || ((reg & 0x00ff) == 0x53) | ||
1681 | || ((reg & 0x00ff) == 0x55)); | ||
1682 | if (reg & 0xff00) { | ||
1683 | outb_p(W83781D_REG_BANK, | ||
1684 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1685 | outb_p(reg >> 8, | ||
1686 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1687 | } | ||
1688 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | ||
1689 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); | ||
1690 | if (word_sized) { | ||
1691 | outb_p((reg & 0xff) + 1, | ||
1692 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1693 | res = | ||
1694 | (res << 8) + inb_p(client->addr + | ||
1695 | W83781D_DATA_REG_OFFSET); | ||
1696 | } | ||
1697 | if (reg & 0xff00) { | ||
1698 | outb_p(W83781D_REG_BANK, | ||
1699 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1700 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | ||
1701 | } | ||
1702 | return res; | ||
1703 | } | ||
1704 | |||
1705 | static void | ||
1706 | w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) | ||
1707 | { | ||
1708 | struct i2c_client *client = &data->client; | ||
1709 | int word_sized; | ||
1710 | |||
1711 | word_sized = (((reg & 0xff00) == 0x100) | ||
1712 | || ((reg & 0xff00) == 0x200)) | ||
1713 | && (((reg & 0x00ff) == 0x53) | ||
1714 | || ((reg & 0x00ff) == 0x55)); | ||
1715 | if (reg & 0xff00) { | ||
1716 | outb_p(W83781D_REG_BANK, | ||
1717 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1718 | outb_p(reg >> 8, | ||
1719 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1720 | } | ||
1721 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | ||
1722 | if (word_sized) { | ||
1723 | outb_p(value >> 8, | ||
1724 | client->addr + W83781D_DATA_REG_OFFSET); | ||
1725 | outb_p((reg & 0xff) + 1, | ||
1726 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1727 | } | ||
1728 | outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET); | ||
1729 | if (reg & 0xff00) { | ||
1730 | outb_p(W83781D_REG_BANK, | ||
1731 | client->addr + W83781D_ADDR_REG_OFFSET); | ||
1732 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | ||
1733 | } | ||
1734 | } | ||
1735 | |||
1736 | /* The SMBus locks itself, usually, but nothing may access the Winbond between | ||
1737 | bank switches. ISA access must always be locked explicitly! | ||
1738 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | ||
1739 | would slow down the W83781D access and should not be necessary. | ||
1740 | There are some ugly typecasts here, but the good news is - they should | ||
1741 | nowhere else be necessary! */ | ||
1742 | static int | ||
1743 | w83781d_read_value(struct w83781d_data *data, u16 reg) | ||
1744 | { | ||
1745 | struct i2c_client *client = &data->client; | ||
1746 | int res; | ||
1747 | |||
1748 | mutex_lock(&data->lock); | ||
1749 | if (client->driver) | ||
1750 | res = w83781d_read_value_i2c(data, reg); | ||
1751 | else | ||
1752 | res = w83781d_read_value_isa(data, reg); | ||
1753 | mutex_unlock(&data->lock); | ||
1754 | return res; | ||
1755 | } | ||
1756 | |||
1757 | static int | ||
1758 | w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) | ||
1759 | { | ||
1760 | struct i2c_client *client = &data->client; | ||
1761 | |||
1762 | mutex_lock(&data->lock); | ||
1763 | if (client->driver) | ||
1764 | w83781d_write_value_i2c(data, reg, value); | ||
1765 | else | ||
1766 | w83781d_write_value_isa(data, reg, value); | ||
1767 | mutex_unlock(&data->lock); | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | static int __devinit | ||
1772 | w83781d_isa_probe(struct platform_device *pdev) | ||
1773 | { | ||
1774 | int err, reg; | ||
1775 | struct w83781d_data *data; | ||
1776 | struct resource *res; | ||
1777 | const char *name; | ||
1778 | |||
1779 | /* Reserve the ISA region */ | ||
1780 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1781 | if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2, | ||
1782 | "w83781d")) { | ||
1783 | err = -EBUSY; | ||
1784 | goto exit; | ||
1785 | } | ||
1786 | |||
1787 | data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL); | ||
1788 | if (!data) { | ||
1789 | err = -ENOMEM; | ||
1790 | goto exit_release_region; | ||
1791 | } | ||
1792 | mutex_init(&data->lock); | ||
1793 | data->client.addr = res->start; | ||
1794 | i2c_set_clientdata(&data->client, data); | ||
1795 | platform_set_drvdata(pdev, data); | ||
1796 | |||
1797 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); | ||
1798 | switch (reg) { | ||
1799 | case 0x30: | ||
1800 | data->type = w83782d; | ||
1801 | name = "w83782d"; | ||
1802 | break; | ||
1803 | default: | ||
1804 | data->type = w83781d; | ||
1805 | name = "w83781d"; | ||
1806 | } | ||
1807 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
1808 | |||
1809 | /* Initialize the W83781D chip */ | ||
1810 | w83781d_init_device(&pdev->dev); | ||
1811 | |||
1812 | /* Register sysfs hooks */ | ||
1813 | err = w83781d_create_files(&pdev->dev, data->type, 1); | ||
1814 | if (err) | ||
1815 | goto exit_remove_files; | ||
1816 | |||
1817 | err = device_create_file(&pdev->dev, &dev_attr_name); | ||
1818 | if (err) | ||
1819 | goto exit_remove_files; | ||
1820 | |||
1821 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | ||
1822 | if (IS_ERR(data->hwmon_dev)) { | ||
1823 | err = PTR_ERR(data->hwmon_dev); | ||
1824 | goto exit_remove_files; | ||
1825 | } | ||
1826 | |||
1827 | return 0; | ||
1828 | |||
1829 | exit_remove_files: | ||
1830 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1831 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1832 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1833 | kfree(data); | ||
1834 | exit_release_region: | ||
1835 | release_region(res->start + W83781D_ADDR_REG_OFFSET, 2); | ||
1836 | exit: | ||
1837 | return err; | ||
1838 | } | ||
1839 | |||
1840 | static int __devexit | ||
1841 | w83781d_isa_remove(struct platform_device *pdev) | ||
1842 | { | ||
1843 | struct w83781d_data *data = platform_get_drvdata(pdev); | ||
1844 | |||
1845 | hwmon_device_unregister(data->hwmon_dev); | ||
1846 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1847 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1848 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1849 | release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2); | ||
1850 | kfree(data); | ||
1851 | |||
1852 | return 0; | ||
1853 | } | ||
1854 | |||
1855 | static struct platform_driver w83781d_isa_driver = { | ||
1856 | .driver = { | ||
1857 | .owner = THIS_MODULE, | ||
1858 | .name = "w83781d", | ||
1859 | }, | ||
1860 | .probe = w83781d_isa_probe, | ||
1861 | .remove = __devexit_p(w83781d_isa_remove), | ||
1862 | }; | ||
1863 | |||
1818 | /* return 1 if a supported chip is found, 0 otherwise */ | 1864 | /* return 1 if a supported chip is found, 0 otherwise */ |
1819 | static int __init | 1865 | static int __init |
1820 | w83781d_isa_found(unsigned short address) | 1866 | w83781d_isa_found(unsigned short address) |
@@ -1951,12 +1997,10 @@ w83781d_isa_device_add(unsigned short address) | |||
1951 | } | 1997 | } |
1952 | 1998 | ||
1953 | static int __init | 1999 | static int __init |
1954 | sensors_w83781d_init(void) | 2000 | w83781d_isa_register(void) |
1955 | { | 2001 | { |
1956 | int res; | 2002 | int res; |
1957 | 2003 | ||
1958 | /* We register the ISA device first, so that we can skip the | ||
1959 | * registration of an I2C interface to the same device. */ | ||
1960 | if (w83781d_isa_found(isa_address)) { | 2004 | if (w83781d_isa_found(isa_address)) { |
1961 | res = platform_driver_register(&w83781d_isa_driver); | 2005 | res = platform_driver_register(&w83781d_isa_driver); |
1962 | if (res) | 2006 | if (res) |
@@ -1968,27 +2012,96 @@ sensors_w83781d_init(void) | |||
1968 | goto exit_unreg_isa_driver; | 2012 | goto exit_unreg_isa_driver; |
1969 | } | 2013 | } |
1970 | 2014 | ||
1971 | res = i2c_add_driver(&w83781d_driver); | ||
1972 | if (res) | ||
1973 | goto exit_unreg_isa_device; | ||
1974 | |||
1975 | return 0; | 2015 | return 0; |
1976 | 2016 | ||
1977 | exit_unreg_isa_device: | 2017 | exit_unreg_isa_driver: |
1978 | platform_device_unregister(pdev); | ||
1979 | exit_unreg_isa_driver: | ||
1980 | platform_driver_unregister(&w83781d_isa_driver); | 2018 | platform_driver_unregister(&w83781d_isa_driver); |
1981 | exit: | 2019 | exit: |
1982 | return res; | 2020 | return res; |
1983 | } | 2021 | } |
1984 | 2022 | ||
1985 | static void __exit | 2023 | static void __exit |
1986 | sensors_w83781d_exit(void) | 2024 | w83781d_isa_unregister(void) |
1987 | { | 2025 | { |
1988 | if (pdev) { | 2026 | if (pdev) { |
1989 | platform_device_unregister(pdev); | 2027 | platform_device_unregister(pdev); |
1990 | platform_driver_unregister(&w83781d_isa_driver); | 2028 | platform_driver_unregister(&w83781d_isa_driver); |
1991 | } | 2029 | } |
2030 | } | ||
2031 | #else /* !CONFIG_ISA */ | ||
2032 | |||
2033 | static struct w83781d_data *w83781d_data_if_isa(void) | ||
2034 | { | ||
2035 | return NULL; | ||
2036 | } | ||
2037 | |||
2038 | static int | ||
2039 | w83781d_alias_detect(struct i2c_client *client, u8 chipid) | ||
2040 | { | ||
2041 | return 0; | ||
2042 | } | ||
2043 | |||
2044 | static int | ||
2045 | w83781d_read_value(struct w83781d_data *data, u16 reg) | ||
2046 | { | ||
2047 | int res; | ||
2048 | |||
2049 | mutex_lock(&data->lock); | ||
2050 | res = w83781d_read_value_i2c(data, reg); | ||
2051 | mutex_unlock(&data->lock); | ||
2052 | |||
2053 | return res; | ||
2054 | } | ||
2055 | |||
2056 | static int | ||
2057 | w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) | ||
2058 | { | ||
2059 | mutex_lock(&data->lock); | ||
2060 | w83781d_write_value_i2c(data, reg, value); | ||
2061 | mutex_unlock(&data->lock); | ||
2062 | |||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static int __init | ||
2067 | w83781d_isa_register(void) | ||
2068 | { | ||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2072 | static void __exit | ||
2073 | w83781d_isa_unregister(void) | ||
2074 | { | ||
2075 | } | ||
2076 | #endif /* CONFIG_ISA */ | ||
2077 | |||
2078 | static int __init | ||
2079 | sensors_w83781d_init(void) | ||
2080 | { | ||
2081 | int res; | ||
2082 | |||
2083 | /* We register the ISA device first, so that we can skip the | ||
2084 | * registration of an I2C interface to the same device. */ | ||
2085 | res = w83781d_isa_register(); | ||
2086 | if (res) | ||
2087 | goto exit; | ||
2088 | |||
2089 | res = i2c_add_driver(&w83781d_driver); | ||
2090 | if (res) | ||
2091 | goto exit_unreg_isa; | ||
2092 | |||
2093 | return 0; | ||
2094 | |||
2095 | exit_unreg_isa: | ||
2096 | w83781d_isa_unregister(); | ||
2097 | exit: | ||
2098 | return res; | ||
2099 | } | ||
2100 | |||
2101 | static void __exit | ||
2102 | sensors_w83781d_exit(void) | ||
2103 | { | ||
2104 | w83781d_isa_unregister(); | ||
1992 | i2c_del_driver(&w83781d_driver); | 2105 | i2c_del_driver(&w83781d_driver); |
1993 | } | 2106 | } |
1994 | 2107 | ||