aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2005-10-26 15:39:40 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 17:02:14 -0400
commitc3df5806cdae6fac678c662b527cb974bef4b60c (patch)
treea510da8447852247907dd6896cdf51c7e3d60844 /drivers
parent8256fe0f40f1cd72f80f2c46fe0ab1638f03a98d (diff)
[PATCH] hwmon: Add PEC support to the lm90 driver
Add PEC support to the lm90 driver. Only the ADM1032 chip supports it, and in a rather tricky way, which is why this patch comes with documentation reinforcements. At least, this demonstrates that the new PEC support logic in i2c-core can properly deal with chips with partial PEC support. As enabling PEC causes a significant performance drop, it can be disabled through a sysfs file (unsurprisingly named "pec"). Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/lm90.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 5acc12ae4e36..fa0793e684fd 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -345,15 +345,63 @@ static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
345static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); 345static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
346static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 346static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
347 347
348/* pec used for ADM1032 only */
349static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
350 char *buf)
351{
352 struct i2c_client *client = to_i2c_client(dev);
353 return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
354}
355
356static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
357 const char *buf, size_t count)
358{
359 struct i2c_client *client = to_i2c_client(dev);
360 long val = simple_strtol(buf, NULL, 10);
361
362 switch (val) {
363 case 0:
364 client->flags &= ~I2C_CLIENT_PEC;
365 break;
366 case 1:
367 client->flags |= I2C_CLIENT_PEC;
368 break;
369 default:
370 return -EINVAL;
371 }
372
373 return count;
374}
375
376static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
377
348/* 378/*
349 * Real code 379 * Real code
350 */ 380 */
351 381
382/* The ADM1032 supports PEC but not on write byte transactions, so we need
383 to explicitely ask for a transaction without PEC. */
384static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
385{
386 return i2c_smbus_xfer(client->adapter, client->addr,
387 client->flags & ~I2C_CLIENT_PEC,
388 I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
389}
390
391/* It is assumed that client->update_lock is held (unless we are in
392 detection or initialization steps). This matters when PEC is enabled,
393 because we don't want the address pointer to change between the write
394 byte and the read byte transactions. */
352static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) 395static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
353{ 396{
354 int err; 397 int err;
355 398
356 err = i2c_smbus_read_byte_data(client, reg); 399 if (client->flags & I2C_CLIENT_PEC) {
400 err = adm1032_write_byte(client, reg);
401 if (err >= 0)
402 err = i2c_smbus_read_byte(client);
403 } else
404 err = i2c_smbus_read_byte_data(client, reg);
357 405
358 if (err < 0) { 406 if (err < 0) {
359 dev_warn(&client->dev, "Register %#02x read failed (%d)\n", 407 dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
@@ -494,6 +542,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
494 name = "lm90"; 542 name = "lm90";
495 } else if (kind == adm1032) { 543 } else if (kind == adm1032) {
496 name = "adm1032"; 544 name = "adm1032";
545 /* The ADM1032 supports PEC, but only if combined
546 transactions are not used. */
547 if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
548 new_client->flags |= I2C_CLIENT_PEC;
497 } else if (kind == lm99) { 549 } else if (kind == lm99) {
498 name = "lm99"; 550 name = "lm99";
499 } else if (kind == lm86) { 551 } else if (kind == lm86) {
@@ -546,6 +598,9 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
546 &sensor_dev_attr_temp2_crit_hyst.dev_attr); 598 &sensor_dev_attr_temp2_crit_hyst.dev_attr);
547 device_create_file(&new_client->dev, &dev_attr_alarms); 599 device_create_file(&new_client->dev, &dev_attr_alarms);
548 600
601 if (new_client->flags & I2C_CLIENT_PEC)
602 device_create_file(&new_client->dev, &dev_attr_pec);
603
549 return 0; 604 return 0;
550 605
551exit_detach: 606exit_detach: