summaryrefslogtreecommitdiff
path: root/sys/dev/fdt/if_dwge.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2023-01-14 17:02:58 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2023-01-14 17:02:58 +0000
commit9036a87f114f4bc615044e92cf50eb9dbfca4d97 (patch)
tree70bd92968e37c09ab91eca72b222e5dd5f542168 /sys/dev/fdt/if_dwge.c
parent76ec20586399aa9632649d2d0c6f71948d59abce (diff)
Add support for "enhanced descriptor" mode found on some variants of the
Synopsys DesignWare GMAC. ok mlarkin@
Diffstat (limited to 'sys/dev/fdt/if_dwge.c')
-rw-r--r--sys/dev/fdt/if_dwge.c55
1 files changed, 44 insertions, 11 deletions
diff --git a/sys/dev/fdt/if_dwge.c b/sys/dev/fdt/if_dwge.c
index 400807576b0..eed03e3fa37 100644
--- a/sys/dev/fdt/if_dwge.c
+++ b/sys/dev/fdt/if_dwge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_dwge.c,v 1.13 2021/12/20 04:21:32 jmatthew Exp $ */
+/* $OpenBSD: if_dwge.c,v 1.14 2023/01/14 17:02:57 kettenis Exp $ */
/*
* Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
* Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -146,6 +146,8 @@
#define GMAC_AXI_BUS_MODE_BLEN_16 (1 << 3)
#define GMAC_AXI_BUS_MODE_BLEN_8 (1 << 2)
#define GMAC_AXI_BUS_MODE_BLEN_4 (1 << 1)
+#define GMAC_HW_FEATURE 0x1058
+#define GMAC_HW_FEATURE_ENHDESSEL (1 << 24)
/*
* DWGE descriptors.
@@ -172,6 +174,11 @@ struct dwge_desc {
#define TDES0_IHE (1 << 16)
#define TDES0_OWN (1 << 31)
+#define ETDES0_TCH (1 << 20)
+#define ETDES0_FS (1 << 28)
+#define ETDES0_LS (1 << 29)
+#define ETDES0_IC (1 << 30)
+
/* Rx status bits */
#define RDES0_PE (1 << 0)
#define RDES0_CE (1 << 1)
@@ -207,6 +214,8 @@ struct dwge_desc {
#define RDES1_RCH (1 << 24)
#define RDES1_DIC (1 << 31)
+#define ERDES1_RCH (1 << 14)
+
struct dwge_buf {
bus_dmamap_t tb_map;
struct mbuf *tb_m;
@@ -243,6 +252,7 @@ struct dwge_softc {
int sc_link;
int sc_phyloc;
int sc_force_thresh_dma_mode;
+ int sc_enh_desc;
struct dwge_dmamem *sc_txring;
struct dwge_buf *sc_txbuf;
@@ -348,6 +358,7 @@ dwge_attach(struct device *parent, struct device *self, void *aux)
uint32_t axi_config;
uint32_t mode, pbl;
uint32_t version;
+ uint32_t feature;
int node;
sc->sc_node = faa->fa_node;
@@ -389,6 +400,12 @@ dwge_attach(struct device *parent, struct device *self, void *aux)
version = dwge_read(sc, GMAC_VERSION);
printf(": rev 0x%02x", version & GMAC_VERSION_SNPS_MASK);
+ if ((version & GMAC_VERSION_SNPS_MASK) > 0x35) {
+ feature = dwge_read(sc, GMAC_HW_FEATURE);
+ if (feature & GMAC_HW_FEATURE_ENHDESSEL)
+ sc->sc_enh_desc = 1;
+ }
+
/* Power up PHY. */
phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
if (phy_supply)
@@ -934,7 +951,7 @@ dwge_tx_proc(struct dwge_softc *sc)
else
sc->sc_tx_cons++;
- txd->sd_status = 0;
+ txd->sd_status = sc->sc_enh_desc ? ETDES0_TCH : 0;
}
if (sc->sc_tx_cons == sc->sc_tx_prod)
@@ -1034,6 +1051,10 @@ dwge_up(struct dwge_softc *sc)
sc->sc_txdesc[i].sd_next =
DWGE_DMA_DVA(sc->sc_txring) +
((i+1) % DWGE_NTXDESC) * sizeof(struct dwge_desc);
+ if (sc->sc_enh_desc)
+ sc->sc_txdesc[i].sd_status = ETDES0_TCH;
+ else
+ sc->sc_txdesc[i].sd_len = TDES1_TCH;
}
bus_dmamap_sync(sc->sc_dmat, DWGE_DMA_MAP(sc->sc_txring),
@@ -1060,6 +1081,8 @@ dwge_up(struct dwge_softc *sc)
sc->sc_rxdesc[i].sd_next =
DWGE_DMA_DVA(sc->sc_rxring) +
((i+1) % DWGE_NRXDESC) * sizeof(struct dwge_desc);
+ sc->sc_rxdesc[i].sd_len =
+ sc->sc_enh_desc ? ERDES1_RCH : RDES1_RCH;
}
if_rxr_init(&sc->sc_rx_ring, 2, DWGE_NRXDESC);
@@ -1243,13 +1266,23 @@ dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx, int *used)
txd = txd_start = &sc->sc_txdesc[frag];
for (i = 0; i < map->dm_nsegs; i++) {
txd->sd_addr = map->dm_segs[i].ds_addr;
- txd->sd_len = map->dm_segs[i].ds_len | TDES1_TCH;
- if (i == 0)
- txd->sd_len |= TDES1_FS;
- if (i == (map->dm_nsegs - 1))
- txd->sd_len |= TDES1_LS | TDES1_IC;
+ if (sc->sc_enh_desc) {
+ txd->sd_status = ETDES0_TCH;
+ txd->sd_len = map->dm_segs[i].ds_len;
+ if (i == 0)
+ txd->sd_status |= ETDES0_FS;
+ if (i == (map->dm_nsegs - 1))
+ txd->sd_status |= ETDES0_LS | ETDES0_IC;
+ } else {
+ txd->sd_status = 0;
+ txd->sd_len = map->dm_segs[i].ds_len | TDES1_TCH;
+ if (i == 0)
+ txd->sd_len |= TDES1_FS;
+ if (i == (map->dm_nsegs - 1))
+ txd->sd_len |= TDES1_LS | TDES1_IC;
+ }
if (i != 0)
- txd->sd_status = TDES0_OWN;
+ txd->sd_status |= TDES0_OWN;
bus_dmamap_sync(sc->sc_dmat, DWGE_DMA_MAP(sc->sc_txring),
frag * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
@@ -1265,11 +1298,10 @@ dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx, int *used)
KASSERT(frag != sc->sc_tx_cons);
}
- txd_start->sd_status = TDES0_OWN;
+ txd_start->sd_status |= TDES0_OWN;
bus_dmamap_sync(sc->sc_dmat, DWGE_DMA_MAP(sc->sc_txring),
*idx * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
-
KASSERT(sc->sc_txbuf[cur].tb_m == NULL);
sc->sc_txbuf[*idx].tb_map = sc->sc_txbuf[cur].tb_map;
sc->sc_txbuf[cur].tb_map = map;
@@ -1401,7 +1433,8 @@ dwge_fill_rx_ring(struct dwge_softc *sc)
break;
rxd = &sc->sc_rxdesc[sc->sc_rx_prod];
- rxd->sd_len = rxb->tb_map->dm_segs[0].ds_len | RDES1_RCH;
+ rxd->sd_len = rxb->tb_map->dm_segs[0].ds_len;
+ rxd->sd_len |= sc->sc_enh_desc ? ERDES1_RCH : RDES1_RCH;
rxd->sd_addr = rxb->tb_map->dm_segs[0].ds_addr;
rxd->sd_status = RDES0_OWN;