summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Campbell <aaron@cvs.openbsd.org>2000-12-06 17:08:28 +0000
committerAaron Campbell <aaron@cvs.openbsd.org>2000-12-06 17:08:28 +0000
commite1a1e49b6d8f502fccd06d6369cb83e0ed290131 (patch)
tree8b7cca38bc90089f28a3d8821099f96692bcb838
parentb3e645440ad21f3a540f13f8c76743fc0ca01771 (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.c91
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.