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