lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5698C1DD.6000607@topic.nl>
Date:	Fri, 15 Jan 2016 10:54:37 +0100
From:	Mike Looijmans <mike.looijmans@...ic.nl>
To:	Guenter Roeck <linux@...ck-us.net>
CC:	<lm-sensors@...sensors.org>, <jdelvare@...e.com>,
	<linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v3] hwmon: Add LTC2990 sensor driver

On 14-01-16 20:14, Guenter Roeck wrote:
> On Wed, Jan 13, 2016 at 03:45:01PM +0100, Mike Looijmans wrote:
>> This adds support for the Linear Technology LTC2990  I2C System Monitor.
>> The LTC2990 supports a combination of voltage, current and temperature
>> monitoring. This driver currently only supports reading two currents
>> by measuring two differential voltages across series resistors, in
>> addition to the Vcc supply voltage and internal temperature.
>>
>> This is sufficient to support the Topic Miami SOM which uses this chip
>> to monitor the currents flowing into the FPGA and the CPU parts.
>>
>> Signed-off-by: Mike Looijmans <mike.looijmans@...ic.nl>
>
> Hi Mike,
>
> almost there. Please see inline.

Great, I'll order some cake :)

Expect v4 in a few minutes, I'm testing it on the hardware now.

> Thanks,
> Guenter
>
>> ---
>> v3: Remove unused includes.
>>      Remove (most) unused register defines.
>>      Also check on SMBUS WORD capability.
>>      Use register defines as value indices.
>>      Alignment fixups with "(".
>> v2: Processed all review comments.
>>       Put chip into continuous measurement mode.
>>       Added ducumentation.
>>       Use standard hwmon interfaces and macros.
>>
>>   Documentation/hwmon/ltc2990 |  44 ++++++++++++
>>   drivers/hwmon/Kconfig       |  14 ++++
>>   drivers/hwmon/Makefile      |   1 +
>>   drivers/hwmon/ltc2990.c     | 159 ++++++++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 218 insertions(+)
>>   create mode 100644 Documentation/hwmon/ltc2990
>>   create mode 100644 drivers/hwmon/ltc2990.c
>>
>> diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990
>> new file mode 100644
>> index 0000000..838b74e
>> --- /dev/null
>> +++ b/Documentation/hwmon/ltc2990
>> @@ -0,0 +1,44 @@
>> +Kernel driver ltc2990
>> +=====================
>> +
>> +Supported chips:
>> +  * Linear Technology LTC2990
>> +    Prefix: 'ltc2990'
>> +    Addresses scanned: -
>> +    Datasheet: http://www.linear.com/product/ltc2990
>> +
>> +Author: Mike Looijmans <mike.looijmans@...ic.nl>
>> +
>> +
>> +Description
>> +-----------
>> +
>> +LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor.
>> +The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4)
>> +can be combined to measure a differential voltage, which is typically used to
>> +measure current through a series resistor, or a temperature.
>> +
>> +This driver currently uses the 2x differential mode only. In order to support
>> +other modes, the driver will need to be expanded.
>> +
>> +
>> +Usage Notes
>> +-----------
>> +
>> +This driver does not probe for PMBus devices. You will have to instantiate
>> +devices explicitly.
>> +
>> +
>> +Sysfs attributes
>> +----------------
>> +
>> +The "curr*_input" measurements actually report the voltage drop across the
>> +input pins in microvolts. This is equivalent to the current through a 1mOhm
>> +sense resistor. Divide the reported value by the actual sense resistor value
>> +in mOhm to get the actual value.
>> +
>> +in0_input     Voltage at Vcc pin in millivolt (range 2.5V to 5V)
>> +temp1_input   Internal chip temperature in millidegrees Celcius
>> +curr1_input   Current in mA across v1-v2 assuming a 1mOhm sense resistor.
>> +curr2_input   Current in mA across v3-v4 assuming a 1mOhm sense resistor.
>> +
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 80a73bf..8a31d64 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -685,6 +685,20 @@ config SENSORS_LTC2945
>>   	  This driver can also be built as a module. If so, the module will
>>   	  be called ltc2945.
>>
>> +config SENSORS_LTC2990
>> +	tristate "Linear Technology LTC2990 (current monitoring mode only)"
>> +	depends on I2C
>> +	help
>> +	  If you say yes here you get support for Linear Technology LTC2990
>> +	  I2C System Monitor. The LTC2990 supports a combination of voltage,
>> +	  current and temperature monitoring, but in addition to the Vcc supply
>> +	  voltage and chip temperature, this driver currently only supports
>> +	  reading two currents by measuring two differential voltages across
>> +	  series resistors.
>> +
>> +	  This driver can also be built as a module. If so, the module will
>> +	  be called ltc2990.
>> +
>>   config SENSORS_LTC4151
>>   	tristate "Linear Technology LTC4151"
>>   	depends on I2C
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 12a3239..e4bd15b 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -101,6 +101,7 @@ obj-$(CONFIG_SENSORS_LM95234)	+= lm95234.o
>>   obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
>>   obj-$(CONFIG_SENSORS_LM95245)	+= lm95245.o
>>   obj-$(CONFIG_SENSORS_LTC2945)	+= ltc2945.o
>> +obj-$(CONFIG_SENSORS_LTC2990)	+= ltc2990.o
>>   obj-$(CONFIG_SENSORS_LTC4151)	+= ltc4151.o
>>   obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
>>   obj-$(CONFIG_SENSORS_LTC4222)	+= ltc4222.o
>> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
>> new file mode 100644
>> index 0000000..37ca5f4
>> --- /dev/null
>> +++ b/drivers/hwmon/ltc2990.c
>> @@ -0,0 +1,159 @@
>> +/*
>> + * Driver for Linear Technology LTC2990 power monitor
>> + *
>> + * Copyright (C) 2014 Topic Embedded Products
>> + * Author: Mike Looijmans <mike.looijmans@...ic.nl>
>> + *
>> + * License: GPLv2
>> + *
>> + * This driver assumes the chip is wired as a dual current monitor, and
>> + * reports the voltage drop across two series resistors. It also reports
>> + * the chip's internal temperature and Vcc power supply voltage.
>> + */
>> +
>> +#include <linux/err.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +
>> +#define LTC2990_STATUS	0x00
>> +#define LTC2990_CONTROL	0x01
>> +#define LTC2990_TRIGGER	0x02
>> +#define LTC2990_TINT_MSB	0x04
>> +#define LTC2990_V1_MSB	0x06
>> +#define LTC2990_V2_MSB	0x08
>> +#define LTC2990_V3_MSB	0x0A
>> +#define LTC2990_V4_MSB	0x0C
>> +#define LTC2990_VCC_MSB	0x0E
>> +
>> +#define LTC2990_CONTROL_KELVIN		BIT(7)
>> +#define LTC2990_CONTROL_SINGLE		BIT(6)
>> +#define LTC2990_CONTROL_MEASURE_ALL	(0x3 << 3)
>> +#define LTC2990_CONTROL_MODE_CURRENT	0x06
>> +#define LTC2990_CONTROL_MODE_VOLTAGE	0x07
>> +
>> +/* convert raw register value to sign-extended integer in 16-bit range */
>> +static int ltc2990_voltage_to_int(int raw)
>> +{
>> +	if (raw & BIT(14)) {
>> +		return -(0x4000 - (raw & 0x3FFF)) << 2;
>> +	} else {
>> +		return (raw & 0x3FFF) << 2;
>> +	}
>
> Unnecessary { }. Please see checkpatch warning.

I'll make sure to run checkpatch again. Its only remaining warning is about 
MAINTAINERS now.

>> +}
>> +
>> +/* Return the converted value from the given register in uV or mC */
>> +static int ltc2990_get_value(struct i2c_client *i2c, u8 reg)
>> +{
>> +	int val;
>> +	int result;
>> +
>> +	val = i2c_smbus_read_word_swapped(i2c, reg);
>> +	if (unlikely(val < 0))
>> +		return val;
>
> This suggests the function returns a value < 0 on error ...

Misleading, since most of the valid results can be negative. I'll change the 
method to return a result code and take a result pointer instead.

>
>> +	switch (reg) {
>> +	case LTC2990_TINT_MSB:
>> +		/* internal temp, 0.0625 degrees/LSB, 13-bit  */
>> +		val = (val & 0x1FFF) << 3;
>> +		result = (val * 1000) >> 7;
>> +		break;
>> +	case LTC2990_V1_MSB:
>> +	case LTC2990_V3_MSB:
>> +		 /* Vx-Vy, 19.42uV/LSB. Depends on mode. */
>> +		result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100);
>> +		break;
>> +	case LTC2990_VCC_MSB:
>> +		/* Vcc, 305.18μV/LSB, 2.5V offset */
>> +		result = ltc2990_voltage_to_int(val) * 30518 / (4 * 100 * 1000);
>> +		result += 2500;
>> +		break;
>> +	default:
>> +		result = 0; /* won't happen, keep compiler happy */
>
> Given that, we can return some error here, and ...
>
>> +		break;
>> +	}
>> +
>> +	return result;
>> +}
>> +
>> +static ssize_t ltc2990_show_value(struct device *dev,
>> +				  struct device_attribute *da, char *buf)
>> +{
>> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
>> +	int value;
>> +
>> +	value = ltc2990_get_value(dev_get_drvdata(dev), attr->index);
>
> ... we should actually check the error return here.
>
> 	if (value < 0)
> 		return value;

Yes, with the change above, it can properly return an error code if the I2C 
transaction failed.

>> +	return snprintf(buf, PAGE_SIZE, "%d\n", value);
>> +}
>> +
>> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL,
>> +			  LTC2990_TINT_MSB);
>> +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL,
>> +			  LTC2990_V1_MSB);
>> +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL,
>> +			  LTC2990_V3_MSB);
>> +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL,
>> +			  LTC2990_VCC_MSB);
>> +
>> +static struct attribute *ltc2990_attrs[] = {
>> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
>> +	&sensor_dev_attr_curr1_input.dev_attr.attr,
>> +	&sensor_dev_attr_curr2_input.dev_attr.attr,
>> +	&sensor_dev_attr_in0_input.dev_attr.attr,
>> +	NULL,
>> +};
>> +ATTRIBUTE_GROUPS(ltc2990);
>> +
>> +static int ltc2990_i2c_probe(struct i2c_client *i2c,
>> +			     const struct i2c_device_id *id)
>> +{
>> +	int ret;
>> +	struct device *hwmon_dev;
>> +
>> +	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
>> +				     I2C_FUNC_SMBUS_WORD_DATA))
>> +		return -ENODEV;
>> +
>> +	/* Setup continuous mode, current monitor */
>> +	ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL,
>> +					LTC2990_CONTROL_MEASURE_ALL |
>> +					LTC2990_CONTROL_MODE_CURRENT);
>> +	if (ret < 0) {
>> +		dev_err(&i2c->dev, "Error: Failed to set control mode.\n");
>> +		return ret;
>> +	}
>> +	/* Trigger once to start continuous conversion */
>> +	ret = i2c_smbus_write_byte_data(i2c, LTC2990_TRIGGER, 1);
>> +	if (ret < 0) {
>> +		dev_err(&i2c->dev, "Error: Failed to start acquisition.\n");
>> +		return ret;
>> +	}
>> +
>> +	hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev,
>> +							   i2c->name,
>> +							   i2c,
>> +							   ltc2990_groups);
>> +
>> +	return PTR_ERR_OR_ZERO(hwmon_dev);
>> +}
>> +
>> +static const struct i2c_device_id ltc2990_i2c_id[] = {
>> +	{ "ltc2990", 0 },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id);
>> +
>> +static struct i2c_driver ltc2990_i2c_driver = {
>> +	.driver = {
>> +		.name = "ltc2990",
>> +	},
>> +	.probe    = ltc2990_i2c_probe,
>> +	.id_table = ltc2990_i2c_id,
>> +};
>> +
>> +module_i2c_driver(ltc2990_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("LTC2990 Sensor Driver");
>> +MODULE_AUTHOR("Topic Embedded Products");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 1.9.1
>>



Kind regards,

Mike Looijmans
System Expert

TOPIC Embedded Products
Eindhovenseweg 32-C, NL-5683 KH Best
Postbus 440, NL-5680 AK Best
Telefoon: +31 (0) 499 33 69 79
E-mail: mike.looijmans@...icproducts.com
Website: www.topicproducts.com

Please consider the environment before printing this e-mail





Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ