2 * Copyright (c) 2002, 2003, 2005 Genetec corp. All rights reserved.
4 * PCMCIA/CF support for TWINTAIL (G4255EB)
5 * Written by Hiroyuki Bessho for Genetec corp.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Genetec corp. may not be used to endorse
16 * or promote products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 #include <sys/callout.h>
37 #include <sys/kernel.h>
38 #include <sys/kthread.h>
39 #include <sys/malloc.h>
42 #include <machine/bus.h>
43 #include <machine/intr.h>
45 #include <dev/pcmcia/pcmciareg.h>
46 #include <dev/pcmcia/pcmciavar.h>
47 #include <dev/pcmcia/pcmciachip.h>
49 #include <arch/arm/xscale/pxa2x0var.h>
50 #include <arch/arm/xscale/pxa2x0reg.h>
51 #include <arch/arm/sa11x0/sa11xx_pcicvar.h>
52 #include <arch/evbarm/g42xxeb/g42xxeb_reg.h>
53 #include <arch/evbarm/g42xxeb/g42xxeb_var.h>
54 #include <arch/evbarm/g42xxeb/gb225reg.h>
55 #include <arch/evbarm/g42xxeb/gb225var.h>
58 //#define DONT_USE_CARD_DETECT_INTR
60 #define PCMCIA_INT G42XXEB_INT_EXT1
61 #define CF_INT G42XXEB_INT_EXT0
64 #define DPRINTF(arg) printf arg
72 struct sapcic_socket ss
; /* inherit socket for sa11x0 pcic */
75 int voltage
; /* card power voltage selected by
81 struct sapcic_softc sc_pc
; /* inherit SA11xx pcic */
83 struct opcic_socket sc_socket
[2];
85 bus_space_handle_t sc_memctl_ioh
;
88 static int opcic_match(struct device
*, struct cfdata
*, void *);
89 static void opcic_attach(struct device
*, struct device
*, void *);
90 static int opcic_print(void *, const char *);
92 static int opcic_read(struct sapcic_socket
*, int);
93 static void opcic_write(struct sapcic_socket
*, int, int);
94 static void opcic_set_power(struct sapcic_socket
*, int);
95 static void opcic_clear_intr(int);
96 static void *opcic_intr_establish(struct sapcic_socket
*, int,
97 int (*)(void *), void *);
98 static void opcic_intr_disestablish(struct sapcic_socket
*, void *);
99 #ifndef DONT_USE_CARD_DETECT_INTR
100 static int opcic_card_detect(void *, int);
103 CFATTACH_DECL(opcic
, sizeof(struct opcic_softc
),
104 opcic_match
, opcic_attach
, NULL
, NULL
);
106 static struct sapcic_tag opcic_tag
= {
111 opcic_intr_establish
,
112 opcic_intr_disestablish
,
116 #define HAVE_CARD(r) (((r)&CARDDET_DET)==0)
118 static inline uint8_t
119 opcic_read_card_status(struct opcic_socket
*so
)
121 struct opcic_softc
*sc
= (struct opcic_softc
*)(so
->ss
.sc
);
122 struct opio_softc
*osc
=
123 device_private(device_parent(sc
->sc_pc
.sc_dev
));
125 return bus_space_read_1(osc
->sc_iot
, osc
->sc_ioh
,
126 GB225_CFDET
+ 2 * so
->ss
.socket
);
131 opcic_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
137 opcic_attach(struct device
*parent
, struct device
*self
, void *aux
)
140 struct pcmciabus_attach_args paa
;
141 struct opcic_softc
*sc
= (struct opcic_softc
*)self
;
142 struct opio_softc
*psc
= (struct opio_softc
*)parent
;
143 struct obio_softc
*bsd
= (struct obio_softc
*)device_parent(parent
);
144 bus_space_handle_t memctl_ioh
= bsd
->sc_memctl_ioh
;
145 bus_space_tag_t iot
= psc
->sc_iot
;
149 /* tell PXA2X0 that we have two sockets */
151 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MECR
, MECR_NOS
);
153 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MECR
, MECR_CIT
|MECR_NOS
);
155 sc
->sc_pc
.sc_iot
= psc
->sc_iot
;
156 sc
->sc_memctl_ioh
= memctl_ioh
;
160 for(i
= 0; i
< 2; i
++) {
161 sc
->sc_socket
[i
].ss
.sc
= &sc
->sc_pc
;
162 sc
->sc_socket
[i
].ss
.socket
= i
;
163 sc
->sc_socket
[i
].ss
.pcictag_cookie
= NULL
;
164 sc
->sc_socket
[i
].ss
.pcictag
= &opcic_tag
;
165 sc
->sc_socket
[i
].ss
.event_thread
= NULL
;
166 sc
->sc_socket
[i
].ss
.event
= 0;
167 sc
->sc_socket
[i
].ss
.laststatus
= CARDDET_NOCARD
;
168 sc
->sc_socket
[i
].ss
.shutdown
= 0;
170 sc
->sc_socket
[i
].ss
.power_capability
=
171 (SAPCIC_POWER_5V
|SAPCIC_POWER_3V
);
173 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MCIO(i
),
174 MC_TIMING_VAL(1,1,1));
176 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MCATT(i
),
177 MC_TIMING_VAL(31,31,31));
180 paa
.paa_busname
= "pcmcia";
181 paa
.pct
= (pcmcia_chipset_tag_t
)&sa11x0_pcmcia_functions
;
182 paa
.pch
= (pcmcia_chipset_handle_t
)&sc
->sc_socket
[i
].ss
;
184 paa
.iosize
= 0x4000000;
186 sc
->sc_socket
[i
].ss
.pcmcia
=
187 config_found_ia(sc
->sc_pc
.sc_dev
,
188 "pcmciabus", &paa
, opcic_print
);
190 #ifndef DONT_USE_CARD_DETECT_INTR
191 /* interrupt for card insertion/removal */
192 opio_intr_establish(psc
,
193 i
==0 ? OPIO_INTR_CF_INSERT
: OPIO_INTR_PCMCIA_INSERT
,
194 IPL_BIO
, opcic_card_detect
, &sc
->sc_socket
[i
]);
196 bus_space_write_4(iot
, ioh
, MEMCTL_MECR
, MECR_NOS
| MECR_CIT
);
200 /* schedule kthread creation */
201 sapcic_kthread_create(&sc
->sc_socket
[i
].ss
);
207 opcic_print(void *aux
, const char *name
)
212 #ifndef DONT_USE_CARD_DETECT_INTR
214 opcic_card_detect(void *arg
, int val
)
216 struct opcic_socket
*socket
= arg
;
217 struct opcic_softc
*sc
= (struct opcic_softc
*)socket
->ss
.sc
;
218 bus_space_tag_t iot
= sc
->sc_pc
.sc_iot
;
219 bus_space_handle_t memctl_ioh
= sc
->sc_memctl_ioh
;
220 int sock_no
= socket
->ss
.socket
;
225 if (HAVE_CARD(val
)) {
226 sc
->sc_cards
|= 1<<sock_no
;
227 /* if it is the first card, turn on expansion memory
230 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MECR
,
231 MECR_NOS
| MECR_CIT
);
234 sc
->sc_cards
&= ~(1<<sock_no
);
235 /* if we loast all cards, turn off expansion memory
238 if (sc
->sc_cards
== 0)
239 bus_space_write_4(iot
, memctl_ioh
,
240 MEMCTL_MECR
, MECR_NOS
);
245 DPRINTF(("%s: card %d %s\n", sc
->sc_pc
.sc_dev
.dv_xname
, sock_no
,
246 HAVE_CARD(val
) ? "inserted" : "removed"));
252 #endif /* DONT_USE_CARD_DETECT_INTR */
255 opcic_read(struct sapcic_socket
*__so
, int which
)
257 struct opcic_socket
*so
= (struct opcic_socket
*)__so
;
260 reg
= opcic_read_card_status(so
);
263 case SAPCIC_STATUS_CARD
:
264 return HAVE_CARD(reg
) ?
265 SAPCIC_CARD_VALID
: SAPCIC_CARD_INVALID
;
267 case SAPCIC_STATUS_VS1
:
268 return (reg
& CARDDET_NVS1
) == 0;
270 case SAPCIC_STATUS_VS2
:
271 return (reg
& CARDDET_NVS2
) == 0;
273 case SAPCIC_STATUS_READY
:
277 panic("%s: bogus register", __func__
);
282 opcic_write(struct sapcic_socket
*__so
, int which
, int arg
)
284 struct opcic_socket
*so
= (struct opcic_socket
*)__so
;
285 struct opcic_softc
*sc
= (struct opcic_softc
*)so
->ss
.sc
;
286 struct opio_softc
*psc
=
287 device_private(device_parent(sc
->sc_pc
.sc_dev
));
288 struct obio_softc
*bsc
=
289 device_private(device_parent(&psc
->sc_dev
));
292 case SAPCIC_CONTROL_RESET
:
293 obio_peripheral_reset(bsc
, so
->ss
.socket
, arg
);
297 case SAPCIC_CONTROL_LINEENABLE
:
300 case SAPCIC_CONTROL_WAITENABLE
:
303 case SAPCIC_CONTROL_POWERSELECT
:
310 panic("%s: bogus register", __func__
);
315 opcic_set_power(struct sapcic_socket
*__so
, int arg
)
317 struct opcic_socket
*so
= (struct opcic_socket
*)__so
;
318 struct opcic_softc
*sc
= (struct opcic_softc
*)so
->ss
.sc
;
319 struct opio_softc
*psc
=
320 device_private(device_parent(sc
->sc_pc
.sc_dev
));
324 if( arg
< 0 || SAPCIC_POWER_5V
< arg
)
325 panic("sacpcic_set_power: bogus arg\n");
327 DPRINTF(("card %d: DET=%x\n",
329 bus_space_read_1(psc
->sc_iot
, psc
->sc_ioh
,
330 GB225_CFDET
+ 2*so
->ss
.socket
)));
332 p
= (volatile uint8_t *)bus_space_vaddr(psc
->sc_iot
, psc
->sc_ioh
)
335 shift
= 4 * !so
->ss
.socket
;
337 save
= disable_interrupts(I32_bit
);
338 *p
= (*p
& ~(0x0f << shift
)) | ((CARDPOW_VPPVCC
| (arg
<<2)) << shift
);
339 restore_interrupts(save
);
341 DPRINTF(("card %d power: %x\n", so
->ss
.socket
, *p
));
345 opcic_clear_intr(int arg
)
350 opcic_intr_establish(struct sapcic_socket
*so
, int level
,
351 int (* ih_fun
)(void *), void *ih_arg
)
353 struct opcic_softc
*sc
= (struct opcic_softc
*)so
->sc
;
354 struct opio_softc
*psc
=
355 device_private(device_parent(sc
->sc_pc
.sc_dev
));
356 struct obio_softc
*bsc
=
357 device_private(device_parent(&psc
->sc_dev
));
360 DPRINTF(("opcic_intr_establish %d\n", so
->socket
));
362 irq
= so
->socket
? PCMCIA_INT
: CF_INT
;
363 return obio_intr_establish(bsc
, irq
, level
, IST_EDGE_FALLING
,
368 opcic_intr_disestablish(struct sapcic_socket
*so
, void *ih
)
370 struct opcic_softc
*sc
= (struct opcic_softc
*)so
->sc
;
371 struct opio_softc
*psc
=
372 device_private(device_parent(sc
->sc_pc
.sc_dev
));
373 struct obio_softc
*bsc
=
374 (struct obio_softc
*) device_parent(&psc
->sc_dev
);
375 int (* func
)(void *) = ((struct obio_handler
*)ih
)->func
;
377 int irq
= so
->socket
? PCMCIA_INT
: CF_INT
;
379 obio_intr_disestablish(bsc
, irq
, func
);