1 /* $OpenBSD: nsclpcsio_isa.c,v 1.12 2007/06/01 21:30:31 cnst Exp $ */ 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 <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 #include <sys/gpio.h> 40 #include <sys/kernel.h> 41 #include <sys/sensors.h> 42 #include <sys/timeout.h> 43 44 #include <machine/bus.h> 45 46 #include <dev/isa/isareg.h> 47 #include <dev/isa/isavar.h> 48 49 #include <dev/gpio/gpiovar.h> 50 51 #if defined(NSC_LPC_SIO_DEBUG) 52 #define DPRINTF(x) do { printf x; } while (0) 53 #else 54 #define DPRINTF(x) 55 #endif 56 57 #define SIO_REG_SID 0x20 /* Super I/O ID */ 58 #define SIO_SID_PC87366 0xE9 /* PC87366 is identified by 0xE9.*/ 59 60 #define SIO_REG_SRID 0x27 /* Super I/O Revision */ 61 62 #define SIO_REG_LDN 0x07 /* Logical Device Number */ 63 #define SIO_LDN_FDC 0x00 /* Floppy Disk Controller (FDC) */ 64 #define SIO_LDN_PP 0x01 /* Parallel Port (PP) */ 65 #define SIO_LDN_SP2 0x02 /* Serial Port 2 with IR (SP2) */ 66 #define SIO_LDN_SP1 0x03 /* Serial Port 1 (SP1) */ 67 #define SIO_LDN_SWC 0x04 /* System Wake-Up Control (SWC) */ 68 #define SIO_LDN_KBCM 0x05 /* Mouse Controller (KBC) */ 69 #define SIO_LDN_KBCK 0x06 /* Keyboard Controller (KBC) */ 70 #define SIO_LDN_GPIO 0x07 /* General-Purpose I/O (GPIO) Ports */ 71 #define SIO_LDN_ACB 0x08 /* ACCESS.bus Interface (ACB) */ 72 #define SIO_LDN_FSCM 0x09 /* Fan Speed Control and Monitor (FSCM) */ 73 #define SIO_LDN_WDT 0x0A /* WATCHDOG Timer (WDT) */ 74 #define SIO_LDN_GMP 0x0B /* Game Port (GMP) */ 75 #define SIO_LDN_MIDI 0x0C /* Musical Instrument Digital Interface */ 76 #define SIO_LDN_VLM 0x0D /* Voltage Level Monitor (VLM) */ 77 #define SIO_LDN_TMS 0x0E /* Temperature Sensor (TMS) */ 78 79 #define SIO_REG_ACTIVE 0x30 /* Logical Device Activate Register */ 80 #define SIO_ACTIVE_EN 0x01 /* enabled */ 81 82 #define SIO_REG_IO_MSB 0x60 /* I/O Port Base, bits 15-8 */ 83 #define SIO_REG_IO_LSB 0x61 /* I/O Port Base, bits 7-0 */ 84 85 #define SIO_LDNUM 15 /* total number of logical devices */ 86 87 /* Supported logical devices description */ 88 static const struct { 89 const char *ld_name; 90 int ld_num; 91 int ld_iosize; 92 } sio_ld[] = { 93 { "GPIO", SIO_LDN_GPIO, 16 }, 94 { "VLM", SIO_LDN_VLM, 16 }, 95 { "TMS", SIO_LDN_TMS, 16 }, 96 }; 97 98 /* GPIO */ 99 #define SIO_GPIO_PINSEL 0xf0 100 #define SIO_GPIO_PINCFG 0xf1 101 #define SIO_GPIO_PINEV 0xf2 102 103 #define SIO_GPIO_CONF_OUTPUTEN (1 << 0) 104 #define SIO_GPIO_CONF_PUSHPULL (1 << 1) 105 #define SIO_GPIO_CONF_PULLUP (1 << 2) 106 107 #define SIO_GPDO0 0x00 108 #define SIO_GPDI0 0x01 109 #define SIO_GPEVEN0 0x02 110 #define SIO_GPEVST0 0x03 111 #define SIO_GPDO1 0x04 112 #define SIO_GPDI1 0x05 113 #define SIO_GPEVEN1 0x06 114 #define SIO_GPEVST1 0x07 115 #define SIO_GPDO2 0x08 116 #define SIO_GPDI2 0x09 117 #define SIO_GPDO3 0x0a 118 #define SIO_GPDI3 0x0b 119 120 #define SIO_GPIO_NPINS 29 121 122 /* TMS */ 123 #define SIO_TEVSTS 0x00 /* Temperature Event Status */ 124 #define SIO_TEVSMI 0x02 /* Temperature Event to SMI */ 125 #define SIO_TEVIRQ 0x04 /* Temperature Event to IRQ */ 126 #define SIO_TMSCFG 0x08 /* TMS Configuration */ 127 #define SIO_TMSBS 0x09 /* TMS Bank Select */ 128 #define SIO_TCHCFST 0x0A /* Temperature Channel Config and Status */ 129 #define SIO_RDCHT 0x0B /* Read Channel Temperature */ 130 #define SIO_CHTH 0x0C /* Channel Temperature High Limit */ 131 #define SIO_CHTL 0x0D /* Channel Temperature Low Limit */ 132 #define SIO_CHOTL 0x0E /* Channel Overtemperature Limit */ 133 134 /* VLM */ 135 #define SIO_VEVSTS0 0x00 /* Voltage Event Status 0 */ 136 #define SIO_VEVSTS1 0x01 /* Voltage Event Status 1 */ 137 #define SIO_VEVSMI0 0x02 /* Voltage Event to SMI 0 */ 138 #define SIO_VEVSMI1 0x03 /* Voltage Event to SMI 1 */ 139 #define SIO_VEVIRQ0 0x04 /* Voltage Event to IRQ 0 */ 140 #define SIO_VEVIRQ1 0x05 /* Voltage Event to IRQ 1 */ 141 #define SIO_VID 0x06 /* Voltage ID */ 142 #define SIO_VCNVR 0x07 /* Voltage Conversion Rate */ 143 #define SIO_VLMCFG 0x08 /* VLM Configuration */ 144 #define SIO_VLMBS 0x09 /* VLM Bank Select */ 145 #define SIO_VCHCFST 0x0A /* Voltage Channel Config and Status */ 146 #define SIO_RDCHV 0x0B /* Read Channel Voltage */ 147 #define SIO_CHVH 0x0C /* Channel Voltage High Limit */ 148 #define SIO_CHVL 0x0D /* Channel Voltage Low Limit */ 149 #define SIO_OTSL 0x0E /* Overtemperature Shutdown Limit */ 150 151 #define SIO_REG_SIOCF1 0x21 152 #define SIO_REG_SIOCF2 0x22 153 #define SIO_REG_SIOCF3 0x23 154 #define SIO_REG_SIOCF4 0x24 155 #define SIO_REG_SIOCF5 0x25 156 #define SIO_REG_SIOCF8 0x28 157 #define SIO_REG_SIOCFA 0x2A 158 #define SIO_REG_SIOCFB 0x2B 159 #define SIO_REG_SIOCFC 0x2C 160 #define SIO_REG_SIOCFD 0x2D 161 162 #define SIO_NUM_SENSORS (3+14) 163 #define SIO_VLM_OFF 3 164 #define SIO_VREF 1235 /* 1000.0 * VREF */ 165 166 struct nsclpcsio_softc { 167 struct device sc_dev; 168 bus_space_tag_t sc_iot; 169 bus_space_handle_t sc_ioh; 170 171 bus_space_handle_t sc_ld_ioh[SIO_LDNUM]; 172 int sc_ld_en[SIO_LDNUM]; 173 174 /* GPIO */ 175 struct gpio_chipset_tag sc_gpio_gc; 176 struct gpio_pin sc_gpio_pins[SIO_GPIO_NPINS]; 177 178 /* TMS and VLM */ 179 struct ksensor sensors[SIO_NUM_SENSORS]; 180 struct ksensordev sensordev; 181 }; 182 183 #define GPIO_READ(sc, reg) \ 184 bus_space_read_1((sc)->sc_iot, \ 185 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg)) 186 #define GPIO_WRITE(sc, reg, val) \ 187 bus_space_write_1((sc)->sc_iot, \ 188 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val)) 189 #define TMS_WRITE(sc, reg, val) \ 190 bus_space_write_1((sc)->sc_iot, \ 191 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val)) 192 #define TMS_READ(sc, reg) \ 193 bus_space_read_1((sc)->sc_iot, \ 194 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg)) 195 #define VLM_WRITE(sc, reg, val) \ 196 bus_space_write_1((sc)->sc_iot, \ 197 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val)) 198 #define VLM_READ(sc, reg) \ 199 bus_space_read_1((sc)->sc_iot, \ 200 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg)) 201 202 int nsclpcsio_isa_match(struct device *, void *, void *); 203 void nsclpcsio_isa_attach(struct device *, struct device *, void *); 204 205 struct cfattach nsclpcsio_isa_ca = { 206 sizeof(struct nsclpcsio_softc), 207 nsclpcsio_isa_match, 208 nsclpcsio_isa_attach 209 }; 210 211 struct cfdriver nsclpcsio_cd = { 212 NULL, "nsclpcsio", DV_DULL 213 }; 214 215 struct timeout nsclpcsio_timeout; 216 217 static u_int8_t nsread(bus_space_tag_t, bus_space_handle_t, int); 218 static void nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); 219 220 void nsclpcsio_gpio_init(struct nsclpcsio_softc *); 221 int nsclpcsio_gpio_pin_read(void *, int); 222 void nsclpcsio_gpio_pin_write(void *, int, int); 223 void nsclpcsio_gpio_pin_ctl(void *, int, int); 224 225 void nsclpcsio_tms_init(struct nsclpcsio_softc *); 226 void nsclpcsio_vlm_init(struct nsclpcsio_softc *); 227 void nsclpcsio_tms_update(struct nsclpcsio_softc *); 228 void nsclpcsio_vlm_update(struct nsclpcsio_softc *); 229 void nsclpcsio_refresh(void *); 230 231 static u_int8_t 232 nsread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx) 233 { 234 bus_space_write_1(iot, ioh, 0, idx); 235 return (bus_space_read_1(iot, ioh, 1)); 236 } 237 238 static void 239 nswrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data) 240 { 241 bus_space_write_1(iot, ioh, 0, idx); 242 bus_space_write_1(iot, ioh, 1, data); 243 } 244 245 int 246 nsclpcsio_isa_match(struct device *parent, void *match, void *aux) 247 { 248 struct isa_attach_args *ia = aux; 249 bus_space_tag_t iot; 250 bus_space_handle_t ioh; 251 int iobase; 252 int rv = 0; 253 254 iot = ia->ia_iot; 255 iobase = ia->ipa_io[0].base; 256 if (bus_space_map(iot, iobase, 2, 0, &ioh)) 257 return (0); 258 259 if (nsread(iot, ioh, SIO_REG_SID) == SIO_SID_PC87366) 260 rv = 1; 261 262 bus_space_unmap(iot, ioh, 2); 263 264 if (rv) { 265 ia->ipa_nio = 1; 266 ia->ipa_io[0].length = 2; 267 268 ia->ipa_nmem = 0; 269 ia->ipa_nirq = 0; 270 ia->ipa_ndrq = 0; 271 } 272 273 return (rv); 274 } 275 276 void 277 nsclpcsio_isa_attach(struct device *parent, struct device *self, void *aux) 278 { 279 struct nsclpcsio_softc *sc = (void *)self; 280 struct isa_attach_args *ia = aux; 281 struct gpiobus_attach_args gba; 282 bus_space_tag_t iot; 283 int iobase; 284 int i; 285 286 iobase = ia->ipa_io[0].base; 287 sc->sc_iot = iot = ia->ia_iot; 288 if (bus_space_map(ia->ia_iot, iobase, 2, 0, &sc->sc_ioh)) { 289 printf(": can't map i/o space\n"); 290 return; 291 } 292 printf(": NSC PC87366 rev %d:", 293 nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID)); 294 295 /* Configure all supported logical devices */ 296 for (i = 0; i < sizeof(sio_ld) / sizeof(sio_ld[0]); i++) { 297 sc->sc_ld_en[sio_ld[i].ld_num] = 0; 298 299 /* Select the device and check if it's activated */ 300 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num); 301 if ((nsread(sc->sc_iot, sc->sc_ioh, 302 SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0) 303 continue; 304 305 /* Map I/O space if necessary */ 306 if (sio_ld[i].ld_iosize != 0) { 307 iobase = (nsread(sc->sc_iot, sc->sc_ioh, 308 SIO_REG_IO_MSB) << 8); 309 iobase |= nsread(sc->sc_iot, sc->sc_ioh, 310 SIO_REG_IO_LSB); 311 if (bus_space_map(sc->sc_iot, iobase, 312 sio_ld[i].ld_iosize, 0, 313 &sc->sc_ld_ioh[sio_ld[i].ld_num])) 314 continue; 315 } 316 317 sc->sc_ld_en[sio_ld[i].ld_num] = 1; 318 printf(" %s", sio_ld[i].ld_name); 319 } 320 321 printf("\n"); 322 323 nsclpcsio_gpio_init(sc); 324 nsclpcsio_tms_init(sc); 325 nsclpcsio_vlm_init(sc); 326 327 /* Hook into hw.sensors sysctl */ 328 strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, 329 sizeof(sc->sensordev.xname)); 330 for (i = 0; i < SIO_NUM_SENSORS; i++) { 331 if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS]) 332 continue; 333 if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM]) 334 continue; 335 sensor_attach(&sc->sensordev, &sc->sensors[i]); 336 } 337 sensordev_install(&sc->sensordev); 338 if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) { 339 timeout_set(&nsclpcsio_timeout, nsclpcsio_refresh, sc); 340 timeout_add(&nsclpcsio_timeout, (20 * hz) / 10); 341 } 342 343 /* Attach GPIO framework */ 344 if (sc->sc_ld_en[SIO_LDN_GPIO]) { 345 gba.gba_name = "gpio"; 346 gba.gba_gc = &sc->sc_gpio_gc; 347 gba.gba_pins = sc->sc_gpio_pins; 348 gba.gba_npins = SIO_GPIO_NPINS; 349 config_found(&sc->sc_dev, &gba, NULL); 350 } 351 } 352 353 void 354 nsclpcsio_refresh(void *arg) 355 { 356 struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg; 357 358 if (sc->sc_ld_en[SIO_LDN_TMS]) 359 nsclpcsio_tms_update(sc); 360 if (sc->sc_ld_en[SIO_LDN_VLM]) 361 nsclpcsio_vlm_update(sc); 362 timeout_add(&nsclpcsio_timeout, (20 * hz) / 10); 363 } 364 365 void 366 nsclpcsio_tms_init(struct nsclpcsio_softc *sc) 367 { 368 int i; 369 370 /* Initialisation, PC87366.pdf, page 208 */ 371 TMS_WRITE(sc, 0x08, 0x00); 372 TMS_WRITE(sc, 0x09, 0x0f); 373 TMS_WRITE(sc, 0x0a, 0x08); 374 TMS_WRITE(sc, 0x0b, 0x04); 375 TMS_WRITE(sc, 0x0c, 0x35); 376 TMS_WRITE(sc, 0x0d, 0x05); 377 TMS_WRITE(sc, 0x0e, 0x05); 378 379 TMS_WRITE(sc, SIO_TMSCFG, 0x00); 380 381 /* Enable the sensors */ 382 for (i = 0; i < 3; i++) { 383 TMS_WRITE(sc, SIO_TMSBS, i); 384 TMS_WRITE(sc, SIO_TCHCFST, 0x01); 385 386 sc->sensors[i].type = SENSOR_TEMP; 387 } 388 389 strlcpy(sc->sensors[0].desc, "Remote", sizeof(sc->sensors[0].desc)); 390 strlcpy(sc->sensors[1].desc, "Remote", sizeof(sc->sensors[1].desc)); 391 strlcpy(sc->sensors[2].desc, "Local", sizeof(sc->sensors[2].desc)); 392 393 nsclpcsio_tms_update(sc); 394 } 395 396 void 397 nsclpcsio_tms_update(struct nsclpcsio_softc *sc) 398 { 399 u_int8_t status; 400 int8_t sdata; 401 int i; 402 403 for (i = 0; i < 3; i++) { 404 TMS_WRITE(sc, SIO_TMSBS, i); 405 status = TMS_READ(sc, SIO_TCHCFST); 406 if (!(status & 0x01)) { 407 DPRINTF(("%s: status %d: disabled\n", 408 sc->sensors[i].desc, status)); 409 sc->sensors[i].value = 0; 410 continue; 411 } 412 sdata = TMS_READ(sc, SIO_RDCHT); 413 DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc, 414 status, sdata)); 415 sc->sensors[i].value = sdata * 1000000 + 273150000; 416 } 417 } 418 419 void 420 nsclpcsio_vlm_init(struct nsclpcsio_softc *sc) 421 { 422 int i; 423 char *desc = NULL; 424 425 VLM_WRITE(sc, SIO_VLMCFG, 0x00); 426 427 /* Enable the sensors */ 428 for (i = 0; i < 14; i++) { 429 VLM_WRITE(sc, SIO_VLMBS, i); 430 VLM_WRITE(sc, SIO_VCHCFST, 0x01); 431 432 desc = NULL; 433 switch (i) { 434 case 7: 435 desc = "VSB"; 436 break; 437 case 8: 438 desc = "VDD"; 439 break; 440 case 9: 441 desc = "VBAT"; 442 break; 443 case 10: 444 desc = "AVDD"; 445 break; 446 case 11: 447 desc = "TS1"; 448 break; 449 case 12: 450 desc = "TS2"; 451 break; 452 case 13: 453 desc = "TS3"; 454 break; 455 } 456 /* only init .desc if we have something meaningful to say */ 457 if (desc != NULL) 458 strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc, 459 sizeof(sc->sensors[SIO_VLM_OFF + i].desc)); 460 sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC; 461 462 } 463 nsclpcsio_vlm_update(sc); 464 } 465 466 void 467 nsclpcsio_vlm_update(struct nsclpcsio_softc *sc) 468 { 469 u_int8_t status; 470 u_int8_t data; 471 int scale, rfact, i; 472 473 for (i = 0; i < 14; i++) { 474 VLM_WRITE(sc, SIO_VLMBS, i); 475 status = VLM_READ(sc, SIO_VCHCFST); 476 if (!(status & 0x01)) { 477 DPRINTF(("%s: status %d: disabled\n", 478 sc->sensors[SIO_VLM_OFF + i].desc, status)); 479 sc->sensors[SIO_VLM_OFF + i].value = 0; 480 continue; 481 } 482 data = VLM_READ(sc, SIO_RDCHV); 483 DPRINTF(("%s: status %d V %d\n", 484 sc->sensors[SIO_VLM_OFF + i].desc, status, data)); 485 486 scale = 1; 487 switch (i) { 488 case 7: 489 case 8: 490 case 10: 491 scale = 2; 492 } 493 494 /* Vi = (2.45�0.05)*VREF *RDCHVi / 256 */ 495 rfact = 10 * scale * ((245 * SIO_VREF) >> 8); 496 sc->sensors[SIO_VLM_OFF + i].value = data * rfact; 497 } 498 } 499 500 static __inline void 501 nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin) 502 { 503 int port, shift; 504 u_int8_t data; 505 506 port = pin / 8; 507 shift = pin % 8; 508 data = (port << 4) | shift; 509 510 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 511 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data); 512 } 513 514 void 515 nsclpcsio_gpio_init(struct nsclpcsio_softc *sc) 516 { 517 int i; 518 519 for (i = 0; i < SIO_GPIO_NPINS; i++) { 520 sc->sc_gpio_pins[i].pin_num = i; 521 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 522 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | 523 GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | 524 GPIO_PIN_PULLUP; 525 526 /* Read initial state */ 527 sc->sc_gpio_pins[i].pin_state = nsclpcsio_gpio_pin_read(sc, 528 i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 529 } 530 531 /* Create controller tag */ 532 sc->sc_gpio_gc.gp_cookie = sc; 533 sc->sc_gpio_gc.gp_pin_read = nsclpcsio_gpio_pin_read; 534 sc->sc_gpio_gc.gp_pin_write = nsclpcsio_gpio_pin_write; 535 sc->sc_gpio_gc.gp_pin_ctl = nsclpcsio_gpio_pin_ctl; 536 } 537 538 int 539 nsclpcsio_gpio_pin_read(void *arg, int pin) 540 { 541 struct nsclpcsio_softc *sc = arg; 542 int port, shift, reg; 543 u_int8_t data; 544 545 port = pin / 8; 546 shift = pin % 8; 547 548 switch (port) { 549 case 0: 550 reg = SIO_GPDI0; 551 break; 552 case 1: 553 reg = SIO_GPDI1; 554 break; 555 case 2: 556 reg = SIO_GPDI2; 557 break; 558 case 3: 559 reg = SIO_GPDI3; 560 break; 561 } 562 563 data = GPIO_READ(sc, reg); 564 565 return ((data >> shift) & 0x1); 566 } 567 568 void 569 nsclpcsio_gpio_pin_write(void *arg, int pin, int value) 570 { 571 struct nsclpcsio_softc *sc = arg; 572 int port, shift, reg; 573 u_int8_t data; 574 575 port = pin / 8; 576 shift = pin % 8; 577 578 switch (port) { 579 case 0: 580 reg = SIO_GPDO0; 581 break; 582 case 1: 583 reg = SIO_GPDO1; 584 break; 585 case 2: 586 reg = SIO_GPDO2; 587 break; 588 case 3: 589 reg = SIO_GPDO3; 590 break; 591 } 592 593 data = GPIO_READ(sc, reg); 594 if (value == 0) 595 data &= ~(1 << shift); 596 else if (value == 1) 597 data |= (1 << shift); 598 599 GPIO_WRITE(sc, reg, data); 600 } 601 602 void 603 nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags) 604 { 605 struct nsclpcsio_softc *sc = arg; 606 u_int8_t conf = 1; 607 608 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 609 nsclpcsio_gpio_pin_select(sc, pin); 610 conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG); 611 612 conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL | 613 SIO_GPIO_CONF_PULLUP); 614 if ((flags & GPIO_PIN_TRISTATE) == 0) 615 conf |= SIO_GPIO_CONF_OUTPUTEN; 616 if (flags & GPIO_PIN_PUSHPULL) 617 conf |= SIO_GPIO_CONF_PUSHPULL; 618 if (flags & GPIO_PIN_PULLUP) 619 conf |= SIO_GPIO_CONF_PULLUP; 620 621 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf); 622 } 623