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