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 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_A: 519 cdesc = "W83627EHF-A"; 520 lm_setup_sensors(sc, w83627ehf_sensors); 521 break; 522 case WB_CHIPID_W83627EHF: 523 cdesc = "W83627EHF"; 524 lm_setup_sensors(sc, w83627ehf_sensors); 525 break; 526 case WB_CHIPID_W83627DHG: 527 cdesc = "W83627DHG"; 528 lm_setup_sensors(sc, w83627dhg_sensors); 529 break; 530 case WB_CHIPID_W83637HF: 531 cdesc = "W83637HF"; 532 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 533 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9) 534 sc->vrm9 = 1; 535 sc->lm_writereg(sc, WB_BANKSEL, banksel); 536 lm_setup_sensors(sc, w83637hf_sensors); 537 break; 538 case WB_CHIPID_W83697HF: 539 cdesc = "W83697HF"; 540 lm_setup_sensors(sc, w83697hf_sensors); 541 break; 542 case WB_CHIPID_W83781D: 543 case WB_CHIPID_W83781D_2: 544 cdesc = "W83781D"; 545 lm_setup_sensors(sc, w83781d_sensors); 546 break; 547 case WB_CHIPID_W83782D: 548 cdesc = "W83782D"; 549 lm_setup_sensors(sc, w83782d_sensors); 550 break; 551 case WB_CHIPID_W83783S: 552 cdesc = "W83783S"; 553 lm_setup_sensors(sc, w83783s_sensors); 554 break; 555 case WB_CHIPID_W83791D: 556 cdesc = "W83791D"; 557 lm_setup_sensors(sc, w83791d_sensors); 558 break; 559 case WB_CHIPID_W83791SD: 560 cdesc = "W83791SD"; 561 break; 562 case WB_CHIPID_W83792D: 563 if (devid >= 0x10 && devid <= 0x29) 564 ksnprintf(desc, sizeof(desc), 565 "W83792D rev %c", 'A' + devid - 0x10); 566 else 567 ksnprintf(desc, sizeof(desc), 568 "W83792D rev 0x%x", devid); 569 cdesc = desc; 570 lm_setup_sensors(sc, w83792d_sensors); 571 break; 572 case WB_CHIPID_AS99127F: 573 if (vendid == WB_VENDID_ASUS) { 574 cdesc = "AS99127F"; 575 lm_setup_sensors(sc, w83781d_sensors); 576 } else { 577 cdesc = "AS99127F rev 2"; 578 lm_setup_sensors(sc, as99127f_sensors); 579 } 580 break; 581 default: 582 ksnprintf(fulldesc, sizeof(fulldesc), 583 "unknown Winbond Hardware Monitor (Chip ID 0x%x)", 584 sc->chipid); 585 device_set_desc_copy(sc->sc_dev, fulldesc); 586 /* Handle as a standard LM78. */ 587 lm_setup_sensors(sc, lm78_sensors); 588 sc->refresh_sensor_data = lm_refresh_sensor_data; 589 return 1; 590 } 591 592 if (cdesc[0] == 'W') 593 ksnprintf(fulldesc, sizeof(fulldesc), 594 "Winbond %s Hardware Monitor", cdesc); 595 else 596 ksnprintf(fulldesc, sizeof(fulldesc), 597 "ASUS %s Hardware Monitor", cdesc); 598 device_set_desc_copy(sc->sc_dev, fulldesc); 599 600 sc->refresh_sensor_data = wb_refresh_sensor_data; 601 return 1; 602 } 603 604 void 605 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors) 606 { 607 int i; 608 609 for (i = 0; sensors[i].desc; i++) { 610 sc->sensors[i].type = sensors[i].type; 611 strlcpy(sc->sensors[i].desc, sensors[i].desc, 612 sizeof(sc->sensors[i].desc)); 613 sc->numsensors++; 614 } 615 sc->lm_sensors = sensors; 616 } 617 618 void 619 lm_refresh(void *arg) 620 { 621 struct lm_softc *sc = arg; 622 623 sc->refresh_sensor_data(sc); 624 } 625 626 void 627 lm_refresh_sensor_data(struct lm_softc *sc) 628 { 629 int i; 630 631 for (i = 0; i < sc->numsensors; i++) 632 sc->lm_sensors[i].refresh(sc, i); 633 } 634 635 void 636 lm_refresh_volt(struct lm_softc *sc, int n) 637 { 638 struct ksensor *sensor = &sc->sensors[n]; 639 int data; 640 641 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 642 sensor->value = (data << 4); 643 sensor->value *= sc->lm_sensors[n].rfact; 644 sensor->value /= 10; 645 } 646 647 void 648 lm_refresh_temp(struct lm_softc *sc, int n) 649 { 650 struct ksensor *sensor = &sc->sensors[n]; 651 int sdata; 652 653 /* 654 * The data sheet suggests that the range of the temperature 655 * sensor is between -55 degC and +125 degC. 656 */ 657 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 658 if (sdata > 0x7d && sdata < 0xc9) { 659 sensor->flags |= SENSOR_FINVALID; 660 sensor->value = 0; 661 } else { 662 if (sdata & 0x80) 663 sdata -= 0x100; 664 sensor->flags &= ~SENSOR_FINVALID; 665 sensor->value = sdata * 1000000 + 273150000; 666 } 667 } 668 669 void 670 lm_refresh_fanrpm(struct lm_softc *sc, int n) 671 { 672 struct ksensor *sensor = &sc->sensors[n]; 673 int data, divisor = 1; 674 675 /* 676 * We might get more accurate fan readings by adjusting the 677 * divisor, but that might interfere with APM or other SMM 678 * BIOS code reading the fan speeds. 679 */ 680 681 /* FAN3 has a fixed fan divisor. */ 682 if (sc->lm_sensors[n].reg == LM_FAN1 || 683 sc->lm_sensors[n].reg == LM_FAN2) { 684 data = sc->lm_readreg(sc, LM_VIDFAN); 685 if (sc->lm_sensors[n].reg == LM_FAN1) 686 divisor = (data >> 4) & 0x03; 687 else 688 divisor = (data >> 6) & 0x03; 689 } 690 691 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 692 if (data == 0xff || data == 0x00) { 693 sensor->flags |= SENSOR_FINVALID; 694 sensor->value = 0; 695 } else { 696 sensor->flags &= ~SENSOR_FINVALID; 697 sensor->value = 1350000 / (data << divisor); 698 } 699 } 700 701 void 702 wb_refresh_sensor_data(struct lm_softc *sc) 703 { 704 int banksel, bank, i; 705 706 /* 707 * Properly save and restore bank selection register. 708 */ 709 710 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL); 711 for (i = 0; i < sc->numsensors; i++) { 712 if (bank != sc->lm_sensors[i].bank) { 713 bank = sc->lm_sensors[i].bank; 714 sc->lm_writereg(sc, WB_BANKSEL, bank); 715 } 716 sc->lm_sensors[i].refresh(sc, i); 717 } 718 sc->lm_writereg(sc, WB_BANKSEL, banksel); 719 } 720 721 void 722 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n) 723 { 724 struct ksensor *sensor = &sc->sensors[n]; 725 int data; 726 727 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 728 729 /* 730 * Depending on the voltage detection method, 731 * one of the following formulas is used: 732 * VRM8 method: value = raw * 0.016V 733 * VRM9 method: value = raw * 0.00488V + 0.70V 734 */ 735 if (sc->vrm9) 736 sensor->value = (data * 4880) + 700000; 737 else 738 sensor->value = (data * 16000); 739 } 740 741 void 742 wb_refresh_nvolt(struct lm_softc *sc, int n) 743 { 744 struct ksensor *sensor = &sc->sensors[n]; 745 int data; 746 747 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 748 sensor->value = ((data << 4) - WB_VREF); 749 sensor->value *= sc->lm_sensors[n].rfact; 750 sensor->value /= 10; 751 sensor->value += WB_VREF * 1000; 752 } 753 754 void 755 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n) 756 { 757 struct ksensor *sensor = &sc->sensors[n]; 758 int data; 759 760 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 761 sensor->value = ((data << 3) - WB_W83627EHF_VREF); 762 sensor->value *= RFACT(232, 10); 763 sensor->value /= 10; 764 sensor->value += WB_W83627EHF_VREF * 1000; 765 } 766 767 void 768 wb_refresh_temp(struct lm_softc *sc, int n) 769 { 770 struct ksensor *sensor = &sc->sensors[n]; 771 int sdata; 772 773 /* 774 * The data sheet suggests that the range of the temperature 775 * sensor is between -55 degC and +125 degC. However, values 776 * around -48 degC seem to be a very common bogus values. 777 * Since such values are unreasonably low, we use -45 degC for 778 * the lower limit instead. 779 */ 780 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 781 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 782 if (sdata > 0x0fa && sdata < 0x1a6) { 783 sensor->flags |= SENSOR_FINVALID; 784 sensor->value = 0; 785 } else { 786 if (sdata & 0x100) 787 sdata -= 0x200; 788 sensor->flags &= ~SENSOR_FINVALID; 789 sensor->value = sdata * 500000 + 273150000; 790 } 791 } 792 793 void 794 wb_refresh_fanrpm(struct lm_softc *sc, int n) 795 { 796 struct ksensor *sensor = &sc->sensors[n]; 797 int fan, data, divisor = 0; 798 799 /* 800 * This is madness; the fan divisor bits are scattered all 801 * over the place. 802 */ 803 804 if (sc->lm_sensors[n].reg == LM_FAN1 || 805 sc->lm_sensors[n].reg == LM_FAN2 || 806 sc->lm_sensors[n].reg == LM_FAN3) { 807 data = sc->lm_readreg(sc, WB_BANK0_VBAT); 808 fan = (sc->lm_sensors[n].reg - LM_FAN1); 809 if ((data >> 5) & (1 << fan)) 810 divisor |= 0x04; 811 } 812 813 if (sc->lm_sensors[n].reg == LM_FAN1 || 814 sc->lm_sensors[n].reg == LM_FAN2) { 815 data = sc->lm_readreg(sc, LM_VIDFAN); 816 if (sc->lm_sensors[n].reg == LM_FAN1) 817 divisor |= (data >> 4) & 0x03; 818 else 819 divisor |= (data >> 6) & 0x03; 820 } else if (sc->lm_sensors[n].reg == LM_FAN3) { 821 data = sc->lm_readreg(sc, WB_PIN); 822 divisor |= (data >> 6) & 0x03; 823 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 || 824 sc->lm_sensors[n].reg == WB_BANK0_FAN5) { 825 data = sc->lm_readreg(sc, WB_BANK0_FAN45); 826 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4) 827 divisor |= (data >> 0) & 0x07; 828 else 829 divisor |= (data >> 4) & 0x07; 830 } 831 832 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 833 if (data == 0xff || data == 0x00) { 834 sensor->flags |= SENSOR_FINVALID; 835 sensor->value = 0; 836 } else { 837 sensor->flags &= ~SENSOR_FINVALID; 838 sensor->value = 1350000 / (data << divisor); 839 } 840 } 841 842 void 843 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n) 844 { 845 struct ksensor *sensor = &sc->sensors[n]; 846 int reg, shift, data, divisor = 1; 847 848 switch (sc->lm_sensors[n].reg) { 849 case 0x28: 850 reg = 0x47; shift = 0; 851 break; 852 case 0x29: 853 reg = 0x47; shift = 4; 854 break; 855 case 0x2a: 856 reg = 0x5b; shift = 0; 857 break; 858 case 0xb8: 859 reg = 0x5b; shift = 4; 860 break; 861 case 0xb9: 862 reg = 0x5c; shift = 0; 863 break; 864 case 0xba: 865 reg = 0x5c; shift = 4; 866 break; 867 case 0xbe: 868 reg = 0x9e; shift = 0; 869 break; 870 default: 871 reg = 0; shift = 0; 872 break; 873 } 874 875 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 876 if (data == 0xff || data == 0x00) { 877 sensor->flags |= SENSOR_FINVALID; 878 sensor->value = 0; 879 } else { 880 if (reg != 0) 881 divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7; 882 sensor->flags &= ~SENSOR_FINVALID; 883 sensor->value = 1350000 / (data << divisor); 884 } 885 } 886 887 void 888 as_refresh_temp(struct lm_softc *sc, int n) 889 { 890 struct ksensor *sensor = &sc->sensors[n]; 891 int sdata; 892 893 /* 894 * It seems a shorted temperature diode produces an all-ones 895 * bit pattern. 896 */ 897 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 898 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 899 if (sdata == 0x1ff) { 900 sensor->flags |= SENSOR_FINVALID; 901 sensor->value = 0; 902 } else { 903 if (sdata & 0x100) 904 sdata -= 0x200; 905 sensor->flags &= ~SENSOR_FINVALID; 906 sensor->value = sdata * 500000 + 273150000; 907 } 908 } 909