diff options
| -rw-r--r-- | Documentation/hwmon/lm90 | 39 | ||||
| -rw-r--r-- | Documentation/hwmon/sysfs-interface | 3 | ||||
| -rw-r--r-- | drivers/hwmon/lm90.c | 57 |
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 | ||
| 72 | The different chipsets of the family are not strictly identical, although | 72 | The different chipsets of the family are not strictly identical, although |
| 73 | very similar. This driver doesn't handle any specific feature for now, | 73 | very similar. This driver doesn't handle any specific feature for now, |
| 74 | but could if there ever was a need for it. For reference, here comes a | 74 | with the exception of SMBus PEC. For reference, here comes a non-exhaustive |
| 75 | non-exhaustive list of specific features: | 75 | list of specific features: |
| 76 | 76 | ||
| 77 | LM90: | 77 | LM90: |
| 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 | ||
| 95 | ADT7461 | 96 | ADT7461 |
| 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 | |||
| 119 | other second; reading them more often will do no harm, but will return | 120 | other second; reading them more often will do no harm, but will return |
| 120 | 'old' values. | 121 | 'old' values. |
| 121 | 122 | ||
| 123 | PEC Support | ||
| 124 | ----------- | ||
| 125 | |||
| 126 | The ADM1032 is the only chip of the family which supports PEC. It does | ||
| 127 | not support PEC on all transactions though, so some care must be taken. | ||
| 128 | |||
| 129 | When reading a register value, the PEC byte is computed and sent by the | ||
| 130 | ADM1032 chip. However, in the case of a combined transaction (SMBus Read | ||
| 131 | Byte), the ADM1032 computes the CRC value over only the second half of | ||
| 132 | the message rather than its entirety, because it thinks the first half | ||
| 133 | of the message belongs to a different transaction. As a result, the CRC | ||
| 134 | value differs from what the SMBus master expects, and all reads fail. | ||
| 135 | |||
| 136 | For this reason, the lm90 driver will enable PEC for the ADM1032 only if | ||
| 137 | the bus supports the SMBus Send Byte and Receive Byte transaction types. | ||
| 138 | These transactions will be used to read register values, instead of | ||
| 139 | SMBus Read Byte, and PEC will work properly. | ||
| 140 | |||
| 141 | Additionally, the ADM1032 doesn't support SMBus Send Byte with PEC. | ||
| 142 | Instead, it will try to write the PEC value to the register (because the | ||
| 143 | SMBus Send Byte transaction with PEC is similar to a Write Byte transaction | ||
| 144 | without PEC), which is not what we want. Thus, PEC is explicitely disabled | ||
| 145 | on SMBus Send Byte transactions in the lm90 driver. | ||
| 146 | |||
| 147 | PEC on byte data transactions represents a significant increase in bandwidth | ||
| 148 | usage (+33% for writes, +25% for reads) in normal conditions. With the need | ||
| 149 | to use two SMBus transaction for reads, this overhead jumps to +50%. Worse, | ||
| 150 | two transactions will typically mean twice as much delay waiting for | ||
| 151 | transaction completion, effectively doubling the register cache refresh time. | ||
| 152 | I guess reliability comes at a price, but it's quite expensive this time. | ||
| 153 | |||
| 154 | So, as not everyone might enjoy the slowdown, PEC can be disabled through | ||
| 155 | sysfs. Just write 0 to the "pec" file and PEC will be disabled. Write 1 | ||
| 156 | to 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 | ||
| 273 | eeprom Raw EEPROM data in binary form. | 273 | eeprom Raw EEPROM data in binary form. |
| 274 | Read only. | 274 | Read only. |
| 275 | |||
| 276 | pec 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, | |||
| 345 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); | 345 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); |
| 346 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 346 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
| 347 | 347 | ||
| 348 | /* pec used for ADM1032 only */ | ||
| 349 | static 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 | |||
| 356 | static 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 | |||
| 376 | static 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. */ | ||
| 384 | static 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. */ | ||
| 352 | static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) | 395 | static 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 | ||
| 551 | exit_detach: | 606 | exit_detach: |
