ts102.c revision 1.5 1 /* $OpenBSD: ts102.c,v 1.14 2005/01/27 17:03:23 millert Exp $ */
2 /* $NetBSD: ts102.c,v 1.5 2005/11/16 04:25:28 macallan 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 struct proc *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_create_event_thread(void *);
160 static void tslot_event_thread(void *);
161 static int tslot_intr(void *);
162 static void tslot_intr_disestablish(pcmcia_chipset_handle_t, void *);
163 static void *tslot_intr_establish(pcmcia_chipset_handle_t,
164 struct pcmcia_function *, int, int (*)(void *), void *);
165
166 const char *tslot_intr_string(pcmcia_chipset_handle_t, void *);
167 static int tslot_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
168 bus_size_t, struct pcmcia_io_handle *);
169 static void tslot_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *);
170 static int tslot_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
171 struct pcmcia_io_handle *, int *);
172 static void tslot_io_unmap(pcmcia_chipset_handle_t, int);
173 static int tslot_match(struct device *, struct cfdata *, void *);
174 static int tslot_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
175 struct pcmcia_mem_handle *);
176 static void tslot_mem_free(pcmcia_chipset_handle_t, struct pcmcia_mem_handle *);
177 static int tslot_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
178 struct pcmcia_mem_handle *, bus_size_t *, int *);
179 static void tslot_mem_unmap(pcmcia_chipset_handle_t, int);
180 static int tslot_print(void *, const char *);
181 static void tslot_queue_event(struct tslot_softc *, int);
182 static void tslot_reset(struct tslot_data *, uint32_t);
183 static void tslot_slot_disable(pcmcia_chipset_handle_t);
184 static void tslot_slot_enable(pcmcia_chipset_handle_t);
185 static void tslot_slot_intr(struct tslot_data *, int);
186 static void tslot_slot_settype(pcmcia_chipset_handle_t, int);
187 static void tslot_update_lcd(struct tslot_softc *, int, int);
188 static void tslot_intr_dispatch(void *arg);
189
190 CFATTACH_DECL(tslot, sizeof(struct tslot_softc),
191 tslot_match, tslot_attach, NULL, NULL);
192
193 extern struct cfdriver tslot_cd;
194
195 /*
196 * PCMCIA chipset methods
197 */
198 struct pcmcia_chip_functions tslot_functions = {
199 tslot_mem_alloc,
200 tslot_mem_free,
201 tslot_mem_map,
202 tslot_mem_unmap,
203
204 tslot_io_alloc,
205 tslot_io_free,
206 tslot_io_map,
207 tslot_io_unmap,
208
209 tslot_intr_establish,
210 tslot_intr_disestablish,
211
212 tslot_slot_enable,
213 tslot_slot_disable,
214 tslot_slot_settype
215 };
216
217 static uint16_t ts102_read_2(bus_space_tag_t,
218 bus_space_handle_t,
219 bus_size_t);
220 static uint32_t ts102_read_4(bus_space_tag_t,
221 bus_space_handle_t,
222 bus_size_t);
223 static uint64_t ts102_read_8(bus_space_tag_t,
224 bus_space_handle_t,
225 bus_size_t);
226 static void ts102_write_2(bus_space_tag_t,
227 bus_space_handle_t,
228 bus_size_t,
229 uint16_t);
230 static void ts102_write_4(bus_space_tag_t,
231 bus_space_handle_t,
232 bus_size_t,
233 uint32_t);
234 static void ts102_write_8(bus_space_tag_t,
235 bus_space_handle_t,
236 bus_size_t,
237 uint64_t);
238
239 static uint16_t
240 ts102_read_2(bus_space_tag_t space, bus_space_handle_t handle,
241 bus_size_t offset)
242 {
243 return (le16toh(*(volatile uint16_t *)(handle +
244 offset)));
245 }
246
247 static uint32_t
248 ts102_read_4(bus_space_tag_t space, bus_space_handle_t handle,
249 bus_size_t offset)
250 {
251 return (le32toh(*(volatile uint32_t *)(handle +
252 offset)));
253 }
254
255 static uint64_t
256 ts102_read_8(bus_space_tag_t space, bus_space_handle_t handle,
257 bus_size_t offset)
258 {
259 return (le64toh(*(volatile uint64_t *)(handle +
260 offset)));
261 }
262
263 static void
264 ts102_write_2(bus_space_tag_t space, bus_space_handle_t handle,
265 bus_size_t offset, uint16_t value)
266 {
267 (*(volatile uint16_t *)(handle + offset)) =
268 htole16(value);
269 }
270
271 static void
272 ts102_write_4(bus_space_tag_t space, bus_space_handle_t handle,
273 bus_size_t offset, uint32_t value)
274 {
275 (*(volatile uint32_t *)(handle + offset)) =
276 htole32(value);
277 }
278
279 static void
280 ts102_write_8(bus_space_tag_t space, bus_space_handle_t handle,
281 bus_size_t offset, uint64_t value)
282 {
283 (*(volatile uint64_t *)(handle + offset)) =
284 htole64(value);
285 }
286
287
288 #define TSLOT_READ(slot, offset) \
289 *(volatile u_int16_t *)((slot)->td_regs + (offset))
290 #define TSLOT_WRITE(slot, offset, value) \
291 *(volatile u_int16_t *)((slot)->td_regs + (offset)) = (value)
292
293 /*
294 * Attachment and initialization
295 */
296
297 static int
298 tslot_match(struct device *parent, struct cfdata *vcf, void *aux)
299 {
300 struct sbus_attach_args *sa = aux;
301
302 return (strcmp("ts102", sa->sa_name) == 0);
303 }
304
305 static void
306 tslot_attach(struct device *parent, struct device *self, void *args)
307 {
308 struct sbus_attach_args *sa = args;
309 struct tslot_softc *sc = (struct tslot_softc *)self;
310 struct tslot_data *td;
311 volatile u_int8_t *regs;
312 int node, slot, rnum, base, size;
313 uint32_t ranges[30];
314 void *rptr = ranges;
315 bus_space_handle_t hrang = 0;
316 bus_space_tag_t tag;
317
318 node = sa->sa_node;
319 sc->sc_bustag=sa->sa_bustag;
320 if (sbus_bus_map(sa->sa_bustag,
321 sa->sa_slot,
322 sa->sa_offset,
323 sa->sa_size,
324 0, &sc->sc_regh) != 0) {
325 printf("%s: cannot map registers\n", self->dv_xname);
326 return;
327 }
328 regs = (uint8_t *)bus_space_vaddr(sa->sa_bustag, sc->sc_regh);
329
330 tag = bus_space_tag_alloc(sa->sa_bustag, sc);
331 if (tag == NULL) {
332 printf("%s: attach: out of memory\n", self->dv_xname);
333 return;
334 }
335 tag->sparc_read_2 = ts102_read_2;
336 tag->sparc_read_4 = ts102_read_4;
337 tag->sparc_read_8 = ts102_read_8;
338 tag->sparc_write_2 = ts102_write_2;
339 tag->sparc_write_4 = ts102_write_4;
340 tag->sparc_write_8 = ts102_write_8;
341
342 sbus_establish(&sc->sc_sd, self);
343
344 bus_intr_establish(sa->sa_bustag, sa->sa_intr[0].oi_pri,
345 IPL_NONE, tslot_intr, sc);
346
347 printf(": %d slots\n", TS102_NUM_SLOTS);
348
349 size = sizeof(ranges);
350 if (prom_getprop(node, "ranges", 4, &size, &rptr) != 0) {
351 printf("couldn't read ranges\n");
352 return;
353 }
354
355 /*
356 * Setup asynchronous event handler
357 */
358 sc->sc_events = 0;
359 kthread_create(tslot_create_event_thread, sc);
360
361 sc->sc_pct = (pcmcia_chipset_tag_t)&tslot_functions;
362 sc->sc_active = 0;
363
364 /*
365 * Setup slots
366 */
367 TSPRINTF("mapping resources...\n");
368 for (slot = 0; slot < TS102_NUM_SLOTS; slot++) {
369 td = &sc->sc_slot[slot];
370 TSPRINTF("slot %d, ",slot);
371 for (rnum = 0; rnum < TS102_RANGE_CNT; rnum++) {
372 base = (slot * TS102_RANGE_CNT + rnum) * 5;
373 TSPRINTF("%d: %08x %08x ",rnum,ranges[base + 3],
374 ranges[base + 4]);
375 if(sbus_bus_map(sc->sc_bustag,
376 sa->sa_slot,
377 ranges[base+3],
378 TS102_ARBITRARY_MAP_SIZE,
379 0, &hrang) != 0) {
380 printf("%s: cannot map registers\n",
381 self->dv_xname);
382 return;
383 }
384 TSPRINTF("%08x: %08x ",(uint32_t)ranges[base + 3],
385 (uint32_t)hrang);
386 td->td_space[rnum] = hrang;
387 }
388 td->td_parent = sc;
389 td->td_pcmciat = tag;
390 td->td_softint = NULL;
391 td->td_regs = regs + slot * (TS102_REG_CARD_B_INT -
392 TS102_REG_CARD_A_INT);
393 td->td_slot = slot;
394
395 TSPRINTF("resetting slot %d %d\n", slot, (int)td->td_regs);
396 tslot_reset(td, TS102_ARBITRARY_MAP_SIZE);
397 }
398 }
399
400 static void
401 tslot_reset(struct tslot_data *td, uint32_t iosize)
402 {
403 struct pcmciabus_attach_args paa;
404 int ctl, status;
405
406 paa.paa_busname = "pcmcia";
407 paa.pct = (pcmcia_chipset_tag_t)td->td_parent->sc_pct;
408 paa.pch = (pcmcia_chipset_handle_t)td;
409 paa.iobase = 0;
410 paa.iosize = iosize;
411
412 td->td_pcmcia = config_found(&td->td_parent->sc_dev, &paa, tslot_print);
413
414 if (td->td_pcmcia == NULL) {
415 /*
416 * If no pcmcia attachment, power down the slot.
417 */
418 tslot_slot_disable((pcmcia_chipset_handle_t)td);
419 return;
420 }
421
422 /*
423 * Initialize the slot
424 */
425
426 ctl = TSLOT_READ(td, TS102_REG_CARD_A_CTL);
427
428 /* force low addresses */
429 ctl &= ~(TS102_CARD_CTL_AA_MASK | TS102_CARD_CTL_IA_MASK);
430
431 /* Put SBus and PCMCIA in their respective endian mode */
432 ctl |= TS102_CARD_CTL_SBLE; /* this is not what it looks like! */
433 ctl &= ~TS102_CARD_CTL_PCMBE; /* default */
434
435 /* disable read ahead and address increment */
436 ctl &= ~TS102_CARD_CTL_RAHD;
437 ctl |= TS102_CARD_CTL_INCDIS;
438
439 /* power on */
440 ctl &= ~TS102_CARD_CTL_PWRD;
441 TSLOT_WRITE(td, TS102_REG_CARD_A_CTL, ctl);
442 TSPRINTF("ctl: %x\n", ctl);
443
444 /*
445 * Enable interrupt upon insertion/removal
446 */
447
448 TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
449 TS102_CARD_INT_MASK_CARDDETECT_STATUS);
450
451 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
452 if (status & TS102_CARD_STS_PRES) {
453 td->td_status = TS_CARD;
454 pcmcia_card_attach(td->td_pcmcia);
455 } else
456 td->td_status = 0;
457 }
458
459 /* XXX there ought to be a common function for this... */
460 static int
461 tslot_print(void *aux, const char *description)
462 {
463 struct pcmciabus_attach_args *paa = aux;
464 struct tslot_data *td = (struct tslot_data *)paa->pch;
465
466 printf(" socket %d", td->td_slot);
467 return (UNCONF);
468 }
469
470 /*
471 * PCMCIA Helpers
472 */
473
474 static int
475 tslot_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size,
476 bus_size_t align, struct pcmcia_io_handle *pih)
477 {
478 struct tslot_data *td = (struct tslot_data *)pch;
479
480 #ifdef TSLOT_DEBUG
481 printf("[io alloc %x]", (uint32_t)size);
482 #endif
483
484 pih->iot = td->td_pcmciat;
485 pih->ioh = td->td_space[TS102_RANGE_IO];
486 pih->addr = start;
487 pih->size = size;
488 pih->flags = 0;
489
490 return (0);
491 }
492
493 static void
494 tslot_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
495 {
496 #ifdef TSLOT_DEBUG
497 printf("[io free]");
498 #endif
499 }
500
501 static int
502 tslot_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
503 bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
504 {
505 struct tslot_data *td = (struct tslot_data *)pch;
506
507 #ifdef TSLOT_DEBUG
508 printf("[io map %x/%x", (uint32_t)offset, (uint32_t)size);
509 #endif
510
511 pih->iot = td->td_pcmciat;
512 if (bus_space_subregion(pih->iot, td->td_space[TS102_RANGE_IO],
513 offset, size, &pih->ioh) != 0)
514 printf("io_map failed, offset %x\n", (uint32_t)offset);
515 *windowp = 0; /* TS102_RANGE_IO */
516
517 #ifdef TSLOT_DEBUG
518 printf("->%x/%x]", (uint32_t)pih->ioh, (uint32_t)size);
519 {
520 int addr, line;
521 for( addr = offset; addr < (offset + size); addr += 16) {
522 printf("%04x:", addr);
523 for(line = addr; line < (addr + 16); line += 2) {
524 printf(" %04x", bus_space_read_2(pih->iot,
525 pih->ioh, line));
526 }
527 printf("\n");
528 }
529 }
530 #endif
531
532 return (0);
533 }
534
535 static void
536 tslot_io_unmap(pcmcia_chipset_handle_t pch, int win)
537 {
538 #ifdef TSLOT_DEBUG
539 struct tslot_data *td = (struct tslot_data *)pch;
540
541 printf("[io unmap]");
542 {
543 int addr, line, offset = 0, size = 0x80;
544 for (addr = offset; addr < (offset + size); addr += 16) {
545 printf("%04x:", addr);
546 for (line = addr; line < (addr + 16); line += 2){
547 printf(" %04x", bus_space_read_2(td->td_pcmciat,
548 td->td_space[2], line));
549 }
550 printf("\n");
551 }
552 }
553 #endif
554 }
555
556 static int
557 tslot_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
558 struct pcmcia_mem_handle *pmh)
559 {
560 struct tslot_data *td = (struct tslot_data *)pch;
561
562 #ifdef TSLOT_DEBUG
563 printf("[mem alloc %x]", (uint32_t)size);
564 #endif
565 pmh->memt = td->td_pcmciat;
566 pmh->size = size;
567 pmh->addr = 0;
568 pmh->mhandle = 0;
569 pmh->realsize = size; /* nothing so far! */
570
571 return (0);
572 }
573
574 static void
575 tslot_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
576 {
577 #ifdef TSLOT_DEBUG
578 printf("[mem free]");
579 #endif
580 }
581
582 static int
583 tslot_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr,
584 bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
585 int *windowp)
586 {
587 struct tslot_data *td = (struct tslot_data *)pch;
588 int slot;
589
590 slot = kind & PCMCIA_MEM_ATTR ? TS102_RANGE_ATTR : TS102_RANGE_COMMON;
591 #ifdef TSLOT_DEBUG
592 printf("[mem map %d %x/%x", slot, (uint32_t)addr, (uint32_t)size);
593 #endif
594
595 pmh->memt = td->td_parent->sc_bustag;
596 if (bus_space_subregion(pmh->memt, td->td_space[slot],
597 addr, size, &pmh->memh) != 0)
598 printf("mem_map failed, offset %x\n", (uint32_t)addr);
599 pmh->realsize = TS102_ARBITRARY_MAP_SIZE - addr;
600 pmh->size = size;
601 *offsetp = 0;
602 *windowp = 0;
603
604 #ifdef TSLOT_DEBUG
605 printf("->%x/%x]", (uint32_t)pmh->memh, (uint32_t)size);
606 #endif
607
608 return (0);
609 }
610
611 static void
612 tslot_mem_unmap(pcmcia_chipset_handle_t pch, int win)
613 {
614 #ifdef TSLOT_DEBUG
615 printf("[mem unmap %d]", win);
616 #endif
617 }
618
619 static void
620 tslot_slot_disable(pcmcia_chipset_handle_t pch)
621 {
622 struct tslot_data *td = (struct tslot_data *)pch;
623 #ifdef TSLOT_DEBUG
624 printf("%s: disable slot %d\n",
625 td->td_parent->sc_dev.dv_xname, td->td_slot);
626 #endif
627
628 /*
629 * Disable card access.
630 */
631 TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
632 TSLOT_READ(td, TS102_REG_CARD_A_STS) & ~TS102_CARD_STS_ACEN);
633
634 /*
635 * Disable interrupts, except for insertion.
636 */
637 TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
638 TS102_CARD_INT_MASK_CARDDETECT_STATUS);
639 }
640
641 static void
642 tslot_slot_enable(pcmcia_chipset_handle_t pch)
643 {
644 struct tslot_data *td = (struct tslot_data *)pch;
645 int status, intr, i;
646
647 #ifdef TSLOT_DEBUG
648 printf("%s: enable slot %d\n",
649 td->td_parent->sc_dev.dv_xname, td->td_slot);
650 #endif
651
652 /* Power down the socket to reset it */
653 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
654 TSPRINTF("status: %x\n", status);
655 TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN);
656
657 /*
658 * wait 300ms until power fails (Tpf). Then, wait 100ms since we
659 * are changing Vcc (Toff).
660 */
661 DELAY((300 + 100) * 1000);
662
663 /*
664 * Power on the card if not already done, and enable card access
665 */
666 status |= TS102_CARD_STS_ACEN;
667 status &= ~TS102_CARD_STS_VCCEN;
668 TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
669
670 /*
671 * wait 100ms until power raise (Tpr) and 20ms to become
672 * stable (Tsu(Vcc)).
673 */
674 DELAY((100 + 20) * 1000);
675
676 status &= ~TS102_CARD_STS_VPP1_MASK;
677 status |= TS102_CARD_STS_VPP1_VCC;
678 TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
679
680 /*
681 * hold RESET at least 20us.
682 */
683 intr = TSLOT_READ(td, TS102_REG_CARD_A_INT);
684 TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
685 DELAY(20);
686 TSLOT_WRITE(td, TS102_REG_CARD_A_INT, intr);
687
688 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
689 DELAY(20 * 1000);
690
691 /* We need level-triggered interrupts for PC Card hardware */
692 TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
693 TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_LVL);
694
695 /*
696 * Wait until the card is unbusy. If it is still busy after 3 seconds,
697 * give up. We could enable card interrupts and wait for the interrupt
698 * to happen when BUSY is released, but the interrupt could also be
699 * triggered by the card itself if it's an I/O card, so better poll
700 * here.
701 */
702 for (i = 30000; i != 0; i--) {
703 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
704 /* If the card has been removed, abort */
705 if ((status & TS102_CARD_STS_PRES) == 0) {
706 tslot_slot_disable(pch);
707 return;
708 }
709 if (status & TS102_CARD_STS_RDY)
710 break;
711 else
712 DELAY(100);
713 }
714
715 if (i == 0) {
716 printf("%s: slot %d still busy after 3 seconds, status 0x%x\n",
717 td->td_parent->sc_dev.dv_xname, td->td_slot,
718 TSLOT_READ(td, TS102_REG_CARD_A_STS));
719 return;
720 }
721 }
722
723 /*
724 * Event management
725 */
726 static void
727 tslot_create_event_thread(void *v)
728 {
729 struct tslot_softc *sc = v;
730 const char *name = sc->sc_dev.dv_xname;
731
732 TSPRINTF("starting event thread...\n");
733 if (kthread_create1(tslot_event_thread, sc, &sc->sc_thread, "%s",
734 name) != 0) {
735 panic("%s: unable to create event kthread", name);
736 }
737 }
738
739 static void
740 tslot_event_thread(void *v)
741 {
742 struct tslot_softc *sc = v;
743 struct tslot_data *td;
744 int s, status;
745 unsigned int socket;
746
747 #if NTCTRL > 0
748 int i;
749
750 /*
751 * First-time setup of our LCD symbol. When a card is present at boot
752 * time we won't detect a change here and therefore the LCD symbol won't
753 * light up.
754 */
755 for (i = 0; i < TS102_NUM_SLOTS; i++) {
756 td = &sc->sc_slot[i];
757 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
758 tslot_update_lcd(sc, i, status & TS102_CARD_STS_PRES);
759 }
760 #endif
761
762 for (;;) {
763 s = splhigh();
764
765 if ((socket = ffs(sc->sc_events)) == 0) {
766 splx(s);
767 tsleep(&sc->sc_events, PWAIT, "tslot_event", 0);
768 continue;
769 }
770 socket--;
771 sc->sc_events &= ~(1 << socket);
772 splx(s);
773
774 if (socket >= TS102_NUM_SLOTS) {
775 #ifdef DEBUG
776 printf("%s: invalid slot number %d\n",
777 sc->sc_dev.dv_xname, socket);
778 #endif
779 continue;
780 }
781
782 td = &sc->sc_slot[socket];
783 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
784
785 if (status & TS102_CARD_STS_PRES) {
786 /* Card insertion */
787 if ((td->td_status & TS_CARD) == 0) {
788 td->td_status |= TS_CARD;
789 tslot_update_lcd(sc, socket, 1);
790 pcmcia_card_attach(td->td_pcmcia);
791 }
792 } else {
793 /* Card removal */
794 if ((td->td_status & TS_CARD) != 0) {
795 tslot_update_lcd(sc, socket, 0);
796 td->td_status &= ~TS_CARD;
797 pcmcia_card_detach(td->td_pcmcia,
798 DETACH_FORCE);
799 }
800 }
801 }
802 }
803
804 /*
805 * Interrupt handling
806 */
807
808 static int
809 tslot_intr(void *v)
810 {
811 struct tslot_softc *sc = v;
812 struct tslot_data *td;
813 int intregs[TS102_NUM_SLOTS], *intreg;
814 int i, s, rc = 0;
815
816 s = splhigh();
817
818 /*
819 * Scan slots, and acknowledge the interrupt if necessary first
820 */
821 for (i = 0; i < TS102_NUM_SLOTS; i++) {
822 td = &sc->sc_slot[i];
823 intreg = &intregs[i];
824 *intreg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
825
826 /*
827 * Acknowledge all interrupt situations at once, even if they
828 * did not occur.
829 */
830 if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
831 TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
832 TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
833 TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0) {
834 rc = 1;
835 TSLOT_WRITE(td, TS102_REG_CARD_A_INT, *intreg |
836 TS102_CARD_INT_RQST_IRQ |
837 TS102_CARD_INT_RQST_WP_STATUS_CHANGED |
838 TS102_CARD_INT_RQST_BATTERY_STATUS_CHANGED |
839 TS102_CARD_INT_RQST_CARDDETECT_STATUS_CHANGED);
840 }
841 }
842
843 #ifdef TSLOT_DEBUG
844 printf("tslot_intr: %x %x\n", intregs[0], intregs[1]);
845 #endif
846
847 /*
848 * Invoke the interrupt handler for each slot
849 */
850 for (i = 0; i < TS102_NUM_SLOTS; i++) {
851 td = &sc->sc_slot[i];
852 intreg = &intregs[i];
853
854 if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
855 TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
856 TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
857 TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0)
858 tslot_slot_intr(td, *intreg);
859 }
860 splx(s);
861
862 return (rc);
863 }
864
865 static void
866 tslot_queue_event(struct tslot_softc *sc, int slot)
867 {
868 int s;
869
870 s = splhigh();
871 sc->sc_events |= (1 << slot);
872 splx(s);
873 wakeup(&sc->sc_events);
874 }
875
876 static void
877 tslot_slot_intr(struct tslot_data *td, int intreg)
878 {
879 struct tslot_softc *sc = td->td_parent;
880 int status, sockstat;
881 uint32_t ireg;
882
883 status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
884 #ifdef TSLOT_DEBUG
885 printf("%s: interrupt on socket %d ir %x sts %x\n",
886 sc->sc_dev.dv_xname, td->td_slot, intreg, status);
887 #endif
888
889 sockstat = td->td_status;
890
891 /*
892 * The TS102 queues interrupt request, and may trigger an interrupt
893 * for a condition the driver does not want to receive anymore (for
894 * example, after a card gets removed).
895 * Thus, only proceed if the driver is currently allowing a particular
896 * condition.
897 */
898
899 if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 &&
900 (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) {
901 tslot_queue_event(sc, td->td_slot);
902 #ifdef TSLOT_DEBUG
903 printf("%s: slot %d status changed from %d to %d\n",
904 sc->sc_dev.dv_xname, td->td_slot, sockstat, td->td_status);
905 #endif
906 /*
907 * Ignore extra interrupt bits, they are part of the change.
908 */
909 return;
910 }
911
912 if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 &&
913 (intreg & TS102_CARD_INT_MASK_IRQ) != 0) {
914 /* ignore interrupts if we have a pending state change */
915 if (sc->sc_events & (1 << td->td_slot))
916 {
917 TSPRINTF("ev: %d\n", sc->sc_events);
918 return;
919 }
920 if ((sockstat & TS_CARD) == 0) {
921 printf("%s: spurious interrupt on slot %d isr %x\n",
922 sc->sc_dev.dv_xname, td->td_slot, intreg);
923 return;
924 }
925
926 if (td->td_intr != NULL) {
927
928 if (td->td_softint != NULL)
929 softintr_schedule(td->td_softint);
930 /*
931 * Disable this sbus interrupt, until the soft-int
932 * handler had a chance to run
933 */
934 ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
935 TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg &
936 ~TS102_CARD_INT_MASK_IRQ);
937 }
938 }
939 }
940
941 static void
942 tslot_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
943 {
944 struct tslot_data *td = (struct tslot_data *)pch;
945
946 td->td_intr = NULL;
947 td->td_intrarg = NULL;
948 if (td->td_softint) {
949 softintr_disestablish(td->td_softint);
950 td->td_softint = NULL;
951 }
952 }
953
954 const char *
955 tslot_intr_string(pcmcia_chipset_handle_t pch, void *ih)
956 {
957 if (ih == NULL)
958 return ("couldn't establish interrupt");
959 else
960 return (""); /* nothing for now */
961 }
962
963 static void *
964 tslot_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
965 int ipl, int (*handler)(void *), void *arg)
966 {
967 struct tslot_data *td = (struct tslot_data *)pch;
968
969 td->td_intr = handler;
970 td->td_intrarg = arg;
971 td->td_softint = softintr_establish(ipl, tslot_intr_dispatch, td);
972
973 return (td);
974 }
975
976 /*
977 * Softinterrupt called to invoke the real driver interrupt handler.
978 */
979 static void
980 tslot_intr_dispatch(void *arg)
981 {
982 struct tslot_data *td = arg;
983 int s;
984 uint32_t ireg;
985
986 /* invoke driver handler */
987 td->td_intr(td->td_intrarg);
988
989 /* enable SBUS interrupts for pcmcia interrupts again */
990 s = splhigh();
991 ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
992 TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg | TS102_CARD_INT_MASK_IRQ);
993 splx(s);
994 }
995
996 static void
997 tslot_slot_settype(pcmcia_chipset_handle_t pch, int type)
998 {
999 struct tslot_data *td = (struct tslot_data *)pch;
1000 uint32_t reg;
1001
1002 /*
1003 * Enable the card interrupts if this is an I/O card.
1004 * Note that the TS102_CARD_STS_IO bit in the status register will
1005 * never get set, despite what the documentation says!
1006 */
1007 TSPRINTF("tslot_slot_settype(%d)\n",type);
1008 if (type == PCMCIA_IFTYPE_IO) {
1009 TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
1010 TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_IO);
1011 TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
1012 TS102_CARD_INT_MASK_CARDDETECT_STATUS |
1013 TS102_CARD_INT_MASK_IRQ);
1014 reg=TSLOT_READ(td, TS102_REG_CARD_A_STS);
1015 TSPRINTF("status: %x\n", reg);
1016 }
1017 }
1018
1019 static void
1020 tslot_update_lcd(struct tslot_softc *sc, int socket, int status)
1021 {
1022 #if NTCTRL > 0
1023 int was = (sc->sc_active != 0), is;
1024 int mask = 1 << socket;
1025
1026 if (status > 0) {
1027 sc->sc_active |= mask;
1028 } else {
1029 sc->sc_active &= (mask ^ 3);
1030 }
1031 is = (sc->sc_active != 0);
1032 if (was != is) {
1033 tctrl_set_lcd(is, 0x40);
1034 }
1035 #endif
1036 }
1037