1 /* $OpenBSD: nsclpcsio_isa.c,v 1.5 2004/11/17 16:53:05 mickey 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 sensor sensors[SIO_NUM_SENSORS]; 180 }; 181 182 #define GPIO_READ(sc, reg) \ 183 bus_space_read_1((sc)->sc_iot, \ 184 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg)) 185 #define GPIO_WRITE(sc, reg, val) \ 186 bus_space_write_1((sc)->sc_iot, \ 187 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val)) 188 #define TMS_WRITE(sc, reg, val) \ 189 bus_space_write_1((sc)->sc_iot, \ 190 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val)) 191 #define TMS_READ(sc, reg) \ 192 bus_space_read_1((sc)->sc_iot, \ 193 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg)) 194 #define VLM_WRITE(sc, reg, val) \ 195 bus_space_write_1((sc)->sc_iot, \ 196 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val)) 197 #define VLM_READ(sc, reg) \ 198 bus_space_read_1((sc)->sc_iot, \ 199 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg)) 200 201 int nsclpcsio_isa_match(struct device *, void *, void *); 202 void nsclpcsio_isa_attach(struct device *, struct device *, void *); 203 204 struct cfattach nsclpcsio_isa_ca = { 205 sizeof(struct nsclpcsio_softc), 206 nsclpcsio_isa_match, 207 nsclpcsio_isa_attach 208 }; 209 210 struct cfdriver nsclpcsio_cd = { 211 NULL, "nsclpcsio", DV_DULL 212 }; 213 214 struct timeout nsclpcsio_timeout; 215 216 static u_int8_t nsread(bus_space_tag_t, bus_space_handle_t, int); 217 static void nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); 218 219 void nsclpcsio_gpio_init(struct nsclpcsio_softc *); 220 int nsclpcsio_gpio_pin_read(void *, int); 221 void nsclpcsio_gpio_pin_write(void *, int, int); 222 void nsclpcsio_gpio_pin_ctl(void *, int, int); 223 224 void nsclpcsio_tms_init(struct nsclpcsio_softc *); 225 void nsclpcsio_vlm_init(struct nsclpcsio_softc *); 226 void nsclpcsio_tms_update(struct nsclpcsio_softc *); 227 void nsclpcsio_vlm_update(struct nsclpcsio_softc *); 228 void nsclpcsio_refresh(void *); 229 230 static u_int8_t 231 nsread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx) 232 { 233 bus_space_write_1(iot, ioh, 0, idx); 234 return (bus_space_read_1(iot, ioh, 1)); 235 } 236 237 static void 238 nswrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data) 239 { 240 bus_space_write_1(iot, ioh, 0, idx); 241 bus_space_write_1(iot, ioh, 1, data); 242 } 243 244 int 245 nsclpcsio_isa_match(struct device *parent, void *match, void *aux) 246 { 247 struct isa_attach_args *ia = aux; 248 bus_space_tag_t iot; 249 bus_space_handle_t ioh; 250 int iobase; 251 int rv = 0; 252 253 iot = ia->ia_iot; 254 iobase = ia->ipa_io[0].base; 255 if (bus_space_map(iot, iobase, 2, 0, &ioh)) 256 return (0); 257 258 if (nsread(iot, ioh, SIO_REG_SID) == SIO_SID_PC87366) 259 rv = 1; 260 261 bus_space_unmap(iot, ioh, 2); 262 263 if (rv) { 264 ia->ipa_nio = 1; 265 ia->ipa_io[0].length = 2; 266 267 ia->ipa_nmem = 0; 268 ia->ipa_nirq = 0; 269 ia->ipa_ndrq = 0; 270 } 271 272 return (rv); 273 } 274 275 void 276 nsclpcsio_isa_attach(struct device *parent, struct device *self, void *aux) 277 { 278 struct nsclpcsio_softc *sc = (void *)self; 279 struct isa_attach_args *ia = aux; 280 struct gpiobus_attach_args gba; 281 bus_space_tag_t iot; 282 int iobase; 283 int i; 284 285 iobase = ia->ipa_io[0].base; 286 sc->sc_iot = iot = ia->ia_iot; 287 if (bus_space_map(ia->ia_iot, iobase, 2, 0, &sc->sc_ioh)) { 288 printf(": can't map i/o space\n"); 289 return; 290 } 291 printf(": NSC PC87366 rev %d:", 292 nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID)); 293 294 /* Configure all supported logical devices */ 295 for (i = 0; i < sizeof(sio_ld) / sizeof(sio_ld[0]); i++) { 296 sc->sc_ld_en[sio_ld[i].ld_num] = 0; 297 298 /* Select the device and check if it's activated */ 299 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num); 300 if ((nsread(sc->sc_iot, sc->sc_ioh, 301 SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0) 302 continue; 303 304 /* Map I/O space if necessary */ 305 if (sio_ld[i].ld_iosize != 0) { 306 iobase = (nsread(sc->sc_iot, sc->sc_ioh, 307 SIO_REG_IO_MSB) << 8); 308 iobase |= nsread(sc->sc_iot, sc->sc_ioh, 309 SIO_REG_IO_LSB); 310 if (bus_space_map(sc->sc_iot, iobase, 311 sio_ld[i].ld_iosize, 0, 312 &sc->sc_ld_ioh[sio_ld[i].ld_num])) 313 continue; 314 } 315 316 sc->sc_ld_en[sio_ld[i].ld_num] = 1; 317 printf(" %s", sio_ld[i].ld_name); 318 } 319 320 printf("\n"); 321 322 nsclpcsio_gpio_init(sc); 323 nsclpcsio_tms_init(sc); 324 nsclpcsio_vlm_init(sc); 325 326 /* Hook into hw.sensors sysctl */ 327 for (i = 0; i < SIO_NUM_SENSORS; i++) { 328 if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS]) 329 continue; 330 if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM]) 331 continue; 332 strlcpy(sc->sensors[i].device, sc->sc_dev.dv_xname, 333 sizeof(sc->sensors[i].device)); 334 SENSOR_ADD(&sc->sensors[i]); 335 } 336 if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) { 337 timeout_set(&nsclpcsio_timeout, nsclpcsio_refresh, sc); 338 timeout_add(&nsclpcsio_timeout, (20 * hz) / 10); 339 } 340 341 /* Attach GPIO framework */ 342 if (sc->sc_ld_en[SIO_LDN_GPIO]) { 343 gba.gba_name = "gpio"; 344 gba.gba_gc = &sc->sc_gpio_gc; 345 gba.gba_pins = sc->sc_gpio_pins; 346 gba.gba_npins = SIO_GPIO_NPINS; 347 config_found(&sc->sc_dev, &gba, NULL); 348 } 349 } 350 351 void 352 nsclpcsio_refresh(void *arg) 353 { 354 struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg; 355 356 if (sc->sc_ld_en[SIO_LDN_TMS]) 357 nsclpcsio_tms_update(sc); 358 if (sc->sc_ld_en[SIO_LDN_VLM]) 359 nsclpcsio_vlm_update(sc); 360 timeout_add(&nsclpcsio_timeout, (20 * hz) / 10); 361 } 362 363 void 364 nsclpcsio_tms_init(struct nsclpcsio_softc *sc) 365 { 366 int i; 367 368 /* Initialisation, PC87366.pdf, page 208 */ 369 TMS_WRITE(sc, 0x08, 0x00); 370 TMS_WRITE(sc, 0x09, 0x0f); 371 TMS_WRITE(sc, 0x0a, 0x08); 372 TMS_WRITE(sc, 0x0b, 0x04); 373 TMS_WRITE(sc, 0x0c, 0x35); 374 TMS_WRITE(sc, 0x0d, 0x05); 375 TMS_WRITE(sc, 0x0e, 0x05); 376 377 TMS_WRITE(sc, SIO_TMSCFG, 0x00); 378 379 /* Enable the sensors */ 380 for (i = 0; i < 3; i++) { 381 TMS_WRITE(sc, SIO_TMSBS, i); 382 TMS_WRITE(sc, SIO_TCHCFST, 0x01); 383 384 sc->sensors[i].type = SENSOR_TEMP; 385 } 386 387 strlcpy(sc->sensors[0].desc, "TSENS1", sizeof(sc->sensors[0].desc)); 388 strlcpy(sc->sensors[1].desc, "TSENS2", sizeof(sc->sensors[0].desc)); 389 strlcpy(sc->sensors[2].desc, "TNSC", sizeof(sc->sensors[0].desc)); 390 391 nsclpcsio_tms_update(sc); 392 } 393 394 void 395 nsclpcsio_tms_update(struct nsclpcsio_softc *sc) 396 { 397 u_int8_t status; 398 int8_t sdata; 399 int i; 400 401 for (i = 0; i < 3; i++) { 402 TMS_WRITE(sc, SIO_TMSBS, i); 403 status = TMS_READ(sc, SIO_TCHCFST); 404 if (!(status & 0x01)) { 405 DPRINTF(("%s: status %d: disabled\n", 406 sc->sensors[i].desc, status)); 407 sc->sensors[i].value = 0; 408 continue; 409 } 410 sdata = TMS_READ(sc, SIO_RDCHT); 411 DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc, 412 status, sdata)); 413 sc->sensors[i].value = sdata * 1000000 + 273150000; 414 } 415 } 416 417 void 418 nsclpcsio_vlm_init(struct nsclpcsio_softc *sc) 419 { 420 int scale, i; 421 char *desc = NULL; 422 423 VLM_WRITE(sc, SIO_VLMCFG, 0x00); 424 425 /* Enable the sensors */ 426 for (i = 0; i < 14; i++) { 427 VLM_WRITE(sc, SIO_VLMBS, i); 428 VLM_WRITE(sc, SIO_VCHCFST, 0x01); 429 430 desc = NULL; 431 scale = 1; 432 switch (i) { 433 case 7: 434 desc = "VSB"; 435 scale = 2; 436 break; 437 case 8: 438 desc = "VDD"; 439 scale = 2; 440 break; 441 case 9: 442 desc = "VBAT"; 443 break; 444 case 10: 445 desc = "AVDD"; 446 scale = 2; 447 break; 448 case 11: 449 desc = "TS1"; 450 break; 451 case 12: 452 desc = "TS2"; 453 break; 454 case 13: 455 desc = "TS3"; 456 break; 457 } 458 if (desc != NULL) 459 strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc, 460 sizeof(sc->sensors[SIO_VLM_OFF + i].desc)); 461 else 462 snprintf(sc->sensors[SIO_VLM_OFF + i].desc, 463 sizeof(sc->sensors[SIO_VLM_OFF].desc), "VSENS%d", i); 464 sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC; 465 466 /* Vi = (2.45�0.05)*VREF *RDCHVi / 256 */ 467 sc->sensors[SIO_VLM_OFF + i].rfact = 468 10 * scale * ((245 * SIO_VREF) >> 8); 469 } 470 nsclpcsio_vlm_update(sc); 471 } 472 473 void 474 nsclpcsio_vlm_update(struct nsclpcsio_softc *sc) 475 { 476 u_int8_t status; 477 u_int8_t data; 478 int i; 479 480 for (i = 0; i < 14; i++) { 481 VLM_WRITE(sc, SIO_VLMBS, i); 482 status = VLM_READ(sc, SIO_VCHCFST); 483 if (!(status & 0x01)) { 484 DPRINTF(("%s: status %d: disabled\n", 485 sc->sensors[SIO_VLM_OFF + i].desc, status)); 486 sc->sensors[SIO_VLM_OFF + i].value = 0; 487 continue; 488 } 489 data = VLM_READ(sc, SIO_RDCHV); 490 DPRINTF(("%s: status %d V %d\n", 491 sc->sensors[SIO_VLM_OFF + i].desc, status, data)); 492 sc->sensors[SIO_VLM_OFF + i].value = 493 data * sc->sensors[SIO_VLM_OFF + i].rfact; 494 } 495 } 496 497 static __inline void 498 nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin) 499 { 500 int port, shift; 501 u_int8_t data; 502 503 port = pin / 8; 504 shift = pin % 8; 505 data = (port << 4) | shift; 506 507 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 508 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data); 509 } 510 511 void 512 nsclpcsio_gpio_init(struct nsclpcsio_softc *sc) 513 { 514 int i; 515 516 for (i = 0; i < SIO_GPIO_NPINS; i++) { 517 sc->sc_gpio_pins[i].pin_num = i; 518 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 519 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | 520 GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | 521 GPIO_PIN_PULLUP; 522 523 /* safe defaults */ 524 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_TRISTATE; 525 sc->sc_gpio_pins[i].pin_state = GPIO_PIN_LOW; 526 nsclpcsio_gpio_pin_ctl(sc, i, sc->sc_gpio_pins[i].pin_flags); 527 nsclpcsio_gpio_pin_write(sc, i, sc->sc_gpio_pins[i].pin_state); 528 } 529 530 /* Create controller tag */ 531 sc->sc_gpio_gc.gp_cookie = sc; 532 sc->sc_gpio_gc.gp_pin_read = nsclpcsio_gpio_pin_read; 533 sc->sc_gpio_gc.gp_pin_write = nsclpcsio_gpio_pin_write; 534 sc->sc_gpio_gc.gp_pin_ctl = nsclpcsio_gpio_pin_ctl; 535 } 536 537 int 538 nsclpcsio_gpio_pin_read(void *arg, int pin) 539 { 540 struct nsclpcsio_softc *sc = arg; 541 int port, shift, reg; 542 u_int8_t data; 543 544 port = pin / 8; 545 shift = pin % 8; 546 547 switch (port) { 548 case 0: 549 reg = SIO_GPDI0; 550 break; 551 case 1: 552 reg = SIO_GPDI1; 553 break; 554 case 2: 555 reg = SIO_GPDI2; 556 break; 557 case 3: 558 reg = SIO_GPDI3; 559 break; 560 } 561 562 data = GPIO_READ(sc, reg); 563 564 return ((data >> shift) & 0x1); 565 } 566 567 void 568 nsclpcsio_gpio_pin_write(void *arg, int pin, int value) 569 { 570 struct nsclpcsio_softc *sc = arg; 571 int port, shift, reg; 572 u_int8_t data; 573 574 port = pin / 8; 575 shift = pin % 8; 576 577 switch (port) { 578 case 0: 579 reg = SIO_GPDO0; 580 break; 581 case 1: 582 reg = SIO_GPDO1; 583 break; 584 case 2: 585 reg = SIO_GPDO2; 586 break; 587 case 3: 588 reg = SIO_GPDO3; 589 break; 590 } 591 592 data = GPIO_READ(sc, reg); 593 if (value == 0) 594 data &= ~(1 << shift); 595 else if (value == 1) 596 data |= (1 << shift); 597 598 GPIO_WRITE(sc, reg, data); 599 } 600 601 void 602 nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags) 603 { 604 struct nsclpcsio_softc *sc = arg; 605 u_int8_t conf = 1; 606 607 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 608 nsclpcsio_gpio_pin_select(sc, pin); 609 conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG); 610 611 conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL | 612 SIO_GPIO_CONF_PULLUP); 613 if ((flags & GPIO_PIN_TRISTATE) == 0) 614 conf |= SIO_GPIO_CONF_OUTPUTEN; 615 if (flags & GPIO_PIN_PUSHPULL) 616 conf |= SIO_GPIO_CONF_PUSHPULL; 617 if (flags & GPIO_PIN_PULLUP) 618 conf |= SIO_GPIO_CONF_PULLUP; 619 620 nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf); 621 } 622