diff options
Diffstat (limited to 'drivers/hwmon/lm70.c')
-rw-r--r-- | drivers/hwmon/lm70.c | 91 |
1 files changed, 78 insertions, 13 deletions
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index d435f003292d..ae6204f33214 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c | |||
@@ -37,9 +37,13 @@ | |||
37 | 37 | ||
38 | #define DRVNAME "lm70" | 38 | #define DRVNAME "lm70" |
39 | 39 | ||
40 | #define LM70_CHIP_LM70 0 /* original NS LM70 */ | ||
41 | #define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */ | ||
42 | |||
40 | struct lm70 { | 43 | struct lm70 { |
41 | struct device *hwmon_dev; | 44 | struct device *hwmon_dev; |
42 | struct mutex lock; | 45 | struct mutex lock; |
46 | unsigned int chip; | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /* sysfs hook function */ | 49 | /* sysfs hook function */ |
@@ -47,7 +51,7 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
47 | struct device_attribute *attr, char *buf) | 51 | struct device_attribute *attr, char *buf) |
48 | { | 52 | { |
49 | struct spi_device *spi = to_spi_device(dev); | 53 | struct spi_device *spi = to_spi_device(dev); |
50 | int status, val; | 54 | int status, val = 0; |
51 | u8 rxbuf[2]; | 55 | u8 rxbuf[2]; |
52 | s16 raw=0; | 56 | s16 raw=0; |
53 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); | 57 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); |
@@ -65,12 +69,12 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
65 | "spi_write_then_read failed with status %d\n", status); | 69 | "spi_write_then_read failed with status %d\n", status); |
66 | goto out; | 70 | goto out; |
67 | } | 71 | } |
68 | dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]); | 72 | raw = (rxbuf[0] << 8) + rxbuf[1]; |
69 | 73 | dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n", | |
70 | raw = (rxbuf[1] << 8) + rxbuf[0]; | 74 | rxbuf[0], rxbuf[1], raw); |
71 | dev_dbg(dev, "raw=0x%x\n", raw); | ||
72 | 75 | ||
73 | /* | 76 | /* |
77 | * LM70: | ||
74 | * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's | 78 | * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's |
75 | * complement value. Only the MSB 11 bits (1 sign + 10 temperature | 79 | * complement value. Only the MSB 11 bits (1 sign + 10 temperature |
76 | * bits) are meaningful; the LSB 5 bits are to be discarded. | 80 | * bits) are meaningful; the LSB 5 bits are to be discarded. |
@@ -80,8 +84,21 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
80 | * by 0.25. Also multiply by 1000 to represent in millidegrees | 84 | * by 0.25. Also multiply by 1000 to represent in millidegrees |
81 | * Celsius. | 85 | * Celsius. |
82 | * So it's equivalent to multiplying by 0.25 * 1000 = 250. | 86 | * So it's equivalent to multiplying by 0.25 * 1000 = 250. |
87 | * | ||
88 | * TMP121/TMP123: | ||
89 | * 13 bits of 2's complement data, discard LSB 3 bits, | ||
90 | * resolution 0.0625 degrees celsius. | ||
83 | */ | 91 | */ |
84 | val = ((int)raw/32) * 250; | 92 | switch (p_lm70->chip) { |
93 | case LM70_CHIP_LM70: | ||
94 | val = ((int)raw / 32) * 250; | ||
95 | break; | ||
96 | |||
97 | case LM70_CHIP_TMP121: | ||
98 | val = ((int)raw / 8) * 625 / 10; | ||
99 | break; | ||
100 | } | ||
101 | |||
85 | status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ | 102 | status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ |
86 | out: | 103 | out: |
87 | mutex_unlock(&p_lm70->lock); | 104 | mutex_unlock(&p_lm70->lock); |
@@ -93,27 +110,39 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); | |||
93 | static ssize_t lm70_show_name(struct device *dev, struct device_attribute | 110 | static ssize_t lm70_show_name(struct device *dev, struct device_attribute |
94 | *devattr, char *buf) | 111 | *devattr, char *buf) |
95 | { | 112 | { |
96 | return sprintf(buf, "lm70\n"); | 113 | struct lm70 *p_lm70 = dev_get_drvdata(dev); |
114 | int ret; | ||
115 | |||
116 | switch (p_lm70->chip) { | ||
117 | case LM70_CHIP_LM70: | ||
118 | ret = sprintf(buf, "lm70\n"); | ||
119 | break; | ||
120 | case LM70_CHIP_TMP121: | ||
121 | ret = sprintf(buf, "tmp121\n"); | ||
122 | break; | ||
123 | default: | ||
124 | ret = -EINVAL; | ||
125 | } | ||
126 | return ret; | ||
97 | } | 127 | } |
98 | 128 | ||
99 | static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); | 129 | static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); |
100 | 130 | ||
101 | /*----------------------------------------------------------------------*/ | 131 | /*----------------------------------------------------------------------*/ |
102 | 132 | ||
103 | static int __devinit lm70_probe(struct spi_device *spi) | 133 | static int __devinit common_probe(struct spi_device *spi, int chip) |
104 | { | 134 | { |
105 | struct lm70 *p_lm70; | 135 | struct lm70 *p_lm70; |
106 | int status; | 136 | int status; |
107 | 137 | ||
108 | /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ | 138 | /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ |
109 | if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) | ||
110 | return -EINVAL; | ||
111 | 139 | ||
112 | p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); | 140 | p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); |
113 | if (!p_lm70) | 141 | if (!p_lm70) |
114 | return -ENOMEM; | 142 | return -ENOMEM; |
115 | 143 | ||
116 | mutex_init(&p_lm70->lock); | 144 | mutex_init(&p_lm70->lock); |
145 | p_lm70->chip = chip; | ||
117 | 146 | ||
118 | /* sysfs hook */ | 147 | /* sysfs hook */ |
119 | p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); | 148 | p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); |
@@ -141,6 +170,24 @@ out_dev_reg_failed: | |||
141 | return status; | 170 | return status; |
142 | } | 171 | } |
143 | 172 | ||
173 | static int __devinit lm70_probe(struct spi_device *spi) | ||
174 | { | ||
175 | /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ | ||
176 | if ((spi->mode & (SPI_CPOL | SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) | ||
177 | return -EINVAL; | ||
178 | |||
179 | return common_probe(spi, LM70_CHIP_LM70); | ||
180 | } | ||
181 | |||
182 | static int __devinit tmp121_probe(struct spi_device *spi) | ||
183 | { | ||
184 | /* signaling is SPI_MODE_0 with only MISO connected */ | ||
185 | if (spi->mode & (SPI_CPOL | SPI_CPHA)) | ||
186 | return -EINVAL; | ||
187 | |||
188 | return common_probe(spi, LM70_CHIP_TMP121); | ||
189 | } | ||
190 | |||
144 | static int __devexit lm70_remove(struct spi_device *spi) | 191 | static int __devexit lm70_remove(struct spi_device *spi) |
145 | { | 192 | { |
146 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); | 193 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); |
@@ -154,6 +201,15 @@ static int __devexit lm70_remove(struct spi_device *spi) | |||
154 | return 0; | 201 | return 0; |
155 | } | 202 | } |
156 | 203 | ||
204 | static struct spi_driver tmp121_driver = { | ||
205 | .driver = { | ||
206 | .name = "tmp121", | ||
207 | .owner = THIS_MODULE, | ||
208 | }, | ||
209 | .probe = tmp121_probe, | ||
210 | .remove = __devexit_p(lm70_remove), | ||
211 | }; | ||
212 | |||
157 | static struct spi_driver lm70_driver = { | 213 | static struct spi_driver lm70_driver = { |
158 | .driver = { | 214 | .driver = { |
159 | .name = "lm70", | 215 | .name = "lm70", |
@@ -165,17 +221,26 @@ static struct spi_driver lm70_driver = { | |||
165 | 221 | ||
166 | static int __init init_lm70(void) | 222 | static int __init init_lm70(void) |
167 | { | 223 | { |
168 | return spi_register_driver(&lm70_driver); | 224 | int ret = spi_register_driver(&lm70_driver); |
225 | if (ret) | ||
226 | return ret; | ||
227 | |||
228 | ret = spi_register_driver(&tmp121_driver); | ||
229 | if (ret) | ||
230 | spi_unregister_driver(&lm70_driver); | ||
231 | |||
232 | return ret; | ||
169 | } | 233 | } |
170 | 234 | ||
171 | static void __exit cleanup_lm70(void) | 235 | static void __exit cleanup_lm70(void) |
172 | { | 236 | { |
173 | spi_unregister_driver(&lm70_driver); | 237 | spi_unregister_driver(&lm70_driver); |
238 | spi_unregister_driver(&tmp121_driver); | ||
174 | } | 239 | } |
175 | 240 | ||
176 | module_init(init_lm70); | 241 | module_init(init_lm70); |
177 | module_exit(cleanup_lm70); | 242 | module_exit(cleanup_lm70); |
178 | 243 | ||
179 | MODULE_AUTHOR("Kaiwan N Billimoria"); | 244 | MODULE_AUTHOR("Kaiwan N Billimoria"); |
180 | MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver"); | 245 | MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver"); |
181 | MODULE_LICENSE("GPL"); | 246 | MODULE_LICENSE("GPL"); |