Annotation of sys/dev/i2c/adm1024.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: adm1024.c,v 1.14 2007/06/24 05:34:35 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Theo de Raadt
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/device.h>
22: #include <sys/sensors.h>
23:
24: #include <dev/i2c/i2cvar.h>
25:
26: /* ADM 1024 registers */
27: #define ADM1024_V2_5 0x20
28: #define ADM1024_Vccp 0x21
29: #define ADM1024_Vcc 0x22
30: #define ADM1024_V5 0x23
31: #define ADM1024_V12 0x24
32: #define ADM1024_Vccp2 0x25
33: #define ADM1024_EXT_TEMP 0x26
34: #define ADM1024_INT_TEMP 0x27
35: #define ADM1024_FAN1 0x28
36: #define ADM1024_FAN2 0x29
37: #define ADM1024_STATUS2 0x42
38: #define ADM1024_FANC 0x47
39: #define ADM1024_STATUS2_EXT 0x40
40: #define ADM1024_COMPANY 0x3e /* contains 0x41 */
41: #define ADM1024_STEPPING 0x3f /* contains 0x2? */
42: #define ADM1024_CONFIG1 0x40
43: #define ADM1024_CONFIG1_START 0x01
44: #define ADM1024_CONFIG1_INTCLR 0x08
45:
46: /* Sensors */
47: #define ADMLC_INT 0
48: #define ADMLC_EXT 1
49: #define ADMLC_V2_5 2
50: #define ADMLC_Vccp 3
51: #define ADMLC_Vcc 4
52: #define ADMLC_V5 5
53: #define ADMLC_V12 6
54: #define ADMLC_Vccp2 7
55: #define ADMLC_FAN1 8
56: #define ADMLC_FAN2 9
57: #define ADMLC_NUM_SENSORS 10
58:
59: struct admlc_softc {
60: struct device sc_dev;
61: i2c_tag_t sc_tag;
62: i2c_addr_t sc_addr;
63:
64: struct ksensor sc_sensor[ADMLC_NUM_SENSORS];
65: struct ksensordev sc_sensordev;
66: int sc_fan1mul;
67: int sc_fan2mul;
68: };
69:
70: int admlc_match(struct device *, void *, void *);
71: void admlc_attach(struct device *, struct device *, void *);
72: void admlc_refresh(void *);
73:
74: struct cfattach admlc_ca = {
75: sizeof(struct admlc_softc), admlc_match, admlc_attach
76: };
77:
78: struct cfdriver admlc_cd = {
79: NULL, "admlc", DV_DULL
80: };
81:
82: int
83: admlc_match(struct device *parent, void *match, void *aux)
84: {
85: struct i2c_attach_args *ia = aux;
86:
87: if (strcmp(ia->ia_name, "adm1024") == 0)
88: return (1);
89: return (0);
90: }
91:
92: void
93: admlc_attach(struct device *parent, struct device *self, void *aux)
94: {
95: struct admlc_softc *sc = (struct admlc_softc *)self;
96: struct i2c_attach_args *ia = aux;
97: u_int8_t cmd, data, data2;
98: int i;
99:
100: sc->sc_tag = ia->ia_tag;
101: sc->sc_addr = ia->ia_addr;
102:
103: iic_acquire_bus(sc->sc_tag, 0);
104: cmd = ADM1024_CONFIG1;
105: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
106: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
107: iic_release_bus(sc->sc_tag, 0);
108: printf(": cannot get control register\n");
109: return;
110: }
111: data2 = data | ADM1024_CONFIG1_START;
112: data2 = data2 & ~ADM1024_CONFIG1_INTCLR;
113: if (data != data2) {
114: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
115: sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
116: iic_release_bus(sc->sc_tag, 0);
117: printf(": cannot set control register\n");
118: return;
119: }
120: }
121:
122: cmd = ADM1024_FANC;
123: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
124: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
125: printf(", unable to read fan setting\n");
126: return;
127: }
128: sc->sc_fan1mul = (1 << (data >> 4) & 0x3);
129: sc->sc_fan2mul = (1 << (data >> 6) & 0x3);
130:
131: iic_release_bus(sc->sc_tag, 0);
132:
133: /* Initialize sensor data. */
134: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
135: sizeof(sc->sc_sensordev.xname));
136:
137: sc->sc_sensor[ADMLC_INT].type = SENSOR_TEMP;
138: strlcpy(sc->sc_sensor[ADMLC_INT].desc, "Internal",
139: sizeof(sc->sc_sensor[ADMLC_INT].desc));
140:
141: sc->sc_sensor[ADMLC_EXT].type = SENSOR_TEMP;
142: strlcpy(sc->sc_sensor[ADMLC_EXT].desc, "External",
143: sizeof(sc->sc_sensor[ADMLC_EXT].desc));
144:
145: sc->sc_sensor[ADMLC_V2_5].type = SENSOR_VOLTS_DC;
146: strlcpy(sc->sc_sensor[ADMLC_V2_5].desc, "2.5 V",
147: sizeof(sc->sc_sensor[ADMLC_V2_5].desc));
148:
149: sc->sc_sensor[ADMLC_Vccp].type = SENSOR_VOLTS_DC;
150: strlcpy(sc->sc_sensor[ADMLC_Vccp].desc, "Vccp",
151: sizeof(sc->sc_sensor[ADMLC_Vccp].desc));
152:
153: sc->sc_sensor[ADMLC_Vcc].type = SENSOR_VOLTS_DC;
154: strlcpy(sc->sc_sensor[ADMLC_Vcc].desc, "Vcc",
155: sizeof(sc->sc_sensor[ADMLC_Vcc].desc));
156:
157: sc->sc_sensor[ADMLC_V5].type = SENSOR_VOLTS_DC;
158: strlcpy(sc->sc_sensor[ADMLC_V5].desc, "5 V",
159: sizeof(sc->sc_sensor[ADMLC_V5].desc));
160:
161: sc->sc_sensor[ADMLC_V12].type = SENSOR_VOLTS_DC;
162: strlcpy(sc->sc_sensor[ADMLC_V12].desc, "12 V",
163: sizeof(sc->sc_sensor[ADMLC_V12].desc));
164:
165: sc->sc_sensor[ADMLC_Vccp2].type = SENSOR_VOLTS_DC;
166: strlcpy(sc->sc_sensor[ADMLC_Vccp2].desc, "Vccp2",
167: sizeof(sc->sc_sensor[ADMLC_Vccp2].desc));
168:
169: sc->sc_sensor[ADMLC_FAN1].type = SENSOR_FANRPM;
170:
171: sc->sc_sensor[ADMLC_FAN2].type = SENSOR_FANRPM;
172:
173:
174: if (sensor_task_register(sc, admlc_refresh, 5) == NULL) {
175: printf(", unable to register update task\n");
176: return;
177: }
178:
179: for (i = 0; i < ADMLC_NUM_SENSORS; i++)
180: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
181: sensordev_install(&sc->sc_sensordev);
182:
183: printf("\n");
184: }
185:
186: static void
187: fanval(struct ksensor *sens, int mul, u_int8_t data)
188: {
189: int tmp = data * mul;
190:
191: if (tmp == 0)
192: sens->flags |= SENSOR_FINVALID;
193: else
194: sens->value = 1350000 / tmp;
195: }
196:
197: void
198: admlc_refresh(void *arg)
199: {
200: struct admlc_softc *sc = arg;
201: u_int8_t cmd, data;
202: int8_t sdata;
203:
204: iic_acquire_bus(sc->sc_tag, 0);
205:
206: cmd = ADM1024_INT_TEMP;
207: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
208: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
209: sc->sc_sensor[ADMLC_INT].value = 273150000 + 1000000 * sdata;
210:
211: cmd = ADM1024_EXT_TEMP;
212: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
213: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
214: sc->sc_sensor[ADMLC_EXT].value = 273150000 + 1000000 * sdata;
215:
216: cmd = ADM1024_STATUS2;
217: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
218: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
219: if (data & ADM1024_STATUS2_EXT)
220: sc->sc_sensor[ADMLC_EXT].flags |= SENSOR_FINVALID;
221: else
222: sc->sc_sensor[ADMLC_EXT].flags &= ~SENSOR_FINVALID;
223: }
224:
225: cmd = ADM1024_V2_5;
226: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
227: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
228: sc->sc_sensor[ADMLC_V2_5].value = 2500000 * data / 192;
229:
230: cmd = ADM1024_Vccp;
231: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
232: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
233: sc->sc_sensor[ADMLC_Vcc].value = 2249000 * data / 192;
234:
235: cmd = ADM1024_Vcc;
236: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
237: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
238: sc->sc_sensor[ADMLC_Vcc].value = 3300000 * data / 192;
239:
240: cmd = ADM1024_V5;
241: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
242: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
243: sc->sc_sensor[ADMLC_V5].value = 5000000 * data / 192;
244:
245: cmd = ADM1024_V12;
246: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
247: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
248: sc->sc_sensor[ADMLC_V12].value = 12000000 * data / 192;
249:
250: cmd = ADM1024_Vccp2;
251: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
252: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
253: sc->sc_sensor[ADMLC_Vccp2].value = 2700000 * data / 192;
254:
255: cmd = ADM1024_FAN1;
256: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
257: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
258: fanval(&sc->sc_sensor[ADMLC_FAN1], sc->sc_fan1mul, data);
259:
260: cmd = ADM1024_FAN2;
261: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
262: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
263: fanval(&sc->sc_sensor[ADMLC_FAN2], sc->sc_fan2mul, data);
264: iic_release_bus(sc->sc_tag, 0);
265: }
CVSweb