linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Ludovic Tancerel <ludovic.tancerel@maplehightech.com>,
	knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net,
	linux-iio@vger.kernel.org, William.Markezana@meas-spec.com
Subject: Re: [PATCH v3 2/6] Add tsys01 meas-spec driver support
Date: Sun, 27 Sep 2015 17:55:56 +0100	[thread overview]
Message-ID: <56081F9C.7070500@kernel.org> (raw)
In-Reply-To: <1443189405-18516-3-git-send-email-ludovic.tancerel@maplehightech.com>

On 25/09/15 14:56, Ludovic Tancerel wrote:
> Support for TSYS01 temperature sensor
> 
> Signed-off-by: Ludovic Tancerel <ludovic.tancerel@maplehightech.com>
This is fine as far as i am concerned, though I would like to leave it
on the list for a little while for others to have a chance to comment.
> ---
>  drivers/iio/temperature/Kconfig  |  11 ++
>  drivers/iio/temperature/Makefile |   1 +
>  drivers/iio/temperature/tsys01.c | 231 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 243 insertions(+)
>  create mode 100644 drivers/iio/temperature/tsys01.c
> 
> diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
> index 21feaa4..35712032 100644
> --- a/drivers/iio/temperature/Kconfig
> +++ b/drivers/iio/temperature/Kconfig
> @@ -23,4 +23,15 @@ config TMP006
>  	  This driver can also be built as a module. If so, the module will
>  	  be called tmp006.
>  
> +config TSYS01
> +	tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
> +	depends on I2C
> +	select IIO_MS_SENSORS_I2C
> +	help
> +	  If you say yes here you get support for the Measurement Specialties
> +	  TSYS01 I2C temperature sensor.
> +
> +	  This driver can also be built as a module. If so, the module will
> +	  be called tsys01.
> +
>  endmenu
> diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
> index 40710a8..368a2a2 100644
> --- a/drivers/iio/temperature/Makefile
> +++ b/drivers/iio/temperature/Makefile
> @@ -4,3 +4,4 @@
>  
>  obj-$(CONFIG_MLX90614) += mlx90614.o
>  obj-$(CONFIG_TMP006) += tmp006.o
> +obj-$(CONFIG_TSYS01) += tsys01.o
> diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c
> new file mode 100644
> index 0000000..5c4127f
> --- /dev/null
> +++ b/drivers/iio/temperature/tsys01.c
> @@ -0,0 +1,231 @@
> +/*
> + * tsys01.c - Support for Measurement-Specialties tsys01 temperature sensor
> + *
> + * Copyright (c) 2015 Measurement-Specialties
> + *
> + * Licensed under the GPL-2.
> + *
> + * Datasheet:
> + *  http://www.meas-spec.com/downloads/TSYS01_Digital_Temperature_Sensor.pdf
> + *
> + */
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/stat.h>
> +#include "../common/ms_sensors/ms_sensors_i2c.h"
> +
> +/* TSYS01 Commands */
> +#define TSYS01_RESET				0x1E
> +#define TSYS01_CONVERSION_START			0x48
> +#define TSYS01_ADC_READ				0x00
> +#define TSYS01_PROM_READ			0xA0
> +
> +#define TSYS01_PROM_WORDS_NB			8
> +
> +struct tsys01_dev {
> +	void *client;
> +	struct mutex lock; /* lock during conversion */
> +
> +	int (*reset)(void *cli, u8 cmd, unsigned int delay);
> +	int (*convert_and_read)(void *cli, u8 conv, u8 rd,
> +				unsigned int delay, u32 *adc);
> +	int (*read_prom_word)(void *cli, int cmd, u16 *word);
> +
> +	u16 prom[TSYS01_PROM_WORDS_NB];
> +};
> +
> +/* Multiplication coefficients for temperature computation */
> +static const int coeff_mul[] = { -1500000, 1000000, -2000000,
> +				 4000000, -2000000 };
> +
> +static int tsys01_read_temperature(struct iio_dev *indio_dev,
> +				   s32 *temperature)
> +{
> +	int ret, i;
> +	u32 adc;
> +	s64 temp = 0;
> +	struct tsys01_dev *dev_data = iio_priv(indio_dev);
> +
> +	mutex_lock(&dev_data->lock);
> +	ret = dev_data->convert_and_read(dev_data->client,
> +					 TSYS01_CONVERSION_START,
> +					 TSYS01_ADC_READ, 9000, &adc);
> +	mutex_unlock(&dev_data->lock);
> +	if (ret)
> +		return ret;
> +
> +	adc >>= 8;
> +
> +	/* Temperature algorithm */
> +	for (i = 4; i > 0; i--) {
> +		temp += coeff_mul[i] *
> +			(s64)dev_data->prom[5 - i];
> +		temp *= (s64)adc;
> +		temp = div64_s64(temp, 100000);
> +	}
> +	temp *= 10;
> +	temp += coeff_mul[0] * (s64)dev_data->prom[5];
> +	temp = div64_s64(temp, 100000);
> +
> +	*temperature = temp;
> +
> +	return 0;
> +}
> +
> +static int tsys01_read_raw(struct iio_dev *indio_dev,
> +			   struct iio_chan_spec const *channel, int *val,
> +			   int *val2, long mask)
> +{
> +	int ret;
> +	s32 temperature;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_PROCESSED:
> +		switch (channel->type) {
> +		case IIO_TEMP:	/* in milli °C */
> +			ret = tsys01_read_temperature(indio_dev, &temperature);
> +			if (ret)
> +				return ret;
> +			*val = temperature;
> +
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_chan_spec tsys01_channels[] = {
> +	{
> +		.type = IIO_TEMP,
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_PROCESSED),
> +	}
> +};
> +
> +static const struct iio_info tsys01_info = {
> +	.read_raw = tsys01_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static bool tsys01_crc_valid(u16 *n_prom)
> +{
> +	u8 cnt;
> +	u8 sum = 0;
> +
> +	for (cnt = 0; cnt < TSYS01_PROM_WORDS_NB; cnt++)
> +		sum += ((n_prom[0] >> 8) + (n_prom[0] & 0xFF));
> +
> +	return (sum == 0);
> +}
> +
> +static int tsys01_read_prom(struct iio_dev *indio_dev)
> +{
> +	int i, ret;
> +	struct tsys01_dev *dev_data = iio_priv(indio_dev);
> +	char buf[7 * TSYS01_PROM_WORDS_NB + 1];
> +	char *ptr = buf;
> +
> +	for (i = 0; i < TSYS01_PROM_WORDS_NB; i++) {
> +		ret = dev_data->read_prom_word(dev_data->client,
> +					       TSYS01_PROM_READ + (i << 1),
> +					       &dev_data->prom[i]);
> +		if (ret)
> +			return ret;
> +
> +		ret = sprintf(ptr, "0x%04x ", dev_data->prom[i]);
> +		ptr += ret;
> +	}
> +
> +	if (!tsys01_crc_valid(dev_data->prom)) {
> +		dev_err(&indio_dev->dev, "prom crc check error\n");
> +		return -ENODEV;
> +	}
> +	*ptr = 0;
> +	dev_info(&indio_dev->dev, "PROM coefficients : %s\n", buf);
> +
> +	return 0;
> +}
> +
> +static int tsys01_probe(struct iio_dev *indio_dev, struct device *dev)
> +{
> +	int ret;
> +	struct tsys01_dev *dev_data = iio_priv(indio_dev);
> +
> +	mutex_init(&dev_data->lock);
> +
> +	indio_dev->info = &tsys01_info;
> +	indio_dev->name = dev->driver->name;
> +	indio_dev->dev.parent = dev;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = tsys01_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(tsys01_channels);
> +
> +	ret = dev_data->reset(dev_data->client, TSYS01_RESET, 3000);
> +	if (ret)
> +		return ret;
> +
> +	ret = tsys01_read_prom(indio_dev);
> +	if (ret)
> +		return ret;
> +
> +	return devm_iio_device_register(dev, indio_dev);
> +}
> +
> +static int tsys01_i2c_probe(struct i2c_client *client,
> +			    const struct i2c_device_id *id)
> +{
> +	struct tsys01_dev *dev_data;
> +	struct iio_dev *indio_dev;
> +
> +	if (!i2c_check_functionality(client->adapter,
> +				     I2C_FUNC_SMBUS_WORD_DATA |
> +				     I2C_FUNC_SMBUS_WRITE_BYTE |
> +				     I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
> +		dev_err(&client->dev,
> +			"Adapter does not support some i2c transaction\n");
> +		return -ENODEV;
> +	}
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dev_data));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	dev_data = iio_priv(indio_dev);
> +	dev_data->client = client;
> +	dev_data->reset = ms_sensors_i2c_reset;
> +	dev_data->read_prom_word = ms_sensors_i2c_read_prom_word;
> +	dev_data->convert_and_read = ms_sensors_i2c_convert_and_read;
> +
> +	i2c_set_clientdata(client, indio_dev);
> +
This separation into i2c probe and main probe is something one would
generally only introduce at the point of adding support for another bus.
It just adds complexity here for little gain.  If there is intent
to add spi support shortly then fair enough, leave it as it is.
> +	return tsys01_probe(indio_dev, &client->dev);
> +}
> +
> +static const struct i2c_device_id tsys01_id[] = {
> +	{"tsys01", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, tsys01_id);
> +
> +static struct i2c_driver tsys01_driver = {
> +	.probe = tsys01_i2c_probe,
> +	.id_table = tsys01_id,
> +	.driver = {
> +		   .name = "tsys01",
> +		   },
> +};
> +
> +module_i2c_driver(tsys01_driver);
> +
> +MODULE_DESCRIPTION("Measurement-Specialties tsys01 temperature driver");
> +MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
> +MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
> +MODULE_LICENSE("GPL v2");
> 


  reply	other threads:[~2015-09-27 16:56 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-25 13:56 [PATCH v3 0/6] iio: TSYS01, TSYS02D, HTU21, MS5637, MS8607, Measurement Specialties driver developments Ludovic Tancerel
2015-09-25 13:56 ` [PATCH v3 1/6] Add meas-spec sensors common part Ludovic Tancerel
2015-09-27 16:23   ` Jonathan Cameron
2015-09-29  7:59     ` ludovic.tancerel
2015-09-29  8:03       ` ludovic.tancerel
2015-09-29 17:20         ` Jonathan Cameron
2015-09-25 13:56 ` [PATCH v3 2/6] Add tsys01 meas-spec driver support Ludovic Tancerel
2015-09-27 16:55   ` Jonathan Cameron [this message]
2015-09-29  9:36     ` ludovic.tancerel
2015-09-29 17:21       ` Jonathan Cameron
2015-09-25 13:56 ` [PATCH v3 3/6] Add tsys02d " Ludovic Tancerel
2015-09-27 17:51   ` Jonathan Cameron
2015-09-29  9:40     ` ludovic.tancerel
2015-09-25 13:56 ` [PATCH v3 4/6] Add htu21 " Ludovic Tancerel
2015-09-27 17:54   ` Jonathan Cameron
2015-09-25 13:56 ` [PATCH v3 5/6] Add ms5637 " Ludovic Tancerel
2015-09-27 17:57   ` Jonathan Cameron
2015-09-29  9:45     ` ludovic.tancerel
2015-09-25 13:56 ` [PATCH v3 6/6] Add ms8607 " Ludovic Tancerel
2015-09-27 18:00   ` Jonathan Cameron
2015-09-29 10:00     ` ludovic.tancerel
2015-09-29 17:27       ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56081F9C.7070500@kernel.org \
    --to=jic23@kernel.org \
    --cc=William.Markezana@meas-spec.com \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=ludovic.tancerel@maplehightech.com \
    --cc=pmeerw@pmeerw.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).