From: Daniel Thompson XGMAC 2.x and 3.x are architecturally very similar. That means that for everything except one erratum we can simply use the XGMAC 2.x callback functions in the stmmac_dma_ops structure. Only the set_rx_ring_len callback is specific to XGMAC 3.01. It limits the number of outstanding write requests that can be serviced per DMA. The other erratum addressed in this patch is simply a comment to ensure that a feature that stmmac doesn't currently use is not enabled without contemplating the errata. Signed-off-by: Daniel Thompson Signed-off-by: Alex Elder --- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 3 ++ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 9b0b5cc619556..bcf59ad8a1939 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -374,6 +374,8 @@ #define XGMAC_DMA_CH_RxDESC_TAIL_LPTR(x) (0x0000312c + (0x80 * (x))) #define XGMAC_DMA_CH_TxDESC_RING_LEN(x) (0x00003130 + (0x80 * (x))) #define XGMAC_DMA_CH_RxDESC_RING_LEN(x) (0x00003134 + (0x80 * (x))) +#define XGMAC_OWRQ GENMASK(25, 24) +#define XGMAC_RDRL GENMASK(15, 0) #define XGMAC_DMA_CH_INT_EN(x) (0x00003138 + (0x80 * (x))) #define XGMAC_NIE BIT(15) #define XGMAC_AIE BIT(14) @@ -463,6 +465,7 @@ extern const struct stmmac_ops dwxgmac210_ops; extern const struct stmmac_ops dwxlgmac2_ops; extern const struct stmmac_dma_ops dwxgmac210_dma_ops; +extern const struct stmmac_dma_ops dwxgmac301_dma_ops; extern const struct stmmac_desc_ops dwxgmac210_desc_ops; #endif /* __STMMAC_DWXGMAC2_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index a84601ac32153..584ab28d7f7f5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -38,6 +38,14 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr, value = u32_replace_bits(value, XGMAC_INTM_MODE1, XGMAC_INTM_MASK); + /* + * A friendly warning to future adventurers. If Descriptor Posted + * Write support, which is off by default, is ever enabled then be sure + * to make it optional. This is required by errata for at least XGMAC + * 3.01A... and the XGMAC 2.x and 3.x are architecturally similar so we + * use dwxgmac2 support for the 3.x family as well. + */ + writel(value, ioaddr + XGMAC_DMA_MODE); } @@ -490,6 +498,20 @@ static void dwxgmac2_set_rx_ring_len(struct stmmac_priv *priv, writel(len, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(chan)); } +static void dwxgmac301_set_rx_ring_len(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 len, u32 chan) +{ + u32 val = FIELD_PREP(XGMAC_RDRL, len); + + /* + * Reduce the number of outstanding write requests to 3 (from default + * of 4). This is an errata workaround for XGMAC 3.01a. + */ + val |= FIELD_PREP(XGMAC_OWRQ, 3); + + writel(val, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(chan)); +} + static void dwxgmac2_set_tx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr, u32 len, u32 chan) { @@ -619,3 +641,34 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = { .enable_sph = dwxgmac2_enable_sph, .enable_tbs = dwxgmac2_enable_tbs, }; + +/* All but one field are the same as dwxgmac210_dma_ops */ +const struct stmmac_dma_ops dwxgmac301_dma_ops = { + .reset = dwxgmac2_dma_reset, + .init = dwxgmac2_dma_init, + .init_chan = dwxgmac2_dma_init_chan, + .init_rx_chan = dwxgmac2_dma_init_rx_chan, + .init_tx_chan = dwxgmac2_dma_init_tx_chan, + .axi = dwxgmac2_dma_axi, + .dump_regs = dwxgmac2_dma_dump_regs, + .dma_rx_mode = dwxgmac2_dma_rx_mode, + .dma_tx_mode = dwxgmac2_dma_tx_mode, + .enable_dma_irq = dwxgmac2_enable_dma_irq, + .disable_dma_irq = dwxgmac2_disable_dma_irq, + .start_tx = dwxgmac2_dma_start_tx, + .stop_tx = dwxgmac2_dma_stop_tx, + .start_rx = dwxgmac2_dma_start_rx, + .stop_rx = dwxgmac2_dma_stop_rx, + .dma_interrupt = dwxgmac2_dma_interrupt, + .get_hw_feature = dwxgmac2_get_hw_feature, + .rx_watchdog = dwxgmac2_rx_watchdog, + .set_rx_ring_len = dwxgmac301_set_rx_ring_len, /* Only 3.01 */ + .set_tx_ring_len = dwxgmac2_set_tx_ring_len, + .set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr, + .set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr, + .enable_tso = dwxgmac2_enable_tso, + .qmode = dwxgmac2_qmode, + .set_bfsize = dwxgmac2_set_bfsize, + .enable_sph = dwxgmac2_enable_sph, + .enable_tbs = dwxgmac2_enable_tbs, +}; -- 2.51.0