diff options
-rw-r--r-- | Documentation/hwmon/lm90.rst | 38 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 3 | ||||
-rw-r--r-- | drivers/hwmon/lm90.c | 119 |
3 files changed, 129 insertions, 31 deletions
diff --git a/Documentation/hwmon/lm90.rst b/Documentation/hwmon/lm90.rst index e947e609990b..53429f79b819 100644 --- a/Documentation/hwmon/lm90.rst +++ b/Documentation/hwmon/lm90.rst @@ -73,6 +73,36 @@ Supported chips: https://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A + * Analog Devices ADT7481 + + Prefix: 'adt7481' + + Addresses scanned: I2C 0x4b and 0x4c + + Datasheet: Publicly available at the ON Semiconductor website + + https://www.onsemi.com/PowerSolutions/product.do?id=ADT7481 + + * Analog Devices ADT7482 + + Prefix: 'adt7482' + + Addresses scanned: I2C 0x4c + + Datasheet: Publicly available at the ON Semiconductor website + + https://www.onsemi.com/PowerSolutions/product.do?id=ADT7482 + + * Analog Devices ADT7483A + + Prefix: 'adt7483a' + + Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e + + Datasheet: Publicly available at the ON Semiconductor website + + https://www.onsemi.com/PowerSolutions/product.do?id=ADT7483A + * ON Semiconductor NCT1008 Prefix: 'nct1008' @@ -323,6 +353,14 @@ ADT7461, ADT7461A, NCT1008: * Extended temperature range (breaks compatibility) * Lower resolution for remote temperature * SMBus PEC support for Write Byte and Receive Byte transactions. + * 10 bit temperature resolution + +ADT7481, ADT7482, ADT7483: + * Temperature offset register + * SMBus PEC support + * 10 bit temperature resolution for external sensors + * Two remote sensors + * Selectable address (ADT7483) MAX6646, MAX6647, MAX6649: * Better local resolution diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 590d3d550acb..df54628bd36b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1358,7 +1358,8 @@ config SENSORS_LM90 depends on I2C help If you say yes here you get support for National Semiconductor LM90, - LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, + LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, ADT7461A, + ADT7481, ADT7482, and ADT7483A, Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658, MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG, diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index fded11b0003e..a915d0356d57 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -64,6 +64,10 @@ * and extended mode. They are mostly compatible with LM90 except for a data * format difference for the temperature value registers. * + * This driver also supports ADT7481, ADT7482, and ADT7483 from Analog Devices + * / ON Semiconductor. The chips are similar to ADT7461 but support two external + * temperature sensors. + * * This driver also supports the SA56004 from Philips. This device is * pin-compatible with the LM86, the ED/EDP parts are also address-compatible. * @@ -114,7 +118,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; -enum chips { adm1032, adt7461, adt7461a, g781, lm86, lm90, lm99, +enum chips { adm1032, adt7461, adt7461a, adt7481, g781, lm86, lm90, lm99, max6646, max6648, max6654, max6657, max6659, max6680, max6696, sa56004, tmp451, tmp461, w83l771, }; @@ -164,6 +168,13 @@ enum chips { adm1032, adt7461, adt7461a, g781, lm86, lm90, lm99, #define TMP461_REG_CHEN 0x16 #define TMP461_REG_DFC 0x24 +/* ADT7481 registers */ +#define ADT7481_REG_STATUS2 0x23 +#define ADT7481_REG_CONFIG2 0x24 + +#define ADT7481_REG_MAN_ID 0x3e +#define ADT7481_REG_CHIP_ID 0x3d + /* Device features */ #define LM90_HAVE_EXTENDED_TEMP BIT(0) /* extended temperature support */ #define LM90_HAVE_OFFSET BIT(1) /* temperature offset register */ @@ -191,6 +202,7 @@ enum chips { adm1032, adt7461, adt7461a, g781, lm86, lm90, lm99, #define LM90_STATUS_LHIGH BIT(6) /* local high temp limit tripped */ #define LM90_STATUS_BUSY BIT(7) /* conversion is ongoing */ +/* MAX6695/6696 and ADT7481 2nd status register */ #define MAX6696_STATUS2_R2THRM BIT(1) /* remote2 THERM limit tripped */ #define MAX6696_STATUS2_R2OPEN BIT(2) /* remote2 is an open circuit */ #define MAX6696_STATUS2_R2LOW BIT(3) /* remote2 low temp limit tripped */ @@ -207,6 +219,9 @@ static const struct i2c_device_id lm90_id[] = { { "adm1032", adm1032 }, { "adt7461", adt7461 }, { "adt7461a", adt7461a }, + { "adt7481", adt7481 }, + { "adt7482", adt7481 }, + { "adt7483a", adt7481 }, { "g781", g781 }, { "lm90", lm90 }, { "lm86", lm86 }, @@ -344,6 +359,7 @@ struct lm90_params { /* Upper 8 bits for max6695/96 */ u8 max_convrate; /* Maximum conversion rate register value */ u8 resolution; /* 16-bit resolution (default 11 bit) */ + u8 reg_status2; /* 2nd status register (optional) */ u8 reg_local_ext; /* Extended local temp register (optional) */ }; @@ -376,6 +392,16 @@ static const struct lm90_params lm90_params[] = { .alert_alarms = 0x7c, .max_convrate = 10, }, + [adt7481] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT + | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP + | LM90_HAVE_UNSIGNED_TEMP | LM90_HAVE_PEC + | LM90_HAVE_TEMP3 | LM90_HAVE_CRIT, + .alert_alarms = 0x1c7c, + .max_convrate = 11, + .resolution = 10, + .reg_status2 = ADT7481_REG_STATUS2, + }, [g781] = { .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT @@ -453,6 +479,7 @@ static const struct lm90_params lm90_params[] = { | LM90_HAVE_ALARMS, .alert_alarms = 0x1c7c, .max_convrate = 6, + .reg_status2 = MAX6696_REG_STATUS2, .reg_local_ext = MAX6657_REG_LOCAL_TEMPL, }, [w83l771] = { @@ -549,6 +576,7 @@ struct lm90_data { u16 alert_alarms; /* Which alarm bits trigger ALERT# */ /* Upper 8 bits for max6695/96 */ u8 max_convrate; /* Maximum conversion rate */ + u8 reg_status2; /* 2nd status register (optional) */ u8 reg_local_ext; /* local extension register offset */ /* registers values */ @@ -679,18 +707,14 @@ static int lm90_update_confreg(struct lm90_data *data, u8 config) * various registers have different meanings as a result of selecting a * non-default remote channel. */ -static int lm90_select_remote_channel(struct lm90_data *data, int channel) +static int lm90_select_remote_channel(struct lm90_data *data, bool second) { - int err = 0; + u8 config = data->config & ~0x08; - if (data->kind == max6696) { - u8 config = data->config & ~0x08; + if (second) + config |= 0x08; - if (channel) - config |= 0x08; - err = lm90_update_confreg(data, config); - } - return err; + return lm90_update_confreg(data, config); } static int lm90_write_convrate(struct lm90_data *data, int val) @@ -806,8 +830,8 @@ static int lm90_update_limits(struct device *dev) data->temp[REMOTE_EMERG] = val << 8; } - if (data->kind == max6696) { - val = lm90_select_remote_channel(data, 1); + if (data->flags & LM90_HAVE_TEMP3) { + val = lm90_select_remote_channel(data, true); if (val < 0) return val; @@ -816,10 +840,12 @@ static int lm90_update_limits(struct device *dev) return val; data->temp[REMOTE2_CRIT] = val << 8; - val = lm90_read_reg(client, MAX6659_REG_REMOTE_EMERG); - if (val < 0) - return val; - data->temp[REMOTE2_EMERG] = val << 8; + if (data->flags & LM90_HAVE_EMERGENCY) { + val = lm90_read_reg(client, MAX6659_REG_REMOTE_EMERG); + if (val < 0) + return val; + data->temp[REMOTE2_EMERG] = val << 8; + } val = lm90_read_reg(client, LM90_REG_REMOTE_LOWH); if (val < 0) @@ -831,7 +857,7 @@ static int lm90_update_limits(struct device *dev) return val; data->temp[REMOTE2_HIGH] = val << 8; - lm90_select_remote_channel(data, 0); + lm90_select_remote_channel(data, false); } return 0; @@ -914,8 +940,8 @@ static int lm90_update_alarms_locked(struct lm90_data *data, bool force) return val; alarms = val & ~LM90_STATUS_BUSY; - if (data->kind == max6696) { - val = lm90_read_reg(client, MAX6696_REG_STATUS2); + if (data->reg_status2) { + val = lm90_read_reg(client, data->reg_status2); if (val < 0) return val; alarms |= val << 8; @@ -1037,20 +1063,20 @@ static int lm90_update_device(struct device *dev) return val; data->temp[REMOTE_TEMP] = val; - if (data->kind == max6696) { - val = lm90_select_remote_channel(data, 1); + if (data->flags & LM90_HAVE_TEMP3) { + val = lm90_select_remote_channel(data, true); if (val < 0) return val; val = lm90_read16(client, LM90_REG_REMOTE_TEMPH, LM90_REG_REMOTE_TEMPL, true); if (val < 0) { - lm90_select_remote_channel(data, 0); + lm90_select_remote_channel(data, false); return val; } data->temp[REMOTE2_TEMP] = val; - lm90_select_remote_channel(data, 0); + lm90_select_remote_channel(data, false); } val = lm90_update_alarms_locked(data, false); @@ -1207,7 +1233,7 @@ static int lm90_set_temp(struct lm90_data *data, int index, int channel, long va lm90_temp_get_resolution(data, index)); if (channel > 1) - lm90_select_remote_channel(data, 1); + lm90_select_remote_channel(data, true); err = lm90_write_reg(client, regh, data->temp[index] >> 8); if (err < 0) @@ -1216,7 +1242,7 @@ static int lm90_set_temp(struct lm90_data *data, int index, int channel, long va err = lm90_write_reg(client, regl, data->temp[index] & 0xff); deselect: if (channel > 1) - lm90_select_remote_channel(data, 0); + lm90_select_remote_channel(data, false); return err; } @@ -1568,9 +1594,15 @@ static const char *lm90_detect_national(struct i2c_client *client, int chip_id, static const char *lm90_detect_analog(struct i2c_client *client, int chip_id, int config1, int convrate) { + int config2 = i2c_smbus_read_byte_data(client, ADT7481_REG_CONFIG2); + int man_id2 = i2c_smbus_read_byte_data(client, ADT7481_REG_MAN_ID); + int chip_id2 = i2c_smbus_read_byte_data(client, ADT7481_REG_CHIP_ID); int address = client->addr; const char *name = NULL; + if (config2 < 0 || man_id2 < 0 || chip_id2 < 0) + return NULL; + switch (chip_id) { case 0x40 ... 0x4f: /* ADM1032 */ if ((address == 0x4c || address == 0x4d) && !(config1 & 0x3f) && @@ -1592,6 +1624,28 @@ static const char *lm90_detect_analog(struct i2c_client *client, int chip_id, convrate <= 0x0a) name = "adt7461a"; break; + case 0x62: /* ADT7481, undocumented */ + if (man_id2 == 0x41 && chip_id2 == 0x81 && + (address == 0x4b || address == 0x4c) && !(config1 & 0x10) && + !(config2 & 0x7f) && (convrate & 0x0f) <= 0x0b) { + name = "adt7481"; + } + break; + case 0x65: /* ADT7482, datasheet */ + case 0x75: /* ADT7482, real chip */ + if (man_id2 == 0x41 && chip_id2 == 0x82 && + address == 0x4c && !(config1 & 0x10) && !(config2 & 0x7f) && + convrate <= 0x0a) + name = "adt7482"; + break; + case 0x94: /* ADT7483 */ + if (man_id2 == 0x41 && chip_id2 == 0x83 && + ((address >= 0x18 && address <= 0x1a) || + (address >= 0x29 && address <= 0x2b) || + (address >= 0x4c && address <= 0x4e)) && + !(config1 & 0x10) && !(config2 & 0x7f) && convrate <= 0x0a) + name = "adt7483a"; + break; default: break; } @@ -1958,9 +2012,9 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data) config |= 0x20; /* - * Select external channel 0 for max6695/96 + * Select external channel 0 for devices with three sensors */ - if (data->kind == max6696) + if (data->flags & LM90_HAVE_TEMP3) config &= ~0x08; /* @@ -2119,13 +2173,18 @@ static int lm90_probe(struct i2c_client *client) data->channel_config[2] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_CRIT_HYST | - HWMON_T_EMERGENCY | HWMON_T_EMERGENCY_HYST | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | - HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY_ALARM | - HWMON_T_FAULT; + HWMON_T_CRIT_ALARM | HWMON_T_FAULT; + if (data->flags & LM90_HAVE_EMERGENCY) { + data->channel_config[2] |= HWMON_T_EMERGENCY | + HWMON_T_EMERGENCY_HYST; + } + if (data->flags & LM90_HAVE_EMERGENCY_ALARM) + data->channel_config[2] |= HWMON_T_EMERGENCY_ALARM; } data->reg_local_ext = lm90_params[data->kind].reg_local_ext; + data->reg_status2 = lm90_params[data->kind].reg_status2; /* Set maximum conversion rate */ data->max_convrate = lm90_params[data->kind].max_convrate; |