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