1 /* $OpenBSD: ts102.c,v 1.14 2005/01/27 17:03:23 millert Exp $ */ 2 /* $NetBSD: ts102.c,v 1.7 2006/03/06 21:43:29 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 uint16_t *)((slot)->td_regs + (offset)) 290 #define TSLOT_WRITE(slot, offset, value) \ 291 *(volatile uint16_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 uint8_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", hz * 30); 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 tadpole_set_lcd(is, 0x40); 1034 } 1035 #endif 1036 } 1037