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