Skip to content

Commit 51c2a48

Browse files
larsclausengroeck
authored andcommitted
hwmon: (adt7410) Add support for the adt7310/adt7320
The adt7310/adt7320 is the SPI version of the adt7410/adt7420. The register map layout is a bit different, i.e. the register addresses differ between the two variants, but the bit layouts of the individual registers are identical. So both chip variants can easily be supported by the same driver. The issue of non matching register address layouts is solved by a simple look-up table which translates the I2C addresses to the SPI addresses. The patch moves the bulk of the adt7410 driver to a common module that will be shared by the adt7410 and adt7310 drivers. This common module implements the driver logic and uses a set of virtual functions to perform IO access. The adt7410 and adt7310 driver modules provide proper implementations of these IO accessor functions for I2C respective SPI. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Reviewed-by: Hartmut Knaack <knaack.h@gmx.de> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent c55dc91 commit 51c2a48

File tree

7 files changed

+719
-453
lines changed

7 files changed

+719
-453
lines changed

Documentation/hwmon/adt7410

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,42 @@ Supported chips:
1212
Addresses scanned: None
1313
Datasheet: Publicly available at the Analog Devices website
1414
http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf
15+
* Analog Devices ADT7310
16+
Prefix: 'adt7310'
17+
Addresses scanned: None
18+
Datasheet: Publicly available at the Analog Devices website
19+
http://www.analog.com/static/imported-files/data_sheets/ADT7310.pdf
20+
* Analog Devices ADT7320
21+
Prefix: 'adt7320'
22+
Addresses scanned: None
23+
Datasheet: Publicly available at the Analog Devices website
24+
http://www.analog.com/static/imported-files/data_sheets/ADT7320.pdf
1525

1626
Author: Hartmut Knaack <knaack.h@gmx.de>
1727

1828
Description
1929
-----------
2030

21-
The ADT7410 is a temperature sensor with rated temperature range of -55°C to
22-
+150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution
23-
of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to
24-
indicate that a minimum or maximum temperature set point has been exceeded, as
25-
well as a critical temperature (CT) pin to indicate that the critical
26-
temperature set point has been exceeded. Both pins can be set up with a common
27-
hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both
28-
pins can individually set to be active-low or active-high, while the whole
29-
device can either run in comparator mode or interrupt mode. The ADT7410
30-
supports continous temperature sampling, as well as sampling one temperature
31-
value per second or even justget one sample on demand for power saving.
32-
Besides, it can completely power down its ADC, if power management is
33-
required.
34-
35-
The ADT7420 is register compatible, the only differences being the package,
36-
a slightly narrower operating temperature range (-40°C to +150°C), and a
37-
better accuracy (0.25°C instead of 0.50°C.)
31+
The ADT7310/ADT7410 is a temperature sensor with rated temperature range of
32+
-55°C to +150°C. It has a high accuracy of +/-0.5°C and can be operated at a
33+
resolution of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an
34+
INT pin to indicate that a minimum or maximum temperature set point has been
35+
exceeded, as well as a critical temperature (CT) pin to indicate that the
36+
critical temperature set point has been exceeded. Both pins can be set up with a
37+
common hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events.
38+
Both pins can individually set to be active-low or active-high, while the whole
39+
device can either run in comparator mode or interrupt mode. The ADT7410 supports
40+
continuous temperature sampling, as well as sampling one temperature value per
41+
second or even just get one sample on demand for power saving. Besides, it can
42+
completely power down its ADC, if power management is required.
43+
44+
The ADT7320/ADT7420 is register compatible, the only differences being the
45+
package, a slightly narrower operating temperature range (-40°C to +150°C), and
46+
a better accuracy (0.25°C instead of 0.50°C.)
47+
48+
The difference between the ADT7310/ADT7320 and ADT7410/ADT7420 is the control
49+
interface, the ADT7310 and ADT7320 use SPI while the ADT7410 and ADT7420 use
50+
I2C.
3851

3952
Configuration Notes
4053
-------------------

drivers/hwmon/Kconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,29 @@ config SENSORS_ADM9240
179179
This driver can also be built as a module. If so, the module
180180
will be called adm9240.
181181

182+
config SENSORS_ADT7X10
183+
tristate
184+
help
185+
This module contains common code shared by the ADT7310/ADT7320 and
186+
ADT7410/ADT7420 temperature monitoring chip drivers.
187+
188+
If build as a module, the module will be called adt7x10.
189+
190+
config SENSORS_ADT7310
191+
tristate "Analog Devices ADT7310/ADT7320"
192+
depends on SPI_MASTER
193+
select SENSORS_ADT7X10
194+
help
195+
If you say yes here you get support for the Analog Devices
196+
ADT7310 and ADT7320 temperature monitoring chips.
197+
198+
This driver can also be built as a module. If so, the module
199+
will be called adt7310.
200+
182201
config SENSORS_ADT7410
183202
tristate "Analog Devices ADT7410/ADT7420"
184203
depends on I2C
204+
select SENSORS_ADT7X10
185205
help
186206
If you say yes here you get support for the Analog Devices
187207
ADT7410 and ADT7420 temperature monitoring chips.

drivers/hwmon/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
3434
obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o
3535
obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
3636
obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o
37+
obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o
38+
obj-$(CONFIG_SENSORS_ADT7310) += adt7310.o
3739
obj-$(CONFIG_SENSORS_ADT7410) += adt7410.o
3840
obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o
3941
obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o

drivers/hwmon/adt7310.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* ADT7310/ADT7310 digital temperature sensor driver
3+
*
4+
* Copyright 2012-2013 Analog Devices Inc.
5+
* Author: Lars-Peter Clausen <lars@metafoo.de>
6+
*
7+
* Licensed under the GPL-2 or later.
8+
*/
9+
10+
#include <linux/module.h>
11+
#include <linux/init.h>
12+
#include <linux/spi/spi.h>
13+
#include <asm/unaligned.h>
14+
15+
#include "adt7x10.h"
16+
17+
#define ADT7310_STATUS 0
18+
#define ADT7310_CONFIG 1
19+
#define ADT7310_TEMPERATURE 2
20+
#define ADT7310_ID 3
21+
#define ADT7310_T_CRIT 4
22+
#define ADT7310_T_HYST 5
23+
#define ADT7310_T_ALARM_HIGH 6
24+
#define ADT7310_T_ALARM_LOW 7
25+
26+
static const u8 adt7310_reg_table[] = {
27+
[ADT7X10_TEMPERATURE] = ADT7310_TEMPERATURE,
28+
[ADT7X10_STATUS] = ADT7310_STATUS,
29+
[ADT7X10_CONFIG] = ADT7310_CONFIG,
30+
[ADT7X10_T_ALARM_HIGH] = ADT7310_T_ALARM_HIGH,
31+
[ADT7X10_T_ALARM_LOW] = ADT7310_T_ALARM_LOW,
32+
[ADT7X10_T_CRIT] = ADT7310_T_CRIT,
33+
[ADT7X10_T_HYST] = ADT7310_T_HYST,
34+
[ADT7X10_ID] = ADT7310_ID,
35+
};
36+
37+
#define ADT7310_CMD_REG_OFFSET 3
38+
#define ADT7310_CMD_READ 0x40
39+
40+
#define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
41+
42+
static int adt7310_spi_read_word(struct device *dev, u8 reg)
43+
{
44+
struct spi_device *spi = to_spi_device(dev);
45+
int ret;
46+
47+
ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
48+
if (ret < 0)
49+
return ret;
50+
51+
return be16_to_cpu(ret);
52+
}
53+
54+
static int adt7310_spi_write_word(struct device *dev, u8 reg, u16 data)
55+
{
56+
struct spi_device *spi = to_spi_device(dev);
57+
u8 buf[3];
58+
59+
buf[0] = AD7310_COMMAND(reg);
60+
put_unaligned_be16(data, &buf[1]);
61+
62+
return spi_write(spi, buf, sizeof(buf));
63+
}
64+
65+
static int adt7310_spi_read_byte(struct device *dev, u8 reg)
66+
{
67+
struct spi_device *spi = to_spi_device(dev);
68+
69+
return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
70+
}
71+
72+
static int adt7310_spi_write_byte(struct device *dev, u8 reg,
73+
u8 data)
74+
{
75+
struct spi_device *spi = to_spi_device(dev);
76+
u8 buf[2];
77+
78+
buf[0] = AD7310_COMMAND(reg);
79+
buf[1] = data;
80+
81+
return spi_write(spi, buf, sizeof(buf));
82+
}
83+
84+
static const struct adt7x10_ops adt7310_spi_ops = {
85+
.read_word = adt7310_spi_read_word,
86+
.write_word = adt7310_spi_write_word,
87+
.read_byte = adt7310_spi_read_byte,
88+
.write_byte = adt7310_spi_write_byte,
89+
};
90+
91+
static int adt7310_spi_probe(struct spi_device *spi)
92+
{
93+
return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name,
94+
&adt7310_spi_ops);
95+
}
96+
97+
static int adt7310_spi_remove(struct spi_device *spi)
98+
{
99+
return adt7x10_remove(&spi->dev);
100+
}
101+
102+
static const struct spi_device_id adt7310_id[] = {
103+
{ "adt7310", 0 },
104+
{ "adt7320", 0 },
105+
{}
106+
};
107+
MODULE_DEVICE_TABLE(spi, adt7310_id);
108+
109+
static struct spi_driver adt7310_driver = {
110+
.driver = {
111+
.name = "adt7310",
112+
.owner = THIS_MODULE,
113+
.pm = ADT7X10_DEV_PM_OPS,
114+
},
115+
.probe = adt7310_spi_probe,
116+
.remove = adt7310_spi_remove,
117+
.id_table = adt7310_id,
118+
};
119+
module_spi_driver(adt7310_driver);
120+
121+
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
122+
MODULE_DESCRIPTION("ADT7310/ADT7320 driver");
123+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)