aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/hwmon/lm9039
-rw-r--r--Documentation/hwmon/sysfs-interface3
-rw-r--r--drivers/hwmon/lm90.c57
3 files changed, 96 insertions, 3 deletions
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 2c4cf39471f4..70abf93ea376 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -71,8 +71,8 @@ increased resolution of the remote temperature measurement.
71 71
72The different chipsets of the family are not strictly identical, although 72The different chipsets of the family are not strictly identical, although
73very similar. This driver doesn't handle any specific feature for now, 73very similar. This driver doesn't handle any specific feature for now,
74but could if there ever was a need for it. For reference, here comes a 74with the exception of SMBus PEC. For reference, here comes a non-exhaustive
75non-exhaustive list of specific features: 75list of specific features:
76 76
77LM90: 77LM90:
78 * Filter and alert configuration register at 0xBF. 78 * Filter and alert configuration register at 0xBF.
@@ -91,6 +91,7 @@ ADM1032:
91 * Conversion averaging. 91 * Conversion averaging.
92 * Up to 64 conversions/s. 92 * Up to 64 conversions/s.
93 * ALERT is triggered by open remote sensor. 93 * ALERT is triggered by open remote sensor.
94 * SMBus PEC support for Write Byte and Receive Byte transactions.
94 95
95ADT7461 96ADT7461
96 * Extended temperature range (breaks compatibility) 97 * Extended temperature range (breaks compatibility)
@@ -119,3 +120,37 @@ The lm90 driver will not update its values more frequently than every
119other second; reading them more often will do no harm, but will return 120other second; reading them more often will do no harm, but will return
120'old' values. 121'old' values.
121 122
123PEC Support
124-----------
125
126The ADM1032 is the only chip of the family which supports PEC. It does
127not support PEC on all transactions though, so some care must be taken.
128
129When reading a register value, the PEC byte is computed and sent by the
130ADM1032 chip. However, in the case of a combined transaction (SMBus Read
131Byte), the ADM1032 computes the CRC value over only the second half of
132the message rather than its entirety, because it thinks the first half
133of the message belongs to a different transaction. As a result, the CRC
134value differs from what the SMBus master expects, and all reads fail.
135
136For this reason, the lm90 driver will enable PEC for the ADM1032 only if
137the bus supports the SMBus Send Byte and Receive Byte transaction types.
138These transactions will be used to read register values, instead of
139SMBus Read Byte, and PEC will work properly.
140
141Additionally, the ADM1032 doesn't support SMBus Send Byte with PEC.
142Instead, it will try to write the PEC value to the register (because the
143SMBus Send Byte transaction with PEC is similar to a Write Byte transaction
144without PEC), which is not what we want. Thus, PEC is explicitely disabled
145on SMBus Send Byte transactions in the lm90 driver.
146
147PEC on byte data transactions represents a significant increase in bandwidth
148usage (+33% for writes, +25% for reads) in normal conditions. With the need
149to use two SMBus transaction for reads, this overhead jumps to +50%. Worse,
150two transactions will typically mean twice as much delay waiting for
151transaction completion, effectively doubling the register cache refresh time.
152I guess reliability comes at a price, but it's quite expensive this time.
153
154So, as not everyone might enjoy the slowdown, PEC can be disabled through
155sysfs. Just write 0 to the "pec" file and PEC will be disabled. Write 1
156to that file to enable PEC again.
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index 346400519d0d..764cdc5480e7 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -272,3 +272,6 @@ beep_mask Bitmask for beep.
272 272
273eeprom Raw EEPROM data in binary form. 273eeprom Raw EEPROM data in binary form.
274 Read only. 274 Read only.
275
276pec Enable or disable PEC (SMBus only)
277 Read/Write
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: