-/* $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>
#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.
#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)
#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;
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;
uint32_t axi_config;
uint32_t mode, pbl;
uint32_t version;
+ uint32_t feature;
int node;
sc->sc_node = faa->fa_node;
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)
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)
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),
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);
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);
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;
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;