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