Skip to content

Commit

Permalink
hwmon: AD7314 driver (ported from IIO)
Browse files Browse the repository at this point in the history
Driver for AD7314, ADT7301, and ADT7302, ported from IIO.

Currently dropped power down mode support.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
[guenter.roeck@ericsson.com: Added MODULE_DEVICE_TABLE]
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
  • Loading branch information
Jonathan Cameron authored and Guenter Roeck committed Oct 24, 2011
1 parent 200855e commit 4f3a659
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 0 deletions.
25 changes: 25 additions & 0 deletions Documentation/hwmon/ad7314
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Kernel driver ad7314
====================

Supported chips:
* Analog Devices AD7314
Prefix: 'ad7314'
Datasheet: Publicly available at Analog Devices website.
* Analog Devices ADT7301
Prefix: 'adt7301'
Datasheet: Publicly available at Analog Devices website.
* Analog Devices ADT7302
Prefix: 'adt7302'
Datasheet: Publicly available at Analog Devices website.

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

Driver supports the above parts. The ad7314 has a 10 bit
sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and
adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade.

Notes
-----

Currently power down mode is not supported.
10 changes: 10 additions & 0 deletions drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ config SENSORS_ABITUGURU3
This driver can also be built as a module. If so, the module
will be called abituguru3.

config SENSORS_AD7314
tristate "Analog Devices AD7314 and compatibles"
depends on SPI && EXPERIMENTAL
help
If you say yes here you get support for the Analog Devices
AD7314, ADT7301 and ADT7302 temperature sensors.

This driver can also be built as a module. If so, the module
will be called ad7314.

config SENSORS_AD7414
tristate "Analog Devices AD7414"
depends on I2C && EXPERIMENTAL
Expand Down
1 change: 1 addition & 0 deletions drivers/hwmon/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o

obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o
obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
obj-$(CONFIG_SENSORS_AD7314) += ad7314.o
obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o
Expand Down
186 changes: 186 additions & 0 deletions drivers/hwmon/ad7314.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*
* Conversion to hwmon from IIO done by Jonathan Cameron <jic23@cam.ac.uk>
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/hwmon-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

/*
* ADT7301 and ADT7302 temperature masks
*/
#define ADT7301_TEMP_SIGN 0x2000
#define ADT7301_TEMP_MASK 0x3FFF

enum ad7314_variant {
adt7301,
adt7302,
ad7314,
};

struct ad7314_data {
struct spi_device *spi_dev;
struct device *hwmon_dev;
u16 rx ____cacheline_aligned;
};

static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
{
int ret;

ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx));
if (ret < 0) {
dev_err(&chip->spi_dev->dev, "SPI read error\n");
return ret;
}

*data = be16_to_cpu(chip->rx);

return ret;
}

static ssize_t ad7314_show_temperature(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ad7314_data *chip = dev_get_drvdata(dev);
s16 data;
int ret;

ret = ad7314_spi_read(chip, &data);
if (ret < 0)
return ret;
switch (spi_get_device_id(chip->spi_dev)->driver_data) {
case ad7314:
data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
data = (data << 6) >> 6;

return sprintf(buf, "%d\n", 250 * data);
case adt7301:
case adt7302:
/*
* Documented as a 13 bit twos complement register
* with a sign bit - which is a 14 bit 2's complement
* register. 1lsb - 31.25 milli degrees centigrade
*/
data &= ADT7301_TEMP_MASK;
data = (data << 2) >> 2;

return sprintf(buf, "%d\n",
DIV_ROUND_CLOSEST(data * 3125, 100));
default:
return -EINVAL;
}
}

static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
ad7314_show_temperature, NULL, 0);

static struct attribute *ad7314_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};

static const struct attribute_group ad7314_group = {
.attrs = ad7314_attributes,
};

static int __devinit ad7314_probe(struct spi_device *spi_dev)
{
int ret;
struct ad7314_data *chip;

chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
ret = -ENOMEM;
goto error_ret;
}
dev_set_drvdata(&spi_dev->dev, chip);

ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
if (ret < 0)
goto error_free_chip;
chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
if (IS_ERR(chip->hwmon_dev)) {
ret = PTR_ERR(chip->hwmon_dev);
goto error_remove_group;
}

return 0;
error_remove_group:
sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
error_free_chip:
kfree(chip);
error_ret:
return ret;
}

static int __devexit ad7314_remove(struct spi_device *spi_dev)
{
struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);

hwmon_device_unregister(chip->hwmon_dev);
sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
kfree(chip);

return 0;
}

static const struct spi_device_id ad7314_id[] = {
{ "adt7301", adt7301 },
{ "adt7302", adt7302 },
{ "ad7314", ad7314 },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7314_id);

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);
}
module_init(ad7314_init);

static __exit void ad7314_exit(void)
{
spi_unregister_driver(&ad7314_driver);
}
module_exit(ad7314_exit);

MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
" temperature sensor driver");
MODULE_LICENSE("GPL v2");

0 comments on commit 4f3a659

Please sign in to comment.