Annotation of sys/dev/i2c/adm1026.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: adm1026.c,v 1.10 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 1026 registers */
27: #define ADM1026_TEMP 0x1f
28: #define ADM1026_STATUS 0x20
29: #define ADM1026_Vbat 0x26
30: #define ADM1026_Ain8 0x27
31: #define ADM1026_EXT1 0x28
32: #define ADM1026_EXT2 0x29
33: #define ADM1026_V3_3stby 0x2a
34: #define ADM1026_V3_3main 0x2b
35: #define ADM1026_V5 0x2c
36: #define ADM1026_Vccp 0x2d
37: #define ADM1026_V12 0x2e
38: #define ADM1026_Vminus12 0x2f
39: #define ADM1026_FAN0 0x38
40: #define ADM1026_FAN1 0x39
41: #define ADM1026_FAN2 0x3a
42: #define ADM1026_FAN3 0x3b
43: #define ADM1026_FAN4 0x3c
44: #define ADM1026_FAN5 0x3d
45: #define ADM1026_FAN6 0x3e
46: #define ADM1026_FAN7 0x3f
47: #define ADM1026_EXT1_OFF 0x6e
48: #define ADM1026_EXT2_OFF 0x6f
49: #define ADM1026_FAN0123DIV 0x02
50: #define ADM1026_FAN4567DIV 0x03
51: #define ADM1026_CONTROL 0x00
52: #define ADM1026_CONTROL_START 0x01
53: #define ADM1026_CONTROL_INTCLR 0x04
54:
55: /* Sensors */
56: #define ADMCTS_TEMP 0
57: #define ADMCTS_EXT1 1
58: #define ADMCTS_EXT2 2
59: #define ADMCTS_Vbat 3
60: #define ADMCTS_V3_3stby 4
61: #define ADMCTS_V3_3main 5
62: #define ADMCTS_V5 6
63: #define ADMCTS_Vccp 7
64: #define ADMCTS_V12 8
65: #define ADMCTS_Vminus12 9
66: #define ADMCTS_FAN0 10
67: #define ADMCTS_FAN1 11
68: #define ADMCTS_FAN2 12
69: #define ADMCTS_FAN3 13
70: #define ADMCTS_FAN4 14
71: #define ADMCTS_FAN5 15
72: #define ADMCTS_FAN6 16
73: #define ADMCTS_FAN7 17
74: #define ADMCTS_NUM_SENSORS 18
75:
76: struct admcts_softc {
77: struct device sc_dev;
78: i2c_tag_t sc_tag;
79: i2c_addr_t sc_addr;
80:
81: struct ksensor sc_sensor[ADMCTS_NUM_SENSORS];
82: struct ksensordev sc_sensordev;
83: int sc_fanmul[8];
84: };
85:
86: int admcts_match(struct device *, void *, void *);
87: void admcts_attach(struct device *, struct device *, void *);
88: void admcts_refresh(void *);
89:
90: struct cfattach admcts_ca = {
91: sizeof(struct admcts_softc), admcts_match, admcts_attach
92: };
93:
94: struct cfdriver admcts_cd = {
95: NULL, "admcts", DV_DULL
96: };
97:
98: int
99: admcts_match(struct device *parent, void *match, void *aux)
100: {
101: struct i2c_attach_args *ia = aux;
102:
103: if (strcmp(ia->ia_name, "adm1026") == 0)
104: return (1);
105: return (0);
106: }
107:
108: void
109: admcts_attach(struct device *parent, struct device *self, void *aux)
110: {
111: struct admcts_softc *sc = (struct admcts_softc *)self;
112: struct i2c_attach_args *ia = aux;
113: u_int8_t cmd, data, data2;
114: int i;
115:
116: sc->sc_tag = ia->ia_tag;
117: sc->sc_addr = ia->ia_addr;
118:
119: iic_acquire_bus(sc->sc_tag, 0);
120: cmd = ADM1026_CONTROL;
121: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
122: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
123: iic_release_bus(sc->sc_tag, 0);
124: printf(": cannot get control register\n");
125: return;
126: }
127: data2 = data | ADM1026_CONTROL_START;
128: data2 = data2 & ~ADM1026_CONTROL_INTCLR;
129: if (data != data2) {
130: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
131: sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
132: iic_release_bus(sc->sc_tag, 0);
133: printf(": cannot set control register\n");
134: return;
135: }
136: }
137:
138: cmd = ADM1026_FAN0123DIV;
139: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
140: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
141: iic_release_bus(sc->sc_tag, 0);
142: printf(": cannot get fan0123div register\n");
143: return;
144: }
145: sc->sc_fanmul[0] = (1 << (data >> 0) & 0x3);
146: sc->sc_fanmul[1] = (1 << (data >> 2) & 0x3);
147: sc->sc_fanmul[2] = (1 << (data >> 4) & 0x3);
148: sc->sc_fanmul[3] = (1 << (data >> 6) & 0x3);
149:
150: cmd = ADM1026_FAN4567DIV;
151: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
152: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
153: iic_release_bus(sc->sc_tag, 0);
154: printf(": cannot get fan0123div register\n");
155: return;
156: }
157: sc->sc_fanmul[4] = (1 << (data >> 0) & 0x3);
158: sc->sc_fanmul[5] = (1 << (data >> 2) & 0x3);
159: sc->sc_fanmul[6] = (1 << (data >> 4) & 0x3);
160: sc->sc_fanmul[7] = (1 << (data >> 6) & 0x3);
161:
162: iic_release_bus(sc->sc_tag, 0);
163:
164: /* Initialize sensor data. */
165: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
166: sizeof(sc->sc_sensordev.xname));
167:
168: sc->sc_sensor[ADMCTS_TEMP].type = SENSOR_TEMP;
169: strlcpy(sc->sc_sensor[ADMCTS_TEMP].desc, "Internal",
170: sizeof(sc->sc_sensor[ADMCTS_TEMP].desc));
171:
172: sc->sc_sensor[ADMCTS_Vbat].type = SENSOR_VOLTS_DC;
173: strlcpy(sc->sc_sensor[ADMCTS_Vbat].desc, "Vbat",
174: sizeof(sc->sc_sensor[ADMCTS_Vbat].desc));
175:
176: sc->sc_sensor[ADMCTS_EXT1].type = SENSOR_TEMP;
177: strlcpy(sc->sc_sensor[ADMCTS_EXT1].desc, "External",
178: sizeof(sc->sc_sensor[ADMCTS_EXT1].desc));
179:
180: sc->sc_sensor[ADMCTS_EXT2].type = SENSOR_TEMP;
181: strlcpy(sc->sc_sensor[ADMCTS_EXT2].desc, "External",
182: sizeof(sc->sc_sensor[ADMCTS_EXT2].desc));
183:
184: sc->sc_sensor[ADMCTS_V3_3stby].type = SENSOR_VOLTS_DC;
185: strlcpy(sc->sc_sensor[ADMCTS_V3_3stby].desc, "3.3 V standby",
186: sizeof(sc->sc_sensor[ADMCTS_V3_3stby].desc));
187:
188: sc->sc_sensor[ADMCTS_V3_3main].type = SENSOR_VOLTS_DC;
189: strlcpy(sc->sc_sensor[ADMCTS_V3_3main].desc, "3.3 V main",
190: sizeof(sc->sc_sensor[ADMCTS_V3_3main].desc));
191:
192: sc->sc_sensor[ADMCTS_V5].type = SENSOR_VOLTS_DC;
193: strlcpy(sc->sc_sensor[ADMCTS_V5].desc, "5 V",
194: sizeof(sc->sc_sensor[ADMCTS_V5].desc));
195:
196: sc->sc_sensor[ADMCTS_Vccp].type = SENSOR_VOLTS_DC;
197: strlcpy(sc->sc_sensor[ADMCTS_Vccp].desc, "Vccp",
198: sizeof(sc->sc_sensor[ADMCTS_Vccp].desc));
199:
200: sc->sc_sensor[ADMCTS_V12].type = SENSOR_VOLTS_DC;
201: strlcpy(sc->sc_sensor[ADMCTS_V12].desc, "12 V",
202: sizeof(sc->sc_sensor[ADMCTS_V12].desc));
203:
204: sc->sc_sensor[ADMCTS_Vminus12].type = SENSOR_VOLTS_DC;
205: strlcpy(sc->sc_sensor[ADMCTS_Vminus12].desc, "-12 V",
206: sizeof(sc->sc_sensor[ADMCTS_Vminus12].desc));
207:
208: sc->sc_sensor[ADMCTS_FAN1].type = SENSOR_FANRPM;
209: sc->sc_sensor[ADMCTS_FAN2].type = SENSOR_FANRPM;
210: sc->sc_sensor[ADMCTS_FAN3].type = SENSOR_FANRPM;
211: sc->sc_sensor[ADMCTS_FAN4].type = SENSOR_FANRPM;
212: sc->sc_sensor[ADMCTS_FAN5].type = SENSOR_FANRPM;
213: sc->sc_sensor[ADMCTS_FAN6].type = SENSOR_FANRPM;
214: sc->sc_sensor[ADMCTS_FAN7].type = SENSOR_FANRPM;
215:
216: if (sensor_task_register(sc, admcts_refresh, 5) == NULL) {
217: printf(", unable to register update task\n");
218: return;
219: }
220:
221: for (i = 0; i < ADMCTS_NUM_SENSORS; i++)
222: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
223: sensordev_install(&sc->sc_sensordev);
224:
225: printf("\n");
226: }
227:
228: static void
229: fanval(struct ksensor *sens, int mul, u_int8_t data)
230: {
231: int tmp = data * mul;
232:
233: if (tmp == 0)
234: sens->flags |= SENSOR_FINVALID;
235: else
236: sens->value = 1350000 / tmp;
237: }
238:
239: void
240: admcts_refresh(void *arg)
241: {
242: struct admcts_softc *sc = arg;
243: u_int8_t cmd, data;
244: int8_t sdata;
245:
246: iic_acquire_bus(sc->sc_tag, 0);
247:
248: cmd = ADM1026_TEMP;
249: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
250: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
251: sc->sc_sensor[ADMCTS_TEMP].value = 273150000 + 1000000 * sdata;
252:
253: cmd = ADM1026_EXT1;
254: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
255: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
256: sc->sc_sensor[ADMCTS_EXT1].value = 273150000 + 1000000 * sdata;
257:
258: cmd = ADM1026_EXT2;
259: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
260: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
261: sc->sc_sensor[ADMCTS_EXT2].value = 273150000 + 1000000 * sdata;
262:
263: cmd = ADM1026_Vbat;
264: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
265: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
266: sc->sc_sensor[ADMCTS_Vbat].value = 3000000 * data / 192;
267:
268: cmd = ADM1026_V3_3stby;
269: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
270: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
271: sc->sc_sensor[ADMCTS_V3_3stby].value = 3300000 * data / 192;
272:
273: cmd = ADM1026_V3_3main;
274: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
275: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
276: sc->sc_sensor[ADMCTS_V3_3main].value = 3300000 * data / 192;
277:
278: cmd = ADM1026_V5;
279: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
280: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
281: sc->sc_sensor[ADMCTS_V5].value = 5500000 * data / 192;
282:
283: cmd = ADM1026_Vccp;
284: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
285: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
286: sc->sc_sensor[ADMCTS_Vccp].value = 2250000 * data / 192;
287:
288: cmd = ADM1026_V12;
289: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
290: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
291: sc->sc_sensor[ADMCTS_V12].value = 12000000 * data / 192;
292:
293: cmd = ADM1026_Vminus12;
294: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
295: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
296: sc->sc_sensor[ADMCTS_Vminus12].value = -2125000 * data / 192;
297:
298: cmd = ADM1026_FAN0;
299: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
300: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
301: fanval(&sc->sc_sensor[ADMCTS_FAN0], sc->sc_fanmul[0], data);
302:
303: cmd = ADM1026_FAN1;
304: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
305: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
306: fanval(&sc->sc_sensor[ADMCTS_FAN1], sc->sc_fanmul[1], data);
307:
308: cmd = ADM1026_FAN2;
309: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
310: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
311: fanval(&sc->sc_sensor[ADMCTS_FAN2], sc->sc_fanmul[2], data);
312:
313: cmd = ADM1026_FAN3;
314: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
315: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
316: fanval(&sc->sc_sensor[ADMCTS_FAN3], sc->sc_fanmul[3], data);
317:
318: cmd = ADM1026_FAN4;
319: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
320: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
321: fanval(&sc->sc_sensor[ADMCTS_FAN4], sc->sc_fanmul[4], data);
322:
323: cmd = ADM1026_FAN5;
324: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
325: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
326: fanval(&sc->sc_sensor[ADMCTS_FAN5], sc->sc_fanmul[5], data);
327:
328: cmd = ADM1026_FAN6;
329: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
330: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
331: fanval(&sc->sc_sensor[ADMCTS_FAN6], sc->sc_fanmul[6], data);
332:
333: cmd = ADM1026_FAN7;
334: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
335: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
336: fanval(&sc->sc_sensor[ADMCTS_FAN7], sc->sc_fanmul[7], data);
337:
338: iic_release_bus(sc->sc_tag, 0);
339: }
CVSweb