Commit d4b94e1f authored by Juerg Haefliger's avatar Juerg Haefliger Committed by Jean Delvare

hwmon: (dme1737) Add support for in7 for SCH5127

Add support for the 1.5V voltage monitoring input (in7) of the
SMSC SCH5127 chip.
Signed-off-by: default avatarJuerg Haefliger <juergh@gmail.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 7a1b76f2
...@@ -42,7 +42,7 @@ Description ...@@ -42,7 +42,7 @@ Description
This driver implements support for the hardware monitoring capabilities of the This driver implements support for the hardware monitoring capabilities of the
SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, SCH311x, SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, SCH311x,
and SCH5127 Super-I/O chips. These chips feature monitoring of 3 temp sensors and SCH5127 Super-I/O chips. These chips feature monitoring of 3 temp sensors
temp[1-3] (2 remote diodes and 1 internal), 7 voltages in[0-6] (6 external and temp[1-3] (2 remote diodes and 1 internal), 8 voltages in[0-7] (7 external and
1 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement 1 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement
up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and
automatically. automatically.
...@@ -105,6 +105,7 @@ SCH5127: ...@@ -105,6 +105,7 @@ SCH5127:
in4: V1_IN 0V - 1.5V in4: V1_IN 0V - 1.5V
in5: VTR (+3.3V standby) 0V - 4.38V in5: VTR (+3.3V standby) 0V - 4.38V
in6: Vbat (+3.0V) 0V - 4.38V in6: Vbat (+3.0V) 0V - 4.38V
in7: Vtrip (+1.5V) 0V - 1.99V
Each voltage input has associated min and max limits which trigger an alarm Each voltage input has associated min and max limits which trigger an alarm
when crossed. when crossed.
...@@ -217,10 +218,10 @@ cpu0_vid RO CPU core reference voltage in ...@@ -217,10 +218,10 @@ cpu0_vid RO CPU core reference voltage in
vrm RW Voltage regulator module version vrm RW Voltage regulator module version
number. number.
in[0-6]_input RO Measured voltage in millivolts. in[0-7]_input RO Measured voltage in millivolts.
in[0-6]_min RW Low limit for voltage input. in[0-7]_min RW Low limit for voltage input.
in[0-6]_max RW High limit for voltage input. in[0-7]_max RW High limit for voltage input.
in[0-6]_alarm RO Voltage input alarm. Returns 1 if in[0-7]_alarm RO Voltage input alarm. Returns 1 if
voltage input is or went outside the voltage input is or went outside the
associated min-max range, 0 otherwise. associated min-max range, 0 otherwise.
...@@ -324,3 +325,4 @@ fan5 opt opt ...@@ -324,3 +325,4 @@ fan5 opt opt
pwm5 opt opt pwm5 opt opt
fan6 opt opt fan6 opt opt
pwm6 opt opt pwm6 opt opt
in7 yes
...@@ -77,12 +77,14 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; ...@@ -77,12 +77,14 @@ enum chips { dme1737, sch5027, sch311x, sch5127 };
* in4 +12V * in4 +12V
* in5 VTR (+3.3V stby) * in5 VTR (+3.3V stby)
* in6 Vbat * in6 Vbat
* in7 Vtrip (sch5127 only)
* *
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
/* Voltages (in) numbered 0-6 (ix) */ /* Voltages (in) numbered 0-7 (ix) */
#define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) \ #define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) : \
: 0x94 + (ix)) (ix) < 7 ? 0x94 + (ix) : \
0x1f)
#define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ #define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \
: 0x91 + (ix) * 2) : 0x91 + (ix) * 2)
#define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ #define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \
...@@ -101,10 +103,11 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; ...@@ -101,10 +103,11 @@ enum chips { dme1737, sch5027, sch311x, sch5127 };
* IN_TEMP_LSB(1) = [temp3, temp1] * IN_TEMP_LSB(1) = [temp3, temp1]
* IN_TEMP_LSB(2) = [in4, temp2] * IN_TEMP_LSB(2) = [in4, temp2]
* IN_TEMP_LSB(3) = [in3, in0] * IN_TEMP_LSB(3) = [in3, in0]
* IN_TEMP_LSB(4) = [in2, in1] */ * IN_TEMP_LSB(4) = [in2, in1]
* IN_TEMP_LSB(5) = [res, in7] */
#define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix)) #define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix))
static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0}; static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0, 5};
static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4}; static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4, 4};
static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1}; static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1};
static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0};
...@@ -145,7 +148,7 @@ static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; ...@@ -145,7 +148,7 @@ static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0};
#define DME1737_REG_ALARM1 0x41 #define DME1737_REG_ALARM1 0x41
#define DME1737_REG_ALARM2 0x42 #define DME1737_REG_ALARM2 0x42
#define DME1737_REG_ALARM3 0x83 #define DME1737_REG_ALARM3 0x83
static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17}; static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17, 18};
static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6};
static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
...@@ -190,6 +193,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; ...@@ -190,6 +193,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
#define HAS_PWM_MIN (1 << 4) /* bit 4 */ #define HAS_PWM_MIN (1 << 4) /* bit 4 */
#define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ #define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */
#define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ #define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */
#define HAS_IN7 (1 << 17) /* bit 17 */
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Data structures and manipulation thereof * Data structures and manipulation thereof
...@@ -213,9 +217,9 @@ struct dme1737_data { ...@@ -213,9 +217,9 @@ struct dme1737_data {
u32 has_features; u32 has_features;
/* Register values */ /* Register values */
u16 in[7]; u16 in[8];
u8 in_min[7]; u8 in_min[8];
u8 in_max[7]; u8 in_max[8];
s16 temp[3]; s16 temp[3];
s8 temp_min[3]; s8 temp_min[3];
s8 temp_max[3]; s8 temp_max[3];
...@@ -247,7 +251,7 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, ...@@ -247,7 +251,7 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300,
static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300,
3300}; 3300};
static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300,
3300}; 3300, 1500};
#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \
(type) == sch5027 ? IN_NOMINAL_SCH5027 : \ (type) == sch5027 ? IN_NOMINAL_SCH5027 : \
(type) == sch5127 ? IN_NOMINAL_SCH5127 : \ (type) == sch5127 ? IN_NOMINAL_SCH5127 : \
...@@ -580,7 +584,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) ...@@ -580,7 +584,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
{ {
struct dme1737_data *data = dev_get_drvdata(dev); struct dme1737_data *data = dev_get_drvdata(dev);
int ix; int ix;
u8 lsb[5]; u8 lsb[6];
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
...@@ -603,6 +607,9 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) ...@@ -603,6 +607,9 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* Voltage inputs are stored as 16 bit values even /* Voltage inputs are stored as 16 bit values even
* though they have only 12 bits resolution. This is * though they have only 12 bits resolution. This is
* to make it consistent with the temp inputs. */ * to make it consistent with the temp inputs. */
if (ix == 7 && !(data->has_features & HAS_IN7)) {
continue;
}
data->in[ix] = dme1737_read(data, data->in[ix] = dme1737_read(data,
DME1737_REG_IN(ix)) << 8; DME1737_REG_IN(ix)) << 8;
data->in_min[ix] = dme1737_read(data, data->in_min[ix] = dme1737_read(data,
...@@ -635,10 +642,16 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) ...@@ -635,10 +642,16 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
* which the registers are read (MSB first, then LSB) is * which the registers are read (MSB first, then LSB) is
* important! */ * important! */
for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
if (ix == 5 && !(data->has_features & HAS_IN7)) {
continue;
}
lsb[ix] = dme1737_read(data, lsb[ix] = dme1737_read(data,
DME1737_REG_IN_TEMP_LSB(ix)); DME1737_REG_IN_TEMP_LSB(ix));
} }
for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
if (ix == 7 && !(data->has_features & HAS_IN7)) {
continue;
}
data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] <<
DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; DME1737_REG_IN_LSB_SHL[ix]) & 0xf0;
} }
...@@ -762,7 +775,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) ...@@ -762,7 +775,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Voltage sysfs attributes * Voltage sysfs attributes
* ix = [0-5] * ix = [0-7]
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
#define SYS_IN_INPUT 0 #define SYS_IN_INPUT 0
...@@ -1439,7 +1452,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, ...@@ -1439,7 +1452,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr,
* Sysfs device attribute defines and structs * Sysfs device attribute defines and structs
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
/* Voltages 0-6 */ /* Voltages 0-7 */
#define SENSOR_DEVICE_ATTR_IN(ix) \ #define SENSOR_DEVICE_ATTR_IN(ix) \
static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \
...@@ -1458,6 +1471,7 @@ SENSOR_DEVICE_ATTR_IN(3); ...@@ -1458,6 +1471,7 @@ SENSOR_DEVICE_ATTR_IN(3);
SENSOR_DEVICE_ATTR_IN(4); SENSOR_DEVICE_ATTR_IN(4);
SENSOR_DEVICE_ATTR_IN(5); SENSOR_DEVICE_ATTR_IN(5);
SENSOR_DEVICE_ATTR_IN(6); SENSOR_DEVICE_ATTR_IN(6);
SENSOR_DEVICE_ATTR_IN(7);
/* Temperatures 1-3 */ /* Temperatures 1-3 */
...@@ -1695,6 +1709,21 @@ static const struct attribute_group dme1737_zone_hyst_group = { ...@@ -1695,6 +1709,21 @@ static const struct attribute_group dme1737_zone_hyst_group = {
.attrs = dme1737_zone_hyst_attr, .attrs = dme1737_zone_hyst_attr,
}; };
/* The following struct holds voltage in7 related attributes, which
* are not available in all chips. The following chips support them:
* SCH5127 */
static struct attribute *dme1737_in7_attr[] = {
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in7_min.dev_attr.attr,
&sensor_dev_attr_in7_max.dev_attr.attr,
&sensor_dev_attr_in7_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group dme1737_in7_group = {
.attrs = dme1737_in7_attr,
};
/* The following structs hold the PWM attributes, some of which are optional. /* The following structs hold the PWM attributes, some of which are optional.
* Their creation depends on the chip configuration which is determined during * Their creation depends on the chip configuration which is determined during
* module load. */ * module load. */
...@@ -1986,6 +2015,9 @@ static void dme1737_remove_files(struct device *dev) ...@@ -1986,6 +2015,9 @@ static void dme1737_remove_files(struct device *dev)
if (data->has_features & HAS_ZONE_HYST) { if (data->has_features & HAS_ZONE_HYST) {
sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group);
} }
if (data->has_features & HAS_IN7) {
sysfs_remove_group(&dev->kobj, &dme1737_in7_group);
}
sysfs_remove_group(&dev->kobj, &dme1737_group); sysfs_remove_group(&dev->kobj, &dme1737_group);
if (!data->client) { if (!data->client) {
...@@ -2030,6 +2062,12 @@ static int dme1737_create_files(struct device *dev) ...@@ -2030,6 +2062,12 @@ static int dme1737_create_files(struct device *dev)
&dme1737_zone_hyst_group))) { &dme1737_zone_hyst_group))) {
goto exit_remove; goto exit_remove;
} }
if (data->has_features & HAS_IN7) {
err = sysfs_create_group(&dev->kobj, &dme1737_in7_group);
if (err) {
goto exit_remove;
}
}
/* Create fan sysfs attributes */ /* Create fan sysfs attributes */
for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
...@@ -2188,7 +2226,7 @@ static int dme1737_init_device(struct device *dev) ...@@ -2188,7 +2226,7 @@ static int dme1737_init_device(struct device *dev)
data->has_features |= HAS_ZONE3; data->has_features |= HAS_ZONE3;
break; break;
case sch5127: case sch5127:
data->has_features |= HAS_FAN(2) | HAS_PWM(2); data->has_features |= HAS_FAN(2) | HAS_PWM(2) | HAS_IN7;
break; break;
default: default:
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment