Yanteng Si (15): net: stmmac: Move the atds flag to the stmmac_dma_cfg structure net: stmmac: Add multi-channel support net: stmmac: Export dwmac1000_dma_ops net: stmmac: dwmac-loongson: Drop useless platform data net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification net: stmmac: dwmac-loongson: Split up the platform data initialization net: stmmac: dwmac-loongson: Add ref and ptp clocks for Loongson net: stmmac: dwmac-loongson: Add phy mask for Loongson GMAC net: stmmac: dwmac-loongson: Add phy_interface for Loongson GMAC net: stmmac: dwmac-loongson: Add full PCI support net: stmmac: dwmac-loongson: Add loongson_dwmac_config_legacy net: stmmac: dwmac-loongson: Fixed failure to set network speed to 1000. net: stmmac: dwmac-loongson: Add Loongson GNET support net: stmmac: dwmac-loongson: Move disable_force flag to _gnet_date net: stmmac: dwmac-loongson: Add loongson module author
drivers/net/ethernet/stmicro/stmmac/common.h | 1 + .../ethernet/stmicro/stmmac/dwmac-loongson.c | 518 ++++++++++++++++-- .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 4 +- .../ethernet/stmicro/stmmac/dwmac1000_dma.c | 35 +- .../ethernet/stmicro/stmmac/dwmac100_dma.c | 2 +- .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 +- .../net/ethernet/stmicro/stmmac/dwmac_dma.h | 20 +- .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 30 +- .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 2 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 5 +- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +- include/linux/stmmac.h | 2 + 13 files changed, 535 insertions(+), 103 deletions(-)
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Alternate Descriptor Size (ATDS) is a part of the DMA-configs together with the PBL, ALL, AEME, etc so the structure is the most suitable place for it.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Reviewed-by: Serge Semin fancer.lancer@gmail.com Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 2 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 ++--- include/linux/stmmac.h | 1 + 8 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 63998d65fef8..031a83678c71 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -299,7 +299,7 @@ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) * Called from stmmac via stmmac_dma_ops->init */ static void sun8i_dwmac_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, int atds) + struct stmmac_dma_cfg *dma_cfg) { writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN); writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index daf79cdbd3ec..bb82ee9b855f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -71,7 +71,7 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) }
static void dwmac1000_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, int atds) + struct stmmac_dma_cfg *dma_cfg) { u32 value = readl(ioaddr + DMA_BUS_MODE); int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; @@ -98,7 +98,7 @@ static void dwmac1000_dma_init(void __iomem *ioaddr, if (dma_cfg->mixed_burst) value |= DMA_BUS_MODE_MB;
- if (atds) + if (dma_cfg->atds) value |= DMA_BUS_MODE_ATDS;
if (dma_cfg->aal) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index dea270f60cc3..f861babc06f9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -19,7 +19,7 @@ #include "dwmac_dma.h"
static void dwmac100_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, int atds) + struct stmmac_dma_cfg *dma_cfg) { /* Enable Application Access by writing to DMA CSR0 */ writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT), diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 84d3a8551b03..e0165358c4ac 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -153,7 +153,7 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv, }
static void dwmac4_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, int atds) + struct stmmac_dma_cfg *dma_cfg) { u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index dd2ab6185c40..7840bc403788 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -20,7 +20,7 @@ static int dwxgmac2_dma_reset(void __iomem *ioaddr) }
static void dwxgmac2_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg, int atds) + struct stmmac_dma_cfg *dma_cfg) { u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 78cdcd8d5e33..7d55b57a972a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -167,8 +167,7 @@ struct dma_features; struct stmmac_dma_ops { /* DMA core initialization */ int (*reset)(void __iomem *ioaddr); - void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, - int atds); + void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg); void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, u32 chan); void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 99c39d14ad5b..9ce91a0250f9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2944,7 +2944,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) struct stmmac_rx_queue *rx_q; struct stmmac_tx_queue *tx_q; u32 chan = 0; - int atds = 0; int ret = 0;
if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) { @@ -2953,7 +2952,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) }
if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) - atds = 1; + priv->plat->dma_cfg->atds = 1;
ret = stmmac_reset(priv, priv->ioaddr); if (ret) { @@ -2962,7 +2961,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) }
/* DMA Configuration */ - stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds); + stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
if (priv->plat->axi) stmmac_axi(priv, priv->ioaddr, priv->plat->axi); diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 5acb77968902..56f739340273 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -100,6 +100,7 @@ struct stmmac_dma_cfg { bool eame; bool multi_msi_en; bool dche; + bool atds; };
#define AXI_BLEN 7
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
DW GMAC v3.x multi-channels feature is implemented as multiple sets of the same CSRs. Here is only preliminary support, it will be useful for the driver further evolution and for the users having multi-channel DWGMAC v3.x devices.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- .../ethernet/stmicro/stmmac/dwmac1000_dma.c | 32 ++++++++++--------- .../net/ethernet/stmicro/stmmac/dwmac_dma.h | 20 ++++++++++-- .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 30 ++++++++--------- drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++-- 6 files changed, 55 insertions(+), 37 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 031a83678c71..1fa6406f2dd4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -395,7 +395,7 @@ static void sun8i_dwmac_dma_start_tx(struct stmmac_priv *priv, writel(v, ioaddr + EMAC_TX_CTL1); }
-static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr) +static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan) { u32 v;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index bb82ee9b855f..f161ec9ac490 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -70,15 +70,17 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) writel(value, ioaddr + DMA_AXI_BUS_MODE); }
-static void dwmac1000_dma_init(void __iomem *ioaddr, - struct stmmac_dma_cfg *dma_cfg) +static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan) { - u32 value = readl(ioaddr + DMA_BUS_MODE); int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; + u32 value;
- /* - * Set the DMA PBL (Programmable Burst Length) mode. + value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan)); + + /* Set the DMA PBL (Programmable Burst Length) mode. * * Note: before stmmac core 3.50 this mode bit was 4xPBL, and * post 3.5 mode bit acts as 8*PBL. @@ -104,10 +106,10 @@ static void dwmac1000_dma_init(void __iomem *ioaddr, if (dma_cfg->aal) value |= DMA_BUS_MODE_AAL;
- writel(value, ioaddr + DMA_BUS_MODE); + writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan));
/* Mask interrupts by writing to CSR7 */ - writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); + writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(chan)); }
static void dwmac1000_dma_init_rx(struct stmmac_priv *priv, @@ -116,7 +118,7 @@ static void dwmac1000_dma_init_rx(struct stmmac_priv *priv, dma_addr_t dma_rx_phy, u32 chan) { /* RX descriptor base address list must be written into DMA CSR3 */ - writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR); + writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RCV_BASE_ADDR(chan)); }
static void dwmac1000_dma_init_tx(struct stmmac_priv *priv, @@ -125,7 +127,7 @@ static void dwmac1000_dma_init_tx(struct stmmac_priv *priv, dma_addr_t dma_tx_phy, u32 chan) { /* TX descriptor base address list must be written into DMA CSR4 */ - writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR); + writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); }
static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz) @@ -153,7 +155,7 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv, void __iomem *ioaddr, int mode, u32 channel, int fifosz, u8 qmode) { - u32 csr6 = readl(ioaddr + DMA_CONTROL); + u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
if (mode == SF_DMA_MODE) { pr_debug("GMAC: enable RX store and forward mode\n"); @@ -175,14 +177,14 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv, /* Configure flow control based on rx fifo size */ csr6 = dwmac1000_configure_fc(csr6, fifosz);
- writel(csr6, ioaddr + DMA_CONTROL); + writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel)); }
static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv, void __iomem *ioaddr, int mode, u32 channel, int fifosz, u8 qmode) { - u32 csr6 = readl(ioaddr + DMA_CONTROL); + u32 csr6 = readl(ioaddr + DMA_CHAN_CONTROL(channel));
if (mode == SF_DMA_MODE) { pr_debug("GMAC: enable TX store and forward mode\n"); @@ -209,7 +211,7 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv, csr6 |= DMA_CONTROL_TTC_256; }
- writel(csr6, ioaddr + DMA_CONTROL); + writel(csr6, ioaddr + DMA_CHAN_CONTROL(channel)); }
static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv, @@ -271,12 +273,12 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr, static void dwmac1000_rx_watchdog(struct stmmac_priv *priv, void __iomem *ioaddr, u32 riwt, u32 queue) { - writel(riwt, ioaddr + DMA_RX_WATCHDOG); + writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue)); }
const struct stmmac_dma_ops dwmac1000_dma_ops = { .reset = dwmac_dma_reset, - .init = dwmac1000_dma_init, + .init_chan = dwmac1000_dma_init_channel, .init_rx_chan = dwmac1000_dma_init_rx, .init_tx_chan = dwmac1000_dma_init_tx, .axi = dwmac1000_dma_axi, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index 72672391675f..363a85469594 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -22,6 +22,23 @@ #define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */ #define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
+/* Following DMA defines are channels oriented */ +#define DMA_CHAN_BASE_OFFSET 0x100 + +static inline u32 dma_chan_base_addr(u32 base, u32 chan) +{ + return base + chan * DMA_CHAN_BASE_OFFSET; +} + +#define DMA_CHAN_XMT_POLL_DEMAND(chan) dma_chan_base_addr(DMA_XMT_POLL_DEMAND, chan) +#define DMA_CHAN_INTR_ENA(chan) dma_chan_base_addr(DMA_INTR_ENA, chan) +#define DMA_CHAN_CONTROL(chan) dma_chan_base_addr(DMA_CONTROL, chan) +#define DMA_CHAN_STATUS(chan) dma_chan_base_addr(DMA_STATUS, chan) +#define DMA_CHAN_BUS_MODE(chan) dma_chan_base_addr(DMA_BUS_MODE, chan) +#define DMA_CHAN_RCV_BASE_ADDR(chan) dma_chan_base_addr(DMA_RCV_BASE_ADDR, chan) +#define DMA_CHAN_TX_BASE_ADDR(chan) dma_chan_base_addr(DMA_TX_BASE_ADDR, chan) +#define DMA_CHAN_RX_WATCHDOG(chan) dma_chan_base_addr(DMA_RX_WATCHDOG, chan) + /* SW Reset */ #define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */
@@ -152,7 +169,7 @@ #define NUM_DWMAC1000_DMA_REGS 23 #define NUM_DWMAC4_DMA_REGS 27
-void dwmac_enable_dma_transmission(void __iomem *ioaddr); +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan); void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, @@ -168,5 +185,4 @@ void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan, u32 dir); int dwmac_dma_reset(void __iomem *ioaddr); - #endif /* __DWMAC_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 85e18f9a22f9..4846bf49c576 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -28,65 +28,65 @@ int dwmac_dma_reset(void __iomem *ioaddr) }
/* CSR1 enables the transmit DMA to check for new descriptor */ -void dwmac_enable_dma_transmission(void __iomem *ioaddr) +void dwmac_enable_dma_transmission(void __iomem *ioaddr, u32 chan) { - writel(1, ioaddr + DMA_XMT_POLL_DEMAND); + writel(1, ioaddr + DMA_CHAN_XMT_POLL_DEMAND(chan)); }
void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx) { - u32 value = readl(ioaddr + DMA_INTR_ENA); + u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
if (rx) value |= DMA_INTR_DEFAULT_RX; if (tx) value |= DMA_INTR_DEFAULT_TX;
- writel(value, ioaddr + DMA_INTR_ENA); + writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan)); }
void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx) { - u32 value = readl(ioaddr + DMA_INTR_ENA); + u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
if (rx) value &= ~DMA_INTR_DEFAULT_RX; if (tx) value &= ~DMA_INTR_DEFAULT_TX;
- writel(value, ioaddr + DMA_INTR_ENA); + writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan)); }
void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CONTROL); + u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); value |= DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); }
void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CONTROL); + u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); value &= ~DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); }
void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CONTROL); + u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); value |= DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CONTROL); + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); }
void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { - u32 value = readl(ioaddr + DMA_CONTROL); + u32 value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); value &= ~DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CONTROL); + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); }
#ifdef DWMAC_DMA_DEBUG @@ -165,7 +165,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); int ret = 0; /* read the status register (CSR5) */ - u32 intr_status = readl(ioaddr + DMA_STATUS); + u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
#ifdef DWMAC_DMA_DEBUG /* Enable it to monitor DMA rx/tx status in case of critical problems */ diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 7d55b57a972a..000fc51e8f32 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -189,7 +189,7 @@ struct stmmac_dma_ops { /* To track extra statistic (if supported) */ void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x, void __iomem *ioaddr); - void (*enable_dma_transmission) (void __iomem *ioaddr); + void (*enable_dma_transmission)(void __iomem *ioaddr, u32 chan); void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx); void (*disable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 9ce91a0250f9..8e8dee956ff6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2512,7 +2512,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) true, priv->mode, true, true, xdp_desc.len);
- stmmac_enable_dma_transmission(priv, priv->ioaddr); + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size); entry = tx_q->cur_tx; @@ -4630,7 +4630,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
- stmmac_enable_dma_transmission(priv, priv->ioaddr); + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
stmmac_flush_tx_descriptors(priv, queue); stmmac_tx_timer_arm(priv, queue); @@ -4849,7 +4849,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, u64_stats_update_end(&txq_stats->q_syncp); }
- stmmac_enable_dma_transmission(priv, priv->ioaddr); + stmmac_enable_dma_transmission(priv, priv->ioaddr, queue);
entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size); tx_q->cur_tx = entry;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
The loongson gnet will call it in the future.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Reviewed-by: Serge Semin fancer.lancer@gmail.com Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index f161ec9ac490..66c0c22908b1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -296,3 +296,4 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = { .get_hw_feature = dwmac1000_get_hw_feature, .rx_watchdog = dwmac1000_rx_watchdog, }; +EXPORT_SYMBOL_GPL(dwmac1000_dma_ops);
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
The multicast_filter_bins is initialized twice, it should be 256, let's drop the first useless assignment.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 9e40c28d453a..19906ea67636 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -15,9 +15,6 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat) plat->has_gmac = 1; plat->force_sf_dma_mode = 1;
- /* Set default value for multicast hash bins */ - plat->multicast_filter_bins = HASH_TABLE_SIZE; - /* Set default value for unicast filter entries */ plat->unicast_filter_entries = 1;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Just use PCI_DEVICE_DATA() macro for device identification, No changes to function functionality.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Reviewed-by: Serge Semin fancer.lancer@gmail.com Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 19906ea67636..4e0838db4259 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -9,6 +9,8 @@ #include <linux/of_irq.h> #include "stmmac.h"
+#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 + static int loongson_default_data(struct plat_stmmacenet_data *plat) { plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ @@ -210,7 +212,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend, loongson_dwmac_resume);
static const struct pci_device_id loongson_dwmac_id_table[] = { - { PCI_VDEVICE(LOONGSON, 0x7a03) }, + { PCI_DEVICE_DATA(LOONGSON, GMAC, NULL) }, {} }; MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Based on IP core classification, loongson has two types of network devices: GMAC and GNET. GMAC's ip_core id is 0x35/0x37, while GNET's ip_core id is 0x37/0x10.
Device tables:
device type pci_id snps_id channel ls2k1000 gmac 7a03 0x35/0x37 1 ls7a1000 gmac 7a03 0x35/0x37 1 ls2k2000 gnet 7a13 0x10 8 ls7a2000 gnet 7a13 0x37 1
The GMAC device only has a MAC chip inside and needs an external PHY chip;
To later distinguish 8-channel gnet devices from single-channel gnet/gmac devices, move rx_queues_to_use loongson_default_data to loongson_dwmac_probe(). Also move mac_interface to loongson_default_data().
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- .../ethernet/stmicro/stmmac/dwmac-loongson.c | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 4e0838db4259..904e288d0be0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -11,22 +11,20 @@
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
-static int loongson_default_data(struct plat_stmmacenet_data *plat) +static void loongson_default_data(struct plat_stmmacenet_data *plat) { plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ plat->has_gmac = 1; plat->force_sf_dma_mode = 1;
+ plat->mac_interface = PHY_INTERFACE_MODE_GMII; + /* Set default value for unicast filter entries */ plat->unicast_filter_entries = 1;
/* Set the maxmtu to a default of JUMBO_LEN */ plat->maxmtu = JUMBO_LEN;
- /* Set default number of RX and TX queues to use */ - plat->tx_queues_to_use = 1; - plat->rx_queues_to_use = 1; - /* Disable Priority config by default */ plat->tx_queues_cfg[0].use_prio = false; plat->rx_queues_cfg[0].use_prio = false; @@ -41,6 +39,12 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat) plat->dma_cfg->pblx8 = true;
plat->multicast_filter_bins = 256; +} + +static int loongson_gmac_data(struct plat_stmmacenet_data *plat) +{ + loongson_default_data(plat); + return 0; }
@@ -109,11 +113,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id }
plat->phy_interface = phy_mode; - plat->mac_interface = PHY_INTERFACE_MODE_GMII;
pci_set_master(pdev);
- loongson_default_data(plat); + loongson_gmac_data(plat); pci_enable_msi(pdev); memset(&res, 0, sizeof(res)); res.addr = pcim_iomap_table(pdev)[0]; @@ -138,6 +141,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id goto err_disable_msi; }
+ plat->tx_queues_to_use = 1; + plat->rx_queues_to_use = 1; + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) goto err_disable_msi;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
The ref/ptp clock of gmac(amd gnet) is 125000000.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 904e288d0be0..9f208f84c1e7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -32,6 +32,9 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat) /* Disable RX queues routing by default */ plat->rx_queues_cfg[0].pkt_route = 0x0;
+ plat->clk_ref_rate = 125000000; + plat->clk_ptp_rate = 125000000; + /* Default to phy auto-detection */ plat->phy_addr = -1;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
The phy mask of gmac(and gnet) is 0.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 9f208f84c1e7..f7618edf4a3a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -48,6 +48,8 @@ static int loongson_gmac_data(struct plat_stmmacenet_data *plat) { loongson_default_data(plat);
+ plat->mdio_bus_data->phy_mask = 0; + return 0; }
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
The mac_interface of gmac is PHY_INTERFACE_MODE_RGMII_ID.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index f7618edf4a3a..e989cb835340 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -49,6 +49,7 @@ static int loongson_gmac_data(struct plat_stmmacenet_data *plat) loongson_default_data(plat);
plat->mdio_bus_data->phy_mask = 0; + plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
return 0; }
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Current dwmac-loongson only support LS2K in the "probed with PCI and configured with DT" manner. Add LS7A support on which the devices are fully PCI (non-DT).
Others: LS2K is a SoC and LS7A is a bridge chip.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- .../ethernet/stmicro/stmmac/dwmac-loongson.c | 113 ++++++++++-------- 1 file changed, 65 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index e989cb835340..1022bceaa680 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -11,8 +11,17 @@
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
-static void loongson_default_data(struct plat_stmmacenet_data *plat) +struct stmmac_pci_info { + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); +}; + +static void loongson_default_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) { + /* Get bus_id, this can be overloaded later */ + plat->bus_id = (pci_domain_nr(pdev->bus) << 16) | + PCI_DEVID(pdev->bus->number, pdev->devfn); + plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -44,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat) plat->multicast_filter_bins = 256; }
-static int loongson_gmac_data(struct plat_stmmacenet_data *plat) +static int loongson_gmac_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) { - loongson_default_data(plat); + loongson_default_data(pdev, plat);
plat->mdio_bus_data->phy_mask = 0; plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID; @@ -54,20 +64,20 @@ static int loongson_gmac_data(struct plat_stmmacenet_data *plat) return 0; }
+static struct stmmac_pci_info loongson_gmac_pci_info = { + .setup = loongson_gmac_data, +}; + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct plat_stmmacenet_data *plat; + int ret, i, bus_id, phy_mode; + struct stmmac_pci_info *info; struct stmmac_resources res; struct device_node *np; - int ret, i, phy_mode;
np = dev_of_node(&pdev->dev);
- if (!np) { - pr_info("dwmac_loongson_pci: No OF node\n"); - return -ENODEV; - } - plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) return -ENOMEM; @@ -78,12 +88,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (!plat->mdio_bus_data) return -ENOMEM;
- plat->mdio_node = of_get_child_by_name(np, "mdio"); - if (plat->mdio_node) { - dev_info(&pdev->dev, "Found MDIO subnode\n"); - plat->mdio_bus_data->needs_reset = true; - } - plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); if (!plat->dma_cfg) { ret = -ENOMEM; @@ -107,46 +111,59 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id break; }
- plat->bus_id = of_alias_get_id(np, "ethernet"); - if (plat->bus_id < 0) - plat->bus_id = pci_dev_id(pdev); + pci_set_master(pdev);
- phy_mode = device_get_phy_mode(&pdev->dev); - if (phy_mode < 0) { - dev_err(&pdev->dev, "phy_mode not found\n"); - ret = phy_mode; + info = (struct stmmac_pci_info *)id->driver_data; + ret = info->setup(pdev, plat); + if (ret) goto err_disable_device; - }
- plat->phy_interface = phy_mode; - - pci_set_master(pdev); + if (np) { + plat->mdio_node = of_get_child_by_name(np, "mdio"); + if (plat->mdio_node) { + dev_info(&pdev->dev, "Found MDIO subnode\n"); + plat->mdio_bus_data->needs_reset = true; + } + + bus_id = of_alias_get_id(np, "ethernet"); + if (bus_id >= 0) + plat->bus_id = bus_id; + + phy_mode = device_get_phy_mode(&pdev->dev); + if (phy_mode < 0) { + dev_err(&pdev->dev, "phy_mode not found\n"); + ret = phy_mode; + goto err_disable_device; + } + plat->phy_interface = phy_mode; + + res.irq = of_irq_get_byname(np, "macirq"); + if (res.irq < 0) { + dev_err(&pdev->dev, "IRQ macirq not found\n"); + ret = -ENODEV; + goto err_disable_msi; + } + + res.wol_irq = of_irq_get_byname(np, "eth_wake_irq"); + if (res.wol_irq < 0) { + dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n"); + res.wol_irq = res.irq; + } + + res.lpi_irq = of_irq_get_byname(np, "eth_lpi"); + if (res.lpi_irq < 0) { + dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); + ret = -ENODEV; + goto err_disable_msi; + } + } else { + res.irq = pdev->irq; + }
- loongson_gmac_data(plat); pci_enable_msi(pdev); memset(&res, 0, sizeof(res)); res.addr = pcim_iomap_table(pdev)[0];
- res.irq = of_irq_get_byname(np, "macirq"); - if (res.irq < 0) { - dev_err(&pdev->dev, "IRQ macirq not found\n"); - ret = -ENODEV; - goto err_disable_msi; - } - - res.wol_irq = of_irq_get_byname(np, "eth_wake_irq"); - if (res.wol_irq < 0) { - dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n"); - res.wol_irq = res.irq; - } - - res.lpi_irq = of_irq_get_byname(np, "eth_lpi"); - if (res.lpi_irq < 0) { - dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); - ret = -ENODEV; - goto err_disable_msi; - } - plat->tx_queues_to_use = 1; plat->rx_queues_to_use = 1;
@@ -224,7 +241,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend, loongson_dwmac_resume);
static const struct pci_device_id loongson_dwmac_id_table[] = { - { PCI_DEVICE_DATA(LOONGSON, GMAC, NULL) }, + { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) }, {} }; MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Move res._irq to loongson_dwmac_config_legacy(). No function changes.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- .../ethernet/stmicro/stmmac/dwmac-loongson.c | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 1022bceaa680..df5899bec91a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -68,6 +68,38 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { .setup = loongson_gmac_data, };
+static int loongson_dwmac_config_legacy(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res, + struct device_node *np) +{ + if (np) { + res->irq = of_irq_get_byname(np, "macirq"); + if (res->irq < 0) { + dev_err(&pdev->dev, "IRQ macirq not found\n"); + return -ENODEV; + } + + res->wol_irq = of_irq_get_byname(np, "eth_wake_irq"); + if (res->wol_irq < 0) { + dev_info(&pdev->dev, + "IRQ eth_wake_irq not found, using macirq\n"); + res->wol_irq = res->irq; + } + + res->lpi_irq = of_irq_get_byname(np, "eth_lpi"); + if (res->lpi_irq < 0) { + dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); + return -ENODEV; + } + } else { + res->irq = pdev->irq; + res->wol_irq = res->irq; + } + + return 0; +} + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct plat_stmmacenet_data *plat; @@ -136,28 +168,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id goto err_disable_device; } plat->phy_interface = phy_mode; - - res.irq = of_irq_get_byname(np, "macirq"); - if (res.irq < 0) { - dev_err(&pdev->dev, "IRQ macirq not found\n"); - ret = -ENODEV; - goto err_disable_msi; - } - - res.wol_irq = of_irq_get_byname(np, "eth_wake_irq"); - if (res.wol_irq < 0) { - dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n"); - res.wol_irq = res.irq; - } - - res.lpi_irq = of_irq_get_byname(np, "eth_lpi"); - if (res.lpi_irq < 0) { - dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); - ret = -ENODEV; - goto err_disable_msi; - } - } else { - res.irq = pdev->irq; }
pci_enable_msi(pdev); @@ -167,6 +177,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id plat->tx_queues_to_use = 1; plat->rx_queues_to_use = 1;
+ ret = loongson_dwmac_config_legacy(pdev, plat, &res, np); + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) goto err_disable_msi;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
GNET devices with dev revision 0x00 do not support manually setting the speed to 1000.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 8 ++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 ++++++ include/linux/stmmac.h | 1 + 3 files changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index df5899bec91a..a16bba389417 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -10,6 +10,7 @@ #include "stmmac.h"
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 +#define PCI_DEVICE_ID_LOONGSON_GNET 0x7a13
struct stmmac_pci_info { int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); @@ -179,6 +180,13 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
ret = loongson_dwmac_config_legacy(pdev, plat, &res, np);
+ /* GNET devices with dev revision 0x00 do not support manually + * setting the speed to 1000. + */ + if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET && + pdev->revision == 0x00) + plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000; + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) goto err_disable_msi; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 521b1b5ffebb..cf83cc95169b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -412,6 +412,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev, return 0; }
+ if (priv->plat->flags & STMMAC_FLAG_DISABLE_FORCE_1000) { + if (cmd->base.speed == SPEED_1000 && + cmd->base.autoneg != AUTONEG_ENABLE) + return -EOPNOTSUPP; + } + return phylink_ethtool_ksettings_set(priv->phylink, cmd); }
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 56f739340273..482f56e27988 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -222,6 +222,7 @@ struct dwmac4_addrs { #define STMMAC_FLAG_RX_CLK_RUNS_IN_LPI BIT(10) #define STMMAC_FLAG_EN_TX_LPI_CLOCKGATING BIT(11) #define STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY BIT(12) +#define STMMAC_FLAG_DISABLE_FORCE_1000 BIT(13)
struct plat_stmmacenet_data { int bus_id;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
There are two types of Loongson DWGMAC. The first type shares the same register definitions and has similar logic as dwmac1000. The second type uses several different register definitions, we think it is necessary to distinguish rx and tx, so we split these bits into two.
Simply put, we split some single bit fields into double bits fileds:
Name Tx Rx
DMA_INTR_ENA_NIE = 0x00040000 | 0x00020000; DMA_INTR_ENA_AIE = 0x00010000 | 0x00008000; DMA_STATUS_NIS = 0x00040000 | 0x00020000; DMA_STATUS_AIS = 0x00010000 | 0x00008000; DMA_STATUS_FBI = 0x00002000 | 0x00001000;
Therefore, when using, TX and RX must be set at the same time.
How to use them: 1. Create the Loongson GNET-specific stmmac_dma_ops.dma_interrupt() stmmac_dma_ops.init_chan() methods in the dwmac-loongson.c driver. Adding all the Loongson-specific macros
2. Create a Loongson GNET-specific platform setup method with the next semantics: + allocate stmmac_dma_ops instance and initialize it with dwmac1000_dma_ops. + override the stmmac_dma_ops.{dma_interrupt, init_chan} with the pointers to the methods defined in 2. + allocate mac_device_info instance and initialize the mac_device_info.dma field with a pointer to the new stmmac_dma_ops instance. + initialize mac_device_info in a way it's done in dwmac1000_setup().
3. Initialize plat_stmmacenet_data.setup() with the pointer to the method created in 2.
GNET features:
Speeds: 10/100/1000Mbps DMA-descriptors type: enhanced L3/L4 filters availability: support VLAN hash table filter: support PHY-interface: GMII Remote Wake-up support: support Mac Management Counters (MMC): support Number of additional MAC addresses: 5 MAC Hash-based filter: support Number of ash table size: 256 DMA chennel number: 0x10 device is 8 and 0x37 device is 1
Others:
GNET integrates both MAC and PHY chips inside. GNET device: LS2K2000, LS7A2000, the chip connection between the mac and phy of these devices is not normal and requires two rounds of negotiation; LS7A2000 does not support half-duplex and multi-channel;
To enable multi-channel on LS2K2000, you need to turn off hardware checksum.
**Note**: Currently, only the LS2K2000's synopsys_id is 0x10, while the synopsys_id of other devices are 0x37.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + .../ethernet/stmicro/stmmac/dwmac-loongson.c | 380 +++++++++++++++++- 2 files changed, 370 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 4dbc076f72d6..f9a3f3321e59 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -29,6 +29,7 @@ /* Synopsys Core versions */ #define DWMAC_CORE_3_40 0x34 #define DWMAC_CORE_3_50 0x35 +#define DWMAC_CORE_3_70 0x37 #define DWMAC_CORE_4_00 0x40 #define DWMAC_CORE_4_10 0x41 #define DWMAC_CORE_5_00 0x50 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index a16bba389417..f90e7d6b1ac3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -8,9 +8,71 @@ #include <linux/device.h> #include <linux/of_irq.h> #include "stmmac.h" +#include "dwmac_dma.h" +#include "dwmac1000.h" + +/* Normal Loongson Tx Summary */ +#define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000 +/* Normal Loongson Rx Summary */ +#define DMA_INTR_ENA_NIE_RX_LOONGSON 0x00020000 + +#define DMA_INTR_NORMAL_LOONGSON (DMA_INTR_ENA_NIE_TX_LOONGSON | \ + DMA_INTR_ENA_NIE_RX_LOONGSON | \ + DMA_INTR_ENA_RIE | DMA_INTR_ENA_TIE) + +/* Abnormal Loongson Tx Summary */ +#define DMA_INTR_ENA_AIE_TX_LOONGSON 0x00010000 +/* Abnormal Loongson Rx Summary */ +#define DMA_INTR_ENA_AIE_RX_LOONGSON 0x00008000 + +#define DMA_INTR_ABNORMAL_LOONGSON (DMA_INTR_ENA_AIE_TX_LOONGSON | \ + DMA_INTR_ENA_AIE_RX_LOONGSON | \ + DMA_INTR_ENA_FBE | DMA_INTR_ENA_UNE) + +#define DMA_INTR_DEFAULT_MASK_LOONGSON (DMA_INTR_NORMAL_LOONGSON | \ + DMA_INTR_ABNORMAL_LOONGSON) + +/* Normal Loongson Tx Interrupt Summary */ +#define DMA_STATUS_NIS_TX_LOONGSON 0x00040000 +/* Normal Loongson Rx Interrupt Summary */ +#define DMA_STATUS_NIS_RX_LOONGSON 0x00020000 + +/* Abnormal Loongson Tx Interrupt Summary */ +#define DMA_STATUS_AIS_TX_LOONGSON 0x00010000 +/* Abnormal Loongson Rx Interrupt Summary */ +#define DMA_STATUS_AIS_RX_LOONGSON 0x00008000 + +/* Fatal Loongson Tx Bus Error Interrupt */ +#define DMA_STATUS_FBI_TX_LOONGSON 0x00002000 +/* Fatal Loongson Rx Bus Error Interrupt */ +#define DMA_STATUS_FBI_RX_LOONGSON 0x00001000 + +#define DMA_STATUS_MSK_COMMON_LOONGSON (DMA_STATUS_NIS_TX_LOONGSON | \ + DMA_STATUS_NIS_RX_LOONGSON | \ + DMA_STATUS_AIS_TX_LOONGSON | \ + DMA_STATUS_AIS_RX_LOONGSON | \ + DMA_STATUS_FBI_TX_LOONGSON | \ + DMA_STATUS_FBI_RX_LOONGSON) + +#define DMA_STATUS_MSK_RX_LOONGSON (DMA_STATUS_ERI | DMA_STATUS_RWT | \ + DMA_STATUS_RPS | DMA_STATUS_RU | \ + DMA_STATUS_RI | DMA_STATUS_OVF | \ + DMA_STATUS_MSK_COMMON_LOONGSON) + +#define DMA_STATUS_MSK_TX_LOONGSON (DMA_STATUS_ETI | DMA_STATUS_UNF | \ + DMA_STATUS_TJT | DMA_STATUS_TU | \ + DMA_STATUS_TPS | DMA_STATUS_TI | \ + DMA_STATUS_MSK_COMMON_LOONGSON)
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 #define PCI_DEVICE_ID_LOONGSON_GNET 0x7a13 +#define LOONGSON_DWMAC_CORE_1_00 0x10 /* Loongson custom IP */ +#define CHANNEL_NUM 8 + +struct loongson_data { + u32 gmac_verion; + struct device *dev; +};
struct stmmac_pci_info { int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); @@ -69,6 +131,168 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { .setup = loongson_gmac_data, };
+static void loongson_gnet_dma_init_channel(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + u32 chan) +{ + int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; + int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; + u32 value; + + value = readl(ioaddr + DMA_CHAN_BUS_MODE(chan)); + + if (dma_cfg->pblx8) + value |= DMA_BUS_MODE_MAXPBL; + + value |= DMA_BUS_MODE_USP; + value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK); + value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT); + value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); + + /* Set the Fixed burst mode */ + if (dma_cfg->fixed_burst) + value |= DMA_BUS_MODE_FB; + + /* Mixed Burst has no effect when fb is set */ + if (dma_cfg->mixed_burst) + value |= DMA_BUS_MODE_MB; + + if (dma_cfg->atds) + value |= DMA_BUS_MODE_ATDS; + + if (dma_cfg->aal) + value |= DMA_BUS_MODE_AAL; + + writel(value, ioaddr + DMA_CHAN_BUS_MODE(chan)); + + /* Mask interrupts by writing to CSR7 */ + writel(DMA_INTR_DEFAULT_MASK_LOONGSON, ioaddr + + DMA_CHAN_INTR_ENA(chan)); +} + +static int loongson_gnet_dma_interrupt(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_extra_stats *x, + u32 chan, u32 dir) +{ + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); + u32 abnor_intr_status; + u32 nor_intr_status; + u32 fb_intr_status; + u32 intr_status; + int ret = 0; + + /* read the status register (CSR5) */ + intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan)); + + if (dir == DMA_DIR_RX) + intr_status &= DMA_STATUS_MSK_RX_LOONGSON; + else if (dir == DMA_DIR_TX) + intr_status &= DMA_STATUS_MSK_TX_LOONGSON; + + nor_intr_status = intr_status & (DMA_STATUS_NIS_TX_LOONGSON | + DMA_STATUS_NIS_RX_LOONGSON); + abnor_intr_status = intr_status & (DMA_STATUS_AIS_TX_LOONGSON | + DMA_STATUS_AIS_RX_LOONGSON); + fb_intr_status = intr_status & (DMA_STATUS_FBI_TX_LOONGSON | + DMA_STATUS_FBI_RX_LOONGSON); + + /* ABNORMAL interrupts */ + if (unlikely(abnor_intr_status)) { + if (unlikely(intr_status & DMA_STATUS_UNF)) { + ret = tx_hard_error_bump_tc; + x->tx_undeflow_irq++; + } + if (unlikely(intr_status & DMA_STATUS_TJT)) + x->tx_jabber_irq++; + if (unlikely(intr_status & DMA_STATUS_OVF)) + x->rx_overflow_irq++; + if (unlikely(intr_status & DMA_STATUS_RU)) + x->rx_buf_unav_irq++; + if (unlikely(intr_status & DMA_STATUS_RPS)) + x->rx_process_stopped_irq++; + if (unlikely(intr_status & DMA_STATUS_RWT)) + x->rx_watchdog_irq++; + if (unlikely(intr_status & DMA_STATUS_ETI)) + x->tx_early_irq++; + if (unlikely(intr_status & DMA_STATUS_TPS)) { + x->tx_process_stopped_irq++; + ret = tx_hard_error; + } + if (unlikely(fb_intr_status)) { + x->fatal_bus_error_irq++; + ret = tx_hard_error; + } + } + /* TX/RX NORMAL interrupts */ + if (likely(nor_intr_status)) { + if (likely(intr_status & DMA_STATUS_RI)) { + u32 value = readl(ioaddr + DMA_INTR_ENA); + /* to schedule NAPI on real RIE event. */ + if (likely(value & DMA_INTR_ENA_RIE)) { + u64_stats_update_begin(&stats->syncp); + u64_stats_inc(&stats->rx_normal_irq_n[chan]); + u64_stats_update_end(&stats->syncp); + ret |= handle_rx; + } + } + if (likely(intr_status & DMA_STATUS_TI)) { + u64_stats_update_begin(&stats->syncp); + u64_stats_inc(&stats->tx_normal_irq_n[chan]); + u64_stats_update_end(&stats->syncp); + ret |= handle_tx; + } + if (unlikely(intr_status & DMA_STATUS_ERI)) + x->rx_early_irq++; + } + /* Optional hardware blocks, interrupts should be disabled */ + if (unlikely(intr_status & + (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) + pr_warn("%s: unexpected status %08x\n", __func__, intr_status); + + /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ + writel((intr_status & 0x7ffff), ioaddr + DMA_CHAN_STATUS(chan)); + + return ret; +} + +static void loongson_gnet_fix_speed(void *priv, unsigned int speed, + unsigned int mode) +{ + struct loongson_data *ld = (struct loongson_data *)priv; + struct net_device *ndev = dev_get_drvdata(ld->dev); + struct stmmac_priv *ptr = netdev_priv(ndev); + + /* The controller and PHY don't work well together. + * We need to use the PS bit to check if the controller's status + * is correct and reset PHY if necessary. + * MAC_CTRL_REG.15 is defined by the GMAC_CONTROL_PS macro. + */ + if (speed == SPEED_1000) { + if (readl(ptr->ioaddr + MAC_CTRL_REG) & + GMAC_CONTROL_PS) + /* Word around hardware bug, restart autoneg */ + phy_restart_aneg(ndev->phydev); + } +} + +static int loongson_gnet_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) +{ + loongson_default_data(pdev, plat); + + plat->phy_interface = PHY_INTERFACE_MODE_GMII; + plat->mdio_bus_data->phy_mask = ~(u32)BIT(2); + plat->fix_mac_speed = loongson_gnet_fix_speed; + + return 0; +} + +static struct stmmac_pci_info loongson_gnet_pci_info = { + .setup = loongson_gnet_data, +}; + static int loongson_dwmac_config_legacy(struct pci_dev *pdev, struct plat_stmmacenet_data *plat, struct stmmac_resources *res, @@ -101,12 +325,125 @@ static int loongson_dwmac_config_legacy(struct pci_dev *pdev, return 0; }
+static int loongson_dwmac_config_msi(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res, + struct device_node *np) +{ + int i, ret, vecs; + + vecs = roundup_pow_of_two(CHANNEL_NUM * 2 + 1); + ret = pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI); + if (ret < 0) { + dev_info(&pdev->dev, + "MSI enable failed, Fallback to legacy interrupt\n"); + return loongson_dwmac_config_legacy(pdev, plat, res, np); + } + + res->irq = pci_irq_vector(pdev, 0); + res->wol_irq = 0; + + /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx | + * --------- ----- -------- -------- ... -------- -------- + * IRQ NUM | 0 | 1 | 2 | ... | 15 | 16 | + */ + for (i = 0; i < CHANNEL_NUM; i++) { + res->rx_irq[CHANNEL_NUM - 1 - i] = + pci_irq_vector(pdev, 1 + i * 2); + res->tx_irq[CHANNEL_NUM - 1 - i] = + pci_irq_vector(pdev, 2 + i * 2); + } + + plat->flags |= STMMAC_FLAG_MULTI_MSI_EN; + + return 0; +} + +static struct mac_device_info *loongson_dwmac_setup(void *apriv) +{ + struct stmmac_priv *priv = apriv; + struct mac_device_info *mac; + struct stmmac_dma_ops *dma; + struct loongson_data *ld; + struct pci_dev *pdev; + + ld = priv->plat->bsp_priv; + pdev = to_pci_dev(priv->device); + + mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL); + if (!mac) + return NULL; + + dma = devm_kzalloc(priv->device, sizeof(*dma), GFP_KERNEL); + if (!dma) + return NULL; + + /* The original IP-core version is 0x37 in all Loongson GNET + * (ls2k2000 and ls7a2000), but the GNET HW designers have changed the + * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the Loongson + * ls2k2000 MAC to emphasize the differences: multiple DMA-channels, + * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the + * original value so the correct HW-interface would be selected. + */ + if (ld->gmac_verion == LOONGSON_DWMAC_CORE_1_00) { + priv->synopsys_id = DWMAC_CORE_3_70; + *dma = dwmac1000_dma_ops; + dma->init_chan = loongson_gnet_dma_init_channel; + dma->dma_interrupt = loongson_gnet_dma_interrupt; + mac->dma = dma; + } + + priv->dev->priv_flags |= IFF_UNICAST_FLT; + + /* Pre-initialize the respective "mac" fields as it's done in + * dwmac1000_setup() + */ + mac->pcsr = priv->ioaddr; + mac->multicast_filter_bins = priv->plat->multicast_filter_bins; + mac->unicast_filter_entries = priv->plat->unicast_filter_entries; + mac->mcast_bits_log2 = 0; + + if (mac->multicast_filter_bins) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + /* The GMAC devices with PCI ID 0x7a03 does not support any pause mode. + * The GNET devices without CORE ID 0x10 does not support half-duplex. + */ + if (pdev->device == PCI_DEVICE_ID_LOONGSON_GMAC) { + mac->link.caps = MAC_10 | MAC_100 | MAC_1000; + } else { + if (ld->gmac_verion == LOONGSON_DWMAC_CORE_1_00) + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000; + else + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10FD | MAC_100FD | MAC_1000FD; + } + + mac->link.duplex = GMAC_CONTROL_DM; + mac->link.speed10 = GMAC_CONTROL_PS; + mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES; + mac->link.speed1000 = 0; + mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES; + mac->mii.addr = GMAC_MII_ADDR; + mac->mii.data = GMAC_MII_DATA; + mac->mii.addr_shift = 11; + mac->mii.addr_mask = 0x0000F800; + mac->mii.reg_shift = 6; + mac->mii.reg_mask = 0x000007C0; + mac->mii.clk_csr_shift = 2; + mac->mii.clk_csr_mask = GENMASK(5, 2); + + return mac; +} + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct plat_stmmacenet_data *plat; int ret, i, bus_id, phy_mode; struct stmmac_pci_info *info; struct stmmac_resources res; + struct loongson_data *ld; struct device_node *np;
np = dev_of_node(&pdev->dev); @@ -122,10 +459,12 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id return -ENOMEM;
plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); - if (!plat->dma_cfg) { - ret = -ENOMEM; - goto err_put_node; - } + if (!plat->dma_cfg) + return -ENOMEM; + + ld = devm_kzalloc(&pdev->dev, sizeof(*ld), GFP_KERNEL); + if (!ld) + return -ENOMEM;
/* Enable pci device */ ret = pci_enable_device(pdev); @@ -171,14 +510,34 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id plat->phy_interface = phy_mode; }
- pci_enable_msi(pdev); + plat->bsp_priv = ld; + plat->setup = loongson_dwmac_setup; + ld->dev = &pdev->dev; + memset(&res, 0, sizeof(res)); res.addr = pcim_iomap_table(pdev)[0]; + ld->gmac_verion = readl(res.addr + GMAC_VERSION) & 0xff; + + switch (ld->gmac_verion) { + case LOONGSON_DWMAC_CORE_1_00: + plat->rx_queues_to_use = CHANNEL_NUM; + plat->tx_queues_to_use = CHANNEL_NUM; + + /* Only channel 0 supports checksum, + * so turn off checksum to enable multiple channels. + */ + for (i = 1; i < CHANNEL_NUM; i++) + plat->tx_queues_cfg[i].coe_unsupported = 1;
- plat->tx_queues_to_use = 1; - plat->rx_queues_to_use = 1; + ret = loongson_dwmac_config_msi(pdev, plat, &res, np); + break; + default: /* 0x35 device and 0x37 device. */ + plat->tx_queues_to_use = 1; + plat->rx_queues_to_use = 1;
- ret = loongson_dwmac_config_legacy(pdev, plat, &res, np); + ret = loongson_dwmac_config_legacy(pdev, plat, &res, np); + break; + }
/* GNET devices with dev revision 0x00 do not support manually * setting the speed to 1000. @@ -189,12 +548,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) - goto err_disable_msi; + goto err_disable_device;
return ret;
-err_disable_msi: - pci_disable_msi(pdev); err_disable_device: pci_disable_device(pdev); err_put_node: @@ -262,6 +619,7 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
static const struct pci_device_id loongson_dwmac_id_table[] = { { PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) }, + { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) }, {} }; MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
We've already introduced loongson_gnet_data(), so the STMMAC_FLAG_DISABLE_FORCE_1000 should be take away from loongson_dwmac_probe().
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- .../net/ethernet/stmicro/stmmac/dwmac-loongson.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index f90e7d6b1ac3..35600a38b074 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -286,6 +286,12 @@ static int loongson_gnet_data(struct pci_dev *pdev, plat->mdio_bus_data->phy_mask = ~(u32)BIT(2); plat->fix_mac_speed = loongson_gnet_fix_speed;
+ /* GNET devices with dev revision 0x00 do not support manually + * setting the speed to 1000. + */ + if (pdev->revision == 0x00) + plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000; + return 0; }
@@ -539,13 +545,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id break; }
- /* GNET devices with dev revision 0x00 do not support manually - * setting the speed to 1000. - */ - if (pdev->device == PCI_DEVICE_ID_LOONGSON_GNET && - pdev->revision == 0x00) - plat->flags |= STMMAC_FLAG_DISABLE_FORCE_1000; - ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) goto err_disable_device;
From: Yanteng Si siyanteng@loongson.cn
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RPAR
Reference: https://lore.kernel.org/all/cover.1714046812.git.siyanteng@loongson.cn
--------------------------------
Add Yanteng Si as MODULE_AUTHOR of Loongson DWMAC PCI driver.
Signed-off-by: Feiyang Chen chenfeiyang@loongson.cn Signed-off-by: Yinggang Gu guyinggang@loongson.cn Signed-off-by: Yanteng Si siyanteng@loongson.cn Signed-off-by: Ming Wang wangming01@loongson.cn --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 35600a38b074..f03d78385ed9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -637,4 +637,5 @@ module_pci_driver(loongson_dwmac_driver);
MODULE_DESCRIPTION("Loongson DWMAC PCI driver"); MODULE_AUTHOR("Qing Zhang zhangqing@loongson.cn"); +MODULE_AUTHOR("Yanteng Si siyanteng@loongson.cn"); MODULE_LICENSE("GPL v2");
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8435 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/8435 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U...