aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaiwan N Billimoria <kaiwan@designergraphix.com>2006-06-12 16:00:05 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-22 14:10:35 -0400
commite1a8e913f97e36cc5a23a24a8b4717e84998f13c (patch)
tree3ee23138ab7acba7a8ceb8f38f14eecac055141e
parent060b2f5584bf3bbb0268c83c24d5a506780fb702 (diff)
[PATCH] lm70: New hardware monitoring driver
This driver implements support for the National Semiconductor LM70 temperature sensor. The LM70 temperature sensor chip supports a single temperature sensor. It communicates with a host processor (or microcontroller) via an SPI/Microwire Bus interface. Communication with the LM70 is simple: when the temperature is to be sensed, the driver accesses the LM70 using SPI communication: 16 SCLK cycles comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's complement digital temperature (sent via the SIO line), is available in the driver for interpretation. This driver makes use of the kernel's in-core SPI support. Signed-off-by: Kaiwan N Billimoria <kaiwan@designergraphix.com> Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/hwmon/lm7031
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/lm70.c165
4 files changed, 207 insertions, 0 deletions
diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70
new file mode 100644
index 000000000000..2bdd3feebf53
--- /dev/null
+++ b/Documentation/hwmon/lm70
@@ -0,0 +1,31 @@
1Kernel driver lm70
2==================
3
4Supported chip:
5 * National Semiconductor LM70
6 Datasheet: http://www.national.com/pf/LM/LM70.html
7
8Author:
9 Kaiwan N Billimoria <kaiwan@designergraphix.com>
10
11Description
12-----------
13
14This driver implements support for the National Semiconductor LM70
15temperature sensor.
16
17The LM70 temperature sensor chip supports a single temperature sensor.
18It communicates with a host processor (or microcontroller) via an
19SPI/Microwire Bus interface.
20
21Communication with the LM70 is simple: when the temperature is to be sensed,
22the driver accesses the LM70 using SPI communication: 16 SCLK cycles
23comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's
24complement digital temperature (sent via the SIO line), is available in the
25driver for interpretation. This driver makes use of the kernel's in-core
26SPI support.
27
28Thanks to
29---------
30Jean Delvare <khali@linux-fr.org> for mentoring the hwmon-side driver
31development.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 43e1f082f7be..0e31a0c496e8 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -204,6 +204,16 @@ config SENSORS_LM63
204 This driver can also be built as a module. If so, the module 204 This driver can also be built as a module. If so, the module
205 will be called lm63. 205 will be called lm63.
206 206
207config SENSORS_LM70
208 tristate "National Semiconductor LM70"
209 depends on HWMON && SPI_MASTER && EXPERIMENTAL
210 help
211 If you say yes here you get support for the National Semiconductor
212 LM70 digital temperature sensor chip.
213
214 This driver can also be built as a module. If so, the module
215 will be called lm70.
216
207config SENSORS_LM75 217config SENSORS_LM75
208 tristate "National Semiconductor LM75 and compatibles" 218 tristate "National Semiconductor LM75 and compatibles"
209 depends on HWMON && I2C 219 depends on HWMON && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 5092999deb7b..31415843a91a 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
28obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o 28obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
29obj-$(CONFIG_SENSORS_IT87) += it87.o 29obj-$(CONFIG_SENSORS_IT87) += it87.o
30obj-$(CONFIG_SENSORS_LM63) += lm63.o 30obj-$(CONFIG_SENSORS_LM63) += lm63.o
31obj-$(CONFIG_SENSORS_LM70) += lm70.o
31obj-$(CONFIG_SENSORS_LM75) += lm75.o 32obj-$(CONFIG_SENSORS_LM75) += lm75.o
32obj-$(CONFIG_SENSORS_LM77) += lm77.o 33obj-$(CONFIG_SENSORS_LM77) += lm77.o
33obj-$(CONFIG_SENSORS_LM78) += lm78.o 34obj-$(CONFIG_SENSORS_LM78) += lm78.o
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
new file mode 100644
index 000000000000..6ba84731b9cd
--- /dev/null
+++ b/drivers/hwmon/lm70.c
@@ -0,0 +1,165 @@
1/*
2 * lm70.c
3 *
4 * The LM70 is a temperature sensor chip from National Semiconductor (NS).
5 * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
6 *
7 * The LM70 communicates with a host processor via an SPI/Microwire Bus
8 * interface. The complete datasheet is available at National's website
9 * here:
10 * http://www.national.com/pf/LM/LM70.html
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/init.h>
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/device.h>
31#include <linux/err.h>
32#include <linux/sysfs.h>
33#include <linux/hwmon.h>
34#include <linux/spi/spi.h>
35#include <asm/semaphore.h>
36
37#define DRVNAME "lm70"
38
39struct lm70 {
40 struct class_device *cdev;
41 struct semaphore sem;
42};
43
44/* sysfs hook function */
45static ssize_t lm70_sense_temp(struct device *dev,
46 struct device_attribute *attr, char *buf)
47{
48 struct spi_device *spi = to_spi_device(dev);
49 int status, val;
50 u8 rxbuf[2];
51 s16 raw=0;
52 struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
53
54 if (down_interruptible(&p_lm70->sem))
55 return -ERESTARTSYS;
56
57 /*
58 * spi_read() requires a DMA-safe buffer; so we use
59 * spi_write_then_read(), transmitting 0 bytes.
60 */
61 status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
62 if (status < 0) {
63 printk(KERN_WARNING
64 "spi_write_then_read failed with status %d\n", status);
65 goto out;
66 }
67 dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]);
68
69 raw = (rxbuf[1] << 8) + rxbuf[0];
70 dev_dbg(dev, "raw=0x%x\n", raw);
71
72 /*
73 * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's
74 * complement value. Only the MSB 11 bits (1 sign + 10 temperature
75 * bits) are meaningful; the LSB 5 bits are to be discarded.
76 * See the datasheet.
77 *
78 * Further, each bit represents 0.25 degrees Celsius; so, multiply
79 * by 0.25. Also multiply by 1000 to represent in millidegrees
80 * Celsius.
81 * So it's equivalent to multiplying by 0.25 * 1000 = 250.
82 */
83 val = ((int)raw/32) * 250;
84 status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */
85out:
86 up(&p_lm70->sem);
87 return status;
88}
89
90static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
91
92/*----------------------------------------------------------------------*/
93
94static int __devinit lm70_probe(struct spi_device *spi)
95{
96 struct lm70 *p_lm70;
97 int status;
98
99 p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
100 if (!p_lm70)
101 return -ENOMEM;
102
103 init_MUTEX(&p_lm70->sem);
104
105 /* sysfs hook */
106 p_lm70->cdev = hwmon_device_register(&spi->dev);
107 if (IS_ERR(p_lm70->cdev)) {
108 dev_dbg(&spi->dev, "hwmon_device_register failed.\n");
109 status = PTR_ERR(p_lm70->cdev);
110 goto out_dev_reg_failed;
111 }
112 dev_set_drvdata(&spi->dev, p_lm70);
113
114 if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) {
115 dev_dbg(&spi->dev, "device_create_file failure.\n");
116 goto out_dev_create_file_failed;
117 }
118
119 return 0;
120
121out_dev_create_file_failed:
122 hwmon_device_unregister(p_lm70->cdev);
123out_dev_reg_failed:
124 dev_set_drvdata(&spi->dev, NULL);
125 kfree(p_lm70);
126 return status;
127}
128
129static int __exit lm70_remove(struct spi_device *spi)
130{
131 struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
132
133 device_remove_file(&spi->dev, &dev_attr_temp1_input);
134 hwmon_device_unregister(p_lm70->cdev);
135 dev_set_drvdata(&spi->dev, NULL);
136 kfree(p_lm70);
137
138 return 0;
139}
140
141static struct spi_driver lm70_driver = {
142 .driver = {
143 .name = "lm70",
144 .owner = THIS_MODULE,
145 },
146 .probe = lm70_probe,
147 .remove = __devexit_p(lm70_remove),
148};
149
150static int __init init_lm70(void)
151{
152 return spi_register_driver(&lm70_driver);
153}
154
155static void __exit cleanup_lm70(void)
156{
157 spi_unregister_driver(&lm70_driver);
158}
159
160module_init(init_lm70);
161module_exit(cleanup_lm70);
162
163MODULE_AUTHOR("Kaiwan N Billimoria");
164MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver");
165MODULE_LICENSE("GPL");