xref: /netbsd-src/sys/arch/sparc/dev/ts102.c (revision 4b293a84e10d4252c834c13e4cd7dd403a91ff9c)
1 /*	$OpenBSD: ts102.c,v 1.14 2005/01/27 17:03:23 millert Exp $	*/
2 /*	$NetBSD: ts102.c,v 1.10 2007/12/03 15:34:21 ad Exp $ */
3 /*
4  * Copyright (c) 2003, 2004, Miodrag Vallat.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Driver for the PCMCIA controller found in Tadpole SPARCbook 3 series
30  * notebooks.
31  *
32  * Based on the information provided in the SPARCbook 3 Technical Reference
33  * Manual (s3gxtrmb.pdf), chapter 7.  A few ramblings against this document
34  * and/or the chip itself are scattered across this file.
35  *
36  * Implementation notes:
37  *
38  * - The TS102 exports its PCMCIA windows as SBus memory ranges: 64MB for
39  *   the common memory window, and 16MB for the attribute and I/O windows.
40  *
41  *   Mapping the whole windows would consume 192MB of address space, which
42  *   is much more that what the iospace can offer.
43  *
44  *   A best-effort solution would be to map the windows on demand. However,
45  *   due to the wap mapdev() works, the va used for the mappings would be
46  *   lost after unmapping (although using an extent to register iospace memory
47  *   usage would fix this). So, instead, we will do a fixed mapping of a subset
48  *   of each window upon attach - this is similar to what the stp4020 driver
49  *   does.
50  *
51  * - IPL for the cards interrupt handles are not respected. See the stp4020
52  *   driver source for comments about this.
53  *
54  * Endianness farce:
55  *
56  * - The documentation pretends that the endianness settings only affect the
57  *   common memory window. Gee, thanks a lot. What about other windows, then?
58  *   As a result, this driver runs with endianness conversions turned off.
59  *
60  * - One of the little-endian SBus and big-endian PCMCIA flags has the reverse
61  *   meaning, actually. To achieve a ``no endianness conversion'' status,
62  *   one has to be set and the other unset. It does not matter which one,
63  *   though.
64  */
65 
66 #include <sys/cdefs.h>
67 
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/errno.h>
71 #include <sys/malloc.h>
72 #include <sys/extent.h>
73 #include <sys/proc.h>
74 #include <sys/kernel.h>
75 #include <sys/kthread.h>
76 #include <sys/device.h>
77 
78 #include <dev/pcmcia/pcmciareg.h>
79 #include <dev/pcmcia/pcmciavar.h>
80 #include <dev/pcmcia/pcmciachip.h>
81 
82 #include <machine/bus.h>
83 #include <machine/intr.h>
84 #include <machine/autoconf.h>
85 
86 #include <dev/sbus/sbusvar.h>
87 #include <sparc/dev/ts102reg.h>
88 
89 #include "tctrl.h"
90 
91 #if NTCTRL > 0
92 #include <machine/tctrl.h>
93 #include <sparc/dev/tctrlvar.h>
94 #endif
95 
96 #define	TS102_NUM_SLOTS		2
97 
98 /*
99  * Memory ranges
100  */
101 #define	TS102_RANGE_COMMON	0
102 #define	TS102_RANGE_ATTR	1
103 #define	TS102_RANGE_IO		2
104 
105 #define	TS102_RANGE_CNT		3
106 #define	TS102_NUM_RANGES	(TS102_RANGE_CNT * TS102_NUM_SLOTS)
107 
108 #define	TS102_ARBITRARY_MAP_SIZE	(1 * 1024 * 1024)
109 
110 struct	tslot_softc;
111 
112 #ifdef TSLOT_DEBUG
113 #define TSPRINTF	printf
114 #else
115 #define TSPRINTF	while (0) printf
116 #endif
117 
118 /*
119  * Per-slot data
120  */
121 struct	tslot_data {
122 	struct tslot_softc	*td_parent;
123 	struct device		*td_pcmcia;
124 
125 	volatile uint8_t	*td_regs;
126 	bus_addr_t		td_space[TS102_RANGE_CNT];
127 	bus_space_tag_t		td_pcmciat;	/* for accessing cards */
128 
129 	/* Interrupt handler */
130 	int			(*td_intr)(void *);
131 	void			*td_intrarg;
132 	void			*td_softint;
133 
134 	/* Socket status */
135 	int			td_slot;
136 	int			td_status;
137 #define	TS_CARD			0x0001
138 };
139 
140 struct	tslot_softc {
141 	struct device	sc_dev;
142 	struct sbusdev	sc_sd;
143 
144 	bus_space_tag_t	sc_bustag;		/* socket control io	*/
145 	bus_space_handle_t	sc_regh;	/*  space		*/
146 
147 	pcmcia_chipset_tag_t sc_pct;
148 
149 	lwp_t		*sc_thread;	/* event thread */
150 	uint32_t	sc_events;	/* sockets with pending events */
151 
152 	/* bits 0 and 1 are set according to card presence in slot 0 and 1 */
153 	uint32_t 	sc_active;
154 
155 	struct tslot_data sc_slot[TS102_NUM_SLOTS];
156 };
157 
158 static void tslot_attach(struct device *, struct device *, void *);
159 static void tslot_event_thread(void *);
160 static int  tslot_intr(void *);
161 static void tslot_intr_disestablish(pcmcia_chipset_handle_t, void *);
162 static void *tslot_intr_establish(pcmcia_chipset_handle_t,
163     struct pcmcia_function *, int, int (*)(void *), void *);
164 
165 const char  *tslot_intr_string(pcmcia_chipset_handle_t, void *);
166 static int  tslot_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
167     bus_size_t, struct pcmcia_io_handle *);
168 static void tslot_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *);
169 static int  tslot_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
170     struct pcmcia_io_handle *, int *);
171 static void tslot_io_unmap(pcmcia_chipset_handle_t, int);
172 static int  tslot_match(struct device *, struct cfdata *, void *);
173 static int  tslot_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
174     struct pcmcia_mem_handle *);
175 static void tslot_mem_free(pcmcia_chipset_handle_t, struct pcmcia_mem_handle *);
176 static int  tslot_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
177     struct pcmcia_mem_handle *, bus_size_t *, int *);
178 static void tslot_mem_unmap(pcmcia_chipset_handle_t, int);
179 static int  tslot_print(void *, const char *);
180 static void tslot_queue_event(struct tslot_softc *, int);
181 static void tslot_reset(struct tslot_data *, uint32_t);
182 static void tslot_slot_disable(pcmcia_chipset_handle_t);
183 static void tslot_slot_enable(pcmcia_chipset_handle_t);
184 static void tslot_slot_intr(struct tslot_data *, int);
185 static void tslot_slot_settype(pcmcia_chipset_handle_t, int);
186 static void tslot_update_lcd(struct tslot_softc *, int, int);
187 static void tslot_intr_dispatch(void *arg);
188 
189 CFATTACH_DECL(tslot, sizeof(struct tslot_softc),
190     tslot_match, tslot_attach, NULL, NULL);
191 
192 extern struct cfdriver tslot_cd;
193 
194 /*
195  * PCMCIA chipset methods
196  */
197 struct	pcmcia_chip_functions tslot_functions = {
198 	tslot_mem_alloc,
199 	tslot_mem_free,
200 	tslot_mem_map,
201 	tslot_mem_unmap,
202 
203 	tslot_io_alloc,
204 	tslot_io_free,
205 	tslot_io_map,
206 	tslot_io_unmap,
207 
208 	tslot_intr_establish,
209 	tslot_intr_disestablish,
210 
211 	tslot_slot_enable,
212 	tslot_slot_disable,
213 	tslot_slot_settype
214 };
215 
216 static	uint16_t ts102_read_2(bus_space_tag_t,
217 				 bus_space_handle_t,
218 				 bus_size_t);
219 static	uint32_t ts102_read_4(bus_space_tag_t,
220 				 bus_space_handle_t,
221 				 bus_size_t);
222 static	uint64_t ts102_read_8(bus_space_tag_t,
223 				 bus_space_handle_t,
224 				 bus_size_t);
225 static	void	ts102_write_2(bus_space_tag_t,
226 				bus_space_handle_t,
227 				bus_size_t,
228 				uint16_t);
229 static	void	ts102_write_4(bus_space_tag_t,
230 				bus_space_handle_t,
231 				bus_size_t,
232 				uint32_t);
233 static	void	ts102_write_8(bus_space_tag_t,
234 				bus_space_handle_t,
235 				bus_size_t,
236 				uint64_t);
237 
238 static uint16_t
239 ts102_read_2(bus_space_tag_t space, bus_space_handle_t handle,
240     bus_size_t offset)
241 {
242 	return (le16toh(*(volatile uint16_t *)(handle +
243 	    offset)));
244 }
245 
246 static uint32_t
247 ts102_read_4(bus_space_tag_t space, bus_space_handle_t handle,
248     bus_size_t offset)
249 {
250 	return (le32toh(*(volatile uint32_t *)(handle +
251 	    offset)));
252 }
253 
254 static uint64_t
255 ts102_read_8(bus_space_tag_t space, bus_space_handle_t handle,
256     bus_size_t offset)
257 {
258 	return (le64toh(*(volatile uint64_t *)(handle +
259 	    offset)));
260 }
261 
262 static void
263 ts102_write_2(bus_space_tag_t space, bus_space_handle_t handle,
264     bus_size_t offset, uint16_t value)
265 {
266 	(*(volatile uint16_t *)(handle + offset)) =
267 	    htole16(value);
268 }
269 
270 static void
271 ts102_write_4(bus_space_tag_t space, bus_space_handle_t handle,
272     bus_size_t offset, uint32_t value)
273 {
274 	(*(volatile uint32_t *)(handle + offset)) =
275 	    htole32(value);
276 }
277 
278 static void
279 ts102_write_8(bus_space_tag_t space, bus_space_handle_t handle,
280     bus_size_t offset, uint64_t value)
281 {
282 	(*(volatile uint64_t *)(handle + offset)) =
283 	    htole64(value);
284 }
285 
286 
287 #define	TSLOT_READ(slot, offset) \
288 	*(volatile uint16_t *)((slot)->td_regs + (offset))
289 #define	TSLOT_WRITE(slot, offset, value) \
290 	*(volatile uint16_t *)((slot)->td_regs + (offset)) = (value)
291 
292 /*
293  * Attachment and initialization
294  */
295 
296 static int
297 tslot_match(struct device *parent, struct cfdata *vcf, void *aux)
298 {
299 	struct sbus_attach_args *sa = aux;
300 
301 	return (strcmp("ts102", sa->sa_name) == 0);
302 }
303 
304 static void
305 tslot_attach(struct device *parent, struct device *self, void *args)
306 {
307 	struct sbus_attach_args *sa = args;
308 	struct tslot_softc *sc = (struct tslot_softc *)self;
309 	struct tslot_data *td;
310 	volatile uint8_t *regs;
311 	int node, slot, rnum, base, size;
312 	uint32_t ranges[30];
313 	void *rptr = ranges;
314 	bus_space_handle_t hrang = 0;
315 	bus_space_tag_t tag;
316 
317 	node = sa->sa_node;
318 	sc->sc_bustag=sa->sa_bustag;
319 	if (sbus_bus_map(sa->sa_bustag,
320 			 sa->sa_slot,
321 			 sa->sa_offset,
322 			 sa->sa_size,
323 			 0, &sc->sc_regh) != 0) {
324 		printf("%s: cannot map registers\n", self->dv_xname);
325 		return;
326 	}
327 	regs = (uint8_t *)bus_space_vaddr(sa->sa_bustag, sc->sc_regh);
328 
329 	tag = bus_space_tag_alloc(sa->sa_bustag, sc);
330 	if (tag == NULL) {
331 		printf("%s: attach: out of memory\n", self->dv_xname);
332 		return;
333 	}
334 	tag->sparc_read_2 = ts102_read_2;
335 	tag->sparc_read_4 = ts102_read_4;
336 	tag->sparc_read_8 = ts102_read_8;
337 	tag->sparc_write_2 = ts102_write_2;
338 	tag->sparc_write_4 = ts102_write_4;
339 	tag->sparc_write_8 = ts102_write_8;
340 
341 	sbus_establish(&sc->sc_sd, self);
342 
343 	bus_intr_establish(sa->sa_bustag, sa->sa_intr[0].oi_pri,
344 	    IPL_NONE, tslot_intr, sc);
345 
346 	printf(": %d slots\n", TS102_NUM_SLOTS);
347 
348 	size = sizeof(ranges);
349 	if (prom_getprop(node, "ranges", 4, &size, &rptr) != 0) {
350 		printf("couldn't read ranges\n");
351 		return;
352 	}
353 
354 	/*
355 	 * Setup asynchronous event handler
356 	 */
357 	sc->sc_events = 0;
358 
359 	TSPRINTF("starting event thread...\n");
360 	if (kthread_create(PRI_NONE, 0, NULL, tslot_event_thread, sc,
361 	    &sc->sc_thread, "%s", self->dv_xname) != 0) {
362 		panic("%s: unable to create event kthread",
363 		    self->dv_xname);
364 	}
365 
366 	sc->sc_pct = (pcmcia_chipset_tag_t)&tslot_functions;
367 	sc->sc_active = 0;
368 
369 	/*
370 	 * Setup slots
371 	 */
372 	TSPRINTF("mapping resources...\n");
373 	for (slot = 0; slot < TS102_NUM_SLOTS; slot++) {
374 		td = &sc->sc_slot[slot];
375 		TSPRINTF("slot %d, ",slot);
376 		for (rnum = 0; rnum < TS102_RANGE_CNT; rnum++) {
377 			base = (slot * TS102_RANGE_CNT + rnum) * 5;
378 			TSPRINTF("%d: %08x %08x ",rnum,ranges[base + 3],
379 			    ranges[base + 4]);
380 			if(sbus_bus_map(sc->sc_bustag,
381 					sa->sa_slot,
382 				 	ranges[base+3],
383 				 	TS102_ARBITRARY_MAP_SIZE,
384 					0, &hrang) != 0) {
385 				printf("%s: cannot map registers\n",
386 				    self->dv_xname);
387 				return;
388 			}
389 			TSPRINTF("%08x: %08x ",(uint32_t)ranges[base + 3],
390 			    (uint32_t)hrang);
391 			td->td_space[rnum] = hrang;
392 		}
393 		td->td_parent = sc;
394 		td->td_pcmciat = tag;
395 		td->td_softint = NULL;
396 		td->td_regs = regs + slot * (TS102_REG_CARD_B_INT -
397 		    TS102_REG_CARD_A_INT);
398 		td->td_slot = slot;
399 
400 		TSPRINTF("resetting slot %d %d\n", slot, (int)td->td_regs);
401 		tslot_reset(td, TS102_ARBITRARY_MAP_SIZE);
402 	}
403 }
404 
405 static void
406 tslot_reset(struct tslot_data *td, uint32_t iosize)
407 {
408 	struct pcmciabus_attach_args paa;
409 	int ctl, status;
410 
411 	paa.paa_busname = "pcmcia";
412 	paa.pct = (pcmcia_chipset_tag_t)td->td_parent->sc_pct;
413 	paa.pch = (pcmcia_chipset_handle_t)td;
414 	paa.iobase = 0;
415 	paa.iosize = iosize;
416 
417 	td->td_pcmcia = config_found(&td->td_parent->sc_dev, &paa, tslot_print);
418 
419 	if (td->td_pcmcia == NULL) {
420 		/*
421 		 * If no pcmcia attachment, power down the slot.
422 		 */
423 		tslot_slot_disable((pcmcia_chipset_handle_t)td);
424 		return;
425 	}
426 
427 	/*
428 	 * Initialize the slot
429 	 */
430 
431 	ctl = TSLOT_READ(td, TS102_REG_CARD_A_CTL);
432 
433 	/* force low addresses */
434 	ctl &= ~(TS102_CARD_CTL_AA_MASK | TS102_CARD_CTL_IA_MASK);
435 
436 	/* Put SBus and PCMCIA in their respective endian mode */
437 	ctl |= TS102_CARD_CTL_SBLE;	/* this is not what it looks like! */
438 	ctl &= ~TS102_CARD_CTL_PCMBE;	/* default */
439 
440 	/* disable read ahead and address increment */
441 	ctl &= ~TS102_CARD_CTL_RAHD;
442 	ctl |= TS102_CARD_CTL_INCDIS;
443 
444 	/* power on */
445 	ctl &= ~TS102_CARD_CTL_PWRD;
446 	TSLOT_WRITE(td, TS102_REG_CARD_A_CTL, ctl);
447 	TSPRINTF("ctl: %x\n", ctl);
448 
449 	/*
450 	 * Enable interrupt upon insertion/removal
451 	 */
452 
453 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
454 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
455 
456 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
457 	if (status & TS102_CARD_STS_PRES) {
458 		td->td_status = TS_CARD;
459 		pcmcia_card_attach(td->td_pcmcia);
460 	} else
461 		td->td_status = 0;
462 }
463 
464 /* XXX there ought to be a common function for this... */
465 static int
466 tslot_print(void *aux, const char *description)
467 {
468 	struct pcmciabus_attach_args *paa = aux;
469 	struct tslot_data *td = (struct tslot_data *)paa->pch;
470 
471 	printf(" socket %d", td->td_slot);
472 	return (UNCONF);
473 }
474 
475 /*
476  * PCMCIA Helpers
477  */
478 
479 static int
480 tslot_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size,
481     bus_size_t align, struct pcmcia_io_handle *pih)
482 {
483 	struct tslot_data *td = (struct tslot_data *)pch;
484 
485 #ifdef TSLOT_DEBUG
486 	printf("[io alloc %x]", (uint32_t)size);
487 #endif
488 
489 	pih->iot = td->td_pcmciat;
490 	pih->ioh = td->td_space[TS102_RANGE_IO];
491 	pih->addr = start;
492 	pih->size = size;
493 	pih->flags = 0;
494 
495 	return (0);
496 }
497 
498 static void
499 tslot_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
500 {
501 #ifdef TSLOT_DEBUG
502 	printf("[io free]");
503 #endif
504 }
505 
506 static int
507 tslot_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
508     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
509 {
510 	struct tslot_data *td = (struct tslot_data *)pch;
511 
512 #ifdef TSLOT_DEBUG
513 	printf("[io map %x/%x", (uint32_t)offset, (uint32_t)size);
514 #endif
515 
516 	pih->iot = td->td_pcmciat;
517 	if (bus_space_subregion(pih->iot, td->td_space[TS102_RANGE_IO],
518 	    offset, size, &pih->ioh) != 0)
519 		printf("io_map failed, offset %x\n", (uint32_t)offset);
520 	*windowp = 0; /* TS102_RANGE_IO */
521 
522 #ifdef TSLOT_DEBUG
523 	printf("->%x/%x]", (uint32_t)pih->ioh, (uint32_t)size);
524 	{
525 		int addr, line;
526 		for( addr = offset; addr < (offset + size); addr += 16) {
527 			printf("%04x:", addr);
528 			for(line = addr; line < (addr + 16); line += 2) {
529 				printf(" %04x", bus_space_read_2(pih->iot,
530 				    pih->ioh, line));
531 			}
532 			printf("\n");
533 		}
534 	}
535 #endif
536 
537 	return (0);
538 }
539 
540 static void
541 tslot_io_unmap(pcmcia_chipset_handle_t pch, int win)
542 {
543 #ifdef TSLOT_DEBUG
544 	struct tslot_data *td = (struct tslot_data *)pch;
545 
546 	printf("[io unmap]");
547 	{
548 		int addr, line, offset = 0, size = 0x80;
549 		for (addr = offset; addr < (offset + size); addr += 16) {
550 			printf("%04x:", addr);
551 			for (line = addr; line < (addr + 16); line += 2){
552 				printf(" %04x", bus_space_read_2(td->td_pcmciat,
553 				    td->td_space[2], line));
554 			}
555 			printf("\n");
556 		}
557 	}
558 #endif
559 }
560 
561 static int
562 tslot_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
563     struct pcmcia_mem_handle *pmh)
564 {
565 	struct tslot_data *td = (struct tslot_data *)pch;
566 
567 #ifdef TSLOT_DEBUG
568 	printf("[mem alloc %x]", (uint32_t)size);
569 #endif
570 	pmh->memt = td->td_pcmciat;
571 	pmh->size = size;
572 	pmh->addr = 0;
573 	pmh->mhandle = 0;
574 	pmh->realsize = size;	/* nothing so far! */
575 
576 	return (0);
577 }
578 
579 static void
580 tslot_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
581 {
582 #ifdef TSLOT_DEBUG
583 	printf("[mem free]");
584 #endif
585 }
586 
587 static int
588 tslot_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr,
589     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
590     int *windowp)
591 {
592 	struct tslot_data *td = (struct tslot_data *)pch;
593 	int slot;
594 
595 	slot = kind & PCMCIA_MEM_ATTR ? TS102_RANGE_ATTR : TS102_RANGE_COMMON;
596 #ifdef TSLOT_DEBUG
597 	printf("[mem map %d %x/%x", slot, (uint32_t)addr, (uint32_t)size);
598 #endif
599 
600 	pmh->memt = td->td_parent->sc_bustag;
601 	if (bus_space_subregion(pmh->memt, td->td_space[slot],
602 	    addr, size, &pmh->memh) != 0)
603 		printf("mem_map failed, offset %x\n", (uint32_t)addr);
604 	pmh->realsize = TS102_ARBITRARY_MAP_SIZE - addr;
605 	pmh->size = size;
606 	*offsetp = 0;
607 	*windowp = 0;
608 
609 #ifdef TSLOT_DEBUG
610 	printf("->%x/%x]", (uint32_t)pmh->memh, (uint32_t)size);
611 #endif
612 
613 	return (0);
614 }
615 
616 static void
617 tslot_mem_unmap(pcmcia_chipset_handle_t pch, int win)
618 {
619 #ifdef TSLOT_DEBUG
620 	printf("[mem unmap %d]", win);
621 #endif
622 }
623 
624 static void
625 tslot_slot_disable(pcmcia_chipset_handle_t pch)
626 {
627 	struct tslot_data *td = (struct tslot_data *)pch;
628 #ifdef TSLOT_DEBUG
629 	printf("%s: disable slot %d\n",
630 	    td->td_parent->sc_dev.dv_xname, td->td_slot);
631 #endif
632 
633 	/*
634 	 * Disable card access.
635 	 */
636 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
637 	    TSLOT_READ(td, TS102_REG_CARD_A_STS) & ~TS102_CARD_STS_ACEN);
638 
639 	/*
640 	 * Disable interrupts, except for insertion.
641 	 */
642 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
643 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
644 }
645 
646 static void
647 tslot_slot_enable(pcmcia_chipset_handle_t pch)
648 {
649 	struct tslot_data *td = (struct tslot_data *)pch;
650 	int status, intr, i;
651 
652 #ifdef TSLOT_DEBUG
653 	printf("%s: enable slot %d\n",
654 	    td->td_parent->sc_dev.dv_xname, td->td_slot);
655 #endif
656 
657 	/* Power down the socket to reset it */
658 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
659 	TSPRINTF("status: %x\n", status);
660 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN);
661 
662 	/*
663 	 * wait 300ms until power fails (Tpf).  Then, wait 100ms since we
664 	 * are changing Vcc (Toff).
665 	 */
666 	DELAY((300 + 100) * 1000);
667 
668 	/*
669 	 * Power on the card if not already done, and enable card access
670 	 */
671 	status |= TS102_CARD_STS_ACEN;
672 	status &= ~TS102_CARD_STS_VCCEN;
673 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
674 
675 	/*
676 	 * wait 100ms until power raise (Tpr) and 20ms to become
677 	 * stable (Tsu(Vcc)).
678 	 */
679 	DELAY((100 + 20) * 1000);
680 
681 	status &= ~TS102_CARD_STS_VPP1_MASK;
682 	status |= TS102_CARD_STS_VPP1_VCC;
683 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
684 
685 	/*
686 	 * hold RESET at least 20us.
687 	 */
688 	intr = TSLOT_READ(td, TS102_REG_CARD_A_INT);
689 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
690 	DELAY(20);
691 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, intr);
692 
693 	/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
694 	DELAY(20 * 1000);
695 
696 	/* We need level-triggered interrupts for PC Card hardware */
697 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
698 		TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_LVL);
699 
700 	/*
701 	 * Wait until the card is unbusy. If it is still busy after 3 seconds,
702 	 * give up. We could enable card interrupts and wait for the interrupt
703 	 * to happen when BUSY is released, but the interrupt could also be
704 	 * triggered by the card itself if it's an I/O card, so better poll
705 	 * here.
706 	 */
707 	for (i = 30000; i != 0; i--) {
708 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
709 		/* If the card has been removed, abort */
710 		if ((status & TS102_CARD_STS_PRES) == 0) {
711 			tslot_slot_disable(pch);
712 			return;
713 		}
714 		if (status & TS102_CARD_STS_RDY)
715 			break;
716 		else
717 			DELAY(100);
718 	}
719 
720 	if (i == 0) {
721 		printf("%s: slot %d still busy after 3 seconds, status 0x%x\n",
722 		    td->td_parent->sc_dev.dv_xname, td->td_slot,
723 		    TSLOT_READ(td, TS102_REG_CARD_A_STS));
724 		return;
725 	}
726 }
727 static void
728 tslot_event_thread(void *v)
729 {
730 	struct tslot_softc *sc = v;
731 	struct tslot_data *td;
732 	int s, status;
733 	unsigned int socket;
734 
735 #if NTCTRL > 0
736 	int i;
737 
738 	/*
739 	 * First-time setup of our LCD symbol. When a card is present at boot
740 	 * time we won't detect a change here and therefore the LCD symbol won't
741 	 * light up.
742 	 */
743 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
744 		td = &sc->sc_slot[i];
745 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
746 		tslot_update_lcd(sc, i, status & TS102_CARD_STS_PRES);
747 	}
748 #endif
749 
750 	for (;;) {
751 		s = splhigh();
752 
753 		if ((socket = ffs(sc->sc_events)) == 0) {
754 			splx(s);
755 			tsleep(&sc->sc_events, PWAIT, "tslot_event", hz * 30);
756 			continue;
757 		}
758 		socket--;
759 		sc->sc_events &= ~(1 << socket);
760 		splx(s);
761 
762 		if (socket >= TS102_NUM_SLOTS) {
763 #ifdef DEBUG
764 			printf("%s: invalid slot number %d\n",
765 			    sc->sc_dev.dv_xname, socket);
766 #endif
767 			continue;
768 		}
769 
770 		td = &sc->sc_slot[socket];
771 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
772 
773 		if (status & TS102_CARD_STS_PRES) {
774 			/* Card insertion */
775 			if ((td->td_status & TS_CARD) == 0) {
776 				td->td_status |= TS_CARD;
777 				tslot_update_lcd(sc, socket, 1);
778 				pcmcia_card_attach(td->td_pcmcia);
779 			}
780 		} else {
781 			/* Card removal */
782 			if ((td->td_status & TS_CARD) != 0) {
783 				tslot_update_lcd(sc, socket, 0);
784 				td->td_status &= ~TS_CARD;
785 				pcmcia_card_detach(td->td_pcmcia,
786 				    DETACH_FORCE);
787 			}
788 		}
789 	}
790 }
791 
792 /*
793  * Interrupt handling
794  */
795 
796 static int
797 tslot_intr(void *v)
798 {
799 	struct tslot_softc *sc = v;
800 	struct tslot_data *td;
801 	int intregs[TS102_NUM_SLOTS], *intreg;
802 	int i, s, rc = 0;
803 
804 	s = splhigh();
805 
806 	/*
807 	 * Scan slots, and acknowledge the interrupt if necessary first
808 	 */
809 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
810 		td = &sc->sc_slot[i];
811 		intreg = &intregs[i];
812 		*intreg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
813 
814 		/*
815 		 * Acknowledge all interrupt situations at once, even if they
816 		 * did not occur.
817 		 */
818 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
819 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
820 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
821 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0) {
822 			rc = 1;
823 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, *intreg |
824 			    TS102_CARD_INT_RQST_IRQ |
825 			    TS102_CARD_INT_RQST_WP_STATUS_CHANGED |
826 			    TS102_CARD_INT_RQST_BATTERY_STATUS_CHANGED |
827 			    TS102_CARD_INT_RQST_CARDDETECT_STATUS_CHANGED);
828 		}
829 	}
830 
831 #ifdef TSLOT_DEBUG
832 	printf("tslot_intr: %x %x\n", intregs[0], intregs[1]);
833 #endif
834 
835 	/*
836 	 * Invoke the interrupt handler for each slot
837 	 */
838 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
839 		td = &sc->sc_slot[i];
840 		intreg = &intregs[i];
841 
842 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
843 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
844 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
845 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0)
846 			tslot_slot_intr(td, *intreg);
847 	}
848 	splx(s);
849 
850 	return (rc);
851 }
852 
853 static void
854 tslot_queue_event(struct tslot_softc *sc, int slot)
855 {
856 	int s;
857 
858 	s = splhigh();
859 	sc->sc_events |= (1 << slot);
860 	splx(s);
861 	wakeup(&sc->sc_events);
862 }
863 
864 static void
865 tslot_slot_intr(struct tslot_data *td, int intreg)
866 {
867 	struct tslot_softc *sc = td->td_parent;
868 	int status, sockstat;
869 	uint32_t ireg;
870 
871 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
872 #ifdef TSLOT_DEBUG
873 	printf("%s: interrupt on socket %d ir %x sts %x\n",
874 	    sc->sc_dev.dv_xname, td->td_slot, intreg, status);
875 #endif
876 
877 	sockstat = td->td_status;
878 
879 	/*
880 	 * The TS102 queues interrupt request, and may trigger an interrupt
881 	 * for a condition the driver does not want to receive anymore (for
882 	 * example, after a card gets removed).
883 	 * Thus, only proceed if the driver is currently allowing a particular
884 	 * condition.
885 	 */
886 
887 	if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 &&
888 	    (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) {
889 		tslot_queue_event(sc, td->td_slot);
890 #ifdef TSLOT_DEBUG
891 		printf("%s: slot %d status changed from %d to %d\n",
892 		    sc->sc_dev.dv_xname, td->td_slot, sockstat, td->td_status);
893 #endif
894 		/*
895 		 * Ignore extra interrupt bits, they are part of the change.
896 		 */
897 		return;
898 	}
899 
900 	if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 &&
901 	    (intreg & TS102_CARD_INT_MASK_IRQ) != 0) {
902 		/* ignore interrupts if we have a pending state change */
903 		if (sc->sc_events & (1 << td->td_slot))
904 		{
905 			TSPRINTF("ev: %d\n", sc->sc_events);
906 			return;
907 		}
908 		if ((sockstat & TS_CARD) == 0) {
909 			printf("%s: spurious interrupt on slot %d isr %x\n",
910 			    sc->sc_dev.dv_xname, td->td_slot, intreg);
911 			return;
912 		}
913 
914 		if (td->td_intr != NULL) {
915 
916 			if (td->td_softint != NULL)
917 				sparc_softintr_schedule(td->td_softint);
918 			/*
919 			 * Disable this sbus interrupt, until the soft-int
920 			 * handler had a chance to run
921 			 */
922 			ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
923 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg &
924 			    ~TS102_CARD_INT_MASK_IRQ);
925 		}
926 	}
927 }
928 
929 static void
930 tslot_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
931 {
932 	struct tslot_data *td = (struct tslot_data *)pch;
933 
934 	td->td_intr = NULL;
935 	td->td_intrarg = NULL;
936 	if (td->td_softint) {
937 		sparc_softintr_disestablish(td->td_softint);
938 		td->td_softint = NULL;
939 	}
940 }
941 
942 const char *
943 tslot_intr_string(pcmcia_chipset_handle_t pch, void *ih)
944 {
945 	if (ih == NULL)
946 		return ("couldn't establish interrupt");
947 	else
948 		return ("");	/* nothing for now */
949 }
950 
951 static void *
952 tslot_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
953     int ipl, int (*handler)(void *), void *arg)
954 {
955 	struct tslot_data *td = (struct tslot_data *)pch;
956 
957 	td->td_intr = handler;
958 	td->td_intrarg = arg;
959 	td->td_softint = sparc_softintr_establish(ipl, tslot_intr_dispatch, td);
960 
961 	return (td);
962 }
963 
964 /*
965  * Softinterrupt called to invoke the real driver interrupt handler.
966  */
967 static void
968 tslot_intr_dispatch(void *arg)
969 {
970 	struct tslot_data *td = arg;
971 	int s;
972 	uint32_t ireg;
973 
974 	/* invoke driver handler */
975 	td->td_intr(td->td_intrarg);
976 
977 	/* enable SBUS interrupts for pcmcia interrupts again */
978 	s = splhigh();
979 	ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
980 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg | TS102_CARD_INT_MASK_IRQ);
981 	splx(s);
982 }
983 
984 static void
985 tslot_slot_settype(pcmcia_chipset_handle_t pch, int type)
986 {
987 	struct tslot_data *td = (struct tslot_data *)pch;
988 	uint32_t reg;
989 
990 	/*
991 	 * Enable the card interrupts if this is an I/O card.
992 	 * Note that the TS102_CARD_STS_IO bit in the status register will
993 	 * never get set, despite what the documentation says!
994 	 */
995 	TSPRINTF("tslot_slot_settype(%d)\n",type);
996 	if (type == PCMCIA_IFTYPE_IO) {
997 		TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
998 		    TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_IO);
999 		TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
1000 		    TS102_CARD_INT_MASK_CARDDETECT_STATUS |
1001 		    TS102_CARD_INT_MASK_IRQ);
1002 		reg=TSLOT_READ(td, TS102_REG_CARD_A_STS);
1003 		TSPRINTF("status: %x\n", reg);
1004 	}
1005 }
1006 
1007 static void
1008 tslot_update_lcd(struct tslot_softc *sc, int socket, int status)
1009 {
1010 #if NTCTRL > 0
1011 	int was = (sc->sc_active != 0), is;
1012 	int mask = 1 << socket;
1013 
1014 	if (status > 0) {
1015 		sc->sc_active |= mask;
1016 	} else {
1017 		sc->sc_active &= (mask ^ 3);
1018 	}
1019 	is = (sc->sc_active != 0);
1020 	if (was != is) {
1021 		tadpole_set_lcd(is, 0x40);
1022 	}
1023 #endif
1024 }
1025