summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorCan Erkin Acar <canacar@cvs.openbsd.org>2016-03-02 01:31:42 +0000
committerCan Erkin Acar <canacar@cvs.openbsd.org>2016-03-02 01:31:42 +0000
commit7fa21becbd63c1496be4e89ab16d8b1b958c1066 (patch)
tree4825b3ed896b67621fc80c832f5f193c58ebb637 /sys
parent6863931862625459ea6e1b97753cf81dc3f3da9f (diff)
Detect and only enable the port that is actually used.
The unused port, if enabled, fills up and triggers flow control, blocking transmit and causing device timeouts. Also enable interrupt pacing to limit interrupts at 2K/s. Reported and fix tested by Anthony Eden. ok dlg@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/armv7/omap/if_cpsw.c61
-rw-r--r--sys/arch/armv7/omap/if_cpswreg.h6
2 files changed, 59 insertions, 8 deletions
diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c
index d508ff04247..78eb6782785 100644
--- a/sys/arch/armv7/omap/if_cpsw.c
+++ b/sys/arch/armv7/omap/if_cpsw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_cpsw.c,v 1.32 2016/01/07 04:41:17 canacar Exp $ */
+/* $OpenBSD: if_cpsw.c,v 1.33 2016/03/02 01:31:41 canacar Exp $ */
/* $NetBSD: if_cpsw.c,v 1.3 2013/04/17 14:36:34 bouyer Exp $ */
/*
@@ -148,6 +148,7 @@ struct cpsw_softc {
volatile bool sc_txeoq;
volatile bool sc_rxeoq;
struct timeout sc_tick;
+ int sc_active_port;
};
#define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
@@ -286,6 +287,45 @@ cpsw_get_mac_addr(struct cpsw_softc *sc)
}
}
+static void
+cpsw_mdio_init(struct cpsw_softc *sc)
+{
+ uint32_t alive, link;
+ u_int tries;
+
+ sc->sc_active_port = 0;
+
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOCONTROL,
+ (1<<30) | (1<<18) | 0xFF);
+
+ for(tries = 0; tries < 1000; tries++) {
+ alive = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOALIVE) & 3;
+ if (alive)
+ break;
+ delay(1);
+ }
+
+ if (alive == 0) {
+ printf("%s: no PHY is alive\n", DEVNAME(sc));
+ return;
+ }
+
+ link = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOLINK) & 3;
+
+ if (alive == 3) {
+ /* both ports are alive, prefer one with link */
+ if (link == 2)
+ sc->sc_active_port = 1;
+ } else if (alive == 2)
+ sc->sc_active_port = 1;
+
+ /* Select the port to monitor */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERPHYSEL0,
+ sc->sc_active_port);
+}
+
void
cpsw_attach(struct device *parent, struct device *self, void *aux)
{
@@ -391,6 +431,8 @@ cpsw_attach(struct device *parent, struct device *self, void *aux)
sc->sc_mii.mii_writereg = cpsw_mii_writereg;
sc->sc_mii.mii_statchg = cpsw_mii_statchg;
+ cpsw_mdio_init(sc);
+
ifmedia_init(&sc->sc_mii.mii_media, 0, cpsw_mediachange,
cpsw_mediastatus);
mii_attach(self, &sc->sc_mii, 0xffffffff,
@@ -776,13 +818,14 @@ cpsw_init(struct ifnet *ifp)
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_LO(i+1),
ac->ac_enaddr[4] | (ac->ac_enaddr[5] << 8));
- /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5),
+ /* Set MACCONTROL for ports 0,1: FULLDUPLEX(0), GMII_EN(5),
IFCTL_A(15), IFCTL_B(16) FIXME */
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_MACCONTROL(i),
1 | (1<<5) | (1<<15) | (1<<16));
- /* Set ALE port to forwarding(3) */
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(i+1), 3);
+ /* Set ALE port to forwarding(3) on the active port */
+ if (i == sc->sc_active_port)
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(i+1), 3);
}
/* Set Host Port Mapping */
@@ -834,6 +877,12 @@ cpsw_init(struct ifnet *ifp)
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CONTROL, 1);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CONTROL, 1);
+ /* Enable interrupt pacing for C0 RX/TX (IMAX set to max intr/ms allowed) */
+#define CPSW_VBUSP_CLK_MHZ 2400 /* hardcoded for BBB */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_IMAX(0), 2);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_IMAX(0), 2);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_INT_CONTROL, 3 << 16 | CPSW_VBUSP_CLK_MHZ/4);
+
/* Enable TX and RX interrupt receive for core 0 */
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 1);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 1);
@@ -852,9 +901,7 @@ cpsw_init(struct ifnet *ifp)
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC);
- /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
- /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOCONTROL, (1<<30) | (1<<18) | 0xFF);
+ cpsw_mdio_init(sc);
mii_mediachg(mii);
diff --git a/sys/arch/armv7/omap/if_cpswreg.h b/sys/arch/armv7/omap/if_cpswreg.h
index 59830aaf209..98ff229b3b5 100644
--- a/sys/arch/armv7/omap/if_cpswreg.h
+++ b/sys/arch/armv7/omap/if_cpswreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_cpswreg.h,v 1.5 2013/11/15 14:31:52 fgsch Exp $ */
+/* $OpenBSD: if_cpswreg.h,v 1.6 2016/03/02 01:31:41 canacar Exp $ */
/*-
* Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
@@ -97,6 +97,8 @@
#define MDIO_OFFSET 0x1000
#define MDIOCONTROL (MDIO_OFFSET + 0x04)
+#define MDIOALIVE (MDIO_OFFSET + 0x08)
+#define MDIOLINK (MDIO_OFFSET + 0x0C)
#define MDIOUSERACCESS0 (MDIO_OFFSET + 0x80)
#define MDIOUSERPHYSEL0 (MDIO_OFFSET + 0x84)
@@ -112,6 +114,8 @@
#define CPSW_WR_C_RX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x44)
#define CPSW_WR_C_TX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x48)
#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
+#define CPSW_WR_C_RX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x70)
+#define CPSW_WR_C_TX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x74)
#define CPSW_MISC_HOST_PEND 0x0004
#define CPSW_CPPI_RAM_OFFSET 0x2000