aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/pccbb
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2006-08-12 09:06:55 +0000
committerWarner Losh <imp@FreeBSD.org>2006-08-12 09:06:55 +0000
commit673c9ca931eceaa7d8964599a6738d6b97c8d066 (patch)
treee22afce7c8f74e5783aabb323f1b346343a1ebf3 /sys/dev/pccbb
parent3c48d33eeca0c2f070207ccfbdf9eb141f3a4405 (diff)
Notes
Diffstat (limited to 'sys/dev/pccbb')
-rw-r--r--sys/dev/pccbb/pccbb.c55
-rw-r--r--sys/dev/pccbb/pccbb_pci.c44
-rw-r--r--sys/dev/pccbb/pccbbreg.h74
3 files changed, 112 insertions, 61 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c
index 3451b12a99a0..4971e89f00b5 100644
--- a/sys/dev/pccbb/pccbb.c
+++ b/sys/dev/pccbb/pccbb.c
@@ -700,7 +700,7 @@ cbb_o2micro_power_hack2(struct cbb_softc *sc, uint8_t reg)
int
cbb_power(device_t brdev, int volts)
{
- uint32_t status, sock_ctrl, mask;
+ uint32_t status, sock_ctrl, reg_ctrl, mask;
struct cbb_softc *sc = device_get_softc(brdev);
int cnt, sane;
int retval = 0;
@@ -744,14 +744,15 @@ cbb_power(device_t brdev, int volts)
reg = cbb_o2micro_power_hack(sc);
/*
- * We have to mask the card change detect interrupt while we're
- * messing with the power. It is allowed to bounce while we're
- * messing with power as things settle down. In addition, we mask off
- * the card's function interrupt by routing it via the ISA bus. This
- * bit generally only affects 16bit cards. Some bridges allow one to
- * set another bit to have it also affect 32bit cards. Since 32bit
- * cards are required to be better behaved, we don't bother to get
- * into those bridge specific features.
+ * We have to mask the card change detect interrupt while
+ * we're messing with the power. It is allowed to bounce
+ * while we're messing with power as things settle down. In
+ * addition, we mask off the card's function interrupt by
+ * routing it via the ISA bus. This bit generally only
+ * affects 16-bit cards. Some bridges allow one to set
+ * another bit to have it also affect 32-bit cards. Since
+ * 32-bit cards are required to be better behaved, we don't
+ * bother to get into those bridge specific features.
*/
mask = cbb_get(sc, CBB_SOCKET_MASK);
mask |= CBB_SOCKET_MASK_POWER;
@@ -763,13 +764,29 @@ cbb_power(device_t brdev, int volts)
if (on) {
mtx_lock(&sc->mtx);
cnt = sc->powerintr;
- sane = 200;
+ /*
+ * 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.
+ */
+ sane = 10;
while (!(cbb_get(sc, CBB_SOCKET_STATE) & CBB_STATE_POWER_CYCLE) &&
cnt == sc->powerintr && sane-- > 0)
- cv_timedwait(&sc->powercv, &sc->mtx, hz / 10);
+ cv_timedwait(&sc->powercv, &sc->mtx, hz / 20);
mtx_unlock(&sc->mtx);
- if (sane <= 0)
+ /*
+ * 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) {
+ tsleep(sc, PZERO, "cbb95B", hz / 10);
+ } else if (sane <= 0) {
device_printf(sc->dev, "power timeout, doom?\n");
+ }
}
/*
@@ -782,10 +799,13 @@ cbb_power(device_t brdev, int volts)
* 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.
*/
cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_POWER);
status = cbb_get(sc, CBB_SOCKET_STATE);
- if (on) {
+ if (on && sc->chipset != CB_TOPIC95) {
if ((status & CBB_STATE_POWER_CYCLE) == 0)
device_printf(sc->dev, "Power not on?\n");
}
@@ -794,6 +814,15 @@ cbb_power(device_t brdev, int volts)
/* XXX Do we want to do something to mitigate things here? */
goto done;
}
+ if (sc->chipset == CB_TOPIC97) {
+ reg_ctrl = pci_read_config(sc->dev, TOPIC_REG_CTRL, 4);
+ reg_ctrl &= ~TOPIC97_REG_CTRL_TESTMODE;
+ if (on)
+ reg_ctrl |= TOPIC97_REG_CTRL_CLKRUN_ENA;
+ else
+ reg_ctrl &= ~TOPIC97_REG_CTRL_CLKRUN_ENA;
+ pci_write_config(sc->dev, TOPIC_REG_CTRL, reg_ctrl, 4);
+ }
PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
& ~CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
retval = 1;
diff --git a/sys/dev/pccbb/pccbb_pci.c b/sys/dev/pccbb/pccbb_pci.c
index 6a13bd795c7f..07abaff5481f 100644
--- a/sys/dev/pccbb/pccbb_pci.c
+++ b/sys/dev/pccbb/pccbb_pci.c
@@ -302,10 +302,11 @@ cbb_pci_attach(device_t brdev)
{
static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
- int rid;
- device_t parent;
struct sysctl_ctx_list *sctx;
struct sysctl_oid *soid;
+ int rid;
+ device_t parent;
+ uint32_t pribus;
parent = device_get_parent(brdev);
mtx_init(&sc->mtx, device_get_nameunit(brdev), "cbb", MTX_DEF);
@@ -317,7 +318,7 @@ cbb_pci_attach(device_t brdev)
sc->exca[0].pccarddev = NULL;
sc->secbus = pci_read_config(brdev, PCIR_SECBUS_2, 1);
sc->subbus = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
- sc->pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1);
+ sc->pribus = pcib_get_bus(parent);
SLIST_INIT(&sc->rl);
cbb_powerstate_d0(brdev);
@@ -359,10 +360,11 @@ cbb_pci_attach(device_t brdev)
* are in an appropriate range.
*/
DEVPRINTF((brdev, "Secondary bus is %d\n", sc->secbus));
- if (sc->secbus == 0) {
+ pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1);
+ if (sc->secbus == 0 || sc->pribus != pribus) {
if (curr_bus_number <= sc->pribus)
curr_bus_number = sc->pribus + 1;
- if (pci_read_config(brdev, PCIR_PRIBUS_2, 1) != sc->pribus) {
+ if (pribus != sc->pribus) {
DEVPRINTF((brdev, "Setting primary bus to %d\n",
sc->pribus));
pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
@@ -553,27 +555,32 @@ cbb_chipinit(struct cbb_softc *sc)
reg = (reg & 0x0f) |
EXCA_O2CC_IREQ_INTC | EXCA_O2CC_STSCHG_INTC;
exca_putb(&sc->exca[0], EXCA_O2MICRO_CTRL_C, reg);
-
break;
case CB_TOPIC97:
/*
* Disable Zoom Video, ToPIC 97, 100.
*/
- pci_write_config(sc->dev, CBBR_TOPIC_ZV_CONTROL, 0, 1);
+ pci_write_config(sc->dev, TOPIC97_ZV_CONTROL, 0, 1);
/*
* ToPIC 97, 100
* At offset 0xa1: INTERRUPT CONTROL register
* 0x1: Turn on INT interrupts.
*/
- PCI_MASK_CONFIG(sc->dev, CBBR_TOPIC_INTCTRL,
- | CBBM_TOPIC_INTCTRL_INTIRQSEL, 1);
+ PCI_MASK_CONFIG(sc->dev, TOPIC_INTCTRL,
+ | TOPIC97_INTCTRL_INTIRQSEL, 1);
+ /*
+ * ToPIC97, 100
+ * Need to assert support for low voltage cards
+ */
+ exca_setb(&sc->exca[0], EXCA_TOPIC97_CTRL,
+ EXCA_TOPIC97_CTRL_LV_MASK);
goto topic_common;
case CB_TOPIC95:
/*
* SOCKETCTRL appears to be TOPIC 95/B specific
*/
- PCI_MASK_CONFIG(sc->dev, CBBR_TOPIC_SOCKETCTRL,
- | CBBM_TOPIC_SOCKETCTRL_SCR_IRQSEL, 4);
+ PCI_MASK_CONFIG(sc->dev, TOPIC95_SOCKETCTRL,
+ | TOPIC95_SOCKETCTRL_SCR_IRQSEL, 4);
topic_common:;
/*
@@ -586,20 +593,19 @@ cbb_chipinit(struct cbb_softc *sc)
* in legacy mode to 0x3e0 and offset 0. (legacy
* mode is determined elsewhere)
*/
- pci_write_config(sc->dev, CBBR_TOPIC_SLOTCTRL,
- CBBM_TOPIC_SLOTCTRL_SLOTON |
- CBBM_TOPIC_SLOTCTRL_SLOTEN |
- CBBM_TOPIC_SLOTCTRL_ID_LOCK |
- CBBM_TOPIC_SLOTCTRL_ID_WP, 1);
+ pci_write_config(sc->dev, TOPIC_SLOTCTRL,
+ TOPIC_SLOTCTRL_SLOTON |
+ TOPIC_SLOTCTRL_SLOTEN |
+ TOPIC_SLOTCTRL_ID_LOCK |
+ TOPIC_SLOTCTRL_ID_WP, 1);
/*
* At offset 0xa3 Card Detect Control Register
* 0x80 CARDBUS enbale
* 0x01 Cleared for hardware change detect
*/
- PCI_MASK2_CONFIG(sc->dev, CBBR_TOPIC_CDC,
- | CBBM_TOPIC_CDC_CARDBUS,
- & ~CBBM_TOPIC_CDC_SWDETECT, 4);
+ PCI_MASK2_CONFIG(sc->dev, TOPIC_CDC,
+ | TOPIC_CDC_CARDBUS, & ~TOPIC_CDC_SWDETECT, 4);
break;
}
diff --git a/sys/dev/pccbb/pccbbreg.h b/sys/dev/pccbb/pccbbreg.h
index a8ca26472ce0..ae73fe1c7149 100644
--- a/sys/dev/pccbb/pccbbreg.h
+++ b/sys/dev/pccbb/pccbbreg.h
@@ -132,44 +132,60 @@
# define CBBM_DEVCTRL_INT_PCI 0x02
/* ToPIC 95 ONLY */
-#define CBBR_TOPIC_SOCKETCTRL 0x90
-# define CBBM_TOPIC_SOCKETCTRL_SCR_IRQSEL 0x00000001 /* PCI intr */
+#define TOPIC95_SOCKETCTRL 0x90
+# define TOPIC95_SOCKETCTRL_SCR_IRQSEL 0x00000001 /* PCI intr */
/* ToPIC 97, 100 */
-#define CBBR_TOPIC_ZV_CONTROL 0x9c /* 1 byte */
-# define CBBM_TOPIC_ZVC_ENABLE 0x1
+#define TOPIC97_ZV_CONTROL 0x9c /* 1 byte */
+# define TOPIC97_ZVC_ENABLE 0x1
/* TOPIC 95+ */
-#define CBBR_TOPIC_SLOTCTRL 0xa0 /* 1 byte */
-# define CBBM_TOPIC_SLOTCTRL_SLOTON 0x80
-# define CBBM_TOPIC_SLOTCTRL_SLOTEN 0x40
-# define CBBM_TOPIC_SLOTCTRL_ID_LOCK 0x20
-# define CBBM_TOPIC_SLOTCTRL_ID_WP 0x10
-# define CBBM_TOPIC_SLOTCTRL_PORT_MASK 0x0c
-# define CBBM_TOPIC_SLOTCTRL_PORT_SHIFT 2
-# define CBBM_TOPIC_SLOTCTRL_OSF_MASK 0x03
-# define CBBM_TOPIC_SLOTCTRL_OSF_SHIFT 0
+#define TOPIC_SLOTCTRL 0xa0 /* 1 byte */
+# define TOPIC_SLOTCTRL_SLOTON 0x80
+# define TOPIC_SLOTCTRL_SLOTEN 0x40
+# define TOPIC_SLOTCTRL_ID_LOCK 0x20
+# define TOPIC_SLOTCTRL_ID_WP 0x10
+# define TOPIC_SLOTCTRL_PORT_MASK 0x0c
+# define TOPIC_SLOTCTRL_PORT_SHIFT 2
+# define TOPIC_SLOTCTRL_OSF_MASK 0x03
+# define TOPIC_SLOTCTRL_OSF_SHIFT 0
/* TOPIC 95+ */
-#define CBBR_TOPIC_INTCTRL 0xa1 /* 1 byte */
-# define CBBM_TOPIC_INTCTRL_INTB 0x20
-# define CBBM_TOPIC_INTCTRL_INTA 0x10
-# define CBBM_TOPIC_INTCTRL_INT_MASK 0x30
+#define TOPIC_INTCTRL 0xa1 /* 1 byte */
+# define TOPIC_INTCTRL_INTB 0x20
+# define TOPIC_INTCTRL_INTA 0x10
+# define TOPIC_INTCTRL_INT_MASK 0x30
/* The following bits may be for ToPIC 95 only */
-# define CBBM_TOPIC_INTCTRL_CLOCK_MASK 0x0c
-# define CBBM_TOPIC_INTCTRL_CLOCK_2 0x08 /* PCI Clk/2 */
-# define CBBM_TOPIC_INTCTRL_CLOCK_1 0x04 /* PCI Clk */
-# define CBBM_TOPIC_INTCTRL_CLOCK_0 0x00 /* no clock */
+# define TOPIC95_INTCTRL_CLOCK_MASK 0x0c
+# define TOPIC95_INTCTRL_CLOCK_2 0x08 /* PCI Clk/2 */
+# define TOPIC95_INTCTRL_CLOCK_1 0x04 /* PCI Clk */
+# define TOPIC95_INTCTRL_CLOCK_0 0x00 /* no clock */
/* ToPIC97, 100 defines the following bits */
-# define CBBM_TOPIC_INTCTRL_STSIRQNP 0x04
-# define CBBM_TOPIC_INTCTRL_IRQNP 0x02
-# define CBBM_TOPIC_INTCTRL_INTIRQSEL 0x01
+# define TOPIC97_INTCTRL_STSIRQNP 0x04
+# define TOPIC97_INTCTRL_IRQNP 0x02
+# define TOPIC97_INTCTRL_INTIRQSEL 0x01
/* TOPIC 95+ */
-#define CBBR_TOPIC_CDC 0xa3 /* 1 byte */
-# define CBBM_TOPIC_CDC_CARDBUS 0x80
-# define CBBM_TOPIC_CDC_VS1 0x04
-# define CBBM_TOPIC_CDC_VS2 0x02
-# define CBBM_TOPIC_CDC_SWDETECT 0x01
+#define TOPIC_CDC 0xa3 /* 1 byte */
+# define TOPIC_CDC_CARDBUS 0x80
+# define TOPIC_CDC_VS1 0x04
+# define TOPIC_CDC_VS2 0x02
+# define TOPIC_CDC_SWDETECT 0x01
+
+/* TOPIC97+? */
+#define TOPIC_REG_CTRL 0xa4 /* 4 bytes */
+# define TOPIC_REG_CTRL_RESUME_RESET 0x80000000
+# define TOPIC_REG_CTRL_REMOVE_RESET 0x40000000
+# define TOPIC97_REG_CTRL_CLKRUN_ENA 0x20000000
+# define TOPIC97_REG_CTRL_TESTMODE 0x10000000
+# define TOPIC97_REG_CTRL_IOPLUP 0x08000000
+# define TOPIC_REG_CTRL_BUFOFF_PWROFF 0x02000000
+# define TOPIC_REG_CTRL_BUFOFF_SIGOFF 0x01000000
+# define TOPIC97_REG_CTRL_CB_DEV_MASK 0x0000f800
+# define TOPIC97_REG_CTRL_CB_DEV_SHIFT 11
+# define TOPIC97_REG_CTRL_RI_DISABLE 0x00000004
+# define TOPIC97_REG_CTRL_CAUDIO_OFF 0x00000002
+# define TOPIC_REG_CTRL_CAUDIO_INVERT 0x00000001
+
/* Socket definitions */
#define CBB_SOCKET_EVENT_CSTS 0x01 /* Card Status Change */