No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / evbarm / gumstix / gxio.c
blobe883dbc7ca450790a5c1fbbda41ad8c3e7f4616d
1 /* $NetBSD: gxio.c,v 1.12 2009/11/22 12:00:56 kiyohara Exp $ */
2 /*
3 * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation.
4 * All rights reserved.
6 * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM
7 * Corporation.
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.
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.12 2009/11/22 12:00:56 kiyohara Exp $");
36 #include "opt_gxio.h"
38 #include <sys/param.h>
39 #include <sys/device.h>
40 #include <sys/errno.h>
41 #include <sys/kernel.h>
43 #include <sys/systm.h>
45 #include <machine/bootconfig.h>
47 #include <arm/xscale/pxa2x0cpu.h>
48 #include <arm/xscale/pxa2x0reg.h>
49 #include <arm/xscale/pxa2x0var.h>
50 #include <arm/xscale/pxa2x0_gpio.h>
51 #include <evbarm/gumstix/gumstixvar.h>
53 #include "locators.h"
56 struct gxioconf {
57 const char *name;
58 void (*config)(void);
61 static int gxiomatch(device_t, cfdata_t, void *);
62 static void gxioattach(device_t, device_t, void *);
63 static int gxiosearch(device_t, cfdata_t, const int *, void *);
64 static int gxioprint(void *, const char *);
66 void gxio_config_pin(void);
67 void gxio_config_expansion(char *);
68 static void gxio_config_gpio(const struct gxioconf *, char *);
69 static void basix_config(void);
70 static void cfstix_config(void);
71 static void etherstix_config(void);
72 static void netcf_config(void);
73 static void netduommc_config(void);
74 static void netduo_config(void);
75 static void netmicrosd_config(void);
76 static void netwifimicrosd_config(void);
77 static void netmmc_config(void);
78 static void wifistix_config(void);
79 static void wifistix_cf_config(void);
81 CFATTACH_DECL_NEW(
82 gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL);
84 char busheader[MAX_BOOT_STRING];
86 #if defined(CPU_XSCALE_PXA250)
87 static struct pxa2x0_gpioconf pxa255dep_gpioconf[] = {
88 /* Bluetooth module configuration */
89 { 7, GPIO_OUT | GPIO_SET }, /* power on */
90 { 12, GPIO_ALT_FN_1_OUT }, /* 32kHz out. required by SingleStone */
92 /* AC97 configuration */
93 { 29, GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */
95 /* FFUART configuration */
96 { 35, GPIO_ALT_FN_1_IN }, /* CTS */
97 { 41, GPIO_ALT_FN_2_OUT }, /* RTS */
99 #ifndef GXIO_BLUETOOTH_ON_HWUART
100 /* BTUART configuration */
101 { 44, GPIO_ALT_FN_1_IN }, /* BTCTS */
102 { 45, GPIO_ALT_FN_2_OUT }, /* BTRTS */
103 #else
104 /* HWUART configuration */
105 { 42, GPIO_ALT_FN_3_IN }, /* HWRXD */
106 { 43, GPIO_ALT_FN_3_OUT }, /* HWTXD */
107 { 44, GPIO_ALT_FN_3_IN }, /* HWCTS */
108 { 45, GPIO_ALT_FN_3_OUT }, /* HWRTS */
109 #endif
111 #ifndef GXIO_BLUETOOTH_ON_HWUART
112 /* HWUART configuration */
113 { 48, GPIO_ALT_FN_1_OUT }, /* HWTXD */
114 { 49, GPIO_ALT_FN_1_IN }, /* HWRXD */
115 { 50, GPIO_ALT_FN_1_IN }, /* HWCTS */
116 { 51, GPIO_ALT_FN_1_OUT }, /* HWRTS */
117 #endif
119 { -1 }
121 #endif
122 #if defined(CPU_XSCALE_PXA270)
123 static struct pxa2x0_gpioconf verdexdep_gpioconf[] = {
124 /* Bluetooth module configuration */
125 { 9, GPIO_ALT_FN_3_OUT }, /* CHOUT<0> */
126 { 12, GPIO_OUT | GPIO_SET },
128 /* LCD configuration */
129 { 17, GPIO_IN }, /* backlight on */
131 /* FFUART configuration */
132 { 27, GPIO_ALT_FN_3_OUT }, /* FFRTS */
133 { 34, GPIO_ALT_FN_1_IN }, /* FFRXD */
134 { 39, GPIO_ALT_FN_2_OUT }, /* FFTXD */
135 { 100, GPIO_ALT_FN_3_IN }, /* FFCTS */
137 /* BTUART configuration */
138 { 42, GPIO_ALT_FN_1_IN }, /* BTRXD */
139 { 43, GPIO_ALT_FN_2_OUT }, /* BTTXD */
140 { 44, GPIO_ALT_FN_1_IN }, /* BTCTS */
141 { 45, GPIO_ALT_FN_2_OUT }, /* BTRTS */
143 /* AC97 configuration */
144 { 29, GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */
146 { -1 }
148 #endif
150 static const struct gxioconf busheader_conf[] = {
151 { "basix", basix_config },
152 { "cfstix", cfstix_config },
153 { "etherstix", etherstix_config },
154 { "netcf", netcf_config },
155 { "netcf-vx", netcf_config },
156 { "netduo-mmc", netduommc_config },
157 { "netduo", netduo_config },
158 { "netmicrosd", netmicrosd_config },
159 { "netmicrosd-vx", netmicrosd_config },
160 { "netwifimicrosd", netwifimicrosd_config },
161 { "netmmc", netmmc_config },
162 { "netpro-vx", netwifimicrosd_config },
163 { "wifistix-cf", wifistix_cf_config },
164 { "wifistix", wifistix_config },
165 { NULL }
168 int gxpcic_gpio_reset;
169 struct gxpcic_slot_irqs gxpcic_slot_irqs[2] = { { 0, -1, -1 }, { 0, -1, -1 } };
172 /* ARGSUSED */
173 static int
174 gxiomatch(device_t parent, cfdata_t match, void *aux)
176 struct pxaip_attach_args *pxa = aux;
177 bus_space_tag_t iot = &pxa2x0_bs_tag;
178 bus_space_handle_t ioh;
180 if (strcmp(pxa->pxa_name, match->cf_name) != 0 ||
181 pxa->pxa_addr != PXAIPCF_ADDR_DEFAULT)
182 return 0;
184 if (bus_space_map(iot,
185 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &ioh))
186 return (0);
187 bus_space_unmap(iot, ioh, PXA2X0_MEMCTL_SIZE);
189 /* nothing */
190 return (1);
193 /* ARGSUSED */
194 static void
195 gxioattach(device_t parent, device_t self, void *aux)
197 struct gxio_softc *sc = device_private(self);
199 aprint_normal("\n");
200 aprint_naive("\n");
202 sc->sc_dev = self;
203 sc->sc_iot = &pxa2x0_bs_tag;
205 if (bus_space_map(sc->sc_iot,
206 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh))
207 return;
210 * Attach each gumstix expansion of busheader side devices
212 config_search_ia(gxiosearch, self, "gxio", NULL);
215 /* ARGSUSED */
216 static int
217 gxiosearch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
219 struct gxio_softc *sc = device_private(parent);
220 struct gxio_attach_args gxa;
222 gxa.gxa_sc = sc;
223 gxa.gxa_iot = sc->sc_iot;
224 gxa.gxa_addr = cf->cf_loc[GXIOCF_ADDR];
225 gxa.gxa_gpirq = cf->cf_loc[GXIOCF_GPIRQ];
227 if (config_match(parent, cf, &gxa))
228 config_attach(parent, cf, &gxa, gxioprint);
230 return (0);
233 /* ARGSUSED */
234 static int
235 gxioprint(void *aux, const char *name)
237 struct gxio_attach_args *gxa = (struct gxio_attach_args *)aux;
239 if (gxa->gxa_addr != GXIOCF_ADDR_DEFAULT)
240 printf(" addr 0x%lx", gxa->gxa_addr);
241 if (gxa->gxa_gpirq > 0)
242 printf(" gpirq %d", gxa->gxa_gpirq);
243 return (UNCONF);
248 * configure for GPIO pin and expansion boards.
250 void
251 gxio_config_pin(void)
253 #if defined(CPU_XSCALE_PXA250)
254 struct pxa2x0_gpioconf *gumstix_gpioconf[] = {
255 pxa25x_com_ffuart_gpioconf,
256 pxa25x_com_stuart_gpioconf,
257 #ifndef GXIO_BLUETOOTH_ON_HWUART
258 pxa25x_com_btuart_gpioconf,
259 #endif
260 pxa25x_com_hwuart_gpioconf,
261 pxa25x_i2c_gpioconf,
262 pxa25x_pxaacu_gpioconf,
263 pxa255dep_gpioconf,
264 NULL
266 #endif
267 #if defined(CPU_XSCALE_PXA270)
268 struct pxa2x0_gpioconf *verdex_gpioconf[] = {
269 pxa27x_com_ffuart_gpioconf,
270 pxa27x_com_stuart_gpioconf,
271 pxa27x_com_btuart_gpioconf,
272 pxa27x_i2c_gpioconf,
273 pxa27x_pxaacu_gpioconf,
274 pxa27x_pxamci_gpioconf,
275 pxa27x_ohci_gpioconf,
276 verdexdep_gpioconf,
277 NULL
279 #endif
281 /* XXX: turn off for power of bluetooth module */
282 #if defined(CPU_XSCALE_PXA250)
283 pxa2x0_gpio_set_function(7, GPIO_OUT | GPIO_CLR);
284 #elif defined(CPU_XSCALE_PXA270)
285 pxa2x0_gpio_set_function(12, GPIO_OUT | GPIO_CLR);
286 #endif
287 delay(100);
289 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250)
290 pxa2x0_gpio_config(
291 (CPU_IS_PXA250) ? gumstix_gpioconf : verdex_gpioconf);
292 #else
293 #if defined(CPU_XSCALE_PXA270)
294 pxa2x0_gpio_config(verdex_gpioconf);
295 #else
296 pxa2x0_gpio_config(gumstix_gpioconf);
297 #endif
298 #endif
301 void
302 gxio_config_expansion(char *expansion)
305 if (expansion == NULL) {
306 printf("not specified 'busheader=' in the boot args.\n");
307 #ifdef GXIO_DEFAULT_EXPANSION
308 printf("configure default expansion (%s)\n",
309 GXIO_DEFAULT_EXPANSION);
310 expansion = __UNCONST(GXIO_DEFAULT_EXPANSION);
311 #else
312 return;
313 #endif
315 gxio_config_gpio(busheader_conf, expansion);
318 static void
319 gxio_config_gpio(const struct gxioconf *gxioconflist, char *expansion)
321 int i, rv;
323 for (i = 0; i < strlen(expansion); i++)
324 expansion[i] = tolower(expansion[i]);
325 for (i = 0; gxioconflist[i].name != NULL; i++) {
326 rv = strncmp(expansion, gxioconflist[i].name,
327 strlen(gxioconflist[i].name) + 1);
328 if (rv == 0) {
329 gxioconflist[i].config();
330 break;
336 static void
337 basix_config(void)
340 pxa2x0_gpio_set_function(8, GPIO_ALT_FN_1_OUT); /* MMCCS0 */
341 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_1_OUT); /* MMCCLK */
342 #if 0
343 /* this configuration set by gxmci.c::pxamci_attach() */
344 pxa2x0_gpio_set_function(11, GPIO_IN); /* nSD_DETECT */
345 pxa2x0_gpio_set_function(22, GPIO_IN); /* nSD_WP */
346 #endif
349 static void
350 cfstix_config(void)
352 u_int gpio, npoe_fn;
353 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250)
354 int bvd = (CPU_IS_PXA250) ? 4 : 111;
355 #else
356 #if defined(CPU_XSCALE_PXA270)
357 const int bvd = 111;
358 #else
359 const int bvd = 4;
360 #endif
361 #endif
363 if (CPU_IS_PXA250) {
364 gxpcic_slot_irqs[0].valid = 1;
365 gxpcic_slot_irqs[0].cd = 11;
366 gxpcic_slot_irqs[0].prdy = 26;
367 gxpcic_gpio_reset = 8;
368 } else {
369 gxpcic_slot_irqs[0].valid = 1;
370 gxpcic_slot_irqs[0].cd = 104;
371 gxpcic_slot_irqs[0].prdy = 96;
372 gxpcic_gpio_reset = 97;
375 #if 1
376 /* PCD/PRDY set by pxa2x0_pcic.c::pxapcic_attach_common() */
377 #else
378 pxa2x0_gpio_set_function(11, GPIO_IN); /* PCD1 */
379 pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY1/~IRQ1 */
380 #endif
381 pxa2x0_gpio_set_function(bvd, GPIO_IN); /* BVD1/~STSCHG1 */
383 for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++)
384 npoe_fn |= pxa2x0_gpio_get_function(gpio);
385 npoe_fn &= GPIO_SET;
387 pxa2x0_gpio_set_function(48, GPIO_ALT_FN_2_OUT | npoe_fn); /* nPOE */
388 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
389 pxa2x0_gpio_set_function(50, GPIO_ALT_FN_2_OUT); /* nPIOR */
390 pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */
391 if (CPU_IS_PXA250) {
392 pxa2x0_gpio_set_function(52, GPIO_ALT_FN_2_OUT); /* nPCE1 */
393 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_2_OUT); /* nPCE2 */
394 pxa2x0_gpio_set_function(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */
395 } else {
396 pxa2x0_gpio_set_function(102, GPIO_ALT_FN_1_OUT); /* nPCE1 */
397 pxa2x0_gpio_set_function(105, GPIO_ALT_FN_1_OUT); /* nPCE2 */
398 pxa2x0_gpio_set_function(79, GPIO_ALT_FN_1_OUT); /* pSKTSEL */
400 pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */
401 pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN); /* nPWAIT */
402 pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */
405 static void
406 etherstix_config(void)
408 extern struct cfdata cfdata[];
409 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250)
410 int rst = (CPU_IS_PXA250) ? 80 : 32;
411 int irq = (CPU_IS_PXA250) ? 36 : 99;
412 #else
413 #if defined(CPU_XSCALE_PXA270)
414 const int rst = 32, irq = 99;
415 #else
416 const int rst = 80, irq = 36;
417 #endif
418 #endif
419 int i;
421 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
422 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */
423 pxa2x0_gpio_set_function(rst, GPIO_OUT | GPIO_SET); /* RESET 1 */
424 delay(1);
425 pxa2x0_gpio_set_function(rst, GPIO_OUT | GPIO_CLR);
426 delay(50000);
428 for (i = 0; cfdata[i].cf_name != NULL; i++)
429 if (strcmp(cfdata[i].cf_name, "sm") == 0 &&
430 strcmp(cfdata[i].cf_atname, "sm_gxio") == 0 &&
431 cfdata[i].cf_loc[GXIOCF_ADDR] == 0x04000300 &&
432 cfdata[i].cf_loc[GXIOCF_GPIRQ] == GXIOCF_GPIRQ_DEFAULT)
433 cfdata[i].cf_loc[GXIOCF_GPIRQ] = irq;
436 static void
437 netcf_config(void)
440 etherstix_config();
441 cfstix_config();
442 if (CPU_IS_PXA270) {
443 /* Overwrite */
444 gxpcic_slot_irqs[0].cd = 104;
445 gxpcic_slot_irqs[0].prdy = 109;
446 gxpcic_gpio_reset = 110;
450 static void
451 netduommc_config(void)
454 netduo_config();
455 basix_config();
458 static void
459 netduo_config(void)
462 etherstix_config();
464 pxa2x0_gpio_set_function(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */
465 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */
466 delay(1);
467 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR);
468 delay(50000);
471 static void
472 netmicrosd_config(void)
475 /* MicroSD(mci) always configure on PXA270 */
477 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
478 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */
479 pxa2x0_gpio_set_function(107, GPIO_OUT | GPIO_CLR); /* RESET 1 */
480 delay(hz / 2);
481 pxa2x0_gpio_set_function(107, GPIO_OUT | GPIO_SET);
482 delay(50000);
485 static void
486 netwifimicrosd_config(void)
489 netmicrosd_config();
491 cfstix_config();
492 /* However use pxamci. */
493 pxa2x0_gpio_set_function(111, GPIO_CLR | GPIO_ALT_FN_1_IN);
494 /* Power to Marvell 88W8385 */
495 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET);
498 static void
499 netmmc_config(void)
502 etherstix_config();
503 basix_config();
506 static void
507 wifistix_config(void)
510 cfstix_config();
512 /* Power to Marvell 88W8385 */
513 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET);
516 static void
517 wifistix_cf_config(void)
520 gxpcic_slot_irqs[1].valid = 1;
521 gxpcic_slot_irqs[1].cd = 36;
522 gxpcic_slot_irqs[1].prdy = 27;
524 #if 1
525 /* this configuration set by pxa2x0_pcic.c::pxapcic_attach_common() */
526 #else
527 pxa2x0_gpio_set_function(36, GPIO_IN); /* PCD2 */
528 pxa2x0_gpio_set_function(27, GPIO_IN); /* PRDY2/~IRQ2 */
529 #endif
530 pxa2x0_gpio_set_function(18, GPIO_IN); /* BVD2/~STSCHG2 */
532 cfstix_config();
534 /* Power to Marvell 88W8385 */
535 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET);