Annotation of sys/dev/ic/lm78.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: lm78.c,v 1.20 2007/06/25 22:50:18 cnst Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005, 2006 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/kernel.h>
! 23: #include <sys/queue.h>
! 24: #include <sys/sensors.h>
! 25: #include <machine/bus.h>
! 26:
! 27: #include <dev/ic/lm78var.h>
! 28:
! 29: #if defined(LMDEBUG)
! 30: #define DPRINTF(x) do { printf x; } while (0)
! 31: #else
! 32: #define DPRINTF(x)
! 33: #endif
! 34:
! 35: /*
! 36: * LM78-compatible chips can typically measure voltages up to 4.096 V.
! 37: * To measure higher voltages the input is attenuated with (external)
! 38: * resistors. Negative voltages are measured using inverting op amps
! 39: * and resistors. So we have to convert the sensor values back to
! 40: * real voltages by applying the appropriate resistor factor.
! 41: */
! 42: #define RFACT_NONE 10000
! 43: #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
! 44: #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
! 45:
! 46: struct cfdriver lm_cd = {
! 47: NULL, "lm", DV_DULL
! 48: };
! 49:
! 50: int lm_match(struct lm_softc *);
! 51: int wb_match(struct lm_softc *);
! 52: int def_match(struct lm_softc *);
! 53:
! 54: void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
! 55: void lm_refresh(void *);
! 56:
! 57: void lm_refresh_sensor_data(struct lm_softc *);
! 58: void lm_refresh_volt(struct lm_softc *, int);
! 59: void lm_refresh_temp(struct lm_softc *, int);
! 60: void lm_refresh_fanrpm(struct lm_softc *, int);
! 61:
! 62: void wb_refresh_sensor_data(struct lm_softc *);
! 63: void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
! 64: void wb_refresh_nvolt(struct lm_softc *, int);
! 65: void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
! 66: void wb_refresh_temp(struct lm_softc *, int);
! 67: void wb_refresh_fanrpm(struct lm_softc *, int);
! 68: void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
! 69:
! 70: void as_refresh_temp(struct lm_softc *, int);
! 71:
! 72: struct lm_chip {
! 73: int (*chip_match)(struct lm_softc *);
! 74: };
! 75:
! 76: struct lm_chip lm_chips[] = {
! 77: { wb_match },
! 78: { lm_match },
! 79: { def_match } /* Must be last */
! 80: };
! 81:
! 82: struct lm_sensor lm78_sensors[] = {
! 83: /* Voltage */
! 84: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 85: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 86: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 87: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
! 88: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
! 89: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
! 90: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
! 91:
! 92: /* Temperature */
! 93: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 94:
! 95: /* Fans */
! 96: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
! 97: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
! 98: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
! 99:
! 100: { NULL }
! 101: };
! 102:
! 103: struct lm_sensor w83627hf_sensors[] = {
! 104: /* Voltage */
! 105: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 106: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 107: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 108: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 109: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 110: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 111: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 112: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
! 113: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
! 114:
! 115: /* Temperature */
! 116: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 117: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 118: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 119:
! 120: /* Fans */
! 121: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 122: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 123: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 124:
! 125: { NULL }
! 126: };
! 127:
! 128: /*
! 129: * The W83627EHF can measure voltages up to 2.048 V instead of the
! 130: * traditional 4.096 V. For measuring positive voltages, this can be
! 131: * accounted for by halving the resistor factor. Negative voltages
! 132: * need special treatment, also because the reference voltage is 2.048 V
! 133: * instead of the traditional 3.6 V.
! 134: */
! 135: struct lm_sensor w83627ehf_sensors[] = {
! 136: /* Voltage */
! 137: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
! 138: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
! 139: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
! 140: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
! 141: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
! 142: { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
! 143: { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
! 144: { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
! 145: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
! 146: { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
! 147:
! 148: /* Temperature */
! 149: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 150: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 151: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 152:
! 153: /* Fans */
! 154: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 155: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 156: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 157:
! 158: { NULL }
! 159: };
! 160:
! 161: /*
! 162: * w83627dhg is almost identical to w83627ehf, except that
! 163: * it has 9 instead of 10 voltage sensors
! 164: */
! 165: struct lm_sensor w83627dhg_sensors[] = {
! 166: /* Voltage */
! 167: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
! 168: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
! 169: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
! 170: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
! 171: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
! 172: { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
! 173: { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
! 174: { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
! 175: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
! 176:
! 177: /* Temperature */
! 178: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 179: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 180: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 181:
! 182: /* Fans */
! 183: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 184: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 185: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 186:
! 187: { NULL }
! 188: };
! 189:
! 190: struct lm_sensor w83637hf_sensors[] = {
! 191: /* Voltage */
! 192: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
! 193: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
! 194: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 195: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
! 196: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
! 197: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
! 198: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
! 199:
! 200: /* Temperature */
! 201: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 202: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 203: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 204:
! 205: /* Fans */
! 206: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 207: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 208: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 209:
! 210: { NULL }
! 211: };
! 212:
! 213: struct lm_sensor w83697hf_sensors[] = {
! 214: /* Voltage */
! 215: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 216: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 217: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 218: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 219: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 220: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 221: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
! 222: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
! 223:
! 224: /* Temperature */
! 225: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 226: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 227:
! 228: /* Fans */
! 229: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 230: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 231:
! 232: { NULL }
! 233: };
! 234:
! 235: /*
! 236: * The datasheet doesn't mention the (internal) resistors used for the
! 237: * +5V, but using the values from the W83782D datasheets seems to
! 238: * provide sensible results.
! 239: */
! 240: struct lm_sensor w83781d_sensors[] = {
! 241: /* Voltage */
! 242: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 243: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 244: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 245: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 246: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 247: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
! 248: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
! 249:
! 250: /* Temperature */
! 251: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 252: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 253: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 254:
! 255: /* Fans */
! 256: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
! 257: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
! 258: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
! 259:
! 260: { NULL }
! 261: };
! 262:
! 263: struct lm_sensor w83782d_sensors[] = {
! 264: /* Voltage */
! 265: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 266: { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 267: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 268: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 269: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 270: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 271: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 272: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
! 273: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
! 274:
! 275: /* Temperature */
! 276: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 277: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 278: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
! 279:
! 280: /* Fans */
! 281: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 282: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 283: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 284:
! 285: { NULL }
! 286: };
! 287:
! 288: struct lm_sensor w83783s_sensors[] = {
! 289: /* Voltage */
! 290: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 291: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 292: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 293: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 294: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 295: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 296:
! 297: /* Temperature */
! 298: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 299: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
! 300:
! 301: /* Fans */
! 302: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 303: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 304: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 305:
! 306: { NULL }
! 307: };
! 308:
! 309: struct lm_sensor w83791d_sensors[] = {
! 310: /* Voltage */
! 311: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 },
! 312: { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 },
! 313: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 },
! 314: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 315: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 316: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 317: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 318: { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
! 319: { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
! 320: { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
! 321:
! 322: /* Temperature */
! 323: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 324: { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
! 325: { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
! 326:
! 327: /* Fans */
! 328: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
! 329: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
! 330: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
! 331: { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
! 332: { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
! 333:
! 334: { NULL }
! 335: };
! 336:
! 337: struct lm_sensor w83792d_sensors[] = {
! 338: /* Voltage */
! 339: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 340: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 341: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 342: { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
! 343: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 344: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 345: { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
! 346: { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
! 347: { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
! 348:
! 349: /* Temperature */
! 350: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 351: { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
! 352: { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
! 353:
! 354: /* Fans */
! 355: { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
! 356: { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
! 357: { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
! 358: { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
! 359: { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
! 360: { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
! 361: { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
! 362:
! 363: { NULL }
! 364: };
! 365:
! 366: struct lm_sensor as99127f_sensors[] = {
! 367: /* Voltage */
! 368: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
! 369: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
! 370: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
! 371: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
! 372: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
! 373: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
! 374: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
! 375:
! 376: /* Temperature */
! 377: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
! 378: { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
! 379: { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
! 380:
! 381: /* Fans */
! 382: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
! 383: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
! 384: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
! 385:
! 386: { NULL }
! 387: };
! 388:
! 389: void
! 390: lm_attach(struct lm_softc *sc)
! 391: {
! 392: u_int i, config;
! 393:
! 394: for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
! 395: if (lm_chips[i].chip_match(sc))
! 396: break;
! 397:
! 398: /* No point in doing anything if we don't have any sensors. */
! 399: if (sc->numsensors == 0)
! 400: return;
! 401:
! 402: sc->sensortask = sensor_task_register(sc, lm_refresh, 5);
! 403: if (sc->sensortask == NULL) {
! 404: printf("%s: unable to register update task\n",
! 405: sc->sc_dev.dv_xname);
! 406: return;
! 407: }
! 408:
! 409: /* Start the monitoring loop */
! 410: config = sc->lm_readreg(sc, LM_CONFIG);
! 411: sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
! 412:
! 413: /* Add sensors */
! 414: for (i = 0; i < sc->numsensors; ++i)
! 415: sensor_attach(&sc->sensordev, &sc->sensors[i]);
! 416: sensordev_install(&sc->sensordev);
! 417: }
! 418:
! 419: int
! 420: lm_detach(struct lm_softc *sc)
! 421: {
! 422: int i;
! 423:
! 424: /* Remove sensors */
! 425: sensordev_deinstall(&sc->sensordev);
! 426: for (i = 0; i < sc->numsensors; i++)
! 427: sensor_detach(&sc->sensordev, &sc->sensors[i]);
! 428:
! 429: if (sc->sensortask != NULL)
! 430: sensor_task_unregister(sc->sensortask);
! 431:
! 432: return 0;
! 433: }
! 434:
! 435: int
! 436: lm_match(struct lm_softc *sc)
! 437: {
! 438: int chipid;
! 439:
! 440: /* See if we have an LM78 or LM79. */
! 441: chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
! 442: switch(chipid) {
! 443: case LM_CHIPID_LM78:
! 444: printf(": LM78\n");
! 445: break;
! 446: case LM_CHIPID_LM78J:
! 447: printf(": LM78J\n");
! 448: break;
! 449: case LM_CHIPID_LM79:
! 450: printf(": LM79\n");
! 451: break;
! 452: case LM_CHIPID_LM81:
! 453: printf(": LM81\n");
! 454: break;
! 455: default:
! 456: return 0;
! 457: }
! 458:
! 459: lm_setup_sensors(sc, lm78_sensors);
! 460: sc->refresh_sensor_data = lm_refresh_sensor_data;
! 461: return 1;
! 462: }
! 463:
! 464: int
! 465: def_match(struct lm_softc *sc)
! 466: {
! 467: int chipid;
! 468:
! 469: chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
! 470: printf(": unknown chip (ID %d)\n", chipid);
! 471:
! 472: lm_setup_sensors(sc, lm78_sensors);
! 473: sc->refresh_sensor_data = lm_refresh_sensor_data;
! 474: return 1;
! 475: }
! 476:
! 477: int
! 478: wb_match(struct lm_softc *sc)
! 479: {
! 480: int banksel, vendid, devid;
! 481:
! 482: /* Read vendor ID */
! 483: banksel = sc->lm_readreg(sc, WB_BANKSEL);
! 484: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
! 485: vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
! 486: sc->lm_writereg(sc, WB_BANKSEL, 0);
! 487: vendid |= sc->lm_readreg(sc, WB_VENDID);
! 488: sc->lm_writereg(sc, WB_BANKSEL, banksel);
! 489: DPRINTF((" winbond vend id 0x%x\n", vendid));
! 490: if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
! 491: return 0;
! 492:
! 493: /* Read device/chip ID */
! 494: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
! 495: devid = sc->lm_readreg(sc, LM_CHIPID);
! 496: sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
! 497: sc->lm_writereg(sc, WB_BANKSEL, banksel);
! 498: DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
! 499: switch(sc->chipid) {
! 500: case WB_CHIPID_W83627HF:
! 501: printf(": W83627HF\n");
! 502: lm_setup_sensors(sc, w83627hf_sensors);
! 503: break;
! 504: case WB_CHIPID_W83627THF:
! 505: printf(": W83627THF\n");
! 506: lm_setup_sensors(sc, w83637hf_sensors);
! 507: break;
! 508: case WB_CHIPID_W83627EHF_A:
! 509: printf(": W83627EHF-A\n");
! 510: lm_setup_sensors(sc, w83627ehf_sensors);
! 511: break;
! 512: case WB_CHIPID_W83627EHF:
! 513: printf(": W83627EHF\n");
! 514: lm_setup_sensors(sc, w83627ehf_sensors);
! 515: break;
! 516: case WB_CHIPID_W83627DHG:
! 517: printf(": W83627DHG\n");
! 518: lm_setup_sensors(sc, w83627dhg_sensors);
! 519: break;
! 520: case WB_CHIPID_W83637HF:
! 521: printf(": W83637HF\n");
! 522: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
! 523: if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
! 524: sc->vrm9 = 1;
! 525: sc->lm_writereg(sc, WB_BANKSEL, banksel);
! 526: lm_setup_sensors(sc, w83637hf_sensors);
! 527: break;
! 528: case WB_CHIPID_W83697HF:
! 529: printf(": W83697HF\n");
! 530: lm_setup_sensors(sc, w83697hf_sensors);
! 531: break;
! 532: case WB_CHIPID_W83781D:
! 533: case WB_CHIPID_W83781D_2:
! 534: printf(": W83781D\n");
! 535: lm_setup_sensors(sc, w83781d_sensors);
! 536: break;
! 537: case WB_CHIPID_W83782D:
! 538: printf(": W83782D\n");
! 539: lm_setup_sensors(sc, w83782d_sensors);
! 540: break;
! 541: case WB_CHIPID_W83783S:
! 542: printf(": W83783S\n");
! 543: lm_setup_sensors(sc, w83783s_sensors);
! 544: break;
! 545: case WB_CHIPID_W83791D:
! 546: printf(": W83791D\n");
! 547: lm_setup_sensors(sc, w83791d_sensors);
! 548: break;
! 549: case WB_CHIPID_W83791SD:
! 550: printf(": W83791SD\n");
! 551: break;
! 552: case WB_CHIPID_W83792D:
! 553: if (devid >= 0x10 && devid <= 0x29)
! 554: printf(": W83792D rev %c\n", 'A' + devid - 0x10);
! 555: else
! 556: printf(": W83792D rev 0x%x\n", devid);
! 557: lm_setup_sensors(sc, w83792d_sensors);
! 558: break;
! 559: case WB_CHIPID_AS99127F:
! 560: if (vendid == WB_VENDID_ASUS) {
! 561: printf(": AS99127F\n");
! 562: lm_setup_sensors(sc, w83781d_sensors);
! 563: } else {
! 564: printf(": AS99127F rev 2\n");
! 565: lm_setup_sensors(sc, as99127f_sensors);
! 566: }
! 567: break;
! 568: default:
! 569: printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid);
! 570: /* Handle as a standard LM78. */
! 571: lm_setup_sensors(sc, lm78_sensors);
! 572: sc->refresh_sensor_data = lm_refresh_sensor_data;
! 573: return 1;
! 574: }
! 575:
! 576: sc->refresh_sensor_data = wb_refresh_sensor_data;
! 577: return 1;
! 578: }
! 579:
! 580: void
! 581: lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
! 582: {
! 583: int i;
! 584:
! 585: strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
! 586: sizeof(sc->sensordev.xname));
! 587:
! 588: for (i = 0; sensors[i].desc; i++) {
! 589: sc->sensors[i].type = sensors[i].type;
! 590: strlcpy(sc->sensors[i].desc, sensors[i].desc,
! 591: sizeof(sc->sensors[i].desc));
! 592: sc->numsensors++;
! 593: }
! 594: sc->lm_sensors = sensors;
! 595: }
! 596:
! 597: void
! 598: lm_refresh(void *arg)
! 599: {
! 600: struct lm_softc *sc = arg;
! 601:
! 602: sc->refresh_sensor_data(sc);
! 603: }
! 604:
! 605: void
! 606: lm_refresh_sensor_data(struct lm_softc *sc)
! 607: {
! 608: int i;
! 609:
! 610: for (i = 0; i < sc->numsensors; i++)
! 611: sc->lm_sensors[i].refresh(sc, i);
! 612: }
! 613:
! 614: void
! 615: lm_refresh_volt(struct lm_softc *sc, int n)
! 616: {
! 617: struct ksensor *sensor = &sc->sensors[n];
! 618: int data;
! 619:
! 620: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 621: sensor->value = (data << 4);
! 622: sensor->value *= sc->lm_sensors[n].rfact;
! 623: sensor->value /= 10;
! 624: }
! 625:
! 626: void
! 627: lm_refresh_temp(struct lm_softc *sc, int n)
! 628: {
! 629: struct ksensor *sensor = &sc->sensors[n];
! 630: int sdata;
! 631:
! 632: /*
! 633: * The data sheet suggests that the range of the temperature
! 634: * sensor is between -55 degC and +125 degC.
! 635: */
! 636: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 637: if (sdata > 0x7d && sdata < 0xc9) {
! 638: sensor->flags |= SENSOR_FINVALID;
! 639: sensor->value = 0;
! 640: } else {
! 641: if (sdata & 0x80)
! 642: sdata -= 0x100;
! 643: sensor->flags &= ~SENSOR_FINVALID;
! 644: sensor->value = sdata * 1000000 + 273150000;
! 645: }
! 646: }
! 647:
! 648: void
! 649: lm_refresh_fanrpm(struct lm_softc *sc, int n)
! 650: {
! 651: struct ksensor *sensor = &sc->sensors[n];
! 652: int data, divisor = 1;
! 653:
! 654: /*
! 655: * We might get more accurate fan readings by adjusting the
! 656: * divisor, but that might interfere with APM or other SMM
! 657: * BIOS code reading the fan speeds.
! 658: */
! 659:
! 660: /* FAN3 has a fixed fan divisor. */
! 661: if (sc->lm_sensors[n].reg == LM_FAN1 ||
! 662: sc->lm_sensors[n].reg == LM_FAN2) {
! 663: data = sc->lm_readreg(sc, LM_VIDFAN);
! 664: if (sc->lm_sensors[n].reg == LM_FAN1)
! 665: divisor = (data >> 4) & 0x03;
! 666: else
! 667: divisor = (data >> 6) & 0x03;
! 668: }
! 669:
! 670: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 671: if (data == 0xff || data == 0x00) {
! 672: sensor->flags |= SENSOR_FINVALID;
! 673: sensor->value = 0;
! 674: } else {
! 675: sensor->flags &= ~SENSOR_FINVALID;
! 676: sensor->value = 1350000 / (data << divisor);
! 677: }
! 678: }
! 679:
! 680: void
! 681: wb_refresh_sensor_data(struct lm_softc *sc)
! 682: {
! 683: int banksel, bank, i;
! 684:
! 685: /*
! 686: * Properly save and restore bank selection register.
! 687: */
! 688:
! 689: banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
! 690: for (i = 0; i < sc->numsensors; i++) {
! 691: if (bank != sc->lm_sensors[i].bank) {
! 692: bank = sc->lm_sensors[i].bank;
! 693: sc->lm_writereg(sc, WB_BANKSEL, bank);
! 694: }
! 695: sc->lm_sensors[i].refresh(sc, i);
! 696: }
! 697: sc->lm_writereg(sc, WB_BANKSEL, banksel);
! 698: }
! 699:
! 700: void
! 701: wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
! 702: {
! 703: struct ksensor *sensor = &sc->sensors[n];
! 704: int data;
! 705:
! 706: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 707:
! 708: /*
! 709: * Depending on the voltage detection method,
! 710: * one of the following formulas is used:
! 711: * VRM8 method: value = raw * 0.016V
! 712: * VRM9 method: value = raw * 0.00488V + 0.70V
! 713: */
! 714: if (sc->vrm9)
! 715: sensor->value = (data * 4880) + 700000;
! 716: else
! 717: sensor->value = (data * 16000);
! 718: }
! 719:
! 720: void
! 721: wb_refresh_nvolt(struct lm_softc *sc, int n)
! 722: {
! 723: struct ksensor *sensor = &sc->sensors[n];
! 724: int data;
! 725:
! 726: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 727: sensor->value = ((data << 4) - WB_VREF);
! 728: sensor->value *= sc->lm_sensors[n].rfact;
! 729: sensor->value /= 10;
! 730: sensor->value += WB_VREF * 1000;
! 731: }
! 732:
! 733: void
! 734: wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
! 735: {
! 736: struct ksensor *sensor = &sc->sensors[n];
! 737: int data;
! 738:
! 739: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 740: sensor->value = ((data << 3) - WB_W83627EHF_VREF);
! 741: sensor->value *= RFACT(232, 10);
! 742: sensor->value /= 10;
! 743: sensor->value += WB_W83627EHF_VREF * 1000;
! 744: }
! 745:
! 746: void
! 747: wb_refresh_temp(struct lm_softc *sc, int n)
! 748: {
! 749: struct ksensor *sensor = &sc->sensors[n];
! 750: int sdata;
! 751:
! 752: /*
! 753: * The data sheet suggests that the range of the temperature
! 754: * sensor is between -55 degC and +125 degC. However, values
! 755: * around -48 degC seem to be a very common bogus values.
! 756: * Since such values are unreasonably low, we use -45 degC for
! 757: * the lower limit instead.
! 758: */
! 759: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
! 760: sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
! 761: if (sdata > 0x0fa && sdata < 0x1a6) {
! 762: sensor->flags |= SENSOR_FINVALID;
! 763: sensor->value = 0;
! 764: } else {
! 765: if (sdata & 0x100)
! 766: sdata -= 0x200;
! 767: sensor->flags &= ~SENSOR_FINVALID;
! 768: sensor->value = sdata * 500000 + 273150000;
! 769: }
! 770: }
! 771:
! 772: void
! 773: wb_refresh_fanrpm(struct lm_softc *sc, int n)
! 774: {
! 775: struct ksensor *sensor = &sc->sensors[n];
! 776: int fan, data, divisor = 0;
! 777:
! 778: /*
! 779: * This is madness; the fan divisor bits are scattered all
! 780: * over the place.
! 781: */
! 782:
! 783: if (sc->lm_sensors[n].reg == LM_FAN1 ||
! 784: sc->lm_sensors[n].reg == LM_FAN2 ||
! 785: sc->lm_sensors[n].reg == LM_FAN3) {
! 786: data = sc->lm_readreg(sc, WB_BANK0_VBAT);
! 787: fan = (sc->lm_sensors[n].reg - LM_FAN1);
! 788: if ((data >> 5) & (1 << fan))
! 789: divisor |= 0x04;
! 790: }
! 791:
! 792: if (sc->lm_sensors[n].reg == LM_FAN1 ||
! 793: sc->lm_sensors[n].reg == LM_FAN2) {
! 794: data = sc->lm_readreg(sc, LM_VIDFAN);
! 795: if (sc->lm_sensors[n].reg == LM_FAN1)
! 796: divisor |= (data >> 4) & 0x03;
! 797: else
! 798: divisor |= (data >> 6) & 0x03;
! 799: } else if (sc->lm_sensors[n].reg == LM_FAN3) {
! 800: data = sc->lm_readreg(sc, WB_PIN);
! 801: divisor |= (data >> 6) & 0x03;
! 802: } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
! 803: sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
! 804: data = sc->lm_readreg(sc, WB_BANK0_FAN45);
! 805: if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
! 806: divisor |= (data >> 0) & 0x07;
! 807: else
! 808: divisor |= (data >> 4) & 0x07;
! 809: }
! 810:
! 811: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 812: if (data == 0xff || data == 0x00) {
! 813: sensor->flags |= SENSOR_FINVALID;
! 814: sensor->value = 0;
! 815: } else {
! 816: sensor->flags &= ~SENSOR_FINVALID;
! 817: sensor->value = 1350000 / (data << divisor);
! 818: }
! 819: }
! 820:
! 821: void
! 822: wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
! 823: {
! 824: struct ksensor *sensor = &sc->sensors[n];
! 825: int reg, shift, data, divisor = 1;
! 826:
! 827: switch (sc->lm_sensors[n].reg) {
! 828: case 0x28:
! 829: reg = 0x47; shift = 0;
! 830: break;
! 831: case 0x29:
! 832: reg = 0x47; shift = 4;
! 833: break;
! 834: case 0x2a:
! 835: reg = 0x5b; shift = 0;
! 836: break;
! 837: case 0xb8:
! 838: reg = 0x5b; shift = 4;
! 839: break;
! 840: case 0xb9:
! 841: reg = 0x5c; shift = 0;
! 842: break;
! 843: case 0xba:
! 844: reg = 0x5c; shift = 4;
! 845: break;
! 846: case 0xbe:
! 847: reg = 0x9e; shift = 0;
! 848: break;
! 849: default:
! 850: reg = 0;
! 851: break;
! 852: }
! 853:
! 854: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
! 855: if (data == 0xff || data == 0x00) {
! 856: sensor->flags |= SENSOR_FINVALID;
! 857: sensor->value = 0;
! 858: } else {
! 859: if (reg != 0)
! 860: divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
! 861: sensor->flags &= ~SENSOR_FINVALID;
! 862: sensor->value = 1350000 / (data << divisor);
! 863: }
! 864: }
! 865:
! 866: void
! 867: as_refresh_temp(struct lm_softc *sc, int n)
! 868: {
! 869: struct ksensor *sensor = &sc->sensors[n];
! 870: int sdata;
! 871:
! 872: /*
! 873: * It seems a shorted temperature diode produces an all-ones
! 874: * bit pattern.
! 875: */
! 876: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
! 877: sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
! 878: if (sdata == 0x1ff) {
! 879: sensor->flags |= SENSOR_FINVALID;
! 880: sensor->value = 0;
! 881: } else {
! 882: if (sdata & 0x100)
! 883: sdata -= 0x200;
! 884: sensor->flags &= ~SENSOR_FINVALID;
! 885: sensor->value = sdata * 500000 + 273150000;
! 886: }
! 887: }
CVSweb