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