xref: /netbsd-src/sys/arch/arm/imx/imx_pcic.c (revision f82ca6eefb335bf699131a4ebe4cc00c8911db8a)
1*f82ca6eeSskrll /*	$Id: imx_pcic.c,v 1.9 2022/09/27 06:36:42 skrll Exp $	*/
2825088edSmatt 
3825088edSmatt /*
4825088edSmatt  * IMX CF interface to pcic/pcmcia
5825088edSmatt  * derived from pxa2x0_pcic
6825088edSmatt  * Sun Apr  1 21:42:37 PDT 2007
7825088edSmatt  */
8825088edSmatt 
9*f82ca6eeSskrll /*	$NetBSD: imx_pcic.c,v 1.9 2022/09/27 06:36:42 skrll Exp $	*/
10825088edSmatt /*	$OpenBSD: pxa2x0_pcic.c,v 1.17 2005/12/14 15:08:51 uwe Exp $	*/
11825088edSmatt 
12825088edSmatt /*
13825088edSmatt  * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
14825088edSmatt  *
15825088edSmatt  * Permission to use, copy, modify, and distribute this software for any
16825088edSmatt  * purpose with or without fee is hereby granted, provided that the above
17825088edSmatt  * copyright notice and this permission notice appear in all copies.
18825088edSmatt  *
19825088edSmatt  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
20825088edSmatt  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
21825088edSmatt  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
22825088edSmatt  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23825088edSmatt  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24825088edSmatt  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
25825088edSmatt  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26825088edSmatt  */
27825088edSmatt 
28825088edSmatt #include <sys/cdefs.h>
29*f82ca6eeSskrll __KERNEL_RCSID(0, "$Id: imx_pcic.c,v 1.9 2022/09/27 06:36:42 skrll Exp $");
30825088edSmatt 
31825088edSmatt #include <sys/param.h>
32825088edSmatt #include <sys/systm.h>
33825088edSmatt #include <sys/device.h>
34825088edSmatt #include <sys/kernel.h>
35825088edSmatt #include <sys/kthread.h>
36825088edSmatt 
37825088edSmatt #include <uvm/uvm.h>
38825088edSmatt 
39ed9977b1Sdyoung #include <sys/bus.h>
40825088edSmatt #include <machine/intr.h>
41825088edSmatt 
42825088edSmatt #include <dev/pcmcia/pcmciareg.h>
43825088edSmatt #include <dev/pcmcia/pcmciavar.h>
44825088edSmatt #include <dev/pcmcia/pcmciachip.h>
45825088edSmatt 
46825088edSmatt #ifdef NOTYET
47825088edSmatt #include <arm/imx/imx_gpio.h>
48825088edSmatt #endif
49825088edSmatt #include <arm/imx/imx_pcic.h>
50825088edSmatt 
51825088edSmatt static int	imx_pcic_print(void *, const char *);
52825088edSmatt 
53825088edSmatt static void	imx_pcic_event_thread(void *);
54825088edSmatt #ifdef NOTYET
55825088edSmatt static void	imx_pcic_event_process(struct imx_pcic_socket *);
56825088edSmatt static void	imx_pcic_attach_card(struct imx_pcic_socket *);
57825088edSmatt #endif
58825088edSmatt #ifdef NOTYET
59825088edSmatt static void	imx_pcic_detach_card(struct imx_pcic_socket *, int);
60825088edSmatt #endif
61825088edSmatt 
62825088edSmatt static int	imx_pcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
63825088edSmatt 		    struct pcmcia_mem_handle *);
64825088edSmatt static void	imx_pcic_mem_free(pcmcia_chipset_handle_t,
65825088edSmatt 		    struct pcmcia_mem_handle *);
66825088edSmatt static int	imx_pcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
67825088edSmatt 		   bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
68825088edSmatt static void	imx_pcic_mem_unmap(pcmcia_chipset_handle_t, int);
69825088edSmatt 
70825088edSmatt static int	imx_pcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
71825088edSmatt 		    bus_size_t, bus_size_t, struct pcmcia_io_handle *);
72825088edSmatt static void	imx_pcic_io_free(pcmcia_chipset_handle_t,
73825088edSmatt 		    struct pcmcia_io_handle *);
74825088edSmatt static int	imx_pcic_io_map(pcmcia_chipset_handle_t, int,
75825088edSmatt 		    bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *);
76825088edSmatt static void	imx_pcic_io_unmap(pcmcia_chipset_handle_t, int);
77825088edSmatt 
78825088edSmatt static void	*imx_pcic_intr_establish(pcmcia_chipset_handle_t,
79825088edSmatt 		    struct pcmcia_function *, int, int (*)(void *), void *);
80825088edSmatt static void	imx_pcic_intr_disestablish(pcmcia_chipset_handle_t, void *);
81825088edSmatt 
82825088edSmatt static void	imx_pcic_socket_enable(pcmcia_chipset_handle_t);
83825088edSmatt static void	imx_pcic_socket_disable(pcmcia_chipset_handle_t);
84825088edSmatt static void	imx_pcic_socket_settype(pcmcia_chipset_handle_t, int);
85825088edSmatt 
86825088edSmatt /*
87825088edSmatt  * PCMCIA chipset methods
88825088edSmatt  */
89825088edSmatt static struct pcmcia_chip_functions imx_pcic_pcmcia_functions = {
90825088edSmatt 	imx_pcic_mem_alloc,
91825088edSmatt 	imx_pcic_mem_free,
92825088edSmatt 	imx_pcic_mem_map,
93825088edSmatt 	imx_pcic_mem_unmap,
94825088edSmatt 
95825088edSmatt 	imx_pcic_io_alloc,
96825088edSmatt 	imx_pcic_io_free,
97825088edSmatt 	imx_pcic_io_map,
98825088edSmatt 	imx_pcic_io_unmap,
99825088edSmatt 
100825088edSmatt 	imx_pcic_intr_establish,
101825088edSmatt 	imx_pcic_intr_disestablish,
102825088edSmatt 
103825088edSmatt 	imx_pcic_socket_enable,
104825088edSmatt 	imx_pcic_socket_disable,
105825088edSmatt 	imx_pcic_socket_settype,
106825088edSmatt };
107825088edSmatt 
108825088edSmatt #define IMX_MEMCTL_BASE	0x08000000		/* XXX */
109825088edSmatt #define IMX_MEMCTL_SIZE	0x00000010		/* XXX */
110825088edSmatt #define IMX_PCIC_SOCKET_BASE	0x08009000		/* XXX */
111825088edSmatt #define IMX_PCIC_SOCKET_OFFSET	0x00000000		/* XXX */
112825088edSmatt #define	IMX_PCIC_ATTR_OFFSET	0x00000800		/* XXX 5912 */
113825088edSmatt #define	IMX_PCIC_COMMON_OFFSET	0x00000000		/* XXX 5912 */
114825088edSmatt 
115825088edSmatt 
116825088edSmatt 
117825088edSmatt /*
118825088edSmatt  * PCMCIA Helpers
119825088edSmatt  */
120825088edSmatt static int
imx_pcic_mem_alloc(pcmcia_chipset_handle_t pch,bus_size_t size,struct pcmcia_mem_handle * pmh)121825088edSmatt imx_pcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
122825088edSmatt     struct pcmcia_mem_handle *pmh)
123825088edSmatt {
124825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
125825088edSmatt 
126825088edSmatt 	/* All we need is the bus space tag */
127825088edSmatt 	memset(pmh, 0, sizeof(*pmh));
128825088edSmatt 	pmh->memt = so->sc->sc_iot;
129825088edSmatt 
130825088edSmatt 	return 0;
131825088edSmatt }
132825088edSmatt 
133825088edSmatt static void
imx_pcic_mem_free(pcmcia_chipset_handle_t pch,struct pcmcia_mem_handle * pmh)134825088edSmatt imx_pcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
135825088edSmatt {
136825088edSmatt 
137825088edSmatt 	/* Nothing to do */
138825088edSmatt }
139825088edSmatt 
140825088edSmatt static int
imx_pcic_mem_map(pcmcia_chipset_handle_t pch,int kind,bus_addr_t card_addr,bus_size_t size,struct pcmcia_mem_handle * pmh,bus_size_t * offsetp,int * windowp)141825088edSmatt imx_pcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr,
142825088edSmatt     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
143825088edSmatt     int *windowp)
144825088edSmatt {
145825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
146825088edSmatt 	int error;
147825088edSmatt 	bus_addr_t pa;
148825088edSmatt 
14910cfc49bSperry printf("%s: card_addr %lx\n", __func__, card_addr);
150825088edSmatt 	pa = trunc_page(card_addr);
151825088edSmatt 	*offsetp = card_addr - pa;
15210cfc49bSperry printf("%s: offset %lx\n", __func__, *offsetp);
153825088edSmatt 	size = round_page(card_addr + size) - pa;
154825088edSmatt 	pmh->realsize = size;
155825088edSmatt 
156825088edSmatt 	pa += IMX_PCIC_SOCKET_BASE;
157825088edSmatt 	pa += IMX_PCIC_SOCKET_OFFSET * so->socket;
15810cfc49bSperry printf("%s: pa %lx\n", __func__, pa);
15910cfc49bSperry printf("%s: kind %x\n", __func__, kind);
160825088edSmatt 
161825088edSmatt 	switch (kind & ~PCMCIA_WIDTH_MEM_MASK) {
162825088edSmatt 	case PCMCIA_MEM_ATTR:
163825088edSmatt 		pa += IMX_PCIC_ATTR_OFFSET;
164825088edSmatt 		break;
165825088edSmatt 	case PCMCIA_MEM_COMMON:
166825088edSmatt 		pa += IMX_PCIC_COMMON_OFFSET;
167825088edSmatt 		break;
168825088edSmatt 	default:
169825088edSmatt 		panic("imx_pcic_mem_map: bogus kind");
170825088edSmatt 	}
171825088edSmatt 
17210cfc49bSperry printf("%s: pa %lx\n", __func__, pa);
173825088edSmatt Debugger();
174825088edSmatt 	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh);
175825088edSmatt 	if (error)
176825088edSmatt 		return error;
177825088edSmatt 
178825088edSmatt 	*windowp = (int)pmh->memh;
179825088edSmatt 	return 0;
180825088edSmatt }
181825088edSmatt 
182825088edSmatt static void
imx_pcic_mem_unmap(pcmcia_chipset_handle_t pch,int window)183825088edSmatt imx_pcic_mem_unmap(pcmcia_chipset_handle_t pch, int window)
184825088edSmatt {
185825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
186825088edSmatt 
187825088edSmatt 	bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */
188825088edSmatt }
189825088edSmatt 
190825088edSmatt static int
imx_pcic_io_alloc(pcmcia_chipset_handle_t pch,bus_addr_t start,bus_size_t size,bus_size_t align,struct pcmcia_io_handle * pih)191825088edSmatt imx_pcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
192825088edSmatt     bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih)
193825088edSmatt {
194825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
195825088edSmatt 	bus_addr_t pa;
196825088edSmatt 	int error;
197825088edSmatt 
198825088edSmatt 	memset(pih, 0, sizeof(*pih));
199825088edSmatt 	pih->iot = so->sc->sc_iot;
200825088edSmatt 	pih->addr = start;
201825088edSmatt 	pih->size = size;
202825088edSmatt 
203825088edSmatt 	pa = pih->addr;
204825088edSmatt 	pa += IMX_PCIC_SOCKET_BASE;
205825088edSmatt 	pa += IMX_PCIC_SOCKET_OFFSET * so->socket;
206825088edSmatt 
207825088edSmatt 	/* XXX Are we ignoring alignment constraints? */
208825088edSmatt 	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh);
209825088edSmatt 
210825088edSmatt 	return error;
211825088edSmatt }
212825088edSmatt 
213825088edSmatt static void
imx_pcic_io_free(pcmcia_chipset_handle_t pch,struct pcmcia_io_handle * pih)214825088edSmatt imx_pcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
215825088edSmatt {
216825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
217825088edSmatt 
218825088edSmatt 	bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size);
219825088edSmatt }
220825088edSmatt 
221825088edSmatt static int
imx_pcic_io_map(pcmcia_chipset_handle_t pch,int width,bus_addr_t offset,bus_size_t size,struct pcmcia_io_handle * pih,int * windowp)222825088edSmatt imx_pcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
223825088edSmatt     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
224825088edSmatt {
225825088edSmatt 
226825088edSmatt 	return 0;
227825088edSmatt }
228825088edSmatt 
229825088edSmatt static void
imx_pcic_io_unmap(pcmcia_chipset_handle_t pch,int window)230825088edSmatt imx_pcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
231825088edSmatt {
232825088edSmatt 
233825088edSmatt 	/* Nothing to do */
234825088edSmatt }
235825088edSmatt 
236825088edSmatt static void *
imx_pcic_intr_establish(pcmcia_chipset_handle_t pch,struct pcmcia_function * pf,int ipl,int (* fct)(void *),void * arg)237825088edSmatt imx_pcic_intr_establish(pcmcia_chipset_handle_t pch,
238825088edSmatt     struct pcmcia_function *pf, int ipl, int (*fct)(void *), void *arg)
239825088edSmatt {
240825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
241825088edSmatt 	/* XXX need to check if something should be done here */
242825088edSmatt 
243825088edSmatt 	return (*so->pcictag->intr_establish)(so, ipl, fct, arg);
244825088edSmatt }
245825088edSmatt 
246825088edSmatt static void
imx_pcic_intr_disestablish(pcmcia_chipset_handle_t pch,void * ih)247825088edSmatt imx_pcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
248825088edSmatt {
249825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
250825088edSmatt 
251825088edSmatt 	(*so->pcictag->intr_disestablish)(so, ih);
252825088edSmatt }
253825088edSmatt 
254825088edSmatt static void
imx_pcic_socket_enable(pcmcia_chipset_handle_t pch)255825088edSmatt imx_pcic_socket_enable(pcmcia_chipset_handle_t pch)
256825088edSmatt {
257825088edSmatt #ifdef NOTYET
258825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
259825088edSmatt 	int i;
260825088edSmatt 
261825088edSmatt 	/* Power down the card and socket before setting the voltage. */
262825088edSmatt 	(*so->pcictag->write)(so, IMX_PCIC_CARD_POWER, IMX_PCIC_POWER_OFF);
263825088edSmatt 	(*so->pcictag->set_power)(so, IMX_PCIC_POWER_OFF);
264825088edSmatt 
265825088edSmatt 	/*
266825088edSmatt 	 * Wait 300ms until power fails (Tpf).  Then, wait 100ms since
267825088edSmatt 	 * we are changing Vcc (Toff).
268825088edSmatt 	 */
269825088edSmatt 	delay((300 + 100) * 1000);
270825088edSmatt 
271825088edSmatt 	/* Power up the socket and card at appropriate voltage. */
272825088edSmatt 	if (so->power_capability & IMX_PCIC_POWER_5V) {
273825088edSmatt 		(*so->pcictag->set_power)(so, IMX_PCIC_POWER_5V);
274825088edSmatt 		(*so->pcictag->write)(so, IMX_PCIC_CARD_POWER,
275825088edSmatt 		    IMX_PCIC_POWER_5V);
276825088edSmatt 	} else {
277825088edSmatt 		(*so->pcictag->set_power)(so, IMX_PCIC_POWER_3V);
278825088edSmatt 		(*so->pcictag->write)(so, IMX_PCIC_CARD_POWER,
279825088edSmatt 		    IMX_PCIC_POWER_3V);
280825088edSmatt 	}
281825088edSmatt 
282825088edSmatt 	/*
283825088edSmatt 	 * Wait 100ms until power raise (Tpr) and 20ms to become
284825088edSmatt 	 * stable (Tsu(Vcc)).
285825088edSmatt 	 *
286825088edSmatt 	 * Some machines require some more time to be settled
287825088edSmatt 	 * (another 200ms is added here).
288825088edSmatt 	 */
289825088edSmatt 	delay((100 + 20 + 200) * 1000);
290825088edSmatt 
291825088edSmatt 	/* Hold RESET at least 10us. */
292825088edSmatt 	(*so->pcictag->write)(so, IMX_PCIC_CARD_RESET, 1);
293825088edSmatt 	delay(10);
294825088edSmatt 	/* XXX wrong, but lets TE-CF100 cards work for some reason. */
295825088edSmatt 	delay(3000);
296825088edSmatt 	(*so->pcictag->write)(so, IMX_PCIC_CARD_RESET, 0);
297825088edSmatt 
298825088edSmatt 	/* Wait 20ms as per PC Card standard (r2.01) section 4.3.6. */
299825088edSmatt 	delay(20 * 1000);
300825088edSmatt 
301825088edSmatt 	/* Wait for the card to become ready. */
302825088edSmatt 	for (i = 0; i < 10000; i++) {
303825088edSmatt 		if ((*so->pcictag->read)(so, IMX_PCIC_CARD_READY))
304825088edSmatt 			break;
305825088edSmatt 		delay(500);
306825088edSmatt 	}
307825088edSmatt #else
30810cfc49bSperry printf("%s: (stubbed)\n", __func__);
309825088edSmatt #endif	/* NOTYET */
310825088edSmatt }
311825088edSmatt 
312825088edSmatt static void
imx_pcic_socket_disable(pcmcia_chipset_handle_t pch)313825088edSmatt imx_pcic_socket_disable(pcmcia_chipset_handle_t pch)
314825088edSmatt {
315825088edSmatt #ifdef NOTYET
316825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)pch;
317825088edSmatt 
318825088edSmatt #ifdef PCICDEBUG
319825088edSmatt 	printf("imx_pcic_socket_disable: socket %d\n", so->socket);
320825088edSmatt #endif
321825088edSmatt 
322825088edSmatt 	/* Power down the card and socket. */
323825088edSmatt 	(*so->pcictag->write)(so, IMX_PCIC_CARD_POWER, IMX_PCIC_POWER_OFF);
324825088edSmatt 	(*so->pcictag->set_power)(so, IMX_PCIC_POWER_OFF);
325825088edSmatt #endif	/* NOTYET */
326825088edSmatt }
327825088edSmatt 
328825088edSmatt static void
imx_pcic_socket_settype(pcmcia_chipset_handle_t pch,int type)329825088edSmatt imx_pcic_socket_settype(pcmcia_chipset_handle_t pch, int type)
330825088edSmatt {
331825088edSmatt 
332825088edSmatt #ifdef PCICDEBUG
333825088edSmatt 	printf("imx_pcic_socket_settype: type=%d",type);
334825088edSmatt 
335825088edSmatt 	switch (type) {
336825088edSmatt 	case PCMCIA_IFTYPE_MEMORY:
337825088edSmatt 		printf("(Memory)\n");
338825088edSmatt 		break;
339825088edSmatt 	case PCMCIA_IFTYPE_IO:
340825088edSmatt 		printf("(I/O)\n");
341825088edSmatt 		break;
342825088edSmatt 	default:
343825088edSmatt 		printf("(unknown)\n");
344825088edSmatt 		break;
345825088edSmatt 	}
346825088edSmatt #endif
347825088edSmatt }
348825088edSmatt 
349825088edSmatt /*
350825088edSmatt  * Attachment and initialization
351825088edSmatt  */
352825088edSmatt static int
imx_pcic_print(void * aux,const char * name)353825088edSmatt imx_pcic_print(void *aux, const char *name)
354825088edSmatt {
355825088edSmatt 
356825088edSmatt 	return UNCONF;
357825088edSmatt }
358825088edSmatt 
359825088edSmatt void
imx_pcic_attach_common(struct imx_pcic_softc * sc,void (* socket_setup_hook)(struct imx_pcic_socket *))360825088edSmatt imx_pcic_attach_common(struct imx_pcic_softc *sc,
361825088edSmatt     void (*socket_setup_hook)(struct imx_pcic_socket *))
362825088edSmatt {
363825088edSmatt 	struct pcmciabus_attach_args paa;
364825088edSmatt 	struct imx_pcic_socket *so;
365825088edSmatt 	int s[IMX_PCIC_NSLOT];
366825088edSmatt 	int i;
367825088edSmatt 
368825088edSmatt 	printf(": %d slot%s\n", sc->sc_nslots, sc->sc_nslots < 2 ? "" : "s");
369825088edSmatt 
370825088edSmatt 	if (sc->sc_nslots == 0) {
371cbab9cadSchs 		aprint_error("%s: can't attach\n", device_xname(sc->sc_dev));
372825088edSmatt 		return;
373825088edSmatt 	}
374825088edSmatt 
375825088edSmatt 	if (bus_space_map(sc->sc_iot, IMX_MEMCTL_BASE, IMX_MEMCTL_SIZE,
376825088edSmatt 	    0, &sc->sc_memctl_ioh)) {
377cbab9cadSchs 		aprint_error("%s: failed to map MEMCTL\n", device_xname(sc->sc_dev));
378825088edSmatt 		return;
379825088edSmatt 	}
380825088edSmatt 
381825088edSmatt #if 0
382825088edSmatt 	/* Clear CIT (card present) and set NOS correctly. */
383825088edSmatt 	bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR,
384825088edSmatt 	    (sc->sc_nslots == 2) ? MECR_NOS : 0);
385825088edSmatt #endif
386825088edSmatt 
387825088edSmatt 	if (sc->sc_flags & PPF_REVERSE_ORDER) {
388825088edSmatt 		for (i = 0; i < sc->sc_nslots; i++) {
389825088edSmatt 			s[i] = sc->sc_nslots - 1 - i;
390825088edSmatt 		}
391825088edSmatt 	} else {
392825088edSmatt 		for (i = 0; i < sc->sc_nslots; i++) {
393825088edSmatt 			s[i] = i;
394825088edSmatt 		}
395825088edSmatt 	}
396825088edSmatt 
397825088edSmatt 	for (i = 0; i < sc->sc_nslots; i++) {
398825088edSmatt 		so = &sc->sc_socket[s[i]];
399825088edSmatt 		so->sc = sc;
400825088edSmatt 		so->socket = s[i];
401825088edSmatt 		so->flags = 0;
402825088edSmatt 
403825088edSmatt 		(*socket_setup_hook)(so);
404825088edSmatt 
405825088edSmatt 		paa.paa_busname = "pcmcia";
406825088edSmatt 		paa.pct = (pcmcia_chipset_tag_t)&imx_pcic_pcmcia_functions;
407825088edSmatt 		paa.pch = (pcmcia_chipset_handle_t)so;
40810cfc49bSperry printf("%s: sc_pa %lx\n", __func__, sc->sc_pa);
409825088edSmatt 
4102685996bSthorpej 		so->pcmcia =
411c7fb772bSthorpej 		    config_found(sc->sc_dev, &paa, imx_pcic_print, CFARGS_NONE);
412825088edSmatt 
413825088edSmatt #ifdef NOTYET
414825088edSmatt 		imx_gpio_set_direction(sc->sc_irqpin[s[i]], GPIO_IN);
415825088edSmatt 		imx_gpio_set_direction(sc->sc_irqcfpin[s[i]], GPIO_IN);
416825088edSmatt 
417825088edSmatt 		/* Card slot interrupt */
418825088edSmatt 		so->irq = imx_gpio_intr_establish(sc->sc_irqcfpin[s[i]],
419825088edSmatt 		    IST_EDGE_BOTH, IPL_BIO /* XXX */, "pcic",
420825088edSmatt 		    imx_pcic_intr, so);
421825088edSmatt 
422825088edSmatt 		/* GPIO pin for interrupt */
423825088edSmatt 		so->irqpin = sc->sc_irqpin[s[i]];
424825088edSmatt #else
425825088edSmatt 		so->irqpin = sc->sc_irqpin[s[i]];
42610cfc49bSperry printf("%s: slot %d, irqpin %d\n",  __func__, s[i], sc->sc_irqpin[s[i]]);
427825088edSmatt #endif	/* NOTYET */
428825088edSmatt 
429825088edSmatt 		if (kthread_create(PRI_NONE, 0, NULL,
430825088edSmatt 		    imx_pcic_event_thread, so, &so->event_thread,
431cbab9cadSchs 		    "%s,%d", device_xname(sc->sc_dev), so->socket) != 0) {
432825088edSmatt 			printf("%s: unable to create event thread for %d\n",
433cbab9cadSchs 				device_xname(sc->sc_dev), so->socket);
434825088edSmatt 		}
435825088edSmatt 	}
436825088edSmatt }
437825088edSmatt 
438825088edSmatt /*
439825088edSmatt  * Card slot interrupt handling
440825088edSmatt  */
441825088edSmatt int
imx_pcic_intr(void * arg)442825088edSmatt imx_pcic_intr(void *arg)
443825088edSmatt {
444825088edSmatt 	struct imx_pcic_socket *so = (struct imx_pcic_socket *)arg;
445825088edSmatt 
446825088edSmatt 	(*so->pcictag->clear_intr)(so);
447825088edSmatt         wakeup(so);
448825088edSmatt 
449825088edSmatt         return 1;
450825088edSmatt }
451825088edSmatt 
452825088edSmatt static void
imx_pcic_event_thread(void * arg)453825088edSmatt imx_pcic_event_thread(void *arg)
454825088edSmatt {
455825088edSmatt #ifdef NOTYET
456825088edSmatt 	struct imx_pcic_socket *sock = (struct imx_pcic_socket *)arg;
457825088edSmatt 	u_int cs;
458825088edSmatt 	int present;
459825088edSmatt 
460825088edSmatt 	while (sock->sc->sc_shutdown == 0) {
461825088edSmatt 		(void) tsleep(sock, PWAIT, "imx_pcicev", 0);
462825088edSmatt 
463825088edSmatt 		/* sleep .25s to avoid chattering interrupts */
464825088edSmatt 		(void) tsleep((void *)sock, PWAIT, "imx_pcicss", hz/4);
465825088edSmatt 
466825088edSmatt 		cs = (*sock->pcictag->read)(sock, IMX_PCIC_CARD_STATUS);
467825088edSmatt 		present = sock->flags & IMX_PCIC_FLAG_CARDP;
468825088edSmatt 		if ((cs == IMX_PCIC_CARD_VALID) == (present == 1)) {
469825088edSmatt 			continue;	/* state unchanged */
470825088edSmatt 		}
471825088edSmatt 
472825088edSmatt 		/* XXX Do both? */
473825088edSmatt 		imx_pcic_event_process(sock);
474825088edSmatt 	}
475825088edSmatt 	sock->event_thread = NULL;
476825088edSmatt 
477825088edSmatt 	/* In case parent is waiting for us to exit. */
478825088edSmatt 	wakeup(sock->sc);
479825088edSmatt 	kthread_exit(0);
480825088edSmatt #endif	/* NOTYET */
481825088edSmatt }
482825088edSmatt 
483825088edSmatt #ifdef NOTYET
484825088edSmatt static void
imx_pcic_event_process(struct imx_pcic_socket * sock)485825088edSmatt imx_pcic_event_process(struct imx_pcic_socket *sock)
486825088edSmatt {
487825088edSmatt 	u_int cs;
488825088edSmatt 
489825088edSmatt 	cs = (*sock->pcictag->read)(sock, IMX_PCIC_CARD_STATUS);
490825088edSmatt 	if (cs == IMX_PCIC_CARD_VALID) {
491825088edSmatt 		if (!(sock->flags & IMX_PCIC_FLAG_CARDP)) {
492825088edSmatt 			imx_pcic_attach_card(sock);
493825088edSmatt 		}
494825088edSmatt 	} else {
495825088edSmatt 		if ((sock->flags & IMX_PCIC_FLAG_CARDP)) {
496825088edSmatt 			imx_pcic_detach_card(sock, DETACH_FORCE);
497825088edSmatt 		}
498825088edSmatt 	}
499825088edSmatt }
500825088edSmatt 
501825088edSmatt static void
imx_pcic_attach_card(struct imx_pcic_socket * h)502825088edSmatt imx_pcic_attach_card(struct imx_pcic_socket *h)
503825088edSmatt {
504825088edSmatt 
505825088edSmatt 	if (h->flags & IMX_PCIC_FLAG_CARDP)
506825088edSmatt 		panic("pcic_attach_card: already attached");
507825088edSmatt 	h->flags |= IMX_PCIC_FLAG_CARDP;
508825088edSmatt 
509825088edSmatt 
510825088edSmatt 	/* call the MI attach function */
511825088edSmatt 	pcmcia_card_attach(h->pcmcia);
512825088edSmatt }
513825088edSmatt #endif	/* NOTYET */
514825088edSmatt 
515825088edSmatt #ifdef NOTYET
516825088edSmatt static void
imx_pcic_detach_card(struct imx_pcic_socket * h,int flags)517825088edSmatt imx_pcic_detach_card(struct imx_pcic_socket *h, int flags)
518825088edSmatt {
519825088edSmatt 	struct imx_pcic_softc *sc = h->sc;
520825088edSmatt 	int i;
521825088edSmatt 
522825088edSmatt 	if (h->flags & IMX_PCIC_FLAG_CARDP) {
523825088edSmatt 		h->flags &= ~IMX_PCIC_FLAG_CARDP;
524825088edSmatt 
525825088edSmatt 		/* call the MI detach function */
526825088edSmatt 		pcmcia_card_detach(h->pcmcia, flags);
527825088edSmatt 	}
528825088edSmatt 
529825088edSmatt 	/* Clear CIT if no other card is present. */
530825088edSmatt 	for (i = 0; i < sc->sc_nslots; i++) {
531825088edSmatt 		if (sc->sc_socket[i].flags & IMX_PCIC_FLAG_CARDP) {
532825088edSmatt 			return;
533825088edSmatt 		}
534825088edSmatt 	}
535825088edSmatt }
536825088edSmatt #endif	/* NOTYET */
537