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