1 /* $NetBSD: gxio.c,v 1.12 2009/11/22 12:00:56 kiyohara Exp $ */
3 * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation.
6 * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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 $");
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>
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);
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 */
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 */
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 */
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 */
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
},
168 int gxpcic_gpio_reset
;
169 struct gxpcic_slot_irqs gxpcic_slot_irqs
[2] = { { 0, -1, -1 }, { 0, -1, -1 } };
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
)
184 if (bus_space_map(iot
,
185 PXA2X0_MEMCTL_BASE
, PXA2X0_MEMCTL_SIZE
, 0, &ioh
))
187 bus_space_unmap(iot
, ioh
, PXA2X0_MEMCTL_SIZE
);
195 gxioattach(device_t parent
, device_t self
, void *aux
)
197 struct gxio_softc
*sc
= device_private(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
))
210 * Attach each gumstix expansion of busheader side devices
212 config_search_ia(gxiosearch
, self
, "gxio", NULL
);
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
;
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
);
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
);
248 * configure for GPIO pin and expansion boards.
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
,
260 pxa25x_com_hwuart_gpioconf
,
262 pxa25x_pxaacu_gpioconf
,
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
,
273 pxa27x_pxaacu_gpioconf
,
274 pxa27x_pxamci_gpioconf
,
275 pxa27x_ohci_gpioconf
,
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
);
289 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250)
291 (CPU_IS_PXA250
) ? gumstix_gpioconf
: verdex_gpioconf
);
293 #if defined(CPU_XSCALE_PXA270)
294 pxa2x0_gpio_config(verdex_gpioconf
);
296 pxa2x0_gpio_config(gumstix_gpioconf
);
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
);
315 gxio_config_gpio(busheader_conf
, expansion
);
319 gxio_config_gpio(const struct gxioconf
*gxioconflist
, char *expansion
)
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);
329 gxioconflist
[i
].config();
340 pxa2x0_gpio_set_function(8, GPIO_ALT_FN_1_OUT
); /* MMCCS0 */
341 pxa2x0_gpio_set_function(53, GPIO_ALT_FN_1_OUT
); /* MMCCLK */
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 */
353 #if defined(CPU_XSCALE_PXA270) && defined(CPU_XSCALE_PXA250)
354 int bvd
= (CPU_IS_PXA250
) ? 4 : 111;
356 #if defined(CPU_XSCALE_PXA270)
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;
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;
376 /* PCD/PRDY set by pxa2x0_pcic.c::pxapcic_attach_common() */
378 pxa2x0_gpio_set_function(11, GPIO_IN
); /* PCD1 */
379 pxa2x0_gpio_set_function(26, GPIO_IN
); /* PRDY1/~IRQ1 */
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
);
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 */
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 */
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 */
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;
413 #if defined(CPU_XSCALE_PXA270)
414 const int rst
= 32, irq
= 99;
416 const int rst
= 80, irq
= 36;
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 */
425 pxa2x0_gpio_set_function(rst
, GPIO_OUT
| GPIO_CLR
);
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
;
444 gxpcic_slot_irqs
[0].cd
= 104;
445 gxpcic_slot_irqs
[0].prdy
= 109;
446 gxpcic_gpio_reset
= 110;
451 netduommc_config(void)
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 */
467 pxa2x0_gpio_set_function(52, GPIO_OUT
| GPIO_CLR
);
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 */
481 pxa2x0_gpio_set_function(107, GPIO_OUT
| GPIO_SET
);
486 netwifimicrosd_config(void)
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
);
507 wifistix_config(void)
512 /* Power to Marvell 88W8385 */
513 pxa2x0_gpio_set_function(80, GPIO_OUT
| GPIO_SET
);
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;
525 /* this configuration set by pxa2x0_pcic.c::pxapcic_attach_common() */
527 pxa2x0_gpio_set_function(36, GPIO_IN
); /* PCD2 */
528 pxa2x0_gpio_set_function(27, GPIO_IN
); /* PRDY2/~IRQ2 */
530 pxa2x0_gpio_set_function(18, GPIO_IN
); /* BVD2/~STSCHG2 */
534 /* Power to Marvell 88W8385 */
535 pxa2x0_gpio_set_function(80, GPIO_OUT
| GPIO_SET
);