Annotation of sys/dev/i2c/ad741x.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ad741x.c,v 1.12 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: /* AD741x registers */
27: #define AD741X_TEMP 0x00
28: #define AD741X_CONFIG 0x01
29: #define AD741X_THYST 0x02
30: #define AD741X_TOTI 0x03
31: #define AD741X_ADC 0x04
32: #define AD741X_CONFIG2 0x05
33:
34: #define AD741X_CONFMASK 0xe0
35:
36: /* Sensors */
37: #define ADC_TEMP 0
38: #define ADC_ADC0 1
39: #define ADC_ADC1 2
40: #define ADC_ADC2 3
41: #define ADC_ADC3 4
42: #define ADC_MAX_SENSORS 5
43:
44: struct adc_softc {
45: struct device sc_dev;
46: i2c_tag_t sc_tag;
47: i2c_addr_t sc_addr;
48: int sc_chip;
49: u_int8_t sc_config;
50:
51: struct ksensor sc_sensor[ADC_MAX_SENSORS];
52: struct ksensordev sc_sensordev;
53: };
54:
55: int adc_match(struct device *, void *, void *);
56: void adc_attach(struct device *, struct device *, void *);
57: int adc_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
58: void adc_refresh(void *);
59:
60: struct cfattach adc_ca = {
61: sizeof(struct adc_softc), adc_match, adc_attach
62: };
63:
64: struct cfdriver adc_cd = {
65: NULL, "adc", DV_DULL
66: };
67:
68: int
69: adc_match(struct device *parent, void *match, void *aux)
70: {
71: struct i2c_attach_args *ia = aux;
72:
73: if (strcmp(ia->ia_name, "ad7417") == 0 ||
74: strcmp(ia->ia_name, "ad7418") == 0)
75: return (1);
76: return (0);
77: }
78:
79: void
80: adc_attach(struct device *parent, struct device *self, void *aux)
81: {
82: struct adc_softc *sc = (struct adc_softc *)self;
83: struct i2c_attach_args *ia = aux;
84: u_int8_t cmd, data;
85: int nsens = 0, i;
86:
87: sc->sc_tag = ia->ia_tag;
88: sc->sc_addr = ia->ia_addr;
89:
90: printf(": %s", ia->ia_name);
91:
92: sc->sc_chip = 0;
93: if (strcmp(ia->ia_name, "ad7417") == 0)
94: sc->sc_chip = 7417;
95: if (strcmp(ia->ia_name, "ad7418") == 0)
96: sc->sc_chip = 7418;
97:
98: if (sc->sc_chip != 0) {
99: cmd = AD741X_CONFIG2;
100: data = 0;
101: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
102: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
103: printf(", config2 reset failed\n");
104: return;
105: }
106: }
107:
108: cmd = AD741X_CONFIG;
109: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
110: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
111: printf(", config reset failed\n");
112: return;
113: }
114: data &= 0xfe;
115: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
116: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
117: printf(", config reset failed\n");
118: return;
119: }
120: sc->sc_config = data;
121:
122: /* Initialize sensor data. */
123: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
124: sizeof(sc->sc_sensordev.xname));
125:
126: sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
127: strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
128: sizeof(sc->sc_sensor[ADC_TEMP].desc));
129: nsens = 1;
130:
131: if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
132: sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
133: nsens++;
134: }
135: if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
136: sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
137: sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
138: sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
139: nsens += 3;
140: }
141:
142: if (sensor_task_register(sc, adc_refresh, 5) == NULL) {
143: printf(", unable to register update task\n");
144: return;
145: }
146:
147: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]);
148: if (sc->sc_chip == 7417 || sc->sc_chip == 7418)
149: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]);
150: if (sc->sc_chip == 7417)
151: for (i = 2; i < nsens; i++)
152: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
153: sensordev_install(&sc->sc_sensordev);
154:
155: printf("\n");
156: }
157:
158: void
159: adc_refresh(void *arg)
160: {
161: struct adc_softc *sc = arg;
162: u_int8_t cmd, data[2], reg;
163: int i;
164:
165: iic_acquire_bus(sc->sc_tag, 0);
166:
167: reg = (sc->sc_config & AD741X_CONFMASK) | (0 << 5);
168: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
169: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
170: goto done;
171: delay(1000);
172: cmd = AD741X_TEMP;
173: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
174: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
175: goto done;
176: sc->sc_sensor[ADC_TEMP].value = 273150000 +
177: ((data[0] << 8 | data[1]) >> 6) * 250000;
178:
179: if (sc->sc_chip == 0)
180: goto done;
181:
182: if (sc->sc_chip == 7418) {
183: reg = (reg & AD741X_CONFMASK) | (4 << 5);
184: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
185: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
186: goto done;
187: delay(1000);
188: cmd = AD741X_ADC;
189: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
190: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
191: goto done;
192: sc->sc_sensor[ADC_ADC0].value =
193: (data[0] << 8 | data[1]) >> 6;
194: goto done;
195: }
196:
197: for (i = 0; i < 4; i++) {
198: reg = (reg & AD741X_CONFMASK) | (i << 5);
199: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
200: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
201: goto done;
202: delay(1000);
203: cmd = AD741X_ADC;
204: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
205: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
206: goto done;
207: sc->sc_sensor[ADC_ADC0 + i].value =
208: (data[0] << 8 | data[1]) >> 6;
209: }
210:
211: done:
212: iic_release_bus(sc->sc_tag, 0);
213: }
CVSweb