diff options
author | Jonathan Cameron <jic23@cam.ac.uk> | 2011-09-29 12:50:04 -0400 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-10-24 14:09:41 -0400 |
commit | 4f3a659581cabf1be441d6467b523be914615496 (patch) | |
tree | 7d5d581f10409b883fab255f7ccede8692497b2b | |
parent | 200855e52db1b1834121ba57fbd89c5b4911e02c (diff) |
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>
-rw-r--r-- | Documentation/hwmon/ad7314 | 25 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/ad7314.c | 186 |
4 files changed, 222 insertions, 0 deletions
diff --git a/Documentation/hwmon/ad7314 b/Documentation/hwmon/ad7314 new file mode 100644 index 000000000000..1912549c7467 --- /dev/null +++ b/Documentation/hwmon/ad7314 | |||
@@ -0,0 +1,25 @@ | |||
1 | Kernel driver ad7314 | ||
2 | ==================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Analog Devices AD7314 | ||
6 | Prefix: 'ad7314' | ||
7 | Datasheet: Publicly available at Analog Devices website. | ||
8 | * Analog Devices ADT7301 | ||
9 | Prefix: 'adt7301' | ||
10 | Datasheet: Publicly available at Analog Devices website. | ||
11 | * Analog Devices ADT7302 | ||
12 | Prefix: 'adt7302' | ||
13 | Datasheet: Publicly available at Analog Devices website. | ||
14 | |||
15 | Description | ||
16 | ----------- | ||
17 | |||
18 | Driver supports the above parts. The ad7314 has a 10 bit | ||
19 | sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and | ||
20 | adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade. | ||
21 | |||
22 | Notes | ||
23 | ----- | ||
24 | |||
25 | Currently power down mode is not supported. | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c6fb7611dd10..378ed8ae34d0 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -68,6 +68,16 @@ config SENSORS_ABITUGURU3 | |||
68 | This driver can also be built as a module. If so, the module | 68 | This driver can also be built as a module. If so, the module |
69 | will be called abituguru3. | 69 | will be called abituguru3. |
70 | 70 | ||
71 | config SENSORS_AD7314 | ||
72 | tristate "Analog Devices AD7314 and compatibles" | ||
73 | depends on SPI && EXPERIMENTAL | ||
74 | help | ||
75 | If you say yes here you get support for the Analog Devices | ||
76 | AD7314, ADT7301 and ADT7302 temperature sensors. | ||
77 | |||
78 | This driver can also be built as a module. If so, the module | ||
79 | will be called ad7314. | ||
80 | |||
71 | config SENSORS_AD7414 | 81 | config SENSORS_AD7414 |
72 | tristate "Analog Devices AD7414" | 82 | tristate "Analog Devices AD7414" |
73 | depends on I2C && EXPERIMENTAL | 83 | depends on I2C && EXPERIMENTAL |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index dbd8963ec7fa..8251ce8cd035 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o | |||
21 | 21 | ||
22 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o | 22 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o |
23 | obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o | 23 | obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o |
24 | obj-$(CONFIG_SENSORS_AD7314) += ad7314.o | ||
24 | obj-$(CONFIG_SENSORS_AD7414) += ad7414.o | 25 | obj-$(CONFIG_SENSORS_AD7414) += ad7414.o |
25 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o | 26 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o |
26 | obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o | 27 | obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o |
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c new file mode 100644 index 000000000000..318e38e85376 --- /dev/null +++ b/drivers/hwmon/ad7314.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | * | ||
8 | * Conversion to hwmon from IIO done by Jonathan Cameron <jic23@cam.ac.uk> | ||
9 | */ | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/sysfs.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/hwmon.h> | ||
18 | #include <linux/hwmon-sysfs.h> | ||
19 | |||
20 | /* | ||
21 | * AD7314 power mode | ||
22 | */ | ||
23 | #define AD7314_PD 0x2000 | ||
24 | |||
25 | /* | ||
26 | * AD7314 temperature masks | ||
27 | */ | ||
28 | #define AD7314_TEMP_SIGN 0x200 | ||
29 | #define AD7314_TEMP_MASK 0x7FE0 | ||
30 | #define AD7314_TEMP_OFFSET 5 | ||
31 | |||
32 | /* | ||
33 | * ADT7301 and ADT7302 temperature masks | ||
34 | */ | ||
35 | #define ADT7301_TEMP_SIGN 0x2000 | ||
36 | #define ADT7301_TEMP_MASK 0x3FFF | ||
37 | |||
38 | enum ad7314_variant { | ||
39 | adt7301, | ||
40 | adt7302, | ||
41 | ad7314, | ||
42 | }; | ||
43 | |||
44 | struct ad7314_data { | ||
45 | struct spi_device *spi_dev; | ||
46 | struct device *hwmon_dev; | ||
47 | u16 rx ____cacheline_aligned; | ||
48 | }; | ||
49 | |||
50 | static int ad7314_spi_read(struct ad7314_data *chip, s16 *data) | ||
51 | { | ||
52 | int ret; | ||
53 | |||
54 | ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx)); | ||
55 | if (ret < 0) { | ||
56 | dev_err(&chip->spi_dev->dev, "SPI read error\n"); | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | *data = be16_to_cpu(chip->rx); | ||
61 | |||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | static ssize_t ad7314_show_temperature(struct device *dev, | ||
66 | struct device_attribute *attr, | ||
67 | char *buf) | ||
68 | { | ||
69 | struct ad7314_data *chip = dev_get_drvdata(dev); | ||
70 | s16 data; | ||
71 | int ret; | ||
72 | |||
73 | ret = ad7314_spi_read(chip, &data); | ||
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | switch (spi_get_device_id(chip->spi_dev)->driver_data) { | ||
77 | case ad7314: | ||
78 | data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET; | ||
79 | data = (data << 6) >> 6; | ||
80 | |||
81 | return sprintf(buf, "%d\n", 250 * data); | ||
82 | case adt7301: | ||
83 | case adt7302: | ||
84 | /* | ||
85 | * Documented as a 13 bit twos complement register | ||
86 | * with a sign bit - which is a 14 bit 2's complement | ||
87 | * register. 1lsb - 31.25 milli degrees centigrade | ||
88 | */ | ||
89 | data &= ADT7301_TEMP_MASK; | ||
90 | data = (data << 2) >> 2; | ||
91 | |||
92 | return sprintf(buf, "%d\n", | ||
93 | DIV_ROUND_CLOSEST(data * 3125, 100)); | ||
94 | default: | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, | ||
100 | ad7314_show_temperature, NULL, 0); | ||
101 | |||
102 | static struct attribute *ad7314_attributes[] = { | ||
103 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
104 | NULL, | ||
105 | }; | ||
106 | |||
107 | static const struct attribute_group ad7314_group = { | ||
108 | .attrs = ad7314_attributes, | ||
109 | }; | ||
110 | |||
111 | static int __devinit ad7314_probe(struct spi_device *spi_dev) | ||
112 | { | ||
113 | int ret; | ||
114 | struct ad7314_data *chip; | ||
115 | |||
116 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
117 | if (chip == NULL) { | ||
118 | ret = -ENOMEM; | ||
119 | goto error_ret; | ||
120 | } | ||
121 | dev_set_drvdata(&spi_dev->dev, chip); | ||
122 | |||
123 | ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group); | ||
124 | if (ret < 0) | ||
125 | goto error_free_chip; | ||
126 | chip->hwmon_dev = hwmon_device_register(&spi_dev->dev); | ||
127 | if (IS_ERR(chip->hwmon_dev)) { | ||
128 | ret = PTR_ERR(chip->hwmon_dev); | ||
129 | goto error_remove_group; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | error_remove_group: | ||
134 | sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); | ||
135 | error_free_chip: | ||
136 | kfree(chip); | ||
137 | error_ret: | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int __devexit ad7314_remove(struct spi_device *spi_dev) | ||
142 | { | ||
143 | struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev); | ||
144 | |||
145 | hwmon_device_unregister(chip->hwmon_dev); | ||
146 | sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); | ||
147 | kfree(chip); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static const struct spi_device_id ad7314_id[] = { | ||
153 | { "adt7301", adt7301 }, | ||
154 | { "adt7302", adt7302 }, | ||
155 | { "ad7314", ad7314 }, | ||
156 | { } | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(spi, ad7314_id); | ||
159 | |||
160 | static struct spi_driver ad7314_driver = { | ||
161 | .driver = { | ||
162 | .name = "ad7314", | ||
163 | .bus = &spi_bus_type, | ||
164 | .owner = THIS_MODULE, | ||
165 | }, | ||
166 | .probe = ad7314_probe, | ||
167 | .remove = __devexit_p(ad7314_remove), | ||
168 | .id_table = ad7314_id, | ||
169 | }; | ||
170 | |||
171 | static __init int ad7314_init(void) | ||
172 | { | ||
173 | return spi_register_driver(&ad7314_driver); | ||
174 | } | ||
175 | module_init(ad7314_init); | ||
176 | |||
177 | static __exit void ad7314_exit(void) | ||
178 | { | ||
179 | spi_unregister_driver(&ad7314_driver); | ||
180 | } | ||
181 | module_exit(ad7314_exit); | ||
182 | |||
183 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | ||
184 | MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital" | ||
185 | " temperature sensor driver"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||