gxio.c revision 1.2 1 /* $NetBSD: gxio.c,v 1.2 2006/10/17 17:06:22 kiyohara Exp $ */
2 /*
3 * Copyright (C) 2005, 2006 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.2 2006/10/17 17:06:22 kiyohara Exp $");
35
36 #include <sys/param.h>
37 #include <sys/device.h>
38 #include <sys/errno.h>
39
40 #include <sys/systm.h>
41
42 #include <machine/bootconfig.h>
43
44 #include <arm/xscale/pxa2x0cpu.h>
45 #include <arm/xscale/pxa2x0reg.h>
46 #include <arm/xscale/pxa2x0var.h>
47 #include <arm/xscale/pxa2x0_gpio.h>
48 #include <evbarm/gumstix/gumstixvar.h>
49
50 #include "locators.h"
51
52
53 static int gxiomatch(struct device *, struct cfdata *, void *);
54 static void gxioattach(struct device *, struct device *, void *);
55 static int gxiosearch(struct device *, struct cfdata *, const int *, void *);
56 static int gxioprint(void *, const char *);
57
58 static void gxio_config_gpio(struct gxio_softc *);
59 static void cfstix_config(struct gxio_softc *);
60 static void etherstix_config(struct gxio_softc *);
61 static void netcf_config(struct gxio_softc *);
62 static void netduo_config(struct gxio_softc *);
63 static void netmmc_config(struct gxio_softc *);
64
65 CFATTACH_DECL(
66 gxio, sizeof(struct gxio_softc), gxiomatch, gxioattach, NULL, NULL);
67
68 char hirose60p[MAX_BOOT_STRING];
69 char busheader[MAX_BOOT_STRING];
70
71 struct gxioconf {
72 const char *name;
73 void (*config)(struct gxio_softc *);
74 uint32_t searchdrv;
75 };
76
77 static const struct gxioconf hirose60p_conf[] = {
78 { NULL }
79 };
80 static const struct gxioconf busheader_conf[] = {
81 { "cfstix", cfstix_config },
82 { "etherstix", etherstix_config },
83 { "netcf", netcf_config },
84 { "netduo", netduo_config },
85 { "netmmc", netmmc_config },
86 { NULL }
87 };
88
89
90 /* ARGSUSED */
91 static int
92 gxiomatch(struct device *parent, struct cfdata *match, void *aux)
93 {
94 bus_space_tag_t iot = &pxa2x0_bs_tag;
95 bus_space_handle_t ioh;
96
97 if (bus_space_map(iot,
98 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &ioh))
99 return (0);
100 bus_space_unmap(iot, ioh, PXA2X0_MEMCTL_SIZE);
101
102 /* nothing */
103 return (1);
104 }
105
106 /* ARGSUSED */
107 static void
108 gxioattach(struct device *parent, struct device *self, void *aux)
109 {
110 struct gxio_softc *sc = (struct gxio_softc *)self;
111
112 printf("\n");
113
114 sc->sc_iot = &pxa2x0_bs_tag;
115
116 if (bus_space_map(sc->sc_iot,
117 PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, 0, &sc->sc_ioh))
118 return;
119
120 /* configuration for GPIO */
121 gxio_config_gpio(sc);
122
123 /*
124 * Attach each gumstix expantion devices
125 */
126 config_search_ia(gxiosearch, self, "gxio", NULL);
127 }
128
129 /* ARGSUSED */
130 static int
131 gxiosearch(
132 struct device *parent, struct cfdata *cf, const int *ldesc, void *aux)
133 {
134 struct gxio_softc *sc = (struct gxio_softc *)parent;
135 struct gxio_attach_args gxa;
136
137 gxa.gxa_sc = sc;
138 gxa.gxa_iot = sc->sc_iot;
139 gxa.gxa_addr = cf->cf_loc[GXIOCF_ADDR];
140 gxa.gxa_gpirq = cf->cf_loc[GXIOCF_GPIRQ];
141
142 if (config_match(parent, cf, &gxa))
143 config_attach(parent, cf, &gxa, gxioprint);
144
145 return (0);
146 }
147
148 /* ARGSUSED */
149 static int
150 gxioprint(void *aux, const char *name)
151 {
152 struct gxio_attach_args *gxa = (struct gxio_attach_args *)aux;
153
154 if (gxa->gxa_addr != GXIOCF_ADDR_DEFAULT)
155 printf(" addr 0x%lx", gxa->gxa_addr);
156 if (gxa->gxa_gpirq > 0)
157 printf(" gpirq %d", gxa->gxa_gpirq);
158 return (UNCONF);
159 }
160
161
162 /*
163 * configure for expansion boards.
164 */
165 void
166 gxio_config_gpio(struct gxio_softc *sc)
167 {
168 int i, rv;
169
170 for (i = 0; i < strlen(hirose60p); i++)
171 hirose60p[i] = tolower(hirose60p[i]);
172 for (i = 0; hirose60p_conf[i].name != NULL; i++) {
173 rv = strncmp(hirose60p, hirose60p_conf[i].name,
174 strlen(hirose60p_conf[i].name) + 1);
175 if (rv == 0) {
176 hirose60p_conf[i].config(sc);
177 break;
178 }
179 }
180
181 for (i = 0; i < strlen(busheader); i++)
182 busheader[i] = tolower(busheader[i]);
183 for (i = 0; busheader_conf[i].name != NULL; i++) {
184 rv = strncmp(busheader, busheader_conf[i].name,
185 strlen(busheader_conf[i].name) + 1);
186 if (rv == 0) {
187 busheader_conf[i].config(sc);
188 break;
189 }
190 }
191 }
192
193 static void
194 cfstix_config(struct gxio_softc *sc)
195 {
196 u_int gpio, npoe_fn;
197
198 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR,
199 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MEMCTL_MECR) & ~MECR_NOS);
200
201 pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_SET); /* RESET */
202 delay(50);
203 pxa2x0_gpio_set_function(8, GPIO_OUT | GPIO_CLR);
204
205 pxa2x0_gpio_set_function(4, GPIO_IN); /* nBVD1/nSTSCHG */
206 pxa2x0_gpio_set_function(27, GPIO_IN); /* ~INPACK */
207 pxa2x0_gpio_set_function(11, GPIO_IN); /* nPCD1 */
208 pxa2x0_gpio_set_function(26, GPIO_IN); /* PRDY/IRQ */
209
210 for (gpio = 48, npoe_fn = 0; gpio <= 53 ; gpio++)
211 npoe_fn |= pxa2x0_gpio_get_function(gpio);
212 npoe_fn &= GPIO_SET;
213
214 pxa2x0_gpio_set_function(48, GPIO_ALT_FN_2_OUT | npoe_fn); /* nPOE */
215 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
216 pxa2x0_gpio_set_function(50, GPIO_ALT_FN_2_OUT); /* nPIOR */
217 pxa2x0_gpio_set_function(51, GPIO_ALT_FN_2_OUT); /* nPIOW */
218 pxa2x0_gpio_set_function(52, GPIO_ALT_FN_2_OUT); /* nPCE1 */
219 pxa2x0_gpio_set_function(54, GPIO_ALT_FN_2_OUT); /* pSKTSEL */
220 pxa2x0_gpio_set_function(55, GPIO_ALT_FN_2_OUT); /* nPREG */
221 pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN); /* nPWAIT */
222 pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN); /* nIOIS16 */
223 }
224
225 /* ARGSUSED */
226 static void
227 etherstix_config(struct gxio_softc *sc)
228 {
229
230 pxa2x0_gpio_set_function(49, GPIO_ALT_FN_2_OUT); /* nPWE */
231 pxa2x0_gpio_set_function(15, GPIO_ALT_FN_2_OUT); /* nCS 1 */
232 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_SET); /* RESET 1 */
233 delay(1);
234 pxa2x0_gpio_set_function(80, GPIO_OUT | GPIO_CLR);
235 delay(50000);
236 }
237
238 static void
239 netcf_config(struct gxio_softc *sc)
240 {
241
242 etherstix_config(sc);
243 cfstix_config(sc);
244 }
245
246 static void
247 netduo_config(struct gxio_softc *sc)
248 {
249
250 etherstix_config(sc);
251
252 pxa2x0_gpio_set_function(78, GPIO_ALT_FN_2_OUT); /* nCS 2 */
253 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_SET); /* RESET 2 */
254 delay(1);
255 pxa2x0_gpio_set_function(52, GPIO_OUT | GPIO_CLR);
256 delay(50000);
257 }
258
259 static void
260 netmmc_config(struct gxio_softc *sc)
261 {
262
263 etherstix_config(sc);
264
265 /* mmc not yet... */
266 }
267