xref: /openbsd-src/sys/dev/i2c/lm87.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: lm87.c,v 1.19 2007/06/24 05:34:35 dlg Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Mark Kettenis
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 /* LM87 registers */
27 #define LM87_2_5V	0x20
28 #define LM87_VCCP1	0x21
29 #define LM87_VCC	0x22
30 #define LM87_5V		0x23
31 #define LM87_12V	0x24
32 #define LM87_VCCP2	0x25
33 #define LM87_EXT_TEMP	0x26
34 #define LM87_INT_TEMP	0x27
35 #define LM87_FAN1	0x28
36 #define LM87_FAN2	0x29
37 #define LM87_REVISION	0x3f
38 #define LM87_CONFIG1	0x40
39 #define  LM87_CONFIG1_START	0x01
40 #define  LM87_CONFIG1_INTCLR	0x08
41 #define LM87_CHANNEL	0x16
42 #define  LM87_CHANNEL_AIN1	0x01
43 #define  LM87_CHANNEL_AIN2	0x02
44 #define LM87_FANDIV	0x47
45 
46 /* Sensors */
47 #define LMENV_2_5V		0
48 #define LMENV_VCCP1		1
49 #define LMENV_VCC		2
50 #define LMENV_5V		3
51 #define LMENV_12V		4
52 #define LMENV_VCCP2		5
53 #define LMENV_EXT_TEMP		6
54 #define LMENV_INT_TEMP		7
55 #define LMENV_FAN1		8
56 #define LMENV_FAN2		9
57 #define LMENV_NUM_SENSORS	10
58 
59 struct lmenv_softc {
60 	struct device sc_dev;
61 	i2c_tag_t sc_tag;
62 	i2c_addr_t sc_addr;
63 
64 	struct ksensor sc_sensor[LMENV_NUM_SENSORS];
65 	struct ksensordev sc_sensordev;
66 	int	sc_fan1_div, sc_fan2_div;
67 	int	sc_family;
68 };
69 
70 int	lmenv_match(struct device *, void *, void *);
71 void	lmenv_attach(struct device *, struct device *, void *);
72 
73 void	lmenv_refresh(void *);
74 
75 struct cfattach lmenv_ca = {
76 	sizeof(struct lmenv_softc), lmenv_match, lmenv_attach
77 };
78 
79 struct cfdriver lmenv_cd = {
80 	NULL, "lmenv", DV_DULL
81 };
82 
83 int
84 lmenv_match(struct device *parent, void *match, void *aux)
85 {
86 	struct i2c_attach_args *ia = aux;
87 
88 	if (strcmp(ia->ia_name, "lm87") == 0 ||
89 	    strcmp(ia->ia_name, "lm87cimt") == 0 ||
90 	    strcmp(ia->ia_name, "adm9240") == 0 ||
91 	    strcmp(ia->ia_name, "lm81") == 0 ||
92 	    strcmp(ia->ia_name, "ds1780") == 0)
93 		return (1);
94 	return (0);
95 }
96 
97 void
98 lmenv_attach(struct device *parent, struct device *self, void *aux)
99 {
100 	struct lmenv_softc *sc = (struct lmenv_softc *)self;
101 	struct i2c_attach_args *ia = aux;
102 	u_int8_t cmd, data, data2, channel;
103 	int i;
104 
105 	sc->sc_tag = ia->ia_tag;
106 	sc->sc_addr = ia->ia_addr;
107 
108 	sc->sc_family = 87;
109 	if (strcmp(ia->ia_name, "lm81") == 0 ||
110 	    strcmp(ia->ia_name, "adm9240") == 0 ||
111 	    strcmp(ia->ia_name, "ds1780") == 0)
112 		sc->sc_family = 81;
113 
114 	iic_acquire_bus(sc->sc_tag, 0);
115 
116 	cmd = LM87_REVISION;
117 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
118 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
119 		iic_release_bus(sc->sc_tag, 0);
120 		printf(": cannot read ID register\n");
121 		return;
122 	}
123 	printf(": %s rev %x", ia->ia_name, data);
124 
125 	cmd = LM87_FANDIV;
126 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
127 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
128 		iic_release_bus(sc->sc_tag, 0);
129 		printf(", cannot read Fan Divisor register\n");
130 		return;
131 	}
132 	sc->sc_fan1_div = 1 << ((data >> 4) & 0x03);
133 	sc->sc_fan2_div = 1 << ((data >> 6) & 0x03);
134 
135 	if (sc->sc_family == 87) {
136 		cmd = LM87_CHANNEL;
137 		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
138 		    sc->sc_addr, &cmd, sizeof cmd, &channel,
139 		    sizeof channel, 0)) {
140 			iic_release_bus(sc->sc_tag, 0);
141 			printf(", cannot read Channel register\n");
142 			return;
143 		}
144 	}
145 
146 	cmd = LM87_CONFIG1;
147 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
148 	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
149 		iic_release_bus(sc->sc_tag, 0);
150 		printf(", cannot read Configuration Register 1\n");
151 		return;
152 	}
153 
154 	/*
155 	 * if chip is not running, try to start it.
156 	 * if it is stalled doing an interrupt, unstall it
157 	 */
158 	data2 = (data | LM87_CONFIG1_START);
159 	data2 = data2 & ~LM87_CONFIG1_INTCLR;
160 
161 	if (data != data2) {
162 		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
163 		    sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
164 			iic_release_bus(sc->sc_tag, 0);
165 			printf(", cannot write Configuration Register 1\n");
166 			return;
167 		}
168 		printf(", starting scan");
169 	}
170 	iic_release_bus(sc->sc_tag, 0);
171 
172 	/* Initialize sensor data. */
173 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
174 	    sizeof(sc->sc_sensordev.xname));
175 
176 	sc->sc_sensor[LMENV_2_5V].type = SENSOR_VOLTS_DC;
177 	strlcpy(sc->sc_sensor[LMENV_2_5V].desc, "+2.5Vin",
178 	    sizeof(sc->sc_sensor[LMENV_2_5V].desc));
179 
180 	sc->sc_sensor[LMENV_VCCP1].type = SENSOR_VOLTS_DC;
181 	strlcpy(sc->sc_sensor[LMENV_VCCP1].desc, "Vccp",
182 	    sizeof(sc->sc_sensor[LMENV_VCCP1].desc));
183 
184 	sc->sc_sensor[LMENV_VCC].type = SENSOR_VOLTS_DC;
185 	strlcpy(sc->sc_sensor[LMENV_VCC].desc, "+Vcc",
186 	    sizeof(sc->sc_sensor[LMENV_VCC].desc));
187 
188 	sc->sc_sensor[LMENV_5V].type = SENSOR_VOLTS_DC;
189 	strlcpy(sc->sc_sensor[LMENV_5V].desc, "+5Vin/Vcc",
190 	    sizeof(sc->sc_sensor[LMENV_5V].desc));
191 
192 	sc->sc_sensor[LMENV_12V].type = SENSOR_VOLTS_DC;
193 	strlcpy(sc->sc_sensor[LMENV_12V].desc, "+12Vin",
194 	    sizeof(sc->sc_sensor[LMENV_12V].desc));
195 
196 	sc->sc_sensor[LMENV_VCCP2].type = SENSOR_VOLTS_DC;
197 	strlcpy(sc->sc_sensor[LMENV_VCCP2].desc, "Vccp",
198 	    sizeof(sc->sc_sensor[LMENV_VCCP2].desc));
199 
200 	sc->sc_sensor[LMENV_EXT_TEMP].type = SENSOR_TEMP;
201 	strlcpy(sc->sc_sensor[LMENV_EXT_TEMP].desc, "External",
202 	    sizeof(sc->sc_sensor[LMENV_EXT_TEMP].desc));
203 	if (sc->sc_family == 81)
204 		sc->sc_sensor[LMENV_EXT_TEMP].flags |= SENSOR_FINVALID;
205 
206 	sc->sc_sensor[LMENV_INT_TEMP].type = SENSOR_TEMP;
207 	strlcpy(sc->sc_sensor[LMENV_INT_TEMP].desc, "Internal",
208 	    sizeof(sc->sc_sensor[LMENV_INT_TEMP].desc));
209 
210 	if (channel & LM87_CHANNEL_AIN1) {
211 		sc->sc_sensor[LMENV_FAN1].type = SENSOR_VOLTS_DC;
212 		strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "AIN1",
213 		    sizeof(sc->sc_sensor[LMENV_FAN1].desc));
214 	} else {
215 		sc->sc_sensor[LMENV_FAN1].type = SENSOR_FANRPM;
216 	}
217 
218 	if (channel & LM87_CHANNEL_AIN2) {
219 		sc->sc_sensor[LMENV_FAN2].type = SENSOR_VOLTS_DC;
220 		strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "AIN2",
221 		    sizeof(sc->sc_sensor[LMENV_FAN2].desc));
222 	} else {
223 		sc->sc_sensor[LMENV_FAN2].type = SENSOR_FANRPM;
224 	}
225 
226 	if (sensor_task_register(sc, lmenv_refresh, 5) == NULL) {
227 		printf(", unable to register update task\n");
228 		return;
229 	}
230 
231 	for (i = 0; i < LMENV_NUM_SENSORS; i++)
232 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
233 	sensordev_install(&sc->sc_sensordev);
234 
235 	printf("\n");
236 }
237 
238 void
239 lmenv_refresh(void *arg)
240 {
241 	struct lmenv_softc *sc = arg;
242 	u_int8_t cmd, data;
243 	u_int tmp;
244 	int sensor;
245 
246 	iic_acquire_bus(sc->sc_tag, 0);
247 
248 	for (sensor = 0; sensor < LMENV_NUM_SENSORS; sensor++) {
249 		cmd = LM87_2_5V + sensor;
250 		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
251 		    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
252 			sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
253 			continue;
254 		}
255 
256 		sc->sc_sensor[sensor].flags &= ~SENSOR_FINVALID;
257 		switch (sensor) {
258 		case LMENV_2_5V:
259 			sc->sc_sensor[sensor].value = 2500000 * data / 192;
260 			break;
261 		case LMENV_5V:
262 			sc->sc_sensor[sensor].value = 5000000 * data / 192;
263 			break;
264 		case LMENV_12V:
265 			sc->sc_sensor[sensor].value = 12000000 * data / 192;
266 			break;
267 		case LMENV_VCCP1:
268 		case LMENV_VCCP2:
269 			sc->sc_sensor[sensor].value = 2700000 * data / 192;
270 			break;
271 		case LMENV_VCC:
272 			sc->sc_sensor[sensor].value = 3300000 * data / 192;
273 			break;
274 		case LMENV_EXT_TEMP:
275 			if (sc->sc_family == 81) {
276 				sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
277 				break;		/* missing on LM81 */
278 			}
279 			/* FALLTHROUGH */
280 		case LMENV_INT_TEMP:
281 			if (data == 0x80)
282 				sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
283 			else
284 				sc->sc_sensor[sensor].value =
285 				    (int8_t)data * 1000000 + 273150000;
286 			break;
287 		case LMENV_FAN1:
288 			if (sc->sc_sensor[sensor].type == SENSOR_VOLTS_DC) {
289 				sc->sc_sensor[sensor].value =
290 				    1870000 * data / 192;
291 				break;
292 			}
293 			tmp = data * sc->sc_fan1_div;
294 			if (tmp == 0)
295 				sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
296 			else
297 				sc->sc_sensor[sensor].value = 1350000 / tmp;
298 			break;
299 		case LMENV_FAN2:
300 			if (sc->sc_sensor[sensor].type == SENSOR_VOLTS_DC) {
301 				sc->sc_sensor[sensor].value =
302 				    1870000 * data / 192;
303 				break;
304 			}
305 			tmp = data * sc->sc_fan2_div;
306 			if (tmp == 0)
307 				sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
308 			else
309 				sc->sc_sensor[sensor].value = 1350000 / tmp;
310 			break;
311 		default:
312 			sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
313 			break;
314 		}
315 	}
316 
317 	iic_release_bus(sc->sc_tag, 0);
318 }
319