1 /* $OpenBSD: adt7460.c,v 1.22 2022/04/06 18:59:28 naddy 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 /* ADT7460 registers */
27 #define ADT7460_2_5V 0x20
28 #define ADT7460_VCCP 0x21
29 #define ADT7460_VCC 0x22
30 #define ADT7460_V5 0x23
31 #define ADT7460_V12 0x24
32 #define ADT7460_VTR 0x99
33 #define ADT7460_VBAT 0x9a
34 #define ADT7460_REM1_TEMP 0x25
35 #define ADT7460_LOCAL_TEMP 0x26
36 #define ADT7460_REM2_TEMP 0x27
37 #define ADT7460_TACH1L 0x28
38 #define ADT7460_TACH1H 0x29
39 #define ADT7460_TACH2L 0x2a
40 #define ADT7460_TACH2H 0x2b
41 #define ADT7460_TACH3L 0x2c
42 #define ADT7460_TACH3H 0x2d
43 #define ADT7460_TACH4L 0x2e
44 #define ADT7460_TACH4H 0x2f
45 #define ADT7460_TACH5L 0xa9
46 #define ADT7460_TACH5H 0xaa
47 #define ADT7460_TACH6L 0xab
48 #define ADT7460_TACH6H 0xac
49 #define ADT7460_REVISION 0x3f
50 #define ADT7460_CONFIG 0x40
51 #define ADT7460_CONFIG_Vcc 0x80
52
53 /* Sensors */
54 #define ADT_2_5V 0
55 #define ADT_VCCP 1
56 #define ADT_VCC 2
57 #define ADT_V5 3
58 #define ADT_V12 4
59 #define ADT_VTR 5
60 #define ADT_VBAT 6
61 #define ADT_REM1_TEMP 7
62 #define ADT_LOCAL_TEMP 8
63 #define ADT_REM2_TEMP 9
64 #define ADT_TACH1 10
65 #define ADT_TACH2 11
66 #define ADT_TACH3 12
67 #define ADT_TACH4 13
68 #define ADT_TACH5 14
69 #define ADT_TACH6 15
70 #define ADT_NUM_SENSORS 16
71
72 struct adt_chip {
73 const char *name;
74 short ratio[7];
75 int type;
76 short vcc;
77 } adt_chips[] = {
78 /* register 0x20 0x21 0x22 0x23 0x24 0xa8 0xaa type */
79 /* 2.5v vccp vcc 5v 12v vtr vbat */
80
81 { "adt7460", { 2500, 0, 3300, 0, 0, 0, 0 }, 7460, 5000 },
82 { "adt7467", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 7467, 5000 },
83 { "adt7475", { 0, 2250, 3300, 0, 0, 0, 0 }, 7475, 0 },
84 { "adt7476", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 7476, 0 },
85 { "adm1027", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 1027, 5000 },
86 { "lm85", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 7467, 0 },
87 { "emc6d100", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 6100, 0 },
88 { "emc6w201", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 6201, 0 },
89 { "lm96000", { 2500, 2250, 3300, 5000, 12000, 0, 0 }, 96000, 0 },
90 { "sch5017", { 5000, 2250, 3300, 5000, 12000, 0, 0 }, 5017, 0 },
91 { "sch5027", { 5000, 2250, 3300, 5000, 12000, 3300, 3300 }, 5027, 0 }
92 };
93
94 struct {
95 char sensor;
96 u_int8_t cmd;
97 u_short index;
98 } worklist[] = {
99 { ADT_2_5V, ADT7460_2_5V, 32768 + 0 },
100 { ADT_VCCP, ADT7460_VCCP, 32768 + 1 },
101 { ADT_VCC, ADT7460_VCC, 32768 + 2 },
102 { ADT_V5, ADT7460_V5, 32768 + 3 },
103 { ADT_V12, ADT7460_V12, 32768 + 4 },
104 { ADT_VTR, ADT7460_VTR, 32768 + 5 },
105 { ADT_VBAT, ADT7460_VBAT, 32768 + 6 },
106 { ADT_REM1_TEMP, ADT7460_REM1_TEMP },
107 { ADT_LOCAL_TEMP, ADT7460_LOCAL_TEMP },
108 { ADT_REM2_TEMP, ADT7460_REM2_TEMP },
109 { ADT_TACH1, ADT7460_TACH1L },
110 { ADT_TACH2, ADT7460_TACH2L },
111 { ADT_TACH3, ADT7460_TACH3L },
112 { ADT_TACH4, ADT7460_TACH4L },
113 { ADT_TACH5, ADT7460_TACH5L },
114 { ADT_TACH6, ADT7460_TACH6L },
115 };
116
117 struct adt_softc {
118 struct device sc_dev;
119 i2c_tag_t sc_tag;
120 i2c_addr_t sc_addr;
121 u_int8_t sc_conf;
122 struct adt_chip *chip;
123
124 struct ksensor sc_sensor[ADT_NUM_SENSORS];
125 struct ksensordev sc_sensordev;
126 };
127
128 int adt_match(struct device *, void *, void *);
129 void adt_attach(struct device *, struct device *, void *);
130
131 void adt_refresh(void *);
132
133 const struct cfattach adt_ca = {
134 sizeof(struct adt_softc), adt_match, adt_attach
135 };
136
137 struct cfdriver adt_cd = {
138 NULL, "adt", DV_DULL
139 };
140
141 int
adt_match(struct device * parent,void * match,void * aux)142 adt_match(struct device *parent, void *match, void *aux)
143 {
144 struct i2c_attach_args *ia = aux;
145 int i;
146
147 for (i = 0; i < sizeof(adt_chips) / sizeof(adt_chips[0]); i++)
148 if (strcmp(ia->ia_name, adt_chips[i].name) == 0)
149 return (1);
150 return (0);
151 }
152
153 void
adt_attach(struct device * parent,struct device * self,void * aux)154 adt_attach(struct device *parent, struct device *self, void *aux)
155 {
156 struct adt_softc *sc = (struct adt_softc *)self;
157 struct i2c_attach_args *ia = aux;
158 u_int8_t cmd, rev, data;
159 int i;
160
161 sc->sc_tag = ia->ia_tag;
162 sc->sc_addr = ia->ia_addr;
163
164 iic_acquire_bus(sc->sc_tag, 0);
165
166 for (i = 0; i < sizeof(adt_chips) / sizeof(adt_chips[0]); i++) {
167 if (strcmp(ia->ia_name, adt_chips[i].name) == 0) {
168 sc->chip = &adt_chips[i];
169 break;
170 }
171 }
172
173 cmd = ADT7460_REVISION;
174 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
175 sc->sc_addr, &cmd, sizeof cmd, &rev, sizeof rev, 0)) {
176 iic_release_bus(sc->sc_tag, 0);
177 printf(": cannot read REV register\n");
178 return;
179 }
180
181 cmd = ADT7460_CONFIG;
182 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
183 sc->sc_addr, &cmd, sizeof cmd, &sc->sc_conf, sizeof sc->sc_conf, 0)) {
184 iic_release_bus(sc->sc_tag, 0);
185 printf(": cannot read config register\n");
186 return;
187 }
188
189 if (sc->chip->type == 7460) {
190 data = 1;
191 cmd = ADT7460_CONFIG;
192 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
193 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
194 iic_release_bus(sc->sc_tag, 0);
195 printf(": cannot set control register\n");
196 return;
197 }
198 }
199
200 iic_release_bus(sc->sc_tag, 0);
201
202 printf(": %s rev 0x%02x", ia->ia_name, rev);
203
204 /* Initialize sensor data. */
205 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
206 sizeof(sc->sc_sensordev.xname));
207
208 sc->sc_sensor[ADT_2_5V].type = SENSOR_VOLTS_DC;
209 strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+2.5Vin",
210 sizeof(sc->sc_sensor[ADT_2_5V].desc));
211
212 if (sc->chip->type == 5017)
213 strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+5VTR",
214 sizeof(sc->sc_sensor[ADT_2_5V].desc));
215 if (sc->chip->type == 5027)
216 strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+5V",
217 sizeof(sc->sc_sensor[ADT_2_5V].desc));
218
219 sc->sc_sensor[ADT_VCCP].type = SENSOR_VOLTS_DC;
220 strlcpy(sc->sc_sensor[ADT_VCCP].desc, "Vccp",
221 sizeof(sc->sc_sensor[ADT_VCCP].desc));
222
223 sc->sc_sensor[ADT_VCC].type = SENSOR_VOLTS_DC;
224 strlcpy(sc->sc_sensor[ADT_VCC].desc, "Vcc",
225 sizeof(sc->sc_sensor[ADT_VCC].desc));
226
227 sc->sc_sensor[ADT_V5].type = SENSOR_VOLTS_DC;
228 strlcpy(sc->sc_sensor[ADT_V5].desc, "+5V",
229 sizeof(sc->sc_sensor[ADT_V5].desc));
230
231 sc->sc_sensor[ADT_V12].type = SENSOR_VOLTS_DC;
232 strlcpy(sc->sc_sensor[ADT_V12].desc, "+12V",
233 sizeof(sc->sc_sensor[ADT_V12].desc));
234
235 sc->sc_sensor[ADT_VTR].type = SENSOR_VOLTS_DC;
236 strlcpy(sc->sc_sensor[ADT_VTR].desc, "+Vtr",
237 sizeof(sc->sc_sensor[ADT_VTR].desc));
238
239 sc->sc_sensor[ADT_VBAT].type = SENSOR_VOLTS_DC;
240 strlcpy(sc->sc_sensor[ADT_VBAT].desc, "+Vbat",
241 sizeof(sc->sc_sensor[ADT_VBAT].desc));
242
243 sc->sc_sensor[ADT_REM1_TEMP].type = SENSOR_TEMP;
244 strlcpy(sc->sc_sensor[ADT_REM1_TEMP].desc, "Remote",
245 sizeof(sc->sc_sensor[ADT_REM1_TEMP].desc));
246
247 sc->sc_sensor[ADT_LOCAL_TEMP].type = SENSOR_TEMP;
248 strlcpy(sc->sc_sensor[ADT_LOCAL_TEMP].desc, "Internal",
249 sizeof(sc->sc_sensor[ADT_LOCAL_TEMP].desc));
250
251 sc->sc_sensor[ADT_REM2_TEMP].type = SENSOR_TEMP;
252 strlcpy(sc->sc_sensor[ADT_REM2_TEMP].desc, "Remote",
253 sizeof(sc->sc_sensor[ADT_REM2_TEMP].desc));
254
255 sc->sc_sensor[ADT_TACH1].type = SENSOR_FANRPM;
256 sc->sc_sensor[ADT_TACH2].type = SENSOR_FANRPM;
257 sc->sc_sensor[ADT_TACH3].type = SENSOR_FANRPM;
258 sc->sc_sensor[ADT_TACH4].type = SENSOR_FANRPM;
259 sc->sc_sensor[ADT_TACH5].type = SENSOR_FANRPM;
260 sc->sc_sensor[ADT_TACH6].type = SENSOR_FANRPM;
261
262 if (sensor_task_register(sc, adt_refresh, 5) == NULL) {
263 printf(", unable to register update task\n");
264 return;
265 }
266
267 for (i = 0; i < ADT_NUM_SENSORS; i++) {
268 if (worklist[i].index >= 32768 &&
269 sc->chip->ratio[worklist[i].index - 32768] == 0)
270 continue;
271 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
272 }
273 sensordev_install(&sc->sc_sensordev);
274
275
276 printf("\n");
277 }
278
279 void
adt_refresh(void * arg)280 adt_refresh(void *arg)
281 {
282 struct adt_softc *sc = arg;
283 u_int8_t cmd, data, data2;
284 u_int16_t fan;
285 int i, ratio;
286
287 iic_acquire_bus(sc->sc_tag, 0);
288
289 for (i = 0; i < sizeof worklist / sizeof(worklist[0]); i++) {
290
291 if (worklist[i].index >= 32768) {
292 ratio = sc->chip->ratio[worklist[i].index - 32768];
293 if (ratio == 0) /* do not read a dead register */
294 continue;
295 }
296 cmd = worklist[i].cmd;
297 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
298 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
299 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
300 continue;
301 }
302
303 sc->sc_sensor[i].flags &= ~SENSOR_FINVALID;
304 switch (worklist[i].sensor) {
305 case ADT_VCC:
306 if (sc->chip->vcc && (sc->sc_conf & ADT7460_CONFIG_Vcc))
307 ratio = sc->chip->vcc;
308 /* FALLTHROUGH */
309 case ADT_2_5V:
310 case ADT_VCCP:
311 case ADT_V5:
312 case ADT_V12:
313 case ADT_VTR:
314 case ADT_VBAT:
315 sc->sc_sensor[i].value = ratio * 1000 * (u_int)data / 192;
316 break;
317 case ADT_LOCAL_TEMP:
318 case ADT_REM1_TEMP:
319 case ADT_REM2_TEMP:
320 if (data == 0x80)
321 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
322 else
323 sc->sc_sensor[i].value =
324 (int8_t)data * 1000000 + 273150000;
325 break;
326 case ADT_TACH1:
327 case ADT_TACH2:
328 case ADT_TACH3:
329 case ADT_TACH4:
330 cmd = worklist[i].cmd + 1; /* TACHnH follows TACHnL */
331 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
332 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
333 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
334 continue;
335 }
336
337 fan = data + (data2 << 8);
338 if (fan == 0 || fan == 0xffff)
339 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
340 else
341 sc->sc_sensor[i].value = (90000 * 60) / fan;
342 break;
343 case ADT_TACH5:
344 case ADT_TACH6:
345 if (sc->chip->type != 5027) {
346 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
347 break; /* only 5027 has these fans? */
348 }
349 cmd = worklist[i].cmd + 1; /* TACHnH follows TACHnL */
350 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
351 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
352 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
353 continue;
354 }
355
356 fan = data + (data2 << 8);
357 if (fan == 0 || fan == 0xffff)
358 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
359 else
360 sc->sc_sensor[i].value = fan * 60;
361 break;
362 default:
363 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
364 break;
365 }
366 }
367
368 iic_release_bus(sc->sc_tag, 0);
369 }
370