xref: /openbsd-src/sys/dev/i2c/adm1024.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
1 /*	$OpenBSD: adm1024.c,v 1.15 2022/04/06 18:59:28 naddy 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 const 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
admlc_match(struct device * parent,void * match,void * aux)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
admlc_attach(struct device * parent,struct device * self,void * aux)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
fanval(struct ksensor * sens,int mul,u_int8_t data)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
admlc_refresh(void * arg)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 }
266