1 /* $NetBSD: gxpcic.c,v 1.10 2009/03/18 10:22:27 cegger Exp $ */
3 * Copyright (C) 2005, 2006 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.
34 * Copyright (c) 2002, 2003, 2005 Genetec corp. All rights reserved.
36 * PCMCIA/CF support for TWINTAIL (G4255EB)
37 * Written by Hiroyuki Bessho for Genetec corp.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. The name of Genetec corp. may not be used to endorse
48 * or promote products derived from this software without specific prior
51 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/types.h>
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/device.h>
68 #include <sys/callout.h>
69 #include <sys/kernel.h>
70 #include <sys/kthread.h>
71 #include <sys/malloc.h>
74 #include <machine/bus.h>
75 #include <machine/intr.h>
77 #include <dev/pcmcia/pcmciareg.h>
78 #include <dev/pcmcia/pcmciavar.h>
79 #include <dev/pcmcia/pcmciachip.h>
81 #include <arch/arm/xscale/pxa2x0cpu.h>
82 #include <arch/arm/xscale/pxa2x0var.h>
83 #include <arch/arm/xscale/pxa2x0reg.h>
84 #include <arch/arm/xscale/pxa2x0_gpio.h>
85 #include <arch/arm/xscale/pxa2x0_pcic.h>
86 #include <arch/evbarm/gumstix/gumstixvar.h>
90 #define DPRINTF(arg) printf arg
95 #define HAVE_CARD(r) (!((r) & GPIO_SET))
98 static int gxpcic_match(device_t
, cfdata_t
, void *);
99 static void gxpcic_attach(device_t
, device_t
, void *);
100 static void gxpcic_socket_setup(struct pxapcic_socket
*);
102 static u_int
gxpcic_read(struct pxapcic_socket
*, int);
103 static void gxpcic_write(struct pxapcic_socket
*, int, u_int
);
104 static void gxpcic_set_power(struct pxapcic_socket
*, int);
105 static void gxpcic_clear_intr(struct pxapcic_socket
*);
106 static void *gxpcic_intr_establish(struct pxapcic_socket
*, int,
107 int (*)(void *), void *);
108 static void gxpcic_intr_disestablish(struct pxapcic_socket
*, void *);
109 __inline
void gxpcic_cpld_clk(void);
110 __inline u_char
gxpcic_cpld_read_bits(int bits
);
111 static int gxpcic_count_slot(struct pxapcic_softc
*);
113 CFATTACH_DECL_NEW(gxpcic
, sizeof(struct pxapcic_softc
),
114 gxpcic_match
, gxpcic_attach
, NULL
, NULL
);
116 static struct pxapcic_tag gxpcic_functions
= {
121 gxpcic_intr_establish
,
122 gxpcic_intr_disestablish
,
127 gxpcic_match(device_t parent
, cfdata_t match
, void *aux
)
129 struct pxaip_attach_args
*pxa
= aux
;
130 struct pxa2x0_gpioconf
*gpioconf
;
134 if (strcmp(pxa
->pxa_name
, match
->cf_name
) != 0)
138 * Check GPIO configuration. If you use these, it is sure already
139 * to have been set by gxio.
141 gpioconf
= CPU_IS_PXA250
? pxa25x_pcic_gpioconf
:
142 pxa27x_pcic_gpioconf
;
143 for (i
= 0; gpioconf
[i
].pin
!= -1; i
++) {
144 reg
= pxa2x0_gpio_get_function(gpioconf
[i
].pin
);
145 if (GPIO_FN(reg
) != GPIO_FN(gpioconf
[i
].value
) ||
146 GPIO_FN_IS_OUT(reg
) != GPIO_FN_IS_OUT(gpioconf
[i
].value
)) {
147 if (!CPU_IS_PXA250
&& gpioconf
[i
].pin
== 111)
153 return 1; /* match */
157 gxpcic_attach(device_t parent
, device_t self
, void *aux
)
159 struct pxapcic_softc
*sc
= device_private(self
);
160 struct pxaip_attach_args
*pxa
= aux
;
164 sc
->sc_iot
= pxa
->pxa_iot
;
166 nslot
= gxpcic_count_slot(sc
);
168 for (i
= 0; i
< nslot
; i
++) {
169 if (!gxpcic_slot_irqs
[i
].valid
)
171 sc
->sc_irqpin
[i
] = gxpcic_slot_irqs
[i
].prdy
;
172 sc
->sc_irqcfpin
[i
] = gxpcic_slot_irqs
[i
].cd
;
174 sc
->sc_nslots
= nslot
;
176 pxapcic_attach_common(sc
, &gxpcic_socket_setup
);
180 gxpcic_socket_setup(struct pxapcic_socket
*so
)
183 struct pxapcic_softc
*sc
= so
->sc
;
187 so
->power_capability
= PXAPCIC_POWER_3V
;
188 so
->pcictag_cookie
= NULL
;
189 so
->pcictag
= &gxpcic_functions
;
191 #if 0 /* We use already set values by u-boot. */
192 bus_space_write_4(sc
->sc_iot
, sc
->sc_memctl_ioh
,
193 MEMCTL_MCMEM(so
->socket
), MC_TIMING_VAL(9 ,9, 29));
194 bus_space_write_4(sc
->sc_iot
, sc
->sc_memctl_ioh
,
195 MEMCTL_MCATT(so
->socket
), MC_TIMING_VAL(9 ,9, 29));
196 bus_space_write_4(sc
->sc_iot
, sc
->sc_memctl_ioh
,
197 MEMCTL_MCIO(so
->socket
), MC_TIMING_VAL(5 ,5, 16));
202 gxpcic_read(struct pxapcic_socket
*so
, int which
)
207 case PXAPCIC_CARD_STATUS
:
208 reg
= pxa2x0_gpio_get_function(gxpcic_slot_irqs
[so
->socket
].cd
);
209 return (HAVE_CARD(reg
) ?
210 PXAPCIC_CARD_VALID
: PXAPCIC_CARD_INVALID
);
212 case PXAPCIC_CARD_READY
:
213 reg
= pxa2x0_gpio_get_function(
214 gxpcic_slot_irqs
[so
->socket
].prdy
);
215 return (reg
& GPIO_SET
? 1 : 0);
218 panic("%s: bogus register", __func__
);
225 gxpcic_write(struct pxapcic_socket
*so
, int which
, u_int arg
)
229 case PXAPCIC_CARD_POWER
:
230 case PXAPCIC_CARD_RESET
:
235 panic("%s: bogus register", __func__
);
241 gxpcic_set_power(struct pxapcic_socket
*__so
, int arg
)
244 if(arg
!= PXAPCIC_POWER_OFF
&& arg
!= PXAPCIC_POWER_3V
)
245 panic("%s: bogus arg\n", __func__
);
252 gxpcic_clear_intr(struct pxapcic_socket
*so
)
259 gxpcic_intr_establish(struct pxapcic_socket
*so
, int level
,
260 int (* ih_fun
)(void *), void *ih_arg
)
263 return pxa2x0_gpio_intr_establish(so
->irqpin
, IST_EDGE_FALLING
,
264 level
, ih_fun
, ih_arg
);
269 gxpcic_intr_disestablish(struct pxapcic_socket
*so
, void *ih
)
272 pxa2x0_gpio_intr_disestablish(ih
);
277 * XXXXX: slot count functions from Linux
280 gxpcic_cpld_clk(void)
283 pxa2x0_gpio_set_function(48, GPIO_OUT
| GPIO_CLR
);
284 pxa2x0_gpio_set_function(48, GPIO_OUT
| GPIO_SET
);
288 gxpcic_cpld_read_bits(int bits
)
290 u_int shift
= 0, gpio
;
294 gpio
= pxa2x0_gpio_get_function(11);
295 result
|= ((gpio
& GPIO_SET
) == GPIO_SET
) << shift
;
303 * We use the CPLD on the CF-CF card to read a value from a shift register.
304 * If we can read that magic sequence, then we have 2 CF cards; otherwise
305 * we assume just one. The CPLD will send the value of the shift register
306 * on GPIO11 (the CD line for slot 0) when RESET is held in reset. We use
307 * GPIO48 (nPWE) as a clock signal, GPIO52/53 (card enable for both cards)
308 * to control read/write to the shift register.
311 gxpcic_count_slot(struct pxapcic_softc
*sc
)
313 u_int poe
, pce1
, pce2
;
316 poe
= pxa2x0_gpio_get_function(48);
317 pce1
= pxa2x0_gpio_get_function(52);
318 pce2
= pxa2x0_gpio_get_function(53);
321 pxa2x0_gpio_set_function(gxpcic_gpio_reset
, GPIO_OUT
| GPIO_CLR
);
323 /* Setup the shift register */
324 pxa2x0_gpio_set_function(52, GPIO_OUT
| GPIO_SET
);
325 pxa2x0_gpio_set_function(53, GPIO_OUT
| GPIO_CLR
);
327 /* Tick the clock to program the shift register */
330 /* Now set shift register into read mode */
331 pxa2x0_gpio_set_function(52, GPIO_OUT
| GPIO_CLR
);
332 pxa2x0_gpio_set_function(53, GPIO_OUT
| GPIO_SET
);
334 /* We can read the bits now -- 0xc2 means "Dual compact flash" */
335 if (gxpcic_cpld_read_bits(8) != 0xc2)
336 /* We do not have 2 CF slots */
339 /* We have 2 CF slots */
344 pxa2x0_gpio_set_function(gxpcic_gpio_reset
, GPIO_OUT
| GPIO_CLR
);
346 pxa2x0_gpio_set_function(48, poe
);
347 pxa2x0_gpio_set_function(52, pce1
);
348 pxa2x0_gpio_set_function(53, pce2
);