1 /* $NetBSD: gxio.c,v 1.29 2022/10/29 13:10:25 jmcneill Exp $ */ 2 /* 3 * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation. 4 * All rights reserved. 5 * 6 * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM 7 * Corporation. 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 * 3. Neither the name of the project nor the name of SOUM Corporation 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT and SOUM CORPORATION ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT AND SOUM CORPORATION 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.29 2022/10/29 13:10:25 jmcneill Exp $"); 35 36 #include "opt_cputypes.h" 37 #include "opt_gumstix.h" 38 #include "opt_gxio.h" 39 40 #include <sys/param.h> 41 #include <sys/device.h> 42 #include <sys/errno.h> 43 #include <sys/kernel.h> 44 45 #include <sys/systm.h> 46 47 #include <machine/bootconfig.h> 48 49 #if defined(CPU_XSCALE) 50 #include <arm/xscale/pxa2x0cpu.h> 51 #endif 52 #include <arm/xscale/pxa2x0reg.h> 53 #include <arm/xscale/pxa2x0var.h> 54 #include <arm/xscale/pxa2x0_gpio.h> 55 #include <evbarm/gumstix/gumstixreg.h> 56 #include <evbarm/gumstix/gumstixvar.h> 57 58 #include "ioconf.h" 59 #include "locators.h" 60 61 62 struct gxioconf { 63 const char *name; 64 void (*config)(void); 65 }; 66 67 #if defined(GUMSTIX) 68 static int gxiomatch(device_t, cfdata_t, void *); 69 static void gxioattach(device_t, device_t, void *); 70 static int gxiosearch(device_t, cfdata_t, const int *, void *); 71 static int gxioprint(void *, const char *); 72 73 CFATTACH_DECL_NEW(gxio, sizeof(struct gxio_softc), 74 gxiomatch, gxioattach, NULL, NULL); 75 #endif 76 77 void gxio_config(void); 78 void gxio_config_expansion(const char *); 79 #if defined(GUMSTIX) 80 static void basix_config(void); 81 static void cfstix_config(void); 82 static void etherstix_config(void); 83 static void netcf_config(void); 84 static void netcf_vx_config(void); 85 static void netduommc_config(void); 86 static void netduo_config(void); 87 static void netmicrosd_config(void); 88 static void netwifimicrosd_config(void); 89 static void netmmc_config(void); 90 static void wifistix_config(void); 91 static void wifistix_cf_config(void); 92 #endif 93 94 #if defined(CPU_XSCALE_PXA250) 95 96 static struct pxa2x0_gpioconf pxa255dep_gpioconf[] = { 97 /* Bluetooth module configuration */ 98 { 7, GPIO_OUT | GPIO_SET }, /* power on */ 99 { 12, GPIO_ALT_FN_1_OUT }, /* 32kHz out. required by SingleStone */ 100 101 /* AC97 configuration */ 102 { 29, GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */ 103 104 /* FFUART configuration */ 105 { 35, GPIO_ALT_FN_1_IN }, /* CTS */ 106 { 41, GPIO_ALT_FN_2_OUT }, /* RTS */ 107 108 #ifndef GXIO_BLUETOOTH_ON_HWUART 109 /* BTUART configuration */ 110 { 44, GPIO_ALT_FN_1_IN }, /* BTCTS */ 111 { 45, GPIO_ALT_FN_2_OUT }, /* BTRTS */ 112 #else 113 /* HWUART configuration */ 114 { 42, GPIO_ALT_FN_3_IN }, /* HWRXD */ 115 { 43, GPIO_ALT_FN_3_OUT }, /* HWTXD */ 116 { 44, GPIO_ALT_FN_3_IN }, /* HWCTS */ 117 { 45, GPIO_ALT_FN_3_OUT }, /* HWRTS */ 118 #endif 119 120 #ifndef GXIO_BLUETOOTH_ON_HWUART 121 /* HWUART configuration */ 122 { 48, GPIO_ALT_FN_1_OUT }, /* HWTXD */ 123 { 49, GPIO_ALT_FN_1_IN }, /* HWRXD */ 124 { 50, GPIO_ALT_FN_1_IN }, /* HWCTS */ 125 { 51, GPIO_ALT_FN_1_OUT }, /* HWRTS */ 126 #endif 127 128 { -1 } 129 }; 130 #endif 131 #if defined(CPU_XSCALE_PXA270) 132 static struct pxa2x0_gpioconf verdexdep_gpioconf[] = { 133 /* Bluetooth module configuration */ 134 { 9, GPIO_ALT_FN_3_OUT }, /* CHOUT<0> */ 135 { 12, GPIO_OUT | GPIO_SET }, 136 137 /* LCD configuration */ 138 { 17, GPIO_IN }, /* backlight on */ 139 140 /* FFUART configuration */ 141 { 34, GPIO_ALT_FN_1_IN }, /* FFRXD */ 142 { 39, GPIO_ALT_FN_2_OUT }, /* FFTXD */ 143 144 /* BTUART configuration */ 145 { 42, GPIO_ALT_FN_1_IN }, /* BTRXD */ 146 { 43, GPIO_ALT_FN_2_OUT }, /* BTTXD */ 147 { 44, GPIO_ALT_FN_1_IN }, /* BTCTS */ 148 { 45, GPIO_ALT_FN_2_OUT }, /* BTRTS */ 149 150 /* AC97 configuration */ 151 { 29, GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */ 152 153 { -1 } 154 }; 155 #endif 156 157 static const struct gxioconf gxioconflist[] = { 158 #if defined(GUMSTIX) 159 { "basix", basix_config }, 160 { "cfstix", cfstix_config }, 161 { "etherstix", etherstix_config }, 162 { "netcf", netcf_config }, 163 { "netcf-vx", netcf_vx_config }, 164 { "netduo-mmc", netduommc_config }, 165 { "netduo", netduo_config }, 166 { "netmicrosd", netmicrosd_config }, 167 { "netmicrosd-vx", netmicrosd_config }, 168 { "netwifimicrosd", netwifimicrosd_config }, 169 { "netmmc", netmmc_config }, 170 { "netpro-vx", netwifimicrosd_config }, 171 { "wifistix-cf", wifistix_cf_config }, 172 { "wifistix", wifistix_config }, 173 #endif 174 { NULL } 175 }; 176 177 int gxpcic_gpio_reset; 178 struct gxpcic_slot_irqs gxpcic_slot_irqs[2] = { { 0, -1, -1 }, { 0, -1, -1 } }; 179 180 181 #if defined(GUMSTIX) 182 /* ARGSUSED */ 183 static int 184 gxiomatch(device_t parent, cfdata_t match, void *aux) 185 { 186 187 struct pxaip_attach_args *pxa = aux; 188 bus_space_tag_t iot = &pxa2x0_bs_tag; 189 bus_space_handle_t ioh; 190 191 if (strcmp(pxa->pxa_name, match->cf_name) != 0 || 192 pxa->pxa_addr != PXAIPCF_ADDR_DEFAULT) 193 return 0; 194 195 if (bus_space_map(iot, 196 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &ioh)) 197 return 0; 198 bus_space_unmap(iot, ioh, PXA2X0_MEMCTL_SIZE); 199 200 /* nothing */ 201 return 1; 202 } 203 204 /* ARGSUSED */ 205 static void 206 gxioattach(device_t parent, device_t self, void *aux) 207 { 208 struct gxio_softc *sc = device_private(self); 209 210 aprint_normal("\n"); 211 aprint_naive("\n"); 212 213 sc->sc_dev = self; 214 sc->sc_iot = &pxa2x0_bs_tag; 215 216 if (bus_space_map(sc->sc_iot, 217 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh)) 218 return; 219 220 /* 221 * Attach each gumstix(busheader)/overo expansion board devices. 222 */ 223 config_search(self, NULL, 224 CFARGS(.search = gxiosearch)); 225 } 226 227 /* ARGSUSED */ 228 static int 229 gxiosearch(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 230 { 231 struct gxio_softc *sc = device_private(parent); 232 struct gxio_attach_args gxa; 233 234 gxa.gxa_sc = sc; 235 gxa.gxa_iot = sc->sc_iot; 236 gxa.gxa_addr = cf->cf_loc[GXIOCF_ADDR]; 237 gxa.gxa_gpirq = cf->cf_loc[GXIOCF_GPIRQ]; 238 239 if (config_probe(parent, cf, &gxa)) 240 config_attach(parent, cf, &gxa, gxioprint, CFARGS_NONE); 241 242 return 0; 243 } 244 245 /* ARGSUSED */ 246 static int 247 gxioprint(void *aux, const char *name) 248 { 249 struct gxio_attach_args *gxa = (struct gxio_attach_args *)aux; 250 251 if (gxa->gxa_addr != GXIOCF_ADDR_DEFAULT) 252 printf(" addr 0x%lx", gxa->gxa_addr); 253 if (gxa->gxa_gpirq > 0) 254 printf(" gpirq %d", gxa->gxa_gpirq); 255 return UNCONF; 256 } 257 #endif 258 259 260 #if defined(GUMSTIX) 261 /* 262 * configure for GPIO pin and expansion boards. 263 */ 264 void 265 gxio_config(void) 266 { 267 #if defined(CPU_XSCALE_PXA250) 268 struct pxa2x0_gpioconf *gumstix_gpioconf[] = { 269 pxa25x_com_ffuart_gpioconf, 270 pxa25x_com_stuart_gpioconf, 271 #ifndef GXIO_BLUETOOTH_ON_HWUART 272 pxa25x_com_btuart_gpioconf, 273 #endif 274 pxa25x_com_hwuart_gpioconf, 275 pxa25x_i2c_gpioconf, 276 pxa25x_pxaacu_gpioconf, 277 pxa255dep_gpioconf, 278 NULL 279 }; 280 #endif 281 #if defined(CPU_XSCALE_PXA270) 282 struct pxa2x0_gpioconf *verdex_gpioconf[] = { 283 pxa27x_com_ffuart_gpioconf, 284 pxa27x_com_stuart_gpioconf, 285 pxa27x_com_btuart_gpioconf, 286 pxa27x_i2c_gpioconf, 287 pxa27x_pxaacu_gpioconf, 288 pxa27x_pxamci_gpioconf, 289 pxa27x_ohci_gpioconf, 290 verdexdep_gpioconf, 291 NULL 292 }; 293 #endif 294 295 /* XXX: turn off for power of bluetooth module */ 296 #if defined(CPU_XSCALE_PXA250) 297 pxa2x0_gpio_set_function(7, GPIO_OUT | GPIO_CLR); 298 #elif defined(CPU_XSCALE_PXA270) 299 pxa2x0_gpio_set_function(12, GPIO_OUT | GPIO_CLR); 300 #endif 301 delay(100); 302 303 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250) 304 pxa2x0_gpio_config( 305 (CPU_IS_PXA250) ? gumstix_gpioconf : verdex_gpioconf); 306 #elif defined(CPU_XSCALE_PXA270) || defined(CPU_XSCALE_PXA250) 307 #if defined(CPU_XSCALE_PXA270) 308 pxa2x0_gpio_config(verdex_gpioconf); 309 #else 310 pxa2x0_gpio_config(gumstix_gpioconf); 311 #endif 312 #endif 313 } 314 #endif 315 316 static int 317 gxio_find_default_expansion(void) 318 { 319 #ifdef GXIO_DEFAULT_EXPANSION 320 int i; 321 322 /* Find out the default expansion */ 323 for (i = 0; gxioconflist[i].name != NULL; i++) 324 if (strncasecmp(gxioconflist[i].name, GXIO_DEFAULT_EXPANSION, 325 strlen(gxioconflist[i].name) + 1) == 0) 326 break; 327 return gxioconflist[i].name == NULL ? -1 : i; 328 #else 329 return -1; 330 #endif 331 } 332 333 void 334 gxio_config_expansion(const char *expansion) 335 { 336 int i, d; 337 338 d = gxio_find_default_expansion(); 339 340 /* Print information about expansions */ 341 printf("supported expansions:\n"); 342 for (i = 0; gxioconflist[i].name != NULL; i++) 343 printf(" %s%s\n", gxioconflist[i].name, 344 i == d ? " (DEFAULT)" : ""); 345 346 347 if (expansion == NULL) { 348 printf("not specified 'expansion=' in the boot args.\n"); 349 i = -1; 350 } else { 351 for (i = 0; gxioconflist[i].name != NULL; i++) 352 if (strncasecmp(gxioconflist[i].name, expansion, 353 strlen(gxioconflist[i].name) + 1) == 0) 354 break; 355 if (gxioconflist[i].name == NULL) { 356 printf("unknown expansion specified: %s\n", expansion); 357 i = -1; 358 } 359 } 360 361 /* 362 * Now proceed to configure the default expansion if one was 363 * specified (and found) or return. 364 */ 365 const char *toconfigure; 366 if (i < 0) { 367 #ifdef GXIO_DEFAULT_EXPANSION 368 if (d == -1) { 369 printf("default expansion (%s) not found\n", 370 GXIO_DEFAULT_EXPANSION); 371 return; 372 } 373 expansion = GXIO_DEFAULT_EXPANSION; 374 i = d; 375 toconfigure = "default"; 376 #else 377 return; 378 #endif 379 } else 380 toconfigure = "specified"; 381 382 printf("configure %s expansion (%s)\n", toconfigure, expansion); 383 gxioconflist[i].config(); 384 } 385 386 387 #if defined(GUMSTIX) 388 389 static void 390 basix_config(void) 391 { 392 393 pxa2x0_gpio_set_function(8, GPIO_ALT_FN_1_OUT); /* MMCCS0 */ 394 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_1_OUT); /* MMCCLK */ 395 #if 0 396 /* this configuration set by gxmci.c::pxamci_attach() */ 397 pxa2x0_gpio_set_function(11, GPIO_IN); /* nSD_DETECT */ 398 pxa2x0_gpio_set_function(22, GPIO_IN); /* nSD_WP */ 399 #endif 400 } 401 402 static void 403 cfstix_config(void) 404 { 405 u_int gpio, npoe_fn; 406 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250) 407 int bvd = (CPU_IS_PXA250) ? 4 : 111; 408 #else 409 #if defined(CPU_XSCALE_PXA270) 410 const int bvd = 111; 411 #else 412 const int bvd = 4; 413 #endif 414 #endif 415 416 if (CPU_IS_PXA250) { 417 gxpcic_slot_irqs[0].valid = 1; 418 gxpcic_slot_irqs[0].cd = 11; 419 gxpcic_slot_irqs[0].prdy = 26; 420 gxpcic_gpio_reset = 8; 421 } else { 422 gxpcic_slot_irqs[0].valid = 1; 423 gxpcic_slot_irqs[0].cd = 104; 424 gxpcic_slot_irqs[0].prdy = 96; 425 gxpcic_gpio_reset = 97; 426 } 427 428 #if 1 429 /* PCD/PRDY set by pxa2x0_pcic.c::pxapcic_attach_common() */ 430 #else 431 pxa2x0_gpio_set_function(11, GPIO_IN); /* PCD1 */ 432 pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY1/~IRQ1 */ 433 #endif 434 pxa2x0_gpio_set_function(bvd, GPIO_IN); /* BVD1/~STSCHG1 */ 435 436 for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++) 437 npoe_fn |= pxa2x0_gpio_get_function(gpio); 438 npoe_fn &= GPIO_SET; 439 440 pxa2x0_gpio_set_function(48, GPIO_ALT_FN_2_OUT | npoe_fn); /* nPOE */ 441 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ 442 pxa2x0_gpio_set_function(50, GPIO_ALT_FN_2_OUT); /* nPIOR */ 443 pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */ 444 if (CPU_IS_PXA250) { 445 pxa2x0_gpio_set_function(52, GPIO_ALT_FN_2_OUT); /* nPCE1 */ 446 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_2_OUT); /* nPCE2 */ 447 pxa2x0_gpio_set_function(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */ 448 } else { 449 pxa2x0_gpio_set_function(102, GPIO_ALT_FN_1_OUT); /* nPCE1 */ 450 pxa2x0_gpio_set_function(105, GPIO_ALT_FN_1_OUT); /* nPCE2 */ 451 pxa2x0_gpio_set_function(79, GPIO_ALT_FN_1_OUT); /* pSKTSEL */ 452 } 453 pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */ 454 pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN); /* nPWAIT */ 455 pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */ 456 } 457 458 static void 459 etherstix_config(void) 460 { 461 extern struct cfdata cfdata[]; 462 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250) 463 int rst = (CPU_IS_PXA250) ? 80 : 32; 464 int irq = (CPU_IS_PXA250) ? 36 : 99; 465 #else 466 #if defined(CPU_XSCALE_PXA270) 467 const int rst = 32, irq = 99; 468 #else 469 const int rst = 80, irq = 36; 470 #endif 471 #endif 472 int i; 473 474 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ 475 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */ 476 pxa2x0_gpio_set_function(rst, GPIO_OUT | GPIO_SET); /* RESET 1 */ 477 delay(1); 478 pxa2x0_gpio_set_function(rst, GPIO_OUT | GPIO_CLR); 479 delay(50000); 480 481 for (i = 0; cfdata[i].cf_name != NULL; i++) 482 if (strcmp(cfdata[i].cf_name, "sm") == 0 && 483 strcmp(cfdata[i].cf_atname, "sm_gxio") == 0 && 484 cfdata[i].cf_loc[GXIOCF_ADDR] == 0x04000300 && 485 cfdata[i].cf_loc[GXIOCF_GPIRQ] == GXIOCF_GPIRQ_DEFAULT) 486 cfdata[i].cf_loc[GXIOCF_GPIRQ] = irq; 487 } 488 489 static void 490 netcf_config(void) 491 { 492 493 etherstix_config(); 494 cfstix_config(); 495 } 496 497 static void 498 netcf_vx_config(void) 499 { 500 501 /* 502 * XXXX: More power is necessary for NIC and USB??? 503 * (no document. from Linux) 504 */ 505 506 pxa2x0_gpio_set_function(27, GPIO_IN); 507 pxa2x0_gpio_set_function(107, GPIO_OUT | GPIO_CLR); 508 pxa2x0_gpio_set_function(118, GPIO_ALT_FN_1_IN | GPIO_CLR); 509 510 etherstix_config(); 511 cfstix_config(); 512 if (CPU_IS_PXA270) { 513 /* Overwrite */ 514 gxpcic_slot_irqs[0].cd = 104; 515 gxpcic_slot_irqs[0].prdy = 109; 516 gxpcic_gpio_reset = 110; 517 }; 518 } 519 520 static void 521 netduommc_config(void) 522 { 523 524 netduo_config(); 525 basix_config(); 526 } 527 528 static void 529 netduo_config(void) 530 { 531 532 etherstix_config(); 533 534 pxa2x0_gpio_set_function(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */ 535 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */ 536 delay(1); 537 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR); 538 delay(50000); 539 } 540 541 static void 542 netmicrosd_config(void) 543 { 544 545 /* MicroSD(mci) always configure on PXA270 */ 546 547 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ 548 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */ 549 pxa2x0_gpio_set_function(107, GPIO_OUT | GPIO_CLR); /* RESET 1 */ 550 delay(hz / 2); 551 pxa2x0_gpio_set_function(107, GPIO_OUT | GPIO_SET); 552 delay(50000); 553 } 554 555 static void 556 netwifimicrosd_config(void) 557 { 558 559 netmicrosd_config(); 560 561 cfstix_config(); 562 /* However use pxamci. */ 563 pxa2x0_gpio_set_function(111, GPIO_CLR | GPIO_ALT_FN_1_IN); 564 /* Power to Marvell 88W8385 */ 565 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET); 566 } 567 568 static void 569 netmmc_config(void) 570 { 571 572 etherstix_config(); 573 basix_config(); 574 } 575 576 static void 577 wifistix_config(void) 578 { 579 580 cfstix_config(); 581 582 /* Power to Marvell 88W8385 */ 583 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET); 584 } 585 586 static void 587 wifistix_cf_config(void) 588 { 589 590 gxpcic_slot_irqs[1].valid = 1; 591 gxpcic_slot_irqs[1].cd = 36; 592 gxpcic_slot_irqs[1].prdy = 27; 593 594 #if 1 595 /* this configuration set by pxa2x0_pcic.c::pxapcic_attach_common() */ 596 #else 597 pxa2x0_gpio_set_function(36, GPIO_IN); /* PCD2 */ 598 pxa2x0_gpio_set_function(27, GPIO_IN); /* PRDY2/~IRQ2 */ 599 #endif 600 pxa2x0_gpio_set_function(18, GPIO_IN); /* BVD2/~STSCHG2 */ 601 602 cfstix_config(); 603 604 /* Power to Marvell 88W8385 */ 605 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET); 606 } 607 #endif 608