1 /* $NetBSD: gxio.c,v 1.7 2007/10/17 19:54:12 garbled 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.7 2007/10/17 19:54:12 garbled Exp $"); 35 36 #include "opt_gxio.h" 37 38 #include <sys/param.h> 39 #include <sys/device.h> 40 #include <sys/errno.h> 41 42 #include <sys/systm.h> 43 44 #include <machine/bootconfig.h> 45 46 #include <arm/xscale/pxa2x0cpu.h> 47 #include <arm/xscale/pxa2x0reg.h> 48 #include <arm/xscale/pxa2x0var.h> 49 #include <arm/xscale/pxa2x0_gpio.h> 50 #include <evbarm/gumstix/gumstixvar.h> 51 52 #include "locators.h" 53 54 55 struct gxioconf { 56 const char *name; 57 void (*config)(void); 58 }; 59 60 static int gxiomatch(struct device *, struct cfdata *, void *); 61 static void gxioattach(struct device *, struct device *, void *); 62 static int gxiosearch(struct device *, struct cfdata *, const int *, void *); 63 static int gxioprint(void *, const char *); 64 65 void gxio_config_pin(void); 66 void gxio_config_expansion(char *); 67 static void gxio_config_gpio(const struct gxioconf *, char *); 68 static void basix_config(void); 69 static void cfstix_config(void); 70 static void etherstix_config(void); 71 static void netcf_config(void); 72 static void netduommc_config(void); 73 static void netduo_config(void); 74 static void netmmc_config(void); 75 static void wifistix_cf_config(void); 76 77 CFATTACH_DECL( 78 gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL); 79 80 char busheader[MAX_BOOT_STRING]; 81 82 static struct pxa2x0_gpioconf boarddep_gpioconf[] = { 83 /* Bluetooth module configuration */ 84 { 7, GPIO_OUT | GPIO_SET }, /* power on */ 85 { 12, GPIO_ALT_FN_1_OUT }, /* 32kHz out. required by SingleStone */ 86 87 /* AC97 configuration */ 88 { 29, GPIO_CLR | GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */ 89 90 #ifndef GXIO_BLUETOOTH_ON_HWUART 91 /* BTUART configuration */ 92 { 44, GPIO_ALT_FN_1_IN }, /* BTCST */ 93 { 45, GPIO_ALT_FN_2_OUT }, /* BTRST */ 94 #else 95 /* HWUART configuration */ 96 { 42, GPIO_ALT_FN_3_IN }, /* HWRXD */ 97 { 43, GPIO_ALT_FN_3_OUT }, /* HWTXD */ 98 { 44, GPIO_ALT_FN_3_IN }, /* HWCST */ 99 { 45, GPIO_ALT_FN_3_OUT }, /* HWRST */ 100 #endif 101 102 #ifndef GXIO_BLUETOOTH_ON_HWUART 103 /* HWUART configuration */ 104 { 48, GPIO_ALT_FN_1_OUT }, /* HWTXD */ 105 { 49, GPIO_ALT_FN_1_IN }, /* HWRXD */ 106 { 50, GPIO_ALT_FN_1_IN }, /* HWCTS */ 107 { 51, GPIO_ALT_FN_1_OUT }, /* HWRTS */ 108 #endif 109 110 { -1 } 111 }; 112 113 static const struct gxioconf busheader_conf[] = { 114 { "basix", basix_config }, 115 { "cfstix", cfstix_config }, 116 { "etherstix", etherstix_config }, 117 { "netcf", netcf_config }, 118 { "netduo-mmc", netduommc_config }, 119 { "netduo", netduo_config }, 120 { "netmmc", netmmc_config }, 121 { "wifistix-cf", wifistix_cf_config }, 122 { "wifistix", cfstix_config }, 123 { NULL } 124 }; 125 126 127 /* ARGSUSED */ 128 static int 129 gxiomatch(struct device *parent, struct cfdata *match, void *aux) 130 { 131 bus_space_tag_t iot = &pxa2x0_bs_tag; 132 bus_space_handle_t ioh; 133 134 if (bus_space_map(iot, 135 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &ioh)) 136 return (0); 137 bus_space_unmap(iot, ioh, PXA2X0_MEMCTL_SIZE); 138 139 /* nothing */ 140 return (1); 141 } 142 143 /* ARGSUSED */ 144 static void 145 gxioattach(struct device *parent, struct device *self, void *aux) 146 { 147 struct gxio_softc *sc = device_private(self); 148 149 aprint_normal("\n"); 150 aprint_naive("\n"); 151 152 sc->sc_iot = &pxa2x0_bs_tag; 153 154 if (bus_space_map(sc->sc_iot, 155 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh)) 156 return; 157 158 /* 159 * Attach each gumstix expansion of busheader side devices 160 */ 161 config_search_ia(gxiosearch, self, "gxio", NULL); 162 } 163 164 /* ARGSUSED */ 165 static int 166 gxiosearch( 167 struct device *parent, struct cfdata *cf, const int *ldesc, void *aux) 168 { 169 struct gxio_softc *sc = device_private(parent); 170 struct gxio_attach_args gxa; 171 172 gxa.gxa_sc = sc; 173 gxa.gxa_iot = sc->sc_iot; 174 gxa.gxa_addr = cf->cf_loc[GXIOCF_ADDR]; 175 gxa.gxa_gpirq = cf->cf_loc[GXIOCF_GPIRQ]; 176 177 if (config_match(parent, cf, &gxa)) 178 config_attach(parent, cf, &gxa, gxioprint); 179 180 return (0); 181 } 182 183 /* ARGSUSED */ 184 static int 185 gxioprint(void *aux, const char *name) 186 { 187 struct gxio_attach_args *gxa = (struct gxio_attach_args *)aux; 188 189 if (gxa->gxa_addr != GXIOCF_ADDR_DEFAULT) 190 printf(" addr 0x%lx", gxa->gxa_addr); 191 if (gxa->gxa_gpirq > 0) 192 printf(" gpirq %d", gxa->gxa_gpirq); 193 return (UNCONF); 194 } 195 196 197 /* 198 * configure for GPIO pin and expansion boards. 199 */ 200 void 201 gxio_config_pin() 202 { 203 struct pxa2x0_gpioconf *gumstix_gpioconf[] = { 204 pxa25x_com_ffuart_gpioconf, 205 pxa25x_com_stuart_gpioconf, 206 #ifndef GXIO_BLUETOOTH_ON_HWUART 207 pxa25x_com_btuart_gpioconf, 208 #endif 209 pxa25x_com_hwuart_gpioconf, 210 pxa25x_i2c_gpioconf, 211 pxa25x_pxaacu_gpioconf, 212 boarddep_gpioconf, 213 NULL 214 }; 215 216 /* XXX: turn off for power of bluetooth module */ 217 pxa2x0_gpio_set_function(7, GPIO_OUT | GPIO_CLR); 218 delay(100); 219 220 pxa2x0_gpio_config(gumstix_gpioconf); 221 } 222 223 void 224 gxio_config_expansion(char *expansion) 225 { 226 #ifdef GXIO_DEFAULT_EXPANSION 227 char default_expansion[] = GXIO_DEFAULT_EXPANSION; 228 #endif 229 230 if (expansion == NULL) { 231 #ifndef GXIO_DEFAULT_EXPANSION 232 return; 233 #else 234 printf("not specified 'busheader=' in the boot args.\n"); 235 printf("configure default expansion (%s)\n", 236 GXIO_DEFAULT_EXPANSION); 237 expansion = default_expansion; 238 #endif 239 } 240 gxio_config_gpio(busheader_conf, expansion); 241 } 242 243 static void 244 gxio_config_gpio(const struct gxioconf *gxioconflist, char *expansion) 245 { 246 int i, rv; 247 248 for (i = 0; i < strlen(expansion); i++) 249 expansion[i] = tolower(expansion[i]); 250 for (i = 0; gxioconflist[i].name != NULL; i++) { 251 rv = strncmp(expansion, gxioconflist[i].name, 252 strlen(gxioconflist[i].name) + 1); 253 if (rv == 0) { 254 gxioconflist[i].config(); 255 break; 256 } 257 } 258 } 259 260 261 static void 262 basix_config() 263 { 264 265 pxa2x0_gpio_set_function(8, GPIO_ALT_FN_1_OUT); /* MMCCS0 */ 266 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_1_OUT); /* MMCCLK */ 267 #if 0 268 /* this configuration set by gxmci.c::pxamci_attach() */ 269 pxa2x0_gpio_set_function(11, GPIO_IN); /* nSD_DETECT */ 270 pxa2x0_gpio_set_function(22, GPIO_IN); /* nSD_WP */ 271 #endif 272 } 273 274 static void 275 cfstix_config() 276 { 277 u_int gpio, npoe_fn; 278 279 #if 1 280 /* this configuration set by pxa2x0_pcic.c::pxapcic_attach_common() */ 281 #else 282 pxa2x0_gpio_set_function(11, GPIO_IN); /* PCD1 */ 283 pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY1/~IRQ1 */ 284 #endif 285 pxa2x0_gpio_set_function(4, GPIO_IN); /* BVD1/~STSCHG1 */ 286 287 for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++) 288 npoe_fn |= pxa2x0_gpio_get_function(gpio); 289 npoe_fn &= GPIO_SET; 290 291 pxa2x0_gpio_set_function(48, GPIO_ALT_FN_2_OUT | npoe_fn); /* nPOE */ 292 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ 293 pxa2x0_gpio_set_function(50, GPIO_ALT_FN_2_OUT); /* nPIOR */ 294 pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */ 295 pxa2x0_gpio_set_function(52, GPIO_ALT_FN_2_OUT); /* nPCE1 */ 296 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_2_OUT); /* nPCE2 */ 297 pxa2x0_gpio_set_function(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */ 298 pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */ 299 pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN); /* nPWAIT */ 300 pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */ 301 } 302 303 static void 304 etherstix_config() 305 { 306 307 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */ 308 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */ 309 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET); /* RESET 1 */ 310 delay(1); 311 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_CLR); 312 delay(50000); 313 } 314 315 static void 316 netcf_config() 317 { 318 319 etherstix_config(); 320 cfstix_config(); 321 } 322 323 static void 324 netduommc_config() 325 { 326 327 netduo_config(); 328 basix_config(); 329 } 330 331 static void 332 netduo_config() 333 { 334 335 etherstix_config(); 336 337 pxa2x0_gpio_set_function(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */ 338 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */ 339 delay(1); 340 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR); 341 delay(50000); 342 } 343 344 static void 345 netmmc_config() 346 { 347 348 etherstix_config(); 349 basix_config(); 350 } 351 352 static void 353 wifistix_cf_config() 354 { 355 356 #if 1 357 /* this configuration set by pxa2x0_pcic.c::pxapcic_attach_common() */ 358 #else 359 pxa2x0_gpio_set_function(36, GPIO_IN); /* PCD2 */ 360 pxa2x0_gpio_set_function(27, GPIO_IN); /* PRDY2/~IRQ2 */ 361 #endif 362 pxa2x0_gpio_set_function(18, GPIO_IN); /* BVD2/~STSCHG2 */ 363 364 cfstix_config(); 365 } 366