Add support for XGMAC2 in stmmac
Subsystems (5)
v4 cover Add support for XGMAC2 in stmmac
This series adds support for 10Gigabit IP in stmmac. The IP is called XGMAC2 and has many similarities with GMAC4. Due to this, its relatively easy to incorporate this new IP into stmmac driver by adding a new block and filling the necessary callbacks.
The functionality added by this series is still reduced but its only a starting point which will later be expanded.
I splitted the patches into funcionality and to ease the review. Only the patch 8/9 really enables the XGMAC2 block by adding a new compatible string.
Version 4 addresses review comments of Florian Fainelli and Rob Herring.
NOTE: Although the IP supports 10G, for now it was only possible to test it at 1G speed due to 10G PHY HW shipping problems. Here follows iperf3 results at 1G:
---
# iperf3 -c 192.168.0.10 Connecting to host 192.168.0.10, port 5201 [ 4] local 192.168.0.3 port 39178 connected to 192.168.0.10 port 5201 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 110 MBytes 920 Mbits/sec 0 482 KBytes [ 4] 1.00-2.00 sec 113 MBytes 946 Mbits/sec 0 482 KBytes [ 4] 2.00-3.00 sec 112 MBytes 937 Mbits/sec 0 482 KBytes [ 4] 3.00-4.00 sec 113 MBytes 946 Mbits/sec 0 482 KBytes [ 4] 4.00-5.00 sec 112 MBytes 935 Mbits/sec 0 482 KBytes [ 4] 5.00-6.00 sec 113 MBytes 946 Mbits/sec 0 482 KBytes [ 4] 6.00-7.00 sec 112 MBytes 937 Mbits/sec 0 482 KBytes [ 4] 7.00-8.00 sec 113 MBytes 946 Mbits/sec 0 482 KBytes [ 4] 8.00-9.00 sec 112 MBytes 937 Mbits/sec 0 482 KBytes [ 4] 9.00-10.00 sec 113 MBytes 946 Mbits/sec 0 482 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 1.09 GBytes 940 Mbits/sec 0 sender [ 4] 0.00-10.00 sec 1.09 GBytes 938 Mbits/sec receiver ---
Jose Abreu (9):
net: stmmac: Add XGMAC 2.10 HWIF entry
net: stmmac: Add MAC related callbacks for XGMAC2
net: stmmac: Add DMA related callbacks for XGMAC2
net: stmmac: Add descriptor related callbacks for XGMAC2
net: stmmac: Add MDIO related functions for XGMAC2
net: stmmac: Add PTP support for XGMAC2
net: stmmac: Integrate XGMAC into main driver flow
net: stmmac: Add the bindings parsing for XGMAC2
dt-bindings: net: stmmac: Add the bindings documentation for XGMAC2.
Documentation/devicetree/bindings/net/stmmac.txt | 5 +- drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +- drivers/net/ethernet/stmicro/stmmac/common.h | 17 +- .../net/ethernet/stmicro/stmmac/dwmac-generic.c | 2 + drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 228 ++++++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 371 +++++++++++++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 280 ++++++++++++++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 411 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 31 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 67 +++- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 133 ++++++- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 + drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 6 +- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 1 + include/linux/stmmac.h | 1 + 16 files changed, 1529 insertions(+), 36 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
Signature · 1 line
2.7.4
PATCH v4 1/9 net: stmmac: Add XGMAC 2.10 HWIF entry
Add a new entry to HWIF table for XGMAC 2.10. For now we fill it with empty callbacks which will be added in posterior patches.
--- drivers/net/ethernet/stmicro/stmmac/common.h | 14 +++++++------ drivers/net/ethernet/stmicro/stmmac/hwif.c | 31 ++++++++++++++++++++++++++-- include/linux/stmmac.h | 1 + 3 files changed, 38 insertions(+), 8 deletions(-)
drivers/net/ethernet/stmicro/stmmac/common.h +8 -6
@@ -36,12 +36,14 @@#include "mmc.h" /* Synopsys Core versions */ -#define DWMAC_CORE_3_40 0x34 -#define DWMAC_CORE_3_50 0x35 -#define DWMAC_CORE_4_00 0x40 -#define DWMAC_CORE_4_10 0x41 -#define DWMAC_CORE_5_00 0x50 -#define DWMAC_CORE_5_10 0x51 +#define DWMAC_CORE_3_40 0x34 +#define DWMAC_CORE_3_50 0x35 +#define DWMAC_CORE_4_00 0x40 +#define DWMAC_CORE_4_10 0x41 +#define DWMAC_CORE_5_00 0x50 +#define DWMAC_CORE_5_10 0x51 +#define DWXGMAC_CORE_2_10 0x21 +#define STMMAC_CHAN0 0/* Always supported and default for all chips */ /* These need to be power of two, and >= 4 */
drivers/net/ethernet/stmicro/stmmac/hwif.c +29 -2
@@ -72,6 +72,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv) static const struct stmmac_hwif_entry { bool gmac; bool gmac4; + bool xgmac; u32 min_id; const struct stmmac_regs_off regs; const void *desc;
@@ -87,6 +88,7 @@ static const struct stmmac_hwif_entry { { .gmac = false, .gmac4 = false, + .xgmac = false, .min_id = 0, .regs = { .ptp_off = PTP_GMAC3_X_OFFSET,
@@ -103,6 +105,7 @@ static const struct stmmac_hwif_entry { }, { .gmac = true, .gmac4 = false, + .xgmac = false, .min_id = 0, .regs = { .ptp_off = PTP_GMAC3_X_OFFSET,
@@ -119,6 +122,7 @@ static const struct stmmac_hwif_entry { }, { .gmac = false, .gmac4 = true, + .xgmac = false, .min_id = 0, .regs = { .ptp_off = PTP_GMAC4_OFFSET,
@@ -135,6 +139,7 @@ static const struct stmmac_hwif_entry { }, { .gmac = false, .gmac4 = true, + .xgmac = false, .min_id = DWMAC_CORE_4_00, .regs = { .ptp_off = PTP_GMAC4_OFFSET,
@@ -151,6 +156,7 @@ static const struct stmmac_hwif_entry { }, { .gmac = false, .gmac4 = true, + .xgmac = false, .min_id = DWMAC_CORE_4_10, .regs = { .ptp_off = PTP_GMAC4_OFFSET,
@@ -167,6 +173,7 @@ static const struct stmmac_hwif_entry { }, { .gmac = false, .gmac4 = true, + .xgmac = false, .min_id = DWMAC_CORE_5_10, .regs = { .ptp_off = PTP_GMAC4_OFFSET,
@@ -180,11 +187,29 @@ static const struct stmmac_hwif_entry { .tc = &dwmac510_tc_ops, .setup = dwmac4_setup, .quirks = NULL, - } + }, { + .gmac = false, + .gmac4 = false, + .xgmac = true, + .min_id = DWXGMAC_CORE_2_10, + .regs = { + .ptp_off = 0, + .mmc_off = 0, + }, + .desc = NULL, + .dma = NULL, + .mac = NULL, + .hwtimestamp = NULL, + .mode = NULL, + .tc = NULL, + .setup = NULL, + .quirks = NULL, + }, };int stmmac_hwif_init (struct stmmac_priv *priv) { +bool needs_xgmac = priv->plat->has_xgmac;bool needs_gmac4 = priv->plat->has_gmac4;bool needs_gmac = priv->plat->has_gmac;const struct stmmac_hwif_entry *entry;
@@ -195,7 +220,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)if (needs_gmac) { id =stmmac_get_id (priv,GMAC_VERSION ); - }else if (needs_gmac4) { + }else if (needs_gmac4 || needs_xgmac) { id =stmmac_get_id (priv,GMAC4_VERSION ); }else { id =0 ;
@@ -229,6 +254,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)continue ;if (needs_gmac4 ^ entry->gmac4)continue ; +if (needs_xgmac ^ entry->xgmac) +continue ;/* Use synopsys_id var because some setups can override this */ if (priv->synopsys_id < entry->min_id)continue ;
include/linux/stmmac.h +1 -0
@@ -190,5 +190,6 @@ struct plat_stmmacenet_data {bool tso_en;int mac_port_sel_speed;bool en_tx_lpi_clockgating; + int has_xgmac; };#endif
Signature · 1 line
2.7.4
PATCH v4 2/9 net: stmmac: Add MAC related callbacks for XGMAC2
In reply to Jose AbreuAdd the MAC related callbacks for the new IP block XGMAC2.
--- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 3 + drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 141 ++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 371 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 4 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + 6 files changed, 519 insertions(+), 3 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/Makefile +1 -1
@@ -5,7 +5,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ - stmmac_tc.o $(stmmac-y) + stmmac_tc.o dwxgmac2_core.o $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
drivers/net/ethernet/stmicro/stmmac/common.h +3 -0
@@ -400,6 +400,8 @@ struct mac_link {u32 speed10;u32 speed100;u32 speed1000; +u32 speed2500; +u32 speed10000;u32 duplex; };
@@ -441,6 +443,7 @@ struct stmmac_rx_routing {int dwmac100_setup (struct stmmac_priv *priv);int dwmac1000_setup (struct stmmac_priv *priv);int dwmac4_setup (struct stmmac_priv *priv); +int dwxgmac2_setup (struct stmmac_priv *priv);void stmmac_set_mac_addr (void __iomem *ioaddr,u8 addr[6 ],unsigned int high,unsigned int low);
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h new file +141 -0
141 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c new file +371 -0
371 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/hwif.c +2 -2
@@ -198,11 +198,11 @@ static const struct stmmac_hwif_entry { }, .desc = NULL, .dma = NULL, - .mac = NULL, + .mac = &dwxgmac210_ops, .hwtimestamp = NULL, .mode = NULL, .tc = NULL, - .setup = NULL, + .setup = dwxgmac2_setup, .quirks = NULL, }, };
drivers/net/ethernet/stmicro/stmmac/hwif.h +1 -0
@@ -479,6 +479,7 @@ extern const struct stmmac_ops dwmac410_ops;extern const struct stmmac_dma_ops dwmac410_dma_ops;extern const struct stmmac_ops dwmac510_ops;extern const struct stmmac_tc_ops dwmac510_tc_ops; +extern const struct stmmac_ops dwxgmac210_ops;#define GMAC_VERSION 0x00000020/* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110/* GMAC4+ CORE Version */
Signature · 1 line
2.7.4
PATCH v4 3/9 net: stmmac: Add DMA related callbacks for XGMAC2
In reply to Jose AbreuAdd the DMA related callbacks for the new IP block XGMAC2.
---
Changes from v3:
- Clear previous BLEN values (Florian)
--- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 57 +++ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 411 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 2 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + 5 files changed, 471 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/Makefile +1 -1
@@ -5,7 +5,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ - stmmac_tc.o dwxgmac2_core.o $(stmmac-y) + stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +57 -0
61 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c new file +411 -0
411 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/hwif.c +1 -1
@@ -197,7 +197,7 @@ static const struct stmmac_hwif_entry { .mmc_off = 0, }, .desc = NULL, - .dma = NULL, + .dma = &dwxgmac210_dma_ops, .mac = &dwxgmac210_ops, .hwtimestamp = NULL, .mode = NULL,
drivers/net/ethernet/stmicro/stmmac/hwif.h +1 -0
@@ -480,6 +480,7 @@ extern const struct stmmac_dma_ops dwmac410_dma_ops;extern const struct stmmac_ops dwmac510_ops;extern const struct stmmac_tc_ops dwmac510_tc_ops;extern const struct stmmac_ops dwxgmac210_ops; +extern const struct stmmac_dma_ops dwxgmac210_dma_ops;#define GMAC_VERSION 0x00000020/* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110/* GMAC4+ CORE Version */
Signature · 1 line
2.7.4
PATCH v4 4/9 net: stmmac: Add descriptor related callbacks for XGMAC2
In reply to Jose AbreuAdd the descriptor related callbacks for the new IP block XGMAC2.
--- drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 30 +++ .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 280 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 2 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + 5 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
drivers/net/ethernet/stmicro/stmmac/Makefile +2 -1
@@ -5,7 +5,8 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ - stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o $(stmmac-y) + stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ + $(stmmac-y) # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +30 -0
@@ -195,4 +195,34 @@#define XGMAC_TPS BIT(1)#define XGMAC_TI BIT(0) +/* Descriptors */ +#define XGMAC_TDES2_IOC BIT(31) +#define XGMAC_TDES2_TTSE BIT(30) +#define XGMAC_TDES2_B2L GENMASK(29, 16) +#define XGMAC_TDES2_B2L_SHIFT 16 +#define XGMAC_TDES2_B1L GENMASK(13, 0) +#define XGMAC_TDES3_OWN BIT(31) +#define XGMAC_TDES3_CTXT BIT(30) +#define XGMAC_TDES3_FD BIT(29) +#define XGMAC_TDES3_LD BIT(28) +#define XGMAC_TDES3_CPC GENMASK(27, 26) +#define XGMAC_TDES3_CPC_SHIFT 26 +#define XGMAC_TDES3_TCMSSV BIT(26) +#define XGMAC_TDES3_THL GENMASK(22, 19) +#define XGMAC_TDES3_THL_SHIFT 19 +#define XGMAC_TDES3_TSE BIT(18) +#define XGMAC_TDES3_CIC GENMASK(17, 16) +#define XGMAC_TDES3_CIC_SHIFT 16 +#define XGMAC_TDES3_TPL GENMASK(17, 0) +#define XGMAC_TDES3_FL GENMASK(14, 0) +#define XGMAC_RDES3_OWN BIT(31) +#define XGMAC_RDES3_CTXT BIT(30) +#define XGMAC_RDES3_IOC BIT(30) +#define XGMAC_RDES3_LD BIT(28) +#define XGMAC_RDES3_CDA BIT(27) +#define XGMAC_RDES3_ES BIT(15) +#define XGMAC_RDES3_PL GENMASK(13, 0) +#define XGMAC_RDES3_TSD BIT(6) +#define XGMAC_RDES3_TSA BIT(4) +#endif /* __STMMAC_DWXGMAC2_H__ */
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c new file +280 -0
280 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/hwif.c +1 -1
@@ -196,7 +196,7 @@ static const struct stmmac_hwif_entry { .ptp_off = 0, .mmc_off = 0, }, - .desc = NULL, + .desc = &dwxgmac210_desc_ops, .dma = &dwxgmac210_dma_ops, .mac = &dwxgmac210_ops, .hwtimestamp = NULL,
drivers/net/ethernet/stmicro/stmmac/hwif.h +1 -0
@@ -481,6 +481,7 @@ extern const struct stmmac_ops dwmac510_ops;extern const struct stmmac_tc_ops dwmac510_tc_ops;extern const struct stmmac_ops dwxgmac210_ops;extern const struct stmmac_dma_ops dwxgmac210_dma_ops; +extern const struct stmmac_desc_ops dwxgmac210_desc_ops;#define GMAC_VERSION 0x00000020/* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110/* GMAC4+ CORE Version */
Signature · 1 line
2.7.4
PATCH v4 5/9 net: stmmac: Add MDIO related functions for XGMAC2
In reply to Jose AbreuAdd the MDIO related funcionalities for the new IP block XGMAC2.
---
Changes from v3:
- Check if unsupported phy_addr was specified in DT
- Clear C22 reg before setting the bit (Florian)
- Limit the number of possible phys to 4 (for now) (Florian)
Changes from v2:
- Use helper to set C22 (Andrew)
- Wait for bus free before setting C22 reg (Andrew)
Changes from v1:
- Remove C45 support (Andrew)
- Add define for bits (Andrew)
- Remove uneeded cast (Andrew)
- Use different callbacks instead of if's (Andrew)
--- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 133 +++++++++++++++++++++- 1 file changed, 129 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +129 -4
@@ -29,6 +29,7 @@#include <linux/phy.h> #include <linux/slab.h> +#include "dwxgmac2.h" #include "stmmac.h" #define MII_BUSY 0x00000001
@@ -39,6 +40,115 @@#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) +/* XGMAC defines */ +#define MII_XGMAC_SADDR BIT(18) +#define MII_XGMAC_CMD_SHIFT 16 +#define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT) +#define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT) +#define MII_XGMAC_BUSY BIT(22) +#define MII_XGMAC_MAX_C22ADDR 3 +#define MII_XGMAC_C22P_MASK GENMASK(MII_XGMAC_MAX_C22ADDR, 0) + +static int stmmac_xgmac2_c22_format (struct stmmac_priv *priv,int phyaddr, +int phyreg,u32 *hw_addr) +{ +unsigned int mii_data = priv->hw->mii.data; +u32 tmp; + +/* HW does not support C22 addr >= 4 */ +if (phyaddr >MII_XGMAC_MAX_C22ADDR ) +return -ENODEV ; +/* Wait until any existing MII operation is complete */ +if (readl_poll_timeout (priv->ioaddr + mii_data, tmp, + !(tmp &MII_XGMAC_BUSY ),100 ,10000 )) +return -EBUSY ; + +/* Set port as Clause 22 */ + tmp =readl (priv->ioaddr +XGMAC_MDIO_C22P ); + tmp &= ~MII_XGMAC_C22P_MASK ; + tmp |=BIT (phyaddr); +writel (tmp, priv->ioaddr +XGMAC_MDIO_C22P ); + + *hw_addr = (phyaddr <<16 ) | (phyreg &0x1f ); +return 0 ; +} + +static int stmmac_xgmac2_mdio_read (struct mii_bus *bus,int phyaddr,int phyreg) +{ +struct net_device *ndev = bus->priv; +struct stmmac_priv *priv =netdev_priv (ndev); +unsigned int mii_address = priv->hw->mii.addr; +unsigned int mii_data = priv->hw->mii.data; +u32 tmp, addr, value =MII_XGMAC_BUSY ; +int ret; + +if (phyreg &MII_ADDR_C45 ) { +return -EOPNOTSUPP ; + }else { + ret =stmmac_xgmac2_c22_format (priv, phyaddr, phyreg, &addr); +if (ret) +return ret; + } + + value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) + & priv->hw->mii.clk_csr_mask; + value |=MII_XGMAC_SADDR |MII_XGMAC_READ ; + +/* Wait until any existing MII operation is complete */ +if (readl_poll_timeout (priv->ioaddr + mii_data, tmp, + !(tmp &MII_XGMAC_BUSY ),100 ,10000 )) +return -EBUSY ; + +/* Set the MII address register to read */ +writel (addr, priv->ioaddr + mii_address); +writel (value, priv->ioaddr + mii_data); + +/* Wait until any existing MII operation is complete */ +if (readl_poll_timeout (priv->ioaddr + mii_data, tmp, + !(tmp &MII_XGMAC_BUSY ),100 ,10000 )) +return -EBUSY ; + +/* Read the data from the MII data register */ +return readl (priv->ioaddr + mii_data) &GENMASK (15 ,0 ); +} + +static int stmmac_xgmac2_mdio_write (struct mii_bus *bus,int phyaddr, +int phyreg,u16 phydata) +{ +struct net_device *ndev = bus->priv; +struct stmmac_priv *priv =netdev_priv (ndev); +unsigned int mii_address = priv->hw->mii.addr; +unsigned int mii_data = priv->hw->mii.data; +u32 addr, tmp, value =MII_XGMAC_BUSY ; +int ret; + +if (phyreg &MII_ADDR_C45 ) { +return -EOPNOTSUPP ; + }else { + ret =stmmac_xgmac2_c22_format (priv, phyaddr, phyreg, &addr); +if (ret) +return ret; + } + + value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) + & priv->hw->mii.clk_csr_mask; + value |= phydata |MII_XGMAC_SADDR ; + value |=MII_XGMAC_WRITE ; + +/* Wait until any existing MII operation is complete */ +if (readl_poll_timeout (priv->ioaddr + mii_data, tmp, + !(tmp &MII_XGMAC_BUSY ),100 ,10000 )) +return -EBUSY ; + +/* Set the MII address register to write */ +writel (addr, priv->ioaddr + mii_address); +writel (value, priv->ioaddr + mii_data); + +/* Wait until any existing MII operation is complete */ +return readl_poll_timeout (priv->ioaddr + mii_data, tmp, + !(tmp &MII_XGMAC_BUSY ),100 ,10000 ); +} +/** * stmmac_mdio_read * @bus: points to the mii_bus structure
@@ -205,7 +315,7 @@ int stmmac_mdio_register(struct net_device *ndev)struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;struct device_node *mdio_node = priv->plat->mdio_node;struct device *dev = ndev->dev.parent; -int addr, found; +int addr, found, max_addr;if (!mdio_bus_data)return 0 ;
@@ -223,8 +333,23 @@ int stmmac_mdio_register(struct net_device *ndev)#endif new_bus->name ="stmmac" ; - new_bus->read = &stmmac_mdio_read; - new_bus->write = &stmmac_mdio_write; + +if (priv->plat->has_xgmac) { + new_bus->read = &stmmac_xgmac2_mdio_read; + new_bus->write = &stmmac_xgmac2_mdio_write; + +/* Right now only C22 phys are supported */ + max_addr =MII_XGMAC_MAX_C22ADDR +1 ; + +/* Check if DT specified an unsupported phy addr */ +if (priv->plat->phy_addr >MII_XGMAC_MAX_C22ADDR ) +dev_err (dev,"Unsupported phy_addr (max=%d)\n" , +MII_XGMAC_MAX_C22ADDR ); + }else { + new_bus->read = &stmmac_mdio_read; + new_bus->write = &stmmac_mdio_write; + max_addr =PHY_MAX_ADDR ; + } new_bus->reset = &stmmac_mdio_reset; snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
@@ -243,7 +368,7 @@ int stmmac_mdio_register(struct net_device *ndev) goto bus_register_done; found =0 ; -for (addr =0 ; addr <PHY_MAX_ADDR ; addr++) { +for (addr =0 ; addr < max_addr; addr++) {struct phy_device *phydev =mdiobus_get_phy (new_bus, addr);if (!phydev)
Signature · 1 line
2.7.4
PATCH v4 6/9 net: stmmac: Add PTP support for XGMAC2
In reply to Jose AbreuXGMAC2 uses the same engine of timestamping as GMAC4. Let's use the same callbacks.
--- drivers/net/ethernet/stmicro/stmmac/hwif.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 6 ++++-- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 1 + 3 files changed, 7 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/hwif.c +2 -2
@@ -193,13 +193,13 @@ static const struct stmmac_hwif_entry { .xgmac = true, .min_id = DWXGMAC_CORE_2_10, .regs = { - .ptp_off = 0, + .ptp_off = PTP_XGMAC_OFFSET, .mmc_off = 0, }, .desc = &dwxgmac210_desc_ops, .dma = &dwxgmac210_dma_ops, .mac = &dwxgmac210_ops, - .hwtimestamp = NULL, + .hwtimestamp = &stmmac_ptp, .mode = NULL, .tc = NULL, .setup = dwxgmac2_setup,
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +4 -2
@@ -71,6 +71,9 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)u32 sec, nsec;u32 quotient, reminder;int neg_adj =0 ; +bool xmac; + + xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;if (delta <0 ) { neg_adj =1 ;
@@ -82,8 +85,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) nsec = reminder;spin_lock_irqsave (&priv->ptp_lock, flags); -stmmac_adjust_systime (priv, priv->ptpaddr, sec, nsec, neg_adj, - priv->plat->has_gmac4); +stmmac_adjust_systime (priv, priv->ptpaddr, sec, nsec, neg_adj, xmac);spin_unlock_irqrestore (&priv->ptp_lock, flags);return 0 ;
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +1 -0
@@ -21,6 +21,7 @@#ifndef __STMMAC_PTP_H__#define __STMMAC_PTP_H__ +#define PTP_XGMAC_OFFSET 0xd00#define PTP_GMAC4_OFFSET 0xb00#define PTP_GMAC3_X_OFFSET 0x700
Signature · 1 line
2.7.4
PATCH v4 7/9 net: stmmac: Integrate XGMAC into main driver flow
In reply to Jose AbreuNow that we have all the XGMAC related callbacks, lets start integrating this IP block into main driver.
Also, we corrected the initialization flow to only start DMA after setting descriptors length.
---
Changes from v1:
- Correct flow of initialization
- Remove 2.5G/10G support (Andrew)
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 67 ++++++++++++++++------- 1 file changed, 48 insertions(+), 19 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +48 -19
@@ -51,6 +51,7 @@#include <linux/reset.h> #include <linux/of_mdio.h> #include "dwmac1000.h" +#include "dwxgmac2.h" #include "hwif.h" #define STMMAC_ALIGN (x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
@@ -262,6 +263,21 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)else priv->clk_csr =0 ; } + +if (priv->plat->has_xgmac) { +if (clk_rate >400000000 ) + priv->clk_csr =0x5 ; +else if (clk_rate >350000000 ) + priv->clk_csr =0x4 ; +else if (clk_rate >300000000 ) + priv->clk_csr =0x3 ; +else if (clk_rate >250000000 ) + priv->clk_csr =0x2 ; +else if (clk_rate >150000000 ) + priv->clk_csr =0x1 ; +else + priv->clk_csr =0x0 ; + } }static void print_pkt (unsigned char *buf,int len)
@@ -498,7 +514,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,if (!priv->hwts_rx_en)return ;/* For GMAC4, the valid timestamp is from CTX next desc. */ -if (priv->plat->has_gmac4) +if (priv->plat->has_gmac4 || priv->plat->has_xgmac) desc = np;/* Check if timestamp is available */
@@ -540,6 +556,9 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)u32 ts_event_en =0 ;u32 value =0 ;u32 sec_inc; +bool xmac; + + xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {netdev_alert (priv->dev,"No support for HW time stamping\n" );
@@ -575,7 +594,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)/* PTP v1, UDP, any kind of event packet */ config.rx_filter =HWTSTAMP_FILTER_PTP_V1_L4_EVENT ;/* take time stamp for all event messages */ -if (priv->plat->has_gmac4) +if (xmac) snap_type_sel =PTP_GMAC4_TCR_SNAPTYPSEL_1 ;else snap_type_sel =PTP_TCR_SNAPTYPSEL_1 ;
@@ -610,7 +629,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) config.rx_filter =HWTSTAMP_FILTER_PTP_V2_L4_EVENT ; ptp_v2 =PTP_TCR_TSVER2ENA ;/* take time stamp for all event messages */ -if (priv->plat->has_gmac4) +if (xmac) snap_type_sel =PTP_GMAC4_TCR_SNAPTYPSEL_1 ;else snap_type_sel =PTP_TCR_SNAPTYPSEL_1 ;
@@ -647,7 +666,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) config.rx_filter =HWTSTAMP_FILTER_PTP_V2_EVENT ; ptp_v2 =PTP_TCR_TSVER2ENA ;/* take time stamp for all event messages */ -if (priv->plat->has_gmac4) +if (xmac) snap_type_sel =PTP_GMAC4_TCR_SNAPTYPSEL_1 ;else snap_type_sel =PTP_TCR_SNAPTYPSEL_1 ;
@@ -718,7 +737,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)/* program Sub Second Increment reg */ stmmac_config_sub_second_increment (priv, priv->ptpaddr, priv->plat->clk_ptp_rate, - priv->plat->has_gmac4, &sec_inc); + xmac, &sec_inc); temp =div_u64 (1000000000ULL , sec_inc);/* Store sub second increment and flags for later use */
@@ -755,12 +774,14 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)*/ static int stmmac_init_ptp (struct stmmac_priv *priv) { +bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; +if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))return -EOPNOTSUPP ; priv->adv_ts =0 ; -/* Check if adv_ts can be enabled for dwmac 4.x core */ -if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp) +/* Check if adv_ts can be enabled for dwmac 4.x / xgmac core */ +if (xmac && priv->dma_cap.atime_stamp) priv->adv_ts =1 ;/* Dwmac 3.x core with extend_desc can support adv_ts */ else if (priv->extend_desc && priv->dma_cap.atime_stamp)
@@ -2173,6 +2194,12 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)return ret; } +/* DMA Configuration */ +stmmac_dma_init (priv, priv->ioaddr, priv->plat->dma_cfg, atds); + +if (priv->plat->axi) +stmmac_axi (priv, priv->ioaddr, priv->plat->axi); +/* DMA RX Channel Configuration */ for (chan =0 ; chan < rx_channels_count; chan++) { rx_q = &priv->rx_queue[chan];
@@ -2203,12 +2230,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)for (chan =0 ; chan < dma_csr_ch; chan++)stmmac_init_chan (priv, priv->ioaddr, priv->plat->dma_cfg, chan); -/* DMA Configuration */ -stmmac_dma_init (priv, priv->ioaddr, priv->plat->dma_cfg, atds); - -if (priv->plat->axi) -stmmac_axi (priv, priv->ioaddr, priv->plat->axi); -return ret; }
@@ -2526,9 +2547,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)netdev_warn (priv->dev,"%s: failed debugFS registration\n" , __func__);#endif -/* Start the ball rolling... */ -stmmac_start_all_dma (priv); - priv->tx_lpi_timer =STMMAC_DEFAULT_TWT_LS ;if (priv->use_riwt) {
@@ -2549,6 +2567,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)stmmac_enable_tso (priv, priv->ioaddr,1 , chan); } +/* Start the ball rolling... */ +stmmac_start_all_dma (priv); +return 0 ; }
@@ -3305,6 +3326,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)int coe = priv->hw->rx_csum;unsigned int next_entry;unsigned int count =0 ; +bool xmac; + + xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;if (netif_msg_rx_status (priv)) {void *rx_head;
@@ -3406,7 +3430,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)* in case of GMAC4 because it needs * to refill the used descriptors, always. */ -if (unlikely (!priv->plat->has_gmac4 && +if (unlikely (!xmac && ((frame_len < priv->rx_copybreak) ||stmmac_rx_threshold_count (rx_q)))) { skb = netdev_alloc_skb_ip_align(priv->dev,
@@ -3642,7 +3666,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)u32 tx_cnt = priv->plat->tx_queues_to_use;u32 queues_count;u32 queue; +bool xmac; + xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt;if (priv->irq_wake)
@@ -3661,7 +3687,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)return IRQ_HANDLED ;/* To handle GMAC own interrupts */ -if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { +if ((priv->plat->has_gmac) || xmac) {int status =stmmac_host_irq_status (priv, priv->hw, &priv->xstats);int mtl_status;
@@ -4269,6 +4295,8 @@ int stmmac_dvr_probe(struct device *device, ndev->min_mtu =ETH_ZLEN -ETH_HLEN ;if ((priv->plat->enh_desc) || (priv->synopsys_id >=DWMAC_CORE_4_00 )) ndev->max_mtu =JUMBO_LEN ; +else if (priv->plat->has_xgmac) + ndev->max_mtu =XGMAC_JUMBO_LEN ;else ndev->max_mtu =SKB_MAX_HEAD (NET_SKB_PAD +NET_IP_ALIGN );/* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu
@@ -4290,7 +4318,8 @@ int stmmac_dvr_probe(struct device *device,* has to be disable and this can be done by passing the * riwt_off field from the platform. */ -if ((priv->synopsys_id >=DWMAC_CORE_3_50 ) && (!priv->plat->riwt_off)) { +if (((priv->synopsys_id >=DWMAC_CORE_3_50 ) || + (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) { priv->use_riwt =1 ;dev_info (priv->device,"Enable RX Mitigation via HW Watchdog Timer\n" );
Signature · 1 line
2.7.4
PATCH v4 8/9 net: stmmac: Add the bindings parsing for XGMAC2
In reply to Jose AbreuAdd the bindings parsing for XGMAC2 IP block.
--- drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 2 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 ++++++ 2 files changed, 8 insertions(+)
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +2 -0
@@ -78,6 +78,8 @@ static const struct of_device_id dwmac_generic_match[] = { { .compatible = "snps,dwmac-4.00"}, { .compatible = "snps,dwmac-4.10a"}, { .compatible = "snps,dwmac"}, + { .compatible = "snps,dwxgmac-2.10"}, + { .compatible = "snps,dwxgmac"}, { } };MODULE_DEVICE_TABLE (of, dwmac_generic_match);
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +6 -0
@@ -486,6 +486,12 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) plat->force_sf_dma_mode =1 ; } +if (of_device_is_compatible (np,"snps,dwxgmac" )) { + plat->has_xgmac =1 ; + plat->pmt =1 ; + plat->tso_en =of_property_read_bool (np,"snps,tso" ); + } + dma_cfg =devm_kzalloc (&pdev->dev,sizeof (*dma_cfg),GFP_KERNEL );if (!dma_cfg) {
Signature · 1 line
2.7.4
PATCH v4 9/9 dt-bindings: net: stmmac: Add the bindings documentation for XGMAC2.
In reply to Jose AbreuAdds the documentation for XGMAC2 DT bindings.
---
Changes from v3:
- Remove driver mention (Rob)
Changes from v1:
- Correct header, now we also support 2.5/10G.
- Add missing '>' (Sergei)
--- Documentation/devicetree/bindings/net/stmmac.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/net/stmmac.txt +3 -2
@@ -1,7 +1,8 @@ -* STMicroelectronics 10/100/1000 Ethernet driver (GMAC) +* STMicroelectronics 10/100/1000/2500/10000 Ethernet (GMAC/XGMAC) Required properties: -- compatible: Should be "snps,dwmac-<ip_version>", "snps,dwmac" +- compatible: Should be "snps,dwmac-<ip_version>", "snps,dwmac" or + "snps,dwxgmac-<ip_version>", "snps,dwxgmac". For backwards compatibility: "st,spear600-gmac" is also supported. - reg: Address and length of the register set for the device - interrupt-parent: Should be the phandle for the interrupt controller
Signature · 1 line
2.7.4
David Miller
maintainerFrom: Jose Abreu <[email protected]>
Date: Wed, 8 Aug 2018 09:04:28 +0100
Quoted 1 line
This series adds support for 10Gigabit IP in stmmac.
Series applied, thanks Jose.