aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch
diff options
context:
space:
mode:
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.patch1923
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 abdc618e6b..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(&reg_space[ETHTOOL_DMA_OFFSET], &reg_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
-@@ -309,6 +309,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);
-@@ -325,8 +332,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;