1/*	$NetBSD: sa11xx_pcic.c,v 1.14 2022/09/27 06:36:43 skrll Exp $	*/
2
3/*
4 * Copyright (c) 2001 IWAMOTO Toshihiro.  All rights reserved.
5 * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Common code for SA-11x0 based PCMCIA modules.
35 */
36
37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: sa11xx_pcic.c,v 1.14 2022/09/27 06:36:43 skrll Exp $");
39
40#include <sys/types.h>
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/device.h>
44#include <sys/callout.h>
45#include <sys/kernel.h>
46#include <sys/kthread.h>
47#include <sys/bus.h>
48#include <sys/intr.h>
49
50#include <uvm/uvm.h>
51
52#include <dev/pcmcia/pcmciareg.h>
53#include <dev/pcmcia/pcmciavar.h>
54#include <dev/pcmcia/pcmciachip.h>
55
56#include <arm/sa11x0/sa11x0_reg.h>
57#include <arm/sa11x0/sa11x0_var.h>
58#include <arm/sa11x0/sa11xx_pcicreg.h>
59#include <arm/sa11x0/sa11xx_pcicvar.h>
60
61static	int	sapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
62					struct pcmcia_mem_handle *);
63static	void	sapcic_mem_free(pcmcia_chipset_handle_t,
64				       struct pcmcia_mem_handle *);
65static	int	sapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
66				      bus_size_t, struct pcmcia_mem_handle *,
67				      bus_addr_t *, int *);
68static	void	sapcic_mem_unmap(pcmcia_chipset_handle_t, int);
69static	int	sapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
70				       bus_size_t, bus_size_t,
71				       struct pcmcia_io_handle *);
72static	void	sapcic_io_free(pcmcia_chipset_handle_t,
73				      struct pcmcia_io_handle *);
74static	int	sapcic_io_map(pcmcia_chipset_handle_t, int,
75				     bus_addr_t, bus_size_t,
76				     struct pcmcia_io_handle *, int *);
77static	void	sapcic_io_unmap(pcmcia_chipset_handle_t, int);
78static	void	*sapcic_intr_establish(pcmcia_chipset_handle_t,
79					      struct pcmcia_function *, int,
80					      int (*)(void *), void *);
81static	void	sapcic_intr_disestablish(pcmcia_chipset_handle_t,
82						void *);
83static	void	sapcic_socket_enable(pcmcia_chipset_handle_t);
84static	void	sapcic_socket_disable(pcmcia_chipset_handle_t);
85static	void	sapcic_socket_settype(pcmcia_chipset_handle_t, int);
86
87static	void	sapcic_event_thread(void *);
88
89static	void	sapcic_delay(int, const char *);
90
91#ifdef DEBUG
92#define DPRINTF(arg)	aprint_normal arg
93#else
94#define DPRINTF(arg)
95#endif
96
97struct pcmcia_chip_functions sa11x0_pcmcia_functions = {
98	sapcic_mem_alloc,
99	sapcic_mem_free,
100	sapcic_mem_map,
101	sapcic_mem_unmap,
102
103	sapcic_io_alloc,
104	sapcic_io_free,
105	sapcic_io_map,
106	sapcic_io_unmap,
107
108	sapcic_intr_establish,
109	sapcic_intr_disestablish,
110
111	sapcic_socket_enable,
112	sapcic_socket_disable,
113	sapcic_socket_settype,
114};
115
116
117void
118sapcic_kthread_create(void *arg)
119{
120	struct sapcic_socket *so = arg;
121
122	/* XXX attach card if already present */
123
124	so->laststatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
125	if (so->laststatus == SAPCIC_CARD_VALID) {
126		aprint_normal_dev(so->sc->sc_dev, "card present\n");
127		pcmcia_card_attach(so->pcmcia);
128	}
129
130	if (kthread_create(PRI_NONE, 0, NULL, sapcic_event_thread, so,
131	    &so->event_thread, "%s,%d", device_xname(so->sc->sc_dev), so->socket)) {
132		aprint_normal_dev(so->sc->sc_dev, "unable to create event thread for socket %d\n",
133		       so->socket);
134		panic("sapcic_kthread_create");
135	}
136}
137
138static void
139sapcic_event_thread(void *arg)
140{
141	struct sapcic_socket *so = arg;
142	int newstatus, s;
143
144	while (so->shutdown == 0) {
145		/*
146		 * Serialize event processing on the PCIC.  We may
147		 * sleep while we hold this lock.
148		 */
149		mutex_enter(&so->sc->sc_lock);
150
151		/* sleep .25s to be enqueued chatterling interrupts */
152		(void) tsleep(sapcic_event_thread, PWAIT, "pcicss", hz / 4);
153
154		s = splhigh();
155		so->event = 0;
156
157		/* we don't rely on interrupt type */
158		newstatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
159		splx(s);
160
161		if (so->laststatus == newstatus) {
162			/*
163			 * No events to process; release the PCIC lock.
164			 */
165			mutex_exit(&so->sc->sc_lock);
166			(void) tsleep(&so->event, PWAIT, "pcicev", hz);
167			continue;
168		}
169
170		so->laststatus = newstatus;
171		switch (newstatus) {
172		case SAPCIC_CARD_VALID:
173			aprint_normal_dev(so->sc->sc_dev, "insertion event\n");
174
175			pcmcia_card_attach(so->pcmcia);
176			break;
177
178		case SAPCIC_CARD_INVALID:
179			aprint_normal_dev(so->sc->sc_dev, "removal event\n");
180
181			pcmcia_card_detach(so->pcmcia, DETACH_FORCE);
182			break;
183
184		default:
185			panic("sapcic_event_thread: unknown status %d",
186			    newstatus);
187		}
188
189		mutex_exit(&so->sc->sc_lock);
190	}
191
192	so->event_thread = NULL;
193
194	/* In case parent is waiting for us to exit. */
195	wakeup(so->sc);
196
197	kthread_exit(0);
198}
199
200static void
201sapcic_delay(int timo, const char *wmesg)
202{
203#ifdef DIAGNOSTIC
204	if (curlwp == NULL)
205		panic("sapcic_delay: called in interrupt context");
206#endif
207
208	tsleep(sapcic_delay, PWAIT, wmesg, roundup(timo * hz, 1000) / 1000);
209}
210
211int
212sapcic_intr(void *arg)
213{
214	struct sapcic_socket *so = arg;
215
216	so->event++;
217	(so->pcictag->clear_intr)(so->socket);
218	wakeup(&so->event);
219	return 1;
220}
221
222static int
223sapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
224    struct pcmcia_mem_handle *pmh)
225{
226	struct sapcic_socket *so = pch;
227
228	/* All we need is bus space tag */
229	memset(pmh, 0, sizeof(*pmh));
230	pmh->memt = so->sc->sc_iot;
231	return 0;
232}
233
234
235static void
236sapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
237{
238}
239
240static int
241sapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr,
242    bus_size_t size, struct pcmcia_mem_handle *pmh, bus_addr_t *offsetp,
243    int *windowp)
244{
245	struct sapcic_socket *so = pch;
246	int error;
247	bus_addr_t pa;
248
249	pa = trunc_page(card_addr);
250	*offsetp = card_addr - pa;
251	size = round_page(card_addr + size) - pa;
252	pmh->realsize = size;
253
254	pa += SAPCIC_BASE_OFFSET;
255	pa += SAPCIC_SOCKET_OFFSET * so->socket;
256
257	switch (kind & ~PCMCIA_WIDTH_MEM_MASK) {
258	case PCMCIA_MEM_ATTR:
259		pa += SAPCIC_ATTR_OFFSET;
260		break;
261	case PCMCIA_MEM_COMMON:
262		pa += SAPCIC_COMMON_OFFSET;
263		break;
264	default:
265		panic("sapcic_mem_map: bogus kind");
266	}
267
268	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh);
269	if (!error)
270		*windowp = (int)pmh->memh;
271	return error;
272}
273
274static void
275sapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window)
276{
277	struct sapcic_socket *so = pch;
278
279	bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */
280}
281
282static int
283sapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
284    bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih)
285{
286	struct sapcic_socket *so = pch;
287	int error;
288	bus_addr_t pa;
289
290	memset(pih, 0, sizeof(*pih));
291	pih->iot = so->sc->sc_iot;
292	pih->addr = start;
293	pih->size = size;
294
295	pa = pih->addr;
296	pa += SAPCIC_BASE_OFFSET;
297	pa += SAPCIC_SOCKET_OFFSET * so->socket;
298
299	DPRINTF(("sapcic_io_alloc: %x %x\n", (unsigned int)pa,
300		 (unsigned int)size));
301	/* XXX Are we ignoring alignment constraints? */
302	error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh);
303
304	return error;
305}
306
307static void
308sapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
309{
310	struct sapcic_socket *so = pch;
311
312	bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size);
313}
314
315static int
316sapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
317    bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
318{
319
320	return 0;
321}
322
323static void sapcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
324{
325}
326
327static void *
328sapcic_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
329    int ipl, int (*fct)(void *), void *arg)
330{
331	struct sapcic_socket *so = pch;
332
333	/* XXX need to check if something should be done here */
334
335	return (so->pcictag->intr_establish)(so, ipl, fct, arg);
336}
337
338static void
339sapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
340{
341	struct sapcic_socket *so = pch;
342
343	(so->pcictag->intr_disestablish)(so, ih);
344}
345
346static void
347sapcic_socket_enable(pcmcia_chipset_handle_t pch)
348{
349	struct sapcic_socket *so = pch;
350	int i;
351
352#if defined(DIAGNOSTIC) && defined(notyet)
353	if (so->flags & PCIC_FLAG_ENABLED)
354		aprint_normal("sapcic_socket_enable: enabling twice\n");
355#endif
356
357	/* disable interrupts */
358
359	/* power down the socket to reset it, clear the card reset pin */
360	(so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
361
362	/*
363	 * wait 300ms until power fails (Tpf).  Then, wait 100ms since
364	 * we are changing Vcc (Toff).
365	 */
366	sapcic_delay(300 + 100, "pccen0");
367
368	/* power up the socket */
369	/* XXX voltage selection should be done in PCMCIA code */
370	if (so->power_capability & SAPCIC_POWER_5V) {
371		(so->pcictag->set_power)(so, SAPCIC_POWER_5V);
372		(so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
373				     SAPCIC_POWER_5V);
374	} else {
375		(so->pcictag->set_power)(so, SAPCIC_POWER_3V);
376		(so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
377				     SAPCIC_POWER_3V);
378	}
379
380	/* enable PCMCIA control lines */
381	(so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 1);
382
383	/*
384	 * wait 100ms until power raise (Tpr) and 20ms to become
385	 * stable (Tsu(Vcc)).
386	 *
387	 * some machines require some more time to be settled
388	 * (300ms is added here).
389	 */
390	sapcic_delay(100 + 20 + 300, "pccen1");
391
392	/* honor nWAIT signal */
393	(so->pcictag->write)(so, SAPCIC_CONTROL_WAITENABLE, 1);
394	/* now make sure we have reset# active */
395	(so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 1);
396
397	/*
398	 * hold RESET at least 10us, this is a min allow for slop in
399	 * delay routine.
400	 */
401	delay(20);
402
403	/* clear the reset flag */
404	(so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 0);
405
406	/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
407	sapcic_delay(20, "pccen2");
408
409	/* wait for the chip to finish initializing */
410	sapcic_delay(10, "pccen3");
411	for (i = 100; i; i--) {
412		if ((so->pcictag->read)(so, SAPCIC_STATUS_READY))
413			break;
414		sapcic_delay(100, "pccen4");
415	}
416	DPRINTF(("sapcic_socket_enable: wait ready %d\n", 100 - i));
417
418	/* finally enable the interrupt */
419
420}
421
422static void
423sapcic_socket_disable(pcmcia_chipset_handle_t pch)
424{
425	struct sapcic_socket *so = pch;
426
427	/* XXX mask card interrupts */
428
429	/* power down the card */
430	(so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
431
432	/* float controller lines */
433	(so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 0);
434}
435
436static void
437sapcic_socket_settype(pcmcia_chipset_handle_t pch, int type)
438{
439
440	/* XXX nothing to do */
441}
442