diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index 3451b12a99a..4971e89f00b 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 6a13bd795c7..07abaff5481 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 a8ca26472ce..ae73fe1c714 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 */