1 1.1 xtraeme /* $OpenBSD: fins.c,v 1.1 2008/03/19 19:33:09 deraadt Exp $ */ 2 1.9 mlelstv /* $NetBSD: finsio_isa.c,v 1.9 2022/06/29 15:56:58 mlelstv Exp $ */ 3 1.1 xtraeme 4 1.1 xtraeme /* 5 1.1 xtraeme * Copyright (c) 2008 Juan Romero Pardines 6 1.1 xtraeme * Copyright (c) 2007, 2008 Geoff Steckel 7 1.1 xtraeme * Copyright (c) 2005, 2006 Mark Kettenis 8 1.1 xtraeme * 9 1.1 xtraeme * Permission to use, copy, modify, and distribute this software for any 10 1.1 xtraeme * purpose with or without fee is hereby granted, provided that the above 11 1.1 xtraeme * copyright notice and this permission notice appear in all copies. 12 1.1 xtraeme * 13 1.1 xtraeme * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 1.1 xtraeme * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 1.1 xtraeme * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 1.1 xtraeme * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 1.1 xtraeme * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 1.1 xtraeme * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 1.1 xtraeme * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 1.1 xtraeme */ 21 1.1 xtraeme #include <sys/cdefs.h> 22 1.9 mlelstv __KERNEL_RCSID(0, "$NetBSD: finsio_isa.c,v 1.9 2022/06/29 15:56:58 mlelstv Exp $"); 23 1.1 xtraeme 24 1.1 xtraeme #include <sys/param.h> 25 1.1 xtraeme #include <sys/systm.h> 26 1.1 xtraeme #include <sys/device.h> 27 1.6 jmcneill #include <sys/module.h> 28 1.1 xtraeme #include <sys/bus.h> 29 1.1 xtraeme 30 1.1 xtraeme #include <dev/isa/isareg.h> 31 1.1 xtraeme #include <dev/isa/isavar.h> 32 1.1 xtraeme 33 1.1 xtraeme #include <dev/sysmon/sysmonvar.h> 34 1.1 xtraeme 35 1.1 xtraeme /* Derived from LM78 code. Only handles chips attached to ISA bus */ 36 1.1 xtraeme 37 1.1 xtraeme /* 38 1.1 xtraeme * Fintek F71805/F71883 Super I/O datasheets: 39 1.1 xtraeme * http://www.fintek.com.tw/files/productfiles/F71805F_V025.pdf 40 1.1 xtraeme * http://www.fintek.com.tw/files/productfiles/F71883_V026P.pdf 41 1.1 xtraeme * 42 1.1 xtraeme * This chip is a multi-io chip with many functions. 43 1.1 xtraeme * Each function may be relocated in I/O space by the BIOS. 44 1.1 xtraeme * The base address (2E or 4E) accesses a configuration space which 45 1.1 xtraeme * has pointers to the individual functions. The config space must be 46 1.1 xtraeme * unlocked with a cookie and relocked afterwards. The chip ID is stored 47 1.1 xtraeme * in config space so it is not normally visible. 48 1.1 xtraeme * 49 1.1 xtraeme * The voltage dividers specified are from reading the chips on one board. 50 1.1 xtraeme * There is no way to determine what they are in the general case. 51 1.1 xtraeme */ 52 1.1 xtraeme 53 1.1 xtraeme #define FINSIO_UNLOCK 0x87 /* magic constant - write 2x to select chip */ 54 1.1 xtraeme #define FINSIO_LOCK 0xaa /* magic constant - write 1x to deselect reg */ 55 1.1 xtraeme 56 1.1 xtraeme #define FINSIO_FUNC_SEL 0x07 /* select which subchip to access */ 57 1.1 xtraeme # define FINSIO_FUNC_HWMON 0x4 58 1.1 xtraeme 59 1.1 xtraeme /* ISA registers index to an internal register space on chip */ 60 1.7 jakllsch #define FINSIO_DECODE_SIZE (8) 61 1.7 jakllsch #define FINSIO_DECODE_MASK (FINSIO_DECODE_SIZE - 1) 62 1.7 jakllsch #define FINSIO_ADDR 5 /* global configuration index */ 63 1.7 jakllsch #define FINSIO_DATA 6 /* and data registers */ 64 1.1 xtraeme 65 1.1 xtraeme /* Global configuration registers */ 66 1.1 xtraeme #define FINSIO_MANUF 0x23 /* manufacturer ID */ 67 1.1 xtraeme # define FINTEK_ID 0x1934 68 1.1 xtraeme #define FINSIO_CHIP 0x20 /* chip ID */ 69 1.1 xtraeme # define FINSIO_IDF71805 0x0406 70 1.1 xtraeme # define FINSIO_IDF71806 0x0341 /* F71872 and F1806 F/FG */ 71 1.1 xtraeme # define FINSIO_IDF71883 0x0541 /* F71882 and F1883 */ 72 1.1 xtraeme # define FINSIO_IDF71862 0x0601 /* F71862FG */ 73 1.6 jmcneill # define FINSIO_IDF8000 0x0581 /* F8000 */ 74 1.1 xtraeme 75 1.1 xtraeme /* in bank sensors of config space */ 76 1.1 xtraeme #define FINSIO_SENSADDR 0x60 /* sensors assigned I/O address (2 bytes) */ 77 1.1 xtraeme 78 1.1 xtraeme #define FINSIO_HWMON_CONF 0x01 /* Hardware Monitor Config. Register */ 79 1.1 xtraeme 80 1.1 xtraeme /* in sensors space */ 81 1.1 xtraeme #define FINSIO_TMODE 0x01 /* temperature mode reg */ 82 1.1 xtraeme 83 1.1 xtraeme #define FINSIO_MAX_SENSORS 20 84 1.1 xtraeme /* 85 1.1 xtraeme * Fintek chips typically measure voltages using 8mv steps. 86 1.1 xtraeme * To measure higher voltages the input is attenuated with (external) 87 1.1 xtraeme * resistors. Negative voltages are measured using inverting op amps 88 1.1 xtraeme * and resistors. So we have to convert the sensor values back to 89 1.1 xtraeme * real voltages by applying the appropriate resistor factor. 90 1.1 xtraeme */ 91 1.1 xtraeme #define FRFACT_NONE 8000 92 1.1 xtraeme #define FRFACT(x, y) (FRFACT_NONE * ((x) + (y)) / (y)) 93 1.1 xtraeme #define FNRFACT(x, y) (-FRFACT_NONE * (x) / (y)) 94 1.1 xtraeme 95 1.1 xtraeme #if defined(FINSIODEBUG) 96 1.1 xtraeme #define DPRINTF(x) do { printf x; } while (0) 97 1.1 xtraeme #else 98 1.1 xtraeme #define DPRINTF(x) 99 1.1 xtraeme #endif 100 1.1 xtraeme 101 1.1 xtraeme struct finsio_softc { 102 1.1 xtraeme bus_space_tag_t sc_iot; 103 1.1 xtraeme bus_space_handle_t sc_ioh; 104 1.1 xtraeme 105 1.1 xtraeme struct sysmon_envsys *sc_sme; 106 1.1 xtraeme envsys_data_t sc_sensor[FINSIO_MAX_SENSORS]; 107 1.1 xtraeme struct finsio_sensor *sc_finsio_sensors; 108 1.1 xtraeme 109 1.1 xtraeme u_int sc_tempsel; 110 1.1 xtraeme }; 111 1.1 xtraeme 112 1.1 xtraeme struct finsio_sensor { 113 1.1 xtraeme const char *fs_desc; 114 1.1 xtraeme u_int fs_type; 115 1.1 xtraeme uint8_t fs_aux; 116 1.1 xtraeme uint8_t fs_reg; 117 1.1 xtraeme void (*fs_refresh)(struct finsio_softc *, envsys_data_t *); 118 1.1 xtraeme int fs_rfact; 119 1.1 xtraeme }; 120 1.1 xtraeme 121 1.1 xtraeme static int finsio_isa_match(device_t, cfdata_t, void *); 122 1.1 xtraeme static void finsio_isa_attach(device_t, device_t, void *); 123 1.3 xtraeme static int finsio_isa_detach(device_t, int); 124 1.1 xtraeme 125 1.1 xtraeme static void finsio_enter(bus_space_tag_t, bus_space_handle_t); 126 1.1 xtraeme static void finsio_exit(bus_space_tag_t, bus_space_handle_t); 127 1.1 xtraeme static uint8_t finsio_readreg(bus_space_tag_t, bus_space_handle_t, int); 128 1.1 xtraeme static void finsio_writereg(bus_space_tag_t, bus_space_handle_t, int, int); 129 1.1 xtraeme 130 1.1 xtraeme static void finsio_refresh(struct sysmon_envsys *, envsys_data_t *); 131 1.1 xtraeme static void finsio_refresh_volt(struct finsio_softc *, envsys_data_t *); 132 1.1 xtraeme static void finsio_refresh_temp(struct finsio_softc *, envsys_data_t *); 133 1.1 xtraeme static void finsio_refresh_fanrpm(struct finsio_softc *, envsys_data_t *); 134 1.1 xtraeme 135 1.1 xtraeme CFATTACH_DECL_NEW(finsio, sizeof(struct finsio_softc), 136 1.3 xtraeme finsio_isa_match, finsio_isa_attach, finsio_isa_detach, NULL); 137 1.1 xtraeme 138 1.1 xtraeme /* Sensors available in F71805/F71806 */ 139 1.1 xtraeme static struct finsio_sensor f71805_sensors[] = { 140 1.1 xtraeme /* Voltage */ 141 1.1 xtraeme { 142 1.1 xtraeme .fs_desc = "+3.3V", 143 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 144 1.1 xtraeme .fs_aux = 0, 145 1.1 xtraeme .fs_reg = 0x10, 146 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 147 1.1 xtraeme .fs_rfact = FRFACT(100, 100) 148 1.1 xtraeme }, 149 1.1 xtraeme { 150 1.1 xtraeme .fs_desc = "Vtt", 151 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 152 1.1 xtraeme .fs_aux = 0, 153 1.1 xtraeme .fs_reg = 0x11, 154 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 155 1.1 xtraeme .fs_rfact = FRFACT_NONE 156 1.1 xtraeme }, 157 1.1 xtraeme { 158 1.1 xtraeme .fs_desc = "Vram", 159 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 160 1.1 xtraeme .fs_aux = 0, 161 1.1 xtraeme .fs_reg = 0x12, 162 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 163 1.1 xtraeme .fs_rfact = FRFACT(100, 100) 164 1.1 xtraeme }, 165 1.1 xtraeme { 166 1.1 xtraeme .fs_desc = "Vchips", 167 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 168 1.1 xtraeme .fs_aux = 0, 169 1.1 xtraeme .fs_reg = 0x13, 170 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 171 1.1 xtraeme .fs_rfact = FRFACT(47, 100) 172 1.1 xtraeme }, 173 1.1 xtraeme { 174 1.1 xtraeme .fs_desc = "+5V", 175 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 176 1.1 xtraeme .fs_aux = 0, 177 1.1 xtraeme .fs_reg = 0x14, 178 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 179 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 180 1.1 xtraeme }, 181 1.1 xtraeme { 182 1.1 xtraeme .fs_desc = "+12V", 183 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 184 1.1 xtraeme .fs_aux = 0, 185 1.1 xtraeme .fs_reg = 0x15, 186 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 187 1.1 xtraeme .fs_rfact = FRFACT(200, 20) 188 1.1 xtraeme }, 189 1.1 xtraeme { 190 1.1 xtraeme .fs_desc = "Vcc 1.5V", 191 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 192 1.1 xtraeme .fs_aux = 0, 193 1.1 xtraeme .fs_reg = 0x16, 194 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 195 1.1 xtraeme .fs_rfact = FRFACT_NONE 196 1.1 xtraeme }, 197 1.1 xtraeme { 198 1.1 xtraeme .fs_desc = "VCore", 199 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 200 1.1 xtraeme .fs_aux = 0, 201 1.1 xtraeme .fs_reg = 0x17, 202 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 203 1.1 xtraeme .fs_rfact = FRFACT_NONE 204 1.1 xtraeme }, 205 1.1 xtraeme { 206 1.1 xtraeme .fs_desc = "Vsb", 207 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 208 1.1 xtraeme .fs_aux = 0, 209 1.1 xtraeme .fs_reg = 0x18, 210 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 211 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 212 1.1 xtraeme }, 213 1.1 xtraeme { 214 1.1 xtraeme .fs_desc = "Vsbint", 215 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 216 1.1 xtraeme .fs_aux = 0, 217 1.1 xtraeme .fs_reg = 0x19, 218 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 219 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 220 1.1 xtraeme }, 221 1.1 xtraeme { 222 1.1 xtraeme .fs_desc = "Vbat", 223 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 224 1.1 xtraeme .fs_aux = 0, 225 1.1 xtraeme .fs_reg = 0x1a, 226 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 227 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 228 1.1 xtraeme }, 229 1.1 xtraeme /* Temperature */ 230 1.1 xtraeme { 231 1.1 xtraeme .fs_desc = "Temp1", 232 1.1 xtraeme .fs_type = ENVSYS_STEMP, 233 1.1 xtraeme .fs_aux = 0x01, 234 1.1 xtraeme .fs_reg = 0x1b, 235 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 236 1.1 xtraeme .fs_rfact = 0 237 1.1 xtraeme }, 238 1.1 xtraeme { 239 1.1 xtraeme .fs_desc = "Temp2", 240 1.1 xtraeme .fs_type = ENVSYS_STEMP, 241 1.1 xtraeme .fs_aux = 0x02, 242 1.1 xtraeme .fs_reg = 0x1c, 243 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 244 1.1 xtraeme .fs_rfact = 0 245 1.1 xtraeme }, 246 1.1 xtraeme { 247 1.1 xtraeme .fs_desc = "Temp3", 248 1.1 xtraeme .fs_type = ENVSYS_STEMP, 249 1.1 xtraeme .fs_aux = 0x04, 250 1.1 xtraeme .fs_reg = 0x1d, 251 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 252 1.1 xtraeme .fs_rfact = 0 253 1.1 xtraeme }, 254 1.1 xtraeme /* Fans */ 255 1.1 xtraeme { 256 1.1 xtraeme .fs_desc = "Fan1", 257 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 258 1.1 xtraeme .fs_aux = 0, 259 1.1 xtraeme .fs_reg = 0x20, 260 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 261 1.1 xtraeme .fs_rfact = 0 262 1.1 xtraeme }, 263 1.1 xtraeme { 264 1.1 xtraeme .fs_desc = "Fan2", 265 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 266 1.1 xtraeme .fs_aux = 0, 267 1.1 xtraeme .fs_reg = 0x22, 268 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 269 1.1 xtraeme .fs_rfact = 0 270 1.1 xtraeme }, 271 1.1 xtraeme { 272 1.1 xtraeme .fs_desc = "Fan3", 273 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 274 1.1 xtraeme .fs_aux = 0, 275 1.1 xtraeme .fs_reg = 0x24, 276 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 277 1.1 xtraeme .fs_rfact = 0 278 1.1 xtraeme }, 279 1.1 xtraeme 280 1.1 xtraeme { .fs_desc = NULL } 281 1.1 xtraeme }; 282 1.1 xtraeme 283 1.1 xtraeme /* Sensors available in F71862/F71882/F71883 */ 284 1.1 xtraeme static struct finsio_sensor f71883_sensors[] = { 285 1.1 xtraeme /* Voltage */ 286 1.1 xtraeme { 287 1.1 xtraeme .fs_desc = "+3.3V", 288 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 289 1.1 xtraeme .fs_aux = 0, 290 1.1 xtraeme .fs_reg = 0x20, 291 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 292 1.1 xtraeme .fs_rfact = FRFACT(100, 100) 293 1.1 xtraeme }, 294 1.1 xtraeme { 295 1.1 xtraeme .fs_desc = "Vcore", 296 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 297 1.1 xtraeme .fs_aux = 0, 298 1.1 xtraeme .fs_reg = 0x21, 299 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 300 1.1 xtraeme .fs_rfact = FRFACT_NONE 301 1.1 xtraeme }, 302 1.1 xtraeme { 303 1.1 xtraeme .fs_desc = "VIN2", 304 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 305 1.1 xtraeme .fs_aux = 0, 306 1.1 xtraeme .fs_reg = 0x22, 307 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 308 1.1 xtraeme .fs_rfact = FRFACT(100, 100) 309 1.1 xtraeme }, 310 1.1 xtraeme { 311 1.1 xtraeme .fs_desc = "VIN3", 312 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 313 1.1 xtraeme .fs_aux = 0, 314 1.1 xtraeme .fs_reg = 0x23, 315 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 316 1.1 xtraeme .fs_rfact = FRFACT(47, 100) 317 1.1 xtraeme }, 318 1.1 xtraeme { 319 1.1 xtraeme .fs_desc = "VIN4", 320 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 321 1.1 xtraeme .fs_aux = 0, 322 1.1 xtraeme .fs_reg = 0x24, 323 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 324 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 325 1.1 xtraeme }, 326 1.1 xtraeme { 327 1.1 xtraeme .fs_desc = "VIN5", 328 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 329 1.1 xtraeme .fs_aux = 0, 330 1.1 xtraeme .fs_reg = 0x25, 331 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 332 1.1 xtraeme .fs_rfact = FRFACT(200, 20) 333 1.1 xtraeme }, 334 1.1 xtraeme { 335 1.1 xtraeme .fs_desc = "VIN6", 336 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 337 1.1 xtraeme .fs_aux = 0, 338 1.1 xtraeme .fs_reg = 0x26, 339 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 340 1.1 xtraeme .fs_rfact = FRFACT(100, 100) 341 1.1 xtraeme }, 342 1.1 xtraeme { 343 1.1 xtraeme .fs_desc = "VSB +3.3V", 344 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 345 1.1 xtraeme .fs_aux = 0, 346 1.1 xtraeme .fs_reg = 0x27, 347 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 348 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 349 1.1 xtraeme }, 350 1.1 xtraeme { 351 1.1 xtraeme .fs_desc = "VBAT", 352 1.1 xtraeme .fs_type = ENVSYS_SVOLTS_DC, 353 1.1 xtraeme .fs_aux = 0, 354 1.1 xtraeme .fs_reg = 0x28, 355 1.1 xtraeme .fs_refresh = finsio_refresh_volt, 356 1.1 xtraeme .fs_rfact = FRFACT(200, 47) 357 1.1 xtraeme }, 358 1.1 xtraeme /* Temperature */ 359 1.1 xtraeme { 360 1.1 xtraeme .fs_desc = "Temp1", 361 1.1 xtraeme .fs_type = ENVSYS_STEMP, 362 1.1 xtraeme .fs_aux = 0x1, 363 1.1 xtraeme .fs_reg = 0x72, 364 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 365 1.1 xtraeme .fs_rfact = 0 366 1.1 xtraeme }, 367 1.1 xtraeme { 368 1.1 xtraeme .fs_desc = "Temp2", 369 1.1 xtraeme .fs_type = ENVSYS_STEMP, 370 1.1 xtraeme .fs_aux = 0x2, 371 1.1 xtraeme .fs_reg = 0x74, 372 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 373 1.1 xtraeme .fs_rfact = 0 374 1.1 xtraeme }, 375 1.1 xtraeme { 376 1.1 xtraeme .fs_desc = "Temp3", 377 1.1 xtraeme .fs_type = ENVSYS_STEMP, 378 1.1 xtraeme .fs_aux = 0x4, 379 1.1 xtraeme .fs_reg = 0x76, 380 1.1 xtraeme .fs_refresh = finsio_refresh_temp, 381 1.1 xtraeme .fs_rfact = 0 382 1.1 xtraeme }, 383 1.1 xtraeme /* Fan */ 384 1.1 xtraeme { 385 1.1 xtraeme .fs_desc = "Fan1", 386 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 387 1.1 xtraeme .fs_aux = 0, 388 1.1 xtraeme .fs_reg = 0xa0, 389 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 390 1.1 xtraeme .fs_rfact = 0 391 1.1 xtraeme }, 392 1.1 xtraeme { 393 1.1 xtraeme .fs_desc = "Fan2", 394 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 395 1.1 xtraeme .fs_aux = 0, 396 1.1 xtraeme .fs_reg = 0xb0, 397 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 398 1.1 xtraeme .fs_rfact = 0 399 1.1 xtraeme }, 400 1.1 xtraeme { 401 1.1 xtraeme .fs_desc = "Fan3", 402 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 403 1.1 xtraeme .fs_aux = 0, 404 1.1 xtraeme .fs_reg = 0xc0, 405 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 406 1.1 xtraeme .fs_rfact = 0 407 1.1 xtraeme }, 408 1.1 xtraeme { 409 1.1 xtraeme .fs_desc = "Fan4", 410 1.1 xtraeme .fs_type = ENVSYS_SFANRPM, 411 1.1 xtraeme .fs_aux = 0, 412 1.1 xtraeme .fs_reg = 0xd0, 413 1.1 xtraeme .fs_refresh = finsio_refresh_fanrpm, 414 1.1 xtraeme .fs_rfact = 0 415 1.1 xtraeme }, 416 1.1 xtraeme 417 1.1 xtraeme { .fs_desc = NULL } 418 1.1 xtraeme }; 419 1.6 jmcneill 420 1.1 xtraeme static int 421 1.1 xtraeme finsio_isa_match(device_t parent, cfdata_t match, void *aux) 422 1.1 xtraeme { 423 1.1 xtraeme struct isa_attach_args *ia = aux; 424 1.1 xtraeme bus_space_handle_t ioh; 425 1.1 xtraeme uint16_t val; 426 1.1 xtraeme 427 1.1 xtraeme /* Must supply an address */ 428 1.1 xtraeme if (ia->ia_nio < 1) 429 1.1 xtraeme return 0; 430 1.1 xtraeme 431 1.1 xtraeme if (ISA_DIRECT_CONFIG(ia)) 432 1.1 xtraeme return 0; 433 1.1 xtraeme 434 1.1 xtraeme if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 435 1.1 xtraeme return 0; 436 1.1 xtraeme 437 1.1 xtraeme if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) 438 1.1 xtraeme return 0; 439 1.1 xtraeme 440 1.1 xtraeme finsio_enter(ia->ia_iot, ioh); 441 1.1 xtraeme /* Find out Manufacturer ID */ 442 1.1 xtraeme val = finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF) << 8; 443 1.1 xtraeme val |= finsio_readreg(ia->ia_iot, ioh, FINSIO_MANUF + 1); 444 1.1 xtraeme finsio_exit(ia->ia_iot, ioh); 445 1.1 xtraeme bus_space_unmap(ia->ia_iot, ioh, 2); 446 1.1 xtraeme 447 1.1 xtraeme if (val != FINTEK_ID) 448 1.1 xtraeme return 0; 449 1.1 xtraeme 450 1.1 xtraeme ia->ia_nio = 1; 451 1.1 xtraeme ia->ia_io[0].ir_size = 2; 452 1.1 xtraeme ia->ia_niomem = 0; 453 1.1 xtraeme ia->ia_nirq = 0; 454 1.1 xtraeme ia->ia_ndrq = 0; 455 1.1 xtraeme 456 1.1 xtraeme return 1; 457 1.1 xtraeme } 458 1.1 xtraeme 459 1.1 xtraeme static void 460 1.1 xtraeme finsio_isa_attach(device_t parent, device_t self, void *aux) 461 1.1 xtraeme { 462 1.1 xtraeme struct finsio_softc *sc = device_private(self); 463 1.1 xtraeme struct isa_attach_args *ia = aux; 464 1.1 xtraeme bus_space_handle_t ioh; 465 1.1 xtraeme uint16_t hwmon_baddr, chipid, cr; 466 1.1 xtraeme int i, rv = 0; 467 1.1 xtraeme 468 1.1 xtraeme aprint_naive("\n"); 469 1.1 xtraeme 470 1.1 xtraeme sc->sc_iot = ia->ia_iot; 471 1.1 xtraeme 472 1.1 xtraeme /* Map Super I/O configuration space */ 473 1.1 xtraeme if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) { 474 1.1 xtraeme aprint_error(": can't map configuration I/O space\n"); 475 1.1 xtraeme return; 476 1.1 xtraeme } 477 1.1 xtraeme 478 1.1 xtraeme finsio_enter(sc->sc_iot, ioh); 479 1.1 xtraeme /* Get the Chip ID */ 480 1.1 xtraeme chipid = finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP) << 8; 481 1.1 xtraeme chipid |= finsio_readreg(sc->sc_iot, ioh, FINSIO_CHIP + 1); 482 1.1 xtraeme /* 483 1.1 xtraeme * Select the Hardware Monitor LDN to find out the I/O 484 1.1 xtraeme * address space. 485 1.1 xtraeme */ 486 1.1 xtraeme finsio_writereg(sc->sc_iot, ioh, FINSIO_FUNC_SEL, FINSIO_FUNC_HWMON); 487 1.1 xtraeme hwmon_baddr = finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR) << 8; 488 1.1 xtraeme hwmon_baddr |= finsio_readreg(sc->sc_iot, ioh, FINSIO_SENSADDR + 1); 489 1.1 xtraeme finsio_exit(sc->sc_iot, ioh); 490 1.1 xtraeme bus_space_unmap(sc->sc_iot, ioh, 2); 491 1.1 xtraeme 492 1.7 jakllsch /* 493 1.7 jakllsch * The address decoder ignores the bottom 3 bits, so do we. 494 1.7 jakllsch */ 495 1.7 jakllsch hwmon_baddr &= ~FINSIO_DECODE_MASK; 496 1.7 jakllsch 497 1.1 xtraeme switch (chipid) { 498 1.1 xtraeme case FINSIO_IDF71805: 499 1.1 xtraeme sc->sc_finsio_sensors = f71805_sensors; 500 1.1 xtraeme aprint_normal(": Fintek F71805 Super I/O\n"); 501 1.1 xtraeme break; 502 1.1 xtraeme case FINSIO_IDF71806: 503 1.1 xtraeme sc->sc_finsio_sensors = f71805_sensors; 504 1.1 xtraeme aprint_normal(": Fintek F71806/F71872 Super I/O\n"); 505 1.1 xtraeme break; 506 1.1 xtraeme case FINSIO_IDF71862: 507 1.1 xtraeme sc->sc_finsio_sensors = f71883_sensors; 508 1.1 xtraeme aprint_normal(": Fintek F71862 Super I/O\n"); 509 1.1 xtraeme break; 510 1.1 xtraeme case FINSIO_IDF71883: 511 1.1 xtraeme sc->sc_finsio_sensors = f71883_sensors; 512 1.1 xtraeme aprint_normal(": Fintek F71882/F71883 Super I/O\n"); 513 1.1 xtraeme break; 514 1.6 jmcneill case FINSIO_IDF8000: 515 1.6 jmcneill sc->sc_finsio_sensors = f71883_sensors; 516 1.6 jmcneill aprint_normal(": ASUS F8000 Super I/O\n"); 517 1.6 jmcneill break; 518 1.1 xtraeme default: 519 1.1 xtraeme /* 520 1.1 xtraeme * Unknown Chip ID, assume the same register layout 521 1.1 xtraeme * than F71805 for now. 522 1.1 xtraeme */ 523 1.1 xtraeme sc->sc_finsio_sensors = f71805_sensors; 524 1.1 xtraeme aprint_normal(": Fintek Super I/O (unknown chip ID %x)\n", 525 1.1 xtraeme chipid); 526 1.1 xtraeme break; 527 1.1 xtraeme } 528 1.1 xtraeme 529 1.1 xtraeme /* Map Hardware Monitor I/O space */ 530 1.7 jakllsch if (bus_space_map(sc->sc_iot, hwmon_baddr, FINSIO_DECODE_SIZE, 531 1.7 jakllsch 0, &sc->sc_ioh)) { 532 1.1 xtraeme aprint_error(": can't map hwmon I/O space\n"); 533 1.1 xtraeme return; 534 1.1 xtraeme } 535 1.1 xtraeme 536 1.1 xtraeme /* 537 1.1 xtraeme * Enable Hardware monitoring for fan/temperature and 538 1.1 xtraeme * voltage sensors. 539 1.1 xtraeme */ 540 1.1 xtraeme cr = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF); 541 1.1 xtraeme finsio_writereg(sc->sc_iot, sc->sc_ioh, FINSIO_HWMON_CONF, cr | 0x3); 542 1.1 xtraeme 543 1.1 xtraeme /* Find out the temperature mode */ 544 1.1 xtraeme sc->sc_tempsel = finsio_readreg(sc->sc_iot, sc->sc_ioh, FINSIO_TMODE); 545 1.1 xtraeme 546 1.1 xtraeme /* 547 1.1 xtraeme * Initialize and attach sensors with sysmon_envsys(9). 548 1.1 xtraeme */ 549 1.1 xtraeme sc->sc_sme = sysmon_envsys_create(); 550 1.1 xtraeme for (i = 0; sc->sc_finsio_sensors[i].fs_desc; i++) { 551 1.5 pgoyette sc->sc_sensor[i].state = ENVSYS_SINVALID; 552 1.1 xtraeme sc->sc_sensor[i].units = sc->sc_finsio_sensors[i].fs_type; 553 1.4 xtraeme if (sc->sc_sensor[i].units == ENVSYS_SVOLTS_DC) 554 1.4 xtraeme sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT; 555 1.1 xtraeme strlcpy(sc->sc_sensor[i].desc, sc->sc_finsio_sensors[i].fs_desc, 556 1.1 xtraeme sizeof(sc->sc_sensor[i].desc)); 557 1.1 xtraeme if (sysmon_envsys_sensor_attach(sc->sc_sme, 558 1.1 xtraeme &sc->sc_sensor[i])) 559 1.1 xtraeme goto fail; 560 1.1 xtraeme } 561 1.1 xtraeme 562 1.1 xtraeme sc->sc_sme->sme_name = device_xname(self); 563 1.1 xtraeme sc->sc_sme->sme_cookie = sc; 564 1.1 xtraeme sc->sc_sme->sme_refresh = finsio_refresh; 565 1.1 xtraeme if ((rv = sysmon_envsys_register(sc->sc_sme))) { 566 1.1 xtraeme aprint_error(": unable to register with sysmon (%d)\n", rv); 567 1.1 xtraeme goto fail; 568 1.1 xtraeme } 569 1.1 xtraeme 570 1.1 xtraeme aprint_normal_dev(self, 571 1.1 xtraeme "Hardware Monitor registers at 0x%x\n", hwmon_baddr); 572 1.1 xtraeme return; 573 1.1 xtraeme 574 1.1 xtraeme fail: 575 1.1 xtraeme sysmon_envsys_destroy(sc->sc_sme); 576 1.9 mlelstv sc->sc_sme = NULL; 577 1.7 jakllsch bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 578 1.1 xtraeme } 579 1.1 xtraeme 580 1.3 xtraeme static int 581 1.3 xtraeme finsio_isa_detach(device_t self, int flags) 582 1.3 xtraeme { 583 1.3 xtraeme struct finsio_softc *sc = device_private(self); 584 1.3 xtraeme 585 1.9 mlelstv if (sc->sc_sme != NULL) 586 1.9 mlelstv sysmon_envsys_unregister(sc->sc_sme); 587 1.7 jakllsch bus_space_unmap(sc->sc_iot, sc->sc_ioh, FINSIO_DECODE_SIZE); 588 1.3 xtraeme return 0; 589 1.3 xtraeme } 590 1.3 xtraeme 591 1.1 xtraeme /* Enter Super I/O configuration mode */ 592 1.1 xtraeme static void 593 1.1 xtraeme finsio_enter(bus_space_tag_t iot, bus_space_handle_t ioh) 594 1.1 xtraeme { 595 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 596 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_UNLOCK); 597 1.1 xtraeme } 598 1.1 xtraeme 599 1.1 xtraeme /* Exit Super I/O configuration mode */ 600 1.1 xtraeme static void 601 1.1 xtraeme finsio_exit(bus_space_tag_t iot, bus_space_handle_t ioh) 602 1.1 xtraeme { 603 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_ADDR, FINSIO_LOCK); 604 1.1 xtraeme } 605 1.1 xtraeme 606 1.1 xtraeme static uint8_t 607 1.1 xtraeme finsio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg) 608 1.1 xtraeme { 609 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 610 1.1 xtraeme return bus_space_read_1(iot, ioh, FINSIO_DATA); 611 1.1 xtraeme } 612 1.1 xtraeme 613 1.1 xtraeme static void 614 1.1 xtraeme finsio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val) 615 1.1 xtraeme { 616 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_ADDR, reg); 617 1.1 xtraeme bus_space_write_1(iot, ioh, FINSIO_DATA, val); 618 1.1 xtraeme } 619 1.1 xtraeme 620 1.1 xtraeme static void 621 1.1 xtraeme finsio_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 622 1.1 xtraeme { 623 1.1 xtraeme struct finsio_softc *sc = sme->sme_cookie; 624 1.1 xtraeme int i = edata->sensor; 625 1.1 xtraeme 626 1.1 xtraeme sc->sc_finsio_sensors[i].fs_refresh(sc, edata); 627 1.1 xtraeme } 628 1.1 xtraeme 629 1.1 xtraeme static void 630 1.1 xtraeme finsio_refresh_volt(struct finsio_softc *sc, envsys_data_t *edata) 631 1.1 xtraeme { 632 1.1 xtraeme struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 633 1.1 xtraeme int data; 634 1.1 xtraeme 635 1.1 xtraeme data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg); 636 1.1 xtraeme DPRINTF(("%s: data 0x%x\n", __func__, data)); 637 1.1 xtraeme 638 1.1 xtraeme if (data == 0xff || data == 0) 639 1.1 xtraeme edata->state = ENVSYS_SINVALID; 640 1.1 xtraeme else { 641 1.1 xtraeme edata->state = ENVSYS_SVALID; 642 1.4 xtraeme if (edata->rfact) 643 1.4 xtraeme edata->value_cur = data * edata->rfact; 644 1.4 xtraeme else 645 1.4 xtraeme edata->value_cur = data * fs->fs_rfact; 646 1.1 xtraeme } 647 1.1 xtraeme } 648 1.1 xtraeme 649 1.1 xtraeme /* The BIOS seems to add a fudge factor to the CPU temp of +5C */ 650 1.1 xtraeme static void 651 1.1 xtraeme finsio_refresh_temp(struct finsio_softc *sc, envsys_data_t *edata) 652 1.1 xtraeme { 653 1.1 xtraeme struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 654 1.1 xtraeme u_int data; 655 1.1 xtraeme u_int llmax; 656 1.1 xtraeme 657 1.1 xtraeme /* 658 1.1 xtraeme * The data sheet says that the range of the temperature 659 1.1 xtraeme * sensor is between 0 and 127 or 140 degrees C depending on 660 1.1 xtraeme * what kind of sensor is used. 661 1.1 xtraeme * A disconnected sensor seems to read over 110 or so. 662 1.1 xtraeme */ 663 1.1 xtraeme data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) & 0xFF; 664 1.1 xtraeme DPRINTF(("%s: data 0x%x\n", __func__, data)); 665 1.1 xtraeme 666 1.1 xtraeme llmax = (sc->sc_tempsel & fs->fs_aux) ? 111 : 128; 667 1.1 xtraeme if (data == 0 || data >= llmax) /* disconnected? */ 668 1.1 xtraeme edata->state = ENVSYS_SINVALID; 669 1.1 xtraeme else { 670 1.1 xtraeme edata->state = ENVSYS_SVALID; 671 1.1 xtraeme edata->value_cur = data * 1000000 + 273150000; 672 1.1 xtraeme } 673 1.1 xtraeme } 674 1.1 xtraeme 675 1.1 xtraeme /* fan speed appears to be a 12-bit number */ 676 1.1 xtraeme static void 677 1.1 xtraeme finsio_refresh_fanrpm(struct finsio_softc *sc, envsys_data_t *edata) 678 1.1 xtraeme { 679 1.1 xtraeme struct finsio_sensor *fs = &sc->sc_finsio_sensors[edata->sensor]; 680 1.1 xtraeme int data; 681 1.1 xtraeme 682 1.1 xtraeme data = finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg) << 8; 683 1.1 xtraeme data |= finsio_readreg(sc->sc_iot, sc->sc_ioh, fs->fs_reg + 1); 684 1.1 xtraeme DPRINTF(("%s: data 0x%x\n", __func__, data)); 685 1.1 xtraeme 686 1.1 xtraeme if (data >= 0xfff) 687 1.1 xtraeme edata->state = ENVSYS_SINVALID; 688 1.1 xtraeme else { 689 1.1 xtraeme edata->value_cur = 1500000 / data; 690 1.1 xtraeme edata->state = ENVSYS_SVALID; 691 1.1 xtraeme } 692 1.1 xtraeme } 693 1.6 jmcneill 694 1.8 pgoyette MODULE(MODULE_CLASS_DRIVER, finsio, "sysmon_envsys"); 695 1.6 jmcneill 696 1.6 jmcneill #ifdef _MODULE 697 1.6 jmcneill #include "ioconf.c" 698 1.6 jmcneill #endif 699 1.6 jmcneill 700 1.6 jmcneill static int 701 1.6 jmcneill finsio_modcmd(modcmd_t cmd, void *opaque) 702 1.6 jmcneill { 703 1.6 jmcneill int error = 0; 704 1.6 jmcneill 705 1.6 jmcneill switch (cmd) { 706 1.6 jmcneill case MODULE_CMD_INIT: 707 1.6 jmcneill #ifdef _MODULE 708 1.6 jmcneill error = config_init_component(cfdriver_ioconf_finsio, 709 1.6 jmcneill cfattach_ioconf_finsio, cfdata_ioconf_finsio); 710 1.6 jmcneill #endif 711 1.6 jmcneill return error; 712 1.6 jmcneill case MODULE_CMD_FINI: 713 1.6 jmcneill #ifdef _MODULE 714 1.6 jmcneill error = config_fini_component(cfdriver_ioconf_finsio, 715 1.6 jmcneill cfattach_ioconf_finsio, cfdata_ioconf_finsio); 716 1.6 jmcneill #endif 717 1.6 jmcneill return error; 718 1.6 jmcneill default: 719 1.6 jmcneill return ENOTTY; 720 1.6 jmcneill } 721 1.6 jmcneill } 722