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

Commit 1259f6ee authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull hwmon updates from Guenter Roeck:
 "New driver for INA219 and INA226, added support for IT8782F and
  IT8783E/F to it87 driver, plus cleanups in a couple of drivers."

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (it87) Make temp3 attribute conditional for IT8782F
  hwmon: (it87) Convert to use devm_kzalloc and devm_request_region
  hwmon: INA219 and INA226 support
  hwmon: (it87) Create voltage attributes only if voltage is enabled
  hwmon: (ntc_thermistor) Fix checkpatch warning
  hwmon: (ntc_thermistor) Optimize and fix build warning
  hwmon: (ntc_thermistor) Return error code from hwmon_device_register
  hwmon: (ntc_thermistor) Convert to devm_kzalloc
  hwmon: (ad7314) Remove unused defines, and rename OFFSET to SHIFT
  acpi_power_meter: clean up code around setup_attrs
  acpi_power_meter: drop meter_rw_attrs, use common meter_attrs
  acpi_power_meter: remove duplicate code between register_{ro,rw}_attrs
  acpi_power_meter: use a {RW,RO}_SENSOR_TEMPLATE macro to clean things up
  acpi_power_meter: use the same struct {rw,ro}_sensor_template for both
  hwmon: use module_pci_driver
  hwmon: (it87) Add support for IT8782F and IT8783E/F
parents 468f4d1a 4573acbc
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line Diff line number Diff line
Kernel driver ina2xx
====================

Supported chips:
  * Texas Instruments INA219
    Prefix: 'ina219'
    Addresses: I2C 0x40 - 0x4f
    Datasheet: Publicly available at the Texas Instruments website
               http://www.ti.com/

  * Texas Instruments INA226
    Prefix: 'ina226'
    Addresses: I2C 0x40 - 0x4f
    Datasheet: Publicly available at the Texas Instruments website
               http://www.ti.com/

Author: Lothar Felten <l-felten@ti.com>

Description
-----------

The INA219 is a high-side current shunt and power monitor with an I2C
interface. The INA219 monitors both shunt drop and supply voltage, with
programmable conversion times and filtering.

The INA226 is a current shunt and power monitor with an I2C interface.
The INA226 monitors both a shunt voltage drop and bus supply voltage.

The shunt value in micro-ohms can be set via platform data.
+19 −9
Original line number Original line Diff line number Diff line
@@ -30,6 +30,14 @@ Supported chips:
    Prefix: 'it8728'
    Prefix: 'it8728'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Datasheet: Not publicly available
    Datasheet: Not publicly available
  * IT8782F
    Prefix: 'it8782'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Datasheet: Not publicly available
  * IT8783E/F
    Prefix: 'it8783'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Datasheet: Not publicly available
  * SiS950   [clone of IT8705F]
  * SiS950   [clone of IT8705F]
    Prefix: 'it87'
    Prefix: 'it87'
    Addresses scanned: from Super I/O config space (8 I/O ports)
    Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -75,7 +83,8 @@ Description
-----------
-----------


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


These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -99,11 +108,11 @@ The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E and later IT8712F revisions
have support for 2 additional fans. The additional fans are supported by the
have support for 2 additional fans. The additional fans are supported by the
driver.
driver.


The IT8716F, IT8718F, IT8720F and IT8721F/IT8758E, and late IT8712F and
The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8782F, IT8783E/F, and late
IT8705F also have optional 16-bit tachometer counters for fans 1 to 3. This
IT8712F and IT8705F also have optional 16-bit tachometer counters for fans 1 to
is better (no more fan clock divider mess) but not compatible with the older
3. This is better (no more fan clock divider mess) but not compatible with the
chips and revisions. The 16-bit tachometer mode is enabled by the driver when
older chips and revisions. The 16-bit tachometer mode is enabled by the driver
one of the above chips is detected.
when one of the above chips is detected.


The IT8726F is just bit enhanced IT8716F with additional hardware
The IT8726F is just bit enhanced IT8716F with additional hardware
for AMD power sequencing. Therefore the chip will appear as IT8716F
for AMD power sequencing. Therefore the chip will appear as IT8716F
@@ -131,9 +140,10 @@ inputs can measure voltages between 0 and 4.08 volts, with a resolution of
0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
voltage in8 does not have limit registers.
voltage in8 does not have limit registers.


On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
On the IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs are
the chip (in7, in8 and optionally in3). The driver handles this transparently
internal and scaled inside the chip (in7 (optional for IT8782F and IT8783E/F),
so user-space doesn't have to care.
in8 and optionally in3). The driver handles this transparently so user-space
doesn't have to care.


The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value:
The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value:
the voltage level your processor should work with. This is hardcoded by
the voltage level your processor should work with. This is hardcoded by
+13 −0
Original line number Original line Diff line number Diff line
@@ -1102,6 +1102,19 @@ config SENSORS_AMC6821
	  This driver can also be build as a module.  If so, the module
	  This driver can also be build as a module.  If so, the module
	  will be called amc6821.
	  will be called amc6821.


config SENSORS_INA2XX
	tristate "Texas Instruments INA219, INA226"
	depends on I2C && EXPERIMENTAL
	help
	  If you say yes here you get support for INA219 and INA226 power
	  monitor chips.

	  The INA2xx driver is configured for the default configuration of
	  the part as described in the datasheet.
	  Default value for Rshunt is 10 mOhms.
	  This driver can also be built as a module.  If so, the module
	  will be called ina2xx.

config SENSORS_THMC50
config SENSORS_THMC50
	tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
	tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
	depends on I2C
	depends on I2C
+1 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
obj-$(CONFIG_SENSORS_IT87)	+= it87.o
obj-$(CONFIG_SENSORS_IT87)	+= it87.o
obj-$(CONFIG_SENSORS_JC42)	+= jc42.o
obj-$(CONFIG_SENSORS_JC42)	+= jc42.o
obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-hwmon.o
obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-hwmon.o
+72 −94
Original line number Original line Diff line number Diff line
@@ -107,15 +107,7 @@ struct acpi_power_meter_resource {
	struct kobject		*holders_dir;
	struct kobject		*holders_dir;
};
};


struct ro_sensor_template {
struct sensor_template {
	char *label;
	ssize_t (*show)(struct device *dev,
			struct device_attribute *devattr,
			char *buf);
	int index;
};

struct rw_sensor_template {
	char *label;
	char *label;
	ssize_t (*show)(struct device *dev,
	ssize_t (*show)(struct device *dev,
			struct device_attribute *devattr,
			struct device_attribute *devattr,
@@ -469,52 +461,67 @@ static ssize_t show_name(struct device *dev,
	return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME);
	return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME);
}
}


#define RO_SENSOR_TEMPLATE(_label, _show, _index)	\
	{						\
		.label = _label,			\
		.show  = _show,				\
		.index = _index,			\
	}

#define RW_SENSOR_TEMPLATE(_label, _show, _set, _index)	\
	{						\
		.label = _label,			\
		.show  = _show,				\
		.set   = _set,				\
		.index = _index,			\
	}

/* Sensor descriptions.  If you add a sensor, update NUM_SENSORS above! */
/* Sensor descriptions.  If you add a sensor, update NUM_SENSORS above! */
static struct ro_sensor_template meter_ro_attrs[] = {
static struct sensor_template meter_attrs[] = {
{POWER_AVERAGE_NAME, show_power, 0},
	RO_SENSOR_TEMPLATE(POWER_AVERAGE_NAME, show_power, 0),
{"power1_accuracy", show_accuracy, 0},
	RO_SENSOR_TEMPLATE("power1_accuracy", show_accuracy, 0),
{"power1_average_interval_min", show_val, 0},
	RO_SENSOR_TEMPLATE("power1_average_interval_min", show_val, 0),
{"power1_average_interval_max", show_val, 1},
	RO_SENSOR_TEMPLATE("power1_average_interval_max", show_val, 1),
{"power1_is_battery", show_val, 5},
	RO_SENSOR_TEMPLATE("power1_is_battery", show_val, 5),
{NULL, NULL, 0},
	RW_SENSOR_TEMPLATE(POWER_AVG_INTERVAL_NAME, show_avg_interval,
		set_avg_interval, 0),
	{},
};
};


static struct rw_sensor_template meter_rw_attrs[] = {
static struct sensor_template misc_cap_attrs[] = {
{POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0},
	RO_SENSOR_TEMPLATE("power1_cap_min", show_val, 2),
{NULL, NULL, NULL, 0},
	RO_SENSOR_TEMPLATE("power1_cap_max", show_val, 3),
	RO_SENSOR_TEMPLATE("power1_cap_hyst", show_val, 4),
	RO_SENSOR_TEMPLATE(POWER_ALARM_NAME, show_val, 6),
	{},
};
};


static struct ro_sensor_template misc_cap_attrs[] = {
static struct sensor_template ro_cap_attrs[] = {
{"power1_cap_min", show_val, 2},
	RO_SENSOR_TEMPLATE(POWER_CAP_NAME, show_cap, 0),
{"power1_cap_max", show_val, 3},
	{},
{"power1_cap_hyst", show_val, 4},
{POWER_ALARM_NAME, show_val, 6},
{NULL, NULL, 0},
};
};


static struct ro_sensor_template ro_cap_attrs[] = {
static struct sensor_template rw_cap_attrs[] = {
{POWER_CAP_NAME, show_cap, 0},
	RW_SENSOR_TEMPLATE(POWER_CAP_NAME, show_cap, set_cap, 0),
{NULL, NULL, 0},
	{},
};
};


static struct rw_sensor_template rw_cap_attrs[] = {
static struct sensor_template trip_attrs[] = {
{POWER_CAP_NAME, show_cap, set_cap, 0},
	RW_SENSOR_TEMPLATE("power1_average_min", show_val, set_trip, 7),
{NULL, NULL, NULL, 0},
	RW_SENSOR_TEMPLATE("power1_average_max", show_val, set_trip, 8),
	{},
};
};


static struct rw_sensor_template trip_attrs[] = {
static struct sensor_template misc_attrs[] = {
{"power1_average_min", show_val, set_trip, 7},
	RO_SENSOR_TEMPLATE("name", show_name, 0),
{"power1_average_max", show_val, set_trip, 8},
	RO_SENSOR_TEMPLATE("power1_model_number", show_str, 0),
{NULL, NULL, NULL, 0},
	RO_SENSOR_TEMPLATE("power1_oem_info", show_str, 2),
	RO_SENSOR_TEMPLATE("power1_serial_number", show_str, 1),
	{},
};
};


static struct ro_sensor_template misc_attrs[] = {
#undef RO_SENSOR_TEMPLATE
{"name", show_name, 0},
#undef RW_SENSOR_TEMPLATE
{"power1_model_number", show_str, 0},
{"power1_oem_info", show_str, 2},
{"power1_serial_number", show_str, 1},
{NULL, NULL, 0},
};


/* Read power domain data */
/* Read power domain data */
static void remove_domain_devices(struct acpi_power_meter_resource *resource)
static void remove_domain_devices(struct acpi_power_meter_resource *resource)
@@ -619,50 +626,25 @@ end:
}
}


/* Registration and deregistration */
/* Registration and deregistration */
static int register_ro_attrs(struct acpi_power_meter_resource *resource,
static int register_attrs(struct acpi_power_meter_resource *resource,
			     struct ro_sensor_template *ro)
			  struct sensor_template *attrs)
{
{
	struct device *dev = &resource->acpi_dev->dev;
	struct device *dev = &resource->acpi_dev->dev;
	struct sensor_device_attribute *sensors =
	struct sensor_device_attribute *sensors =
		&resource->sensors[resource->num_sensors];
		&resource->sensors[resource->num_sensors];
	int res = 0;
	int res = 0;


	while (ro->label) {
	while (attrs->label) {
		sensors->dev_attr.attr.name = ro->label;
		sensors->dev_attr.attr.name = attrs->label;
		sensors->dev_attr.attr.mode = S_IRUGO;
		sensors->dev_attr.attr.mode = S_IRUGO;
		sensors->dev_attr.show = ro->show;
		sensors->dev_attr.show = attrs->show;
		sensors->index = ro->index;
		sensors->index = attrs->index;


		sysfs_attr_init(&sensors->dev_attr.attr);
		if (attrs->set) {
		res = device_create_file(dev, &sensors->dev_attr);
			sensors->dev_attr.attr.mode |= S_IWUSR;
		if (res) {
			sensors->dev_attr.store = attrs->set;
			sensors->dev_attr.attr.name = NULL;
			goto error;
		}
		sensors++;
		resource->num_sensors++;
		ro++;
		}
		}


error:
	return res;
}

static int register_rw_attrs(struct acpi_power_meter_resource *resource,
			     struct rw_sensor_template *rw)
{
	struct device *dev = &resource->acpi_dev->dev;
	struct sensor_device_attribute *sensors =
		&resource->sensors[resource->num_sensors];
	int res = 0;

	while (rw->label) {
		sensors->dev_attr.attr.name = rw->label;
		sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
		sensors->dev_attr.show = rw->show;
		sensors->dev_attr.store = rw->set;
		sensors->index = rw->index;

		sysfs_attr_init(&sensors->dev_attr.attr);
		sysfs_attr_init(&sensors->dev_attr.attr);
		res = device_create_file(dev, &sensors->dev_attr);
		res = device_create_file(dev, &sensors->dev_attr);
		if (res) {
		if (res) {
@@ -671,7 +653,7 @@ static int register_rw_attrs(struct acpi_power_meter_resource *resource,
		}
		}
		sensors++;
		sensors++;
		resource->num_sensors++;
		resource->num_sensors++;
		rw++;
		attrs++;
	}
	}


error:
error:
@@ -703,10 +685,7 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
		return res;
		return res;


	if (resource->caps.flags & POWER_METER_CAN_MEASURE) {
	if (resource->caps.flags & POWER_METER_CAN_MEASURE) {
		res = register_ro_attrs(resource, meter_ro_attrs);
		res = register_attrs(resource, meter_attrs);
		if (res)
			goto error;
		res = register_rw_attrs(resource, meter_rw_attrs);
		if (res)
		if (res)
			goto error;
			goto error;
	}
	}
@@ -718,28 +697,27 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
			goto skip_unsafe_cap;
			goto skip_unsafe_cap;
		}
		}


		if (resource->caps.configurable_cap) {
		if (resource->caps.configurable_cap)
			res = register_rw_attrs(resource, rw_cap_attrs);
			res = register_attrs(resource, rw_cap_attrs);
			if (res)
		else
				goto error;
			res = register_attrs(resource, ro_cap_attrs);
		} else {

			res = register_ro_attrs(resource, ro_cap_attrs);
		if (res)
		if (res)
			goto error;
			goto error;
		}

		res = register_ro_attrs(resource, misc_cap_attrs);
		res = register_attrs(resource, misc_cap_attrs);
		if (res)
		if (res)
			goto error;
			goto error;
	}
	}
skip_unsafe_cap:


skip_unsafe_cap:
	if (resource->caps.flags & POWER_METER_CAN_TRIP) {
	if (resource->caps.flags & POWER_METER_CAN_TRIP) {
		res = register_rw_attrs(resource, trip_attrs);
		res = register_attrs(resource, trip_attrs);
		if (res)
		if (res)
			goto error;
			goto error;
	}
	}


	res = register_ro_attrs(resource, misc_attrs);
	res = register_attrs(resource, misc_attrs);
	if (res)
	if (res)
		goto error;
		goto error;


Loading