forked from microsoft/WSL2-Linux-Kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hwmon: AD7314 driver (ported from IIO)
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
Showing
4 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); |