diff options
author | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-12-06 17:08:28 +0000 |
---|---|---|
committer | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-12-06 17:08:28 +0000 |
commit | e1a1e49b6d8f502fccd06d6369cb83e0ed290131 (patch) | |
tree | 8b7cca38bc90089f28a3d8821099f96692bcb838 | |
parent | b3e645440ad21f3a540f13f8c76743fc0ca01771 (diff) |
BUG FIX: change enable sequence for 16-bit pcmcia cards. This change
provides better (not perfect) reset sequence. The most significant
change is asserting output enable reg before power up. Stop routing
interrupt during reset.
From NetBSD.
-rw-r--r-- | sys/dev/pci/pccbb.c | 91 |
1 files changed, 43 insertions, 48 deletions
diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index 6474e480912..e240773bb0f 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pccbb.c,v 1.12 2000/11/29 22:57:16 aaron Exp $ */ +/* $OpenBSD: pccbb.c,v 1.13 2000/12/06 17:08:27 aaron Exp $ */ /* $NetBSD: pccbb.c,v 1.42 2000/06/16 23:41:35 cgd Exp $ */ /* @@ -747,7 +747,7 @@ pccbb_chipinit(sc) /* Route functional interrupts to PCI. */ reg = pci_conf_read(pc, tag, PCI_BCR_INTR); - reg &= ~CB_BCR_INTR_IREQ_ENABLE; /* use PCI Intr */ + reg |= CB_BCR_INTR_IREQ_ENABLE; /* disable PCI Intr */ reg |= CB_BCR_WRITE_POST_ENABLE; /* enable write post */ reg |= CB_BCR_RESET_ENABLE; /* assert reset */ pci_conf_write(pc, tag, PCI_BCR_INTR, reg); @@ -1076,6 +1076,9 @@ pccbb_pcmcia_read(ph, reg) struct pcic_handle *ph; int reg; { + bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h, + PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_READ); + return bus_space_read_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg); } @@ -1086,6 +1089,9 @@ pccbb_pcmcia_write(ph, reg, val) int reg; u_int8_t val; { + bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h, + PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_WRITE); + bus_space_write_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg, val); } @@ -1222,13 +1228,6 @@ pccbb_power(ct, command) bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl); status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); - delay(20 * 1000); /* wait 20 ms: Vcc setup time */ - /* - * XXX delay 200 ms: though the standard defines that the Vcc set-up - * time is 20 ms, some PC-Card bridge requires longer duration. - */ - delay(200 * 1000); - if (status & CB_SOCKET_STAT_BADVCC) { /* bad Vcc request */ printf ("%s: bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n", @@ -1268,6 +1267,13 @@ pccbb_power(ct, command) #endif return 0; } + + /* + * XXX delay 300 ms: though the standard defines that the Vcc set-up + * time is 20 ms, some PC-Card bridge requires longer duration. + */ + delay(300 * 1000); + return 1; /* power changed correctly */ } @@ -1655,24 +1661,23 @@ pccbb_intr_establish(sc, irq, level, func, arg) void *arg; { struct pccbb_intrhand_list *pil, *newpil; + pcireg_t reg; DPRINTF(("pccbb_intr_establish start. %p\n", sc->sc_pil)); if (sc->sc_pil == NULL) { /* initialize bridge intr routing */ + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR); + reg &= ~CB_BCR_INTR_IREQ_ENABLE; + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg); switch (sc->sc_chipset) { case CB_TI113X: - { - pcireg_t cbctrl = - pci_conf_read(sc->sc_pc, sc->sc_tag, - PCI_CBCTRL); - /* functional intr enabled */ - cbctrl |= PCI113X_CBCTRL_PCI_INTR; - pci_conf_write(sc->sc_pc, sc->sc_tag, - PCI_CBCTRL, cbctrl); - break; - } + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); + /* functional intr enabled */ + reg |= PCI113X_CBCTRL_PCI_INTR; + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg); + break; default: break; } @@ -1717,6 +1722,7 @@ pccbb_intr_disestablish(sc, ih) void *ih; { struct pccbb_intrhand_list *pil, **pil_prev; + pcireg_t reg; DPRINTF(("pccbb_intr_disestablish start. %p\n", sc->sc_pil)); @@ -1737,18 +1743,18 @@ pccbb_intr_disestablish(sc, ih) DPRINTF(("pccbb_intr_disestablish: no interrupt handler\n")); + /* stop routing PCI intr */ + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR); + reg |= CB_BCR_INTR_IREQ_ENABLE; + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg); + switch (sc->sc_chipset) { case CB_TI113X: - { - pcireg_t cbctrl = - pci_conf_read(sc->sc_pc, sc->sc_tag, - PCI_CBCTRL); - /* functional intr disabled */ - cbctrl &= ~PCI113X_CBCTRL_PCI_INTR; - pci_conf_write(sc->sc_pc, sc->sc_tag, - PCI_CBCTRL, cbctrl); - break; - } + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); + /* functional intr disabled */ + reg &= ~PCI113X_CBCTRL_PCI_INTR; + pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg); + break; default: break; } @@ -2221,15 +2227,9 @@ pccbb_pcmcia_socket_enable(pch) return; } - /* assert reset bit */ - intr = Pcic_read(ph, PCIC_INTR); - intr &= ~(PCIC_INTR_RESET | PCIC_INTR_CARDTYPE_MASK); - Pcic_write(ph, PCIC_INTR, intr); - /* disable socket i/o: negate output enable bit */ - power = Pcic_read(ph, PCIC_PWRCTL); - power &= ~PCIC_PWRCTL_OE; + power = 0; Pcic_write(ph, PCIC_PWRCTL, power); /* power down the socket to reset it, clear the card reset pin */ @@ -2242,21 +2242,16 @@ pccbb_pcmcia_socket_enable(pch) */ /* delay(300*1000); too much */ - /* power up the socket */ - pccbb_power(sc, voltage); - - /* - * wait 100ms until power raise (Tpr) and 20ms to become - * stable (Tsu(Vcc)). - * - * some machines require some more time to be settled - * (another 200ms is added here). - */ - /* delay((100 + 20 + 200)*1000); too much */ - + /* assert reset bit */ + intr = Pcic_read(ph, PCIC_INTR); + intr &= ~(PCIC_INTR_RESET | PCIC_INTR_CARDTYPE_MASK); + Pcic_write(ph, PCIC_INTR, intr); + + /* power up the socket and output enable */ power = Pcic_read(ph, PCIC_PWRCTL); power |= PCIC_PWRCTL_OE; Pcic_write(ph, PCIC_PWRCTL, power); + pccbb_power(sc, voltage); /* * hold RESET at least 10us. |