A couple of lm90 driver fixes. None of them are critical,
 but they should nevertheless be fixed.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmHHQUwACgkQyx8mb86f
 mYEZ6RAAh7t8ePVhgZvy26q0Lz86xmle3npou6GspvJywxtaMIxHb9ojffGp3mpS
 64TksTkgV0f7d+hWcB1CuY2rJB4jt1oGjfV0waYzM6kduKSRwxsauH556rfgfz27
 quauK152uQKxFP3p/lI040lQKxa3kUnM+xj0+7FFvimaJe05zEMMJqt6DqHJ4LTF
 qqd9v4gb9aIxrDKECYVohagYXL5P5dsmtGsrY4rqxtUUC/cmLXzTYY4Uyf7Bz96h
 HQlidtMYL1VyLAin/E2VDCbSwKqG/uhLc4dxHQ8MjDgbKfWCdwSWEKgjRIAw9P8j
 lK8d8eB82wm1arDXdndSZg4Iww+SekZtbv5EgRDDEOxuNzq5hyydbmd5ECxBqiot
 WkV0vrIG8x1hXij2OH+dIpfIGqcQHKf4NIVPQRHkVebgAywVxsn2uoOl3aaE6fZI
 HjHR6dbEd9dhTwQrZIOUbPnRaNljq0a1HFs5P3N5m91iOW/f93+IdSAxWN1aWIsH
 nWPrXvMFRrE+1FjNdnplPZ+VxUHjkeYXy5bWi0Jv6RmZyrcHDbBei5Dv7/7y7Qje
 HHp1F/JZ1wYYg1S75ludDs9DT4BEuWMOcNffB3WeZrzpSTOgeUbDl/u1nlyVQ8lk
 Oh+XdSc+S/ibNpmEaOSMFpBxc2/E/MaCPLj0sZ1NW2iv8xA4iLk=
 =JB4V
 -----END PGP SIGNATURE-----

Merge tag 'hwmon-for-v5.16-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fixes from Guenter Roeck:
 "A couple of lm90 driver fixes. None of them are critical, but they
  should nevertheless be fixed"

* tag 'hwmon-for-v5.16-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (lm90) Do not report 'busy' status bit as alarm
  hwmom: (lm90) Fix citical alarm status for MAX6680/MAX6681
  hwmon: (lm90) Drop critical attribute support for MAX6654
  hwmon: (lm90) Prevent integer overflow/underflow in hysteresis calculations
  hwmon: (lm90) Fix usage of CONFIG2 register in detect function
This commit is contained in:
Linus Torvalds 2021-12-25 13:08:22 -08:00
Родитель 5b5e3d0347 cdc5287aca
Коммит e2ae0d4a6b
1 изменённых файлов: 62 добавлений и 44 удалений

Просмотреть файл

@ -35,13 +35,14 @@
* explicitly as max6659, or if its address is not 0x4c. * explicitly as max6659, or if its address is not 0x4c.
* These chips lack the remote temperature offset feature. * These chips lack the remote temperature offset feature.
* *
* This driver also supports the MAX6654 chip made by Maxim. This chip can * This driver also supports the MAX6654 chip made by Maxim. This chip can be
* be at 9 different addresses, similar to MAX6680/MAX6681. The MAX6654 is * at 9 different addresses, similar to MAX6680/MAX6681. The MAX6654 is similar
* otherwise similar to MAX6657/MAX6658/MAX6659. Extended range is available * to MAX6657/MAX6658/MAX6659, but does not support critical temperature
* by setting the configuration register accordingly, and is done during * limits. Extended range is available by setting the configuration register
* initialization. Extended precision is only available at conversion rates * accordingly, and is done during initialization. Extended precision is only
* of 1 Hz and slower. Note that extended precision is not enabled by * available at conversion rates of 1 Hz and slower. Note that extended
* default, as this driver initializes all chips to 2 Hz by design. * precision is not enabled by default, as this driver initializes all chips
* to 2 Hz by design.
* *
* This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and
* MAX6692 chips made by Maxim. These are again similar to the LM86, * MAX6692 chips made by Maxim. These are again similar to the LM86,
@ -188,6 +189,8 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */
#define LM90_HAVE_EXTENDED_TEMP (1 << 8) /* extended temperature support*/ #define LM90_HAVE_EXTENDED_TEMP (1 << 8) /* extended temperature support*/
#define LM90_PAUSE_FOR_CONFIG (1 << 9) /* Pause conversion for config */ #define LM90_PAUSE_FOR_CONFIG (1 << 9) /* Pause conversion for config */
#define LM90_HAVE_CRIT (1 << 10)/* Chip supports CRIT/OVERT register */
#define LM90_HAVE_CRIT_ALRM_SWP (1 << 11)/* critical alarm bits swapped */
/* LM90 status */ /* LM90 status */
#define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */ #define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */
@ -197,6 +200,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define LM90_STATUS_RHIGH (1 << 4) /* remote high temp limit tripped */ #define LM90_STATUS_RHIGH (1 << 4) /* remote high temp limit tripped */
#define LM90_STATUS_LLOW (1 << 5) /* local low temp limit tripped */ #define LM90_STATUS_LLOW (1 << 5) /* local low temp limit tripped */
#define LM90_STATUS_LHIGH (1 << 6) /* local high temp limit tripped */ #define LM90_STATUS_LHIGH (1 << 6) /* local high temp limit tripped */
#define LM90_STATUS_BUSY (1 << 7) /* conversion is ongoing */
#define MAX6696_STATUS2_R2THRM (1 << 1) /* remote2 THERM limit tripped */ #define MAX6696_STATUS2_R2THRM (1 << 1) /* remote2 THERM limit tripped */
#define MAX6696_STATUS2_R2OPEN (1 << 2) /* remote2 is an open circuit */ #define MAX6696_STATUS2_R2OPEN (1 << 2) /* remote2 is an open circuit */
@ -354,38 +358,43 @@ struct lm90_params {
static const struct lm90_params lm90_params[] = { static const struct lm90_params lm90_params[] = {
[adm1032] = { [adm1032] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT, | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 10, .max_convrate = 10,
}, },
[adt7461] = { [adt7461] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP
| LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 10, .max_convrate = 10,
}, },
[g781] = { [g781] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT, | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
}, },
[lm86] = { [lm86] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_CRIT,
.alert_alarms = 0x7b, .alert_alarms = 0x7b,
.max_convrate = 9, .max_convrate = 9,
}, },
[lm90] = { [lm90] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_CRIT,
.alert_alarms = 0x7b, .alert_alarms = 0x7b,
.max_convrate = 9, .max_convrate = 9,
}, },
[lm99] = { [lm99] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_CRIT,
.alert_alarms = 0x7b, .alert_alarms = 0x7b,
.max_convrate = 9, .max_convrate = 9,
}, },
[max6646] = { [max6646] = {
.flags = LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 6, .max_convrate = 6,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
@ -396,50 +405,51 @@ static const struct lm90_params lm90_params[] = {
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6657] = { [max6657] = {
.flags = LM90_PAUSE_FOR_CONFIG, .flags = LM90_PAUSE_FOR_CONFIG | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6659] = { [max6659] = {
.flags = LM90_HAVE_EMERGENCY, .flags = LM90_HAVE_EMERGENCY | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6680] = { [max6680] = {
.flags = LM90_HAVE_OFFSET, .flags = LM90_HAVE_OFFSET | LM90_HAVE_CRIT
| LM90_HAVE_CRIT_ALRM_SWP,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 7, .max_convrate = 7,
}, },
[max6696] = { [max6696] = {
.flags = LM90_HAVE_EMERGENCY .flags = LM90_HAVE_EMERGENCY
| LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3 | LM90_HAVE_CRIT,
.alert_alarms = 0x1c7c, .alert_alarms = 0x1c7c,
.max_convrate = 6, .max_convrate = 6,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[w83l771] = { [w83l771] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
}, },
[sa56004] = { [sa56004] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT,
.alert_alarms = 0x7b, .alert_alarms = 0x7b,
.max_convrate = 9, .max_convrate = 9,
.reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL,
}, },
[tmp451] = { [tmp451] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 9, .max_convrate = 9,
.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
}, },
[tmp461] = { [tmp461] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 9, .max_convrate = 9,
.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
@ -668,20 +678,22 @@ static int lm90_update_limits(struct device *dev)
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
int val; int val;
val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT); if (data->flags & LM90_HAVE_CRIT) {
if (val < 0) val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT);
return val; if (val < 0)
data->temp8[LOCAL_CRIT] = val; return val;
data->temp8[LOCAL_CRIT] = val;
val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT); val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT);
if (val < 0) if (val < 0)
return val; return val;
data->temp8[REMOTE_CRIT] = val; data->temp8[REMOTE_CRIT] = val;
val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST); val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST);
if (val < 0) if (val < 0)
return val; return val;
data->temp_hyst = val; data->temp_hyst = val;
}
val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH); val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH);
if (val < 0) if (val < 0)
@ -809,7 +821,7 @@ static int lm90_update_device(struct device *dev)
val = lm90_read_reg(client, LM90_REG_R_STATUS); val = lm90_read_reg(client, LM90_REG_R_STATUS);
if (val < 0) if (val < 0)
return val; return val;
data->alarms = val; /* lower 8 bit of alarms */ data->alarms = val & ~LM90_STATUS_BUSY;
if (data->kind == max6696) { if (data->kind == max6696) {
val = lm90_select_remote_channel(data, 1); val = lm90_select_remote_channel(data, 1);
@ -1160,8 +1172,8 @@ static int lm90_set_temphyst(struct lm90_data *data, long val)
else else
temp = temp_from_s8(data->temp8[LOCAL_CRIT]); temp = temp_from_s8(data->temp8[LOCAL_CRIT]);
/* prevent integer underflow */ /* prevent integer overflow/underflow */
val = max(val, -128000l); val = clamp_val(val, -128000l, 255000l);
data->temp_hyst = hyst_to_reg(temp - val); data->temp_hyst = hyst_to_reg(temp - val);
err = i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, err = i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
@ -1192,6 +1204,7 @@ static const u8 lm90_temp_emerg_index[3] = {
static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 }; static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 };
static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 }; static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 };
static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 }; static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 };
static const u8 lm90_crit_alarm_bits_swapped[3] = { 1, 0, 9 };
static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 }; static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 };
static const u8 lm90_fault_bits[3] = { 0, 2, 10 }; static const u8 lm90_fault_bits[3] = { 0, 2, 10 };
@ -1217,7 +1230,10 @@ static int lm90_temp_read(struct device *dev, u32 attr, int channel, long *val)
*val = (data->alarms >> lm90_max_alarm_bits[channel]) & 1; *val = (data->alarms >> lm90_max_alarm_bits[channel]) & 1;
break; break;
case hwmon_temp_crit_alarm: case hwmon_temp_crit_alarm:
*val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1; if (data->flags & LM90_HAVE_CRIT_ALRM_SWP)
*val = (data->alarms >> lm90_crit_alarm_bits_swapped[channel]) & 1;
else
*val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1;
break; break;
case hwmon_temp_emergency_alarm: case hwmon_temp_emergency_alarm:
*val = (data->alarms >> lm90_emergency_alarm_bits[channel]) & 1; *val = (data->alarms >> lm90_emergency_alarm_bits[channel]) & 1;
@ -1465,12 +1481,11 @@ static int lm90_detect(struct i2c_client *client,
if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0) if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
return -ENODEV; return -ENODEV;
if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) { if (man_id == 0x01 || man_id == 0x5C || man_id == 0xA1) {
config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2); config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
if (config2 < 0) if (config2 < 0)
return -ENODEV; return -ENODEV;
} else }
config2 = 0; /* Make compiler happy */
if ((address == 0x4C || address == 0x4D) if ((address == 0x4C || address == 0x4D)
&& man_id == 0x01) { /* National Semiconductor */ && man_id == 0x01) { /* National Semiconductor */
@ -1903,11 +1918,14 @@ static int lm90_probe(struct i2c_client *client)
info->config = data->channel_config; info->config = data->channel_config;
data->channel_config[0] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | data->channel_config[0] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM;
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM;
data->channel_config[1] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | data->channel_config[1] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | HWMON_T_FAULT;
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT;
if (data->flags & LM90_HAVE_CRIT) {
data->channel_config[0] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST;
data->channel_config[1] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST;
}
if (data->flags & LM90_HAVE_OFFSET) if (data->flags & LM90_HAVE_OFFSET)
data->channel_config[1] |= HWMON_T_OFFSET; data->channel_config[1] |= HWMON_T_OFFSET;