summaryrefslogtreecommitdiff
path: root/sys/dev/pci
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 /sys/dev/pci
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.
Diffstat (limited to 'sys/dev/pci')
-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.