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