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