1 /* $NetBSD: ug.c,v 1.15 2022/09/25 18:43:32 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Mihai Chelaru <kefren@netbsd.ro> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: ug.c,v 1.15 2022/09/25 18:43:32 thorpej Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/proc.h> 35 #include <sys/device.h> 36 #include <sys/errno.h> 37 #include <sys/conf.h> 38 #include <sys/envsys.h> 39 #include <sys/time.h> 40 41 #include <sys/bus.h> 42 #include <sys/intr.h> 43 44 #include <dev/isa/isareg.h> 45 #include <dev/isa/isavar.h> 46 47 #include <dev/sysmon/sysmonvar.h> 48 49 #include <dev/ic/ugreg.h> 50 #include <dev/ic/ugvar.h> 51 52 uint8_t ug_ver; 53 54 /* 55 * Imported from linux driver 56 */ 57 58 static const struct ug2_motherboard_info ug2_mb[] = { 59 { 0x000C, "unknown. Please send-pr(1)", { 60 { "CPU Core", 0, 0, 10, 1, 0 }, 61 { "DDR", 1, 0, 10, 1, 0 }, 62 { "DDR VTT", 2, 0, 10, 1, 0 }, 63 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 64 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 65 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 66 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 67 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 68 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 69 { "ATX +5V", 9, 0, 30, 1, 0 }, 70 { "+3.3V", 10, 0, 20, 1, 0 }, 71 { "5VSB", 11, 0, 30, 1, 0 }, 72 { "CPU", 24, 1, 1, 1, 0 }, 73 { "System", 25, 1, 1, 1, 0 }, 74 { "PWM", 26, 1, 1, 1, 0 }, 75 { "CPU Fan", 32, 2, 60, 1, 0 }, 76 { "NB Fan", 33, 2, 60, 1, 0 }, 77 { "SYS FAN", 34, 2, 60, 1, 0 }, 78 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 79 { NULL, 0, 0, 0, 0, 0 } } 80 }, 81 { 0x000D, "Abit AW8", { 82 { "CPU Core", 0, 0, 10, 1, 0 }, 83 { "DDR", 1, 0, 10, 1, 0 }, 84 { "DDR VTT", 2, 0, 10, 1, 0 }, 85 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 86 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 87 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 88 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 89 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 90 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 91 { "ATX +5V", 9, 0, 30, 1, 0 }, 92 { "+3.3V", 10, 0, 20, 1, 0 }, 93 { "5VSB", 11, 0, 30, 1, 0 }, 94 { "CPU", 24, 1, 1, 1, 0 }, 95 { "System", 25, 1, 1, 1, 0 }, 96 { "PWM1", 26, 1, 1, 1, 0 }, 97 { "PWM2", 27, 1, 1, 1, 0 }, 98 { "PWM3", 28, 1, 1, 1, 0 }, 99 { "PWM4", 29, 1, 1, 1, 0 }, 100 { "CPU Fan", 32, 2, 60, 1, 0 }, 101 { "NB Fan", 33, 2, 60, 1, 0 }, 102 { "SYS Fan", 34, 2, 60, 1, 0 }, 103 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 104 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 105 { "AUX3 Fan", 37, 2, 60, 1, 0 }, 106 { "AUX4 Fan", 38, 2, 60, 1, 0 }, 107 { "AUX5 Fan", 39, 2, 60, 1, 0 }, 108 { NULL, 0, 0, 0, 0, 0 } } 109 }, 110 { 0x000E, "Abit AL8", { 111 { "CPU Core", 0, 0, 10, 1, 0 }, 112 { "DDR", 1, 0, 10, 1, 0 }, 113 { "DDR VTT", 2, 0, 10, 1, 0 }, 114 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 115 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 116 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 117 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 118 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 119 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 120 { "ATX +5V", 9, 0, 30, 1, 0 }, 121 { "+3.3V", 10, 0, 20, 1, 0 }, 122 { "5VSB", 11, 0, 30, 1, 0 }, 123 { "CPU", 24, 1, 1, 1, 0 }, 124 { "System", 25, 1, 1, 1, 0 }, 125 { "PWM", 26, 1, 1, 1, 0 }, 126 { "CPU Fan", 32, 2, 60, 1, 0 }, 127 { "NB Fan", 33, 2, 60, 1, 0 }, 128 { "SYS Fan", 34, 2, 60, 1, 0 }, 129 { NULL, 0, 0, 0, 0, 0 } } 130 }, 131 { 0x000F, "unknown. Please send-pr(1)", { 132 { "CPU Core", 0, 0, 10, 1, 0 }, 133 { "DDR", 1, 0, 10, 1, 0 }, 134 { "DDR VTT", 2, 0, 10, 1, 0 }, 135 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 136 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 137 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 138 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 139 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 140 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 141 { "ATX +5V", 9, 0, 30, 1, 0 }, 142 { "+3.3V", 10, 0, 20, 1, 0 }, 143 { "5VSB", 11, 0, 30, 1, 0 }, 144 { "CPU", 24, 1, 1, 1, 0 }, 145 { "System", 25, 1, 1, 1, 0 }, 146 { "PWM", 26, 1, 1, 1, 0 }, 147 { "CPU Fan", 32, 2, 60, 1, 0 }, 148 { "NB Fan", 33, 2, 60, 1, 0 }, 149 { "SYS Fan", 34, 2, 60, 1, 0 }, 150 { NULL, 0, 0, 0, 0, 0 } } 151 }, 152 { 0x0010, "Abit NI8 SLI GR", { 153 { "CPU Core", 0, 0, 10, 1, 0 }, 154 { "DDR", 1, 0, 10, 1, 0 }, 155 { "DDR VTT", 2, 0, 10, 1, 0 }, 156 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 157 { "NB 1.4V", 4, 0, 10, 1, 0 }, 158 { "SB 1.5V", 6, 0, 10, 1, 0 }, 159 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 160 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 161 { "ATX +5V", 9, 0, 30, 1, 0 }, 162 { "+3.3V", 10, 0, 20, 1, 0 }, 163 { "5VSB", 11, 0, 30, 1, 0 }, 164 { "CPU", 24, 1, 1, 1, 0 }, 165 { "SYS", 25, 1, 1, 1, 0 }, 166 { "PWM", 26, 1, 1, 1, 0 }, 167 { "CPU Fan", 32, 2, 60, 1, 0 }, 168 { "NB Fan", 33, 2, 60, 1, 0 }, 169 { "SYS Fan", 34, 2, 60, 1, 0 }, 170 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 171 { "OTES1 Fan", 36, 2, 60, 1, 0 }, 172 { NULL, 0, 0, 0, 0, 0 } } 173 }, 174 { 0x0011, "Abit AT8 32X", { 175 { "CPU Core", 0, 0, 10, 1, 0 }, 176 { "DDR", 1, 0, 20, 1, 0 }, 177 { "DDR VTT", 2, 0, 10, 1, 0 }, 178 { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 }, 179 { "NB 1.8V", 4, 0, 10, 1, 0 }, 180 { "NB 1.8V Dual", 5, 0, 10, 1, 0 }, 181 { "HTV 1.2", 3, 0, 10, 1, 0 }, 182 { "PCIE 1.2V", 12, 0, 10, 1, 0 }, 183 { "NB 1.2V", 13, 0, 10, 1, 0 }, 184 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 185 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 186 { "ATX +5V", 9, 0, 30, 1, 0 }, 187 { "+3.3V", 10, 0, 20, 1, 0 }, 188 { "5VSB", 11, 0, 30, 1, 0 }, 189 { "CPU", 24, 1, 1, 1, 0 }, 190 { "NB", 25, 1, 1, 1, 0 }, 191 { "System", 26, 1, 1, 1, 0 }, 192 { "PWM", 27, 1, 1, 1, 0 }, 193 { "CPU Fan", 32, 2, 60, 1, 0 }, 194 { "NB Fan", 33, 2, 60, 1, 0 }, 195 { "SYS Fan", 34, 2, 60, 1, 0 }, 196 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 197 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 198 { NULL, 0, 0, 0, 0, 0 } } 199 }, 200 { 0x0012, "unknown. Please send-pr(1)", { 201 { "CPU Core", 0, 0, 10, 1, 0 }, 202 { "DDR", 1, 0, 20, 1, 0 }, 203 { "DDR VTT", 2, 0, 10, 1, 0 }, 204 { "HyperTransport", 3, 0, 10, 1, 0 }, 205 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, 206 { "NB", 4, 0, 10, 1, 0 }, 207 { "SB", 6, 0, 10, 1, 0 }, 208 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 209 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 210 { "ATX +5V", 9, 0, 30, 1, 0 }, 211 { "+3.3V", 10, 0, 20, 1, 0 }, 212 { "5VSB", 11, 0, 30, 1, 0 }, 213 { "CPU", 24, 1, 1, 1, 0 }, 214 { "SYS", 25, 1, 1, 1, 0 }, 215 { "PWM", 26, 1, 1, 1, 0 }, 216 { "CPU Fan", 32, 2, 60, 1, 0 }, 217 { "NB Fan", 33, 2, 60, 1, 0 }, 218 { "SYS Fan", 34, 2, 60, 1, 0 }, 219 { "AUX1 Fan", 36, 2, 60, 1, 0 }, 220 { NULL, 0, 0, 0, 0, 0 } } 221 }, 222 { 0x0013, "unknown. Please send-pr(1)", { 223 { "CPU Core", 0, 0, 10, 1, 0 }, 224 { "DDR", 1, 0, 10, 1, 0 }, 225 { "DDR VTT", 2, 0, 10, 1, 0 }, 226 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 227 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 228 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 229 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 230 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 231 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 232 { "ATX +5V", 9, 0, 30, 1, 0 }, 233 { "+3.3V", 10, 0, 20, 1, 0 }, 234 { "5VSB", 11, 0, 30, 1, 0 }, 235 { "CPU", 24, 1, 1, 1, 0 }, 236 { "System", 25, 1, 1, 1, 0 }, 237 { "PWM1", 26, 1, 1, 1, 0 }, 238 { "PWM2", 27, 1, 1, 1, 0 }, 239 { "PWM3", 28, 1, 1, 1, 0 }, 240 { "PWM4", 29, 1, 1, 1, 0 }, 241 { "CPU Fan", 32, 2, 60, 1, 0 }, 242 { "NB Fan", 33, 2, 60, 1, 0 }, 243 { "SYS Fan", 34, 2, 60, 1, 0 }, 244 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 245 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 246 { "AUX3 Fan", 37, 2, 60, 1, 0 }, 247 { "AUX4 Fan", 38, 2, 60, 1, 0 }, 248 { NULL, 0, 0, 0, 0, 0 } } 249 }, 250 { 0x0014, "Abit AB9 Pro", { 251 { "CPU Core", 0, 0, 10, 1, 0 }, 252 { "DDR", 1, 0, 10, 1, 0 }, 253 { "DDR VTT", 2, 0, 10, 1, 0 }, 254 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 255 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 256 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 257 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 258 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 259 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 260 { "ATX +5V", 9, 0, 30, 1, 0 }, 261 { "+3.3V", 10, 0, 20, 1, 0 }, 262 { "5VSB", 11, 0, 30, 1, 0 }, 263 { "CPU", 24, 1, 1, 1, 0 }, 264 { "System", 25, 1, 1, 1, 0 }, 265 { "PWM", 26, 1, 1, 1, 0 }, 266 { "CPU Fan", 32, 2, 60, 1, 0 }, 267 { "NB Fan", 33, 2, 60, 1, 0 }, 268 { "SYS Fan", 34, 2, 60, 1, 0 }, 269 { NULL, 0, 0, 0, 0, 0 } } 270 }, 271 { 0x0015, "unknown. Please send-pr(1)", { 272 { "CPU Core", 0, 0, 10, 1, 0 }, 273 { "DDR", 1, 0, 20, 1, 0 }, 274 { "DDR VTT", 2, 0, 10, 1, 0 }, 275 { "HyperTransport", 3, 0, 10, 1, 0 }, 276 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, 277 { "NB", 4, 0, 10, 1, 0 }, 278 { "SB", 6, 0, 10, 1, 0 }, 279 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 280 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 281 { "ATX +5V", 9, 0, 30, 1, 0 }, 282 { "+3.3V", 10, 0, 20, 1, 0 }, 283 { "5VSB", 11, 0, 30, 1, 0 }, 284 { "CPU", 24, 1, 1, 1, 0 }, 285 { "SYS", 25, 1, 1, 1, 0 }, 286 { "PWM", 26, 1, 1, 1, 0 }, 287 { "CPU Fan", 32, 2, 60, 1, 0 }, 288 { "NB Fan", 33, 2, 60, 1, 0 }, 289 { "SYS Fan", 34, 2, 60, 1, 0 }, 290 { "AUX1 Fan", 33, 2, 60, 1, 0 }, 291 { "AUX2 Fan", 35, 2, 60, 1, 0 }, 292 { "AUX3 Fan", 36, 2, 60, 1, 0 }, 293 { NULL, 0, 0, 0, 0, 0 } } 294 }, 295 { 0x0016, "generic", { 296 { "CPU Core", 0, 0, 10, 1, 0 }, 297 { "DDR", 1, 0, 20, 1, 0 }, 298 { "DDR VTT", 2, 0, 10, 1, 0 }, 299 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 300 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 301 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 302 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 303 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 304 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 305 { "ATX +5V", 9, 0, 30, 1, 0 }, 306 { "+3.3V", 10, 0, 20, 1, 0 }, 307 { "5VSB", 11, 0, 30, 1, 0 }, 308 { "CPU", 24, 1, 1, 1, 0 }, 309 { "System", 25, 1, 1, 1, 0 }, 310 { "PWM", 26, 1, 1, 1, 0 }, 311 { "CPU Fan", 32, 2, 60, 1, 0 }, 312 { "NB Fan", 33, 2, 60, 1, 0 }, 313 { "SYS FAN", 34, 2, 60, 1, 0 }, 314 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 315 { NULL, 0, 0, 0, 0, 0 } } 316 }, 317 { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } } 318 }; 319 320 321 int 322 ug_reset(struct ug_softc *sc) 323 { 324 int cnt = 0; 325 326 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) != 0x08) { 327 /* 8 meaning Voodoo */ 328 329 if (cnt++ > UG_DELAY_CYCLES) 330 return 0; 331 332 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0); 333 334 /* Wait for 0x09 at Data Port */ 335 if (!ug_waitfor(sc, UG_DATA, 0x09)) 336 return 0; 337 338 /* Wait for 0xAC at Cmd Port */ 339 if (!ug_waitfor(sc, UG_CMD, 0xAC)) 340 return 0; 341 } 342 343 return 1; 344 } 345 346 uint8_t 347 ug_read(struct ug_softc *sc, unsigned short sensor) 348 { 349 uint8_t bank, sens, rv; 350 351 bank = (sensor & 0xFF00) >> 8; 352 sens = sensor & 0x00FF; 353 354 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, bank); 355 356 /* Wait 8 at Data Port */ 357 if (!ug_waitfor(sc, UG_DATA, 8)) 358 return 0; 359 360 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, sens); 361 362 /* Wait 1 at Data Port */ 363 if (!ug_waitfor(sc, UG_DATA, 1)) 364 return 0; 365 366 /* Finally read the sensor */ 367 rv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD); 368 369 ug_reset(sc); 370 371 return rv; 372 } 373 374 int 375 ug_waitfor(struct ug_softc *sc, uint16_t offset, uint8_t value) 376 { 377 int cnt = 0; 378 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset) != value) { 379 if (cnt++ > UG_DELAY_CYCLES) 380 return 0; 381 } 382 return 1; 383 } 384 385 void 386 ug_setup_sensors(struct ug_softc *sc) 387 { 388 int i; 389 390 /* Setup Temps */ 391 for (i = 0; i < UG_VOLT_MIN; i++) 392 sc->sc_sensor[i].units = ENVSYS_STEMP; 393 394 #define COPYDESCR(x, y) \ 395 do { \ 396 strlcpy((x), (y), sizeof(x)); \ 397 } while (0) 398 399 COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp"); 400 COPYDESCR(sc->sc_sensor[1].desc, "SYS Temp"); 401 COPYDESCR(sc->sc_sensor[2].desc, "PWN Temp"); 402 403 /* Right, Now setup U sensors */ 404 405 for (i = UG_VOLT_MIN; i < UG_FAN_MIN; i++) { 406 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 407 sc->sc_sensor[i].rfact = UG_RFACT; 408 } 409 410 COPYDESCR(sc->sc_sensor[3].desc, "HTVdd"); 411 COPYDESCR(sc->sc_sensor[4].desc, "VCore"); 412 COPYDESCR(sc->sc_sensor[5].desc, "DDRVdd"); 413 COPYDESCR(sc->sc_sensor[6].desc, "Vdd3V3"); 414 COPYDESCR(sc->sc_sensor[7].desc, "Vdd5V"); 415 COPYDESCR(sc->sc_sensor[8].desc, "NBVdd"); 416 COPYDESCR(sc->sc_sensor[9].desc, "AGPVdd"); 417 COPYDESCR(sc->sc_sensor[10].desc, "DDRVtt"); 418 COPYDESCR(sc->sc_sensor[11].desc, "Vdd5VSB"); 419 COPYDESCR(sc->sc_sensor[12].desc, "Vdd3VDual"); 420 COPYDESCR(sc->sc_sensor[13].desc, "SBVdd"); 421 422 /* Fan sensors */ 423 for (i = UG_FAN_MIN; i < UG_NUM_SENSORS; i++) 424 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 425 426 COPYDESCR(sc->sc_sensor[14].desc, "CPU Fan"); 427 COPYDESCR(sc->sc_sensor[15].desc, "NB Fan"); 428 COPYDESCR(sc->sc_sensor[16].desc, "SYS Fan"); 429 COPYDESCR(sc->sc_sensor[17].desc, "AUX Fan 1"); 430 COPYDESCR(sc->sc_sensor[18].desc, "AUX Fan 2"); 431 432 /* All sensors */ 433 for (i = 0; i < UG_NUM_SENSORS; i++) 434 sc->sc_sensor[i].units = ENVSYS_SINVALID; 435 } 436 437 void 438 ug_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 439 { 440 struct ug_softc *sc = sme->sme_cookie; 441 442 /* Sensors return C while we need uK */ 443 444 if (edata->sensor < UG_VOLT_MIN - 1) /* CPU and SYS Temps */ 445 edata->value_cur = ug_read(sc, UG_CPUTEMP + edata->sensor) 446 * 1000000 + 273150000; 447 else if (edata->sensor == 2) /* PWMTEMP */ 448 edata->value_cur = ug_read(sc, UG_PWMTEMP) 449 * 1000000 + 273150000; 450 451 /* Voltages */ 452 453 #define VOLT_SENSOR UG_HTV + edata->sensor - UG_VOLT_MIN 454 455 else 456 if ((edata->sensor >= UG_VOLT_MIN) && (edata->sensor < UG_FAN_MIN)) { 457 edata->value_cur = ug_read(sc, VOLT_SENSOR); 458 switch(VOLT_SENSOR) { 459 case UG_5V: /* 6V RFact */ 460 case UG_5VSB: 461 edata->value_cur *= UG_RFACT6; 462 break; 463 case UG_3V3: /* 4V RFact */ 464 case UG_3VDUAL: 465 edata->value_cur *= UG_RFACT4; 466 break; 467 default: /* 3V RFact */ 468 edata->value_cur *= UG_RFACT3; 469 break; 470 } 471 } else 472 473 #undef VOLT_SENSOR 474 475 /* and Fans */ 476 if (edata->sensor >= UG_FAN_MIN) 477 edata->value_cur = ug_read(sc, UG_CPUFAN + 478 edata->sensor - UG_FAN_MIN) * UG_RFACT_FAN; 479 } 480 481 void 482 ug2_attach(device_t dv) 483 { 484 struct ug_softc *sc = device_private(dv); 485 uint8_t buf[2]; 486 int i; 487 const struct ug2_motherboard_info *ai; 488 const struct ug2_sensor_info *si; 489 490 aprint_normal(": Abit uGuru 2005 system monitor\n"); 491 492 if (ug2_read(sc, UG2_MISC_BANK, UG2_BOARD_ID, 2, buf) != 2) { 493 aprint_error_dev(dv, "Cannot detect board ID. Using default\n"); 494 buf[0] = UG_MAX_MSB_BOARD; 495 buf[1] = UG_MAX_LSB_BOARD; 496 } 497 498 if (buf[0] > UG_MAX_MSB_BOARD || buf[1] > UG_MAX_LSB_BOARD || 499 buf[1] < UG_MIN_LSB_BOARD) { 500 aprint_error_dev(dv, "Invalid board ID(%X,%X). Using default\n", 501 buf[0], buf[1]); 502 buf[0] = UG_MAX_MSB_BOARD; 503 buf[1] = UG_MAX_LSB_BOARD; 504 } 505 506 ai = &ug2_mb[buf[1] - UG_MIN_LSB_BOARD]; 507 508 aprint_normal_dev(dv, "mainboard %s (%.2X%.2X)\n", 509 ai->name, buf[0], buf[1]); 510 511 sc->mbsens = (const void *)ai->sensors; 512 sc->sc_sme = sysmon_envsys_create(); 513 514 for (i = 0, si = ai->sensors; si && si->name; si++, i++) { 515 COPYDESCR(sc->sc_sensor[i].desc, si->name); 516 sc->sc_sensor[i].rfact = 1; 517 sc->sc_sensor[i].state = ENVSYS_SVALID; 518 switch (si->type) { 519 case UG2_VOLTAGE_SENSOR: 520 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 521 sc->sc_sensor[i].rfact = UG_RFACT; 522 break; 523 case UG2_TEMP_SENSOR: 524 sc->sc_sensor[i].units = ENVSYS_STEMP; 525 break; 526 case UG2_FAN_SENSOR: 527 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 528 break; 529 default: 530 break; 531 } 532 if (sysmon_envsys_sensor_attach(sc->sc_sme, 533 &sc->sc_sensor[i])) { 534 sysmon_envsys_destroy(sc->sc_sme); 535 return; 536 } 537 } 538 #undef COPYDESCR 539 540 sc->sc_sme->sme_name = device_xname(dv); 541 sc->sc_sme->sme_cookie = sc; 542 sc->sc_sme->sme_refresh = ug2_refresh; 543 544 if (sysmon_envsys_register(sc->sc_sme)) { 545 aprint_error_dev(dv, "unable to register with sysmon\n"); 546 sysmon_envsys_destroy(sc->sc_sme); 547 } 548 } 549 550 void 551 ug2_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 552 { 553 struct ug_softc *sc = sme->sme_cookie; 554 const struct ug2_sensor_info *si = 555 (const struct ug2_sensor_info *)sc->mbsens; 556 int rfact = 1; 557 uint8_t v; 558 559 si += edata->sensor; 560 561 #define SENSOR_VALUE (v * si->multiplier * rfact / si->divisor + si->offset) 562 563 if (ug2_read(sc, UG2_SENSORS_BANK, UG2_VALUES_OFFSET + 564 si->port, 1, &v) == 1) { 565 switch (si->type) { 566 case UG2_TEMP_SENSOR: 567 edata->value_cur = SENSOR_VALUE * 1000000 568 + 273150000; 569 break; 570 case UG2_VOLTAGE_SENSOR: 571 rfact = UG_RFACT; 572 edata->value_cur = SENSOR_VALUE; 573 break; 574 default: 575 edata->value_cur = SENSOR_VALUE; 576 break; 577 } 578 } 579 #undef SENSOR_VALUE 580 } 581 582 static int 583 ug2_wait_ready(bus_space_tag_t iot, bus_space_handle_t ioh) 584 { 585 int cnt = 0; 586 587 bus_space_write_1(iot, ioh, UG_DATA, 0x1a); 588 while (bus_space_read_1(iot, ioh, UG_DATA) & 589 UG2_STATUS_BUSY) { 590 if (cnt++ > UG_DELAY_CYCLES) 591 return 0; 592 } 593 return 1; 594 } 595 596 static int 597 ug2_wait_readable(bus_space_tag_t iot, bus_space_handle_t ioh) 598 { 599 int cnt = 0; 600 601 while (!(bus_space_read_1(iot, ioh, UG_DATA) & 602 UG2_STATUS_READY_FOR_READ)) { 603 if (cnt++ > UG_DELAY_CYCLES) 604 return 0; 605 } 606 return 1; 607 } 608 609 int 610 ug2_sync(bus_space_tag_t iot, bus_space_handle_t ioh) 611 { 612 int cnt = 0; 613 614 #define UG2_WAIT_READY if(ug2_wait_ready(iot, ioh) == 0) return 0; 615 616 /* Don't sync two times in a row */ 617 if (ug_ver != 0) { 618 ug_ver = 0; 619 return 1; 620 } 621 622 UG2_WAIT_READY; 623 bus_space_write_1(iot, ioh, UG_DATA, 0x20); 624 UG2_WAIT_READY; 625 bus_space_write_1(iot, ioh, UG_CMD, 0x10); 626 UG2_WAIT_READY; 627 bus_space_write_1(iot, ioh, UG_CMD, 0x00); 628 UG2_WAIT_READY; 629 if (ug2_wait_readable(iot, ioh) == 0) 630 return 0; 631 while (bus_space_read_1(iot, ioh, UG_CMD) != 0xAC) 632 if (cnt++ > UG_DELAY_CYCLES) 633 return 0; 634 return 1; 635 } 636 637 int 638 ug2_read(struct ug_softc *sc, uint8_t bank, uint8_t offset, uint8_t count, 639 uint8_t *ret) 640 { 641 int i; 642 bus_space_tag_t iot = sc->sc_iot; 643 bus_space_handle_t ioh = sc->sc_ioh; 644 645 if (ug2_sync(iot, ioh) == 0) 646 return 0; 647 648 bus_space_write_1(iot, ioh, UG_DATA, 0x1A); 649 UG2_WAIT_READY; 650 bus_space_write_1(iot, ioh, UG_CMD, bank); 651 UG2_WAIT_READY; 652 bus_space_write_1(iot, ioh, UG_CMD, offset); 653 UG2_WAIT_READY; 654 bus_space_write_1(iot, ioh, UG_CMD, count); 655 UG2_WAIT_READY; 656 657 #undef UG2_WAIT_READY 658 659 /* Now wait for the results */ 660 for (i = 0; i < count; i++) { 661 if (ug2_wait_readable(sc->sc_iot, sc->sc_ioh) == 0) 662 break; 663 ret[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD); 664 } 665 666 return i; 667 } 668