aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/pccbb
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2015-01-16 06:19:08 +0000
committerWarner Losh <imp@FreeBSD.org>2015-01-16 06:19:08 +0000
commitb45c7d14d00c6bd38d0ae784ed32099f006cf5b2 (patch)
treee4880f02a15f453c508e81639f65f2eed9f65a0f /sys/dev/pccbb
parent1acffcc470922938a41e058413a41c7115c6643f (diff)
Notes
Diffstat (limited to 'sys/dev/pccbb')
-rw-r--r--sys/dev/pccbb/pccbb.c108
-rw-r--r--sys/dev/pccbb/pccbb_isa.c18
-rw-r--r--sys/dev/pccbb/pccbb_pci.c84
-rw-r--r--sys/dev/pccbb/pccbbvar.h2
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,