Annotation of sys/dev/i2c/lm75.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lm75.c,v 1.15 2007/03/22 16:55:31 deraadt Exp $ */
2: /* $NetBSD: lm75.c,v 1.1 2003/09/30 00:35:31 thorpej Exp $ */
3: /*
4: * Copyright (c) 2006 Theo de Raadt <deraadt@openbsd.org>
5: * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: /*
21: * National Semiconductor LM75/LM77 temperature sensor.
22: */
23:
24: #include <sys/param.h>
25: #include <sys/systm.h>
26: #include <sys/device.h>
27: #include <sys/kernel.h>
28: #include <sys/sensors.h>
29:
30: #include <dev/i2c/i2cvar.h>
31:
32: #define LM_MODEL_LM75 1
33: #define LM_MODEL_LM77 2
34: #define LM_MODEL_DS1775 3
35: #define LM_MODEL_LM75A 4
36:
37: #define LM_POLLTIME 3 /* 3s */
38:
39: #define LM75_REG_TEMP 0x00
40: #define LM75_REG_CONFIG 0x01
41: #define LM75_CONFIG_SHUTDOWN 0x01
42: #define LM75_CONFIG_CMPINT 0x02
43: #define LM75_CONFIG_OSPOLARITY 0x04
44: #define LM75_CONFIG_FAULT_QUEUE_MASK 0x18
45: #define LM75_CONFIG_FAULT_QUEUE_1 (0 << 3)
46: #define LM75_CONFIG_FAULT_QUEUE_2 (1 << 3)
47: #define LM75_CONFIG_FAULT_QUEUE_4 (2 << 3)
48: #define LM75_CONFIG_FAULT_QUEUE_6 (3 << 3)
49: #define LM77_CONFIG_INTPOLARITY 0x08
50: #define LM77_CONFIG_FAULT_QUEUE_4 0x10
51: #define DS1755_CONFIG_RESOLUTION(i) (9 + (((i) >> 5) & 3))
52: #define LM75_REG_THYST_SET_POINT 0x02
53: #define LM75_REG_TOS_SET_POINT 0x03
54: #define LM77_REG_TLOW 0x04
55: #define LM77_REG_THIGH 0x05
56:
57: struct lmtemp_softc {
58: struct device sc_dev;
59: i2c_tag_t sc_tag;
60: int sc_addr;
61: int sc_model;
62: int sc_bits;
63:
64: struct ksensor sc_sensor;
65: struct ksensordev sc_sensordev;
66: };
67:
68: int lmtemp_match(struct device *, void *, void *);
69: void lmtemp_attach(struct device *, struct device *, void *);
70:
71: struct cfattach lmtemp_ca = {
72: sizeof(struct lmtemp_softc),
73: lmtemp_match,
74: lmtemp_attach
75: };
76:
77: struct cfdriver lmtemp_cd = {
78: NULL, "lmtemp", DV_DULL
79: };
80:
81: /*
82: * Temperature on the LM75 is represented by a 9-bit two's complement
83: * integer in steps of 0.5C. The following examples are taken from
84: * the LM75 data sheet:
85: *
86: * +125C 0 1111 1010 0x0fa
87: * +25C 0 0011 0010 0x032
88: * +0.5C 0 0000 0001 0x001
89: * 0C 0 0000 0000 0x000
90: * -0.5C 1 1111 1111 0x1ff
91: * -25C 1 1100 1110 0x1ce
92: * -55C 1 1001 0010 0x192
93: *
94: * Temperature on the LM75A is represented by an 11-bit two's complement
95: * integer in steps of 0.125C. The LM75A can be treated like an LM75 if
96: * the extra precision is not required. The following examples are
97: * taken from the LM75A data sheet:
98: *
99: * +127.000C 011 1111 1000 0x3f8
100: * +126.875C 011 1111 0111 0x3f7
101: * +126.125C 011 1111 0001 0x3f1
102: * +125.000C 011 1110 1000 0x3e8
103: * +25.000C 000 1100 1000 0x0c8
104: * +0.125C 000 0000 0001 0x001
105: * 0C 000 0000 0000 0x000
106: * -0.125C 111 1111 1111 0x7ff
107: * -25.000C 111 0011 1000 0x738
108: * -54.875C 110 0100 1001 0x649
109: * -55.000C 110 0100 1000 0x648
110: *
111: * Temperature on the LM77 is represented by a 10-bit two's complement
112: * integer in steps of 0.5C:
113: *
114: * +130C 01 0000 0100 0x104
115: * +125C 00 1111 1010 0x0fa
116: * +25C 00 0011 0010 0x032
117: * +0.5C 00 0000 0001 0x001
118: * 0C 00 0000 0000 0x000
119: * -0.5C 11 1111 1111 0x3ff
120: * -25C 11 1100 1110 0x3ce
121: * -55C 11 1001 0010 0x392
122: *
123: * LM75 temperature word:
124: *
125: * MSB Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 X X X X X X X
126: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
127: *
128: *
129: * LM75A temperature word:
130: *
131: * MSB Bit9 Bit8 Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 X X X X X
132: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
133: *
134: *
135: * LM77 temperature word:
136: *
137: * Sign Sign Sign Sign MSB Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 Status bits
138: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
139: */
140:
141: int lmtemp_temp_read(struct lmtemp_softc *, uint8_t, int *);
142: void lmtemp_refresh_sensor_data(void *);
143:
144: int
145: lmtemp_match(struct device *parent, void *match, void *aux)
146: {
147: struct i2c_attach_args *ia = aux;
148:
149: if (strcmp(ia->ia_name, "lm75") == 0 ||
150: strcmp(ia->ia_name, "lm77") == 0 ||
151: strcmp(ia->ia_name, "ds1775") == 0 ||
152: strcmp(ia->ia_name, "lm75a") == 0)
153: return (1);
154: return (0);
155: }
156:
157: void
158: lmtemp_attach(struct device *parent, struct device *self, void *aux)
159: {
160: struct lmtemp_softc *sc = (struct lmtemp_softc *)self;
161: struct i2c_attach_args *ia = aux;
162: u_int8_t cmd, data;
163:
164: sc->sc_tag = ia->ia_tag;
165: sc->sc_addr = ia->ia_addr;
166:
167: printf(": %s", ia->ia_name);
168:
169: /* If in SHUTDOWN mode, wake it up */
170: iic_acquire_bus(sc->sc_tag, 0);
171: cmd = LM75_REG_CONFIG;
172: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
173: sc->sc_addr, &cmd, 1, &data, 1, 0)) {
174: iic_release_bus(sc->sc_tag, 0);
175: return;
176: }
177: if (data & LM75_CONFIG_SHUTDOWN) {
178: data &= ~LM75_CONFIG_SHUTDOWN;
179: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
180: sc->sc_addr, &cmd, 1, &data, 1, 0)) {
181: printf(", cannot wake up\n");
182: iic_release_bus(sc->sc_tag, 0);
183: return;
184: }
185: printf(", woken up");
186: }
187: iic_release_bus(sc->sc_tag, 0);
188:
189: sc->sc_model = LM_MODEL_LM75;
190: sc->sc_bits = 9;
191: if (strcmp(ia->ia_name, "lm77") == 0) {
192: sc->sc_model = LM_MODEL_LM77;
193: sc->sc_bits = 13;
194: } else if (strcmp(ia->ia_name, "ds1775") == 0) {
195: sc->sc_model = LM_MODEL_DS1775;
196: sc->sc_bits = 9;
197: //sc->sc_bits = DS1755_CONFIG_RESOLUTION(data);
198: } else if (strcmp(ia->ia_name, "lm75a") == 0) {
199: /* For simplicity's sake, treat the LM75A as an LM75 */
200: sc->sc_model = LM_MODEL_LM75A;
201: sc->sc_bits = 9;
202: }
203:
204: printf("\n");
205:
206: /* Initialize sensor data */
207: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
208: sizeof(sc->sc_sensordev.xname));
209: sc->sc_sensor.type = SENSOR_TEMP;
210:
211: /* Hook into the hw.sensors sysctl */
212: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
213: sensordev_install(&sc->sc_sensordev);
214:
215:
216: sensor_task_register(sc, lmtemp_refresh_sensor_data, LM_POLLTIME);
217: }
218:
219: int
220: lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, int *valp)
221: {
222: u_int8_t cmd, buf[2];
223: int error;
224:
225: cmd = which;
226: error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
227: sc->sc_addr, &cmd, 1, buf, 2, 0);
228: if (error)
229: return (error);
230:
231: /* Some chips return transient 0's.. we try next time */
232: if (buf[0] == 0x00 && buf[1] == 0x00)
233: return (1);
234:
235: /* convert to half-degrees C */
236: *valp = ((buf[0] << 8) | buf[1]) / (1 << (16 - sc->sc_bits));
237: return (0);
238: }
239:
240: void
241: lmtemp_refresh_sensor_data(void *aux)
242: {
243: struct lmtemp_softc *sc = aux;
244: int val;
245: int error;
246:
247: error = lmtemp_temp_read(sc, LM75_REG_TEMP, &val);
248: if (error) {
249: #if 0
250: printf("%s: unable to read temperature, error = %d\n",
251: sc->sc_dev.dv_xname, error);
252: #endif
253: sc->sc_sensor.flags |= SENSOR_FINVALID;
254: return;
255: }
256:
257: sc->sc_sensor.value = val * 500000 + 273150000;
258: sc->sc_sensor.flags &= ~SENSOR_FINVALID;
259: }
CVSweb