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 /sys/dev/pci/pccbb.c | |
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.
Diffstat (limited to 'sys/dev/pci/pccbb.c')
-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. |