Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adfeb6e9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  hwmon: (sysfs-interface) Update tempX_type attribute to be more generic
  hwmon: (adm1031) Fix coding style issues
  hwmon: (it87) Add IT8728F support
  hwmon: (coretemp) Add missing section annotations
  hwmon: (lm90) Add range check to set_update_interval
  hwmon: (lm63) Support extended lookup table of LM96163
  hwmon: (lm63) Expose automatic fan speed control lookup table
  hwmon: (lm63) Fix incorrect comment about I2C address
  hwmon: (lm63) LM64 has a dedicated pin for tachometer
  hwmon: (lm63) Add sensor type attribute for external sensor on LM96163
  hwmon: (lm63) Add support for update_interval sysfs attribute
  hwmon: (lm63) Add support for writing the external critical temperature
  hwmon: (lm63) Add support for unsigned upper temperature limits
  hwmon: (lm63) Add support for LM96163
  hwmon: (lm63) Add support for external temperature offset register
  hwmon: (lm63) Fix checkpatch errors
  hwmon: (max1111) Change sysfs interface to in[0-3]_input in millivolts
parents 97740400 5f8b1f87
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -26,6 +26,10 @@ Supported chips:
    Prefix: 'it8721'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Datasheet: Not publicly available
  * IT8728F
    Prefix: 'it8728'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Datasheet: Not publicly available
  * SiS950   [clone of IT8705F]
    Prefix: 'it87'
    Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -71,7 +75,7 @@ Description
-----------

This driver implements support for the IT8705F, IT8712F, IT8716F,
IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips.
IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips.

These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -105,6 +109,9 @@ The IT8726F is just bit enhanced IT8716F with additional hardware
for AMD power sequencing. Therefore the chip will appear as IT8716F
to userspace applications.

The IT8728F is considered compatible with the IT8721F, until a datasheet
becomes available (hopefully.)

Temperatures are measured in degrees Celsius. An alarm is triggered once
when the Overtemperature Shutdown limit is crossed.

@@ -121,8 +128,8 @@ alarm is triggered if the voltage has crossed a programmable minimum or
maximum limit. Note that minimum in this case always means 'closest to
zero'; this is important for negative voltage measurements. All voltage
inputs can measure voltages between 0 and 4.08 volts, with a resolution of
0.016 volt (except IT8721F/IT8758E: 0.012 volt.) The battery voltage in8 does
not have limit registers.
0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
voltage in8 does not have limit registers.

On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
the chip (in7, in8 and optionally in3). The driver handles this transparently
+17 −4
Original line number Diff line number Diff line
@@ -12,6 +12,11 @@ Supported chips:
    Addresses scanned: I2C 0x18 and 0x4e
    Datasheet: Publicly available at the National Semiconductor website
               http://www.national.com/pf/LM/LM64.html
  * National Semiconductor LM96163
    Prefix: 'lm96163'
    Addresses scanned: I2C 0x4c
    Datasheet: Publicly available at the National Semiconductor website
               http://www.national.com/pf/LM/LM96163.html

Author: Jean Delvare <khali@linux-fr.org>

@@ -49,16 +54,24 @@ value for measuring the speed of the fan. It can measure fan speeds down to
Note that the pin used for fan monitoring is shared with an alert out
function. Depending on how the board designer wanted to use the chip, fan
speed monitoring will or will not be possible. The proper chip configuration
is left to the BIOS, and the driver will blindly trust it.
is left to the BIOS, and the driver will blindly trust it. Only the original
LM63 suffers from this limitation, the LM64 and LM96163 have separate pins
for fan monitoring and alert out. On the LM64, monitoring is always enabled;
on the LM96163 it can be disabled.

A PWM output can be used to control the speed of the fan. The LM63 has two
PWM modes: manual and automatic. Automatic mode is not fully implemented yet
(you cannot define your custom PWM/temperature curve), and mode change isn't
supported either.

The lm63 driver will not update its values more frequently than every
second; reading them more often will do no harm, but will return 'old'
values.
The lm63 driver will not update its values more frequently than configured with
the update_interval sysfs attribute; reading them more often will do no harm,
but will return 'old' values. Values in the automatic fan control lookup table
(attributes pwm1_auto_*) have their own independent lifetime of 5 seconds.

The LM64 is effectively an LM63 with GPIO lines. The driver does not
support these GPIO lines at present.

The LM96163 is an enhanced version of LM63 with improved temperature accuracy
and better PWM resolution. For LM96163, the external temperature sensor type is
configurable as CPU embedded diode(1) or 3904 transistor(2).
+1 −1
Original line number Diff line number Diff line
@@ -304,7 +304,7 @@ value (fastest fan speed) wins.
temp[1-*]_type	Sensor type selection.
		Integers 1 to 6
		RW
		1: PII/Celeron Diode
		1: CPU embedded diode
		2: 3904 transistor
		3: thermal diode
		4: thermistor
+4 −4
Original line number Diff line number Diff line
@@ -474,8 +474,8 @@ config SENSORS_IT87
	select HWMON_VID
	help
	  If you say yes here you get support for ITE IT8705F, IT8712F,
	  IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor
	  chips, and the SiS960 clone.
	  IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
	  sensor chips, and the SiS960 clone.

	  This driver can also be built as a module.  If so, the module
	  will be called it87.
@@ -515,11 +515,11 @@ config SENSORS_LINEAGE
	  will be called lineage-pem.

config SENSORS_LM63
	tristate "National Semiconductor LM63 and LM64"
	tristate "National Semiconductor LM63 and compatibles"
	depends on I2C
	help
	  If you say yes here you get support for the National
	  Semiconductor LM63 and LM64 remote diode digital temperature
	  Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
	  sensors with integrated fan control.  Such chips are found
	  on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
	  others.
+103 −50
Original line number Diff line number Diff line
@@ -155,7 +155,8 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
#define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
						      (val) | 0x70 : (val))

#define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
#define FAN_FROM_REG(reg, div)		((reg) ? \
					 (11250 * 60) / ((reg) * (div)) : 0)

static int FAN_TO_REG(int reg, int div)
{
@@ -258,13 +259,13 @@ get_fan_auto_nearest(struct adm1031_data *data,
		}
	}

	if (exact_match >= 0) {
	if (exact_match >= 0)
		*new_reg = exact_match;
	} else if (first_match >= 0) {
	else if (first_match >= 0)
		*new_reg = first_match;
	} else {
	else
		return -EINVAL;
	}

	return 0;
}

@@ -283,16 +284,21 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	long val;
	u8 reg;
	int ret;
	u8 old_fan_mode;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	old_fan_mode = data->conf1;

	mutex_lock(&data->update_lock);

	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
	ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg);
	if (ret) {
		mutex_unlock(&data->update_lock);
		return ret;
	}
@@ -350,7 +356,12 @@ set_auto_temp_min(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	mutex_lock(&data->update_lock);
	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
@@ -374,10 +385,16 @@ set_auto_temp_max(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	mutex_lock(&data->update_lock);
	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
						  data->pwm[nr]);
	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
			    data->temp_max[nr]);
	mutex_unlock(&data->update_lock);
@@ -410,8 +427,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	int reg;
	long val;
	int ret, reg;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	mutex_lock(&data->update_lock);
	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
@@ -449,7 +470,11 @@ static int trust_fan_readings(struct adm1031_data *data, int chan)

	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
		switch (data->conf1 & 0x60) {
		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
		case 0x00:
			/*
			 * remote temp1 controls fan1,
			 * remote temp2 controls fan2
			 */
			res = data->temp[chan+1] >=
			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
			break;
@@ -515,7 +540,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	mutex_lock(&data->update_lock);
	if (val) {
@@ -534,10 +564,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val = simple_strtol(buf, NULL, 10);
	long val;
	u8 tmp;
	int old_div;
	int new_min;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	tmp = val == 8 ? 0xc0 :
	      val == 4 ? 0x80 :
@@ -631,9 +666,13 @@ static ssize_t set_temp_offset(struct device *dev,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val;
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	val = simple_strtol(buf, NULL, 10);
	val = SENSORS_LIMIT(val, -15000, 15000);
	mutex_lock(&data->update_lock);
	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
@@ -648,9 +687,13 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val;
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	val = simple_strtol(buf, NULL, 10);
	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
	mutex_lock(&data->update_lock);
	data->temp_min[nr] = TEMP_TO_REG(val);
@@ -665,9 +708,13 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val;
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	val = simple_strtol(buf, NULL, 10);
	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
	mutex_lock(&data->update_lock);
	data->temp_max[nr] = TEMP_TO_REG(val);
@@ -682,9 +729,13 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int nr = to_sensor_dev_attr(attr)->index;
	int val;
	long val;
	int ret;

	ret = kstrtol(buf, 10, &val);
	if (ret)
		return ret;

	val = simple_strtol(buf, NULL, 10);
	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
	mutex_lock(&data->update_lock);
	data->temp_crit[nr] = TEMP_TO_REG(val);
@@ -711,7 +762,8 @@ temp_reg(2);
temp_reg(3);

/* Alarms */
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
			   char *buf)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf, "%d\n", data->alarm);
@@ -919,12 +971,13 @@ static int adm1031_probe(struct i2c_client *client,
	adm1031_init_client(client);

	/* Register sysfs hooks */
	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
	err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
	if (err)
		goto exit_free;

	if (data->chip_type == adm1031) {
		if ((err = sysfs_create_group(&client->dev.kobj,
						&adm1031_group_opt)))
		err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
		if (err)
			goto exit_remove;
	}

@@ -970,14 +1023,13 @@ static void adm1031_init_client(struct i2c_client *client)
	}
	/* Initialize the ADM1031 chip (enables fan speed reading ) */
	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
	if ((read_val | mask) != read_val) {
	if ((read_val | mask) != read_val)
		adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
	}

	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
				ADM1031_CONF1_MONITOR_ENABLE);
		adm1031_write_value(client, ADM1031_REG_CONF1,
				    read_val | ADM1031_CONF1_MONITOR_ENABLE);
	}

	/* Read the chip's update rate */
@@ -1024,8 +1076,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
				/* oldh is actually newer */
				if (newh != oldh)
					dev_warn(&client->dev,
						 "Remote temperature may be "
						 "wrong.\n");
					  "Remote temperature may be wrong.\n");
#endif
			}
			data->temp[chan] = newh;
@@ -1052,22 +1103,24 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);

		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
				<< 8);
		if (data->chip_type == adm1030) {
		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
		if (data->chip_type == adm1030)
			data->alarm &= 0xc0ff;
		}

		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
		     chan++) {
			data->fan_div[chan] =
			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
			    adm1031_read_value(client,
					       ADM1031_REG_FAN_DIV(chan));
			data->fan_min[chan] =
			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
			    adm1031_read_value(client,
					       ADM1031_REG_FAN_MIN(chan));
			data->fan[chan] =
			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
			    adm1031_read_value(client,
					       ADM1031_REG_FAN_SPEED(chan));
			data->pwm[chan] =
			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
				   (4*chan));
			  (adm1031_read_value(client,
					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
		}
		data->last_updated = jiffies;
		data->valid = 1;
Loading