xref: /netbsd-src/sys/arch/evbarm/gumstix/gxio.c (revision 8ac07aec990b9d2e483062509d0a9fa5b4f57cf2)
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