1 /* $OpenBSD: lm78.c,v 1.21 2011/07/26 18:43:35 deraadt 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_match(struct lm_softc *sc) 421 { 422 int chipid; 423 424 /* See if we have an LM78 or LM79. */ 425 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 426 switch(chipid) { 427 case LM_CHIPID_LM78: 428 printf(": LM78\n"); 429 break; 430 case LM_CHIPID_LM78J: 431 printf(": LM78J\n"); 432 break; 433 case LM_CHIPID_LM79: 434 printf(": LM79\n"); 435 break; 436 case LM_CHIPID_LM81: 437 printf(": LM81\n"); 438 break; 439 default: 440 return 0; 441 } 442 443 lm_setup_sensors(sc, lm78_sensors); 444 sc->refresh_sensor_data = lm_refresh_sensor_data; 445 return 1; 446 } 447 448 int 449 def_match(struct lm_softc *sc) 450 { 451 int chipid; 452 453 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 454 printf(": unknown chip (ID %d)\n", chipid); 455 456 lm_setup_sensors(sc, lm78_sensors); 457 sc->refresh_sensor_data = lm_refresh_sensor_data; 458 return 1; 459 } 460 461 int 462 wb_match(struct lm_softc *sc) 463 { 464 int banksel, vendid, devid; 465 466 /* Read vendor ID */ 467 banksel = sc->lm_readreg(sc, WB_BANKSEL); 468 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC); 469 vendid = sc->lm_readreg(sc, WB_VENDID) << 8; 470 sc->lm_writereg(sc, WB_BANKSEL, 0); 471 vendid |= sc->lm_readreg(sc, WB_VENDID); 472 sc->lm_writereg(sc, WB_BANKSEL, banksel); 473 DPRINTF((" winbond vend id 0x%x\n", vendid)); 474 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS) 475 return 0; 476 477 /* Read device/chip ID */ 478 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 479 devid = sc->lm_readreg(sc, LM_CHIPID); 480 sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID); 481 sc->lm_writereg(sc, WB_BANKSEL, banksel); 482 DPRINTF((" winbond chip id 0x%x\n", sc->chipid)); 483 switch(sc->chipid) { 484 case WB_CHIPID_W83627HF: 485 printf(": W83627HF\n"); 486 lm_setup_sensors(sc, w83627hf_sensors); 487 break; 488 case WB_CHIPID_W83627THF: 489 printf(": W83627THF\n"); 490 lm_setup_sensors(sc, w83637hf_sensors); 491 break; 492 case WB_CHIPID_W83627EHF_A: 493 printf(": W83627EHF-A\n"); 494 lm_setup_sensors(sc, w83627ehf_sensors); 495 break; 496 case WB_CHIPID_W83627EHF: 497 printf(": W83627EHF\n"); 498 lm_setup_sensors(sc, w83627ehf_sensors); 499 break; 500 case WB_CHIPID_W83627DHG: 501 printf(": W83627DHG\n"); 502 lm_setup_sensors(sc, w83627dhg_sensors); 503 break; 504 case WB_CHIPID_W83637HF: 505 printf(": W83637HF\n"); 506 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 507 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9) 508 sc->vrm9 = 1; 509 sc->lm_writereg(sc, WB_BANKSEL, banksel); 510 lm_setup_sensors(sc, w83637hf_sensors); 511 break; 512 case WB_CHIPID_W83697HF: 513 printf(": W83697HF\n"); 514 lm_setup_sensors(sc, w83697hf_sensors); 515 break; 516 case WB_CHIPID_W83781D: 517 case WB_CHIPID_W83781D_2: 518 printf(": W83781D\n"); 519 lm_setup_sensors(sc, w83781d_sensors); 520 break; 521 case WB_CHIPID_W83782D: 522 printf(": W83782D\n"); 523 lm_setup_sensors(sc, w83782d_sensors); 524 break; 525 case WB_CHIPID_W83783S: 526 printf(": W83783S\n"); 527 lm_setup_sensors(sc, w83783s_sensors); 528 break; 529 case WB_CHIPID_W83791D: 530 printf(": W83791D\n"); 531 lm_setup_sensors(sc, w83791d_sensors); 532 break; 533 case WB_CHIPID_W83791SD: 534 printf(": W83791SD\n"); 535 break; 536 case WB_CHIPID_W83792D: 537 if (devid >= 0x10 && devid <= 0x29) 538 printf(": W83792D rev %c\n", 'A' + devid - 0x10); 539 else 540 printf(": W83792D rev 0x%x\n", devid); 541 lm_setup_sensors(sc, w83792d_sensors); 542 break; 543 case WB_CHIPID_AS99127F: 544 if (vendid == WB_VENDID_ASUS) { 545 printf(": AS99127F\n"); 546 lm_setup_sensors(sc, w83781d_sensors); 547 } else { 548 printf(": AS99127F rev 2\n"); 549 lm_setup_sensors(sc, as99127f_sensors); 550 } 551 break; 552 default: 553 printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid); 554 /* Handle as a standard LM78. */ 555 lm_setup_sensors(sc, lm78_sensors); 556 sc->refresh_sensor_data = lm_refresh_sensor_data; 557 return 1; 558 } 559 560 sc->refresh_sensor_data = wb_refresh_sensor_data; 561 return 1; 562 } 563 564 void 565 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors) 566 { 567 int i; 568 569 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 570 sizeof(sc->sensordev.xname)); 571 572 for (i = 0; sensors[i].desc; i++) { 573 sc->sensors[i].type = sensors[i].type; 574 strlcpy(sc->sensors[i].desc, sensors[i].desc, 575 sizeof(sc->sensors[i].desc)); 576 sc->numsensors++; 577 } 578 sc->lm_sensors = sensors; 579 } 580 581 void 582 lm_refresh(void *arg) 583 { 584 struct lm_softc *sc = arg; 585 586 if (sc->flags & LM78_DEAD) { 587 /* Remove sensors */ 588 int i; 589 590 printf("%s: disabling sensors\n", sc->sc_dev.dv_xname); 591 sensordev_deinstall(&sc->sensordev); 592 for (i = 0; i < sc->numsensors; i++) 593 sensor_detach(&sc->sensordev, &sc->sensors[i]); 594 if (sc->sensortask != NULL) 595 sensor_task_unregister(sc->sensortask); 596 sc->sensortask = NULL; 597 return; 598 } 599 600 sc->refresh_sensor_data(sc); 601 } 602 603 void 604 lm_refresh_sensor_data(struct lm_softc *sc) 605 { 606 int i; 607 608 for (i = 0; i < sc->numsensors; i++) 609 sc->lm_sensors[i].refresh(sc, i); 610 } 611 612 void 613 lm_refresh_volt(struct lm_softc *sc, int n) 614 { 615 struct ksensor *sensor = &sc->sensors[n]; 616 int data; 617 618 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 619 sensor->value = (data << 4); 620 sensor->value *= sc->lm_sensors[n].rfact; 621 sensor->value /= 10; 622 } 623 624 void 625 lm_refresh_temp(struct lm_softc *sc, int n) 626 { 627 struct ksensor *sensor = &sc->sensors[n]; 628 int sdata; 629 630 /* 631 * The data sheet suggests that the range of the temperature 632 * sensor is between -55 degC and +125 degC. 633 */ 634 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 635 if (sdata > 0x7d && sdata < 0xc9) { 636 sensor->flags |= SENSOR_FINVALID; 637 sensor->value = 0; 638 } else { 639 if (sdata & 0x80) 640 sdata -= 0x100; 641 sensor->flags &= ~SENSOR_FINVALID; 642 sensor->value = sdata * 1000000 + 273150000; 643 } 644 } 645 646 void 647 lm_refresh_fanrpm(struct lm_softc *sc, int n) 648 { 649 struct ksensor *sensor = &sc->sensors[n]; 650 int data, divisor = 1; 651 652 /* 653 * We might get more accurate fan readings by adjusting the 654 * divisor, but that might interfere with APM or other SMM 655 * BIOS code reading the fan speeds. 656 */ 657 658 /* FAN3 has a fixed fan divisor. */ 659 if (sc->lm_sensors[n].reg == LM_FAN1 || 660 sc->lm_sensors[n].reg == LM_FAN2) { 661 data = sc->lm_readreg(sc, LM_VIDFAN); 662 if (sc->lm_sensors[n].reg == LM_FAN1) 663 divisor = (data >> 4) & 0x03; 664 else 665 divisor = (data >> 6) & 0x03; 666 } 667 668 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 669 if (data == 0xff || data == 0x00) { 670 sensor->flags |= SENSOR_FINVALID; 671 sensor->value = 0; 672 } else { 673 sensor->flags &= ~SENSOR_FINVALID; 674 sensor->value = 1350000 / (data << divisor); 675 } 676 } 677 678 void 679 wb_refresh_sensor_data(struct lm_softc *sc) 680 { 681 int banksel, bank, i; 682 683 /* 684 * Properly save and restore bank selection register. 685 */ 686 687 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL); 688 for (i = 0; i < sc->numsensors; i++) { 689 if (bank != sc->lm_sensors[i].bank) { 690 bank = sc->lm_sensors[i].bank; 691 sc->lm_writereg(sc, WB_BANKSEL, bank); 692 } 693 sc->lm_sensors[i].refresh(sc, i); 694 } 695 sc->lm_writereg(sc, WB_BANKSEL, banksel); 696 } 697 698 void 699 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n) 700 { 701 struct ksensor *sensor = &sc->sensors[n]; 702 int data; 703 704 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 705 706 /* 707 * Depending on the voltage detection method, 708 * one of the following formulas is used: 709 * VRM8 method: value = raw * 0.016V 710 * VRM9 method: value = raw * 0.00488V + 0.70V 711 */ 712 if (sc->vrm9) 713 sensor->value = (data * 4880) + 700000; 714 else 715 sensor->value = (data * 16000); 716 } 717 718 void 719 wb_refresh_nvolt(struct lm_softc *sc, int n) 720 { 721 struct ksensor *sensor = &sc->sensors[n]; 722 int data; 723 724 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 725 sensor->value = ((data << 4) - WB_VREF); 726 sensor->value *= sc->lm_sensors[n].rfact; 727 sensor->value /= 10; 728 sensor->value += WB_VREF * 1000; 729 } 730 731 void 732 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n) 733 { 734 struct ksensor *sensor = &sc->sensors[n]; 735 int data; 736 737 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 738 sensor->value = ((data << 3) - WB_W83627EHF_VREF); 739 sensor->value *= RFACT(232, 10); 740 sensor->value /= 10; 741 sensor->value += WB_W83627EHF_VREF * 1000; 742 } 743 744 void 745 wb_refresh_temp(struct lm_softc *sc, int n) 746 { 747 struct ksensor *sensor = &sc->sensors[n]; 748 int sdata; 749 750 /* 751 * The data sheet suggests that the range of the temperature 752 * sensor is between -55 degC and +125 degC. However, values 753 * around -48 degC seem to be a very common bogus values. 754 * Since such values are unreasonably low, we use -45 degC for 755 * the lower limit instead. 756 */ 757 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 758 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 759 if (sdata > 0x0fa && sdata < 0x1a6) { 760 sensor->flags |= SENSOR_FINVALID; 761 sensor->value = 0; 762 } else { 763 if (sdata & 0x100) 764 sdata -= 0x200; 765 sensor->flags &= ~SENSOR_FINVALID; 766 sensor->value = sdata * 500000 + 273150000; 767 } 768 } 769 770 void 771 wb_refresh_fanrpm(struct lm_softc *sc, int n) 772 { 773 struct ksensor *sensor = &sc->sensors[n]; 774 int fan, data, divisor = 0; 775 776 /* 777 * This is madness; the fan divisor bits are scattered all 778 * over the place. 779 */ 780 781 if (sc->lm_sensors[n].reg == LM_FAN1 || 782 sc->lm_sensors[n].reg == LM_FAN2 || 783 sc->lm_sensors[n].reg == LM_FAN3) { 784 data = sc->lm_readreg(sc, WB_BANK0_VBAT); 785 fan = (sc->lm_sensors[n].reg - LM_FAN1); 786 if ((data >> 5) & (1 << fan)) 787 divisor |= 0x04; 788 } 789 790 if (sc->lm_sensors[n].reg == LM_FAN1 || 791 sc->lm_sensors[n].reg == LM_FAN2) { 792 data = sc->lm_readreg(sc, LM_VIDFAN); 793 if (sc->lm_sensors[n].reg == LM_FAN1) 794 divisor |= (data >> 4) & 0x03; 795 else 796 divisor |= (data >> 6) & 0x03; 797 } else if (sc->lm_sensors[n].reg == LM_FAN3) { 798 data = sc->lm_readreg(sc, WB_PIN); 799 divisor |= (data >> 6) & 0x03; 800 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 || 801 sc->lm_sensors[n].reg == WB_BANK0_FAN5) { 802 data = sc->lm_readreg(sc, WB_BANK0_FAN45); 803 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4) 804 divisor |= (data >> 0) & 0x07; 805 else 806 divisor |= (data >> 4) & 0x07; 807 } 808 809 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 810 if (data == 0xff || data == 0x00) { 811 sensor->flags |= SENSOR_FINVALID; 812 sensor->value = 0; 813 } else { 814 sensor->flags &= ~SENSOR_FINVALID; 815 sensor->value = 1350000 / (data << divisor); 816 } 817 } 818 819 void 820 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n) 821 { 822 struct ksensor *sensor = &sc->sensors[n]; 823 int reg, shift, data, divisor = 1; 824 825 switch (sc->lm_sensors[n].reg) { 826 case 0x28: 827 reg = 0x47; shift = 0; 828 break; 829 case 0x29: 830 reg = 0x47; shift = 4; 831 break; 832 case 0x2a: 833 reg = 0x5b; shift = 0; 834 break; 835 case 0xb8: 836 reg = 0x5b; shift = 4; 837 break; 838 case 0xb9: 839 reg = 0x5c; shift = 0; 840 break; 841 case 0xba: 842 reg = 0x5c; shift = 4; 843 break; 844 case 0xbe: 845 reg = 0x9e; shift = 0; 846 break; 847 default: 848 reg = 0; 849 break; 850 } 851 852 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 853 if (data == 0xff || data == 0x00) { 854 sensor->flags |= SENSOR_FINVALID; 855 sensor->value = 0; 856 } else { 857 if (reg != 0) 858 divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7; 859 sensor->flags &= ~SENSOR_FINVALID; 860 sensor->value = 1350000 / (data << divisor); 861 } 862 } 863 864 void 865 as_refresh_temp(struct lm_softc *sc, int n) 866 { 867 struct ksensor *sensor = &sc->sensors[n]; 868 int sdata; 869 870 /* 871 * It seems a shorted temperature diode produces an all-ones 872 * bit pattern. 873 */ 874 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 875 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 876 if (sdata == 0x1ff) { 877 sensor->flags |= SENSOR_FINVALID; 878 sensor->value = 0; 879 } else { 880 if (sdata & 0x100) 881 sdata -= 0x200; 882 sensor->flags &= ~SENSOR_FINVALID; 883 sensor->value = sdata * 500000 + 273150000; 884 } 885 } 886