xref: /openbsd/sys/dev/i2c/ad741x.c (revision afa48fb4)
1*afa48fb4Sderaadt /*	$OpenBSD: ad741x.c,v 1.1 2005/11/15 18:28:05 deraadt Exp $	*/
2*afa48fb4Sderaadt 
3*afa48fb4Sderaadt /*
4*afa48fb4Sderaadt  * Copyright (c) 2005 Theo de Raadt
5*afa48fb4Sderaadt  *
6*afa48fb4Sderaadt  * Permission to use, copy, modify, and distribute this software for any
7*afa48fb4Sderaadt  * purpose with or without fee is hereby granted, provided that the above
8*afa48fb4Sderaadt  * copyright notice and this permission notice appear in all copies.
9*afa48fb4Sderaadt  *
10*afa48fb4Sderaadt  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*afa48fb4Sderaadt  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*afa48fb4Sderaadt  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*afa48fb4Sderaadt  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*afa48fb4Sderaadt  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*afa48fb4Sderaadt  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*afa48fb4Sderaadt  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*afa48fb4Sderaadt  */
18*afa48fb4Sderaadt 
19*afa48fb4Sderaadt #include <sys/param.h>
20*afa48fb4Sderaadt #include <sys/systm.h>
21*afa48fb4Sderaadt #include <sys/device.h>
22*afa48fb4Sderaadt #include <sys/sensors.h>
23*afa48fb4Sderaadt 
24*afa48fb4Sderaadt #include <dev/i2c/i2cvar.h>
25*afa48fb4Sderaadt 
26*afa48fb4Sderaadt /* AD741x registers */
27*afa48fb4Sderaadt #define AD741X_TEMP	0x00
28*afa48fb4Sderaadt #define AD741X_CONFIG	0x01
29*afa48fb4Sderaadt #define AD741X_THYST	0x02
30*afa48fb4Sderaadt #define AD741X_TOTI	0x03
31*afa48fb4Sderaadt #define AD741X_ADC	0x04
32*afa48fb4Sderaadt #define AD741X_CONFIG2	0x05
33*afa48fb4Sderaadt 
34*afa48fb4Sderaadt #define AD741X_CONFMASK	0xe0
35*afa48fb4Sderaadt 
36*afa48fb4Sderaadt /* Sensors */
37*afa48fb4Sderaadt #define ADC_TEMP		0
38*afa48fb4Sderaadt #define ADC_ADC0		1
39*afa48fb4Sderaadt #define ADC_ADC1		2
40*afa48fb4Sderaadt #define ADC_ADC2		3
41*afa48fb4Sderaadt #define ADC_ADC3		4
42*afa48fb4Sderaadt #define ADC_NUM_SENSORS		5
43*afa48fb4Sderaadt 
44*afa48fb4Sderaadt struct adc_softc {
45*afa48fb4Sderaadt 	struct device sc_dev;
46*afa48fb4Sderaadt 	i2c_tag_t sc_tag;
47*afa48fb4Sderaadt 	i2c_addr_t sc_addr;
48*afa48fb4Sderaadt 
49*afa48fb4Sderaadt 	struct sensor sc_sensor[ADC_NUM_SENSORS];
50*afa48fb4Sderaadt };
51*afa48fb4Sderaadt 
52*afa48fb4Sderaadt int	adc_match(struct device *, void *, void *);
53*afa48fb4Sderaadt void	adc_attach(struct device *, struct device *, void *);
54*afa48fb4Sderaadt int	adc_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
55*afa48fb4Sderaadt void	adc_refresh(void *);
56*afa48fb4Sderaadt 
57*afa48fb4Sderaadt struct cfattach adc_ca = {
58*afa48fb4Sderaadt 	sizeof(struct adc_softc), adc_match, adc_attach
59*afa48fb4Sderaadt };
60*afa48fb4Sderaadt 
61*afa48fb4Sderaadt struct cfdriver adc_cd = {
62*afa48fb4Sderaadt 	NULL, "adc", DV_DULL
63*afa48fb4Sderaadt };
64*afa48fb4Sderaadt 
65*afa48fb4Sderaadt int
66*afa48fb4Sderaadt adc_match(struct device *parent, void *match, void *aux)
67*afa48fb4Sderaadt {
68*afa48fb4Sderaadt 	struct i2c_attach_args *ia = aux;
69*afa48fb4Sderaadt 
70*afa48fb4Sderaadt 	if (ia->ia_compat) {
71*afa48fb4Sderaadt 		if (strcmp(ia->ia_compat, "ad7417") == 0)
72*afa48fb4Sderaadt 			return (1);
73*afa48fb4Sderaadt 		return (0);
74*afa48fb4Sderaadt 	}
75*afa48fb4Sderaadt 	return (1);
76*afa48fb4Sderaadt }
77*afa48fb4Sderaadt 
78*afa48fb4Sderaadt void
79*afa48fb4Sderaadt adc_attach(struct device *parent, struct device *self, void *aux)
80*afa48fb4Sderaadt {
81*afa48fb4Sderaadt 	struct adc_softc *sc = (struct adc_softc *)self;
82*afa48fb4Sderaadt 	struct i2c_attach_args *ia = aux;
83*afa48fb4Sderaadt 	u_int8_t cmd, data;
84*afa48fb4Sderaadt 	int i;
85*afa48fb4Sderaadt 
86*afa48fb4Sderaadt 	sc->sc_tag = ia->ia_tag;
87*afa48fb4Sderaadt 	sc->sc_addr = ia->ia_addr;
88*afa48fb4Sderaadt 
89*afa48fb4Sderaadt 	cmd = AD741X_CONFIG;
90*afa48fb4Sderaadt 	data = 0;
91*afa48fb4Sderaadt 	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
92*afa48fb4Sderaadt 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
93*afa48fb4Sderaadt 		printf(", config reset failed\n");
94*afa48fb4Sderaadt 		return;
95*afa48fb4Sderaadt 	}
96*afa48fb4Sderaadt 
97*afa48fb4Sderaadt 	cmd = AD741X_CONFIG2;
98*afa48fb4Sderaadt 	data = 0;
99*afa48fb4Sderaadt 	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
100*afa48fb4Sderaadt 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
101*afa48fb4Sderaadt 		printf(", config2 reset failed\n");
102*afa48fb4Sderaadt 		return;
103*afa48fb4Sderaadt 	}
104*afa48fb4Sderaadt 
105*afa48fb4Sderaadt 	/* Initialize sensor data. */
106*afa48fb4Sderaadt 	for (i = 0; i < ADC_NUM_SENSORS; i++)
107*afa48fb4Sderaadt 		strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname,
108*afa48fb4Sderaadt 		    sizeof(sc->sc_sensor[i].device));
109*afa48fb4Sderaadt 
110*afa48fb4Sderaadt 	sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
111*afa48fb4Sderaadt 	strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
112*afa48fb4Sderaadt 	    sizeof(sc->sc_sensor[ADC_TEMP].desc));
113*afa48fb4Sderaadt 
114*afa48fb4Sderaadt 	sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
115*afa48fb4Sderaadt 	strlcpy(sc->sc_sensor[ADC_ADC0].desc, "adc0",
116*afa48fb4Sderaadt 	    sizeof(sc->sc_sensor[ADC_ADC0].desc));
117*afa48fb4Sderaadt 	sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
118*afa48fb4Sderaadt 	strlcpy(sc->sc_sensor[ADC_ADC1].desc, "adc1",
119*afa48fb4Sderaadt 	    sizeof(sc->sc_sensor[ADC_ADC1].desc));
120*afa48fb4Sderaadt 	sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
121*afa48fb4Sderaadt 	strlcpy(sc->sc_sensor[ADC_ADC2].desc, "adc2",
122*afa48fb4Sderaadt 	    sizeof(sc->sc_sensor[ADC_ADC2].desc));
123*afa48fb4Sderaadt 	sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
124*afa48fb4Sderaadt 	strlcpy(sc->sc_sensor[ADC_ADC3].desc, "adc3",
125*afa48fb4Sderaadt 	    sizeof(sc->sc_sensor[ADC_ADC3].desc));
126*afa48fb4Sderaadt 
127*afa48fb4Sderaadt 	if (sensor_task_register(sc, adc_refresh, 5)) {
128*afa48fb4Sderaadt 		printf(", unable to register update task\n");
129*afa48fb4Sderaadt 		return;
130*afa48fb4Sderaadt 	}
131*afa48fb4Sderaadt 
132*afa48fb4Sderaadt 	for (i = 0; i < ADC_NUM_SENSORS; i++)
133*afa48fb4Sderaadt 		SENSOR_ADD(&sc->sc_sensor[i]);
134*afa48fb4Sderaadt 
135*afa48fb4Sderaadt 	printf("\n");
136*afa48fb4Sderaadt }
137*afa48fb4Sderaadt 
138*afa48fb4Sderaadt void	adc_readport(struct adc_softc *, u_int8_t, u_int8_t, int);
139*afa48fb4Sderaadt 
140*afa48fb4Sderaadt void
141*afa48fb4Sderaadt adc_refresh(void *arg)
142*afa48fb4Sderaadt {
143*afa48fb4Sderaadt 	struct adc_softc *sc = arg;
144*afa48fb4Sderaadt 	u_int8_t cmd, data[2], reg;
145*afa48fb4Sderaadt 	int i;
146*afa48fb4Sderaadt 
147*afa48fb4Sderaadt 	iic_acquire_bus(sc->sc_tag, 0);
148*afa48fb4Sderaadt 
149*afa48fb4Sderaadt 	cmd = AD741X_CONFIG;
150*afa48fb4Sderaadt 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
151*afa48fb4Sderaadt 	    sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
152*afa48fb4Sderaadt 		goto fail;
153*afa48fb4Sderaadt 	reg = (reg & AD741X_CONFMASK) | (0 << 5);
154*afa48fb4Sderaadt 	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
155*afa48fb4Sderaadt 	    sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
156*afa48fb4Sderaadt 		goto fail;
157*afa48fb4Sderaadt 	cmd = AD741X_TEMP;
158*afa48fb4Sderaadt 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
159*afa48fb4Sderaadt 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
160*afa48fb4Sderaadt 		goto fail;
161*afa48fb4Sderaadt 	sc->sc_sensor[ADC_TEMP].value = 273150000 +
162*afa48fb4Sderaadt 	    ((data[0] << 8 | data[1]) >> 6) * 250000;
163*afa48fb4Sderaadt 
164*afa48fb4Sderaadt 	for (i = 0; i < 4; i++) {
165*afa48fb4Sderaadt 		reg = (reg & AD741X_CONFMASK) | (i << 5);
166*afa48fb4Sderaadt 		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
167*afa48fb4Sderaadt 		    sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
168*afa48fb4Sderaadt 			goto fail;
169*afa48fb4Sderaadt 		cmd = AD741X_ADC;
170*afa48fb4Sderaadt 		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
171*afa48fb4Sderaadt 		    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
172*afa48fb4Sderaadt 			goto fail;
173*afa48fb4Sderaadt 		sc->sc_sensor[ADC_ADC0 + i].value =
174*afa48fb4Sderaadt 		    (data[0] << 8 | data[1]) >> 6;
175*afa48fb4Sderaadt 	}
176*afa48fb4Sderaadt 
177*afa48fb4Sderaadt fail:
178*afa48fb4Sderaadt 	iic_release_bus(sc->sc_tag, 0);
179*afa48fb4Sderaadt }
180