Re: [PATCH 04/14] staging: iio: adc: new driver for AD7314 devices

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

 



On 10/23/10 21:29, Mike Frysinger wrote:
> From: Sonic Zhang <sonic.zhang@xxxxxxxxxx>
> 
Why IIO?  Do you have a use case that needs features off IIO
and wouldn't be covered by hwmon?

Not using any here, so I'm doubtful about this (Sonic and I
exchanged a few emails about this a while back).

Few comments inline and I guess iio then moving to hwmon is
fine with me if you want to do it... (hwmon is simpler!).

> Signed-off-by: Sonic Zhang <sonic.zhang@xxxxxxxxxx>
> Signed-off-by: Mike Frysinger <vapier@xxxxxxxxxx>
> ---
>  drivers/staging/iio/adc/Kconfig  |    7 +
>  drivers/staging/iio/adc/Makefile |    1 +
>  drivers/staging/iio/adc/ad7314.c |  308 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 316 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/staging/iio/adc/ad7314.c
> 
> diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
> index 847f5f2..6d3b8bc 100644
> --- a/drivers/staging/iio/adc/Kconfig
> +++ b/drivers/staging/iio/adc/Kconfig
> @@ -54,3 +54,10 @@ config AD7298
>  	help
>  	  Say yes here to build support for Analog Devices AD7298
>  	  temperature sensors and ADC.
> +
> +config AD7314
> +	tristate "Analog Devices AD7314 temperature sensor driver"
> +	depends on SPI
Please list all parts supported (appear to be several others in the
id table.)
> +	help
> +	  Say yes here to build support for Analog Devices AD7314
> +	  temperature sensors.
> diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
> index d0ea747..04fd93b 100644
> --- a/drivers/staging/iio/adc/Makefile
> +++ b/drivers/staging/iio/adc/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_AD7150) += ad7150.o
>  obj-$(CONFIG_AD7152) += ad7152.o
>  obj-$(CONFIG_AD7291) += ad7291.o
>  obj-$(CONFIG_AD7298) += ad7298.o
> +obj-$(CONFIG_AD7314) += ad7314.o
> diff --git a/drivers/staging/iio/adc/ad7314.c b/drivers/staging/iio/adc/ad7314.c
> new file mode 100644
> index 0000000..8c17b1f
> --- /dev/null
> +++ b/drivers/staging/iio/adc/ad7314.c
> @@ -0,0 +1,308 @@
> +/*
> + * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
> + *
> + * Copyright 2010 Analog Devices Inc.
> + *
> + * Licensed under the GPL-2 or later.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/gpio.h>
> +#include <linux/workqueue.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/list.h>
> +#include <linux/spi/spi.h>
> +#include <linux/rtc.h>
> +
> +#include "../iio.h"
> +#include "../sysfs.h"
> +
> +/*
> + * AD7314 power mode
> + */
> +#define AD7314_PD		0x2000
> +
> +/*
> + * AD7314 temperature masks
> + */
> +#define AD7314_TEMP_SIGN		0x200
> +#define AD7314_TEMP_MASK		0x7FE0
> +#define AD7314_TEMP_OFFSET		5
> +#define AD7314_TEMP_FLOAT_OFFSET	2
> +#define AD7314_TEMP_FLOAT_MASK		0x3
> +
> +/*
> + * ADT7301 and ADT7302 temperature masks
> + */
> +#define ADT7301_TEMP_SIGN		0x2000
> +#define ADT7301_TEMP_MASK		0x2FFF
> +#define ADT7301_TEMP_FLOAT_OFFSET	5
> +#define ADT7301_TEMP_FLOAT_MASK		0x1F
> +
> +/*
> + * struct ad7314_chip_info - chip specifc information
> + */
> +
> +struct ad7314_chip_info {
> +	const char *name;
> +	struct spi_device *spi_dev;
> +	struct iio_dev *indio_dev;
> +	s64 last_timestamp;
> +	u8  mode;
> +};
> +
> +/*
> + * ad7314 register access by SPI
> + */
> +
> +static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data)
> +{
> +	struct spi_device *spi_dev = chip->spi_dev;
> +	int ret = 0;
> +	u16 value;
> +
> +	ret = spi_read(spi_dev, (u8 *)&value, sizeof(value));
> +	if (ret < 0) {
> +		dev_err(&spi_dev->dev, "SPI read error\n");
> +		return ret;
> +	}
> +
> +	*data = be16_to_cpu((u16)value);
> +
> +	return ret;
> +}
> +
> +static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data)
> +{
> +	struct spi_device *spi_dev = chip->spi_dev;
> +	int ret = 0;
> +	u16 value = cpu_to_be16(data);
> +
> +	ret = spi_write(spi_dev, (u8 *)&value, sizeof(value));
> +	if (ret < 0)
> +		dev_err(&spi_dev->dev, "SPI write error\n");
> +
> +	return ret;
> +}
> +
> +static ssize_t ad7314_show_mode(struct device *dev,
> +		struct device_attribute *attr,
> +		char *buf)
> +{
> +	struct iio_dev *dev_info = dev_get_drvdata(dev);
> +	struct ad7314_chip_info *chip = dev_info->dev_data;
> +
> +	if (chip->mode)
> +		return sprintf(buf, "power-save\n");
> +	else
> +		return sprintf(buf, "full\n");
> +}
> +
> +static ssize_t ad7314_store_mode(struct device *dev,
> +		struct device_attribute *attr,
> +		const char *buf,
> +		size_t len)
> +{
> +	struct iio_dev *dev_info = dev_get_drvdata(dev);
> +	struct ad7314_chip_info *chip = dev_info->dev_data;
> +	u16 mode = 0;
> +	int ret;
> +
> +	if (!strcmp(buf, "full"))
> +		mode = AD7314_PD;
> +
> +	ret = ad7314_spi_write(chip, mode);
> +	if (ret)
> +		return -EIO;
> +
> +	chip->mode = mode;
> +
> +	return len;
> +}
> +
> +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
> +		ad7314_show_mode,
> +		ad7314_store_mode,
> +		0);
I'm still anti 'mode' attributes. They just don't generalize.
> +
> +static ssize_t ad7314_show_available_modes(struct device *dev,
> +		struct device_attribute *attr,
> +		char *buf)
> +{
> +	return sprintf(buf, "full\npower-save\n");
Do this via sampling_frequency (assuming that is what changes!)
> +}
> +
> +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0);
mode_available please.
> +
> +static ssize_t ad7314_show_temperature(struct device *dev,
> +		struct device_attribute *attr,
> +		char *buf)
> +{
> +	struct iio_dev *dev_info = dev_get_drvdata(dev);
> +	struct ad7314_chip_info *chip = dev_info->dev_data;
> +	u16 data;
> +	char sign = ' ';
> +	int ret;
> +
> +	if (chip->mode) {
> +		ret = ad7314_spi_write(chip, 0);
> +		if (ret)
> +			return -EIO;
Error eating.
> +	}
> +
> +	ret = ad7314_spi_read(chip, &data);
> +	if (ret)
> +		return -EIO;
> +
> +	if (chip->mode)
> +		ad7314_spi_write(chip, chip->mode);
> +
> +	if (strcmp(chip->name, "ad7314")) {
> +		data = (data & AD7314_TEMP_MASK) >>
> +			AD7314_TEMP_OFFSET;
> +		if (data & AD7314_TEMP_SIGN) {
> +			data = (AD7314_TEMP_SIGN << 1) - data;
> +			sign = '-';
> +		}
> +
> +		return sprintf(buf, "%c%d.%.2d\n", sign,
> +				data >> AD7314_TEMP_FLOAT_OFFSET,
> +				(data & AD7314_TEMP_FLOAT_MASK) * 25);
> +	} else {
> +		data &= ADT7301_TEMP_MASK;
> +		if (data & ADT7301_TEMP_SIGN) {
> +			data = (ADT7301_TEMP_SIGN << 1) - data;
> +			sign = '-';
> +		}
> +
> +		return sprintf(buf, "%c%d.%.5d\n", sign,
> +				data >> ADT7301_TEMP_FLOAT_OFFSET,
> +				(data & ADT7301_TEMP_FLOAT_MASK) * 3125);
> +	}
> +}
> +
> +static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0);
> +
> +static ssize_t ad7314_show_name(struct device *dev,
> +		struct device_attribute *attr,
> +		char *buf)
> +{
> +	struct iio_dev *dev_info = dev_get_drvdata(dev);
> +	struct ad7314_chip_info *chip = dev_info->dev_data;
> +	return sprintf(buf, "%s\n", chip->name);
> +}
> +
> +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL, 0);
> +
> +static struct attribute *ad7314_attributes[] = {
> +	&iio_dev_attr_available_modes.dev_attr.attr,
> +	&iio_dev_attr_mode.dev_attr.attr,
> +	&iio_dev_attr_temperature.dev_attr.attr,
temp_input please (we match hwmon where possible).

> +	&iio_dev_attr_name.dev_attr.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group ad7314_attribute_group = {
> +	.attrs = ad7314_attributes,
> +};
> +
> +/*
> + * device probe and remove
> + */
> +
> +static int __devinit ad7314_probe(struct spi_device *spi_dev)
> +{
> +	struct ad7314_chip_info *chip;
> +	int ret = 0;
> +
> +	chip = kzalloc(sizeof(struct ad7314_chip_info), GFP_KERNEL);
> +
> +	if (chip == NULL)
> +		return -ENOMEM;
> +
> +	/* this is only used for device removal purposes */
> +	dev_set_drvdata(&spi_dev->dev, chip);
> +
> +	chip->spi_dev = spi_dev;
> +	chip->name = spi_dev->modalias;
> +
> +	chip->indio_dev = iio_allocate_device();
> +	if (chip->indio_dev == NULL) {
> +		ret = -ENOMEM;
> +		goto error_free_chip;
> +	}
> +
> +	chip->indio_dev->dev.parent = &spi_dev->dev;
> +	chip->indio_dev->attrs = &ad7314_attribute_group;
> +	chip->indio_dev->dev_data = (void *)chip;
> +	chip->indio_dev->driver_module = THIS_MODULE;
> +
> +	ret = iio_device_register(chip->indio_dev);
> +	if (ret)
> +		goto error_free_dev;
> +
> +	dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
> +			 chip->name);
> +
> +	return 0;
> +error_free_dev:
> +	iio_free_device(chip->indio_dev);
> +error_free_chip:
> +	kfree(chip);
> +
> +	return ret;
> +}
> +
> +static int __devexit ad7314_remove(struct spi_device *spi_dev)
> +{
> +	struct ad7314_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
> +	struct iio_dev *indio_dev = chip->indio_dev;
> +
> +	dev_set_drvdata(&spi_dev->dev, NULL);
> +	if (spi_dev->irq)
> +		iio_unregister_interrupt_line(indio_dev, 0);
> +	iio_device_unregister(indio_dev);
> +	iio_free_device(chip->indio_dev);
> +	kfree(chip);
> +
> +	return 0;
> +}
> +
> +static const struct spi_device_id ad7314_id[] = {
> +	{ "adt7301", 0 },
> +	{ "adt7302", 0 },
> +	{ "ad7314", 0 },
> +	{}
> +};
> +
> +static struct spi_driver ad7314_driver = {
> +	.driver = {
> +		.name = "ad7314",
> +		.bus = &spi_bus_type,
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = ad7314_probe,
> +	.remove = __devexit_p(ad7314_remove),
> +	.id_table = ad7314_id,
> +};
> +
> +static __init int ad7314_init(void)
> +{
> +	return spi_register_driver(&ad7314_driver);
> +}
> +
> +static __exit void ad7314_exit(void)
> +{
> +	spi_unregister_driver(&ad7314_driver);
> +}
> +
> +MODULE_AUTHOR("Sonic Zhang <sonic.zhang@xxxxxxxxxx>");
> +MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
> +			" temperature sensor driver");
> +MODULE_LICENSE("GPL v2");
> +
> +module_init(ad7314_init);
> +module_exit(ad7314_exit);

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux