diff options
Diffstat (limited to 'target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch')
-rw-r--r-- | target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch | 1923 |
1 files changed, 0 insertions, 1923 deletions
diff --git a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch b/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch deleted file mode 100644 index 12b8ad04e1..0000000000 --- a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch +++ /dev/null @@ -1,1923 +0,0 @@ ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -145,6 +145,17 @@ config DWMAC_SUNXI - This selects Allwinner SoC glue layer support for the - stmmac device driver. This driver is used for A20/A31 - GMAC ethernet controller. -+ -+config DWMAC_SUN8I -+ tristate "Allwinner sun8i GMAC support" -+ default ARCH_SUNXI -+ depends on OF && (ARCH_SUNXI || COMPILE_TEST) -+ ---help--- -+ Support for Allwinner H3 A83T A64 EMAC ethernet controllers. -+ -+ This selects Allwinner SoC glue layer support for the -+ stmmac device driver. This driver is used for H3/A83T/A64 -+ EMAC ethernet controller. - endif - - config STMMAC_PCI ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-alt - obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o - obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o - obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o -+obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o - obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o - obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o - stmmac-platform-objs:= stmmac_platform.o ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -549,9 +549,11 @@ extern const struct stmmac_hwtimestamp s - extern const struct stmmac_mode_ops dwmac4_ring_mode_ops; - - struct mac_link { -- int port; -- int duplex; -- int speed; -+ u32 speed_mask; -+ u32 speed10; -+ u32 speed100; -+ u32 speed1000; -+ u32 duplex; - }; - - struct mii_regs { ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -270,7 +270,10 @@ static int socfpga_dwmac_set_phy_mode(st - ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); - ctrl |= val << reg_shift; - -- if (dwmac->f2h_ptp_ref_clk) { -+ if (dwmac->f2h_ptp_ref_clk || -+ phymode == PHY_INTERFACE_MODE_MII || -+ phymode == PHY_INTERFACE_MODE_GMII || -+ phymode == PHY_INTERFACE_MODE_SGMII) { - ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); - regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, - &module); ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -0,0 +1,1007 @@ -+/* -+ * dwmac-sun8i.c - Allwinner sun8i DWMAC specific glue layer -+ * -+ * Copyright (C) 2017 Corentin Labbe <clabbe.montjoie@gmail.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/clk.h> -+#include <linux/io.h> -+#include <linux/iopoll.h> -+#include <linux/mfd/syscon.h> -+#include <linux/module.h> -+#include <linux/of_device.h> -+#include <linux/of_mdio.h> -+#include <linux/of_net.h> -+#include <linux/phy.h> -+#include <linux/platform_device.h> -+#include <linux/regulator/consumer.h> -+#include <linux/regmap.h> -+#include <linux/stmmac.h> -+ -+#include "stmmac.h" -+#include "stmmac_platform.h" -+ -+/* General notes on dwmac-sun8i: -+ * Locking: no locking is necessary in this file because all necessary locking -+ * is done in the "stmmac files" -+ */ -+ -+/* struct emac_variant - Descrive dwmac-sun8i hardware variant -+ * @default_syscon_value: The default value of the EMAC register in syscon -+ * This value is used for disabling properly EMAC -+ * and used as a good starting value in case of the -+ * boot process(uboot) leave some stuff. -+ * @internal_phy: Does the MAC embed an internal PHY -+ * @support_mii: Does the MAC handle MII -+ * @support_rmii: Does the MAC handle RMII -+ * @support_rgmii: Does the MAC handle RGMII -+ */ -+struct emac_variant { -+ u32 default_syscon_value; -+ int internal_phy; -+ bool support_mii; -+ bool support_rmii; -+ bool support_rgmii; -+}; -+ -+/* struct sunxi_priv_data - hold all sunxi private data -+ * @tx_clk: reference to MAC TX clock -+ * @ephy_clk: reference to the optional EPHY clock for the internal PHY -+ * @regulator: reference to the optional regulator -+ * @rst_ephy: reference to the optional EPHY reset for the internal PHY -+ * @variant: reference to the current board variant -+ * @regmap: regmap for using the syscon -+ * @use_internal_phy: Does the current PHY choice imply using the internal PHY -+ */ -+struct sunxi_priv_data { -+ struct clk *tx_clk; -+ struct clk *ephy_clk; -+ struct regulator *regulator; -+ struct reset_control *rst_ephy; -+ const struct emac_variant *variant; -+ struct regmap *regmap; -+ bool use_internal_phy; -+}; -+ -+static const struct emac_variant emac_variant_h3 = { -+ .default_syscon_value = 0x58000, -+ .internal_phy = PHY_INTERFACE_MODE_MII, -+ .support_mii = true, -+ .support_rmii = true, -+ .support_rgmii = true -+}; -+ -+static const struct emac_variant emac_variant_v3s = { -+ .default_syscon_value = 0x38000, -+ .internal_phy = PHY_INTERFACE_MODE_MII, -+ .support_mii = true -+}; -+ -+static const struct emac_variant emac_variant_a83t = { -+ .default_syscon_value = 0, -+ .internal_phy = 0, -+ .support_mii = true, -+ .support_rgmii = true -+}; -+ -+static const struct emac_variant emac_variant_a64 = { -+ .default_syscon_value = 0, -+ .internal_phy = 0, -+ .support_mii = true, -+ .support_rmii = true, -+ .support_rgmii = true -+}; -+ -+#define EMAC_BASIC_CTL0 0x00 -+#define EMAC_BASIC_CTL1 0x04 -+#define EMAC_INT_STA 0x08 -+#define EMAC_INT_EN 0x0C -+#define EMAC_TX_CTL0 0x10 -+#define EMAC_TX_CTL1 0x14 -+#define EMAC_TX_FLOW_CTL 0x1C -+#define EMAC_TX_DESC_LIST 0x20 -+#define EMAC_RX_CTL0 0x24 -+#define EMAC_RX_CTL1 0x28 -+#define EMAC_RX_DESC_LIST 0x34 -+#define EMAC_RX_FRM_FLT 0x38 -+#define EMAC_MDIO_CMD 0x48 -+#define EMAC_MDIO_DATA 0x4C -+#define EMAC_MACADDR_HI(reg) (0x50 + (reg) * 8) -+#define EMAC_MACADDR_LO(reg) (0x54 + (reg) * 8) -+#define EMAC_TX_DMA_STA 0xB0 -+#define EMAC_TX_CUR_DESC 0xB4 -+#define EMAC_TX_CUR_BUF 0xB8 -+#define EMAC_RX_DMA_STA 0xC0 -+#define EMAC_RX_CUR_DESC 0xC4 -+#define EMAC_RX_CUR_BUF 0xC8 -+ -+/* Use in EMAC_BASIC_CTL0 */ -+#define EMAC_DUPLEX_FULL BIT(0) -+#define EMAC_LOOPBACK BIT(1) -+#define EMAC_SPEED_1000 0 -+#define EMAC_SPEED_100 (0x03 << 2) -+#define EMAC_SPEED_10 (0x02 << 2) -+ -+/* Use in EMAC_BASIC_CTL1 */ -+#define EMAC_BURSTLEN_SHIFT 24 -+ -+/* Used in EMAC_RX_FRM_FLT */ -+#define EMAC_FRM_FLT_RXALL BIT(0) -+#define EMAC_FRM_FLT_CTL BIT(13) -+#define EMAC_FRM_FLT_MULTICAST BIT(16) -+ -+/* Used in RX_CTL1*/ -+#define EMAC_RX_MD BIT(1) -+#define EMAC_RX_TH_MASK GENMASK(4, 5) -+#define EMAC_RX_TH_32 0 -+#define EMAC_RX_TH_64 (0x1 << 4) -+#define EMAC_RX_TH_96 (0x2 << 4) -+#define EMAC_RX_TH_128 (0x3 << 4) -+#define EMAC_RX_DMA_EN BIT(30) -+#define EMAC_RX_DMA_START BIT(31) -+ -+/* Used in TX_CTL1*/ -+#define EMAC_TX_MD BIT(1) -+#define EMAC_TX_NEXT_FRM BIT(2) -+#define EMAC_TX_TH_MASK GENMASK(8, 10) -+#define EMAC_TX_TH_64 0 -+#define EMAC_TX_TH_128 (0x1 << 8) -+#define EMAC_TX_TH_192 (0x2 << 8) -+#define EMAC_TX_TH_256 (0x3 << 8) -+#define EMAC_TX_DMA_EN BIT(30) -+#define EMAC_TX_DMA_START BIT(31) -+ -+/* Used in RX_CTL0 */ -+#define EMAC_RX_RECEIVER_EN BIT(31) -+#define EMAC_RX_DO_CRC BIT(27) -+#define EMAC_RX_FLOW_CTL_EN BIT(16) -+ -+/* Used in TX_CTL0 */ -+#define EMAC_TX_TRANSMITTER_EN BIT(31) -+ -+/* Used in EMAC_TX_FLOW_CTL */ -+#define EMAC_TX_FLOW_CTL_EN BIT(0) -+ -+/* Used in EMAC_INT_STA */ -+#define EMAC_TX_INT BIT(0) -+#define EMAC_TX_DMA_STOP_INT BIT(1) -+#define EMAC_TX_BUF_UA_INT BIT(2) -+#define EMAC_TX_TIMEOUT_INT BIT(3) -+#define EMAC_TX_UNDERFLOW_INT BIT(4) -+#define EMAC_TX_EARLY_INT BIT(5) -+#define EMAC_RX_INT BIT(8) -+#define EMAC_RX_BUF_UA_INT BIT(9) -+#define EMAC_RX_DMA_STOP_INT BIT(10) -+#define EMAC_RX_TIMEOUT_INT BIT(11) -+#define EMAC_RX_OVERFLOW_INT BIT(12) -+#define EMAC_RX_EARLY_INT BIT(13) -+#define EMAC_RGMII_STA_INT BIT(16) -+ -+#define MAC_ADDR_TYPE_DST BIT(31) -+ -+/* H3 specific bits for EPHY */ -+#define H3_EPHY_ADDR_SHIFT 20 -+#define H3_EPHY_CLK_SEL BIT(18) /* 1: 24MHz, 0: 25MHz */ -+#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */ -+#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */ -+#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */ -+ -+/* H3/A64 specific bits */ -+#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */ -+ -+/* Generic system control EMAC_CLK bits */ -+#define SYSCON_ETXDC_MASK GENMASK(2, 0) -+#define SYSCON_ETXDC_SHIFT 10 -+#define SYSCON_ERXDC_MASK GENMASK(4, 0) -+#define SYSCON_ERXDC_SHIFT 5 -+/* EMAC PHY Interface Type */ -+#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */ -+#define SYSCON_ETCS_MASK GENMASK(1, 0) -+#define SYSCON_ETCS_MII 0x0 -+#define SYSCON_ETCS_EXT_GMII 0x1 -+#define SYSCON_ETCS_INT_GMII 0x2 -+#define SYSCON_EMAC_REG 0x30 -+ -+/* sun8i_dwmac_dma_reset() - reset the EMAC -+ * Called from stmmac via stmmac_dma_ops->reset -+ */ -+static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) -+{ -+ writel(0, ioaddr + EMAC_RX_CTL1); -+ writel(0, ioaddr + EMAC_TX_CTL1); -+ writel(0, ioaddr + EMAC_RX_FRM_FLT); -+ writel(0, ioaddr + EMAC_RX_DESC_LIST); -+ writel(0, ioaddr + EMAC_TX_DESC_LIST); -+ writel(0, ioaddr + EMAC_INT_EN); -+ writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); -+ return 0; -+} -+ -+/* sun8i_dwmac_dma_init() - initialize the EMAC -+ * Called from stmmac via stmmac_dma_ops->init -+ */ -+static void sun8i_dwmac_dma_init(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds) -+{ -+ /* Write TX and RX descriptors address */ -+ writel(dma_rx, ioaddr + EMAC_RX_DESC_LIST); -+ writel(dma_tx, ioaddr + EMAC_TX_DESC_LIST); -+ -+ writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN); -+ writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); -+} -+ -+/* sun8i_dwmac_dump_regs() - Dump EMAC address space -+ * Called from stmmac_dma_ops->dump_regs -+ * Used for ethtool -+ */ -+static void sun8i_dwmac_dump_regs(void __iomem *ioaddr, u32 *reg_space) -+{ -+ int i; -+ -+ for (i = 0; i < 0xC8; i += 4) { -+ if (i == 0x32 || i == 0x3C) -+ continue; -+ reg_space[i / 4] = readl(ioaddr + i); -+ } -+} -+ -+/* sun8i_dwmac_dump_mac_regs() - Dump EMAC address space -+ * Called from stmmac_ops->dump_regs -+ * Used for ethtool -+ */ -+static void sun8i_dwmac_dump_mac_regs(struct mac_device_info *hw, -+ u32 *reg_space) -+{ -+ int i; -+ void __iomem *ioaddr = hw->pcsr; -+ -+ for (i = 0; i < 0xC8; i += 4) { -+ if (i == 0x32 || i == 0x3C) -+ continue; -+ reg_space[i / 4] = readl(ioaddr + i); -+ } -+} -+ -+static void sun8i_dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan) -+{ -+ writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN); -+} -+ -+static void sun8i_dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan) -+{ -+ writel(0, ioaddr + EMAC_INT_EN); -+} -+ -+static void sun8i_dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v |= EMAC_TX_DMA_START; -+ v |= EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v |= EMAC_TX_DMA_START; -+ v |= EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v &= ~EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ v |= EMAC_RX_DMA_START; -+ v |= EMAC_RX_DMA_EN; -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ v &= ~EMAC_RX_DMA_EN; -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static int sun8i_dwmac_dma_interrupt(void __iomem *ioaddr, -+ struct stmmac_extra_stats *x, u32 chan) -+{ -+ u32 v; -+ int ret = 0; -+ -+ v = readl(ioaddr + EMAC_INT_STA); -+ -+ if (v & EMAC_TX_INT) { -+ ret |= handle_tx; -+ x->tx_normal_irq_n++; -+ } -+ -+ if (v & EMAC_TX_DMA_STOP_INT) -+ x->tx_process_stopped_irq++; -+ -+ if (v & EMAC_TX_BUF_UA_INT) -+ x->tx_process_stopped_irq++; -+ -+ if (v & EMAC_TX_TIMEOUT_INT) -+ ret |= tx_hard_error; -+ -+ if (v & EMAC_TX_UNDERFLOW_INT) { -+ ret |= tx_hard_error; -+ x->tx_undeflow_irq++; -+ } -+ -+ if (v & EMAC_TX_EARLY_INT) -+ x->tx_early_irq++; -+ -+ if (v & EMAC_RX_INT) { -+ ret |= handle_rx; -+ x->rx_normal_irq_n++; -+ } -+ -+ if (v & EMAC_RX_BUF_UA_INT) -+ x->rx_buf_unav_irq++; -+ -+ if (v & EMAC_RX_DMA_STOP_INT) -+ x->rx_process_stopped_irq++; -+ -+ if (v & EMAC_RX_TIMEOUT_INT) -+ ret |= tx_hard_error; -+ -+ if (v & EMAC_RX_OVERFLOW_INT) { -+ ret |= tx_hard_error; -+ x->rx_overflow_irq++; -+ } -+ -+ if (v & EMAC_RX_EARLY_INT) -+ x->rx_early_irq++; -+ -+ if (v & EMAC_RGMII_STA_INT) -+ x->irq_rgmii_n++; -+ -+ writel(v, ioaddr + EMAC_INT_STA); -+ -+ return ret; -+} -+ -+static void sun8i_dwmac_dma_operation_mode(void __iomem *ioaddr, int txmode, -+ int rxmode, int rxfifosz) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ if (txmode == SF_DMA_MODE) { -+ v |= EMAC_TX_MD; -+ /* Undocumented bit (called TX_NEXT_FRM in BSP), the original -+ * comment is -+ * "Operating on second frame increase the performance -+ * especially when transmit store-and-forward is used." -+ */ -+ v |= EMAC_TX_NEXT_FRM; -+ } else { -+ v &= ~EMAC_TX_MD; -+ v &= ~EMAC_TX_TH_MASK; -+ if (txmode < 64) -+ v |= EMAC_TX_TH_64; -+ else if (txmode < 128) -+ v |= EMAC_TX_TH_128; -+ else if (txmode < 192) -+ v |= EMAC_TX_TH_192; -+ else if (txmode < 256) -+ v |= EMAC_TX_TH_256; -+ } -+ writel(v, ioaddr + EMAC_TX_CTL1); -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ if (rxmode == SF_DMA_MODE) { -+ v |= EMAC_RX_MD; -+ } else { -+ v &= ~EMAC_RX_MD; -+ v &= ~EMAC_RX_TH_MASK; -+ if (rxmode < 32) -+ v |= EMAC_RX_TH_32; -+ else if (rxmode < 64) -+ v |= EMAC_RX_TH_64; -+ else if (rxmode < 96) -+ v |= EMAC_RX_TH_96; -+ else if (rxmode < 128) -+ v |= EMAC_RX_TH_128; -+ } -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = { -+ .reset = sun8i_dwmac_dma_reset, -+ .init = sun8i_dwmac_dma_init, -+ .dump_regs = sun8i_dwmac_dump_regs, -+ .dma_mode = sun8i_dwmac_dma_operation_mode, -+ .enable_dma_transmission = sun8i_dwmac_enable_dma_transmission, -+ .enable_dma_irq = sun8i_dwmac_enable_dma_irq, -+ .disable_dma_irq = sun8i_dwmac_disable_dma_irq, -+ .start_tx = sun8i_dwmac_dma_start_tx, -+ .stop_tx = sun8i_dwmac_dma_stop_tx, -+ .start_rx = sun8i_dwmac_dma_start_rx, -+ .stop_rx = sun8i_dwmac_dma_stop_rx, -+ .dma_interrupt = sun8i_dwmac_dma_interrupt, -+}; -+ -+static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) -+{ -+ struct sunxi_priv_data *gmac = priv; -+ int ret; -+ -+ if (gmac->regulator) { -+ ret = regulator_enable(gmac->regulator); -+ if (ret) { -+ dev_err(&pdev->dev, "Fail to enable regulator\n"); -+ return ret; -+ } -+ } -+ -+ ret = clk_prepare_enable(gmac->tx_clk); -+ if (ret) { -+ if (gmac->regulator) -+ regulator_disable(gmac->regulator); -+ dev_err(&pdev->dev, "Could not enable AHB clock\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = (8 << EMAC_BURSTLEN_SHIFT); /* burst len */ -+ writel(v, ioaddr + EMAC_BASIC_CTL1); -+} -+ -+static void sun8i_dwmac_set_mac(void __iomem *ioaddr, bool enable) -+{ -+ u32 t, r; -+ -+ t = readl(ioaddr + EMAC_TX_CTL0); -+ r = readl(ioaddr + EMAC_RX_CTL0); -+ if (enable) { -+ t |= EMAC_TX_TRANSMITTER_EN; -+ r |= EMAC_RX_RECEIVER_EN; -+ } else { -+ t &= ~EMAC_TX_TRANSMITTER_EN; -+ r &= ~EMAC_RX_RECEIVER_EN; -+ } -+ writel(t, ioaddr + EMAC_TX_CTL0); -+ writel(r, ioaddr + EMAC_RX_CTL0); -+} -+ -+/* Set MAC address at slot reg_n -+ * All slot > 0 need to be enabled with MAC_ADDR_TYPE_DST -+ * If addr is NULL, clear the slot -+ */ -+static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw, -+ unsigned char *addr, -+ unsigned int reg_n) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ if (!addr) { -+ writel(0, ioaddr + EMAC_MACADDR_HI(reg_n)); -+ return; -+ } -+ -+ stmmac_set_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n), -+ EMAC_MACADDR_LO(reg_n)); -+ if (reg_n > 0) { -+ v = readl(ioaddr + EMAC_MACADDR_HI(reg_n)); -+ v |= MAC_ADDR_TYPE_DST; -+ writel(v, ioaddr + EMAC_MACADDR_HI(reg_n)); -+ } -+} -+ -+static void sun8i_dwmac_get_umac_addr(struct mac_device_info *hw, -+ unsigned char *addr, -+ unsigned int reg_n) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ -+ stmmac_get_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n), -+ EMAC_MACADDR_LO(reg_n)); -+} -+ -+/* caution this function must return non 0 to work */ -+static int sun8i_dwmac_rx_ipc_enable(struct mac_device_info *hw) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL0); -+ v |= EMAC_RX_DO_CRC; -+ writel(v, ioaddr + EMAC_RX_CTL0); -+ -+ return 1; -+} -+ -+static void sun8i_dwmac_set_filter(struct mac_device_info *hw, -+ struct net_device *dev) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ int i = 1; -+ struct netdev_hw_addr *ha; -+ int macaddrs = netdev_uc_count(dev) + netdev_mc_count(dev) + 1; -+ -+ v = EMAC_FRM_FLT_CTL; -+ -+ if (dev->flags & IFF_PROMISC) { -+ v = EMAC_FRM_FLT_RXALL; -+ } else if (dev->flags & IFF_ALLMULTI) { -+ v |= EMAC_FRM_FLT_MULTICAST; -+ } else if (macaddrs <= hw->unicast_filter_entries) { -+ if (!netdev_mc_empty(dev)) { -+ netdev_for_each_mc_addr(ha, dev) { -+ sun8i_dwmac_set_umac_addr(hw, ha->addr, i); -+ i++; -+ } -+ } -+ if (!netdev_uc_empty(dev)) { -+ netdev_for_each_uc_addr(ha, dev) { -+ sun8i_dwmac_set_umac_addr(hw, ha->addr, i); -+ i++; -+ } -+ } -+ } else { -+ netdev_info(dev, "Too many address, switching to promiscuous\n"); -+ v = EMAC_FRM_FLT_RXALL; -+ } -+ -+ /* Disable unused address filter slots */ -+ while (i < hw->unicast_filter_entries) -+ sun8i_dwmac_set_umac_addr(hw, NULL, i++); -+ -+ writel(v, ioaddr + EMAC_RX_FRM_FLT); -+} -+ -+static void sun8i_dwmac_flow_ctrl(struct mac_device_info *hw, -+ unsigned int duplex, unsigned int fc, -+ unsigned int pause_time, u32 tx_cnt) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL0); -+ if (fc == FLOW_AUTO) -+ v |= EMAC_RX_FLOW_CTL_EN; -+ else -+ v &= ~EMAC_RX_FLOW_CTL_EN; -+ writel(v, ioaddr + EMAC_RX_CTL0); -+ -+ v = readl(ioaddr + EMAC_TX_FLOW_CTL); -+ if (fc == FLOW_AUTO) -+ v |= EMAC_TX_FLOW_CTL_EN; -+ else -+ v &= ~EMAC_TX_FLOW_CTL_EN; -+ writel(v, ioaddr + EMAC_TX_FLOW_CTL); -+} -+ -+static int sun8i_dwmac_reset(struct stmmac_priv *priv) -+{ -+ u32 v; -+ int err; -+ -+ v = readl(priv->ioaddr + EMAC_BASIC_CTL1); -+ writel(v | 0x01, priv->ioaddr + EMAC_BASIC_CTL1); -+ -+ /* The timeout was previoulsy set to 10ms, but some board (OrangePI0) -+ * need more if no cable plugged. 100ms seems OK -+ */ -+ err = readl_poll_timeout(priv->ioaddr + EMAC_BASIC_CTL1, v, -+ !(v & 0x01), 100, 100000); -+ -+ if (err) { -+ dev_err(priv->device, "EMAC reset timeout\n"); -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) -+{ -+ struct sunxi_priv_data *gmac = priv->plat->bsp_priv; -+ struct device_node *node = priv->device->of_node; -+ int ret; -+ u32 reg, val; -+ -+ regmap_read(gmac->regmap, SYSCON_EMAC_REG, &val); -+ reg = gmac->variant->default_syscon_value; -+ if (reg != val) -+ dev_warn(priv->device, -+ "Current syscon value is not the default %x (expect %x)\n", -+ val, reg); -+ -+ if (gmac->variant->internal_phy) { -+ if (!gmac->use_internal_phy) { -+ /* switch to external PHY interface */ -+ reg &= ~H3_EPHY_SELECT; -+ } else { -+ reg |= H3_EPHY_SELECT; -+ reg &= ~H3_EPHY_SHUTDOWN; -+ dev_dbg(priv->device, "Select internal_phy %x\n", reg); -+ -+ if (of_property_read_bool(priv->plat->phy_node, -+ "allwinner,leds-active-low")) -+ reg |= H3_EPHY_LED_POL; -+ else -+ reg &= ~H3_EPHY_LED_POL; -+ -+ /* Force EPHY xtal frequency to 24MHz. */ -+ reg |= H3_EPHY_CLK_SEL; -+ -+ ret = of_mdio_parse_addr(priv->device, -+ priv->plat->phy_node); -+ if (ret < 0) { -+ dev_err(priv->device, "Could not parse MDIO addr\n"); -+ return ret; -+ } -+ /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY -+ * address. No need to mask it again. -+ */ -+ reg |= ret << H3_EPHY_ADDR_SHIFT; -+ } -+ } -+ -+ if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) { -+ if (val % 100) { -+ dev_err(priv->device, "tx-delay must be a multiple of 100\n"); -+ return -EINVAL; -+ } -+ val /= 100; -+ dev_dbg(priv->device, "set tx-delay to %x\n", val); -+ if (val <= SYSCON_ETXDC_MASK) { -+ reg &= ~(SYSCON_ETXDC_MASK << SYSCON_ETXDC_SHIFT); -+ reg |= (val << SYSCON_ETXDC_SHIFT); -+ } else { -+ dev_err(priv->device, "Invalid TX clock delay: %d\n", -+ val); -+ return -EINVAL; -+ } -+ } -+ -+ if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) { -+ if (val % 100) { -+ dev_err(priv->device, "rx-delay must be a multiple of 100\n"); -+ return -EINVAL; -+ } -+ val /= 100; -+ dev_dbg(priv->device, "set rx-delay to %x\n", val); -+ if (val <= SYSCON_ERXDC_MASK) { -+ reg &= ~(SYSCON_ERXDC_MASK << SYSCON_ERXDC_SHIFT); -+ reg |= (val << SYSCON_ERXDC_SHIFT); -+ } else { -+ dev_err(priv->device, "Invalid RX clock delay: %d\n", -+ val); -+ return -EINVAL; -+ } -+ } -+ -+ /* Clear interface mode bits */ -+ reg &= ~(SYSCON_ETCS_MASK | SYSCON_EPIT); -+ if (gmac->variant->support_rmii) -+ reg &= ~SYSCON_RMII_EN; -+ -+ switch (priv->plat->interface) { -+ case PHY_INTERFACE_MODE_MII: -+ /* default */ -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII; -+ break; -+ case PHY_INTERFACE_MODE_RMII: -+ reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII; -+ break; -+ default: -+ dev_err(priv->device, "Unsupported interface mode: %s", -+ phy_modes(priv->plat->interface)); -+ return -EINVAL; -+ } -+ -+ regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); -+ -+ return 0; -+} -+ -+static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac) -+{ -+ u32 reg = gmac->variant->default_syscon_value; -+ -+ regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); -+} -+ -+static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv) -+{ -+ struct sunxi_priv_data *gmac = priv->plat->bsp_priv; -+ int ret; -+ -+ if (!gmac->use_internal_phy) -+ return 0; -+ -+ ret = clk_prepare_enable(gmac->ephy_clk); -+ if (ret) { -+ dev_err(priv->device, "Cannot enable ephy\n"); -+ return ret; -+ } -+ -+ /* Make sure the EPHY is properly reseted, as U-Boot may leave -+ * it at deasserted state, and thus it may fail to reset EMAC. -+ */ -+ reset_control_assert(gmac->rst_ephy); -+ -+ ret = reset_control_deassert(gmac->rst_ephy); -+ if (ret) { -+ dev_err(priv->device, "Cannot deassert ephy\n"); -+ clk_disable_unprepare(gmac->ephy_clk); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int sun8i_dwmac_unpower_internal_phy(struct sunxi_priv_data *gmac) -+{ -+ if (!gmac->use_internal_phy) -+ return 0; -+ -+ clk_disable_unprepare(gmac->ephy_clk); -+ reset_control_assert(gmac->rst_ephy); -+ return 0; -+} -+ -+/* sun8i_power_phy() - Activate the PHY: -+ * In case of error, no need to call sun8i_unpower_phy(), -+ * it will be called anyway by sun8i_dwmac_exit() -+ */ -+static int sun8i_power_phy(struct stmmac_priv *priv) -+{ -+ int ret; -+ -+ ret = sun8i_dwmac_power_internal_phy(priv); -+ if (ret) -+ return ret; -+ -+ ret = sun8i_dwmac_set_syscon(priv); -+ if (ret) -+ return ret; -+ -+ /* After changing syscon value, the MAC need reset or it will use -+ * the last value (and so the last PHY set. -+ */ -+ ret = sun8i_dwmac_reset(priv); -+ if (ret) -+ return ret; -+ return 0; -+} -+ -+static void sun8i_unpower_phy(struct sunxi_priv_data *gmac) -+{ -+ sun8i_dwmac_unset_syscon(gmac); -+ sun8i_dwmac_unpower_internal_phy(gmac); -+} -+ -+static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) -+{ -+ struct sunxi_priv_data *gmac = priv; -+ -+ sun8i_unpower_phy(gmac); -+ -+ clk_disable_unprepare(gmac->tx_clk); -+ -+ if (gmac->regulator) -+ regulator_disable(gmac->regulator); -+} -+ -+static const struct stmmac_ops sun8i_dwmac_ops = { -+ .core_init = sun8i_dwmac_core_init, -+ .set_mac = sun8i_dwmac_set_mac, -+ .dump_regs = sun8i_dwmac_dump_mac_regs, -+ .rx_ipc = sun8i_dwmac_rx_ipc_enable, -+ .set_filter = sun8i_dwmac_set_filter, -+ .flow_ctrl = sun8i_dwmac_flow_ctrl, -+ .set_umac_addr = sun8i_dwmac_set_umac_addr, -+ .get_umac_addr = sun8i_dwmac_get_umac_addr, -+}; -+ -+static struct mac_device_info *sun8i_dwmac_setup(void *ppriv) -+{ -+ struct mac_device_info *mac; -+ struct stmmac_priv *priv = ppriv; -+ int ret; -+ -+ mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL); -+ if (!mac) -+ return NULL; -+ -+ ret = sun8i_power_phy(priv); -+ if (ret) -+ return NULL; -+ -+ mac->pcsr = priv->ioaddr; -+ mac->mac = &sun8i_dwmac_ops; -+ mac->dma = &sun8i_dwmac_dma_ops; -+ -+ /* The loopback bit seems to be re-set when link change -+ * Simply mask it each time -+ * Speed 10/100/1000 are set in BIT(2)/BIT(3) -+ */ -+ mac->link.speed_mask = GENMASK(3, 2) | EMAC_LOOPBACK; -+ mac->link.speed10 = EMAC_SPEED_10; -+ mac->link.speed100 = EMAC_SPEED_100; -+ mac->link.speed1000 = EMAC_SPEED_1000; -+ mac->link.duplex = EMAC_DUPLEX_FULL; -+ mac->mii.addr = EMAC_MDIO_CMD; -+ mac->mii.data = EMAC_MDIO_DATA; -+ mac->mii.reg_shift = 4; -+ mac->mii.reg_mask = GENMASK(8, 4); -+ mac->mii.addr_shift = 12; -+ mac->mii.addr_mask = GENMASK(16, 12); -+ mac->mii.clk_csr_shift = 20; -+ mac->mii.clk_csr_mask = GENMASK(22, 20); -+ mac->unicast_filter_entries = 8; -+ -+ /* Synopsys Id is not available */ -+ priv->synopsys_id = 0; -+ -+ return mac; -+} -+ -+static int sun8i_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct sunxi_priv_data *gmac; -+ struct device *dev = &pdev->dev; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); -+ if (!gmac) -+ return -ENOMEM; -+ -+ gmac->variant = of_device_get_match_data(&pdev->dev); -+ if (!gmac->variant) { -+ dev_err(&pdev->dev, "Missing dwmac-sun8i variant\n"); -+ return -EINVAL; -+ } -+ -+ gmac->tx_clk = devm_clk_get(dev, "stmmaceth"); -+ if (IS_ERR(gmac->tx_clk)) { -+ dev_err(dev, "Could not get TX clock\n"); -+ return PTR_ERR(gmac->tx_clk); -+ } -+ -+ /* Optional regulator for PHY */ -+ gmac->regulator = devm_regulator_get_optional(dev, "phy"); -+ if (IS_ERR(gmac->regulator)) { -+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ dev_info(dev, "No regulator found\n"); -+ gmac->regulator = NULL; -+ } -+ -+ gmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "syscon"); -+ if (IS_ERR(gmac->regmap)) { -+ ret = PTR_ERR(gmac->regmap); -+ dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret); -+ return ret; -+ } -+ -+ plat_dat->interface = of_get_phy_mode(dev->of_node); -+ if (plat_dat->interface == gmac->variant->internal_phy) { -+ dev_info(&pdev->dev, "Will use internal PHY\n"); -+ gmac->use_internal_phy = true; -+ gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0); -+ if (IS_ERR(gmac->ephy_clk)) { -+ ret = PTR_ERR(gmac->ephy_clk); -+ dev_err(&pdev->dev, "Cannot get EPHY clock: %d\n", ret); -+ return -EINVAL; -+ } -+ -+ gmac->rst_ephy = of_reset_control_get(plat_dat->phy_node, NULL); -+ if (IS_ERR(gmac->rst_ephy)) { -+ ret = PTR_ERR(gmac->rst_ephy); -+ if (ret == -EPROBE_DEFER) -+ return ret; -+ dev_err(&pdev->dev, "No EPHY reset control found %d\n", -+ ret); -+ return -EINVAL; -+ } -+ } else { -+ dev_info(&pdev->dev, "Will use external PHY\n"); -+ gmac->use_internal_phy = false; -+ } -+ -+ /* platform data specifying hardware features and callbacks. -+ * hardware features were copied from Allwinner drivers. -+ */ -+ plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; -+ plat_dat->tx_coe = 1; -+ plat_dat->has_sun8i = true; -+ plat_dat->bsp_priv = gmac; -+ plat_dat->init = sun8i_dwmac_init; -+ plat_dat->exit = sun8i_dwmac_exit; -+ plat_dat->setup = sun8i_dwmac_setup; -+ -+ ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+ if (ret) -+ sun8i_dwmac_exit(pdev, plat_dat->bsp_priv); -+ -+ return ret; -+} -+ -+static const struct of_device_id sun8i_dwmac_match[] = { -+ { .compatible = "allwinner,sun8i-h3-emac", -+ .data = &emac_variant_h3 }, -+ { .compatible = "allwinner,sun8i-v3s-emac", -+ .data = &emac_variant_v3s }, -+ { .compatible = "allwinner,sun8i-a83t-emac", -+ .data = &emac_variant_a83t }, -+ { .compatible = "allwinner,sun50i-a64-emac", -+ .data = &emac_variant_a64 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); -+ -+static struct platform_driver sun8i_dwmac_driver = { -+ .probe = sun8i_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "dwmac-sun8i", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = sun8i_dwmac_match, -+ }, -+}; -+module_platform_driver(sun8i_dwmac_driver); -+ -+MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com>"); -+MODULE_DESCRIPTION("Allwinner sun8i DWMAC specific glue layer"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -@@ -45,15 +45,17 @@ static void dwmac1000_core_init(struct m - if (hw->ps) { - value |= GMAC_CONTROL_TE; - -- if (hw->ps == SPEED_1000) { -- value &= ~GMAC_CONTROL_PS; -- } else { -- value |= GMAC_CONTROL_PS; -- -- if (hw->ps == SPEED_10) -- value &= ~GMAC_CONTROL_FES; -- else -- value |= GMAC_CONTROL_FES; -+ value &= ~hw->link.speed_mask; -+ switch (hw->ps) { -+ case SPEED_1000: -+ value |= hw->link.speed1000; -+ break; -+ case SPEED_100: -+ value |= hw->link.speed100; -+ break; -+ case SPEED_10: -+ value |= hw->link.speed10; -+ break; - } - } - -@@ -531,9 +533,11 @@ struct mac_device_info *dwmac1000_setup( - mac->mac = &dwmac1000_ops; - mac->dma = &dwmac1000_dma_ops; - -- mac->link.port = GMAC_CONTROL_PS; - mac->link.duplex = GMAC_CONTROL_DM; -- mac->link.speed = GMAC_CONTROL_FES; -+ 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; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -205,8 +205,8 @@ static void dwmac1000_dump_dma_regs(void - { - int i; - -- for (i = 0; i < 22; i++) -- if ((i < 9) || (i > 17)) -+ for (i = 0; i < NUM_DWMAC1000_DMA_REGS; i++) -+ if ((i < 12) || (i > 17)) - reg_space[DMA_BUS_MODE / 4 + i] = - readl(ioaddr + DMA_BUS_MODE + i * 4); - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -@@ -175,9 +175,11 @@ struct mac_device_info *dwmac100_setup(v - mac->mac = &dwmac100_ops; - mac->dma = &dwmac100_dma_ops; - -- mac->link.port = MAC_CONTROL_PS; - mac->link.duplex = MAC_CONTROL_F; -- mac->link.speed = 0; -+ mac->link.speed10 = 0; -+ mac->link.speed100 = 0; -+ mac->link.speed1000 = 0; -+ mac->link.speed_mask = MAC_CONTROL_PS; - mac->mii.addr = MAC_MII_ADDR; - mac->mii.data = MAC_MII_DATA; - mac->mii.addr_shift = 11; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -@@ -70,7 +70,7 @@ static void dwmac100_dump_dma_regs(void - { - int i; - -- for (i = 0; i < 9; i++) -+ for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++) - reg_space[DMA_BUS_MODE / 4 + i] = - readl(ioaddr + DMA_BUS_MODE + i * 4); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -35,15 +35,17 @@ static void dwmac4_core_init(struct mac_ - if (hw->ps) { - value |= GMAC_CONFIG_TE; - -- if (hw->ps == SPEED_1000) { -- value &= ~GMAC_CONFIG_PS; -- } else { -- value |= GMAC_CONFIG_PS; -- -- if (hw->ps == SPEED_10) -- value &= ~GMAC_CONFIG_FES; -- else -- value |= GMAC_CONFIG_FES; -+ value &= hw->link.speed_mask; -+ switch (hw->ps) { -+ case SPEED_1000: -+ value |= hw->link.speed1000; -+ break; -+ case SPEED_100: -+ value |= hw->link.speed100; -+ break; -+ case SPEED_10: -+ value |= hw->link.speed10; -+ break; - } - } - -@@ -115,7 +117,7 @@ static void dwmac4_tx_queue_routing(stru - void __iomem *ioaddr = hw->pcsr; - u32 value; - -- const struct stmmac_rx_routing route_possibilities[] = { -+ static const struct stmmac_rx_routing route_possibilities[] = { - { GMAC_RXQCTRL_AVCPQ_MASK, GMAC_RXQCTRL_AVCPQ_SHIFT }, - { GMAC_RXQCTRL_PTPQ_MASK, GMAC_RXQCTRL_PTPQ_SHIFT }, - { GMAC_RXQCTRL_DCBCPQ_MASK, GMAC_RXQCTRL_DCBCPQ_SHIFT }, -@@ -747,9 +749,11 @@ struct mac_device_info *dwmac4_setup(voi - if (mac->multicast_filter_bins) - mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); - -- mac->link.port = GMAC_CONFIG_PS; - mac->link.duplex = GMAC_CONFIG_DM; -- mac->link.speed = GMAC_CONFIG_FES; -+ mac->link.speed10 = GMAC_CONFIG_PS; -+ mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS; -+ mac->link.speed1000 = 0; -+ mac->link.speed_mask = GMAC_CONFIG_FES | GMAC_CONFIG_PS; - mac->mii.addr = GMAC_MDIO_ADDR; - mac->mii.data = GMAC_MDIO_DATA; - mac->mii.addr_shift = 21; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -@@ -71,9 +71,9 @@ static void dwmac4_dma_axi(void __iomem - writel(value, ioaddr + DMA_SYS_BUS_MODE); - } - --void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, -- u32 dma_rx_phy, u32 chan) -+static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_rx_phy, u32 chan) - { - u32 value; - u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; -@@ -85,9 +85,9 @@ void dwmac4_dma_init_rx_chan(void __iome - writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(chan)); - } - --void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, -- u32 dma_tx_phy, u32 chan) -+static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx_phy, u32 chan) - { - u32 value; - u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -@@ -99,8 +99,8 @@ void dwmac4_dma_init_tx_chan(void __iome - writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); - } - --void dwmac4_dma_init_channel(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, u32 chan) -+static void dwmac4_dma_init_channel(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, u32 chan) - { - u32 value; - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -@@ -136,6 +136,9 @@ - #define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ - #define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ - -+#define NUM_DWMAC100_DMA_REGS 9 -+#define NUM_DWMAC1000_DMA_REGS 23 -+ - void dwmac_enable_dma_transmission(void __iomem *ioaddr); - void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan); - void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -@@ -248,6 +248,7 @@ void stmmac_set_mac_addr(void __iomem *i - data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; - writel(data, ioaddr + low); - } -+EXPORT_SYMBOL_GPL(stmmac_set_mac_addr); - - /* Enable disable MAC RX/TX */ - void stmmac_set_mac(void __iomem *ioaddr, bool enable) -@@ -279,4 +280,4 @@ void stmmac_get_mac_addr(void __iomem *i - addr[4] = hi_addr & 0xff; - addr[5] = (hi_addr >> 8) & 0xff; - } -- -+EXPORT_SYMBOL_GPL(stmmac_get_mac_addr); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -104,7 +104,7 @@ struct stmmac_priv { - /* TX Queue */ - struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES]; - -- int oldlink; -+ bool oldlink; - int speed; - int oldduplex; - unsigned int flow_ctrl; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -29,10 +29,12 @@ - #include "stmmac.h" - #include "dwmac_dma.h" - --#define REG_SPACE_SIZE 0x1054 -+#define REG_SPACE_SIZE 0x1060 - #define MAC100_ETHTOOL_NAME "st_mac100" - #define GMAC_ETHTOOL_NAME "st_gmac" - -+#define ETHTOOL_DMA_OFFSET 55 -+ - struct stmmac_stats { - char stat_string[ETH_GSTRING_LEN]; - int sizeof_stat; -@@ -273,7 +275,6 @@ static int stmmac_ethtool_get_link_ksett - { - struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phy = dev->phydev; -- int rc; - - if (priv->hw->pcs & STMMAC_PCS_RGMII || - priv->hw->pcs & STMMAC_PCS_SGMII) { -@@ -364,8 +365,8 @@ static int stmmac_ethtool_get_link_ksett - "link speed / duplex setting\n", dev->name); - return -EBUSY; - } -- rc = phy_ethtool_ksettings_get(phy, cmd); -- return rc; -+ phy_ethtool_ksettings_get(phy, cmd); -+ return 0; - } - - static int -@@ -443,6 +444,9 @@ static void stmmac_ethtool_gregs(struct - - priv->hw->mac->dump_regs(priv->hw, reg_space); - priv->hw->dma->dump_regs(priv->ioaddr, reg_space); -+ /* Copy DMA registers to where ethtool expects them */ -+ memcpy(®_space[ETHTOOL_DMA_OFFSET], ®_space[DMA_BUS_MODE / 4], -+ NUM_DWMAC1000_DMA_REGS * 4); - } - - static void ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -235,6 +235,17 @@ static void stmmac_clk_csr_set(struct st - else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) - priv->clk_csr = STMMAC_CSR_250_300M; - } -+ -+ if (priv->plat->has_sun8i) { -+ if (clk_rate > 160000000) -+ priv->clk_csr = 0x03; -+ else if (clk_rate > 80000000) -+ priv->clk_csr = 0x02; -+ else if (clk_rate > 40000000) -+ priv->clk_csr = 0x01; -+ else -+ priv->clk_csr = 0; -+ } - } - - static void print_pkt(unsigned char *buf, int len) -@@ -789,7 +800,7 @@ static void stmmac_adjust_link(struct ne - struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phydev = dev->phydev; - unsigned long flags; -- int new_state = 0; -+ bool new_state = false; - - if (!phydev) - return; -@@ -802,8 +813,8 @@ static void stmmac_adjust_link(struct ne - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != priv->oldduplex) { -- new_state = 1; -- if (!(phydev->duplex)) -+ new_state = true; -+ if (!phydev->duplex) - ctrl &= ~priv->hw->link.duplex; - else - ctrl |= priv->hw->link.duplex; -@@ -814,30 +825,17 @@ static void stmmac_adjust_link(struct ne - stmmac_mac_flow_ctrl(priv, phydev->duplex); - - if (phydev->speed != priv->speed) { -- new_state = 1; -+ new_state = true; -+ ctrl &= ~priv->hw->link.speed_mask; - switch (phydev->speed) { -- case 1000: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) -- ctrl &= ~priv->hw->link.port; -+ case SPEED_1000: -+ ctrl |= priv->hw->link.speed1000; - break; -- case 100: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) { -- ctrl |= priv->hw->link.port; -- ctrl |= priv->hw->link.speed; -- } else { -- ctrl &= ~priv->hw->link.port; -- } -+ case SPEED_100: -+ ctrl |= priv->hw->link.speed100; - break; -- case 10: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) { -- ctrl |= priv->hw->link.port; -- ctrl &= ~(priv->hw->link.speed); -- } else { -- ctrl &= ~priv->hw->link.port; -- } -+ case SPEED_10: -+ ctrl |= priv->hw->link.speed10; - break; - default: - netif_warn(priv, link, priv->dev, -@@ -853,12 +851,12 @@ static void stmmac_adjust_link(struct ne - writel(ctrl, priv->ioaddr + MAC_CTRL_REG); - - if (!priv->oldlink) { -- new_state = 1; -- priv->oldlink = 1; -+ new_state = true; -+ priv->oldlink = true; - } - } else if (priv->oldlink) { -- new_state = 1; -- priv->oldlink = 0; -+ new_state = true; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - } -@@ -921,7 +919,7 @@ static int stmmac_init_phy(struct net_de - char bus_id[MII_BUS_ID_SIZE]; - int interface = priv->plat->interface; - int max_speed = priv->plat->max_speed; -- priv->oldlink = 0; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - -@@ -1456,7 +1454,7 @@ static void free_dma_rx_desc_resources(s - static void free_dma_tx_desc_resources(struct stmmac_priv *priv) - { - u32 tx_count = priv->plat->tx_queues_to_use; -- u32 queue = 0; -+ u32 queue; - - /* Free TX queue resources */ - for (queue = 0; queue < tx_count; queue++) { -@@ -1505,7 +1503,7 @@ static int alloc_dma_rx_desc_resources(s - sizeof(dma_addr_t), - GFP_KERNEL); - if (!rx_q->rx_skbuff_dma) -- return -ENOMEM; -+ goto err_dma; - - rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE, - sizeof(struct sk_buff *), -@@ -1568,13 +1566,13 @@ static int alloc_dma_tx_desc_resources(s - sizeof(*tx_q->tx_skbuff_dma), - GFP_KERNEL); - if (!tx_q->tx_skbuff_dma) -- return -ENOMEM; -+ goto err_dma; - - tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE, - sizeof(struct sk_buff *), - GFP_KERNEL); - if (!tx_q->tx_skbuff) -- goto err_dma_buffers; -+ goto err_dma; - - if (priv->extend_desc) { - tx_q->dma_etx = dma_zalloc_coherent(priv->device, -@@ -1584,7 +1582,7 @@ static int alloc_dma_tx_desc_resources(s - &tx_q->dma_tx_phy, - GFP_KERNEL); - if (!tx_q->dma_etx) -- goto err_dma_buffers; -+ goto err_dma; - } else { - tx_q->dma_tx = dma_zalloc_coherent(priv->device, - DMA_TX_SIZE * -@@ -1593,13 +1591,13 @@ static int alloc_dma_tx_desc_resources(s - &tx_q->dma_tx_phy, - GFP_KERNEL); - if (!tx_q->dma_tx) -- goto err_dma_buffers; -+ goto err_dma; - } - } - - return 0; - --err_dma_buffers: -+err_dma: - free_dma_tx_desc_resources(priv); - - return ret; -@@ -2907,8 +2905,7 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->xstats.tx_set_ic_bit++; - } - -- if (!priv->hwts_tx_en) -- skb_tx_timestamp(skb); -+ skb_tx_timestamp(skb); - - if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - priv->hwts_tx_en)) { -@@ -2993,7 +2990,7 @@ static netdev_tx_t stmmac_xmit(struct sk - - /* Manage oversized TCP frames for GMAC4 device */ - if (skb_is_gso(skb) && priv->tso) { -- if (ip_hdr(skb)->protocol == IPPROTO_TCP) -+ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) - return stmmac_tso_xmit(skb, dev); - } - -@@ -3124,8 +3121,7 @@ static netdev_tx_t stmmac_xmit(struct sk - priv->xstats.tx_set_ic_bit++; - } - -- if (!priv->hwts_tx_en) -- skb_tx_timestamp(skb); -+ skb_tx_timestamp(skb); - - /* Ready to fill the first descriptor and set the OWN bit w/o any - * problems because all the descriptors are actually ready to be -@@ -4002,7 +3998,9 @@ static int stmmac_hw_init(struct stmmac_ - struct mac_device_info *mac; - - /* Identify the MAC HW device */ -- if (priv->plat->has_gmac) { -+ if (priv->plat->setup) { -+ mac = priv->plat->setup(priv); -+ } else if (priv->plat->has_gmac) { - priv->dev->priv_flags |= IFF_UNICAST_FLT; - mac = dwmac1000_setup(priv->ioaddr, - priv->plat->multicast_filter_bins, -@@ -4022,6 +4020,10 @@ static int stmmac_hw_init(struct stmmac_ - - priv->hw = mac; - -+ /* dwmac-sun8i only work in chain mode */ -+ if (priv->plat->has_sun8i) -+ chain_mode = 1; -+ - /* To use the chained or ring mode */ - if (priv->synopsys_id >= DWMAC_CORE_4_00) { - priv->hw->mode = &dwmac4_ring_mode_ops; -@@ -4150,8 +4152,15 @@ int stmmac_dvr_probe(struct device *devi - if ((phyaddr >= 0) && (phyaddr <= 31)) - priv->plat->phy_addr = phyaddr; - -- if (priv->plat->stmmac_rst) -+ if (priv->plat->stmmac_rst) { -+ ret = reset_control_assert(priv->plat->stmmac_rst); - reset_control_deassert(priv->plat->stmmac_rst); -+ /* Some reset controllers have only reset callback instead of -+ * assert + deassert callbacks pair. -+ */ -+ if (ret == -ENOTSUPP) -+ reset_control_reset(priv->plat->stmmac_rst); -+ } - - /* Init MAC and get the capabilities */ - ret = stmmac_hw_init(priv); -@@ -4168,7 +4177,7 @@ int stmmac_dvr_probe(struct device *devi - NETIF_F_RXCSUM; - - if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { -- ndev->hw_features |= NETIF_F_TSO; -+ ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; - priv->tso = true; - dev_info(priv->device, "TSO feature enabled\n"); - } -@@ -4330,7 +4339,7 @@ int stmmac_suspend(struct device *dev) - } - spin_unlock_irqrestore(&priv->lock, flags); - -- priv->oldlink = 0; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - return 0; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -@@ -204,6 +204,7 @@ int stmmac_mdio_register(struct net_devi - struct stmmac_priv *priv = netdev_priv(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; - - if (!mdio_bus_data) -@@ -237,7 +238,7 @@ int stmmac_mdio_register(struct net_devi - else - err = mdiobus_register(new_bus); - if (err != 0) { -- netdev_err(ndev, "Cannot register the MDIO bus\n"); -+ dev_err(dev, "Cannot register the MDIO bus\n"); - goto bus_register_fail; - } - -@@ -292,7 +293,7 @@ int stmmac_mdio_register(struct net_devi - } - - if (!found && !mdio_node) { -- netdev_warn(ndev, "No PHY found\n"); -+ dev_warn(dev, "No PHY found\n"); - mdiobus_unregister(new_bus); - mdiobus_free(new_bus); - return -ENODEV; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -30,42 +30,39 @@ - * negative value of the address means that MAC controller is not connected - * with PHY. - */ --struct stmmac_pci_dmi_data { -- const char *name; -- const char *asset_tag; -+struct stmmac_pci_func_data { - unsigned int func; - int phy_addr; - }; - -+struct stmmac_pci_dmi_data { -+ const struct stmmac_pci_func_data *func; -+ size_t nfuncs; -+}; -+ - struct stmmac_pci_info { -- struct pci_dev *pdev; -- int (*setup)(struct plat_stmmacenet_data *plat, -- struct stmmac_pci_info *info); -- struct stmmac_pci_dmi_data *dmi; -+ int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); - }; - --static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info) -+static int stmmac_pci_find_phy_addr(struct pci_dev *pdev, -+ const struct dmi_system_id *dmi_list) - { -- const char *name = dmi_get_system_info(DMI_BOARD_NAME); -- const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG); -- unsigned int func = PCI_FUNC(info->pdev->devfn); -- struct stmmac_pci_dmi_data *dmi; -- -- /* -- * Galileo boards with old firmware don't support DMI. We always return -- * 1 here, so at least first found MAC controller would be probed. -- */ -- if (!name) -- return 1; -- -- for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) { -- if (!strcmp(dmi->name, name) && dmi->func == func) { -- /* If asset tag is provided, match on it as well. */ -- if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag)) -- continue; -- return dmi->phy_addr; -- } -- } -+ const struct stmmac_pci_func_data *func_data; -+ const struct stmmac_pci_dmi_data *dmi_data; -+ const struct dmi_system_id *dmi_id; -+ int func = PCI_FUNC(pdev->devfn); -+ size_t n; -+ -+ dmi_id = dmi_first_match(dmi_list); -+ if (!dmi_id) -+ return -ENODEV; -+ -+ dmi_data = dmi_id->driver_data; -+ func_data = dmi_data->func; -+ -+ for (n = 0; n < dmi_data->nfuncs; n++, func_data++) -+ if (func_data->func == func) -+ return func_data->phy_addr; - - return -ENODEV; - } -@@ -100,7 +97,8 @@ static void common_default_data(struct p - plat->rx_queues_cfg[0].pkt_route = 0x0; - } - --static void stmmac_default_data(struct plat_stmmacenet_data *plat) -+static int stmmac_default_data(struct pci_dev *pdev, -+ struct plat_stmmacenet_data *plat) - { - /* Set common default data first */ - common_default_data(plat); -@@ -112,12 +110,77 @@ static void stmmac_default_data(struct p - plat->dma_cfg->pbl = 32; - plat->dma_cfg->pblx8 = true; - /* TODO: AXI */ -+ -+ return 0; - } - --static int quark_default_data(struct plat_stmmacenet_data *plat, -- struct stmmac_pci_info *info) -+static const struct stmmac_pci_info stmmac_pci_info = { -+ .setup = stmmac_default_data, -+}; -+ -+static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = { -+ { -+ .func = 6, -+ .phy_addr = 1, -+ }, -+}; -+ -+static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = { -+ .func = galileo_stmmac_func_data, -+ .nfuncs = ARRAY_SIZE(galileo_stmmac_func_data), -+}; -+ -+static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = { -+ { -+ .func = 6, -+ .phy_addr = 1, -+ }, -+ { -+ .func = 7, -+ .phy_addr = 1, -+ }, -+}; -+ -+static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = { -+ .func = iot2040_stmmac_func_data, -+ .nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data), -+}; -+ -+static const struct dmi_system_id quark_pci_dmi[] = { -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), -+ DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, -+ "6ES7647-0AA00-0YA2"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), -+ DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, -+ "6ES7647-0AA00-1YA2"), -+ }, -+ .driver_data = (void *)&iot2040_stmmac_dmi_data, -+ }, -+ {} -+}; -+ -+static int quark_default_data(struct pci_dev *pdev, -+ struct plat_stmmacenet_data *plat) - { -- struct pci_dev *pdev = info->pdev; - int ret; - - /* Set common default data first */ -@@ -127,9 +190,19 @@ static int quark_default_data(struct pla - * Refuse to load the driver and register net device if MAC controller - * does not connect to any PHY interface. - */ -- ret = stmmac_pci_find_phy_addr(info); -- if (ret < 0) -- return ret; -+ ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi); -+ if (ret < 0) { -+ /* Return error to the caller on DMI enabled boards. */ -+ if (dmi_get_system_info(DMI_BOARD_NAME)) -+ return ret; -+ -+ /* -+ * Galileo boards with old firmware don't support DMI. We always -+ * use 1 here as PHY address, so at least the first found MAC -+ * controller would be probed. -+ */ -+ ret = 1; -+ } - - plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn); - plat->phy_addr = ret; -@@ -143,41 +216,8 @@ static int quark_default_data(struct pla - return 0; - } - --static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = { -- { -- .name = "Galileo", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "GalileoGen2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-0YA2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-1YA2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-1YA2", -- .func = 7, -- .phy_addr = 1, -- }, -- {} --}; -- --static struct stmmac_pci_info quark_pci_info = { -+static const struct stmmac_pci_info quark_pci_info = { - .setup = quark_default_data, -- .dmi = quark_pci_dmi_data, - }; - - /** -@@ -236,15 +276,9 @@ static int stmmac_pci_probe(struct pci_d - - pci_set_master(pdev); - -- if (info) { -- info->pdev = pdev; -- if (info->setup) { -- ret = info->setup(plat, info); -- if (ret) -- return ret; -- } -- } else -- stmmac_default_data(plat); -+ ret = info->setup(pdev, plat); -+ if (ret) -+ return ret; - - pci_enable_msi(pdev); - -@@ -306,14 +340,21 @@ static int stmmac_pci_resume(struct devi - - static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); - --#define STMMAC_VENDOR_ID 0x700 -+/* synthetic ID, no official vendor */ -+#define PCI_VENDOR_ID_STMMAC 0x700 -+ - #define STMMAC_QUARK_ID 0x0937 - #define STMMAC_DEVICE_ID 0x1108 - -+#define STMMAC_DEVICE(vendor_id, dev_id, info) { \ -+ PCI_VDEVICE(vendor_id, dev_id), \ -+ .driver_data = (kernel_ulong_t)&info \ -+ } -+ - static const struct pci_device_id stmmac_id_table[] = { -- {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, -- {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, -- {PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info}, -+ STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info), -+ STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info), -+ STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info), - {} - }; - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -308,6 +308,13 @@ static int stmmac_dt_phy(struct plat_stm - struct device_node *np, struct device *dev) - { - bool mdio = true; -+ static const struct of_device_id need_mdio_ids[] = { -+ { .compatible = "snps,dwc-qos-ethernet-4.10" }, -+ { .compatible = "allwinner,sun8i-a83t-emac" }, -+ { .compatible = "allwinner,sun8i-h3-emac" }, -+ { .compatible = "allwinner,sun8i-v3s-emac" }, -+ { .compatible = "allwinner,sun50i-a64-emac" }, -+ }; - - /* If phy-handle property is passed from DT, use it as the PHY */ - plat->phy_node = of_parse_phandle(np, "phy-handle", 0); -@@ -324,8 +331,7 @@ static int stmmac_dt_phy(struct plat_stm - mdio = false; - } - -- /* exception for dwmac-dwc-qos-eth glue logic */ -- if (of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) { -+ if (of_match_node(need_mdio_ids, np)) { - plat->mdio_node = of_get_child_by_name(np, "mdio"); - } else { - /** ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -177,6 +177,7 @@ struct plat_stmmacenet_data { - void (*fix_mac_speed)(void *priv, unsigned int speed); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); -+ struct mac_device_info *(*setup)(void *priv); - void *bsp_priv; - struct clk *stmmac_clk; - struct clk *pclk; -@@ -185,6 +186,7 @@ struct plat_stmmacenet_data { - struct reset_control *stmmac_rst; - struct stmmac_axi *axi; - int has_gmac4; -+ bool has_sun8i; - bool tso_en; - int mac_port_sel_speed; - bool en_tx_lpi_clockgating; |