1 /* $OpenBSD: adt7460.c,v 1.21 2007/12/12 16:56:59 deraadt 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 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 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 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 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