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