1 /* $OpenBSD: lm78.c,v 1.26 2022/04/08 15:02:28 naddy 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 *, const 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 const struct lm_chip lm_chips[] = { 78 { wb_match }, 79 { lm_match }, 80 { def_match } /* Must be last */ 81 }; 82 83 const 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 const 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 const 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 const 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 const 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 /* NCT6779D */ 219 const struct lm_sensor nct6779d_sensors[] = { 220 /* Voltage */ 221 { "VCore", SENSOR_VOLTS_DC, 4, 0x80, lm_refresh_volt, RFACT_NONE }, 222 { "VIN1", SENSOR_VOLTS_DC, 4, 0x81, lm_refresh_volt, RFACT(56, 10) / 2 }, 223 { "AVCC", SENSOR_VOLTS_DC, 4, 0x82, lm_refresh_volt, RFACT(34, 34) / 2 }, 224 { "+3.3V", SENSOR_VOLTS_DC, 4, 0x83, lm_refresh_volt, RFACT(34, 34) / 2 }, 225 { "VIN0", SENSOR_VOLTS_DC, 4, 0x84, lm_refresh_volt, RFACT(48600, 10000) }, 226 { "VIN8", SENSOR_VOLTS_DC, 4, 0x85, lm_refresh_volt, RFACT_NONE / 2 }, 227 { "VIN4", SENSOR_VOLTS_DC, 4, 0x86, lm_refresh_volt, RFACT_NONE / 2 }, 228 { "+3.3VSB", SENSOR_VOLTS_DC, 4, 0x87, lm_refresh_volt, RFACT(34, 34) / 2 }, 229 { "VBAT", SENSOR_VOLTS_DC, 4, 0x88, lm_refresh_volt, RFACT_NONE }, 230 { "VTT", SENSOR_VOLTS_DC, 4, 0x89, lm_refresh_volt, RFACT_NONE }, 231 { "VIN5", SENSOR_VOLTS_DC, 4, 0x8a, lm_refresh_volt, RFACT_NONE / 2 }, 232 { "VIN6", SENSOR_VOLTS_DC, 4, 0x8b, lm_refresh_volt, RFACT_NONE / 2 }, 233 { "VIN2", SENSOR_VOLTS_DC, 4, 0x8c, lm_refresh_volt, RFACT_NONE }, 234 { "VIN3", SENSOR_VOLTS_DC, 4, 0x8d, lm_refresh_volt, RFACT(14414, 10000) }, 235 { "VIN7", SENSOR_VOLTS_DC, 4, 0x8e, lm_refresh_volt, RFACT_NONE / 2 }, 236 237 /* Temperature */ 238 { "MB Temperature", SENSOR_TEMP, 4, 0x90, lm_refresh_temp, 0 }, 239 { "CPU Temperature", SENSOR_TEMP, 4, 0x91, wb_refresh_temp, 0 }, 240 { "Aux Temp0", SENSOR_TEMP, 4, 0x92, wb_refresh_temp, 0 }, 241 { "Aux Temp1", SENSOR_TEMP, 4, 0x93, wb_refresh_temp, 0 }, 242 { "Aux Temp2", SENSOR_TEMP, 4, 0x94, wb_refresh_temp, 0 }, 243 { "Aux Temp3", SENSOR_TEMP, 4, 0x95, wb_refresh_temp, 0 }, 244 245 /* Fans */ 246 { "System Fan", SENSOR_FANRPM, 4, 0xc0, wb_nct6776f_refresh_fanrpm, 0 }, 247 { "CPU Fan", SENSOR_FANRPM, 4, 0xc2, wb_nct6776f_refresh_fanrpm, 0 }, 248 { "Aux Fan0", SENSOR_FANRPM, 4, 0xc4, wb_nct6776f_refresh_fanrpm, 0 }, 249 { "Aux Fan1", SENSOR_FANRPM, 4, 0xc6, wb_nct6776f_refresh_fanrpm, 0 }, 250 { "Aux Fan2", SENSOR_FANRPM, 4, 0xc8, wb_nct6776f_refresh_fanrpm, 0 }, 251 252 { NULL } 253 }; 254 255 const struct lm_sensor w83637hf_sensors[] = { 256 /* Voltage */ 257 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore }, 258 { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) }, 259 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 260 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) }, 261 { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) }, 262 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) }, 263 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 264 265 /* Temperature */ 266 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 267 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 268 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 269 270 /* Fans */ 271 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 272 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 273 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 274 275 { NULL } 276 }; 277 278 const struct lm_sensor w83697hf_sensors[] = { 279 /* Voltage */ 280 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 281 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 282 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 283 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 284 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 285 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 286 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) }, 287 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 288 289 /* Temperature */ 290 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 291 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 292 293 /* Fans */ 294 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 295 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 296 297 { NULL } 298 }; 299 300 /* 301 * The datasheet doesn't mention the (internal) resistors used for the 302 * +5V, but using the values from the W83782D datasheets seems to 303 * provide sensible results. 304 */ 305 const struct lm_sensor w83781d_sensors[] = { 306 /* Voltage */ 307 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 308 { "VCore B", 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, lm_refresh_volt, NRFACT(2100, 604) }, 313 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) }, 314 315 /* Temperature */ 316 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 317 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 318 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 319 320 /* Fans */ 321 { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm }, 322 { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm }, 323 { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm }, 324 325 { NULL } 326 }; 327 328 const struct lm_sensor w83782d_sensors[] = { 329 /* Voltage */ 330 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 331 { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 332 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 333 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 334 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 335 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 336 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 337 { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) }, 338 { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE }, 339 340 /* Temperature */ 341 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 342 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 343 { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp }, 344 345 /* Fans */ 346 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 347 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 348 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 349 350 { NULL } 351 }; 352 353 const struct lm_sensor w83783s_sensors[] = { 354 /* Voltage */ 355 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 356 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 357 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 358 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 359 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 360 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 361 362 /* Temperature */ 363 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 364 { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp }, 365 366 /* Fans */ 367 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 368 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 369 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 370 371 { NULL } 372 }; 373 374 const struct lm_sensor w83791d_sensors[] = { 375 /* Voltage */ 376 { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 }, 377 { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 }, 378 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 }, 379 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 380 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 381 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 382 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 383 { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) }, 384 { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE }, 385 { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE }, 386 387 /* Temperature */ 388 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 389 { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp }, 390 { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp }, 391 392 /* Fans */ 393 { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm }, 394 { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm }, 395 { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm }, 396 { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm }, 397 { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm }, 398 399 { NULL } 400 }; 401 402 const struct lm_sensor w83792d_sensors[] = { 403 /* Voltage */ 404 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 405 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 406 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 407 { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) }, 408 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 409 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 410 { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) }, 411 { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) }, 412 { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE }, 413 414 /* Temperature */ 415 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 416 { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp }, 417 { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp }, 418 419 /* Fans */ 420 { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm }, 421 { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm }, 422 { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm }, 423 { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm }, 424 { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm }, 425 { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm }, 426 { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm }, 427 428 { NULL } 429 }; 430 431 const struct lm_sensor as99127f_sensors[] = { 432 /* Voltage */ 433 { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE }, 434 { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE }, 435 { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE }, 436 { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) }, 437 { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) }, 438 { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) }, 439 { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) }, 440 441 /* Temperature */ 442 { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp }, 443 { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp }, 444 { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp }, 445 446 /* Fans */ 447 { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm }, 448 { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm }, 449 { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm }, 450 451 { NULL } 452 }; 453 454 void 455 lm_attach(struct lm_softc *sc) 456 { 457 u_int i, config; 458 459 for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++) 460 if (lm_chips[i].chip_match(sc)) 461 break; 462 463 /* No point in doing anything if we don't have any sensors. */ 464 if (sc->numsensors == 0) 465 return; 466 467 sc->sensortask = sensor_task_register(sc, lm_refresh, 5); 468 if (sc->sensortask == NULL) { 469 printf("%s: unable to register update task\n", 470 sc->sc_dev.dv_xname); 471 return; 472 } 473 474 /* Start the monitoring loop */ 475 config = sc->lm_readreg(sc, LM_CONFIG); 476 sc->lm_writereg(sc, LM_CONFIG, config | 0x01); 477 478 /* Add sensors */ 479 for (i = 0; i < sc->numsensors; ++i) 480 sensor_attach(&sc->sensordev, &sc->sensors[i]); 481 sensordev_install(&sc->sensordev); 482 } 483 484 int 485 lm_match(struct lm_softc *sc) 486 { 487 int chipid; 488 489 /* See if we have an LM78 or LM79. */ 490 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 491 switch(chipid) { 492 case LM_CHIPID_LM78: 493 printf(": LM78\n"); 494 break; 495 case LM_CHIPID_LM78J: 496 printf(": LM78J\n"); 497 break; 498 case LM_CHIPID_LM79: 499 printf(": LM79\n"); 500 break; 501 case LM_CHIPID_LM81: 502 printf(": LM81\n"); 503 break; 504 default: 505 return 0; 506 } 507 508 lm_setup_sensors(sc, lm78_sensors); 509 sc->refresh_sensor_data = lm_refresh_sensor_data; 510 return 1; 511 } 512 513 int 514 def_match(struct lm_softc *sc) 515 { 516 int chipid; 517 518 chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK; 519 printf(": unknown chip (ID %d)\n", chipid); 520 521 lm_setup_sensors(sc, lm78_sensors); 522 sc->refresh_sensor_data = lm_refresh_sensor_data; 523 return 1; 524 } 525 526 int 527 wb_match(struct lm_softc *sc) 528 { 529 int banksel, vendid, devid; 530 531 /* Read vendor ID */ 532 banksel = sc->lm_readreg(sc, WB_BANKSEL); 533 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC); 534 vendid = sc->lm_readreg(sc, WB_VENDID) << 8; 535 sc->lm_writereg(sc, WB_BANKSEL, 0); 536 vendid |= sc->lm_readreg(sc, WB_VENDID); 537 sc->lm_writereg(sc, WB_BANKSEL, banksel); 538 DPRINTF((" winbond vend id 0x%x\n", vendid)); 539 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS) 540 return 0; 541 542 /* Read device/chip ID */ 543 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 544 devid = sc->lm_readreg(sc, LM_CHIPID); 545 sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID); 546 sc->lm_writereg(sc, WB_BANKSEL, banksel); 547 DPRINTF((" winbond chip id 0x%x\n", sc->chipid)); 548 switch(sc->chipid) { 549 case WB_CHIPID_W83627HF: 550 printf(": W83627HF\n"); 551 lm_setup_sensors(sc, w83627hf_sensors); 552 break; 553 case WB_CHIPID_W83627THF: 554 printf(": W83627THF\n"); 555 lm_setup_sensors(sc, w83637hf_sensors); 556 break; 557 case WB_CHIPID_W83627EHF_A: 558 printf(": W83627EHF-A\n"); 559 lm_setup_sensors(sc, w83627ehf_sensors); 560 break; 561 case WB_CHIPID_W83627EHF: 562 printf(": W83627EHF\n"); 563 lm_setup_sensors(sc, w83627ehf_sensors); 564 break; 565 case WB_CHIPID_W83627DHG: 566 switch (sc->sioid) { 567 case WBSIO_ID_NCT6775F: 568 printf(": NCT6775F\n"); 569 lm_setup_sensors(sc, nct6776f_sensors); 570 break; 571 case WBSIO_ID_NCT6776F: 572 printf(": NCT6776F\n"); 573 lm_setup_sensors(sc, nct6776f_sensors); 574 break; 575 case WBSIO_ID_NCT5104D: 576 printf(": NCT5104D\n"); 577 lm_setup_sensors(sc, nct6776f_sensors); 578 break; 579 case WBSIO_ID_NCT6779D: 580 printf(": NCT6779D\n"); 581 lm_setup_sensors(sc, nct6779d_sensors); 582 break; 583 case WBSIO_ID_NCT6791D: 584 printf(": NCT6791D\n"); 585 lm_setup_sensors(sc, nct6779d_sensors); 586 break; 587 case WBSIO_ID_NCT6792D: 588 printf(": NCT6792D\n"); 589 lm_setup_sensors(sc, nct6779d_sensors); 590 break; 591 case WBSIO_ID_NCT6793D: 592 printf(": NCT6793D\n"); 593 lm_setup_sensors(sc, nct6779d_sensors); 594 break; 595 case WBSIO_ID_NCT6795D: 596 printf(": NCT6795D\n"); 597 lm_setup_sensors(sc, nct6779d_sensors); 598 break; 599 default: 600 printf(": W83627DHG\n"); 601 lm_setup_sensors(sc, w83627dhg_sensors); 602 } 603 break; 604 case WB_CHIPID_W83637HF: 605 printf(": W83637HF\n"); 606 sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0); 607 if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9) 608 sc->vrm9 = 1; 609 sc->lm_writereg(sc, WB_BANKSEL, banksel); 610 lm_setup_sensors(sc, w83637hf_sensors); 611 break; 612 case WB_CHIPID_W83697HF: 613 printf(": W83697HF\n"); 614 lm_setup_sensors(sc, w83697hf_sensors); 615 break; 616 case WB_CHIPID_W83781D: 617 case WB_CHIPID_W83781D_2: 618 printf(": W83781D\n"); 619 lm_setup_sensors(sc, w83781d_sensors); 620 break; 621 case WB_CHIPID_W83782D: 622 printf(": W83782D\n"); 623 lm_setup_sensors(sc, w83782d_sensors); 624 break; 625 case WB_CHIPID_W83783S: 626 printf(": W83783S\n"); 627 lm_setup_sensors(sc, w83783s_sensors); 628 break; 629 case WB_CHIPID_W83791D: 630 printf(": W83791D\n"); 631 lm_setup_sensors(sc, w83791d_sensors); 632 break; 633 case WB_CHIPID_W83791SD: 634 printf(": W83791SD\n"); 635 break; 636 case WB_CHIPID_W83792D: 637 if (devid >= 0x10 && devid <= 0x29) 638 printf(": W83792D rev %c\n", 'A' + devid - 0x10); 639 else 640 printf(": W83792D rev 0x%x\n", devid); 641 lm_setup_sensors(sc, w83792d_sensors); 642 break; 643 case WB_CHIPID_AS99127F: 644 if (vendid == WB_VENDID_ASUS) { 645 printf(": AS99127F\n"); 646 lm_setup_sensors(sc, w83781d_sensors); 647 } else { 648 printf(": AS99127F rev 2\n"); 649 lm_setup_sensors(sc, as99127f_sensors); 650 } 651 break; 652 default: 653 printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid); 654 /* Handle as a standard LM78. */ 655 lm_setup_sensors(sc, lm78_sensors); 656 sc->refresh_sensor_data = lm_refresh_sensor_data; 657 return 1; 658 } 659 660 sc->refresh_sensor_data = wb_refresh_sensor_data; 661 return 1; 662 } 663 664 void 665 lm_setup_sensors(struct lm_softc *sc, const struct lm_sensor *sensors) 666 { 667 int i; 668 669 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 670 sizeof(sc->sensordev.xname)); 671 672 for (i = 0; sensors[i].desc; i++) { 673 sc->sensors[i].type = sensors[i].type; 674 strlcpy(sc->sensors[i].desc, sensors[i].desc, 675 sizeof(sc->sensors[i].desc)); 676 sc->numsensors++; 677 } 678 sc->lm_sensors = sensors; 679 } 680 681 void 682 lm_refresh(void *arg) 683 { 684 struct lm_softc *sc = arg; 685 686 sc->refresh_sensor_data(sc); 687 } 688 689 void 690 lm_refresh_sensor_data(struct lm_softc *sc) 691 { 692 int i; 693 694 for (i = 0; i < sc->numsensors; i++) 695 sc->lm_sensors[i].refresh(sc, i); 696 } 697 698 void 699 lm_refresh_volt(struct lm_softc *sc, int n) 700 { 701 struct ksensor *sensor = &sc->sensors[n]; 702 int data; 703 704 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 705 sensor->value = (data << 4); 706 sensor->value *= sc->lm_sensors[n].rfact; 707 sensor->value /= 10; 708 } 709 710 void 711 lm_refresh_temp(struct lm_softc *sc, int n) 712 { 713 struct ksensor *sensor = &sc->sensors[n]; 714 int sdata; 715 716 /* 717 * The data sheet suggests that the range of the temperature 718 * sensor is between -55 degC and +125 degC. 719 */ 720 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 721 if (sdata > 0x7d && sdata < 0xc9) { 722 sensor->flags |= SENSOR_FINVALID; 723 sensor->value = 0; 724 } else { 725 if (sdata & 0x80) 726 sdata -= 0x100; 727 sensor->flags &= ~SENSOR_FINVALID; 728 sensor->value = sdata * 1000000 + 273150000; 729 } 730 } 731 732 void 733 lm_refresh_fanrpm(struct lm_softc *sc, int n) 734 { 735 struct ksensor *sensor = &sc->sensors[n]; 736 int data, divisor = 1; 737 738 /* 739 * We might get more accurate fan readings by adjusting the 740 * divisor, but that might interfere with APM or other SMM 741 * BIOS code reading the fan speeds. 742 */ 743 744 /* FAN3 has a fixed fan divisor. */ 745 if (sc->lm_sensors[n].reg == LM_FAN1 || 746 sc->lm_sensors[n].reg == LM_FAN2) { 747 data = sc->lm_readreg(sc, LM_VIDFAN); 748 if (sc->lm_sensors[n].reg == LM_FAN1) 749 divisor = (data >> 4) & 0x03; 750 else 751 divisor = (data >> 6) & 0x03; 752 } 753 754 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 755 if (data == 0xff || data == 0x00) { 756 sensor->flags |= SENSOR_FINVALID; 757 sensor->value = 0; 758 } else { 759 sensor->flags &= ~SENSOR_FINVALID; 760 sensor->value = 1350000 / (data << divisor); 761 } 762 } 763 764 void 765 wb_refresh_sensor_data(struct lm_softc *sc) 766 { 767 int banksel, bank, i; 768 769 /* 770 * Properly save and restore bank selection register. 771 */ 772 773 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL); 774 for (i = 0; i < sc->numsensors; i++) { 775 if (bank != sc->lm_sensors[i].bank) { 776 bank = sc->lm_sensors[i].bank; 777 sc->lm_writereg(sc, WB_BANKSEL, bank); 778 } 779 sc->lm_sensors[i].refresh(sc, i); 780 } 781 sc->lm_writereg(sc, WB_BANKSEL, banksel); 782 } 783 784 void 785 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n) 786 { 787 struct ksensor *sensor = &sc->sensors[n]; 788 int data; 789 790 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 791 792 /* 793 * Depending on the voltage detection method, 794 * one of the following formulas is used: 795 * VRM8 method: value = raw * 0.016V 796 * VRM9 method: value = raw * 0.00488V + 0.70V 797 */ 798 if (sc->vrm9) 799 sensor->value = (data * 4880) + 700000; 800 else 801 sensor->value = (data * 16000); 802 } 803 804 void 805 wb_refresh_nvolt(struct lm_softc *sc, int n) 806 { 807 struct ksensor *sensor = &sc->sensors[n]; 808 int data; 809 810 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 811 sensor->value = ((data << 4) - WB_VREF); 812 sensor->value *= sc->lm_sensors[n].rfact; 813 sensor->value /= 10; 814 sensor->value += WB_VREF * 1000; 815 } 816 817 void 818 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n) 819 { 820 struct ksensor *sensor = &sc->sensors[n]; 821 int data; 822 823 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 824 sensor->value = ((data << 3) - WB_W83627EHF_VREF); 825 sensor->value *= RFACT(232, 10); 826 sensor->value /= 10; 827 sensor->value += WB_W83627EHF_VREF * 1000; 828 } 829 830 void 831 wb_refresh_temp(struct lm_softc *sc, int n) 832 { 833 struct ksensor *sensor = &sc->sensors[n]; 834 int sdata; 835 836 /* 837 * The data sheet suggests that the range of the temperature 838 * sensor is between -55 degC and +125 degC. However, values 839 * around -48 degC seem to be a very common bogus values. 840 * Since such values are unreasonably low, we use -45 degC for 841 * the lower limit instead. 842 */ 843 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 844 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 845 if (sdata > 0x0fa && sdata < 0x1a6) { 846 sensor->flags |= SENSOR_FINVALID; 847 sensor->value = 0; 848 } else { 849 if (sdata & 0x100) 850 sdata -= 0x200; 851 sensor->flags &= ~SENSOR_FINVALID; 852 sensor->value = sdata * 500000 + 273150000; 853 } 854 } 855 856 void 857 wb_refresh_fanrpm(struct lm_softc *sc, int n) 858 { 859 struct ksensor *sensor = &sc->sensors[n]; 860 int fan, data, divisor = 0; 861 862 /* 863 * This is madness; the fan divisor bits are scattered all 864 * over the place. 865 */ 866 867 if (sc->lm_sensors[n].reg == LM_FAN1 || 868 sc->lm_sensors[n].reg == LM_FAN2 || 869 sc->lm_sensors[n].reg == LM_FAN3) { 870 data = sc->lm_readreg(sc, WB_BANK0_VBAT); 871 fan = (sc->lm_sensors[n].reg - LM_FAN1); 872 if ((data >> 5) & (1 << fan)) 873 divisor |= 0x04; 874 } 875 876 if (sc->lm_sensors[n].reg == LM_FAN1 || 877 sc->lm_sensors[n].reg == LM_FAN2) { 878 data = sc->lm_readreg(sc, LM_VIDFAN); 879 if (sc->lm_sensors[n].reg == LM_FAN1) 880 divisor |= (data >> 4) & 0x03; 881 else 882 divisor |= (data >> 6) & 0x03; 883 } else if (sc->lm_sensors[n].reg == LM_FAN3) { 884 data = sc->lm_readreg(sc, WB_PIN); 885 divisor |= (data >> 6) & 0x03; 886 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 || 887 sc->lm_sensors[n].reg == WB_BANK0_FAN5) { 888 data = sc->lm_readreg(sc, WB_BANK0_FAN45); 889 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4) 890 divisor |= (data >> 0) & 0x07; 891 else 892 divisor |= (data >> 4) & 0x07; 893 } 894 895 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 896 if (data == 0xff || data == 0x00) { 897 sensor->flags |= SENSOR_FINVALID; 898 sensor->value = 0; 899 } else { 900 sensor->flags &= ~SENSOR_FINVALID; 901 sensor->value = 1350000 / (data << divisor); 902 } 903 } 904 905 void 906 wb_nct6776f_refresh_fanrpm(struct lm_softc *sc, int n) 907 { 908 struct ksensor *sensor = &sc->sensors[n]; 909 int datah, datal; 910 911 datah = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 912 datal = sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1); 913 914 if (datah == 0xff) { 915 sensor->flags |= SENSOR_FINVALID; 916 sensor->value = 0; 917 } else { 918 sensor->flags &= ~SENSOR_FINVALID; 919 sensor->value = (datah << 8) | datal; 920 } 921 } 922 923 void 924 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n) 925 { 926 struct ksensor *sensor = &sc->sensors[n]; 927 int reg, shift, data, divisor = 1; 928 929 switch (sc->lm_sensors[n].reg) { 930 case 0x28: 931 reg = 0x47; shift = 0; 932 break; 933 case 0x29: 934 reg = 0x47; shift = 4; 935 break; 936 case 0x2a: 937 reg = 0x5b; shift = 0; 938 break; 939 case 0xb8: 940 reg = 0x5b; shift = 4; 941 break; 942 case 0xb9: 943 reg = 0x5c; shift = 0; 944 break; 945 case 0xba: 946 reg = 0x5c; shift = 4; 947 break; 948 case 0xbe: 949 reg = 0x9e; shift = 0; 950 break; 951 default: 952 reg = 0; 953 break; 954 } 955 956 data = sc->lm_readreg(sc, sc->lm_sensors[n].reg); 957 if (data == 0xff || data == 0x00) { 958 sensor->flags |= SENSOR_FINVALID; 959 sensor->value = 0; 960 } else { 961 if (reg != 0) 962 divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7; 963 sensor->flags &= ~SENSOR_FINVALID; 964 sensor->value = 1350000 / (data << divisor); 965 } 966 } 967 968 void 969 as_refresh_temp(struct lm_softc *sc, int n) 970 { 971 struct ksensor *sensor = &sc->sensors[n]; 972 int sdata; 973 974 /* 975 * It seems a shorted temperature diode produces an all-ones 976 * bit pattern. 977 */ 978 sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1; 979 sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7; 980 if (sdata == 0x1ff) { 981 sensor->flags |= SENSOR_FINVALID; 982 sensor->value = 0; 983 } else { 984 if (sdata & 0x100) 985 sdata -= 0x200; 986 sensor->flags &= ~SENSOR_FINVALID; 987 sensor->value = sdata * 500000 + 273150000; 988 } 989 } 990