blob: f85ce70d96779b5dcd366983f48d4458cc782704 [file] [log] [blame]
Jonathan Cameron4f3a6592011-09-29 12:50:04 -04001/*
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
38enum ad7314_variant {
39 adt7301,
40 adt7302,
41 ad7314,
42};
43
44struct ad7314_data {
45 struct spi_device *spi_dev;
46 struct device *hwmon_dev;
47 u16 rx ____cacheline_aligned;
48};
49
Guenter Roeckeae14152012-04-20 11:39:17 -040050static int ad7314_spi_read(struct ad7314_data *chip)
Jonathan Cameron4f3a6592011-09-29 12:50:04 -040051{
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
Guenter Roeckeae14152012-04-20 11:39:17 -040060 return be16_to_cpu(chip->rx);
Jonathan Cameron4f3a6592011-09-29 12:50:04 -040061}
62
63static ssize_t ad7314_show_temperature(struct device *dev,
64 struct device_attribute *attr,
65 char *buf)
66{
67 struct ad7314_data *chip = dev_get_drvdata(dev);
68 s16 data;
69 int ret;
70
Guenter Roeckeae14152012-04-20 11:39:17 -040071 ret = ad7314_spi_read(chip);
Jonathan Cameron4f3a6592011-09-29 12:50:04 -040072 if (ret < 0)
73 return ret;
74 switch (spi_get_device_id(chip->spi_dev)->driver_data) {
75 case ad7314:
Guenter Roeckeae14152012-04-20 11:39:17 -040076 data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
Jonathan Cameron4f3a6592011-09-29 12:50:04 -040077 data = (data << 6) >> 6;
78
79 return sprintf(buf, "%d\n", 250 * data);
80 case adt7301:
81 case adt7302:
82 /*
83 * Documented as a 13 bit twos complement register
84 * with a sign bit - which is a 14 bit 2's complement
85 * register. 1lsb - 31.25 milli degrees centigrade
86 */
Guenter Roeckeae14152012-04-20 11:39:17 -040087 data = ret & ADT7301_TEMP_MASK;
Jonathan Cameron4f3a6592011-09-29 12:50:04 -040088 data = (data << 2) >> 2;
89
90 return sprintf(buf, "%d\n",
91 DIV_ROUND_CLOSEST(data * 3125, 100));
92 default:
93 return -EINVAL;
94 }
95}
96
97static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
98 ad7314_show_temperature, NULL, 0);
99
100static struct attribute *ad7314_attributes[] = {
101 &sensor_dev_attr_temp1_input.dev_attr.attr,
102 NULL,
103};
104
105static const struct attribute_group ad7314_group = {
106 .attrs = ad7314_attributes,
107};
108
109static int __devinit ad7314_probe(struct spi_device *spi_dev)
110{
111 int ret;
112 struct ad7314_data *chip;
113
114 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
115 if (chip == NULL) {
116 ret = -ENOMEM;
117 goto error_ret;
118 }
119 dev_set_drvdata(&spi_dev->dev, chip);
120
121 ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
122 if (ret < 0)
123 goto error_free_chip;
124 chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
125 if (IS_ERR(chip->hwmon_dev)) {
126 ret = PTR_ERR(chip->hwmon_dev);
127 goto error_remove_group;
128 }
Graeme Smechere16de912012-04-03 19:42:21 -0400129 chip->spi_dev = spi_dev;
Jonathan Cameron4f3a6592011-09-29 12:50:04 -0400130
131 return 0;
132error_remove_group:
133 sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
134error_free_chip:
135 kfree(chip);
136error_ret:
137 return ret;
138}
139
140static int __devexit ad7314_remove(struct spi_device *spi_dev)
141{
142 struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
143
144 hwmon_device_unregister(chip->hwmon_dev);
145 sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
146 kfree(chip);
147
148 return 0;
149}
150
151static const struct spi_device_id ad7314_id[] = {
152 { "adt7301", adt7301 },
153 { "adt7302", adt7302 },
154 { "ad7314", ad7314 },
155 { }
156};
157MODULE_DEVICE_TABLE(spi, ad7314_id);
158
159static struct spi_driver ad7314_driver = {
160 .driver = {
161 .name = "ad7314",
Jonathan Cameron4f3a6592011-09-29 12:50:04 -0400162 .owner = THIS_MODULE,
163 },
164 .probe = ad7314_probe,
165 .remove = __devexit_p(ad7314_remove),
166 .id_table = ad7314_id,
167};
168
Axel Lin91efffe2012-01-20 15:53:47 +0800169module_spi_driver(ad7314_driver);
Jonathan Cameron4f3a6592011-09-29 12:50:04 -0400170
171MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
172MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
173 " temperature sensor driver");
174MODULE_LICENSE("GPL v2");