1 /* $NetBSD: stp4020.c,v 1.28 2002/10/10 22:23:16 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * STP4020: SBus/PCMCIA bridge supporting two Type-3 PCMCIA cards. 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: stp4020.c,v 1.28 2002/10/10 22:23:16 martin Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/errno.h> 49 #include <sys/malloc.h> 50 #include <sys/extent.h> 51 #include <sys/proc.h> 52 #include <sys/kernel.h> 53 #include <sys/kthread.h> 54 #include <sys/device.h> 55 56 #include <dev/pcmcia/pcmciareg.h> 57 #include <dev/pcmcia/pcmciavar.h> 58 #include <dev/pcmcia/pcmciachip.h> 59 60 #include <machine/bus.h> 61 #include <machine/intr.h> 62 63 #include <dev/sbus/sbusvar.h> 64 #include <dev/sbus/stp4020reg.h> 65 66 #define STP4020_DEBUG 1 /* XXX-temp */ 67 68 /* 69 * We use the three available windows per socket in a simple, fixed 70 * arrangement. Each window maps (at full 1 MB size) one of the pcmcia 71 * spaces into sbus space. 72 */ 73 #define STP_WIN_ATTR 0 /* index of the attribute memory space window */ 74 #define STP_WIN_MEM 1 /* index of the common memory space window */ 75 #define STP_WIN_IO 2 /* index of the io space window */ 76 77 78 #if defined(STP4020_DEBUG) 79 int stp4020_debug = 0; 80 #define DPRINTF(x) do { if (stp4020_debug) printf x; } while(0) 81 #else 82 #define DPRINTF(x) 83 #endif 84 85 /* 86 * Event queue; events detected in an interrupt context go here 87 * awaiting attention from our event handling thread. 88 */ 89 struct stp4020_event { 90 SIMPLEQ_ENTRY(stp4020_event) se_q; 91 int se_type; 92 int se_sock; 93 }; 94 /* Defined event types */ 95 #define STP4020_EVENT_INSERTION 0 96 #define STP4020_EVENT_REMOVAL 1 97 98 /* 99 * Per socket data. 100 */ 101 struct stp4020_socket { 102 struct stp4020_softc *sc; /* Back link */ 103 int flags; 104 #define STP4020_SOCKET_BUSY 0x0001 105 #define STP4020_SOCKET_SHUTDOWN 0x0002 106 int sock; /* Socket number (0 or 1) */ 107 int sbus_intno; /* Do we use first (0) or second (1) 108 interrupt? */ 109 bus_space_tag_t tag; /* socket control space */ 110 bus_space_handle_t regs; /* */ 111 struct device *pcmcia; /* Associated PCMCIA device */ 112 int (*intrhandler) /* Card driver interrupt handler */ 113 __P((void *)); 114 void *intrarg; /* Card interrupt handler argument */ 115 int ipl; /* Interrupt level suggested by card */ 116 struct { 117 bus_space_handle_t winaddr;/* this window's address */ 118 } windows[STP4020_NWIN]; 119 120 }; 121 122 struct stp4020_softc { 123 struct device sc_dev; /* Base device */ 124 struct sbusdev sc_sd; /* SBus device */ 125 bus_space_tag_t sc_bustag; 126 bus_dma_tag_t sc_dmatag; 127 pcmcia_chipset_tag_t sc_pct; /* Chipset methods */ 128 129 struct proc *event_thread; /* event handling thread */ 130 SIMPLEQ_HEAD(, stp4020_event) events; /* Pending events for thread */ 131 132 struct stp4020_socket sc_socks[STP4020_NSOCK]; 133 }; 134 135 136 static int stp4020print __P((void *, const char *)); 137 static int stp4020match __P((struct device *, struct cfdata *, void *)); 138 static void stp4020attach __P((struct device *, struct device *, void *)); 139 static int stp4020_intr __P((void *)); 140 static void stp4020_map_window(struct stp4020_socket *h, int win, int speed); 141 static void stp4020_calc_speed(int bus_speed, int ns, int *length, int *delay); 142 143 CFATTACH_DECL(nell, sizeof(struct stp4020_softc), 144 stp4020match, stp4020attach, NULL, NULL); 145 146 #ifdef STP4020_DEBUG 147 static void stp4020_dump_regs __P((struct stp4020_socket *)); 148 #endif 149 150 static int stp4020_rd_sockctl __P((struct stp4020_socket *, int)); 151 static void stp4020_wr_sockctl __P((struct stp4020_socket *, int, int)); 152 static int stp4020_rd_winctl __P((struct stp4020_socket *, int, int)); 153 static void stp4020_wr_winctl __P((struct stp4020_socket *, int, int, int)); 154 155 void stp4020_delay __P((unsigned int)); 156 void stp4020_attach_socket __P((struct stp4020_socket *, int)); 157 void stp4020_create_event_thread __P((void *)); 158 void stp4020_event_thread __P((void *)); 159 void stp4020_queue_event __P((struct stp4020_softc *, int, int)); 160 161 int stp4020_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t, 162 struct pcmcia_mem_handle *)); 163 void stp4020_chip_mem_free __P((pcmcia_chipset_handle_t, 164 struct pcmcia_mem_handle *)); 165 int stp4020_chip_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, 166 bus_size_t, struct pcmcia_mem_handle *, 167 bus_size_t *, int *)); 168 void stp4020_chip_mem_unmap __P((pcmcia_chipset_handle_t, int)); 169 170 int stp4020_chip_io_alloc __P((pcmcia_chipset_handle_t, 171 bus_addr_t, bus_size_t, bus_size_t, 172 struct pcmcia_io_handle *)); 173 void stp4020_chip_io_free __P((pcmcia_chipset_handle_t, 174 struct pcmcia_io_handle *)); 175 int stp4020_chip_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, 176 bus_size_t, struct pcmcia_io_handle *, int *)); 177 void stp4020_chip_io_unmap __P((pcmcia_chipset_handle_t, int)); 178 179 void stp4020_chip_socket_enable __P((pcmcia_chipset_handle_t)); 180 void stp4020_chip_socket_disable __P((pcmcia_chipset_handle_t)); 181 void *stp4020_chip_intr_establish __P((pcmcia_chipset_handle_t, 182 struct pcmcia_function *, int, 183 int (*) __P((void *)), void *)); 184 void stp4020_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *)); 185 186 /* Our PCMCIA chipset methods */ 187 static struct pcmcia_chip_functions stp4020_functions = { 188 stp4020_chip_mem_alloc, 189 stp4020_chip_mem_free, 190 stp4020_chip_mem_map, 191 stp4020_chip_mem_unmap, 192 193 stp4020_chip_io_alloc, 194 stp4020_chip_io_free, 195 stp4020_chip_io_map, 196 stp4020_chip_io_unmap, 197 198 stp4020_chip_intr_establish, 199 stp4020_chip_intr_disestablish, 200 201 stp4020_chip_socket_enable, 202 stp4020_chip_socket_disable 203 }; 204 205 206 static __inline__ int 207 stp4020_rd_sockctl(h, idx) 208 struct stp4020_socket *h; 209 int idx; 210 { 211 int o = ((STP4020_SOCKREGS_SIZE * (h->sock)) + idx); 212 return (bus_space_read_2(h->tag, h->regs, o)); 213 } 214 215 static __inline__ void 216 stp4020_wr_sockctl(h, idx, v) 217 struct stp4020_socket *h; 218 int idx; 219 int v; 220 { 221 int o = (STP4020_SOCKREGS_SIZE * (h->sock)) + idx; 222 bus_space_write_2(h->tag, h->regs, o, v); 223 } 224 225 static __inline__ int 226 stp4020_rd_winctl(h, win, idx) 227 struct stp4020_socket *h; 228 int win; 229 int idx; 230 { 231 int o = (STP4020_SOCKREGS_SIZE * (h->sock)) + 232 (STP4020_WINREGS_SIZE * win) + idx; 233 return (bus_space_read_2(h->tag, h->regs, o)); 234 } 235 236 static __inline__ void 237 stp4020_wr_winctl(h, win, idx, v) 238 struct stp4020_socket *h; 239 int win; 240 int idx; 241 int v; 242 { 243 int o = (STP4020_SOCKREGS_SIZE * (h->sock)) + 244 (STP4020_WINREGS_SIZE * win) + idx; 245 246 bus_space_write_2(h->tag, h->regs, o, v); 247 } 248 249 250 int 251 stp4020print(aux, busname) 252 void *aux; 253 const char *busname; 254 { 255 struct pcmciabus_attach_args *paa = aux; 256 struct stp4020_socket *h = paa->pch; 257 258 printf(" socket %d", h->sock); 259 return (UNCONF); 260 } 261 262 int 263 stp4020match(parent, cf, aux) 264 struct device *parent; 265 struct cfdata *cf; 266 void *aux; 267 { 268 struct sbus_attach_args *sa = aux; 269 270 return (strcmp("SUNW,pcmcia", sa->sa_name) == 0); 271 } 272 273 /* 274 * Attach all the sub-devices we can find 275 */ 276 void 277 stp4020attach(parent, self, aux) 278 struct device *parent, *self; 279 void *aux; 280 { 281 struct sbus_attach_args *sa = aux; 282 struct stp4020_softc *sc = (void *)self; 283 int node, rev; 284 int i, sbus_intno; 285 bus_space_handle_t bh; 286 287 node = sa->sa_node; 288 289 /* lsb of our config flags decides which interrupt we use */ 290 sbus_intno = sc->sc_dev.dv_cfdata->cf_flags & 1; 291 292 /* Transfer bus tags */ 293 sc->sc_bustag = sa->sa_bustag; 294 sc->sc_dmatag = sa->sa_dmatag; 295 296 /* Set up per-socket static initialization */ 297 sc->sc_socks[0].sc = sc->sc_socks[1].sc = sc; 298 sc->sc_socks[0].tag = sc->sc_socks[1].tag = sa->sa_bustag; 299 sc->sc_socks[0].sbus_intno = 300 sc->sc_socks[1].sbus_intno = sbus_intno; 301 302 if (sa->sa_nreg < 8) { 303 printf("%s: only %d register sets\n", 304 self->dv_xname, sa->sa_nreg); 305 return; 306 } 307 308 if (sa->sa_nintr != 2) { 309 printf("%s: expect 2 interrupt Sbus levels; got %d\n", 310 self->dv_xname, sa->sa_nintr); 311 return; 312 } 313 314 #define STP4020_BANK_PROM 0 315 #define STP4020_BANK_CTRL 4 316 for (i = 0; i < 8; i++) { 317 318 /* 319 * STP4020 Register address map: 320 * bank 0: Forth PROM 321 * banks 1-3: socket 0, windows 0-2 322 * bank 4: control registers 323 * banks 5-7: socket 1, windows 0-2 324 */ 325 326 if (i == STP4020_BANK_PROM) 327 /* Skip the PROM */ 328 continue; 329 330 if (sbus_bus_map(sa->sa_bustag, 331 sa->sa_reg[i].oa_space, 332 sa->sa_reg[i].oa_base, 333 sa->sa_reg[i].oa_size, 334 0, &bh) != 0) { 335 printf("%s: attach: cannot map registers\n", 336 self->dv_xname); 337 return; 338 } 339 340 if (i == STP4020_BANK_CTRL) { 341 /* 342 * Copy tag and handle to both socket structures 343 * for easy access in control/status IO functions. 344 */ 345 sc->sc_socks[0].regs = sc->sc_socks[1].regs = bh; 346 } else if (i < STP4020_BANK_CTRL) { 347 /* banks 1-3 */ 348 sc->sc_socks[0].windows[i-1].winaddr = bh; 349 } else { 350 /* banks 5-7 */ 351 sc->sc_socks[1].windows[i-5].winaddr = bh; 352 } 353 } 354 355 sbus_establish(&sc->sc_sd, &sc->sc_dev); 356 357 /* We only use one interrupt level. */ 358 if (sa->sa_nintr > sbus_intno) { 359 bus_intr_establish(sa->sa_bustag, 360 sa->sa_intr[sbus_intno].oi_pri, 361 IPL_NONE, 0, stp4020_intr, sc); 362 } 363 364 rev = stp4020_rd_sockctl(&sc->sc_socks[0], STP4020_ISR1_IDX) & 365 STP4020_ISR1_REV_M; 366 printf(": rev %x\n", rev); 367 368 sc->sc_pct = (pcmcia_chipset_tag_t)&stp4020_functions; 369 370 /* 371 * Arrange that a kernel thread be created to handle 372 * insert/removal events. 373 */ 374 SIMPLEQ_INIT(&sc->events); 375 kthread_create(stp4020_create_event_thread, sc); 376 377 for (i = 0; i < STP4020_NSOCK; i++) { 378 struct stp4020_socket *h = &sc->sc_socks[i]; 379 h->sock = i; 380 h->sc = sc; 381 #ifdef STP4020_DEBUG 382 if (stp4020_debug) 383 stp4020_dump_regs(h); 384 #endif 385 stp4020_attach_socket(h, sa->sa_frequency); 386 } 387 } 388 389 void 390 stp4020_attach_socket(h, speed) 391 struct stp4020_socket *h; 392 int speed; 393 { 394 struct pcmciabus_attach_args paa; 395 int v; 396 397 /* Map all three windows */ 398 stp4020_map_window(h, STP_WIN_ATTR, speed); 399 stp4020_map_window(h, STP_WIN_MEM, speed); 400 stp4020_map_window(h, STP_WIN_IO, speed); 401 402 /* Configure one pcmcia device per socket */ 403 paa.paa_busname = "pcmcia"; 404 paa.pct = (pcmcia_chipset_tag_t)h->sc->sc_pct; 405 paa.pch = (pcmcia_chipset_handle_t)h; 406 paa.iobase = 0; 407 paa.iosize = STP4020_WINDOW_SIZE; 408 409 h->pcmcia = config_found(&h->sc->sc_dev, &paa, stp4020print); 410 411 if (h->pcmcia == NULL) 412 return; 413 414 /* 415 * There's actually a pcmcia bus attached; initialize the slot. 416 */ 417 418 /* 419 * Clear things up before we enable status change interrupts. 420 * This seems to not be fully initialized by the PROM. 421 */ 422 stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0); 423 stp4020_wr_sockctl(h, STP4020_ICR0_IDX, 0); 424 stp4020_wr_sockctl(h, STP4020_ISR1_IDX, 0x3fff); 425 stp4020_wr_sockctl(h, STP4020_ISR0_IDX, 0x3fff); 426 427 /* 428 * Enable socket status change interrupts. 429 * We only use one common interrupt for status change 430 * and IO, to avoid locking issues. 431 */ 432 v = STP4020_ICR0_ALL_STATUS_IE 433 | (h->sbus_intno ? STP4020_ICR0_SCILVL_SB1 434 : STP4020_ICR0_SCILVL_SB0); 435 stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v); 436 437 /* Get live status bits from ISR0 */ 438 v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX); 439 if ((v & (STP4020_ISR0_CD1ST|STP4020_ISR0_CD2ST)) == 0) 440 return; 441 442 pcmcia_card_attach(h->pcmcia); 443 h->flags |= STP4020_SOCKET_BUSY; 444 } 445 446 447 /* 448 * Deferred thread creation callback. 449 */ 450 void 451 stp4020_create_event_thread(arg) 452 void *arg; 453 { 454 struct stp4020_softc *sc = arg; 455 const char *name = sc->sc_dev.dv_xname; 456 457 if (kthread_create1(stp4020_event_thread, sc, &sc->event_thread, 458 "%s", name)) { 459 panic("%s: unable to create event thread", name); 460 } 461 } 462 463 /* 464 * The actual event handling thread. 465 */ 466 void 467 stp4020_event_thread(arg) 468 void *arg; 469 { 470 struct stp4020_softc *sc = arg; 471 struct stp4020_event *e; 472 int s; 473 474 while (1) { 475 struct stp4020_socket *h; 476 int n; 477 478 s = splhigh(); 479 if ((e = SIMPLEQ_FIRST(&sc->events)) == NULL) { 480 splx(s); 481 (void)tsleep(&sc->events, PWAIT, "pcicev", 0); 482 continue; 483 } 484 SIMPLEQ_REMOVE_HEAD(&sc->events, se_q); 485 splx(s); 486 487 n = e->se_sock; 488 if (n < 0 || n >= STP4020_NSOCK) 489 panic("stp4020_event_thread: wayward socket number %d", 490 n); 491 492 h = &sc->sc_socks[n]; 493 switch (e->se_type) { 494 case STP4020_EVENT_INSERTION: 495 pcmcia_card_attach(h->pcmcia); 496 break; 497 case STP4020_EVENT_REMOVAL: 498 pcmcia_card_detach(h->pcmcia, DETACH_FORCE); 499 break; 500 default: 501 panic("stp4020_event_thread: unknown event type %d", 502 e->se_type); 503 } 504 free(e, M_TEMP); 505 } 506 } 507 508 void 509 stp4020_queue_event(sc, sock, event) 510 struct stp4020_softc *sc; 511 int sock, event; 512 { 513 struct stp4020_event *e; 514 int s; 515 516 e = malloc(sizeof(*e), M_TEMP, M_NOWAIT); 517 if (e == NULL) 518 panic("stp4020_queue_event: can't allocate event"); 519 520 e->se_type = event; 521 e->se_sock = sock; 522 s = splhigh(); 523 SIMPLEQ_INSERT_TAIL(&sc->events, e, se_q); 524 splx(s); 525 wakeup(&sc->events); 526 } 527 528 int 529 stp4020_intr(arg) 530 void *arg; 531 { 532 struct stp4020_softc *sc = arg; 533 int i, r = 0, cd_change = 0; 534 535 /* 536 * Check each socket for pending requests. 537 */ 538 for (i = 0 ; i < STP4020_NSOCK; i++) { 539 struct stp4020_socket *h; 540 int v; 541 542 h = &sc->sc_socks[i]; 543 v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX); 544 545 /* Ack all interrupts at once */ 546 stp4020_wr_sockctl(h, STP4020_ISR0_IDX, STP4020_ISR0_ALL_STATUS_IRQ); 547 548 #ifdef STP4020_DEBUG 549 if (stp4020_debug != 0) { 550 char bits[64]; 551 bitmask_snprintf(v, STP4020_ISR0_IOBITS, 552 bits, sizeof(bits)); 553 printf("stp4020_statintr: ISR0=%s\n", bits); 554 } 555 #endif 556 557 if ((v & STP4020_ISR0_CDCHG) != 0) { 558 /* 559 * Card status change detect 560 */ 561 cd_change = 1; 562 r = 1; 563 if ((v & (STP4020_ISR0_CD1ST|STP4020_ISR0_CD2ST)) == (STP4020_ISR0_CD1ST|STP4020_ISR0_CD2ST)){ 564 if ((h->flags & STP4020_SOCKET_BUSY) == 0) { 565 stp4020_queue_event(sc, i, 566 STP4020_EVENT_INSERTION); 567 h->flags |= STP4020_SOCKET_BUSY; 568 } 569 } 570 if ((v & (STP4020_ISR0_CD1ST|STP4020_ISR0_CD2ST)) == 0){ 571 if ((h->flags & STP4020_SOCKET_BUSY) != 0) { 572 stp4020_queue_event(sc, i, 573 STP4020_EVENT_REMOVAL); 574 h->flags &= ~STP4020_SOCKET_BUSY; 575 } 576 } 577 } 578 579 if ((v & STP4020_ISR0_IOINT) != 0) { 580 /* we can not deny this is ours, no matter what the 581 card driver says. */ 582 r = 1; 583 584 /* ack interrupt */ 585 stp4020_wr_sockctl(h, STP4020_ISR0_IDX, v); 586 587 /* It's a card interrupt */ 588 if ((h->flags & STP4020_SOCKET_BUSY) == 0) { 589 printf("stp4020[%d]: spurious interrupt?\n", 590 h->sock); 591 continue; 592 } 593 /* Call card handler, if any */ 594 if (h->intrhandler != NULL) { 595 /* 596 * Called without handling of it's requested 597 * protection level (h->ipl), since we have 598 * no general queuing mechanism available 599 * right now and we know for sure we are 600 * running at a higher protection level 601 * right now. 602 */ 603 (*h->intrhandler)(h->intrarg); 604 } 605 } 606 607 /* informational messages */ 608 if ((v & STP4020_ISR0_BVD1CHG) != 0) { 609 /* ignore if this is caused by insert or removal */ 610 if (!cd_change) 611 printf("stp4020[%d]: Battery change 1\n", h->sock); 612 r = 1; 613 } 614 615 if ((v & STP4020_ISR0_BVD2CHG) != 0) { 616 /* ignore if this is caused by insert or removal */ 617 if (!cd_change) 618 printf("stp4020[%d]: Battery change 2\n", h->sock); 619 r = 1; 620 } 621 622 if ((v & STP4020_ISR0_RDYCHG) != 0) { 623 DPRINTF(("stp4020[%d]: Ready/Busy change\n", h->sock)); 624 r = 1; 625 } 626 627 if ((v & STP4020_ISR0_WPCHG) != 0) { 628 DPRINTF(("stp4020[%d]: Write protect change\n", h->sock)); 629 r = 1; 630 } 631 632 if ((v & STP4020_ISR0_PCTO) != 0) { 633 DPRINTF(("stp4020[%d]: Card access timeout\n", h->sock)); 634 r = 1; 635 } 636 637 } 638 639 return (r); 640 } 641 642 /* 643 * The function gets the sbus speed and a access time and calculates 644 * values for the CMDLNG and CMDDLAY registers. 645 */ 646 static void 647 stp4020_calc_speed(int bus_speed, int ns, int *length, int *delay) 648 { 649 int result; 650 651 if (ns < STP4020_MEM_SPEED_MIN) 652 ns = STP4020_MEM_SPEED_MIN; 653 else if (ns > STP4020_MEM_SPEED_MAX) 654 ns = STP4020_MEM_SPEED_MAX; 655 result = ns*(bus_speed/1000); 656 if (result % 1000000) 657 result = result/1000000 + 1; 658 else 659 result /= 1000000; 660 *length = result; 661 662 /* the sbus frequency range is limited, so we can keep this simple */ 663 *delay = ns <= STP4020_MEM_SPEED_MIN? 1 : 2; 664 } 665 666 static void 667 stp4020_map_window(struct stp4020_socket *h, int win, int speed) 668 { 669 int v, length, delay; 670 671 /* 672 * According to the PC Card standard 300ns access timing should be 673 * used for attribute memory access. Our pcmcia framework does not 674 * seem to propagate timing information, so we use that 675 * everywhere. 676 */ 677 stp4020_calc_speed(speed, (win==STP_WIN_ATTR)? 300 : 100, &length, &delay); 678 679 /* 680 * Fill in the Address Space Select and Base Address 681 * fields of this windows control register 0. 682 */ 683 v = ((delay << STP4020_WCR0_CMDDLY_S)&STP4020_WCR0_CMDDLY_M) 684 | ((length << STP4020_WCR0_CMDLNG_S)&STP4020_WCR0_CMDLNG_M); 685 switch (win) { 686 case STP_WIN_ATTR: 687 v |= STP4020_WCR0_ASPSEL_AM; 688 break; 689 case STP_WIN_MEM: 690 v |= STP4020_WCR0_ASPSEL_CM; 691 break; 692 case STP_WIN_IO: 693 v |= STP4020_WCR0_ASPSEL_IO; 694 break; 695 } 696 v |= (STP4020_ADDR2PAGE(0) & STP4020_WCR0_BASE_M); 697 stp4020_wr_winctl(h, win, STP4020_WCR0_IDX, v); 698 stp4020_wr_winctl(h, win, STP4020_WCR1_IDX, 1<<STP4020_WCR1_WAITREQ_S); 699 } 700 701 int 702 stp4020_chip_mem_alloc(pch, size, pcmhp) 703 pcmcia_chipset_handle_t pch; 704 bus_size_t size; 705 struct pcmcia_mem_handle *pcmhp; 706 { 707 struct stp4020_socket *h = (struct stp4020_socket *)pch; 708 709 /* we can not do much here, defere work to _mem_map */ 710 pcmhp->memt = h->tag; 711 pcmhp->size = size; 712 pcmhp->addr = 0; 713 pcmhp->mhandle = 0; 714 pcmhp->realsize = size; 715 716 return (0); 717 } 718 719 void 720 stp4020_chip_mem_free(pch, pcmhp) 721 pcmcia_chipset_handle_t pch; 722 struct pcmcia_mem_handle *pcmhp; 723 { 724 } 725 726 int 727 stp4020_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp) 728 pcmcia_chipset_handle_t pch; 729 int kind; 730 bus_addr_t card_addr; 731 bus_size_t size; 732 struct pcmcia_mem_handle *pcmhp; 733 bus_size_t *offsetp; 734 int *windowp; 735 { 736 struct stp4020_socket *h = (struct stp4020_socket *)pch; 737 int win = (kind&PCMCIA_MEM_ATTR)? STP_WIN_ATTR : STP_WIN_MEM; 738 739 pcmhp->memt = h->tag; 740 bus_space_subregion(h->tag, h->windows[win].winaddr, card_addr, size, &pcmhp->memh); 741 pcmhp->size = size; 742 pcmhp->realsize = STP4020_WINDOW_SIZE - card_addr; 743 *offsetp = 0; 744 *windowp = 0; 745 746 return (0); 747 } 748 749 void 750 stp4020_chip_mem_unmap(pch, win) 751 pcmcia_chipset_handle_t pch; 752 int win; 753 { 754 } 755 756 int 757 stp4020_chip_io_alloc(pch, start, size, align, pcihp) 758 pcmcia_chipset_handle_t pch; 759 bus_addr_t start; 760 bus_size_t size; 761 bus_size_t align; 762 struct pcmcia_io_handle *pcihp; 763 { 764 struct stp4020_socket *h = (struct stp4020_socket *)pch; 765 766 pcihp->iot = h->tag; 767 pcihp->ioh = h->windows[STP_WIN_IO].winaddr; 768 return 0; 769 } 770 771 void 772 stp4020_chip_io_free(pch, pcihp) 773 pcmcia_chipset_handle_t pch; 774 struct pcmcia_io_handle *pcihp; 775 { 776 } 777 778 int 779 stp4020_chip_io_map(pch, width, offset, size, pcihp, windowp) 780 pcmcia_chipset_handle_t pch; 781 int width; 782 bus_addr_t offset; 783 bus_size_t size; 784 struct pcmcia_io_handle *pcihp; 785 int *windowp; 786 { 787 struct stp4020_socket *h = (struct stp4020_socket *)pch; 788 789 pcihp->iot = h->tag; 790 bus_space_subregion(h->tag, h->windows[STP_WIN_IO].winaddr, offset, size, &pcihp->ioh); 791 *windowp = 0; 792 return 0; 793 } 794 795 void 796 stp4020_chip_io_unmap(pch, win) 797 pcmcia_chipset_handle_t pch; 798 int win; 799 { 800 } 801 802 void 803 stp4020_chip_socket_enable(pch) 804 pcmcia_chipset_handle_t pch; 805 { 806 struct stp4020_socket *h = (struct stp4020_socket *)pch; 807 int i, v; 808 809 /* this bit is mostly stolen from pcic_attach_card */ 810 811 /* Power down the socket to reset it, clear the card reset pin */ 812 stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0); 813 814 /* 815 * wait 300ms until power fails (Tpf). Then, wait 100ms since 816 * we are changing Vcc (Toff). 817 */ 818 stp4020_delay((300 + 100) * 1000); 819 820 /* Power up the socket */ 821 v = STP4020_ICR1_MSTPWR; 822 stp4020_wr_sockctl(h, STP4020_ICR1_IDX, v); 823 824 /* 825 * wait 100ms until power raise (Tpr) and 20ms to become 826 * stable (Tsu(Vcc)). 827 */ 828 stp4020_delay((100 + 20) * 1000); 829 830 v |= STP4020_ICR1_PCIFOE|STP4020_ICR1_VPP1_VCC; 831 stp4020_wr_sockctl(h, STP4020_ICR1_IDX, v); 832 833 /* 834 * hold RESET at least 10us. 835 */ 836 delay(10); 837 838 /* Clear reset flag */ 839 v = stp4020_rd_sockctl(h, STP4020_ICR0_IDX); 840 v &= ~STP4020_ICR0_RESET; 841 stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v); 842 843 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ 844 stp4020_delay(20000); 845 846 /* Wait for the chip to finish initializing (5 seconds max) */ 847 for (i = 10000; i > 0; i--) { 848 v = stp4020_rd_sockctl(h, STP4020_ISR0_IDX); 849 if ((v & STP4020_ISR0_RDYST) != 0) 850 break; 851 delay(500); 852 } 853 if (i <= 0) { 854 char bits[64]; 855 bitmask_snprintf(stp4020_rd_sockctl(h, STP4020_ISR0_IDX), 856 STP4020_ISR0_IOBITS, bits, sizeof(bits)); 857 printf("stp4020_chip_socket_enable: not ready: status %s\n", 858 bits); 859 return; 860 } 861 862 v = stp4020_rd_sockctl(h, STP4020_ICR0_IDX); 863 864 /* 865 * Check the card type. 866 * Enable socket I/O interrupts for IO cards. 867 * We use level SB_INT[0] for I/O interrupts. 868 */ 869 if (pcmcia_card_gettype(h->pcmcia) == PCMCIA_IFTYPE_IO) { 870 v &= ~(STP4020_ICR0_IOILVL|STP4020_ICR0_IFTYPE); 871 v |= STP4020_ICR0_IFTYPE_IO|STP4020_ICR0_IOIE 872 |STP4020_ICR0_SPKREN; 873 v |= h->sbus_intno ? STP4020_ICR0_IOILVL_SB1 874 : STP4020_ICR0_IOILVL_SB0; 875 DPRINTF(("%s: configuring card for IO useage\n", h->sc->sc_dev.dv_xname)); 876 } else { 877 v &= ~(STP4020_ICR0_IOILVL|STP4020_ICR0_IFTYPE 878 |STP4020_ICR0_SPKREN); 879 v |= STP4020_ICR0_IFTYPE_MEM; 880 DPRINTF(("%s: configuring card for MEM ONLY useage\n", h->sc->sc_dev.dv_xname)); 881 } 882 stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v); 883 } 884 885 void 886 stp4020_chip_socket_disable(pch) 887 pcmcia_chipset_handle_t pch; 888 { 889 struct stp4020_socket *h = (struct stp4020_socket *)pch; 890 int v; 891 892 /* 893 * Disable socket I/O interrupts. 894 */ 895 v = stp4020_rd_sockctl(h, STP4020_ICR0_IDX); 896 v &= ~(STP4020_ICR0_IOIE | STP4020_ICR0_IOILVL); 897 stp4020_wr_sockctl(h, STP4020_ICR0_IDX, v); 898 899 /* Power down the socket */ 900 stp4020_wr_sockctl(h, STP4020_ICR1_IDX, 0); 901 902 /* 903 * wait 300ms until power fails (Tpf). 904 */ 905 stp4020_delay(300 * 1000); 906 } 907 908 void * 909 stp4020_chip_intr_establish(pch, pf, ipl, handler, arg) 910 pcmcia_chipset_handle_t pch; 911 struct pcmcia_function *pf; 912 int ipl; 913 int (*handler) __P((void *)); 914 void *arg; 915 { 916 struct stp4020_socket *h = (struct stp4020_socket *)pch; 917 918 h->intrhandler = handler; 919 h->intrarg = arg; 920 h->ipl = ipl; 921 return h; 922 } 923 924 void 925 stp4020_chip_intr_disestablish(pch, ih) 926 pcmcia_chipset_handle_t pch; 927 void *ih; 928 { 929 struct stp4020_socket *h = (struct stp4020_socket *)pch; 930 931 h->intrhandler = NULL; 932 h->intrarg = NULL; 933 } 934 935 /* 936 * Delay and possibly yield CPU. 937 * XXX - assumes a context 938 */ 939 void 940 stp4020_delay(ms) 941 unsigned int ms; 942 { 943 unsigned int ticks; 944 945 /* Convert to ticks */ 946 ticks = (ms * hz ) / 1000000; 947 948 if (cold || ticks == 0) { 949 delay(ms); 950 return; 951 } 952 953 #ifdef DIAGNOSTIC 954 if (ticks > 60*hz) 955 panic("stp4020: preposterous delay: %u", ticks); 956 #endif 957 tsleep(&ticks, 0, "stp4020_delay", ticks); 958 } 959 960 #ifdef STP4020_DEBUG 961 void 962 stp4020_dump_regs(h) 963 struct stp4020_socket *h; 964 { 965 char bits[64]; 966 /* 967 * Dump control and status registers. 968 */ 969 printf("socket[%d] registers:\n", h->sock); 970 bitmask_snprintf(stp4020_rd_sockctl(h, STP4020_ICR0_IDX), 971 STP4020_ICR0_BITS, bits, sizeof(bits)); 972 printf("\tICR0=%s\n", bits); 973 974 bitmask_snprintf(stp4020_rd_sockctl(h, STP4020_ICR1_IDX), 975 STP4020_ICR1_BITS, bits, sizeof(bits)); 976 printf("\tICR1=%s\n", bits); 977 978 bitmask_snprintf(stp4020_rd_sockctl(h, STP4020_ISR0_IDX), 979 STP4020_ISR0_IOBITS, bits, sizeof(bits)); 980 printf("\tISR0=%s\n", bits); 981 982 bitmask_snprintf(stp4020_rd_sockctl(h, STP4020_ISR1_IDX), 983 STP4020_ISR1_BITS, bits, sizeof(bits)); 984 printf("\tISR1=%s\n", bits); 985 } 986 #endif /* STP4020_DEBUG */ 987