1 /* $OpenBSD: blambert $ */ 2 /* $NetBSD: nsclpcsio_isa.c,v 1.5 2002/10/22 16:18:26 drochner Exp $ */ 3 4 /* 5 * Copyright (c) 2002 Matthias Drochner. All rights reserved. 6 * Copyright (c) 2004 Markus Friedl. All rights reserved. 7 * Copyright (c) 2004 Alexander Yurchenko. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * National Semiconductor PC87366 LPC Super I/O. 33 * Supported logical devices: GPIO, TMS, VLM. 34 */ 35 36 #include "use_gpio.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/device.h> 41 #include <sys/kernel.h> 42 #include <sys/sensors.h> 43 #include <sys/module.h> 44 #include <sys/rman.h> 45 46 #include <sys/bus.h> 47 48 #include <bus/isa/isareg.h> 49 #include <bus/isa/isavar.h> 50 51 #include <dev/misc/gpio/gpio.h> 52 53 #if defined(NSC_LPC_SIO_DEBUG) 54 #define DPRINTF(x) do { kprintf x; } while (0) 55 #else 56 #define DPRINTF(x) 57 #endif 58 59 #define SIO_REG_SID 0x20 /* Super I/O ID */ 60 #define SIO_SID_PC87366 0xE9 /* PC87366 is identified by 0xE9.*/ 61 62 #define SIO_REG_SRID 0x27 /* Super I/O Revision */ 63 64 #define SIO_REG_LDN 0x07 /* Logical Device Number */ 65 #define SIO_LDN_FDC 0x00 /* Floppy Disk Controller (FDC) */ 66 #define SIO_LDN_PP 0x01 /* Parallel Port (PP) */ 67 #define SIO_LDN_SP2 0x02 /* Serial Port 2 with IR (SP2) */ 68 #define SIO_LDN_SP1 0x03 /* Serial Port 1 (SP1) */ 69 #define SIO_LDN_SWC 0x04 /* System Wake-Up Control (SWC) */ 70 #define SIO_LDN_KBCM 0x05 /* Mouse Controller (KBC) */ 71 #define SIO_LDN_KBCK 0x06 /* Keyboard Controller (KBC) */ 72 #define SIO_LDN_GPIO 0x07 /* General-Purpose I/O (GPIO) Ports */ 73 #define SIO_LDN_ACB 0x08 /* ACCESS.bus Interface (ACB) */ 74 #define SIO_LDN_FSCM 0x09 /* Fan Speed Control and Monitor (FSCM) */ 75 #define SIO_LDN_WDT 0x0A /* WATCHDOG Timer (WDT) */ 76 #define SIO_LDN_GMP 0x0B /* Game Port (GMP) */ 77 #define SIO_LDN_MIDI 0x0C /* Musical Instrument Digital Interface */ 78 #define SIO_LDN_VLM 0x0D /* Voltage Level Monitor (VLM) */ 79 #define SIO_LDN_TMS 0x0E /* Temperature Sensor (TMS) */ 80 81 #define SIO_REG_ACTIVE 0x30 /* Logical Device Activate Register */ 82 #define SIO_ACTIVE_EN 0x01 /* enabled */ 83 84 #define SIO_REG_IO_MSB 0x60 /* I/O Port Base, bits 15-8 */ 85 #define SIO_REG_IO_LSB 0x61 /* I/O Port Base, bits 7-0 */ 86 87 #define SIO_LDNUM 15 /* total number of logical devices */ 88 89 /* Supported logical devices description */ 90 static const struct { 91 const char *ld_name; 92 int ld_num; 93 int ld_iosize; 94 } sio_ld[] = { 95 { "GPIO", SIO_LDN_GPIO, 16 }, 96 { "VLM", SIO_LDN_VLM, 16 }, 97 { "TMS", SIO_LDN_TMS, 16 }, 98 }; 99 100 /* GPIO */ 101 #define SIO_GPIO_PINSEL 0xf0 102 #define SIO_GPIO_PINCFG 0xf1 103 #define SIO_GPIO_PINEV 0xf2 104 105 #define SIO_GPIO_CONF_OUTPUTEN (1 << 0) 106 #define SIO_GPIO_CONF_PUSHPULL (1 << 1) 107 #define SIO_GPIO_CONF_PULLUP (1 << 2) 108 109 #define SIO_GPDO0 0x00 110 #define SIO_GPDI0 0x01 111 #define SIO_GPEVEN0 0x02 112 #define SIO_GPEVST0 0x03 113 #define SIO_GPDO1 0x04 114 #define SIO_GPDI1 0x05 115 #define SIO_GPEVEN1 0x06 116 #define SIO_GPEVST1 0x07 117 #define SIO_GPDO2 0x08 118 #define SIO_GPDI2 0x09 119 #define SIO_GPDO3 0x0a 120 #define SIO_GPDI3 0x0b 121 122 #define SIO_GPIO_NPINS 29 123 124 /* TMS */ 125 #define SIO_TEVSTS 0x00 /* Temperature Event Status */ 126 #define SIO_TEVSMI 0x02 /* Temperature Event to SMI */ 127 #define SIO_TEVIRQ 0x04 /* Temperature Event to IRQ */ 128 #define SIO_TMSCFG 0x08 /* TMS Configuration */ 129 #define SIO_TMSBS 0x09 /* TMS Bank Select */ 130 #define SIO_TCHCFST 0x0A /* Temperature Channel Config and Status */ 131 #define SIO_RDCHT 0x0B /* Read Channel Temperature */ 132 #define SIO_CHTH 0x0C /* Channel Temperature High Limit */ 133 #define SIO_CHTL 0x0D /* Channel Temperature Low Limit */ 134 #define SIO_CHOTL 0x0E /* Channel Overtemperature Limit */ 135 136 /* VLM */ 137 #define SIO_VEVSTS0 0x00 /* Voltage Event Status 0 */ 138 #define SIO_VEVSTS1 0x01 /* Voltage Event Status 1 */ 139 #define SIO_VEVSMI0 0x02 /* Voltage Event to SMI 0 */ 140 #define SIO_VEVSMI1 0x03 /* Voltage Event to SMI 1 */ 141 #define SIO_VEVIRQ0 0x04 /* Voltage Event to IRQ 0 */ 142 #define SIO_VEVIRQ1 0x05 /* Voltage Event to IRQ 1 */ 143 #define SIO_VID 0x06 /* Voltage ID */ 144 #define SIO_VCNVR 0x07 /* Voltage Conversion Rate */ 145 #define SIO_VLMCFG 0x08 /* VLM Configuration */ 146 #define SIO_VLMBS 0x09 /* VLM Bank Select */ 147 #define SIO_VCHCFST 0x0A /* Voltage Channel Config and Status */ 148 #define SIO_RDCHV 0x0B /* Read Channel Voltage */ 149 #define SIO_CHVH 0x0C /* Channel Voltage High Limit */ 150 #define SIO_CHVL 0x0D /* Channel Voltage Low Limit */ 151 #define SIO_OTSL 0x0E /* Overtemperature Shutdown Limit */ 152 153 #define SIO_REG_SIOCF1 0x21 154 #define SIO_REG_SIOCF2 0x22 155 #define SIO_REG_SIOCF3 0x23 156 #define SIO_REG_SIOCF4 0x24 157 #define SIO_REG_SIOCF5 0x25 158 #define SIO_REG_SIOCF8 0x28 159 #define SIO_REG_SIOCFA 0x2A 160 #define SIO_REG_SIOCFB 0x2B 161 #define SIO_REG_SIOCFC 0x2C 162 #define SIO_REG_SIOCFD 0x2D 163 164 #define SIO_NUM_SENSORS (3+14) 165 #define SIO_VLM_OFF 3 166 #define SIO_VREF 1235 /* 1000.0 * VREF */ 167 168 struct nsclpcsio_softc { 169 struct device* sc_dev; 170 struct resource *sc_iores; 171 int sc_iorid; 172 bus_space_tag_t sc_iot; 173 bus_space_handle_t sc_ioh; 174 175 bus_space_handle_t sc_ld_ioh[SIO_LDNUM]; 176 int sc_ld_en[SIO_LDNUM]; 177 #if NGPIO > 0 178 /* GPIO */ 179 struct gpio sc_gpio_gc; 180 struct gpio_pin sc_gpio_pins[SIO_GPIO_NPINS]; 181 #endif 182 183 /* TMS and VLM */ 184 struct ksensor sensors[SIO_NUM_SENSORS]; 185 struct ksensordev sensordev; 186 }; 187 188 #define GPIO_READ(sc, reg) \ 189 bus_space_read_1((sc)->sc_iot, \ 190 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg)) 191 #define GPIO_WRITE(sc, reg, val) \ 192 bus_space_write_1((sc)->sc_iot, \ 193 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val)) 194 #define TMS_WRITE(sc, reg, val) \ 195 bus_space_write_1((sc)->sc_iot, \ 196 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val)) 197 #define TMS_READ(sc, reg) \ 198 bus_space_read_1((sc)->sc_iot, \ 199 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg)) 200 #define VLM_WRITE(sc, reg, val) \ 201 bus_space_write_1((sc)->sc_iot, \ 202 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val)) 203 #define VLM_READ(sc, reg) \ 204 bus_space_read_1((sc)->sc_iot, \ 205 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg)) 206 207 int nsclpcsio_isa_probe(struct device *); 208 int nsclpcsio_isa_attach(struct device *); 209 210 211 static device_method_t nsclpcsio_isa_methods[] = { 212 DEVMETHOD(device_probe, nsclpcsio_isa_probe), 213 DEVMETHOD(device_attach, nsclpcsio_isa_attach), 214 DEVMETHOD_END 215 }; 216 217 static driver_t nsclpcsio_isa_driver = { 218 "nsclpcsio", 219 nsclpcsio_isa_methods, 220 sizeof (struct nsclpcsio_softc) 221 }; 222 223 static devclass_t nsclpcsio_devclass; 224 225 DRIVER_MODULE(nsclpcsio_isa, isa, nsclpcsio_isa_driver, nsclpcsio_devclass, NULL, NULL); 226 227 228 229 static u_int8_t nsread(bus_space_tag_t, bus_space_handle_t, int); 230 static void nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); 231 232 #if NGPIO > 0 233 void nsclpcsio_gpio_init(struct nsclpcsio_softc *); 234 int nsclpcsio_gpio_pin_read(void *, int); 235 void nsclpcsio_gpio_pin_write(void *, int, int); 236 void nsclpcsio_gpio_pin_ctl(void *, int, int); 237 #endif 238 239 void nsclpcsio_tms_init(struct nsclpcsio_softc *); 240 void nsclpcsio_vlm_init(struct nsclpcsio_softc *); 241 void nsclpcsio_tms_update(struct nsclpcsio_softc *); 242 void nsclpcsio_vlm_update(struct nsclpcsio_softc *); 243 void nsclpcsio_refresh(void *); 244 245 static u_int8_t 246 nsread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx) 247 { 248 bus_space_write_1(iot, ioh, 0, idx); 249 return (bus_space_read_1(iot, ioh, 1)); 250 } 251 252 static void 253 nswrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data) 254 { 255 bus_space_write_1(iot, ioh, 0, idx); 256 bus_space_write_1(iot, ioh, 1, data); 257 } 258 259 int 260 nsclpcsio_isa_probe(struct device *dev) 261 { 262 struct resource *iores; 263 int iorid = 0; 264 bus_space_tag_t iot; 265 bus_space_handle_t ioh; 266 int rv = 0; 267 268 iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid, 0ul, ~0ul, 8, RF_ACTIVE); 269 if (iores == NULL) { 270 return 1; 271 } 272 iot = rman_get_bustag(iores); 273 ioh = rman_get_bushandle(iores); 274 275 if (nsread(iot, ioh, SIO_REG_SID) == SIO_SID_PC87366) 276 rv = 1; 277 278 bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores); 279 if (rv) { 280 return 0; 281 } 282 283 return 1; 284 } 285 286 int 287 nsclpcsio_isa_attach(struct device *dev) 288 { 289 int iobase; 290 struct nsclpcsio_softc *sc = device_get_softc(dev); 291 int i; 292 293 sc->sc_dev = dev; 294 sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid, 0ul, ~0ul, 8, RF_ACTIVE); 295 if (sc->sc_iores == NULL) { 296 return 1; 297 } 298 sc->sc_iot = rman_get_bustag(sc->sc_iores); 299 sc->sc_ioh = rman_get_bushandle(sc->sc_iores); 300 301 kprintf("%s: NSC PC87366 rev %d:", device_get_nameunit(sc->sc_dev), 302 nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID)); 303 304 /* Configure all supported logical devices */ 305 for (i = 0; i < NELEM(sio_ld); i++) { 306 sc->sc_ld_en[sio_ld[i].ld_num] = 0; 307 308 /* Select the device and check if it's activated */ 309 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num); 310 if ((nsread(sc->sc_iot, sc->sc_ioh, 311 SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0) 312 continue; 313 314 /* Map I/O space if necessary */ 315 if (sio_ld[i].ld_iosize != 0) { 316 317 iobase = (nsread(sc->sc_iot, sc->sc_ioh, 318 SIO_REG_IO_MSB) << 8); 319 320 iobase |= nsread(sc->sc_iot, sc->sc_ioh, 321 SIO_REG_IO_LSB); 322 #if 0 323 /* XXX: Not elegant without alloc_resource, but works */ 324 kprintf("debugging: iobase = %x\n", iobase); 325 iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid, 326 iobase, sio_ld[i].ld_iosize, sio_ld[i].ld_iosize, RF_ACTIVE); 327 if (iores == NULL) { 328 kprintf("messed up alloc3\n"); 329 continue; 330 } 331 /* XXX: if implemented, also use the rman get handle stuff */ 332 #endif 333 sc->sc_ld_ioh[sio_ld[i].ld_num] = iobase; 334 } 335 336 sc->sc_ld_en[sio_ld[i].ld_num] = 1; 337 kprintf(" %s", sio_ld[i].ld_name); 338 } 339 340 kprintf("\n"); 341 #if NGPIO > 0 342 nsclpcsio_gpio_init(sc); 343 #endif 344 nsclpcsio_tms_init(sc); 345 nsclpcsio_vlm_init(sc); 346 347 /* Hook into hw.sensors sysctl */ 348 strlcpy(sc->sensordev.xname, device_get_nameunit(sc->sc_dev), 349 sizeof(sc->sensordev.xname)); 350 for (i = 0; i < SIO_NUM_SENSORS; i++) { 351 if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS]) 352 continue; 353 if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM]) 354 continue; 355 sensor_attach(&sc->sensordev, &sc->sensors[i]); 356 } 357 sensordev_install(&sc->sensordev); 358 if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) { 359 sensor_task_register(sc, nsclpcsio_refresh, 2); 360 } 361 362 #if NGPIO > 0 363 /* Attach GPIO framework */ 364 if (sc->sc_ld_en[SIO_LDN_GPIO]) { 365 sc->sc_gpio_gc.driver_name = "pc83766"; 366 sc->sc_gpio_gc.arg = sc; 367 sc->sc_gpio_gc.pin_read = nsclpcsio_gpio_pin_read; 368 sc->sc_gpio_gc.pin_write = nsclpcsio_gpio_pin_write; 369 sc->sc_gpio_gc.pin_ctl = nsclpcsio_gpio_pin_ctl; 370 sc->sc_gpio_gc.pins = sc->sc_gpio_pins; 371 sc->sc_gpio_gc.npins = SIO_GPIO_NPINS; 372 gpio_register(&sc->sc_gpio_gc); 373 } 374 #endif 375 376 return 0; 377 } 378 379 void 380 nsclpcsio_refresh(void *arg) 381 { 382 struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg; 383 384 if (sc->sc_ld_en[SIO_LDN_TMS]) 385 nsclpcsio_tms_update(sc); 386 if (sc->sc_ld_en[SIO_LDN_VLM]) 387 nsclpcsio_vlm_update(sc); 388 } 389 390 void 391 nsclpcsio_tms_init(struct nsclpcsio_softc *sc) 392 { 393 int i; 394 395 /* Initialisation, PC87366.pdf, page 208 */ 396 TMS_WRITE(sc, 0x08, 0x00); 397 TMS_WRITE(sc, 0x09, 0x0f); 398 TMS_WRITE(sc, 0x0a, 0x08); 399 TMS_WRITE(sc, 0x0b, 0x04); 400 TMS_WRITE(sc, 0x0c, 0x35); 401 TMS_WRITE(sc, 0x0d, 0x05); 402 TMS_WRITE(sc, 0x0e, 0x05); 403 404 TMS_WRITE(sc, SIO_TMSCFG, 0x00); 405 406 /* Enable the sensors */ 407 for (i = 0; i < 3; i++) { 408 TMS_WRITE(sc, SIO_TMSBS, i); 409 TMS_WRITE(sc, SIO_TCHCFST, 0x01); 410 411 sc->sensors[i].type = SENSOR_TEMP; 412 } 413 414 strlcpy(sc->sensors[0].desc, "Remote", sizeof(sc->sensors[0].desc)); 415 strlcpy(sc->sensors[1].desc, "Remote", sizeof(sc->sensors[1].desc)); 416 strlcpy(sc->sensors[2].desc, "Local", sizeof(sc->sensors[2].desc)); 417 418 nsclpcsio_tms_update(sc); 419 } 420 421 void 422 nsclpcsio_tms_update(struct nsclpcsio_softc *sc) 423 { 424 u_int8_t status; 425 int8_t sdata; 426 int i; 427 428 for (i = 0; i < 3; i++) { 429 TMS_WRITE(sc, SIO_TMSBS, i); 430 status = TMS_READ(sc, SIO_TCHCFST); 431 if (!(status & 0x01)) { 432 DPRINTF(("%s: status %d: disabled\n", 433 sc->sensors[i].desc, status)); 434 sc->sensors[i].value = 0; 435 continue; 436 } 437 sdata = TMS_READ(sc, SIO_RDCHT); 438 DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc, 439 status, sdata)); 440 sc->sensors[i].value = sdata * 1000000 + 273150000; 441 } 442 } 443 444 void 445 nsclpcsio_vlm_init(struct nsclpcsio_softc *sc) 446 { 447 int i; 448 char *desc = NULL; 449 450 VLM_WRITE(sc, SIO_VLMCFG, 0x00); 451 452 /* Enable the sensors */ 453 for (i = 0; i < 14; i++) { 454 VLM_WRITE(sc, SIO_VLMBS, i); 455 VLM_WRITE(sc, SIO_VCHCFST, 0x01); 456 457 desc = NULL; 458 switch (i) { 459 case 7: 460 desc = "VSB"; 461 break; 462 case 8: 463 desc = "VDD"; 464 break; 465 case 9: 466 desc = "VBAT"; 467 break; 468 case 10: 469 desc = "AVDD"; 470 break; 471 case 11: 472 desc = "TS1"; 473 break; 474 case 12: 475 desc = "TS2"; 476 break; 477 case 13: 478 desc = "TS3"; 479 break; 480 } 481 /* only init .desc if we have something meaningful to say */ 482 if (desc != NULL) 483 strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc, 484 sizeof(sc->sensors[SIO_VLM_OFF + i].desc)); 485 sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC; 486 487 } 488 nsclpcsio_vlm_update(sc); 489 } 490 491 void 492 nsclpcsio_vlm_update(struct nsclpcsio_softc *sc) 493 { 494 u_int8_t status; 495 u_int8_t data; 496 int scale, rfact, i; 497 498 for (i = 0; i < 14; i++) { 499 VLM_WRITE(sc, SIO_VLMBS, i); 500 status = VLM_READ(sc, SIO_VCHCFST); 501 if (!(status & 0x01)) { 502 DPRINTF(("%s: status %d: disabled\n", 503 sc->sensors[SIO_VLM_OFF + i].desc, status)); 504 sc->sensors[SIO_VLM_OFF + i].value = 0; 505 continue; 506 } 507 data = VLM_READ(sc, SIO_RDCHV); 508 DPRINTF(("%s: status %d V %d\n", 509 sc->sensors[SIO_VLM_OFF + i].desc, status, data)); 510 511 scale = 1; 512 switch (i) { 513 case 7: 514 case 8: 515 case 10: 516 scale = 2; 517 } 518 519 /* Vi = (2.45�0.05)*VREF *RDCHVi / 256 */ 520 rfact = 10 * scale * ((245 * SIO_VREF) >> 8); 521 sc->sensors[SIO_VLM_OFF + i].value = data * rfact; 522 } 523 } 524 525 #if NGPIO > 0 526 static __inline void 527 nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin) 528 { 529 int port, shift; 530 u_int8_t data; 531 532 port = pin / 8; 533 shift = pin % 8; 534 data = (port << 4) | shift; 535 536 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 537 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data); 538 } 539 540 void 541 nsclpcsio_gpio_init(struct nsclpcsio_softc *sc) 542 { 543 int i; 544 545 for (i = 0; i < SIO_GPIO_NPINS; i++) { 546 sc->sc_gpio_pins[i].pin_num = i; 547 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 548 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | 549 GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | 550 GPIO_PIN_PULLUP; 551 552 /* Read initial state */ 553 sc->sc_gpio_pins[i].pin_state = nsclpcsio_gpio_pin_read(sc, 554 i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 555 } 556 } 557 558 int 559 nsclpcsio_gpio_pin_read(void *arg, int pin) 560 { 561 struct nsclpcsio_softc *sc = arg; 562 int port, shift, reg; 563 u_int8_t data; 564 565 port = pin / 8; 566 shift = pin % 8; 567 568 switch (port) { 569 case 0: 570 reg = SIO_GPDI0; 571 break; 572 case 1: 573 reg = SIO_GPDI1; 574 break; 575 case 2: 576 reg = SIO_GPDI2; 577 break; 578 case 3: 579 reg = SIO_GPDI3; 580 break; 581 default: 582 return 0; 583 } 584 585 data = GPIO_READ(sc, reg); 586 587 return ((data >> shift) & 0x1); 588 } 589 590 void 591 nsclpcsio_gpio_pin_write(void *arg, int pin, int value) 592 { 593 struct nsclpcsio_softc *sc = arg; 594 int port, shift, reg; 595 u_int8_t data; 596 597 port = pin / 8; 598 shift = pin % 8; 599 600 switch (port) { 601 case 0: 602 reg = SIO_GPDO0; 603 break; 604 case 1: 605 reg = SIO_GPDO1; 606 break; 607 case 2: 608 reg = SIO_GPDO2; 609 break; 610 case 3: 611 reg = SIO_GPDO3; 612 break; 613 default: 614 return; 615 } 616 617 data = GPIO_READ(sc, reg); 618 if (value == 0) 619 data &= ~(1 << shift); 620 else if (value == 1) 621 data |= (1 << shift); 622 623 GPIO_WRITE(sc, reg, data); 624 } 625 626 void 627 nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags) 628 { 629 struct nsclpcsio_softc *sc = arg; 630 u_int8_t conf = 1; 631 632 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 633 nsclpcsio_gpio_pin_select(sc, pin); 634 conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG); 635 636 conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL | 637 SIO_GPIO_CONF_PULLUP); 638 if ((flags & GPIO_PIN_TRISTATE) == 0) 639 conf |= SIO_GPIO_CONF_OUTPUTEN; 640 if (flags & GPIO_PIN_PUSHPULL) 641 conf |= SIO_GPIO_CONF_PUSHPULL; 642 if (flags & GPIO_PIN_PULLUP) 643 conf |= SIO_GPIO_CONF_PULLUP; 644 645 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf); 646 } 647 #endif /* NGPIO */ 648