Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus
[linux-btrfs-devel.git] / drivers / staging / iio / adc / ad7314.c
blob9070d9cac725d3370f7b43a18493716ff3d15865
1 /*
2 * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
4 * Copyright 2010 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
7 */
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/sysfs.h>
13 #include <linux/spi/spi.h>
15 #include "../iio.h"
16 #include "../sysfs.h"
19 * AD7314 power mode
21 #define AD7314_PD 0x2000
24 * AD7314 temperature masks
26 #define AD7314_TEMP_SIGN 0x200
27 #define AD7314_TEMP_MASK 0x7FE0
28 #define AD7314_TEMP_OFFSET 5
29 #define AD7314_TEMP_FLOAT_OFFSET 2
30 #define AD7314_TEMP_FLOAT_MASK 0x3
33 * ADT7301 and ADT7302 temperature masks
35 #define ADT7301_TEMP_SIGN 0x2000
36 #define ADT7301_TEMP_MASK 0x2FFF
37 #define ADT7301_TEMP_FLOAT_OFFSET 5
38 #define ADT7301_TEMP_FLOAT_MASK 0x1F
41 * struct ad7314_chip_info - chip specifc information
44 struct ad7314_chip_info {
45 struct spi_device *spi_dev;
46 s64 last_timestamp;
47 u8 mode;
51 * ad7314 register access by SPI
54 static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data)
56 struct spi_device *spi_dev = chip->spi_dev;
57 int ret = 0;
58 u16 value;
60 ret = spi_read(spi_dev, (u8 *)&value, sizeof(value));
61 if (ret < 0) {
62 dev_err(&spi_dev->dev, "SPI read error\n");
63 return ret;
66 *data = be16_to_cpu((u16)value);
68 return ret;
71 static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data)
73 struct spi_device *spi_dev = chip->spi_dev;
74 int ret = 0;
75 u16 value = cpu_to_be16(data);
77 ret = spi_write(spi_dev, (u8 *)&value, sizeof(value));
78 if (ret < 0)
79 dev_err(&spi_dev->dev, "SPI write error\n");
81 return ret;
84 static ssize_t ad7314_show_mode(struct device *dev,
85 struct device_attribute *attr,
86 char *buf)
88 struct iio_dev *dev_info = dev_get_drvdata(dev);
89 struct ad7314_chip_info *chip = iio_priv(dev_info);
91 if (chip->mode)
92 return sprintf(buf, "power-save\n");
93 else
94 return sprintf(buf, "full\n");
97 static ssize_t ad7314_store_mode(struct device *dev,
98 struct device_attribute *attr,
99 const char *buf,
100 size_t len)
102 struct iio_dev *dev_info = dev_get_drvdata(dev);
103 struct ad7314_chip_info *chip = iio_priv(dev_info);
104 u16 mode = 0;
105 int ret;
107 if (!strcmp(buf, "full"))
108 mode = AD7314_PD;
110 ret = ad7314_spi_write(chip, mode);
111 if (ret)
112 return -EIO;
114 chip->mode = mode;
116 return len;
119 static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
120 ad7314_show_mode,
121 ad7314_store_mode,
124 static ssize_t ad7314_show_available_modes(struct device *dev,
125 struct device_attribute *attr,
126 char *buf)
128 return sprintf(buf, "full\npower-save\n");
131 static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0);
133 static ssize_t ad7314_show_temperature(struct device *dev,
134 struct device_attribute *attr,
135 char *buf)
137 struct iio_dev *dev_info = dev_get_drvdata(dev);
138 struct ad7314_chip_info *chip = iio_priv(dev_info);
139 u16 data;
140 char sign = ' ';
141 int ret;
143 if (chip->mode) {
144 ret = ad7314_spi_write(chip, 0);
145 if (ret)
146 return -EIO;
149 ret = ad7314_spi_read(chip, &data);
150 if (ret)
151 return -EIO;
153 if (chip->mode)
154 ad7314_spi_write(chip, chip->mode);
156 if (strcmp(dev_info->name, "ad7314")) {
157 data = (data & AD7314_TEMP_MASK) >>
158 AD7314_TEMP_OFFSET;
159 if (data & AD7314_TEMP_SIGN) {
160 data = (AD7314_TEMP_SIGN << 1) - data;
161 sign = '-';
164 return sprintf(buf, "%c%d.%.2d\n", sign,
165 data >> AD7314_TEMP_FLOAT_OFFSET,
166 (data & AD7314_TEMP_FLOAT_MASK) * 25);
167 } else {
168 data &= ADT7301_TEMP_MASK;
169 if (data & ADT7301_TEMP_SIGN) {
170 data = (ADT7301_TEMP_SIGN << 1) - data;
171 sign = '-';
174 return sprintf(buf, "%c%d.%.5d\n", sign,
175 data >> ADT7301_TEMP_FLOAT_OFFSET,
176 (data & ADT7301_TEMP_FLOAT_MASK) * 3125);
180 static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0);
182 static struct attribute *ad7314_attributes[] = {
183 &iio_dev_attr_available_modes.dev_attr.attr,
184 &iio_dev_attr_mode.dev_attr.attr,
185 &iio_dev_attr_temperature.dev_attr.attr,
186 NULL,
189 static const struct attribute_group ad7314_attribute_group = {
190 .attrs = ad7314_attributes,
193 static const struct iio_info ad7314_info = {
194 .attrs = &ad7314_attribute_group,
195 .driver_module = THIS_MODULE,
198 * device probe and remove
201 static int __devinit ad7314_probe(struct spi_device *spi_dev)
203 struct ad7314_chip_info *chip;
204 struct iio_dev *indio_dev;
205 int ret = 0;
207 indio_dev = iio_allocate_device(sizeof(*chip));
208 if (indio_dev == NULL) {
209 ret = -ENOMEM;
210 goto error_ret;
212 chip = iio_priv(indio_dev);
213 /* this is only used for device removal purposes */
214 dev_set_drvdata(&spi_dev->dev, chip);
216 chip->spi_dev = spi_dev;
218 indio_dev->name = spi_get_device_id(spi_dev)->name;
219 indio_dev->dev.parent = &spi_dev->dev;
220 indio_dev->info = &ad7314_info;
222 ret = iio_device_register(indio_dev);
223 if (ret)
224 goto error_free_dev;
226 dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
227 indio_dev->name);
229 return 0;
230 error_free_dev:
231 iio_free_device(indio_dev);
232 error_ret:
233 return ret;
236 static int __devexit ad7314_remove(struct spi_device *spi_dev)
238 struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
240 dev_set_drvdata(&spi_dev->dev, NULL);
241 iio_device_unregister(indio_dev);
242 iio_free_device(indio_dev);
244 return 0;
247 static const struct spi_device_id ad7314_id[] = {
248 { "adt7301", 0 },
249 { "adt7302", 0 },
250 { "ad7314", 0 },
254 static struct spi_driver ad7314_driver = {
255 .driver = {
256 .name = "ad7314",
257 .bus = &spi_bus_type,
258 .owner = THIS_MODULE,
260 .probe = ad7314_probe,
261 .remove = __devexit_p(ad7314_remove),
262 .id_table = ad7314_id,
265 static __init int ad7314_init(void)
267 return spi_register_driver(&ad7314_driver);
270 static __exit void ad7314_exit(void)
272 spi_unregister_driver(&ad7314_driver);
275 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
276 MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
277 " temperature sensor driver");
278 MODULE_LICENSE("GPL v2");
280 module_init(ad7314_init);
281 module_exit(ad7314_exit);