aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2007-10-10 10:30:23 -0400
committerMark M. Hoffman <mhoffman@lightlink.com>2007-10-13 20:37:19 -0400
commitd58df9cd788e6fb4962e1c8d5ba7b8b95d639a44 (patch)
tree90a4d4b4ed5dc30f0e186a835f430bd8be4fb259
parentc09c5184a26158da32801e89d5849d774605f0dd (diff)
hwmon: (w83627hf) don't assume bank 0
The bank switching code assumes that the bank selector is set to 0 when the driver is loaded. This might not be the case. This is exactly the same bug as was fixed in the w83627ehf driver two months ago: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0956895aa6f8dc6a33210967252fd7787652537d In practice, this bug was causing the sensor thermal types to be improperly reported for my W83627THF the first time I was loading the w83627hf driver. From the driver history, I'd say that it has been broken since September 2005 (when we stopped resetting the chip by default at driver load.) Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
-rw-r--r--drivers/hwmon/w83627hf.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 2169d8c8bbe4..20ae425a1980 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -1319,6 +1319,24 @@ static int __devexit w83627hf_remove(struct platform_device *pdev)
1319} 1319}
1320 1320
1321 1321
1322/* Registers 0x50-0x5f are banked */
1323static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
1324{
1325 if ((reg & 0x00f0) == 0x50) {
1326 outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1327 outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
1328 }
1329}
1330
1331/* Not strictly necessary, but play it safe for now */
1332static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
1333{
1334 if (reg & 0xff00) {
1335 outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1336 outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1337 }
1338}
1339
1322static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) 1340static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
1323{ 1341{
1324 int res, word_sized; 1342 int res, word_sized;
@@ -1329,12 +1347,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
1329 && (((reg & 0x00ff) == 0x50) 1347 && (((reg & 0x00ff) == 0x50)
1330 || ((reg & 0x00ff) == 0x53) 1348 || ((reg & 0x00ff) == 0x53)
1331 || ((reg & 0x00ff) == 0x55)); 1349 || ((reg & 0x00ff) == 0x55));
1332 if (reg & 0xff00) { 1350 w83627hf_set_bank(data, reg);
1333 outb_p(W83781D_REG_BANK,
1334 data->addr + W83781D_ADDR_REG_OFFSET);
1335 outb_p(reg >> 8,
1336 data->addr + W83781D_DATA_REG_OFFSET);
1337 }
1338 outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); 1351 outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1339 res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); 1352 res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
1340 if (word_sized) { 1353 if (word_sized) {
@@ -1344,11 +1357,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
1344 (res << 8) + inb_p(data->addr + 1357 (res << 8) + inb_p(data->addr +
1345 W83781D_DATA_REG_OFFSET); 1358 W83781D_DATA_REG_OFFSET);
1346 } 1359 }
1347 if (reg & 0xff00) { 1360 w83627hf_reset_bank(data, reg);
1348 outb_p(W83781D_REG_BANK,
1349 data->addr + W83781D_ADDR_REG_OFFSET);
1350 outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1351 }
1352 mutex_unlock(&data->lock); 1361 mutex_unlock(&data->lock);
1353 return res; 1362 return res;
1354} 1363}
@@ -1419,12 +1428,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
1419 || ((reg & 0xff00) == 0x200)) 1428 || ((reg & 0xff00) == 0x200))
1420 && (((reg & 0x00ff) == 0x53) 1429 && (((reg & 0x00ff) == 0x53)
1421 || ((reg & 0x00ff) == 0x55)); 1430 || ((reg & 0x00ff) == 0x55));
1422 if (reg & 0xff00) { 1431 w83627hf_set_bank(data, reg);
1423 outb_p(W83781D_REG_BANK,
1424 data->addr + W83781D_ADDR_REG_OFFSET);
1425 outb_p(reg >> 8,
1426 data->addr + W83781D_DATA_REG_OFFSET);
1427 }
1428 outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); 1432 outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1429 if (word_sized) { 1433 if (word_sized) {
1430 outb_p(value >> 8, 1434 outb_p(value >> 8,
@@ -1434,11 +1438,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
1434 } 1438 }
1435 outb_p(value & 0xff, 1439 outb_p(value & 0xff,
1436 data->addr + W83781D_DATA_REG_OFFSET); 1440 data->addr + W83781D_DATA_REG_OFFSET);
1437 if (reg & 0xff00) { 1441 w83627hf_reset_bank(data, reg);
1438 outb_p(W83781D_REG_BANK,
1439 data->addr + W83781D_ADDR_REG_OFFSET);
1440 outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1441 }
1442 mutex_unlock(&data->lock); 1442 mutex_unlock(&data->lock);
1443 return 0; 1443 return 0;
1444} 1444}