xref: /netbsd-src/sys/arch/arm/xscale/pxa2x0_pcic.c (revision f82ca6eefb335bf699131a4ebe4cc00c8911db8a)
1 /*	$NetBSD: pxa2x0_pcic.c,v 1.15 2022/09/27 06:36:43 skrll Exp $	*/
2 /*	$OpenBSD: pxa2x0_pcic.c,v 1.17 2005/12/14 15:08:51 uwe Exp $	*/
3 
4 /*
5  * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: pxa2x0_pcic.c,v 1.15 2022/09/27 06:36:43 skrll Exp $");
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/kernel.h>
27 #include <sys/kthread.h>
28 
29 #include <uvm/uvm.h>
30 
31 #include <sys/bus.h>
32 #include <machine/intr.h>
33 
34 #include <dev/pcmcia/pcmciareg.h>
35 #include <dev/pcmcia/pcmciavar.h>
36 #include <dev/pcmcia/pcmciachip.h>
37 
38 #include <arm/xscale/pxa2x0cpu.h>
39 #include <arm/xscale/pxa2x0reg.h>
40 #include <arm/xscale/pxa2x0var.h>
41 #include <arm/xscale/pxa2x0_gpio.h>
42 #include <arm/xscale/pxa2x0_pcic.h>
43 
44 static int	pxapcic_print(void *, const char *);
45 
46 static void	pxapcic_doattach(device_t);
47 
48 static void	pxapcic_event_thread(void *);
49 static void	pxapcic_event_process(struct pxapcic_socket *);
50 static void	pxapcic_attach_card(struct pxapcic_socket *);
51 static void	pxapcic_detach_card(struct pxapcic_socket *, int);
52 
53 static int	pxapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
54 		    struct pcmcia_mem_handle *);
55 static void	pxapcic_mem_free(pcmcia_chipset_handle_t,
56 		    struct pcmcia_mem_handle *);
57 static int	pxapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
58 		   bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
59 static void	pxapcic_mem_unmap(pcmcia_chipset_handle_t, int);
60 
61 static int	pxapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
62 		    bus_size_t, bus_size_t, struct pcmcia_io_handle *);
63 static void	pxapcic_io_free(pcmcia_chipset_handle_t,
64 		    struct pcmcia_io_handle *);
65 static int	pxapcic_io_map(pcmcia_chipset_handle_t, int,
66 		    bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *);
67 static void	pxapcic_io_unmap(pcmcia_chipset_handle_t, int);
68 
69 static void	*pxapcic_intr_establish(pcmcia_chipset_handle_t,
70 		    struct pcmcia_function *, int, int (*)(void *), void *);
71 static void	pxapcic_intr_disestablish(pcmcia_chipset_handle_t, void *);
72 
73 static void	pxapcic_socket_enable(pcmcia_chipset_handle_t);
74 static void	pxapcic_socket_disable(pcmcia_chipset_handle_t);
75 static void	pxapcic_socket_settype(pcmcia_chipset_handle_t, int);
76 
77 /*
78  * PCMCIA chipset methods
79  */
80 static struct pcmcia_chip_functions pxapcic_pcmcia_functions = {
81 	pxapcic_mem_alloc,
82 	pxapcic_mem_free,
83 	pxapcic_mem_map,
84 	pxapcic_mem_unmap,
85 
86 	pxapcic_io_alloc,
87 	pxapcic_io_free,
88 	pxapcic_io_map,
89 	pxapcic_io_unmap,
90 
91 	pxapcic_intr_establish,
92 	pxapcic_intr_disestablish,
93 
94 	pxapcic_socket_enable,
95 	pxapcic_socket_disable,
96 	pxapcic_socket_settype,
97 };
98 
99 #define	PXAPCIC_ATTR_OFFSET	0x08000000
100 #define	PXAPCIC_COMMON_OFFSET	0x0C000000
101 
102 /*
103  * PCMCIA Helpers
104  */
105 static int
pxapcic_mem_alloc(pcmcia_chipset_handle_t pch,bus_size_t size,struct pcmcia_mem_handle * pmh)106 pxapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
107     struct pcmcia_mem_handle *pmh)
108 {
109 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
110 
111 	/* All we need is the bus space tag */
112 	memset(pmh, 0, sizeof(*pmh));
113 	pmh->memt = so->sc->sc_iot;
114 
115 	return 0;
116 }
117 
118 static void
pxapcic_mem_free(pcmcia_chipset_handle_t pch,struct pcmcia_mem_handle * pmh)119 pxapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
120 {
121 
122 	/* Nothing to do */
123 }
124 
125 static int
pxapcic_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)126 pxapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr,
127     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
128     int *windowp)
129 {
130 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
131 	int error;
132 	bus_addr_t pa;
133 
134 	pa = trunc_page(card_addr);
135 	*offsetp = card_addr - pa;
136 	size = round_page(card_addr + size) - pa;
137 	pmh->realsize = size;
138 
139 	pa += PXA2X0_PCIC_SOCKET_BASE;
140 	pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket;
141 
142 	switch (kind & ~PCMCIA_WIDTH_MEM_MASK) {
143 	case PCMCIA_MEM_ATTR:
144 		pa += PXAPCIC_ATTR_OFFSET;
145 		break;
146 	case PCMCIA_MEM_COMMON:
147 		pa += PXAPCIC_COMMON_OFFSET;
148 		break;
149 	default:
150 		panic("pxapcic_mem_map: bogus kind");
151 	}
152 
153 	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh);
154 	if (error)
155 		return error;
156 
157 	*windowp = (int)pmh->memh;
158 	return 0;
159 }
160 
161 static void
pxapcic_mem_unmap(pcmcia_chipset_handle_t pch,int window)162 pxapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window)
163 {
164 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
165 
166 	bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */
167 }
168 
169 static int
pxapcic_io_alloc(pcmcia_chipset_handle_t pch,bus_addr_t start,bus_size_t size,bus_size_t align,struct pcmcia_io_handle * pih)170 pxapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
171     bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih)
172 {
173 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
174 	bus_addr_t pa;
175 	int error;
176 
177 	memset(pih, 0, sizeof(*pih));
178 	pih->iot = so->sc->sc_iot;
179 	pih->addr = start;
180 	pih->size = size;
181 
182 	pa = pih->addr;
183 	pa += PXA2X0_PCIC_SOCKET_BASE;
184 	pa += PXA2X0_PCIC_SOCKET_OFFSET * so->socket;
185 
186 	/* XXX Are we ignoring alignment constraints? */
187 	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh);
188 
189 	return error;
190 }
191 
192 static void
pxapcic_io_free(pcmcia_chipset_handle_t pch,struct pcmcia_io_handle * pih)193 pxapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
194 {
195 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
196 
197 	bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size);
198 }
199 
200 static int
pxapcic_io_map(pcmcia_chipset_handle_t pch,int width,bus_addr_t offset,bus_size_t size,struct pcmcia_io_handle * pih,int * windowp)201 pxapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
202     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
203 {
204 
205 	return 0;
206 }
207 
208 static void
pxapcic_io_unmap(pcmcia_chipset_handle_t pch,int window)209 pxapcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
210 {
211 
212 	/* Nothing to do */
213 }
214 
215 static void *
pxapcic_intr_establish(pcmcia_chipset_handle_t pch,struct pcmcia_function * pf,int ipl,int (* fct)(void *),void * arg)216 pxapcic_intr_establish(pcmcia_chipset_handle_t pch,
217     struct pcmcia_function *pf, int ipl, int (*fct)(void *), void *arg)
218 {
219 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
220 	/* XXX need to check if something should be done here */
221 
222 	return (*so->pcictag->intr_establish)(so, ipl, fct, arg);
223 }
224 
225 static void
pxapcic_intr_disestablish(pcmcia_chipset_handle_t pch,void * ih)226 pxapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
227 {
228 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
229 
230 	(*so->pcictag->intr_disestablish)(so, ih);
231 }
232 
233 static void
pxapcic_socket_enable(pcmcia_chipset_handle_t pch)234 pxapcic_socket_enable(pcmcia_chipset_handle_t pch)
235 {
236 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
237 	int i;
238 
239 	/* Power down the card and socket before setting the voltage. */
240 	(*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF);
241 	(*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF);
242 
243 	/*
244 	 * Wait 300ms until power fails (Tpf).  Then, wait 100ms since
245 	 * we are changing Vcc (Toff).
246 	 */
247 	delay((300 + 100) * 1000);
248 
249 	/* Power up the socket and card at appropriate voltage. */
250 	if (so->power_capability & PXAPCIC_POWER_5V) {
251 		(*so->pcictag->set_power)(so, PXAPCIC_POWER_5V);
252 		(*so->pcictag->write)(so, PXAPCIC_CARD_POWER,
253 		    PXAPCIC_POWER_5V);
254 	} else {
255 		(*so->pcictag->set_power)(so, PXAPCIC_POWER_3V);
256 		(*so->pcictag->write)(so, PXAPCIC_CARD_POWER,
257 		    PXAPCIC_POWER_3V);
258 	}
259 
260 	/*
261 	 * Wait 100ms until power raise (Tpr) and 20ms to become
262 	 * stable (Tsu(Vcc)).
263 	 *
264 	 * Some machines require some more time to be settled
265 	 * (another 200ms is added here).
266 	 */
267 	delay((100 + 20 + 200) * 1000);
268 
269 	/* Hold RESET at least 10us. */
270 	(*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 1);
271 	delay(10);
272 	/* XXX wrong, but lets TE-CF100 cards work for some reason. */
273 	delay(3000);
274 	(*so->pcictag->write)(so, PXAPCIC_CARD_RESET, 0);
275 
276 	/* Wait 20ms as per PC Card standard (r2.01) section 4.3.6. */
277 	delay(20 * 1000);
278 
279 	/* Wait for the card to become ready. */
280 	for (i = 0; i < 10000; i++) {
281 		if ((*so->pcictag->read)(so, PXAPCIC_CARD_READY))
282 			break;
283 		delay(500);
284 	}
285 }
286 
287 static void
pxapcic_socket_disable(pcmcia_chipset_handle_t pch)288 pxapcic_socket_disable(pcmcia_chipset_handle_t pch)
289 {
290 	struct pxapcic_socket *so = (struct pxapcic_socket *)pch;
291 
292 #ifdef PCICDEBUG
293 	printf("pxapcic_socket_disable: socket %d\n", so->socket);
294 #endif
295 
296 	/* Power down the card and socket. */
297 	(*so->pcictag->write)(so, PXAPCIC_CARD_POWER, PXAPCIC_POWER_OFF);
298 	(*so->pcictag->set_power)(so, PXAPCIC_POWER_OFF);
299 }
300 
301 static void
pxapcic_socket_settype(pcmcia_chipset_handle_t pch,int type)302 pxapcic_socket_settype(pcmcia_chipset_handle_t pch, int type)
303 {
304 
305 #ifdef PCICDEBUG
306 	printf("pxapcic_socket_settype: type=%d",type);
307 
308 	switch (type) {
309 	case PCMCIA_IFTYPE_MEMORY:
310 		printf("(Memory)\n");
311 		break;
312 	case PCMCIA_IFTYPE_IO:
313 		printf("(I/O)\n");
314 		break;
315 	default:
316 		printf("(unknown)\n");
317 		break;
318 	}
319 #endif
320 }
321 
322 /*
323  * Attachment and initialization
324  */
325 static int
pxapcic_print(void * aux,const char * name)326 pxapcic_print(void *aux, const char *name)
327 {
328 
329 	return UNCONF;
330 }
331 
332 void
pxapcic_attach_common(struct pxapcic_softc * sc,void (* socket_setup_hook)(struct pxapcic_socket *))333 pxapcic_attach_common(struct pxapcic_softc *sc,
334     void (*socket_setup_hook)(struct pxapcic_socket *))
335 {
336 	struct pcmciabus_attach_args paa;
337 	struct pxapcic_socket *so;
338 	int s[PXAPCIC_NSLOT];
339 	int i;
340 
341 	printf(": %d slot%s\n", sc->sc_nslots, sc->sc_nslots < 2 ? "" : "s");
342 
343 	if (sc->sc_nslots == 0) {
344 		aprint_error_dev(sc->sc_dev, "can't attach\n");
345 		return;
346 	}
347 
348 	if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE,
349 	    0, &sc->sc_memctl_ioh)) {
350 		aprint_error_dev(sc->sc_dev, "failed to map MEMCTL\n");
351 		return;
352 	}
353 
354 	/* Clear CIT (card present) and set NOS correctly. */
355 	bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR,
356 	    (sc->sc_nslots == 2) ? MECR_NOS : 0);
357 
358 	if (sc->sc_flags & PPF_REVERSE_ORDER) {
359 		for (i = 0; i < sc->sc_nslots; i++) {
360 			s[i] = sc->sc_nslots - 1 - i;
361 		}
362 	} else {
363 		for (i = 0; i < sc->sc_nslots; i++) {
364 			s[i] = i;
365 		}
366 	}
367 
368 	for (i = 0; i < sc->sc_nslots; i++) {
369 		so = &sc->sc_socket[s[i]];
370 		so->sc = sc;
371 		so->socket = s[i];
372 		so->flags = 0;
373 
374 		(*socket_setup_hook)(so);
375 
376 		paa.paa_busname = "pcmcia";
377 		paa.pct = (pcmcia_chipset_tag_t)&pxapcic_pcmcia_functions;
378 		paa.pch = (pcmcia_chipset_handle_t)so;
379 
380 		so->pcmcia =
381 		    config_found(sc->sc_dev, &paa, pxapcic_print, CFARGS_NONE);
382 
383 		pxa2x0_gpio_set_function(sc->sc_irqpin[s[i]], GPIO_IN);
384 		pxa2x0_gpio_set_function(sc->sc_irqcfpin[s[i]], GPIO_IN);
385 
386 		/* Card slot interrupt */
387 		so->irq = pxa2x0_gpio_intr_establish(sc->sc_irqcfpin[s[i]],
388 		    IST_EDGE_BOTH, IPL_BIO /* XXX */, pxapcic_intr, so);
389 
390 		/* GPIO pin for interrupt */
391 		so->irqpin = sc->sc_irqpin[s[i]];
392 	}
393 
394 	config_interrupts(sc->sc_dev, pxapcic_doattach);
395 }
396 
397 void
pxapcic_doattach(device_t self)398 pxapcic_doattach(device_t self)
399 {
400 	struct pxapcic_softc *sc = device_private(self);
401 	struct pxapcic_socket *sock;
402 	int s[PXAPCIC_NSLOT];
403 	int i;
404 	u_int cs;
405 
406 	if (sc->sc_flags & PPF_REVERSE_ORDER) {
407 		for (i = 0; i < sc->sc_nslots; i++) {
408 			s[i] = sc->sc_nslots - 1 - i;
409 		}
410 	} else {
411 		for (i = 0; i < sc->sc_nslots; i++) {
412 			s[i] = i;
413 		}
414 	}
415 
416 	for (i = 0; i < sc->sc_nslots; i++) {
417 		sock = &sc->sc_socket[s[i]];
418 
419 		config_pending_incr(self);
420 
421 		/* If there's a card there, attach it. */
422 		cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS);
423 		if (cs == PXAPCIC_CARD_VALID)
424 			pxapcic_attach_card(sock);
425 
426 		if (kthread_create(PRI_NONE, 0, NULL, pxapcic_event_thread,
427 		    sock, &sock->event_thread, "%s,%d",
428 		    device_xname(sc->sc_dev), sock->socket)) {
429 			aprint_error_dev(sc->sc_dev,
430 			    "unable to create event thread for %d\n",
431 			    sock->socket);
432 		}
433 	}
434 }
435 
436 /*
437  * Card slot interrupt handling
438  */
439 int
pxapcic_intr(void * arg)440 pxapcic_intr(void *arg)
441 {
442 	struct pxapcic_socket *so = (struct pxapcic_socket *)arg;
443 
444 	(*so->pcictag->clear_intr)(so);
445         wakeup(so);
446 
447         return 1;
448 }
449 
450 static void
pxapcic_event_thread(void * arg)451 pxapcic_event_thread(void *arg)
452 {
453 	struct pxapcic_socket *sock = (struct pxapcic_socket *)arg;
454 	u_int cs;
455 	int present;
456 
457 	config_pending_decr(sock->sc->sc_dev);
458 
459 	while (sock->sc->sc_shutdown == 0) {
460 		(void) tsleep(sock, PWAIT, "pxapcicev", 0);
461 
462 		/* sleep .25s to avoid chattering interrupts */
463 		(void) tsleep((void *)sock, PWAIT, "pxapcicss", hz/4);
464 
465 		cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS);
466 		present = sock->flags & PXAPCIC_FLAG_CARDP;
467 		if ((cs == PXAPCIC_CARD_VALID) == (present == 1)) {
468 			continue;	/* state unchanged */
469 		}
470 
471 		/* XXX Do both? */
472 		pxapcic_event_process(sock);
473 	}
474 	sock->event_thread = NULL;
475 
476 	/* In case parent is waiting for us to exit. */
477 	wakeup(sock->sc);
478 	kthread_exit(0);
479 }
480 
481 static void
pxapcic_event_process(struct pxapcic_socket * sock)482 pxapcic_event_process(struct pxapcic_socket *sock)
483 {
484 	u_int cs;
485 
486 	cs = (*sock->pcictag->read)(sock, PXAPCIC_CARD_STATUS);
487 	if (cs == PXAPCIC_CARD_VALID) {
488 		if (!(sock->flags & PXAPCIC_FLAG_CARDP)) {
489 			pxapcic_attach_card(sock);
490 		}
491 	} else {
492 		if ((sock->flags & PXAPCIC_FLAG_CARDP)) {
493 			pxapcic_detach_card(sock, DETACH_FORCE);
494 		}
495 	}
496 }
497 
498 static void
pxapcic_attach_card(struct pxapcic_socket * h)499 pxapcic_attach_card(struct pxapcic_socket *h)
500 {
501 	struct pxapcic_softc *sc = h->sc;
502 	uint32_t reg;
503 
504 	if (h->flags & PXAPCIC_FLAG_CARDP)
505 		panic("pcic_attach_card: already attached");
506 	h->flags |= PXAPCIC_FLAG_CARDP;
507 
508 	/* Set CIT if any card is present. */
509 	reg = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR);
510 	bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR,
511 	    reg | MECR_CIT);
512 
513 	/* call the MI attach function */
514 	pcmcia_card_attach(h->pcmcia);
515 }
516 
517 static void
pxapcic_detach_card(struct pxapcic_socket * h,int flags)518 pxapcic_detach_card(struct pxapcic_socket *h, int flags)
519 {
520 	struct pxapcic_softc *sc = h->sc;
521 	uint32_t reg;
522 	int i;
523 
524 	if (h->flags & PXAPCIC_FLAG_CARDP) {
525 		h->flags &= ~PXAPCIC_FLAG_CARDP;
526 
527 		/* call the MI detach function */
528 		pcmcia_card_detach(h->pcmcia, flags);
529 	}
530 
531 	/* Clear CIT if no other card is present. */
532 	for (i = 0; i < sc->sc_nslots; i++) {
533 		if (sc->sc_socket[i].flags & PXAPCIC_FLAG_CARDP) {
534 			return;
535 		}
536 	}
537 
538 	reg = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR);
539 	bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, MEMCTL_MECR,
540 	    reg & ~MECR_CIT);
541 }
542