1 /* $OpenBSD: lm78.c,v 1.23 2011/12/06 16:06:07 mpf 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 #include <dev/isa/wbsioreg.h> 29 30 #if defined(LMDEBUG) 31 #define DPRINTF(x) do { printf x; } while (0) 32 #else 33 #define DPRINTF(x) 34 #endif 35 36 /* 37 * LM78-compatible chips can typically measure voltages up to 4.096 V. 38 * To measure higher voltages the input is attenuated with (external) 39 * resistors. Negative voltages are measured using inverting op amps 40 * and resistors. So we have to convert the sensor values back to 41 * real voltages by applying the appropriate resistor factor. 42 */ 43 #define RFACT_NONE 10000 44 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y)) 45 #define NRFACT(x, y) (-RFACT_NONE * (x) / (y)) 46 47 struct cfdriver lm_cd = { 48 NULL, "lm", DV_DULL 49 }; 50 51 int lm_match(struct lm_softc *); 52 int wb_match(struct lm_softc *); 53 int def_match(struct lm_softc *); 54 55 void lm_setup_sensors(struct lm_softc *, struct lm_sensor *); 56 void lm_refresh(void *); 57 58 void lm_refresh_sensor_data(struct lm_softc *); 59 void lm_refresh_volt(struct lm_softc *, int); 60 void lm_refresh_temp(struct lm_softc *, int); 61 void lm_refresh_fanrpm(struct lm_softc *, int); 62 63 void wb_refresh_sensor_data(struct lm_softc *); 64 void wb_w83637hf_refresh_vcore(struct lm_softc *, int); 65 void wb_refresh_nvolt(struct lm_softc *, int); 66 void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int); 67 void wb_refresh_temp(struct lm_softc *, int); 68 void wb_refresh_fanrpm(struct lm_softc *, int); 69 void wb_nct6776f_refresh_fanrpm(struct lm_softc *, int); 70 void wb_w83792d_refresh_fanrpm(struct lm_softc *, int); 71 72 void as_refresh_temp(struct lm_softc *, int); 73 74 struct lm_chip { 75 int (*chip_match)(struct lm_softc *); 76 }; 77 78 struct lm_chip lm_chips[] = { 79 { wb_match }, 80 { lm_match }, 81 { def_match } /* Must be last */ 82 }; 83 84 struct lm_sensor lm78_sensors[] = { 85 /* Voltage */ 86 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 87 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 88 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 89 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) }, 90 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) }, 91 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) }, 92 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) }, 93 94 /* Temperature */ 95 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 96 97 /* Fans */ 98 { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm }, 99 { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm }, 100 { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm }, 101 102 { NULL } 103 }; 104 105 struct lm_sensor w83627hf_sensors[] = { 106 /* Voltage */ 107 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 108 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 109 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 110 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 111 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 112 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 113 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 114 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) }, 115 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 116 117 /* Temperature */ 118 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 119 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 120 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 121 122 /* Fans */ 123 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 124 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 125 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 126 127 { NULL } 128 }; 129 130 /* 131 * The W83627EHF can measure voltages up to 2.048 V instead of the 132 * traditional 4.096 V. For measuring positive voltages, this can be 133 * accounted for by halving the resistor factor. Negative voltages 134 * need special treatment, also because the reference voltage is 2.048 V 135 * instead of the traditional 3.6 V. 136 */ 137 struct lm_sensor w83627ehf_sensors[] = { 138 /* Voltage */ 139 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2}, 140 { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 }, 141 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 }, 142 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 }, 143 { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt }, 144 { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 }, 145 { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 }, 146 { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 }, 147 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 }, 148 { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 }, 149 150 /* Temperature */ 151 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 152 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 153 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 154 155 /* Fans */ 156 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 157 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 158 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 159 160 { NULL } 161 }; 162 163 /* 164 * w83627dhg is almost identical to w83627ehf, except that 165 * it has 9 instead of 10 voltage sensors 166 */ 167 struct lm_sensor w83627dhg_sensors[] = { 168 /* Voltage */ 169 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2}, 170 { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 }, 171 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 }, 172 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 }, 173 { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt }, 174 { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 }, 175 { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 }, 176 { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 }, 177 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 }, 178 179 /* Temperature */ 180 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 181 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 182 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 183 184 /* Fans */ 185 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 186 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 187 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 188 189 { NULL } 190 }; 191 192 struct lm_sensor nct6776f_sensors[] = { 193 /* Voltage */ 194 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2}, 195 { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 }, 196 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 }, 197 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 }, 198 { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt }, 199 { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 }, 200 { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 }, 201 { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 }, 202 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 }, 203 204 /* Temperature */ 205 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 206 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 207 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 208 209 /* Fans */ 210 { "", SENSOR_FANRPM, 6, 0x56, wb_nct6776f_refresh_fanrpm }, 211 { "", SENSOR_FANRPM, 6, 0x58, wb_nct6776f_refresh_fanrpm }, 212 { "", SENSOR_FANRPM, 6, 0x5a, wb_nct6776f_refresh_fanrpm }, 213 { "", SENSOR_FANRPM, 6, 0x5c, wb_nct6776f_refresh_fanrpm }, 214 { "", SENSOR_FANRPM, 6, 0x5e, wb_nct6776f_refresh_fanrpm }, 215 216 { NULL } 217 }; 218 219 struct lm_sensor w83637hf_sensors[] = { 220 /* Voltage */ 221 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore }, 222 { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) }, 223 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 224 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) }, 225 { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) }, 226 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) }, 227 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 228 229 /* Temperature */ 230 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 231 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 232 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 233 234 /* Fans */ 235 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 236 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 237 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 238 239 { NULL } 240 }; 241 242 struct lm_sensor w83697hf_sensors[] = { 243 /* Voltage */ 244 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 245 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 246 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 247 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 248 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 249 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 250 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) }, 251 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 252 253 /* Temperature */ 254 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 255 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 256 257 /* Fans */ 258 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 259 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 260 261 { NULL } 262 }; 263 264 /* 265 * The datasheet doesn't mention the (internal) resistors used for the 266 * +5V, but using the values from the W83782D datasheets seems to 267 * provide sensible results. 268 */ 269 struct lm_sensor w83781d_sensors[] = { 270 /* Voltage */ 271 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 272 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 273 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 274 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 275 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 276 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) }, 277 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) }, 278 279 /* Temperature */ 280 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 281 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 282 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 283 284 /* Fans */ 285 { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm }, 286 { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm }, 287 { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm }, 288 289 { NULL } 290 }; 291 292 struct lm_sensor w83782d_sensors[] = { 293 /* Voltage */ 294 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 295 { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 296 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 297 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 298 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 299 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 300 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 301 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) }, 302 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 303 304 /* Temperature */ 305 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 306 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 307 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 308 309 /* Fans */ 310 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 311 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 312 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 313 314 { NULL } 315 }; 316 317 struct lm_sensor w83783s_sensors[] = { 318 /* Voltage */ 319 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 320 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 321 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 322 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 323 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 324 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 325 326 /* Temperature */ 327 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 328 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 329 330 /* Fans */ 331 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 332 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 333 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 334 335 { NULL } 336 }; 337 338 struct lm_sensor w83791d_sensors[] = { 339 /* Voltage */ 340 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 }, 341 { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 }, 342 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 }, 343 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 344 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 345 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 346 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 347 { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) }, 348 { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE }, 349 { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE }, 350 351 /* Temperature */ 352 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 353 { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp }, 354 { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp }, 355 356 /* Fans */ 357 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 358 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 359 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 360 { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm }, 361 { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm }, 362 363 { NULL } 364 }; 365 366 struct lm_sensor w83792d_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, wb_refresh_nvolt, RFACT(120, 56) }, 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, lm_refresh_volt, RFACT(34, 50) }, 375 { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) }, 376 { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE }, 377 378 /* Temperature */ 379 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 380 { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp }, 381 { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp }, 382 383 /* Fans */ 384 { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm }, 385 { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm }, 386 { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm }, 387 { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm }, 388 { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm }, 389 { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm }, 390 { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm }, 391 392 { NULL } 393 }; 394 395 struct lm_sensor as99127f_sensors[] = { 396 /* Voltage */ 397 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 398 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 399 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 400 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 401 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 402 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 403 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 404 405 /* Temperature */ 406 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 407 { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp }, 408 { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp }, 409 410 /* Fans */ 411 { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm }, 412 { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm }, 413 { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm }, 414 415 { NULL } 416 }; 417 418 void 419 lm_attach(struct lm_softc *sc) 420 { 421 u_int i, config; 422 423 for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++) 424 if (lm_chips[i].chip_match(sc)) 425 break; 426 427 /* No point in doing anything if we don't have any sensors. */ 428 if (sc->numsensors == 0) 429 return; 430 431 sc->sensortask = sensor_task_register(sc, lm_refresh, 5); 432 if (sc->sensortask == NULL) { 433 printf("%s: unable to register update task\n", 434 sc->sc_dev.dv_xname); 435 return; 436 } 437 438 /* Start the monitoring loop */ 439 config = sc->lm_readreg(sc, LM_CONFIG); 440 sc->lm_writereg(sc, LM_CONFIG, config | 0x01); 441 442 /* Add sensors */ 443 for (i = 0; i < sc->numsensors; ++i) 444 sensor_attach(&sc->sensordev, &sc->sensors[i]); 445 sensordev_install(&sc->sensordev); 446 } 447 448 int 449 lm_match(struct lm_softc *sc) 450 { 451 int chipid; 452 453 /* See if we have an LM78 or LM79. */ 454 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 455 switch(chipid) { 456 case LM_CHIPID_LM78: 457 printf(": LM78\n"); 458 break; 459 case LM_CHIPID_LM78J: 460 printf(": LM78J\n"); 461 break; 462 case LM_CHIPID_LM79: 463 printf(": LM79\n"); 464 break; 465 case LM_CHIPID_LM81: 466 printf(": LM81\n"); 467 break; 468 default: 469 return 0; 470 } 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 def_match(struct lm_softc *sc) 479 { 480 int chipid; 481 482 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 483 printf(": unknown chip (ID %d)\n", chipid); 484 485 lm_setup_sensors(sc, lm78_sensors); 486 sc->refresh_sensor_data = lm_refresh_sensor_data; 487 return 1; 488 } 489 490 int 491 wb_match(struct lm_softc *sc) 492 { 493 int banksel, vendid, devid; 494 495 /* Read vendor ID */ 496 banksel = sc->lm_readreg(sc, WB_BANKSEL); 497 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC); 498 vendid = sc->lm_readreg(sc, WB_VENDID) << 8; 499 sc->lm_writereg(sc, WB_BANKSEL, 0); 500 vendid |= sc->lm_readreg(sc, WB_VENDID); 501 sc->lm_writereg(sc, WB_BANKSEL, banksel); 502 DPRINTF((" winbond vend id 0x%x\n", vendid)); 503 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS) 504 return 0; 505 506 /* Read device/chip ID */ 507 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 508 devid = sc->lm_readreg(sc, LM_CHIPID); 509 sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID); 510 sc->lm_writereg(sc, WB_BANKSEL, banksel); 511 DPRINTF((" winbond chip id 0x%x\n", sc->chipid)); 512 switch(sc->chipid) { 513 case WB_CHIPID_W83627HF: 514 printf(": W83627HF\n"); 515 lm_setup_sensors(sc, w83627hf_sensors); 516 break; 517 case WB_CHIPID_W83627THF: 518 printf(": W83627THF\n"); 519 lm_setup_sensors(sc, w83637hf_sensors); 520 break; 521 case WB_CHIPID_W83627EHF_A: 522 printf(": W83627EHF-A\n"); 523 lm_setup_sensors(sc, w83627ehf_sensors); 524 break; 525 case WB_CHIPID_W83627EHF: 526 printf(": W83627EHF\n"); 527 lm_setup_sensors(sc, w83627ehf_sensors); 528 break; 529 case WB_CHIPID_W83627DHG: 530 if (sc->sioid == WBSIO_ID_NCT6776F) { 531 printf(": NCT6776F\n"); 532 lm_setup_sensors(sc, nct6776f_sensors); 533 } else { 534 printf(": W83627DHG\n"); 535 lm_setup_sensors(sc, w83627dhg_sensors); 536 } 537 break; 538 case WB_CHIPID_W83637HF: 539 printf(": W83637HF\n"); 540 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 541 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9) 542 sc->vrm9 = 1; 543 sc->lm_writereg(sc, WB_BANKSEL, banksel); 544 lm_setup_sensors(sc, w83637hf_sensors); 545 break; 546 case WB_CHIPID_W83697HF: 547 printf(": W83697HF\n"); 548 lm_setup_sensors(sc, w83697hf_sensors); 549 break; 550 case WB_CHIPID_W83781D: 551 case WB_CHIPID_W83781D_2: 552 printf(": W83781D\n"); 553 lm_setup_sensors(sc, w83781d_sensors); 554 break; 555 case WB_CHIPID_W83782D: 556 printf(": W83782D\n"); 557 lm_setup_sensors(sc, w83782d_sensors); 558 break; 559 case WB_CHIPID_W83783S: 560 printf(": W83783S\n"); 561 lm_setup_sensors(sc, w83783s_sensors); 562 break; 563 case WB_CHIPID_W83791D: 564 printf(": W83791D\n"); 565 lm_setup_sensors(sc, w83791d_sensors); 566 break; 567 case WB_CHIPID_W83791SD: 568 printf(": W83791SD\n"); 569 break; 570 case WB_CHIPID_W83792D: 571 if (devid >= 0x10 && devid <= 0x29) 572 printf(": W83792D rev %c\n", 'A' + devid - 0x10); 573 else 574 printf(": W83792D rev 0x%x\n", devid); 575 lm_setup_sensors(sc, w83792d_sensors); 576 break; 577 case WB_CHIPID_AS99127F: 578 if (vendid == WB_VENDID_ASUS) { 579 printf(": AS99127F\n"); 580 lm_setup_sensors(sc, w83781d_sensors); 581 } else { 582 printf(": AS99127F rev 2\n"); 583 lm_setup_sensors(sc, as99127f_sensors); 584 } 585 break; 586 default: 587 printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid); 588 /* Handle as a standard LM78. */ 589 lm_setup_sensors(sc, lm78_sensors); 590 sc->refresh_sensor_data = lm_refresh_sensor_data; 591 return 1; 592 } 593 594 sc->refresh_sensor_data = wb_refresh_sensor_data; 595 return 1; 596 } 597 598 void 599 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors) 600 { 601 int i; 602 603 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 604 sizeof(sc->sensordev.xname)); 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_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n) 841 { 842 struct ksensor *sensor = &sc->sensors[n]; 843 int datah, datal; 844 845 datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 846 datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1); 847 848 if (datah == 0xff) { 849 sensor->flags |= SENSOR_FINVALID; 850 sensor->value = 0; 851 } else { 852 sensor->flags &= ~SENSOR_FINVALID; 853 sensor->value = (datah << 8) | datal; 854 } 855 } 856 857 void 858 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n) 859 { 860 struct ksensor *sensor = &sc->sensors[n]; 861 int reg, shift, data, divisor = 1; 862 863 switch (sc->lm_sensors[n].reg) { 864 case 0x28: 865 reg = 0x47; shift = 0; 866 break; 867 case 0x29: 868 reg = 0x47; shift = 4; 869 break; 870 case 0x2a: 871 reg = 0x5b; shift = 0; 872 break; 873 case 0xb8: 874 reg = 0x5b; shift = 4; 875 break; 876 case 0xb9: 877 reg = 0x5c; shift = 0; 878 break; 879 case 0xba: 880 reg = 0x5c; shift = 4; 881 break; 882 case 0xbe: 883 reg = 0x9e; shift = 0; 884 break; 885 default: 886 reg = 0; 887 break; 888 } 889 890 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 891 if (data == 0xff || data == 0x00) { 892 sensor->flags |= SENSOR_FINVALID; 893 sensor->value = 0; 894 } else { 895 if (reg != 0) 896 divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7; 897 sensor->flags &= ~SENSOR_FINVALID; 898 sensor->value = 1350000 / (data << divisor); 899 } 900 } 901 902 void 903 as_refresh_temp(struct lm_softc *sc, int n) 904 { 905 struct ksensor *sensor = &sc->sensors[n]; 906 int sdata; 907 908 /* 909 * It seems a shorted temperature diode produces an all-ones 910 * bit pattern. 911 */ 912 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 913 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 914 if (sdata == 0x1ff) { 915 sensor->flags |= SENSOR_FINVALID; 916 sensor->value = 0; 917 } else { 918 if (sdata & 0x100) 919 sdata -= 0x200; 920 sensor->flags &= ~SENSOR_FINVALID; 921 sensor->value = sdata * 500000 + 273150000; 922 } 923 } 924