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
44static int	pxapcic_print(void *, const char *);
45
46static void	pxapcic_doattach(device_t);
47
48static void	pxapcic_event_thread(void *);
49static void	pxapcic_event_process(struct pxapcic_socket *);
50static void	pxapcic_attach_card(struct pxapcic_socket *);
51static void	pxapcic_detach_card(struct pxapcic_socket *, int);
52
53static int	pxapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
54		    struct pcmcia_mem_handle *);
55static void	pxapcic_mem_free(pcmcia_chipset_handle_t,
56		    struct pcmcia_mem_handle *);
57static int	pxapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
58		   bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
59static void	pxapcic_mem_unmap(pcmcia_chipset_handle_t, int);
60
61static int	pxapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
62		    bus_size_t, bus_size_t, struct pcmcia_io_handle *);
63static void	pxapcic_io_free(pcmcia_chipset_handle_t,
64		    struct pcmcia_io_handle *);
65static int	pxapcic_io_map(pcmcia_chipset_handle_t, int,
66		    bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *);
67static void	pxapcic_io_unmap(pcmcia_chipset_handle_t, int);
68
69static void	*pxapcic_intr_establish(pcmcia_chipset_handle_t,
70		    struct pcmcia_function *, int, int (*)(void *), void *);
71static void	pxapcic_intr_disestablish(pcmcia_chipset_handle_t, void *);
72
73static void	pxapcic_socket_enable(pcmcia_chipset_handle_t);
74static void	pxapcic_socket_disable(pcmcia_chipset_handle_t);
75static void	pxapcic_socket_settype(pcmcia_chipset_handle_t, int);
76
77/*
78 * PCMCIA chipset methods
79 */
80static 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 */
105static int
106pxapcic_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
118static void
119pxapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
120{
121
122	/* Nothing to do */
123}
124
125static int
126pxapcic_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
161static void
162pxapcic_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
169static int
170pxapcic_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
192static void
193pxapcic_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
200static int
201pxapcic_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
208static void
209pxapcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
210{
211
212	/* Nothing to do */
213}
214
215static void *
216pxapcic_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
225static void
226pxapcic_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
233static void
234pxapcic_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
287static void
288pxapcic_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
301static void
302pxapcic_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 */
325static int
326pxapcic_print(void *aux, const char *name)
327{
328
329	return UNCONF;
330}
331
332void
333pxapcic_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
397void
398pxapcic_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 */
439int
440pxapcic_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
450static void
451pxapcic_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
481static void
482pxapcic_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
498static void
499pxapcic_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
517static void
518pxapcic_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