diff options
| author | Warner Losh <imp@FreeBSD.org> | 2015-01-14 05:41:33 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2015-01-14 05:41:33 +0000 |
| commit | 8b91d5b0086f455a70b1afe8122462766f382cab (patch) | |
| tree | 03e8b75d5622afe91bdb056f1cb7eeafb54a1f89 /sys/dev/pccbb | |
| parent | 8bf007e1e6a9d5b82ff18016bf9ca15e5f64671b (diff) | |
Notes
Diffstat (limited to 'sys/dev/pccbb')
| -rw-r--r-- | sys/dev/pccbb/pccbb.c | 108 | ||||
| -rw-r--r-- | sys/dev/pccbb/pccbb_isa.c | 18 | ||||
| -rw-r--r-- | sys/dev/pccbb/pccbb_pci.c | 84 | ||||
| -rw-r--r-- | sys/dev/pccbb/pccbbvar.h | 2 |
4 files changed, 112 insertions, 100 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index 08ff42772ee34..77a9725026724 100644 --- a/sys/dev/pccbb/pccbb.c +++ b/sys/dev/pccbb/pccbb.c @@ -477,7 +477,7 @@ cbb_event_thread(void *arg) */ mtx_lock(&Giant); status = cbb_get(sc, CBB_SOCKET_STATE); - DPRINTF(("Status is 0x%x\n", status)); + DEVPRINTF((sc->dev, "Status is %#x\n", status)); if (!CBB_CARD_PRESENT(status)) { not_a_card = 0; /* We know card type */ cbb_removal(sc); @@ -800,13 +800,14 @@ cbb_power(device_t brdev, int volts) if (on) { mtx_lock(&sc->mtx); cnt = sc->powerintr; + /* * We have a shortish timeout of 500ms here. Some bridges do - * not generate a POWER_CYCLE event for 16-bit cards. In - * those cases, we have to cope the best we can, and having - * only a short delay is better than the alternatives. Others - * raise the power cycle a smidge before it is really ready. - * We deal with those below. + * not generate a POWER_CYCLE event for 16-bit cards. In those + * cases, we have to cope the best we can, and having only a + * short delay is better than the alternatives. Others raise + * the power cycle a smidge before it is really ready. We deal + * with those below. */ sane = 10; while (!(cbb_get(sc, CBB_SOCKET_STATE) & CBB_STATE_POWER_CYCLE) && @@ -816,19 +817,18 @@ cbb_power(device_t brdev, int volts) /* * Relax for 100ms. Some bridges appear to assert this signal - * right away, but before the card has stabilized. Other - * cards need need more time to cope up reliabily. - * Experiments with troublesome setups show this to be a - * "cheap" way to enhance reliabilty. We need not do this for - * "off" since we don't touch the card after we turn it off. + * right away, but before the card has stabilized. Other cards + * need need more time to cope up reliabily. Experiments with + * troublesome setups show this to be a "cheap" way to enhance + * reliabilty. */ pause("cbbPwr", min(hz / 10, 1)); /* - * The TOPIC95B requires a little bit extra time to get its - * act together, so delay for an additional 100ms. Also as - * documented below, it doesn't seem to set the POWER_CYCLE - * bit, so don't whine if it never came on. + * The TOPIC95B requires a little bit extra time to get its act + * together, so delay for an additional 100ms. Also as + * documented below, it doesn't seem to set the POWER_CYCLE bit, + * so don't whine if it never came on. */ if (sc->chipset == CB_TOPIC95) pause("cbb95B", hz / 10); @@ -838,26 +838,27 @@ cbb_power(device_t brdev, int volts) /* * After the power is good, we can turn off the power interrupt. - * However, the PC Card standard says that we must delay turning the - * CD bit back on for a bit to allow for bouncyness on power down - * (recall that we don't wait above for a power down, since we don't - * get an interrupt for that). We're called either from the suspend - * code in which case we don't want to turn card change on again, or - * we're called from the card insertion code, in which case the cbb - * thread will turn it on for us before it waits to be woken by a - * change event. + * However, the PC Card standard says that we must delay turning the CD + * bit back on for a bit to allow for bouncyness on power down. We just + * pause a little below to cover that. Most bridges don't seem to need + * this delay. * - * NB: Topic95B doesn't set the power cycle bit. we assume that - * both it and the TOPIC95 behave the same. + * NB: Topic95B doesn't set the power cycle bit. We assume that + * both it and the TOPIC95 behave the same, though despite efforts + * to find one, the author never could locate a laptop with a TOPIC95 + * in it. */ cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_POWER); status = cbb_get(sc, CBB_SOCKET_STATE); if (on && sc->chipset != CB_TOPIC95) { if ((status & CBB_STATE_POWER_CYCLE) == 0) device_printf(sc->dev, "Power not on?\n"); + } else { + pause("cbbDwn", hz / 10); } if (status & CBB_STATE_BAD_VCC_REQ) { - device_printf(sc->dev, "Bad Vcc requested\n"); + device_printf(sc->dev, "Bad Vcc requested status %#x %dV\n", + status, volts); /* * Turn off the power, and try again. Retrigger other * active interrupts via force register. From NetBSD @@ -1563,61 +1564,6 @@ cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value) } int -cbb_suspend(device_t self) -{ - int error = 0; - struct cbb_softc *sc = device_get_softc(self); - - error = bus_generic_suspend(self); - if (error != 0) - return (error); - cbb_set(sc, CBB_SOCKET_MASK, 0); /* Quiet hardware */ - sc->cardok = 0; /* Card is bogus now */ - return (0); -} - -int -cbb_resume(device_t self) -{ - int error = 0; - struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self); - uint32_t tmp; - - /* - * In the APM and early ACPI era, BIOSes saved the PCI config - * registers. As chips became more complicated, that functionality moved - * into the ACPI code / tables. We must therefore, restore the settings - * we made here to make sure the device come back. Transitions to Dx - * from D0 and back to D0 cause the bridge to lose its config space, so - * all the bus mappings and such are preserved. - * - * For most drivers, the PCI layer handles this saving. However, since - * there's much black magic and arcane art hidden in these few lines of - * code that would be difficult to transition into the PCI - * layer. chipinit was several years of trial and error to write. - */ - pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4); - DEVPRINTF((self, "PCI Memory allocated: %08lx\n", - rman_get_start(sc->base_res))); - - sc->chipinit(sc); - - /* reset interrupt -- Do we really need to do this? */ - tmp = cbb_get(sc, CBB_SOCKET_EVENT); - cbb_set(sc, CBB_SOCKET_EVENT, tmp); - - /* CSC Interrupt: Card detect interrupt on */ - cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); - - /* Signal the thread to wakeup. */ - wakeup(&sc->intrhand); - - error = bus_generic_resume(self); - - return (error); -} - -int cbb_child_present(device_t parent, device_t child) { struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(parent); diff --git a/sys/dev/pccbb/pccbb_isa.c b/sys/dev/pccbb/pccbb_isa.c index c511062510556..ed31bd06c8329 100644 --- a/sys/dev/pccbb/pccbb_isa.c +++ b/sys/dev/pccbb/pccbb_isa.c @@ -203,13 +203,27 @@ cbb_isa_attach(device_t dev) return (ENOMEM); } +static int +cbb_isa_suspend(device_t dev) +{ + + return 0; +} + +static int +cbb_isa_resume(device_t dev) +{ + + return 0; +} + static device_method_t cbb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cbb_isa_probe), DEVMETHOD(device_attach, cbb_isa_attach), DEVMETHOD(device_detach, cbb_detach), - DEVMETHOD(device_suspend, cbb_suspend), - DEVMETHOD(device_resume, cbb_resume), + DEVMETHOD(device_suspend, cbb_isa_suspend), + DEVMETHOD(device_resume, cbb_isa_resume), /* bus methods */ DEVMETHOD(bus_read_ivar, cbb_read_ivar), diff --git a/sys/dev/pccbb/pccbb_pci.c b/sys/dev/pccbb/pccbb_pci.c index 7b4727cc3e7a4..15d382dafe6c9 100644 --- a/sys/dev/pccbb/pccbb_pci.c +++ b/sys/dev/pccbb/pccbb_pci.c @@ -301,6 +301,41 @@ cbb_print_config(device_t dev) printf("\n"); } +static void +cbb_pci_bridge_init(device_t brdev) +{ + struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev); + u_int32_t membase, irq; + + if (pci_get_powerstate(brdev) != PCI_POWERSTATE_D0) { + /* Reset the power state. */ + device_printf(brdev, "chip is in D%d power mode " + "-- setting to D0\n", pci_get_powerstate(brdev)); + pci_set_powerstate(brdev, PCI_POWERSTATE_D0); + } + membase = rman_get_start(sc->base_res); + irq = rman_get_start(sc->irq_res); + + pci_write_config(brdev, CBBR_SOCKBASE, membase, 4); + pci_write_config(brdev, PCIR_INTLINE, irq, 4); + PCI_ENABLE_IO(device_get_parent(brdev), brdev, SYS_RES_MEMORY); + + exca_init(&sc->exca[0], brdev, sc->bst, sc->bsh, CBB_EXCA_OFFSET); + sc->chipinit(sc); + + /* reset 16-bit pcmcia bus */ + exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET); + + /* turn off power */ + cbb_power(brdev, CARD_OFF); + + /* CSC Interrupt: Card detect interrupt on */ + cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); + + /* reset interrupt */ + cbb_set(sc, CBB_SOCKET_EVENT, cbb_get(sc, CBB_SOCKET_EVENT)); +} + static int cbb_pci_attach(device_t brdev) { @@ -345,11 +380,9 @@ cbb_pci_attach(device_t brdev) sc->bst = rman_get_bustag(sc->base_res); sc->bsh = rman_get_bushandle(sc->base_res); - exca_init(&sc->exca[0], brdev, sc->bst, sc->bsh, CBB_EXCA_OFFSET); sc->exca[0].flags |= EXCA_HAS_MEMREG_WIN; sc->exca[0].chipset = EXCA_CARDBUS; sc->chipinit = cbb_chipinit; - sc->chipinit(sc); /*Sysctls*/ sctx = device_get_sysctl_ctx(brdev); @@ -427,17 +460,7 @@ cbb_pci_attach(device_t brdev) goto err; } - /* reset 16-bit pcmcia bus */ - exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET); - - /* turn off power */ - cbb_power(brdev, CARD_OFF); - - /* CSC Interrupt: Card detect interrupt on */ - cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); - - /* reset interrupt */ - cbb_set(sc, CBB_SOCKET_EVENT, cbb_get(sc, CBB_SOCKET_EVENT)); + cbb_pci_bridge_init(brdev); if (bootverbose) cbb_print_config(brdev); @@ -877,14 +900,45 @@ cbb_write_config(device_t brdev, u_int b, u_int s, u_int f, u_int reg, uint32_t b, s, f, reg, val, width); } +static int +cbb_pci_suspend(device_t brdev) +{ + int error = 0; + struct cbb_softc *sc = device_get_softc(brdev); + + error = bus_generic_suspend(brdev); + if (error != 0) + return (error); + cbb_set(sc, CBB_SOCKET_MASK, 0); /* Quiet hardware */ + sc->cardok = 0; /* Card is bogus now */ + return (0); +} + +static int +cbb_pci_resume(device_t brdev) +{ + int error = 0; + struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev); + + /* Reinitialize the hardware, ala attach */ + cbb_pci_bridge_init(brdev); + + /* Signal the thread to wakeup to see if we have any cards to work with. */ + wakeup(&sc->intrhand); + + error = bus_generic_resume(brdev); + + return (error); +} + static device_method_t cbb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cbb_pci_probe), DEVMETHOD(device_attach, cbb_pci_attach), DEVMETHOD(device_detach, cbb_detach), DEVMETHOD(device_shutdown, cbb_pci_shutdown), - DEVMETHOD(device_suspend, cbb_suspend), - DEVMETHOD(device_resume, cbb_resume), + DEVMETHOD(device_suspend, cbb_pci_suspend), + DEVMETHOD(device_resume, cbb_pci_resume), /* bus methods */ DEVMETHOD(bus_read_ivar, cbb_read_ivar), diff --git a/sys/dev/pccbb/pccbbvar.h b/sys/dev/pccbb/pccbbvar.h index c3e2d24b14c69..f19b933ba2de2 100644 --- a/sys/dev/pccbb/pccbbvar.h +++ b/sys/dev/pccbb/pccbbvar.h @@ -134,11 +134,9 @@ int cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result); int cbb_release_resource(device_t brdev, device_t child, int type, int rid, struct resource *r); -int cbb_resume(device_t self); int cbb_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); -int cbb_suspend(device_t self); int cbb_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie); int cbb_write_ivar(device_t brdev, device_t child, int which, |
