diff options
| author | Warner Losh <imp@FreeBSD.org> | 2015-01-16 06:19:08 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2015-01-16 06:19:08 +0000 |
| commit | b45c7d14d00c6bd38d0ae784ed32099f006cf5b2 (patch) | |
| tree | e4880f02a15f453c508e81639f65f2eed9f65a0f /sys/dev/pccbb | |
| parent | 1acffcc470922938a41e058413a41c7115c6643f (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, 100 insertions, 112 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index 77a972502672..08ff42772ee3 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); - DEVPRINTF((sc->dev, "Status is %#x\n", status)); + DPRINTF(("Status is 0x%x\n", status)); if (!CBB_CARD_PRESENT(status)) { not_a_card = 0; /* We know card type */ cbb_removal(sc); @@ -800,14 +800,13 @@ 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) && @@ -817,18 +816,19 @@ 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. + * 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. */ 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,27 +838,26 @@ 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. We just - * pause a little below to cover that. Most bridges don't seem to need - * this delay. + * 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. * - * 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. + * NB: Topic95B doesn't set the power cycle bit. we assume that + * both it and the TOPIC95 behave the same. */ 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 status %#x %dV\n", - status, volts); + device_printf(sc->dev, "Bad Vcc requested\n"); /* * Turn off the power, and try again. Retrigger other * active interrupts via force register. From NetBSD @@ -1564,6 +1563,61 @@ 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 ed31bd06c832..c51106251055 100644 --- a/sys/dev/pccbb/pccbb_isa.c +++ b/sys/dev/pccbb/pccbb_isa.c @@ -203,27 +203,13 @@ 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_isa_suspend), - DEVMETHOD(device_resume, cbb_isa_resume), + DEVMETHOD(device_suspend, cbb_suspend), + DEVMETHOD(device_resume, cbb_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 15d382dafe6c..7b4727cc3e7a 100644 --- a/sys/dev/pccbb/pccbb_pci.c +++ b/sys/dev/pccbb/pccbb_pci.c @@ -301,41 +301,6 @@ 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) { @@ -380,9 +345,11 @@ 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); @@ -460,7 +427,17 @@ cbb_pci_attach(device_t brdev) goto err; } - cbb_pci_bridge_init(brdev); + /* 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)); if (bootverbose) cbb_print_config(brdev); @@ -900,45 +877,14 @@ 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_pci_suspend), - DEVMETHOD(device_resume, cbb_pci_resume), + DEVMETHOD(device_suspend, cbb_suspend), + DEVMETHOD(device_resume, cbb_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 f19b933ba2de..c3e2d24b14c6 100644 --- a/sys/dev/pccbb/pccbbvar.h +++ b/sys/dev/pccbb/pccbbvar.h @@ -134,9 +134,11 @@ 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, |
