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