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