Re: [PATCH v2] hwmon: (max31722) Add support for MAX31722/MAX31723 temperature sensors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Guenter Roeck [mailto:linux@xxxxxxxxxxxx]
> Sent: Tuesday, March 29, 2016 6:45 PM
> To: Breana, Tiberiu A <tiberiu.a.breana@xxxxxxxxx>
> Cc: lm-sensors@xxxxxxxxxxxxxx; Baluta, Daniel <daniel.baluta@xxxxxxxxx>
> Subject: Re: [PATCH v2] hwmon: (max31722) Add support for
> MAX31722/MAX31723 temperature sensors
> 
> On Mon, Mar 28, 2016 at 05:15:57PM +0300, Tiberiu Breana wrote:
> > Add basic support for the Maxim Integrated MAX31722/MAX31723 SPI
> > temperature sensors / thermostats.
> >
> > Includes:
> >     - ACPI support;
> >     - raw temperature readings;
> >     - power management
> >
> > Datasheet:
> > https://datasheets.maximintegrated.com/en/ds/MAX31722-
> MAX31723.pdf
> >
> > Signed-off-by: Tiberiu Breana <tiberiu.a.breana@xxxxxxxxx>
> > ---
> > Changes from v1:
> > - addressed Guenter's comments
> > - removed regmap
> 
> Why ? Just wondering.

It added a lot of code bloat and not much else.

> 
> Did you drop patch #2, or is it going to come later ?

It's coming later.

> 
> More comments below.
> 
> Thanks,
> Guenter

All the suggested changes will be applied in v3 soon.
Thanks,

Tiberiu

> 
> > - set resolution to 12 bits
> > ---
> >  Documentation/hwmon/max31722 |  34 ++++++++
> >  drivers/hwmon/Kconfig        |  11 +++
> >  drivers/hwmon/Makefile       |   1 +
> >  drivers/hwmon/max31722.c     | 182
> +++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 228 insertions(+)
> >  create mode 100644 Documentation/hwmon/max31722  create mode
> 100644
> > drivers/hwmon/max31722.c
> >
> > diff --git a/Documentation/hwmon/max31722
> > b/Documentation/hwmon/max31722 new file mode 100644 index
> > 0000000..090da845
> > --- /dev/null
> > +++ b/Documentation/hwmon/max31722
> > @@ -0,0 +1,34 @@
> > +Kernel driver max31722
> > +======================
> > +
> > +Supported chips:
> > +  * Maxim Integrated MAX31722
> > +    Prefix: 'max31722'
> > +    ACPI ID: MAX31722
> > +    Addresses scanned: -
> > +    Datasheet:
> > +https://datasheets.maximintegrated.com/en/ds/MAX31722-
> MAX31723.pdf
> > +  * Maxim Integrated MAX31723
> > +    Prefix: 'max31723'
> > +    ACPI ID: MAX31723
> > +    Addresses scanned: -
> > +    Datasheet:
> > +https://datasheets.maximintegrated.com/en/ds/MAX31722-
> MAX31723.pdf
> > +
> > +Author: Tiberiu Breana <tiberiu.a.breana@xxxxxxxxx>
> > +
> > +Description
> > +-----------
> > +
> > +This driver adds support for the Maxim Integrated MAX31722/MAX31723
> > +thermometers and thermostats running over an SPI interface.
> > +
> > +Usage Notes
> > +-----------
> > +
> > +This driver uses ACPI to auto-detect devices. See ACPI IDs in the above
> section.
> > +
> > +Sysfs entries
> > +-------------
> > +
> > +The following attribute is supported:
> > +
> > +temp1_input		Measured temperature. Read-only.
> > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index
> > 60fb80b..b819312 100644
> > --- a/drivers/hwmon/Kconfig
> > +++ b/drivers/hwmon/Kconfig
> > @@ -807,6 +807,17 @@ config SENSORS_MAX197
> >  	  This driver can also be built as a module. If so, the module
> >  	  will be called max197.
> >
> > +config SENSORS_MAX31722
> > +tristate "MAX31722 temperature sensor"
> > +	depends on SPI
> > +	select REGMAP_SPI
> 
> You dropped regmap, so this should no longer be necessary.
> 
> > +	help
> > +	  Support for the Maxim Integrated MAX31722/MAX31723 digital
> > +	  thermometers/thermostats operating over an SPI interface.
> > +
> > +	  This driver can also be built as a module. If so, the module
> > +	  will be called max31722.
> > +
> >  config SENSORS_MAX6639
> >  	tristate "Maxim MAX6639 sensor chip"
> >  	depends on I2C
> > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index
> > 30c94df..689afe9 100644
> > --- a/drivers/hwmon/Makefile
> > +++ b/drivers/hwmon/Makefile
> > @@ -111,6 +111,7 @@ obj-$(CONFIG_SENSORS_MAX16065)	+=
> max16065.o
> >  obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
> >  obj-$(CONFIG_SENSORS_MAX1668)	+= max1668.o
> >  obj-$(CONFIG_SENSORS_MAX197)	+= max197.o
> > +obj-$(CONFIG_SENSORS_MAX31722)	+= max31722.o
> >  obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
> >  obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
> >  obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
> > diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c new
> > file mode 100644 index 0000000..b3606d9
> > --- /dev/null
> > +++ b/drivers/hwmon/max31722.c
> > @@ -0,0 +1,182 @@
> > +/*
> > + * max31722 - hwmon driver for Maxim Integrated MAX31722/MAX31723
> SPI
> > + * digital thermometer and thermostats.
> > + *
> > + * Copyright (c) 2016, Intel Corporation.
> > + *
> > + * This file is subject to the terms and conditions of version 2 of
> > + * the GNU General Public License. See the file COPYING in the main
> > + * directory of this archive for more details.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/acpi.h>
> > +#include <linux/module.h>
> > +#include <linux/spi/spi.h>
> > +#include <linux/hwmon.h>
> > +#include <linux/hwmon-sysfs.h>
> 
> Please lust include files in alphabetic order; that makes it easier to make
> changes later.
> 
> > +
> > +#define MAX31722_REG_CFG				0x00
> > +#define MAX31722_REG_TEMP_LSB				0x01
> > +
> > +#define MAX31722_MODE_CONTINUOUS			0x00
> > +#define MAX31722_MODE_STANDBY				0x01
> > +#define MAX31722_MODE_MASK				0xFE
> > +#define MAX31722_RESOLUTION_12BIT			0x06
> > +#define MAX31722_12BIT_STEP				62
> > +#define MAX31722_WRITE_MASK				0x80
> > +
> > +struct max31722_data {
> > +	struct device *hwmon_dev;
> > +	struct spi_device *spi_device;
> > +	u8 mode;
> > +};
> > +
> > +static int max31722_set_mode(struct max31722_data *data, u8 mode) {
> > +	int ret;
> > +	struct spi_device *spi = data->spi_device;
> > +	u8 buf[2] = {
> > +		MAX31722_REG_CFG | MAX31722_WRITE_MASK,
> > +		(data->mode & MAX31722_MODE_MASK) | mode
> > +	};
> > +
> > +	ret = spi_write(spi, &buf, sizeof(buf));
> > +
> Please drop this empty line.
> 
> > +	if (ret < 0) {
> > +		dev_err(&spi->dev, "failed to set sensor mode.\n");
> > +		return ret;
> > +	}
> > +	data->mode = (data->mode & MAX31722_MODE_MASK) | mode;
> > +
> > +	return 0;
> > +}
> > +
> > +static ssize_t max31722_show_temp(struct device *dev,
> > +				  struct device_attribute *attr,
> > +				  char *buf)
> > +{
> > +	u16 temp;
> > +	struct max31722_data *data = dev_get_drvdata(dev);
> > +
> > +	temp = spi_w8r16(data->spi_device, MAX31722_REG_TEMP_LSB);
> > +	if (temp < 0)
> > +		return temp;
> 
> temp is u16, so this doesn't work.
> 
> > +	/* Keep 12 bits and multiply by the scale of 62 millidegrees/bit. */
> > +	return sprintf(buf, "%d\n",
> > +		      ((s16)le16_to_cpu(temp) >> 4) * MAX31722_12BIT_STEP);
> 
> The step width is really 62.5 milli-degrees C, so this introduces an error.
> Something like
> 	(s16)le16_to_cpu(temp) * 125 / 32
> would be more accurate.
> 
> > +}
> > +
> > +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
> > +			  max31722_show_temp, NULL, 0);
> > +
> > +static struct attribute *max31722_attrs[] = {
> > +	&sensor_dev_attr_temp1_input.dev_attr.attr,
> > +	NULL,
> > +};
> > +
> > +ATTRIBUTE_GROUPS(max31722);
> > +
> > +static int max31722_probe(struct spi_device *spi) {
> > +	int ret;
> > +	struct max31722_data *data;
> > +	/*
> > +	 * Set SD bit to 0 so we can have continuous measurements.
> > +	 * Set resolution to 12 bits for maximum precision.
> > +	 */
> > +	u8 mode = MAX31722_MODE_CONTINUOUS |
> MAX31722_RESOLUTION_12BIT;
> > +	u8 init_buf[2] = {
> > +		MAX31722_REG_CFG | MAX31722_WRITE_MASK,
> > +		mode
> > +	};
> > +
> > +	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
> > +	if (!data)
> > +		return -ENOMEM;
> > +
> > +	spi_set_drvdata(spi, data);
> > +	data->spi_device = spi;
> > +	ret = spi_write(spi, &init_buf, sizeof(init_buf));
> > +	if (ret < 0) {
> > +		max31722_set_mode(data, MAX31722_MODE_STANDBY);
> > +		return ret;
> > +	}
> > +	data->mode = mode;
> 
> Initializing data->mode with
>         MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT and
> calling
>         max31722_set_mode(data, MAX31722_MODE_CONTINUOUS); would
> accomplish the same with less complexity.
> 
> Also, since the write failed, calling max31722_set_mode() on error (especially
> with the un-initialized data->mode) doesn't make much sense. You might as
> well just return in that case.
> 
> > +
> > +	data->hwmon_dev =
> > +		devm_hwmon_device_register_with_groups(&spi->dev,
> > +						       spi->modalias,
> > +						       data,
> > +						       max31722_groups);
> > +	if (IS_ERR(data->hwmon_dev)) {
> > +		max31722_set_mode(data, MAX31722_MODE_STANDBY);
> > +		return PTR_ERR(data->hwmon_dev);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int max31722_remove(struct spi_device *spi) {
> > +	struct max31722_data *data = spi_get_drvdata(spi);
> > +
> > +	hwmon_device_unregister(data->hwmon_dev);
> > +
> This defeats the purpose of using
> devm_hwmon_device_register_with_groups().
> Please use hwmon_device_register_with_groups() instead.
> 
> > +	return max31722_set_mode(data, MAX31722_MODE_STANDBY); }
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int max31722_suspend(struct device *dev) {
> > +	struct spi_device *spi_device = to_spi_device(dev);
> > +	struct max31722_data *data = spi_get_drvdata(spi_device);
> > +
> > +	return max31722_set_mode(data, MAX31722_MODE_STANDBY); }
> > +
> > +static int max31722_resume(struct device *dev) {
> > +	struct spi_device *spi_device = to_spi_device(dev);
> > +	struct max31722_data *data = spi_get_drvdata(spi_device);
> > +
> > +	return max31722_set_mode(data,
> MAX31722_MODE_CONTINUOUS); }
> > +
> > +static SIMPLE_DEV_PM_OPS(max31722_pm_ops, max31722_suspend,
> > +max31722_resume);
> > +
> > +#define MAX31722_PM_OPS (&max31722_pm_ops) #else #define
> > +MAX31722_PM_OPS NULL #endif
> 
> Please drop the #ifdef and tag the functions with __maybe_unused.
> While this causes max31722_pm_ops to be defined in the non-PM case, it
> ensures that the functions are always compiled.
> The benefit outweighs the cost.
> 
> > +
> > +static const struct spi_device_id max31722_spi_id[] = {
> > +	{"max31722", 0},
> > +	{"max31723", 0},
> > +	{}
> > +};
> > +
> > +static const struct acpi_device_id max31722_acpi_id[] = {
> > +	{"MAX31722", 0},
> > +	{"MAX31723", 0},
> > +	{}
> > +};
> 
> I think you may need to tag this array with __maybe_unused to avoid an
> unused warning if ACPI is not configured.
> 
> > +
> > +MODULE_DEVICE_TABLE(spi, max31722_spi_id);
> > +
> > +static struct spi_driver max31722_driver = {
> > +	.driver = {
> > +		.name = "max31722",
> > +		.pm = MAX31722_PM_OPS,
> > +		.acpi_match_table = ACPI_PTR(max31722_acpi_id),
> > +	},
> > +	.probe =            max31722_probe,
> > +	.remove =           max31722_remove,
> > +	.id_table =         max31722_spi_id,
> > +};
> > +
> > +module_spi_driver(max31722_driver);
> > +
> > +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@xxxxxxxxx>");
> > +MODULE_DESCRIPTION("max31722 sensor driver");
> MODULE_LICENSE("GPL
> > +v2");
> > --
> > 1.9.1
> >

_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors



[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux