summaryrefslogtreecommitdiff
path: root/target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch
diff options
context:
space:
mode:
authorRam Chandra Jangir <rjangi@codeaurora.org>2016-05-21 14:48:31 +0530
committerJohn Crispin <john@phrozen.org>2016-05-27 15:50:17 +0200
commit5e49c5795697868f6317f17fda5a2b04f299e116 (patch)
treebf6ebcc54ae88fa08f268f02a8f118939fe6bf6a /target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch
parent955c341d3bec0eb4971a03924e99156367255d7b (diff)
downloadmtk-20170518-5e49c5795697868f6317f17fda5a2b04f299e116.zip
mtk-20170518-5e49c5795697868f6317f17fda5a2b04f299e116.tar.gz
mtk-20170518-5e49c5795697868f6317f17fda5a2b04f299e116.tar.bz2
ipq806x: Add support for linux-4.4
1)Changes - Rebased the patches for linux-4.4.7 - Added patch to fix spi nor fifo and dma support - Added patch to configure watchdog barktime 2)Testing Tested on IPQ AP148 Board: a. NOR boot and NAND boot b. ethernet network and ath10k wifi c. ubi sysupgrade UnTested dwc3 usb has not been validated on IPQ board(AP148) 3)Known Issues: Once we flash ubi image on AP148, and if we reset the board, uboot on first boot creates PEB and LEB for dynamic sized partitions, which is incorrect and not what linux expects which causes errors when trying to mount rootfs. In order to test this, we can use the below steps: a. Flash the ubi image on board and don't reset the board b. load the kernel fit image in RAM and boot from there. Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
Diffstat (limited to 'target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch')
-rw-r--r--target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch4258
1 files changed, 0 insertions, 4258 deletions
diff --git a/target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch b/target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch
deleted file mode 100644
index 539d1a1..0000000
--- a/target/linux/ipq806x/patches-3.18/701-stmmac_update_to_4.3.patch
+++ /dev/null
@@ -1,4258 +0,0 @@
---- a/include/linux/stmmac.h
-+++ b/include/linux/stmmac.h
-@@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
- int phy_addr;
- int interface;
- struct stmmac_mdio_bus_data *mdio_bus_data;
-+ struct device_node *phy_node;
- struct stmmac_dma_cfg *dma_cfg;
- int clk_csr;
- int has_gmac;
-@@ -114,32 +115,12 @@ struct plat_stmmacenet_data {
- int maxmtu;
- int multicast_filter_bins;
- int unicast_filter_entries;
-+ int tx_fifo_size;
-+ int rx_fifo_size;
- void (*fix_mac_speed)(void *priv, unsigned int speed);
- void (*bus_setup)(void __iomem *ioaddr);
-- void *(*setup)(struct platform_device *pdev);
-- void (*free)(struct platform_device *pdev, void *priv);
- int (*init)(struct platform_device *pdev, void *priv);
- void (*exit)(struct platform_device *pdev, void *priv);
-- void *custom_cfg;
-- void *custom_data;
- void *bsp_priv;
- };
--
--/* of_data for SoC glue layer device tree bindings */
--
--struct stmmac_of_data {
-- int has_gmac;
-- int enh_desc;
-- int tx_coe;
-- int rx_coe;
-- int bugged_jumbo;
-- int pmt;
-- int riwt_off;
-- void (*fix_mac_speed)(void *priv, unsigned int speed);
-- void (*bus_setup)(void __iomem *ioaddr);
-- void *(*setup)(struct platform_device *pdev);
-- void (*free)(struct platform_device *pdev, void *priv);
-- int (*init)(struct platform_device *pdev, void *priv);
-- void (*exit)(struct platform_device *pdev, void *priv);
--};
- #endif
---- a/drivers/net/ethernet/stmicro/Kconfig
-+++ b/drivers/net/ethernet/stmicro/Kconfig
-@@ -7,9 +7,7 @@ config NET_VENDOR_STMICRO
- default y
- depends on HAS_IOMEM
- ---help---
-- If you have a network (Ethernet) card belonging to this class, say Y
-- and read the Ethernet-HOWTO, available from
-- <http://www.tldp.org/docs.html#howto>.
-+ If you have a network (Ethernet) card belonging to this class, say Y.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
-+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
-@@ -14,21 +14,54 @@ config STMMAC_ETH
- if STMMAC_ETH
-
- config STMMAC_PLATFORM
-- bool "STMMAC Platform bus support"
-+ tristate "STMMAC Platform bus support"
- depends on STMMAC_ETH
-+ select MFD_SYSCON
- default y
- ---help---
-- This selects the platform specific bus support for
-- the stmmac device driver. This is the driver used
-- on many embedded STM platforms based on ARM and SuperH
-- processors.
-+ This selects the platform specific bus support for the stmmac driver.
-+ This is the driver used on several SoCs:
-+ STi, Allwinner, Amlogic Meson, Altera SOCFPGA.
-+
- If you have a controller with this interface, say Y or M here.
-
- If unsure, say N.
-
-+if STMMAC_PLATFORM
-+
-+config DWMAC_GENERIC
-+ tristate "Generic driver for DWMAC"
-+ default STMMAC_PLATFORM
-+ ---help---
-+ Generic DWMAC driver for platforms that don't require any
-+ platform specific code to function or is using platform
-+ data for setup.
-+
-+config DWMAC_IPQ806X
-+ tristate "QCA IPQ806x DWMAC support"
-+ default ARCH_QCOM
-+ depends on OF
-+ select MFD_SYSCON
-+ help
-+ Support for QCA IPQ806X DWMAC Ethernet.
-+
-+ This selects the IPQ806x SoC glue layer support for the stmmac
-+ device driver. This driver does not use any of the hardware
-+ acceleration features available on this SoC. Network devices
-+ will behave like standard non-accelerated ethernet interfaces.
-+
-+config DWMAC_LPC18XX
-+ tristate "NXP LPC18xx/43xx DWMAC support"
-+ default ARCH_LPC18XX
-+ depends on OF
-+ select MFD_SYSCON
-+ ---help---
-+ Support for NXP LPC18xx/43xx DWMAC Ethernet.
-+
- config DWMAC_MESON
-- bool "Amlogic Meson dwmac support"
-- depends on STMMAC_PLATFORM && ARCH_MESON
-+ tristate "Amlogic Meson dwmac support"
-+ default ARCH_MESON
-+ depends on OF
- help
- Support for Ethernet controller on Amlogic Meson SoCs.
-
-@@ -36,9 +69,22 @@ config DWMAC_MESON
- the stmmac device driver. This driver is used for Meson6 and
- Meson8 SoCs.
-
-+config DWMAC_ROCKCHIP
-+ tristate "Rockchip dwmac support"
-+ default ARCH_ROCKCHIP
-+ depends on OF
-+ select MFD_SYSCON
-+ help
-+ Support for Ethernet controller on Rockchip RK3288 SoC.
-+
-+ This selects the Rockchip RK3288 SoC glue layer support for
-+ the stmmac device driver.
-+
- config DWMAC_SOCFPGA
-- bool "SOCFPGA dwmac support"
-- depends on STMMAC_PLATFORM && MFD_SYSCON && (ARCH_SOCFPGA || COMPILE_TEST)
-+ tristate "SOCFPGA dwmac support"
-+ default ARCH_SOCFPGA
-+ depends on OF
-+ select MFD_SYSCON
- help
- Support for ethernet controller on Altera SOCFPGA
-
-@@ -46,21 +92,11 @@ config DWMAC_SOCFPGA
- for the stmmac device driver. This driver is used for
- arria5 and cyclone5 FPGA SoCs.
-
--config DWMAC_SUNXI
-- bool "Allwinner GMAC support"
-- depends on STMMAC_PLATFORM && ARCH_SUNXI
-- default y
-- ---help---
-- Support for Allwinner A20/A31 GMAC ethernet controllers.
--
-- This selects Allwinner SoC glue layer support for the
-- stmmac device driver. This driver is used for A20/A31
-- GMAC ethernet controller.
--
- config DWMAC_STI
-- bool "STi GMAC support"
-- depends on STMMAC_PLATFORM && ARCH_STI
-- default y
-+ tristate "STi GMAC support"
-+ default ARCH_STI
-+ depends on OF
-+ select MFD_SYSCON
- ---help---
- Support for ethernet controller on STi SOCs.
-
-@@ -68,8 +104,20 @@ config DWMAC_STI
- device driver. This driver is used on for the STi series
- SOCs GMAC ethernet controller.
-
-+config DWMAC_SUNXI
-+ tristate "Allwinner GMAC support"
-+ default ARCH_SUNXI
-+ depends on OF
-+ ---help---
-+ Support for Allwinner A20/A31 GMAC ethernet controllers.
-+
-+ This selects Allwinner SoC glue layer support for the
-+ stmmac device driver. This driver is used for A20/A31
-+ GMAC ethernet controller.
-+endif
-+
- config STMMAC_PCI
-- bool "STMMAC PCI bus support"
-+ tristate "STMMAC PCI bus support"
- depends on STMMAC_ETH && PCI
- ---help---
- This is to select the Synopsys DWMAC available on PCI devices,
-@@ -79,22 +127,4 @@ config STMMAC_PCI
- D1215994A VIRTEX FPGA board.
-
- If unsure, say N.
--
--config STMMAC_DEBUG_FS
-- bool "Enable monitoring via sysFS "
-- default n
-- depends on STMMAC_ETH && DEBUG_FS
-- ---help---
-- The stmmac entry in /sys reports DMA TX/RX rings
-- or (if supported) the HW cap register.
--
--config STMMAC_DA
-- bool "STMMAC DMA arbitration scheme"
-- default n
-- ---help---
-- Selecting this option, rx has priority over Tx (only for Giga
-- Ethernet device).
-- By default, the DMA arbitration scheme is based on Round-robin
-- (rx:tx priority is 1:1).
--
- endif
---- a/drivers/net/ethernet/stmicro/stmmac/Makefile
-+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
-@@ -1,11 +1,20 @@
- obj-$(CONFIG_STMMAC_ETH) += stmmac.o
--stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
--stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
--stmmac-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
--stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
--stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
--stmmac-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o
- stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
-- chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
-- dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
-+ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
-+ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
- mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y)
-+
-+# Ordering matters. Generic driver must be last.
-+obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
-+obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
-+obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
-+obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
-+obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
-+obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o
-+obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
-+obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
-+obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
-+stmmac-platform-objs:= stmmac_platform.o
-+
-+obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
-+stmmac-pci-objs:= stmmac_pci.o
---- a/drivers/net/ethernet/stmicro/stmmac/common.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
-@@ -44,6 +44,7 @@
- #undef FRAME_FILTER_DEBUG
- /* #define FRAME_FILTER_DEBUG */
-
-+/* Extra statistic and debug information exposed by ethtool */
- struct stmmac_extra_stats {
- /* Transmit errors */
- unsigned long tx_underflow ____cacheline_aligned;
-@@ -149,7 +150,7 @@ struct stmmac_extra_stats {
- #define MAC_CSR_H_FRQ_MASK 0x20
-
- #define HASH_TABLE_SIZE 64
--#define PAUSE_TIME 0x200
-+#define PAUSE_TIME 0xffff
-
- /* Flow Control defines */
- #define FLOW_OFF 0
-@@ -220,6 +221,7 @@ enum dma_irq_status {
- handle_tx = 0x8,
- };
-
-+/* EEE and LPI defines */
- #define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 0)
- #define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 1)
- #define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 2)
-@@ -229,6 +231,7 @@ enum dma_irq_status {
- #define CORE_PCS_LINK_STATUS (1 << 6)
- #define CORE_RGMII_IRQ (1 << 7)
-
-+/* Physical Coding Sublayer */
- struct rgmii_adv {
- unsigned int pause;
- unsigned int duplex;
-@@ -294,6 +297,7 @@ struct dma_features {
-
- #define JUMBO_LEN 9000
-
-+/* Descriptors helpers */
- struct stmmac_desc_ops {
- /* DMA RX descriptor ring initialization */
- void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode,
-@@ -341,6 +345,10 @@ struct stmmac_desc_ops {
- int (*get_rx_timestamp_status) (void *desc, u32 ats);
- };
-
-+extern const struct stmmac_desc_ops enh_desc_ops;
-+extern const struct stmmac_desc_ops ndesc_ops;
-+
-+/* Specific DMA helpers */
- struct stmmac_dma_ops {
- /* DMA core initialization */
- int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
-@@ -349,7 +357,8 @@ struct stmmac_dma_ops {
- void (*dump_regs) (void __iomem *ioaddr);
- /* Set tx/rx threshold in the csr6 register
- * An invalid value enables the store-and-forward mode */
-- void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode);
-+ void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode,
-+ int rxfifosz);
- /* To track extra statistic (if supported) */
- void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
- void __iomem *ioaddr);
-@@ -370,6 +379,7 @@ struct stmmac_dma_ops {
-
- struct mac_device_info;
-
-+/* Helpers to program the MAC core */
- struct stmmac_ops {
- /* MAC core initialization */
- void (*core_init)(struct mac_device_info *hw, int mtu);
-@@ -400,6 +410,7 @@ struct stmmac_ops {
- void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
- };
-
-+/* PTP and HW Timer helpers */
- struct stmmac_hwtimestamp {
- void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
- void (*config_sub_second_increment) (void __iomem *ioaddr);
-@@ -410,6 +421,8 @@ struct stmmac_hwtimestamp {
- u64(*get_systime) (void __iomem *ioaddr);
- };
-
-+extern const struct stmmac_hwtimestamp stmmac_ptp;
-+
- struct mac_link {
- int port;
- int duplex;
-@@ -421,6 +434,7 @@ struct mii_regs {
- unsigned int data; /* MII Data */
- };
-
-+/* Helpers to manage the descriptors for chain and ring modes */
- struct stmmac_mode_ops {
- void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
- unsigned int extend_desc);
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
-@@ -0,0 +1,81 @@
-+/*
-+ * Generic DWMAC platform driver
-+ *
-+ * Copyright (C) 2007-2011 STMicroelectronics Ltd
-+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+
-+#include "stmmac.h"
-+#include "stmmac_platform.h"
-+
-+static int dwmac_generic_probe(struct platform_device *pdev)
-+{
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
-+ int ret;
-+
-+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
-+ if (ret)
-+ return ret;
-+
-+ if (pdev->dev.of_node) {
-+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
-+ if (IS_ERR(plat_dat)) {
-+ dev_err(&pdev->dev, "dt configuration failed\n");
-+ return PTR_ERR(plat_dat);
-+ }
-+ } else {
-+ plat_dat = dev_get_platdata(&pdev->dev);
-+ if (!plat_dat) {
-+ dev_err(&pdev->dev, "no platform data provided\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Set default value for multicast hash bins */
-+ plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
-+
-+ /* Set default value for unicast filter entries */
-+ plat_dat->unicast_filter_entries = 1;
-+ }
-+
-+ /* Custom initialisation (if needed) */
-+ if (plat_dat->init) {
-+ ret = plat_dat->init(pdev, plat_dat->bsp_priv);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id dwmac_generic_match[] = {
-+ { .compatible = "st,spear600-gmac"},
-+ { .compatible = "snps,dwmac-3.610"},
-+ { .compatible = "snps,dwmac-3.70a"},
-+ { .compatible = "snps,dwmac-3.710"},
-+ { .compatible = "snps,dwmac"},
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, dwmac_generic_match);
-+
-+static struct platform_driver dwmac_generic_driver = {
-+ .probe = dwmac_generic_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = STMMAC_RESOURCE_NAME,
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = of_match_ptr(dwmac_generic_match),
-+ },
-+};
-+module_platform_driver(dwmac_generic_driver);
-+
-+MODULE_DESCRIPTION("Generic dwmac driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
-@@ -0,0 +1,373 @@
-+/*
-+ * Qualcomm Atheros IPQ806x GMAC glue layer
-+ *
-+ * Copyright (C) 2015 The Linux Foundation
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include <linux/phy.h>
-+#include <linux/regmap.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/of_net.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/stmmac.h>
-+#include <linux/of_mdio.h>
-+#include <linux/module.h>
-+
-+#include "stmmac_platform.h"
-+
-+#define NSS_COMMON_CLK_GATE 0x8
-+#define NSS_COMMON_CLK_GATE_PTP_EN(x) BIT(0x10 + x)
-+#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x) BIT(0x9 + (x * 2))
-+#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x) BIT(0x8 + (x * 2))
-+#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x) BIT(0x4 + x)
-+#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x) BIT(0x0 + x)
-+
-+#define NSS_COMMON_CLK_DIV0 0xC
-+#define NSS_COMMON_CLK_DIV_OFFSET(x) (x * 8)
-+#define NSS_COMMON_CLK_DIV_MASK 0x7f
-+
-+#define NSS_COMMON_CLK_SRC_CTRL 0x14
-+#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x) (x)
-+/* Mode is coded on 1 bit but is different depending on the MAC ID:
-+ * MAC0: QSGMII=0 RGMII=1
-+ * MAC1: QSGMII=0 SGMII=0 RGMII=1
-+ * MAC2 & MAC3: QSGMII=0 SGMII=1
-+ */
-+#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x) 1
-+#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x) ((x >= 2) ? 1 : 0)
-+
-+#define NSS_COMMON_MACSEC_CTL 0x28
-+#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x) (1 << x)
-+
-+#define NSS_COMMON_GMAC_CTL(x) (0x30 + (x * 4))
-+#define NSS_COMMON_GMAC_CTL_CSYS_REQ BIT(19)
-+#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL BIT(16)
-+#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET 8
-+#define NSS_COMMON_GMAC_CTL_IFG_OFFSET 0
-+#define NSS_COMMON_GMAC_CTL_IFG_MASK 0x3f
-+
-+#define NSS_COMMON_CLK_DIV_RGMII_1000 1
-+#define NSS_COMMON_CLK_DIV_RGMII_100 9
-+#define NSS_COMMON_CLK_DIV_RGMII_10 99
-+#define NSS_COMMON_CLK_DIV_SGMII_1000 0
-+#define NSS_COMMON_CLK_DIV_SGMII_100 4
-+#define NSS_COMMON_CLK_DIV_SGMII_10 49
-+
-+#define QSGMII_PCS_MODE_CTL 0x68
-+#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x) BIT((x * 8) + 7)
-+
-+#define QSGMII_PCS_CAL_LCKDT_CTL 0x120
-+#define QSGMII_PCS_CAL_LCKDT_CTL_RST BIT(19)
-+
-+/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
-+#define QSGMII_PHY_SGMII_CTL(x) ((x == 1) ? 0x134 : \
-+ (0x13c + (4 * (x - 2))))
-+#define QSGMII_PHY_CDR_EN BIT(0)
-+#define QSGMII_PHY_RX_FRONT_EN BIT(1)
-+#define QSGMII_PHY_RX_SIGNAL_DETECT_EN BIT(2)
-+#define QSGMII_PHY_TX_DRIVER_EN BIT(3)
-+#define QSGMII_PHY_QSGMII_EN BIT(7)
-+#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET 12
-+#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK 0x7
-+#define QSGMII_PHY_RX_DC_BIAS_OFFSET 18
-+#define QSGMII_PHY_RX_DC_BIAS_MASK 0x3
-+#define QSGMII_PHY_RX_INPUT_EQU_OFFSET 20
-+#define QSGMII_PHY_RX_INPUT_EQU_MASK 0x3
-+#define QSGMII_PHY_CDR_PI_SLEW_OFFSET 22
-+#define QSGMII_PHY_CDR_PI_SLEW_MASK 0x3
-+#define QSGMII_PHY_TX_DRV_AMP_OFFSET 28
-+#define QSGMII_PHY_TX_DRV_AMP_MASK 0xf
-+
-+struct ipq806x_gmac {
-+ struct platform_device *pdev;
-+ struct regmap *nss_common;
-+ struct regmap *qsgmii_csr;
-+ uint32_t id;
-+ struct clk *core_clk;
-+ phy_interface_t phy_mode;
-+};
-+
-+static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+ struct device *dev = &gmac->pdev->dev;
-+ int div;
-+
-+ switch (speed) {
-+ case SPEED_1000:
-+ div = NSS_COMMON_CLK_DIV_SGMII_1000;
-+ break;
-+
-+ case SPEED_100:
-+ div = NSS_COMMON_CLK_DIV_SGMII_100;
-+ break;
-+
-+ case SPEED_10:
-+ div = NSS_COMMON_CLK_DIV_SGMII_10;
-+ break;
-+
-+ default:
-+ dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
-+ return -EINVAL;
-+ }
-+
-+ return div;
-+}
-+
-+static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+ struct device *dev = &gmac->pdev->dev;
-+ int div;
-+
-+ switch (speed) {
-+ case SPEED_1000:
-+ div = NSS_COMMON_CLK_DIV_RGMII_1000;
-+ break;
-+
-+ case SPEED_100:
-+ div = NSS_COMMON_CLK_DIV_RGMII_100;
-+ break;
-+
-+ case SPEED_10:
-+ div = NSS_COMMON_CLK_DIV_RGMII_10;
-+ break;
-+
-+ default:
-+ dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
-+ return -EINVAL;
-+ }
-+
-+ return div;
-+}
-+
-+static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+ uint32_t clk_bits, val;
-+ int div;
-+
-+ switch (gmac->phy_mode) {
-+ case PHY_INTERFACE_MODE_RGMII:
-+ div = get_clk_div_rgmii(gmac, speed);
-+ clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
-+ NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
-+ break;
-+
-+ case PHY_INTERFACE_MODE_SGMII:
-+ div = get_clk_div_sgmii(gmac, speed);
-+ clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
-+ NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
-+ break;
-+
-+ default:
-+ dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+ phy_modes(gmac->phy_mode));
-+ return -EINVAL;
-+ }
-+
-+ /* Disable the clocks */
-+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+ val &= ~clk_bits;
-+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+ /* Set the divider */
-+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
-+ val &= ~(NSS_COMMON_CLK_DIV_MASK
-+ << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
-+ val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
-+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
-+
-+ /* Enable the clock back */
-+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+ val |= clk_bits;
-+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+ return 0;
-+}
-+
-+static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
-+{
-+ struct device *dev = &gmac->pdev->dev;
-+
-+ gmac->phy_mode = of_get_phy_mode(dev->of_node);
-+ if (gmac->phy_mode < 0) {
-+ dev_err(dev, "missing phy mode property\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
-+ dev_err(dev, "missing qcom id property\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ /* The GMACs are called 1 to 4 in the documentation, but to simplify the
-+ * code and keep it consistent with the Linux convention, we'll number
-+ * them from 0 to 3 here.
-+ */
-+ if (gmac->id < 0 || gmac->id > 3) {
-+ dev_err(dev, "invalid gmac id\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ gmac->core_clk = devm_clk_get(dev, "stmmaceth");
-+ if (IS_ERR(gmac->core_clk)) {
-+ dev_err(dev, "missing stmmaceth clk property\n");
-+ return gmac->core_clk;
-+ }
-+ clk_set_rate(gmac->core_clk, 266000000);
-+
-+ /* Setup the register map for the nss common registers */
-+ gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
-+ "qcom,nss-common");
-+ if (IS_ERR(gmac->nss_common)) {
-+ dev_err(dev, "missing nss-common node\n");
-+ return gmac->nss_common;
-+ }
-+
-+ /* Setup the register map for the qsgmii csr registers */
-+ gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
-+ "qcom,qsgmii-csr");
-+ if (IS_ERR(gmac->qsgmii_csr)) {
-+ dev_err(dev, "missing qsgmii-csr node\n");
-+ return gmac->qsgmii_csr;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
-+{
-+ struct ipq806x_gmac *gmac = priv;
-+
-+ ipq806x_gmac_set_speed(gmac, speed);
-+}
-+
-+static int ipq806x_gmac_probe(struct platform_device *pdev)
-+{
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
-+ struct device *dev = &pdev->dev;
-+ struct ipq806x_gmac *gmac;
-+ int val;
-+ void *err;
-+
-+ val = stmmac_get_platform_resources(pdev, &stmmac_res);
-+ if (val)
-+ return val;
-+
-+ 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->pdev = pdev;
-+
-+ err = ipq806x_gmac_of_parse(gmac);
-+ if (IS_ERR(err)) {
-+ dev_err(dev, "device tree parsing error\n");
-+ return PTR_ERR(err);
-+ }
-+
-+ regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
-+ QSGMII_PCS_CAL_LCKDT_CTL_RST);
-+
-+ /* Inter frame gap is set to 12 */
-+ val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
-+ 12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
-+ /* We also initiate an AXI low power exit request */
-+ val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
-+ switch (gmac->phy_mode) {
-+ case PHY_INTERFACE_MODE_RGMII:
-+ val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
-+ break;
-+ case PHY_INTERFACE_MODE_SGMII:
-+ val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
-+ break;
-+ default:
-+ dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+ phy_modes(gmac->phy_mode));
-+ return -EINVAL;
-+ }
-+ regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
-+
-+ /* Configure the clock src according to the mode */
-+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
-+ val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id));
-+ switch (gmac->phy_mode) {
-+ case PHY_INTERFACE_MODE_RGMII:
-+ val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
-+ NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
-+ break;
-+ case PHY_INTERFACE_MODE_SGMII:
-+ val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
-+ NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
-+ break;
-+ default:
-+ dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+ phy_modes(gmac->phy_mode));
-+ return -EINVAL;
-+ }
-+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
-+
-+ /* Enable PTP clock */
-+ regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+ val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
-+ regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+ if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
-+ regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
-+ QSGMII_PHY_CDR_EN |
-+ QSGMII_PHY_RX_FRONT_EN |
-+ QSGMII_PHY_RX_SIGNAL_DETECT_EN |
-+ QSGMII_PHY_TX_DRIVER_EN |
-+ QSGMII_PHY_QSGMII_EN |
-+ 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
-+ 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
-+ 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
-+ 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
-+ 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
-+ }
-+
-+ plat_dat->has_gmac = true;
-+ plat_dat->bsp_priv = gmac;
-+ plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
-+ { .compatible = "qcom,ipq806x-gmac" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
-+
-+static struct platform_driver ipq806x_gmac_dwmac_driver = {
-+ .probe = ipq806x_gmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "ipq806x-gmac-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = ipq806x_gmac_dwmac_match,
-+ },
-+};
-+module_platform_driver(ipq806x_gmac_dwmac_driver);
-+
-+MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>");
-+MODULE_DESCRIPTION("Qualcomm Atheros IPQ806x DWMAC specific glue layer");
-+MODULE_LICENSE("Dual BSD/GPL");
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
-@@ -0,0 +1,86 @@
-+/*
-+ * DWMAC glue for NXP LPC18xx/LPC43xx Ethernet
-+ *
-+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+
-+#include <linux/mfd/syscon.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_net.h>
-+#include <linux/phy.h>
-+#include <linux/platform_device.h>
-+#include <linux/regmap.h>
-+#include <linux/stmmac.h>
-+
-+#include "stmmac_platform.h"
-+
-+/* Register defines for CREG syscon */
-+#define LPC18XX_CREG_CREG6 0x12c
-+# define LPC18XX_CREG_CREG6_ETHMODE_MASK 0x7
-+# define LPC18XX_CREG_CREG6_ETHMODE_MII 0x0
-+# define LPC18XX_CREG_CREG6_ETHMODE_RMII 0x4
-+
-+static int lpc18xx_dwmac_probe(struct platform_device *pdev)
-+{
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
-+ struct regmap *reg;
-+ u8 ethmode;
-+ 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);
-+
-+ plat_dat->has_gmac = true;
-+
-+ reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
-+ if (IS_ERR(reg)) {
-+ dev_err(&pdev->dev, "syscon lookup failed\n");
-+ return PTR_ERR(reg);
-+ }
-+
-+ if (plat_dat->interface == PHY_INTERFACE_MODE_MII) {
-+ ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII;
-+ } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) {
-+ ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII;
-+ } else {
-+ dev_err(&pdev->dev, "Only MII and RMII mode supported\n");
-+ return -EINVAL;
-+ }
-+
-+ regmap_update_bits(reg, LPC18XX_CREG_CREG6,
-+ LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode);
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id lpc18xx_dwmac_match[] = {
-+ { .compatible = "nxp,lpc1850-dwmac" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match);
-+
-+static struct platform_driver lpc18xx_dwmac_driver = {
-+ .probe = lpc18xx_dwmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "lpc18xx-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = lpc18xx_dwmac_match,
-+ },
-+};
-+module_platform_driver(lpc18xx_dwmac_driver);
-+
-+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
-+MODULE_DESCRIPTION("DWMAC glue for LPC18xx/43xx Ethernet");
-+MODULE_LICENSE("GPL v2");
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
-@@ -15,9 +15,12 @@
- #include <linux/ethtool.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
-+#include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/stmmac.h>
-
-+#include "stmmac_platform.h"
-+
- #define ETHMAC_SPEED_100 BIT(1)
-
- struct meson_dwmac {
-@@ -44,24 +47,54 @@ static void meson6_dwmac_fix_mac_speed(v
- writel(val, dwmac->reg);
- }
-
--static void *meson6_dwmac_setup(struct platform_device *pdev)
-+static int meson6_dwmac_probe(struct platform_device *pdev)
- {
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
- struct meson_dwmac *dwmac;
- struct resource *res;
-+ 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);
-
- dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
- if (!dwmac)
-- return ERR_PTR(-ENOMEM);
-+ return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- dwmac->reg = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(dwmac->reg))
-- return dwmac->reg;
-+ return PTR_ERR(dwmac->reg);
-+
-+ plat_dat->bsp_priv = dwmac;
-+ plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
-
-- return dwmac;
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- }
-
--const struct stmmac_of_data meson6_dwmac_data = {
-- .setup = meson6_dwmac_setup,
-- .fix_mac_speed = meson6_dwmac_fix_mac_speed,
-+static const struct of_device_id meson6_dwmac_match[] = {
-+ { .compatible = "amlogic,meson6-dwmac" },
-+ { }
- };
-+MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
-+
-+static struct platform_driver meson6_dwmac_driver = {
-+ .probe = meson6_dwmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "meson6-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = meson6_dwmac_match,
-+ },
-+};
-+module_platform_driver(meson6_dwmac_driver);
-+
-+MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
-+MODULE_DESCRIPTION("Amlogic Meson DWMAC glue layer");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
-@@ -0,0 +1,626 @@
-+/**
-+ * dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer
-+ *
-+ * Copyright (C) 2014 Chen-Zhi (Roger Chen)
-+ *
-+ * Chen-Zhi (Roger Chen) <roger.chen@rock-chips.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/stmmac.h>
-+#include <linux/bitops.h>
-+#include <linux/clk.h>
-+#include <linux/phy.h>
-+#include <linux/of_net.h>
-+#include <linux/gpio.h>
-+#include <linux/module.h>
-+#include <linux/of_gpio.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/delay.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+
-+#include "stmmac_platform.h"
-+
-+struct rk_priv_data;
-+struct rk_gmac_ops {
-+ void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
-+ int tx_delay, int rx_delay);
-+ void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
-+ void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
-+ void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
-+};
-+
-+struct rk_priv_data {
-+ struct platform_device *pdev;
-+ int phy_iface;
-+ struct regulator *regulator;
-+ const struct rk_gmac_ops *ops;
-+
-+ bool clk_enabled;
-+ bool clock_input;
-+
-+ struct clk *clk_mac;
-+ struct clk *gmac_clkin;
-+ struct clk *mac_clk_rx;
-+ struct clk *mac_clk_tx;
-+ struct clk *clk_mac_ref;
-+ struct clk *clk_mac_refout;
-+ struct clk *aclk_mac;
-+ struct clk *pclk_mac;
-+
-+ int tx_delay;
-+ int rx_delay;
-+
-+ struct regmap *grf;
-+};
-+
-+#define HIWORD_UPDATE(val, mask, shift) \
-+ ((val) << (shift) | (mask) << ((shift) + 16))
-+
-+#define GRF_BIT(nr) (BIT(nr) | BIT(nr+16))
-+#define GRF_CLR_BIT(nr) (BIT(nr+16))
-+
-+#define RK3288_GRF_SOC_CON1 0x0248
-+#define RK3288_GRF_SOC_CON3 0x0250
-+
-+/*RK3288_GRF_SOC_CON1*/
-+#define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \
-+ GRF_CLR_BIT(8))
-+#define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
-+ GRF_BIT(8))
-+#define RK3288_GMAC_FLOW_CTRL GRF_BIT(9)
-+#define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9)
-+#define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10)
-+#define RK3288_GMAC_SPEED_100M GRF_BIT(10)
-+#define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11)
-+#define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11)
-+#define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
-+#define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13))
-+#define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13))
-+#define RK3288_GMAC_RMII_MODE GRF_BIT(14)
-+#define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14)
-+
-+/*RK3288_GRF_SOC_CON3*/
-+#define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
-+#define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
-+#define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
-+#define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
-+#define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
-+#define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
-+
-+static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
-+ int tx_delay, int rx_delay)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "Missing rockchip,grf property\n");
-+ return;
-+ }
-+
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_PHY_INTF_SEL_RGMII |
-+ RK3288_GMAC_RMII_MODE_CLR);
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
-+ RK3288_GMAC_RXCLK_DLY_ENABLE |
-+ RK3288_GMAC_TXCLK_DLY_ENABLE |
-+ RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
-+ RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
-+}
-+
-+static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "Missing rockchip,grf property\n");
-+ return;
-+ }
-+
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
-+}
-+
-+static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "Missing rockchip,grf property\n");
-+ return;
-+ }
-+
-+ if (speed == 10)
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_CLK_2_5M);
-+ else if (speed == 100)
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_CLK_25M);
-+ else if (speed == 1000)
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_CLK_125M);
-+ else
-+ dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
-+}
-+
-+static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "Missing rockchip,grf property\n");
-+ return;
-+ }
-+
-+ if (speed == 10) {
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_RMII_CLK_2_5M |
-+ RK3288_GMAC_SPEED_10M);
-+ } else if (speed == 100) {
-+ regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-+ RK3288_GMAC_RMII_CLK_25M |
-+ RK3288_GMAC_SPEED_100M);
-+ } else {
-+ dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
-+ }
-+}
-+
-+static const struct rk_gmac_ops rk3288_ops = {
-+ .set_to_rgmii = rk3288_set_to_rgmii,
-+ .set_to_rmii = rk3288_set_to_rmii,
-+ .set_rgmii_speed = rk3288_set_rgmii_speed,
-+ .set_rmii_speed = rk3288_set_rmii_speed,
-+};
-+
-+#define RK3368_GRF_SOC_CON15 0x043c
-+#define RK3368_GRF_SOC_CON16 0x0440
-+
-+/* RK3368_GRF_SOC_CON15 */
-+#define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \
-+ GRF_CLR_BIT(11))
-+#define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
-+ GRF_BIT(11))
-+#define RK3368_GMAC_FLOW_CTRL GRF_BIT(8)
-+#define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8)
-+#define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7)
-+#define RK3368_GMAC_SPEED_100M GRF_BIT(7)
-+#define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3)
-+#define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3)
-+#define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
-+#define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5))
-+#define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5))
-+#define RK3368_GMAC_RMII_MODE GRF_BIT(6)
-+#define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6)
-+
-+/* RK3368_GRF_SOC_CON16 */
-+#define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
-+#define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
-+#define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
-+#define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
-+#define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
-+#define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
-+
-+static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
-+ int tx_delay, int rx_delay)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-+ return;
-+ }
-+
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_PHY_INTF_SEL_RGMII |
-+ RK3368_GMAC_RMII_MODE_CLR);
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
-+ RK3368_GMAC_RXCLK_DLY_ENABLE |
-+ RK3368_GMAC_TXCLK_DLY_ENABLE |
-+ RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
-+ RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
-+}
-+
-+static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-+ return;
-+ }
-+
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
-+}
-+
-+static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-+ return;
-+ }
-+
-+ if (speed == 10)
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_CLK_2_5M);
-+ else if (speed == 100)
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_CLK_25M);
-+ else if (speed == 1000)
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_CLK_125M);
-+ else
-+ dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
-+}
-+
-+static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (IS_ERR(bsp_priv->grf)) {
-+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
-+ return;
-+ }
-+
-+ if (speed == 10) {
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_RMII_CLK_2_5M |
-+ RK3368_GMAC_SPEED_10M);
-+ } else if (speed == 100) {
-+ regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
-+ RK3368_GMAC_RMII_CLK_25M |
-+ RK3368_GMAC_SPEED_100M);
-+ } else {
-+ dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
-+ }
-+}
-+
-+static const struct rk_gmac_ops rk3368_ops = {
-+ .set_to_rgmii = rk3368_set_to_rgmii,
-+ .set_to_rmii = rk3368_set_to_rmii,
-+ .set_rgmii_speed = rk3368_set_rgmii_speed,
-+ .set_rmii_speed = rk3368_set_rmii_speed,
-+};
-+
-+static int gmac_clk_init(struct rk_priv_data *bsp_priv)
-+{
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ bsp_priv->clk_enabled = false;
-+
-+ bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
-+ if (IS_ERR(bsp_priv->mac_clk_rx))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "mac_clk_rx");
-+
-+ bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
-+ if (IS_ERR(bsp_priv->mac_clk_tx))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "mac_clk_tx");
-+
-+ bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
-+ if (IS_ERR(bsp_priv->aclk_mac))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "aclk_mac");
-+
-+ bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
-+ if (IS_ERR(bsp_priv->pclk_mac))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "pclk_mac");
-+
-+ bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
-+ if (IS_ERR(bsp_priv->clk_mac))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "stmmaceth");
-+
-+ if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
-+ bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
-+ if (IS_ERR(bsp_priv->clk_mac_ref))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "clk_mac_ref");
-+
-+ if (!bsp_priv->clock_input) {
-+ bsp_priv->clk_mac_refout =
-+ devm_clk_get(dev, "clk_mac_refout");
-+ if (IS_ERR(bsp_priv->clk_mac_refout))
-+ dev_err(dev, "cannot get clock %s\n",
-+ "clk_mac_refout");
-+ }
-+ }
-+
-+ if (bsp_priv->clock_input) {
-+ dev_info(dev, "clock input from PHY\n");
-+ } else {
-+ if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-+ clk_set_rate(bsp_priv->clk_mac, 50000000);
-+ }
-+
-+ return 0;
-+}
-+
-+static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
-+{
-+ int phy_iface = phy_iface = bsp_priv->phy_iface;
-+
-+ if (enable) {
-+ if (!bsp_priv->clk_enabled) {
-+ if (phy_iface == PHY_INTERFACE_MODE_RMII) {
-+ if (!IS_ERR(bsp_priv->mac_clk_rx))
-+ clk_prepare_enable(
-+ bsp_priv->mac_clk_rx);
-+
-+ if (!IS_ERR(bsp_priv->clk_mac_ref))
-+ clk_prepare_enable(
-+ bsp_priv->clk_mac_ref);
-+
-+ if (!IS_ERR(bsp_priv->clk_mac_refout))
-+ clk_prepare_enable(
-+ bsp_priv->clk_mac_refout);
-+ }
-+
-+ if (!IS_ERR(bsp_priv->aclk_mac))
-+ clk_prepare_enable(bsp_priv->aclk_mac);
-+
-+ if (!IS_ERR(bsp_priv->pclk_mac))
-+ clk_prepare_enable(bsp_priv->pclk_mac);
-+
-+ if (!IS_ERR(bsp_priv->mac_clk_tx))
-+ clk_prepare_enable(bsp_priv->mac_clk_tx);
-+
-+ /**
-+ * if (!IS_ERR(bsp_priv->clk_mac))
-+ * clk_prepare_enable(bsp_priv->clk_mac);
-+ */
-+ mdelay(5);
-+ bsp_priv->clk_enabled = true;
-+ }
-+ } else {
-+ if (bsp_priv->clk_enabled) {
-+ if (phy_iface == PHY_INTERFACE_MODE_RMII) {
-+ if (!IS_ERR(bsp_priv->mac_clk_rx))
-+ clk_disable_unprepare(
-+ bsp_priv->mac_clk_rx);
-+
-+ if (!IS_ERR(bsp_priv->clk_mac_ref))
-+ clk_disable_unprepare(
-+ bsp_priv->clk_mac_ref);
-+
-+ if (!IS_ERR(bsp_priv->clk_mac_refout))
-+ clk_disable_unprepare(
-+ bsp_priv->clk_mac_refout);
-+ }
-+
-+ if (!IS_ERR(bsp_priv->aclk_mac))
-+ clk_disable_unprepare(bsp_priv->aclk_mac);
-+
-+ if (!IS_ERR(bsp_priv->pclk_mac))
-+ clk_disable_unprepare(bsp_priv->pclk_mac);
-+
-+ if (!IS_ERR(bsp_priv->mac_clk_tx))
-+ clk_disable_unprepare(bsp_priv->mac_clk_tx);
-+ /**
-+ * if (!IS_ERR(bsp_priv->clk_mac))
-+ * clk_disable_unprepare(bsp_priv->clk_mac);
-+ */
-+ bsp_priv->clk_enabled = false;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
-+{
-+ struct regulator *ldo = bsp_priv->regulator;
-+ int ret;
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (!ldo) {
-+ dev_err(dev, "no regulator found\n");
-+ return -1;
-+ }
-+
-+ if (enable) {
-+ ret = regulator_enable(ldo);
-+ if (ret)
-+ dev_err(dev, "fail to enable phy-supply\n");
-+ } else {
-+ ret = regulator_disable(ldo);
-+ if (ret)
-+ dev_err(dev, "fail to disable phy-supply\n");
-+ }
-+
-+ return 0;
-+}
-+
-+static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
-+ const struct rk_gmac_ops *ops)
-+{
-+ struct rk_priv_data *bsp_priv;
-+ struct device *dev = &pdev->dev;
-+ int ret;
-+ const char *strings = NULL;
-+ int value;
-+
-+ bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
-+ if (!bsp_priv)
-+ return ERR_PTR(-ENOMEM);
-+
-+ bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
-+ bsp_priv->ops = ops;
-+
-+ bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
-+ if (IS_ERR(bsp_priv->regulator)) {
-+ if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
-+ dev_err(dev, "phy regulator is not available yet, deferred probing\n");
-+ return ERR_PTR(-EPROBE_DEFER);
-+ }
-+ dev_err(dev, "no regulator found\n");
-+ bsp_priv->regulator = NULL;
-+ }
-+
-+ ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
-+ if (ret) {
-+ dev_err(dev, "Can not read property: clock_in_out.\n");
-+ bsp_priv->clock_input = true;
-+ } else {
-+ dev_info(dev, "clock input or output? (%s).\n",
-+ strings);
-+ if (!strcmp(strings, "input"))
-+ bsp_priv->clock_input = true;
-+ else
-+ bsp_priv->clock_input = false;
-+ }
-+
-+ ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
-+ if (ret) {
-+ bsp_priv->tx_delay = 0x30;
-+ dev_err(dev, "Can not read property: tx_delay.");
-+ dev_err(dev, "set tx_delay to 0x%x\n",
-+ bsp_priv->tx_delay);
-+ } else {
-+ dev_info(dev, "TX delay(0x%x).\n", value);
-+ bsp_priv->tx_delay = value;
-+ }
-+
-+ ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
-+ if (ret) {
-+ bsp_priv->rx_delay = 0x10;
-+ dev_err(dev, "Can not read property: rx_delay.");
-+ dev_err(dev, "set rx_delay to 0x%x\n",
-+ bsp_priv->rx_delay);
-+ } else {
-+ dev_info(dev, "RX delay(0x%x).\n", value);
-+ bsp_priv->rx_delay = value;
-+ }
-+
-+ bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
-+ "rockchip,grf");
-+ bsp_priv->pdev = pdev;
-+
-+ /*rmii or rgmii*/
-+ if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
-+ dev_info(dev, "init for RGMII\n");
-+ bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
-+ bsp_priv->rx_delay);
-+ } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
-+ dev_info(dev, "init for RMII\n");
-+ bsp_priv->ops->set_to_rmii(bsp_priv);
-+ } else {
-+ dev_err(dev, "NO interface defined!\n");
-+ }
-+
-+ gmac_clk_init(bsp_priv);
-+
-+ return bsp_priv;
-+}
-+
-+static int rk_gmac_init(struct platform_device *pdev, void *priv)
-+{
-+ struct rk_priv_data *bsp_priv = priv;
-+ int ret;
-+
-+ ret = phy_power_on(bsp_priv, true);
-+ if (ret)
-+ return ret;
-+
-+ ret = gmac_clk_enable(bsp_priv, true);
-+ if (ret)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static void rk_gmac_exit(struct platform_device *pdev, void *priv)
-+{
-+ struct rk_priv_data *gmac = priv;
-+
-+ phy_power_on(gmac, false);
-+ gmac_clk_enable(gmac, false);
-+}
-+
-+static void rk_fix_speed(void *priv, unsigned int speed)
-+{
-+ struct rk_priv_data *bsp_priv = priv;
-+ struct device *dev = &bsp_priv->pdev->dev;
-+
-+ if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
-+ bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
-+ else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-+ bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
-+ else
-+ dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
-+}
-+
-+static int rk_gmac_probe(struct platform_device *pdev)
-+{
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
-+ const struct rk_gmac_ops *data;
-+ int ret;
-+
-+ data = of_device_get_match_data(&pdev->dev);
-+ if (!data) {
-+ dev_err(&pdev->dev, "no of match data provided\n");
-+ return -EINVAL;
-+ }
-+
-+ 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);
-+
-+ plat_dat->has_gmac = true;
-+ plat_dat->init = rk_gmac_init;
-+ plat_dat->exit = rk_gmac_exit;
-+ plat_dat->fix_mac_speed = rk_fix_speed;
-+
-+ plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
-+ if (IS_ERR(plat_dat->bsp_priv))
-+ return PTR_ERR(plat_dat->bsp_priv);
-+
-+ ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
-+ if (ret)
-+ return ret;
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id rk_gmac_dwmac_match[] = {
-+ { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
-+ { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
-+
-+static struct platform_driver rk_gmac_dwmac_driver = {
-+ .probe = rk_gmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "rk_gmac-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = rk_gmac_dwmac_match,
-+ },
-+};
-+module_platform_driver(rk_gmac_dwmac_driver);
-+
-+MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
-+MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
-+MODULE_LICENSE("GPL");
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
-@@ -23,7 +23,9 @@
- #include <linux/regmap.h>
- #include <linux/reset.h>
- #include <linux/stmmac.h>
-+
- #include "stmmac.h"
-+#include "stmmac_platform.h"
-
- #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
- #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
-@@ -89,7 +91,9 @@ static int socfpga_dwmac_parse_data(stru
- STMMAC_RESOURCE_NAME);
- if (IS_ERR(dwmac->stmmac_rst)) {
- dev_info(dev, "Could not get reset control!\n");
-- return -EINVAL;
-+ if (PTR_ERR(dwmac->stmmac_rst) == -EPROBE_DEFER)
-+ return -EPROBE_DEFER;
-+ dwmac->stmmac_rst = NULL;
- }
-
- dwmac->interface = of_get_phy_mode(np);
-@@ -171,31 +175,6 @@ static int socfpga_dwmac_setup(struct so
- return 0;
- }
-
--static void *socfpga_dwmac_probe(struct platform_device *pdev)
--{
-- struct device *dev = &pdev->dev;
-- int ret;
-- struct socfpga_dwmac *dwmac;
--
-- dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
-- if (!dwmac)
-- return ERR_PTR(-ENOMEM);
--
-- ret = socfpga_dwmac_parse_data(dwmac, dev);
-- if (ret) {
-- dev_err(dev, "Unable to parse OF data\n");
-- return ERR_PTR(ret);
-- }
--
-- ret = socfpga_dwmac_setup(dwmac);
-- if (ret) {
-- dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
-- return ERR_PTR(ret);
-- }
--
-- return dwmac;
--}
--
- static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
- {
- struct socfpga_dwmac *dwmac = priv;
-@@ -253,9 +232,65 @@ static int socfpga_dwmac_init(struct pla
- return ret;
- }
-
--const struct stmmac_of_data socfpga_gmac_data = {
-- .setup = socfpga_dwmac_probe,
-- .init = socfpga_dwmac_init,
-- .exit = socfpga_dwmac_exit,
-- .fix_mac_speed = socfpga_dwmac_fix_mac_speed,
-+static int socfpga_dwmac_probe(struct platform_device *pdev)
-+{
-+ struct plat_stmmacenet_data *plat_dat;
-+ struct stmmac_resources stmmac_res;
-+ struct device *dev = &pdev->dev;
-+ int ret;
-+ struct socfpga_dwmac *dwmac;
-+
-+ 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);
-+
-+ dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
-+ if (!dwmac)
-+ return -ENOMEM;
-+
-+ ret = socfpga_dwmac_parse_data(dwmac, dev);
-+ if (ret) {
-+ dev_err(dev, "Unable to parse OF data\n");
-+ return ret;
-+ }
-+
-+ ret = socfpga_dwmac_setup(dwmac);
-+ if (ret) {
-+ dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
-+ return ret;
-+ }
-+
-+ plat_dat->bsp_priv = dwmac;
-+ plat_dat->init = socfpga_dwmac_init;
-+ plat_dat->exit = socfpga_dwmac_exit;
-+ plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
-+
-+ ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv);
-+ if (ret)
-+ return ret;
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id socfpga_dwmac_match[] = {
-+ { .compatible = "altr,socfpga-stmmac" },
-+ { }
- };
-+MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
-+
-+static struct platform_driver socfpga_dwmac_driver = {
-+ .probe = socfpga_dwmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "socfpga-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = socfpga_dwmac_match,
-+ },
-+};
-+module_platform_driver(socfpga_dwmac_driver);
-+
-+MODULE_LICENSE("GPL v2");
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
-@@ -1,4 +1,4 @@
--/**
-+/*
- * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
- *
- * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
-@@ -17,11 +17,15 @@
- #include <linux/stmmac.h>
- #include <linux/phy.h>
- #include <linux/mfd/syscon.h>
-+#include <linux/module.h>
- #include <linux/regmap.h>
- #include <linux/clk.h>
- #include <linux/of.h>
-+#include <linux/of_device.h>
- #include <linux/of_net.h>
-
-+#include "stmmac_platform.h"
-+
- #define DWMAC_125MHZ 125000000
- #define DWMAC_50MHZ 50000000
- #define DWMAC_25MHZ 25000000
-@@ -35,9 +39,8 @@
- #define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \
- iface == PHY_INTERFACE_MODE_GMII)
-
--/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families) */
--
--/**
-+/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
-+ *
- * Below table summarizes the clock requirement and clock sources for
- * supported phy interface modes with link speeds.
- * ________________________________________________
-@@ -76,9 +79,7 @@
- #define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
- #define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125 BIT(6)
-
--/* STiD127 register definitions */
--
--/**
-+/* STiD127 register definitions
- *-----------------------
- * src |BIT(6)| BIT(7)|
- *-----------------------
-@@ -104,13 +105,13 @@
- #define EN_MASK GENMASK(1, 1)
- #define EN BIT(1)
-
--/**
-+/*
- * 3 bits [4:2]
- * 000-GMII/MII
- * 001-RGMII
- * 010-SGMII
- * 100-RMII
--*/
-+ */
- #define MII_PHY_SEL_MASK GENMASK(4, 2)
- #define ETH_PHY_SEL_RMII BIT(4)
- #define ETH_PHY_SEL_SGMII BIT(3)
-@@ -123,11 +124,16 @@ struct sti_dwmac {
- bool ext_phyclk; /* Clock from external PHY */
- u32 tx_retime_src; /* TXCLK Retiming*/
- struct clk *clk; /* PHY clock */
-- int ctrl_reg; /* GMAC glue-logic control register */
-+ u32 ctrl_reg; /* GMAC glue-logic control register */
- int clk_sel_reg; /* GMAC ext clk selection register */
- struct device *dev;
- struct regmap *regmap;
- u32 speed;
-+ void (*fix_retime_src)(void *priv, unsigned int speed);
-+};
-+
-+struct sti_dwmac_of_data {
-+ void (*fix_retime_src)(void *priv, unsigned int speed);
- };
-
- static u32 phy_intf_sels[] = {
-@@ -222,8 +228,9 @@ static void stid127_fix_retime_src(void
- regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
- }
-
--static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
-+static int sti_dwmac_init(struct platform_device *pdev, void *priv)
- {
-+ struct sti_dwmac *dwmac = priv;
- struct regmap *regmap = dwmac->regmap;
- int iface = dwmac->interface;
- struct device *dev = dwmac->dev;
-@@ -241,28 +248,8 @@ static void sti_dwmac_ctrl_init(struct s
-
- val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
- regmap_update_bits(regmap, reg, ENMII_MASK, val);
--}
-
--static int stix4xx_init(struct platform_device *pdev, void *priv)
--{
-- struct sti_dwmac *dwmac = priv;
-- u32 spd = dwmac->speed;
--
-- sti_dwmac_ctrl_init(dwmac);
--
-- stih4xx_fix_retime_src(priv, spd);
--
-- return 0;
--}
--
--static int stid127_init(struct platform_device *pdev, void *priv)
--{
-- struct sti_dwmac *dwmac = priv;
-- u32 spd = dwmac->speed;
--
-- sti_dwmac_ctrl_init(dwmac);
--
-- stid127_fix_retime_src(priv, spd);
-+ dwmac->fix_retime_src(priv, dwmac->speed);
-
- return 0;
- }
-@@ -286,11 +273,6 @@ static int sti_dwmac_parse_data(struct s
- if (!np)
- return -EINVAL;
-
-- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
-- if (!res)
-- return -ENODATA;
-- dwmac->ctrl_reg = res->start;
--
- /* clk selection from extra syscfg register */
- dwmac->clk_sel_reg = -ENXIO;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
-@@ -301,6 +283,12 @@ static int sti_dwmac_parse_data(struct s
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
-+ err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
-+ if (err) {
-+ dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
-+ return err;
-+ }
-+
- dwmac->dev = dev;
- dwmac->interface = of_get_phy_mode(np);
- dwmac->regmap = regmap;
-@@ -310,16 +298,16 @@ static int sti_dwmac_parse_data(struct s
-
- if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
- const char *rs;
-- dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
-
- err = of_property_read_string(np, "st,tx-retime-src", &rs);
-- if (err < 0)
-+ if (err < 0) {
- dev_warn(dev, "Use internal clock source\n");
--
-- if (!strcasecmp(rs, "clk_125"))
-+ dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
-+ } else if (!strcasecmp(rs, "clk_125")) {
- dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
-- else if (!strcasecmp(rs, "txclk"))
-+ } else if (!strcasecmp(rs, "txclk")) {
- dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
-+ }
-
- dwmac->speed = SPEED_1000;
- }
-@@ -333,34 +321,80 @@ static int sti_dwmac_parse_data(struct s
- return 0;
- }
-
--static void *sti_dwmac_setup(struct platform_device *pdev)
-+static int sti_dwmac_probe(struct platform_device *pdev)
- {
-+ struct plat_stmmacenet_data *plat_dat;
-+ const struct sti_dwmac_of_data *data;
-+ struct stmmac_resources stmmac_res;
- struct sti_dwmac *dwmac;
- int ret;
-
-+ data = of_device_get_match_data(&pdev->dev);
-+ if (!data) {
-+ dev_err(&pdev->dev, "No OF match data provided\n");
-+ return -EINVAL;
-+ }
-+
-+ 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);
-+
- dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
- if (!dwmac)
-- return ERR_PTR(-ENOMEM);
-+ return -ENOMEM;
-
- ret = sti_dwmac_parse_data(dwmac, pdev);
- if (ret) {
- dev_err(&pdev->dev, "Unable to parse OF data\n");
-- return ERR_PTR(ret);
-+ return ret;
- }
-
-- return dwmac;
-+ dwmac->fix_retime_src = data->fix_retime_src;
-+
-+ plat_dat->bsp_priv = dwmac;
-+ plat_dat->init = sti_dwmac_init;
-+ plat_dat->exit = sti_dwmac_exit;
-+ plat_dat->fix_mac_speed = data->fix_retime_src;
-+
-+ ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
-+ if (ret)
-+ return ret;
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- }
-
--const struct stmmac_of_data stih4xx_dwmac_data = {
-- .fix_mac_speed = stih4xx_fix_retime_src,
-- .setup = sti_dwmac_setup,
-- .init = stix4xx_init,
-- .exit = sti_dwmac_exit,
-+static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
-+ .fix_retime_src = stih4xx_fix_retime_src,
- };
-
--const struct stmmac_of_data stid127_dwmac_data = {
-- .fix_mac_speed = stid127_fix_retime_src,
-- .setup = sti_dwmac_setup,
-- .init = stid127_init,
-- .exit = sti_dwmac_exit,
-+static const struct sti_dwmac_of_data stid127_dwmac_data = {
-+ .fix_retime_src = stid127_fix_retime_src,
- };
-+
-+static const struct of_device_id sti_dwmac_match[] = {
-+ { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
-+ { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
-+ { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
-+ { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, sti_dwmac_match);
-+
-+static struct platform_driver sti_dwmac_driver = {
-+ .probe = sti_dwmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "sti-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = sti_dwmac_match,
-+ },
-+};
-+module_platform_driver(sti_dwmac_driver);
-+
-+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>");
-+MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer");
-+MODULE_LICENSE("GPL");
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
-@@ -1,4 +1,4 @@
--/**
-+/*
- * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
- *
- * Copyright (C) 2013 Chen-Yu Tsai
-@@ -18,10 +18,14 @@
-
- #include <linux/stmmac.h>
- #include <linux/clk.h>
-+#include <linux/module.h>
- #include <linux/phy.h>
-+#include <linux/platform_device.h>
- #include <linux/of_net.h>
- #include <linux/regulator/consumer.h>
-
-+#include "stmmac_platform.h"
-+
- struct sunxi_priv_data {
- int interface;
- int clk_enabled;
-@@ -29,35 +33,6 @@ struct sunxi_priv_data {
- struct regulator *regulator;
- };
-
--static void *sun7i_gmac_setup(struct platform_device *pdev)
--{
-- struct sunxi_priv_data *gmac;
-- struct device *dev = &pdev->dev;
--
-- gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
-- if (!gmac)
-- return ERR_PTR(-ENOMEM);
--
-- gmac->interface = of_get_phy_mode(dev->of_node);
--
-- gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
-- if (IS_ERR(gmac->tx_clk)) {
-- dev_err(dev, "could not get tx clock\n");
-- return 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 ERR_PTR(-EPROBE_DEFER);
-- dev_info(dev, "no regulator found\n");
-- gmac->regulator = NULL;
-- }
--
-- return gmac;
--}
--
- #define SUN7I_GMAC_GMII_RGMII_RATE 125000000
- #define SUN7I_GMAC_MII_RATE 25000000
-
-@@ -128,13 +103,76 @@ static void sun7i_fix_speed(void *priv,
- }
- }
-
--/* of_data specifying hardware features and callbacks.
-- * hardware features were copied from Allwinner drivers. */
--const struct stmmac_of_data sun7i_gmac_data = {
-- .has_gmac = 1,
-- .tx_coe = 1,
-- .fix_mac_speed = sun7i_fix_speed,
-- .setup = sun7i_gmac_setup,
-- .init = sun7i_gmac_init,
-- .exit = sun7i_gmac_exit,
-+static int sun7i_gmac_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->interface = of_get_phy_mode(dev->of_node);
-+
-+ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
-+ 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;
-+ }
-+
-+ /* platform data specifying hardware features and callbacks.
-+ * hardware features were copied from Allwinner drivers. */
-+ plat_dat->tx_coe = 1;
-+ plat_dat->has_gmac = true;
-+ plat_dat->bsp_priv = gmac;
-+ plat_dat->init = sun7i_gmac_init;
-+ plat_dat->exit = sun7i_gmac_exit;
-+ plat_dat->fix_mac_speed = sun7i_fix_speed;
-+
-+ ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
-+ if (ret)
-+ return ret;
-+
-+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
-+}
-+
-+static const struct of_device_id sun7i_dwmac_match[] = {
-+ { .compatible = "allwinner,sun7i-a20-gmac" },
-+ { }
- };
-+MODULE_DEVICE_TABLE(of, sun7i_dwmac_match);
-+
-+static struct platform_driver sun7i_dwmac_driver = {
-+ .probe = sun7i_gmac_probe,
-+ .remove = stmmac_pltfr_remove,
-+ .driver = {
-+ .name = "sun7i-dwmac",
-+ .pm = &stmmac_pltfr_pm_ops,
-+ .of_match_table = sun7i_dwmac_match,
-+ },
-+};
-+module_platform_driver(sun7i_dwmac_driver);
-+
-+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-+MODULE_DESCRIPTION("Allwinner sunxi DWMAC specific glue layer");
-+MODULE_LICENSE("GPL");
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
-@@ -172,6 +172,7 @@ enum inter_frame_gap {
- /* GMAC FLOW CTRL defines */
- #define GMAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */
- #define GMAC_FLOW_CTRL_PT_SHIFT 16
-+#define GMAC_FLOW_CTRL_UP 0x00000008 /* Unicast pause frame enable */
- #define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */
- #define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */
- #define GMAC_FLOW_CTRL_FCB_BPA 0x00000001 /* Flow Control Busy ... */
-@@ -246,6 +247,56 @@ enum ttc_control {
- #define DMA_CONTROL_FEF 0x00000080
- #define DMA_CONTROL_FUF 0x00000040
-
-+/* Receive flow control activation field
-+ * RFA field in DMA control register, bits 23,10:9
-+ */
-+#define DMA_CONTROL_RFA_MASK 0x00800600
-+
-+/* Receive flow control deactivation field
-+ * RFD field in DMA control register, bits 22,12:11
-+ */
-+#define DMA_CONTROL_RFD_MASK 0x00401800
-+
-+/* RFD and RFA fields are encoded as follows
-+ *
-+ * Bit Field
-+ * 0,00 - Full minus 1KB (only valid when rxfifo >= 4KB and EFC enabled)
-+ * 0,01 - Full minus 2KB (only valid when rxfifo >= 4KB and EFC enabled)
-+ * 0,10 - Full minus 3KB (only valid when rxfifo >= 4KB and EFC enabled)
-+ * 0,11 - Full minus 4KB (only valid when rxfifo > 4KB and EFC enabled)
-+ * 1,00 - Full minus 5KB (only valid when rxfifo > 8KB and EFC enabled)
-+ * 1,01 - Full minus 6KB (only valid when rxfifo > 8KB and EFC enabled)
-+ * 1,10 - Full minus 7KB (only valid when rxfifo > 8KB and EFC enabled)
-+ * 1,11 - Reserved
-+ *
-+ * RFD should always be > RFA for a given FIFO size. RFD == RFA may work,
-+ * but packet throughput performance may not be as expected.
-+ *
-+ * Be sure that bit 3 in GMAC Register 6 is set for Unicast Pause frame
-+ * detection (IEEE Specification Requirement, Annex 31B, 31B.1, Pause
-+ * Description).
-+ *
-+ * Be sure that DZPA (bit 7 in Flow Control Register, GMAC Register 6),
-+ * is set to 0. This allows pause frames with a quanta of 0 to be sent
-+ * as an XOFF message to the link peer.
-+ */
-+
-+#define RFA_FULL_MINUS_1K 0x00000000
-+#define RFA_FULL_MINUS_2K 0x00000200
-+#define RFA_FULL_MINUS_3K 0x00000400
-+#define RFA_FULL_MINUS_4K 0x00000600
-+#define RFA_FULL_MINUS_5K 0x00800000
-+#define RFA_FULL_MINUS_6K 0x00800200
-+#define RFA_FULL_MINUS_7K 0x00800400
-+
-+#define RFD_FULL_MINUS_1K 0x00000000
-+#define RFD_FULL_MINUS_2K 0x00000800
-+#define RFD_FULL_MINUS_3K 0x00001000
-+#define RFD_FULL_MINUS_4K 0x00001800
-+#define RFD_FULL_MINUS_5K 0x00400000
-+#define RFD_FULL_MINUS_6K 0x00400800
-+#define RFD_FULL_MINUS_7K 0x00401000
-+
- enum rtc_control {
- DMA_CONTROL_RTC_64 = 0x00000000,
- DMA_CONTROL_RTC_32 = 0x00000008,
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
-@@ -201,7 +201,10 @@ static void dwmac1000_flow_ctrl(struct m
- unsigned int fc, unsigned int pause_time)
- {
- void __iomem *ioaddr = hw->pcsr;
-- unsigned int flow = 0;
-+ /* Set flow such that DZPQ in Mac Register 6 is 0,
-+ * and unicast pause detect is enabled.
-+ */
-+ unsigned int flow = GMAC_FLOW_CTRL_UP;
-
- pr_debug("GMAC Flow-Control:\n");
- if (fc & FLOW_RX) {
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
-@@ -70,10 +70,6 @@ static int dwmac1000_dma_init(void __iom
- if (mb)
- value |= DMA_BUS_MODE_MB;
-
--#ifdef CONFIG_STMMAC_DA
-- value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */
--#endif
--
- if (atds)
- value |= DMA_BUS_MODE_ATDS;
-
-@@ -110,8 +106,29 @@ static int dwmac1000_dma_init(void __iom
- return 0;
- }
-
-+static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
-+{
-+ csr6 &= ~DMA_CONTROL_RFA_MASK;
-+ csr6 &= ~DMA_CONTROL_RFD_MASK;
-+
-+ /* Leave flow control disabled if receive fifo size is less than
-+ * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
-+ * and send XON when 2K less than full.
-+ */
-+ if (rxfifosz < 4096) {
-+ csr6 &= ~DMA_CONTROL_EFC;
-+ pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
-+ rxfifosz);
-+ } else {
-+ csr6 |= DMA_CONTROL_EFC;
-+ csr6 |= RFA_FULL_MINUS_1K;
-+ csr6 |= RFD_FULL_MINUS_2K;
-+ }
-+ return csr6;
-+}
-+
- static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
-- int rxmode)
-+ int rxmode, int rxfifosz)
- {
- u32 csr6 = readl(ioaddr + DMA_CONTROL);
-
-@@ -157,6 +174,9 @@ static void dwmac1000_dma_operation_mode
- csr6 |= DMA_CONTROL_RTC_128;
- }
-
-+ /* Configure flow control based on rx fifo size */
-+ csr6 = dwmac1000_configure_fc(csr6, rxfifosz);
-+
- writel(csr6, ioaddr + DMA_CONTROL);
- }
-
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
-@@ -72,7 +72,7 @@ static int dwmac100_dma_init(void __iome
- * control register.
- */
- static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
-- int rxmode)
-+ int rxmode, int rxfifosz)
- {
- u32 csr6 = readl(ioaddr + DMA_CONTROL);
-
---- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
-@@ -73,7 +73,7 @@
- #define MMC_RX_OCTETCOUNT_G 0x00000188
- #define MMC_RX_BROADCASTFRAME_G 0x0000018c
- #define MMC_RX_MULTICASTFRAME_G 0x00000190
--#define MMC_RX_CRC_ERRROR 0x00000194
-+#define MMC_RX_CRC_ERROR 0x00000194
- #define MMC_RX_ALIGN_ERROR 0x00000198
- #define MMC_RX_RUN_ERROR 0x0000019C
- #define MMC_RX_JABBER_ERROR 0x000001A0
-@@ -196,7 +196,7 @@ void dwmac_mmc_read(void __iomem *ioaddr
- mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
- mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
- mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
-- mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERRROR);
-+ mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERROR);
- mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
- mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
- mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-@@ -34,6 +34,14 @@
- #include <linux/ptp_clock_kernel.h>
- #include <linux/reset.h>
-
-+struct stmmac_resources {
-+ void __iomem *addr;
-+ const char *mac;
-+ int wol_irq;
-+ int lpi_irq;
-+ int irq;
-+};
-+
- struct stmmac_tx_info {
- dma_addr_t buf;
- bool map_as_page;
-@@ -97,6 +105,7 @@ struct stmmac_priv {
- int wolopts;
- int wol_irq;
- struct clk *stmmac_clk;
-+ struct clk *pclk;
- struct reset_control *stmmac_rst;
- int clk_csr;
- struct timer_list eee_ctrl_timer;
-@@ -116,97 +125,28 @@ struct stmmac_priv {
- int use_riwt;
- int irq_wake;
- spinlock_t ptp_lock;
-+
-+#ifdef CONFIG_DEBUG_FS
-+ struct dentry *dbgfs_dir;
-+ struct dentry *dbgfs_rings_status;
-+ struct dentry *dbgfs_dma_cap;
-+#endif
- };
-
- int stmmac_mdio_unregister(struct net_device *ndev);
- int stmmac_mdio_register(struct net_device *ndev);
- int stmmac_mdio_reset(struct mii_bus *mii);
- void stmmac_set_ethtool_ops(struct net_device *netdev);
--extern const struct stmmac_desc_ops enh_desc_ops;
--extern const struct stmmac_desc_ops ndesc_ops;
--extern const struct stmmac_hwtimestamp stmmac_ptp;
-+
- int stmmac_ptp_register(struct stmmac_priv *priv);
- void stmmac_ptp_unregister(struct stmmac_priv *priv);
- int stmmac_resume(struct net_device *ndev);
- int stmmac_suspend(struct net_device *ndev);
- int stmmac_dvr_remove(struct net_device *ndev);
--struct stmmac_priv *stmmac_dvr_probe(struct device *device,
-- struct plat_stmmacenet_data *plat_dat,
-- void __iomem *addr);
-+int stmmac_dvr_probe(struct device *device,
-+ struct plat_stmmacenet_data *plat_dat,
-+ struct stmmac_resources *res);
- void stmmac_disable_eee_mode(struct stmmac_priv *priv);
- bool stmmac_eee_init(struct stmmac_priv *priv);
-
--#ifdef CONFIG_STMMAC_PLATFORM
--#ifdef CONFIG_DWMAC_MESON
--extern const struct stmmac_of_data meson6_dwmac_data;
--#endif
--#ifdef CONFIG_DWMAC_SUNXI
--extern const struct stmmac_of_data sun7i_gmac_data;
--#endif
--#ifdef CONFIG_DWMAC_STI
--extern const struct stmmac_of_data stih4xx_dwmac_data;
--extern const struct stmmac_of_data stid127_dwmac_data;
--#endif
--#ifdef CONFIG_DWMAC_SOCFPGA
--extern const struct stmmac_of_data socfpga_gmac_data;
--#endif
--extern struct platform_driver stmmac_pltfr_driver;
--static inline int stmmac_register_platform(void)
--{
-- int err;
--
-- err = platform_driver_register(&stmmac_pltfr_driver);
-- if (err)
-- pr_err("stmmac: failed to register the platform driver\n");
--
-- return err;
--}
--
--static inline void stmmac_unregister_platform(void)
--{
-- platform_driver_unregister(&stmmac_pltfr_driver);
--}
--#else
--static inline int stmmac_register_platform(void)
--{
-- pr_debug("stmmac: do not register the platf driver\n");
--
-- return 0;
--}
--
--static inline void stmmac_unregister_platform(void)
--{
--}
--#endif /* CONFIG_STMMAC_PLATFORM */
--
--#ifdef CONFIG_STMMAC_PCI
--extern struct pci_driver stmmac_pci_driver;
--static inline int stmmac_register_pci(void)
--{
-- int err;
--
-- err = pci_register_driver(&stmmac_pci_driver);
-- if (err)
-- pr_err("stmmac: failed to register the PCI driver\n");
--
-- return err;
--}
--
--static inline void stmmac_unregister_pci(void)
--{
-- pci_unregister_driver(&stmmac_pci_driver);
--}
--#else
--static inline int stmmac_register_pci(void)
--{
-- pr_debug("stmmac: do not register the PCI driver\n");
--
-- return 0;
--}
--
--static inline void stmmac_unregister_pci(void)
--{
--}
--#endif /* CONFIG_STMMAC_PCI */
--
- #endif /* __STMMAC_H__ */
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
-@@ -696,7 +696,7 @@ static int stmmac_set_coalesce(struct ne
- (ec->tx_max_coalesced_frames == 0))
- return -EINVAL;
-
-- if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) ||
-+ if ((ec->tx_coalesce_usecs > STMMAC_MAX_COAL_TX_TICK) ||
- (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
- return -EINVAL;
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -44,14 +44,15 @@
- #include <linux/slab.h>
- #include <linux/prefetch.h>
- #include <linux/pinctrl/consumer.h>
--#ifdef CONFIG_STMMAC_DEBUG_FS
-+#ifdef CONFIG_DEBUG_FS
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
--#endif /* CONFIG_STMMAC_DEBUG_FS */
-+#endif /* CONFIG_DEBUG_FS */
- #include <linux/net_tstamp.h>
- #include "stmmac_ptp.h"
- #include "stmmac.h"
- #include <linux/reset.h>
-+#include <linux/of_mdio.h>
-
- #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
-
-@@ -116,17 +117,17 @@ MODULE_PARM_DESC(chain_mode, "To use cha
-
- static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
-
--#ifdef CONFIG_STMMAC_DEBUG_FS
-+#ifdef CONFIG_DEBUG_FS
- static int stmmac_init_fs(struct net_device *dev);
--static void stmmac_exit_fs(void);
-+static void stmmac_exit_fs(struct net_device *dev);
- #endif
-
- #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
-
- /**
- * stmmac_verify_args - verify the driver parameters.
-- * Description: it verifies if some wrong parameter is passed to the driver.
-- * Note that wrong parameters are replaced with the default values.
-+ * Description: it checks the driver parameters and set a default in case of
-+ * errors.
- */
- static void stmmac_verify_args(void)
- {
-@@ -191,14 +192,8 @@ static void stmmac_clk_csr_set(struct st
-
- static void print_pkt(unsigned char *buf, int len)
- {
-- int j;
-- pr_debug("len = %d byte, buf addr: 0x%p", len, buf);
-- for (j = 0; j < len; j++) {
-- if ((j % 16) == 0)
-- pr_debug("\n %03x:", j);
-- pr_debug(" %02x", buf[j]);
-- }
-- pr_debug("\n");
-+ pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf);
-+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
- }
-
- /* minimum number of free TX descriptors required to wake up TX process */
-@@ -210,7 +205,7 @@ static inline u32 stmmac_tx_avail(struct
- }
-
- /**
-- * stmmac_hw_fix_mac_speed: callback for speed selection
-+ * stmmac_hw_fix_mac_speed - callback for speed selection
- * @priv: driver private structure
- * Description: on some platforms (e.g. ST), some HW system configuraton
- * registers have to be set according to the link speed negotiated.
-@@ -224,9 +219,10 @@ static inline void stmmac_hw_fix_mac_spe
- }
-
- /**
-- * stmmac_enable_eee_mode: Check and enter in LPI mode
-+ * stmmac_enable_eee_mode - check and enter in LPI mode
- * @priv: driver private structure
-- * Description: this function is to verify and enter in LPI mode for EEE.
-+ * Description: this function is to verify and enter in LPI mode in case of
-+ * EEE.
- */
- static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
- {
-@@ -237,7 +233,7 @@ static void stmmac_enable_eee_mode(struc
- }
-
- /**
-- * stmmac_disable_eee_mode: disable/exit from EEE
-+ * stmmac_disable_eee_mode - disable and exit from LPI mode
- * @priv: driver private structure
- * Description: this function is to exit and disable EEE in case of
- * LPI state is true. This is called by the xmit.
-@@ -250,7 +246,7 @@ void stmmac_disable_eee_mode(struct stmm
- }
-
- /**
-- * stmmac_eee_ctrl_timer: EEE TX SW timer.
-+ * stmmac_eee_ctrl_timer - EEE TX SW timer.
- * @arg : data hook
- * Description:
- * if there is no data transfer and if we are not in LPI state,
-@@ -265,13 +261,12 @@ static void stmmac_eee_ctrl_timer(unsign
- }
-
- /**
-- * stmmac_eee_init: init EEE
-+ * stmmac_eee_init - init EEE
- * @priv: driver private structure
- * Description:
-- * If the EEE support has been enabled while configuring the driver,
-- * if the GMAC actually supports the EEE (from the HW cap reg) and the
-- * phy can also manage EEE, so enable the LPI state and start the timer
-- * to verify if the tx path can enter in LPI state.
-+ * if the GMAC supports the EEE (from the HW cap reg) and the phy device
-+ * can also manage EEE, this function enable the LPI state and start related
-+ * timer.
- */
- bool stmmac_eee_init(struct stmmac_priv *priv)
- {
-@@ -316,11 +311,11 @@ bool stmmac_eee_init(struct stmmac_priv
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->eee_active) {
- priv->eee_active = 1;
-- init_timer(&priv->eee_ctrl_timer);
-- priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
-- priv->eee_ctrl_timer.data = (unsigned long)priv;
-- priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
-- add_timer(&priv->eee_ctrl_timer);
-+ setup_timer(&priv->eee_ctrl_timer,
-+ stmmac_eee_ctrl_timer,
-+ (unsigned long)priv);
-+ mod_timer(&priv->eee_ctrl_timer,
-+ STMMAC_LPI_T(eee_timer));
-
- priv->hw->mac->set_eee_timer(priv->hw,
- STMMAC_DEFAULT_LIT_LS,
-@@ -338,7 +333,7 @@ out:
- return ret;
- }
-
--/* stmmac_get_tx_hwtstamp: get HW TX timestamps
-+/* stmmac_get_tx_hwtstamp - get HW TX timestamps
- * @priv: driver private structure
- * @entry : descriptor index to be used.
- * @skb : the socket buffer
-@@ -380,7 +375,7 @@ static void stmmac_get_tx_hwtstamp(struc
- return;
- }
-
--/* stmmac_get_rx_hwtstamp: get HW RX timestamps
-+/* stmmac_get_rx_hwtstamp - get HW RX timestamps
- * @priv: driver private structure
- * @entry : descriptor index to be used.
- * @skb : the socket buffer
-@@ -615,7 +610,7 @@ static int stmmac_hwtstamp_ioctl(struct
- * where, freq_div_ratio = clk_ptp_ref_i/50MHz
- * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
- * NOTE: clk_ptp_ref_i should be >= 50MHz to
-- * achive 20ns accuracy.
-+ * achieve 20ns accuracy.
- *
- * 2^x * y == (y << x), hence
- * 2^32 * 50000000 ==> (50000000 << 32)
-@@ -636,11 +631,11 @@ static int stmmac_hwtstamp_ioctl(struct
- }
-
- /**
-- * stmmac_init_ptp: init PTP
-+ * stmmac_init_ptp - init PTP
- * @priv: driver private structure
-- * Description: this is to verify if the HW supports the PTPv1 or v2.
-+ * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
- * This is done by looking at the HW cap. register.
-- * Also it registers the ptp driver.
-+ * This function also registers the ptp driver.
- */
- static int stmmac_init_ptp(struct stmmac_priv *priv)
- {
-@@ -682,9 +677,13 @@ static void stmmac_release_ptp(struct st
- }
-
- /**
-- * stmmac_adjust_link
-+ * stmmac_adjust_link - adjusts the link parameters
- * @dev: net device structure
-- * Description: it adjusts the link parameters.
-+ * Description: this is the helper called by the physical abstraction layer
-+ * drivers to communicate the phy link status. According the speed and duplex
-+ * this driver can invoke registered glue-logic as well.
-+ * It also invoke the eee initialization because it could happen when switch
-+ * on different networks (that are eee capable).
- */
- static void stmmac_adjust_link(struct net_device *dev)
- {
-@@ -774,7 +773,7 @@ static void stmmac_adjust_link(struct ne
- }
-
- /**
-- * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
-+ * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
- * @priv: driver private structure
- * Description: this is to verify if the HW supports the PCS.
- * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
-@@ -818,21 +817,31 @@ static int stmmac_init_phy(struct net_de
- priv->speed = 0;
- priv->oldduplex = -1;
-
-- if (priv->plat->phy_bus_name)
-- snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
-- priv->plat->phy_bus_name, priv->plat->bus_id);
-- else
-- snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
-- priv->plat->bus_id);
-+ if (priv->plat->phy_node) {
-+ phydev = of_phy_connect(dev, priv->plat->phy_node,
-+ &stmmac_adjust_link, 0, interface);
-+ } else {
-+ if (priv->plat->phy_bus_name)
-+ snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
-+ priv->plat->phy_bus_name, priv->plat->bus_id);
-+ else
-+ snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
-+ priv->plat->bus_id);
-
-- snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
-- priv->plat->phy_addr);
-- pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt);
-+ snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
-+ priv->plat->phy_addr);
-+ pr_debug("stmmac_init_phy: trying to attach to %s\n",
-+ phy_id_fmt);
-
-- phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
-+ phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
-+ interface);
-+ }
-
-- if (IS_ERR(phydev)) {
-+ if (IS_ERR_OR_NULL(phydev)) {
- pr_err("%s: Could not attach to PHY\n", dev->name);
-+ if (!phydev)
-+ return -ENODEV;
-+
- return PTR_ERR(phydev);
- }
-
-@@ -850,7 +859,7 @@ static int stmmac_init_phy(struct net_de
- * device as well.
- * Note: phydev->phy_id is the result of reading the UID PHY registers.
- */
-- if (phydev->phy_id == 0) {
-+ if (!priv->plat->phy_node && phydev->phy_id == 0) {
- phy_disconnect(phydev);
- return -ENODEV;
- }
-@@ -863,7 +872,7 @@ static int stmmac_init_phy(struct net_de
- }
-
- /**
-- * stmmac_display_ring: display ring
-+ * stmmac_display_ring - display ring
- * @head: pointer to the head of the ring passed.
- * @size: size of the ring.
- * @extend_desc: to verify if extended descriptors are used.
-@@ -931,7 +940,7 @@ static int stmmac_set_bfsize(int mtu, in
- }
-
- /**
-- * stmmac_clear_descriptors: clear descriptors
-+ * stmmac_clear_descriptors - clear descriptors
- * @priv: driver private structure
- * Description: this function is called to clear the tx and rx descriptors
- * in case of both basic and extended descriptors are used.
-@@ -963,18 +972,25 @@ static void stmmac_clear_descriptors(str
- (i == txsize - 1));
- }
-
-+/**
-+ * stmmac_init_rx_buffers - init the RX descriptor buffer.
-+ * @priv: driver private structure
-+ * @p: descriptor pointer
-+ * @i: descriptor index
-+ * @flags: gfp flag.
-+ * Description: this function is called to allocate a receive buffer, perform
-+ * the DMA mapping and init the descriptor.
-+ */
- static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
- int i, gfp_t flags)
- {
- struct sk_buff *skb;
-
-- skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
-- flags);
-+ skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
- if (!skb) {
- pr_err("%s: Rx init fails; skb is NULL\n", __func__);
- return -ENOMEM;
- }
-- skb_reserve(skb, NET_IP_ALIGN);
- priv->rx_skbuff[i] = skb;
- priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
- priv->dma_buf_sz,
-@@ -1007,7 +1023,8 @@ static void stmmac_free_rx_buffers(struc
- /**
- * init_dma_desc_rings - init the RX/TX descriptor rings
- * @dev: net device structure
-- * Description: this function initializes the DMA RX/TX descriptors
-+ * @flags: gfp flag.
-+ * Description: this function initializes the DMA RX/TX descriptors
- * and allocates the socket buffers. It suppors the chained and ring
- * modes.
- */
-@@ -1089,6 +1106,7 @@ static int init_dma_desc_rings(struct ne
-
- priv->dirty_tx = 0;
- priv->cur_tx = 0;
-+ netdev_reset_queue(priv->dev);
-
- stmmac_clear_descriptors(priv);
-
-@@ -1144,6 +1162,14 @@ static void dma_free_tx_skbufs(struct st
- }
- }
-
-+/**
-+ * alloc_dma_desc_resources - alloc TX/RX resources.
-+ * @priv: private structure
-+ * Description: according to which descriptor can be used (extend or basic)
-+ * this function allocates the resources for TX and RX paths. In case of
-+ * reception, for example, it pre-allocated the RX socket buffer in order to
-+ * allow zero-copy mechanism.
-+ */
- static int alloc_dma_desc_resources(struct stmmac_priv *priv)
- {
- unsigned int txsize = priv->dma_tx_size;
-@@ -1255,13 +1281,15 @@ static void free_dma_desc_resources(stru
- /**
- * stmmac_dma_operation_mode - HW DMA operation mode
- * @priv: driver private structure
-- * Description: it sets the DMA operation mode: tx/rx DMA thresholds
-- * or Store-And-Forward capability.
-+ * Description: it is used for configuring the DMA operation mode register in
-+ * order to program the tx/rx DMA thresholds or Store-And-Forward mode.
- */
- static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
- {
-+ int rxfifosz = priv->plat->rx_fifo_size;
-+
- if (priv->plat->force_thresh_dma_mode)
-- priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
-+ priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
- else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
- /*
- * In case of GMAC, SF mode can be enabled
-@@ -1270,20 +1298,23 @@ static void stmmac_dma_operation_mode(st
- * 2) There is no bugged Jumbo frame support
- * that needs to not insert csum in the TDES.
- */
-- priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
-- tc = SF_DMA_MODE;
-+ priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE,
-+ rxfifosz);
-+ priv->xstats.threshold = SF_DMA_MODE;
- } else
-- priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
-+ priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE,
-+ rxfifosz);
- }
-
- /**
-- * stmmac_tx_clean:
-+ * stmmac_tx_clean - to manage the transmission completion
- * @priv: driver private structure
-- * Description: it reclaims resources after transmission completes.
-+ * Description: it reclaims the transmit resources after transmission completes.
- */
- static void stmmac_tx_clean(struct stmmac_priv *priv)
- {
- unsigned int txsize = priv->dma_tx_size;
-+ unsigned int bytes_compl = 0, pkts_compl = 0;
-
- spin_lock(&priv->tx_lock);
-
-@@ -1340,6 +1371,8 @@ static void stmmac_tx_clean(struct stmma
- priv->hw->mode->clean_desc3(priv, p);
-
- if (likely(skb != NULL)) {
-+ pkts_compl++;
-+ bytes_compl += skb->len;
- dev_consume_skb_any(skb);
- priv->tx_skbuff[entry] = NULL;
- }
-@@ -1348,6 +1381,9 @@ static void stmmac_tx_clean(struct stmma
-
- priv->dirty_tx++;
- }
-+
-+ netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
-+
- if (unlikely(netif_queue_stopped(priv->dev) &&
- stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
- netif_tx_lock(priv->dev);
-@@ -1378,10 +1414,10 @@ static inline void stmmac_disable_dma_ir
- }
-
- /**
-- * stmmac_tx_err: irq tx error mng function
-+ * stmmac_tx_err - to manage the tx error
- * @priv: driver private structure
- * Description: it cleans the descriptors and restarts the transmission
-- * in case of errors.
-+ * in case of transmission errors.
- */
- static void stmmac_tx_err(struct stmmac_priv *priv)
- {
-@@ -1402,6 +1438,7 @@ static void stmmac_tx_err(struct stmmac_
- (i == txsize - 1));
- priv->dirty_tx = 0;
- priv->cur_tx = 0;
-+ netdev_reset_queue(priv->dev);
- priv->hw->dma->start_tx(priv->ioaddr);
-
- priv->dev->stats.tx_errors++;
-@@ -1409,16 +1446,16 @@ static void stmmac_tx_err(struct stmmac_
- }
-
- /**
-- * stmmac_dma_interrupt: DMA ISR
-+ * stmmac_dma_interrupt - DMA ISR
- * @priv: driver private structure
- * Description: this is the DMA ISR. It is called by the main ISR.
-- * It calls the dwmac dma routine to understand which type of interrupt
-- * happened. In case of there is a Normal interrupt and either TX or RX
-- * interrupt happened so the NAPI is scheduled.
-+ * It calls the dwmac dma routine and schedule poll method in case of some
-+ * work can be done.
- */
- static void stmmac_dma_interrupt(struct stmmac_priv *priv)
- {
- int status;
-+ int rxfifosz = priv->plat->rx_fifo_size;
-
- status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
- if (likely((status & handle_rx)) || (status & handle_tx)) {
-@@ -1429,9 +1466,15 @@ static void stmmac_dma_interrupt(struct
- }
- if (unlikely(status & tx_hard_error_bump_tc)) {
- /* Try to bump up the dma threshold on this failure */
-- if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
-+ if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
-+ (tc <= 256)) {
- tc += 64;
-- priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
-+ if (priv->plat->force_thresh_dma_mode)
-+ priv->hw->dma->dma_mode(priv->ioaddr, tc, tc,
-+ rxfifosz);
-+ else
-+ priv->hw->dma->dma_mode(priv->ioaddr, tc,
-+ SF_DMA_MODE, rxfifosz);
- priv->xstats.threshold = tc;
- }
- } else if (unlikely(status == tx_hard_error))
-@@ -1457,6 +1500,12 @@ static void stmmac_mmc_setup(struct stmm
- pr_info(" No MAC Management Counters available\n");
- }
-
-+/**
-+ * stmmac_get_synopsys_id - return the SYINID.
-+ * @priv: driver private structure
-+ * Description: this simple function is to decode and return the SYINID
-+ * starting from the HW core register.
-+ */
- static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
- {
- u32 hwid = priv->hw->synopsys_uid;
-@@ -1475,11 +1524,11 @@ static u32 stmmac_get_synopsys_id(struct
- }
-
- /**
-- * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
-+ * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
- * @priv: driver private structure
- * Description: select the Enhanced/Alternate or Normal descriptors.
-- * In case of Enhanced/Alternate, it looks at the extended descriptors are
-- * supported by the HW cap. register.
-+ * In case of Enhanced/Alternate, it checks if the extended descriptors are
-+ * supported by the HW capability register.
- */
- static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
- {
-@@ -1501,7 +1550,7 @@ static void stmmac_selec_desc_mode(struc
- }
-
- /**
-- * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
-+ * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
- * @priv: driver private structure
- * Description:
- * new GMAC chip generations have a new register to indicate the
-@@ -1559,7 +1608,7 @@ static int stmmac_get_hw_features(struct
- }
-
- /**
-- * stmmac_check_ether_addr: check if the MAC addr is valid
-+ * stmmac_check_ether_addr - check if the MAC addr is valid
- * @priv: driver private structure
- * Description:
- * it is to verify if the MAC address is valid, in case of failures it
-@@ -1578,7 +1627,7 @@ static void stmmac_check_ether_addr(stru
- }
-
- /**
-- * stmmac_init_dma_engine: DMA init.
-+ * stmmac_init_dma_engine - DMA init.
- * @priv: driver private structure
- * Description:
- * It inits the DMA invoking the specific MAC/GMAC callback.
-@@ -1607,7 +1656,7 @@ static int stmmac_init_dma_engine(struct
- }
-
- /**
-- * stmmac_tx_timer: mitigation sw timer for tx.
-+ * stmmac_tx_timer - mitigation sw timer for tx.
- * @data: data pointer
- * Description:
- * This is the timer handler to directly invoke the stmmac_tx_clean.
-@@ -1620,7 +1669,7 @@ static void stmmac_tx_timer(unsigned lon
- }
-
- /**
-- * stmmac_init_tx_coalesce: init tx mitigation options.
-+ * stmmac_init_tx_coalesce - init tx mitigation options.
- * @priv: driver private structure
- * Description:
- * This inits the transmit coalesce parameters: i.e. timer rate,
-@@ -1639,15 +1688,18 @@ static void stmmac_init_tx_coalesce(stru
- }
-
- /**
-- * stmmac_hw_setup: setup mac in a usable state.
-+ * stmmac_hw_setup - setup mac in a usable state.
- * @dev : pointer to the device structure.
- * Description:
-- * This function sets up the ip in a usable state.
-+ * this is the main function to setup the HW in a usable state because the
-+ * dma engine is reset, the core registers are configured (e.g. AXI,
-+ * Checksum features, timers). The DMA is ready to start receiving and
-+ * transmitting.
- * Return value:
- * 0 on success and an appropriate (-)ve integer as defined in errno.h
- * file on failure.
- */
--static int stmmac_hw_setup(struct net_device *dev)
-+static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
- {
- struct stmmac_priv *priv = netdev_priv(dev);
- int ret;
-@@ -1684,11 +1736,13 @@ static int stmmac_hw_setup(struct net_de
-
- stmmac_mmc_setup(priv);
-
-- ret = stmmac_init_ptp(priv);
-- if (ret && ret != -EOPNOTSUPP)
-- pr_warn("%s: failed PTP initialisation\n", __func__);
-+ if (init_ptp) {
-+ ret = stmmac_init_ptp(priv);
-+ if (ret && ret != -EOPNOTSUPP)
-+ pr_warn("%s: failed PTP initialisation\n", __func__);
-+ }
-
--#ifdef CONFIG_STMMAC_DEBUG_FS
-+#ifdef CONFIG_DEBUG_FS
- ret = stmmac_init_fs(dev);
- if (ret < 0)
- pr_warn("%s: failed debugFS registration\n", __func__);
-@@ -1763,7 +1817,7 @@ static int stmmac_open(struct net_device
- goto init_error;
- }
-
-- ret = stmmac_hw_setup(dev);
-+ ret = stmmac_hw_setup(dev, true);
- if (ret < 0) {
- pr_err("%s: Hw setup failed\n", __func__);
- goto init_error;
-@@ -1870,8 +1924,8 @@ static int stmmac_release(struct net_dev
-
- netif_carrier_off(dev);
-
--#ifdef CONFIG_STMMAC_DEBUG_FS
-- stmmac_exit_fs();
-+#ifdef CONFIG_DEBUG_FS
-+ stmmac_exit_fs(dev);
- #endif
-
- stmmac_release_ptp(priv);
-@@ -1880,7 +1934,7 @@ static int stmmac_release(struct net_dev
- }
-
- /**
-- * stmmac_xmit: Tx entry point of the driver
-+ * stmmac_xmit - Tx entry point of the driver
- * @skb : the socket buffer
- * @dev : device pointer
- * Description : this is the tx entry point of the driver.
-@@ -2024,6 +2078,7 @@ static netdev_tx_t stmmac_xmit(struct sk
- if (!priv->hwts_tx_en)
- skb_tx_timestamp(skb);
-
-+ netdev_sent_queue(dev, skb->len);
- priv->hw->dma->enable_dma_transmission(priv->ioaddr);
-
- spin_unlock(&priv->tx_lock);
-@@ -2055,7 +2110,7 @@ static void stmmac_rx_vlan(struct net_de
-
-
- /**
-- * stmmac_rx_refill: refill used skb preallocated buffers
-+ * stmmac_rx_refill - refill used skb preallocated buffers
- * @priv: driver private structure
- * Description : this is to reallocate the skb for the reception process
- * that is based on zero-copy.
-@@ -2106,7 +2161,7 @@ static inline void stmmac_rx_refill(stru
- }
-
- /**
-- * stmmac_rx_refill: refill used skb preallocated buffers
-+ * stmmac_rx - manage the receive process
- * @priv: driver private structure
- * @limit: napi bugget.
- * Description : this the function called by the napi poll method.
-@@ -2375,8 +2430,11 @@ static int stmmac_set_features(struct ne
- * @irq: interrupt number.
- * @dev_id: to pass the net device pointer.
- * Description: this is the main driver interrupt service routine.
-- * It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
-- * interrupts.
-+ * It can call:
-+ * o DMA service routine (to manage incoming frame reception and transmission
-+ * status)
-+ * o Core interrupts to manage: remote wake-up, management counter, LPI
-+ * interrupts.
- */
- static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
- {
-@@ -2457,10 +2515,8 @@ static int stmmac_ioctl(struct net_devic
- return ret;
- }
-
--#ifdef CONFIG_STMMAC_DEBUG_FS
-+#ifdef CONFIG_DEBUG_FS
- static struct dentry *stmmac_fs_dir;
--static struct dentry *stmmac_rings_status;
--static struct dentry *stmmac_dma_cap;
-
- static void sysfs_display_ring(void *head, int size, int extend_desc,
- struct seq_file *seq)
-@@ -2599,36 +2655,39 @@ static const struct file_operations stmm
-
- static int stmmac_init_fs(struct net_device *dev)
- {
-- /* Create debugfs entries */
-- stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
-+ struct stmmac_priv *priv = netdev_priv(dev);
-
-- if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
-- pr_err("ERROR %s, debugfs create directory failed\n",
-- STMMAC_RESOURCE_NAME);
-+ /* Create per netdev entries */
-+ priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
-+
-+ if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
-+ pr_err("ERROR %s/%s, debugfs create directory failed\n",
-+ STMMAC_RESOURCE_NAME, dev->name);
-
- return -ENOMEM;
- }
-
- /* Entry to report DMA RX/TX rings */
-- stmmac_rings_status = debugfs_create_file("descriptors_status",
-- S_IRUGO, stmmac_fs_dir, dev,
-- &stmmac_rings_status_fops);
-+ priv->dbgfs_rings_status =
-+ debugfs_create_file("descriptors_status", S_IRUGO,
-+ priv->dbgfs_dir, dev,
-+ &stmmac_rings_status_fops);
-
-- if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
-+ if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
- pr_info("ERROR creating stmmac ring debugfs file\n");
-- debugfs_remove(stmmac_fs_dir);
-+ debugfs_remove_recursive(priv->dbgfs_dir);
-
- return -ENOMEM;
- }
-
- /* Entry to report the DMA HW features */
-- stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
-- dev, &stmmac_dma_cap_fops);
-+ priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
-+ priv->dbgfs_dir,
-+ dev, &stmmac_dma_cap_fops);
-
-- if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
-+ if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
- pr_info("ERROR creating stmmac MMC debugfs file\n");
-- debugfs_remove(stmmac_rings_status);
-- debugfs_remove(stmmac_fs_dir);
-+ debugfs_remove_recursive(priv->dbgfs_dir);
-
- return -ENOMEM;
- }
-@@ -2636,13 +2695,13 @@ static int stmmac_init_fs(struct net_dev
- return 0;
- }
-
--static void stmmac_exit_fs(void)
-+static void stmmac_exit_fs(struct net_device *dev)
- {
-- debugfs_remove(stmmac_rings_status);
-- debugfs_remove(stmmac_dma_cap);
-- debugfs_remove(stmmac_fs_dir);
-+ struct stmmac_priv *priv = netdev_priv(dev);
-+
-+ debugfs_remove_recursive(priv->dbgfs_dir);
- }
--#endif /* CONFIG_STMMAC_DEBUG_FS */
-+#endif /* CONFIG_DEBUG_FS */
-
- static const struct net_device_ops stmmac_netdev_ops = {
- .ndo_open = stmmac_open,
-@@ -2663,11 +2722,10 @@ static const struct net_device_ops stmma
- /**
- * stmmac_hw_init - Init the MAC device
- * @priv: driver private structure
-- * Description: this function detects which MAC device
-- * (GMAC/MAC10-100) has to attached, checks the HW capability
-- * (if supported) and sets the driver's features (for example
-- * to use the ring or chaine mode or support the normal/enh
-- * descriptor structure).
-+ * Description: this function is to configure the MAC device according to
-+ * some platform parameters or the HW capability register. It prepares the
-+ * driver to use either ring or chain modes and to setup either enhanced or
-+ * normal descriptors.
- */
- static int stmmac_hw_init(struct stmmac_priv *priv)
- {
-@@ -2714,7 +2772,11 @@ static int stmmac_hw_init(struct stmmac_
- priv->plat->enh_desc = priv->dma_cap.enh_desc;
- priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
-
-- priv->plat->tx_coe = priv->dma_cap.tx_coe;
-+ /* TXCOE doesn't work in thresh DMA mode */
-+ if (priv->plat->force_thresh_dma_mode)
-+ priv->plat->tx_coe = 0;
-+ else
-+ priv->plat->tx_coe = priv->dma_cap.tx_coe;
-
- if (priv->dma_cap.rx_coe_type2)
- priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
-@@ -2747,13 +2809,15 @@ static int stmmac_hw_init(struct stmmac_
- * stmmac_dvr_probe
- * @device: device pointer
- * @plat_dat: platform data pointer
-- * @addr: iobase memory address
-+ * @res: stmmac resource pointer
- * Description: this is the main probe function used to
- * call the alloc_etherdev, allocate the priv structure.
-+ * Return:
-+ * returns 0 on success, otherwise errno.
- */
--struct stmmac_priv *stmmac_dvr_probe(struct device *device,
-- struct plat_stmmacenet_data *plat_dat,
-- void __iomem *addr)
-+int stmmac_dvr_probe(struct device *device,
-+ struct plat_stmmacenet_data *plat_dat,
-+ struct stmmac_resources *res)
- {
- int ret = 0;
- struct net_device *ndev = NULL;
-@@ -2761,7 +2825,7 @@ struct stmmac_priv *stmmac_dvr_probe(str
-
- ndev = alloc_etherdev(sizeof(struct stmmac_priv));
- if (!ndev)
-- return NULL;
-+ return -ENOMEM;
-
- SET_NETDEV_DEV(ndev, device);
-
-@@ -2772,8 +2836,17 @@ struct stmmac_priv *stmmac_dvr_probe(str
- stmmac_set_ethtool_ops(ndev);
- priv->pause = pause;
- priv->plat = plat_dat;
-- priv->ioaddr = addr;
-- priv->dev->base_addr = (unsigned long)addr;
-+ priv->ioaddr = res->addr;
-+ priv->dev->base_addr = (unsigned long)res->addr;
-+
-+ priv->dev->irq = res->irq;
-+ priv->wol_irq = res->wol_irq;
-+ priv->lpi_irq = res->lpi_irq;
-+
-+ if (res->mac)
-+ memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
-+
-+ dev_set_drvdata(device, priv->dev);
-
- /* Verify driver arguments */
- stmmac_verify_args();
-@@ -2800,6 +2873,16 @@ struct stmmac_priv *stmmac_dvr_probe(str
- }
- clk_prepare_enable(priv->stmmac_clk);
-
-+ priv->pclk = devm_clk_get(priv->device, "pclk");
-+ if (IS_ERR(priv->pclk)) {
-+ if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) {
-+ ret = -EPROBE_DEFER;
-+ goto error_pclk_get;
-+ }
-+ priv->pclk = NULL;
-+ }
-+ clk_prepare_enable(priv->pclk);
-+
- priv->stmmac_rst = devm_reset_control_get(priv->device,
- STMMAC_RESOURCE_NAME);
- if (IS_ERR(priv->stmmac_rst)) {
-@@ -2878,19 +2961,22 @@ struct stmmac_priv *stmmac_dvr_probe(str
- }
- }
-
-- return priv;
-+ return 0;
-
- error_mdio_register:
- unregister_netdev(ndev);
- error_netdev_register:
- netif_napi_del(&priv->napi);
- error_hw_init:
-+ clk_disable_unprepare(priv->pclk);
-+error_pclk_get:
- clk_disable_unprepare(priv->stmmac_clk);
- error_clk_get:
- free_netdev(ndev);
-
-- return ERR_PTR(ret);
-+ return ret;
- }
-+EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
-
- /**
- * stmmac_dvr_remove
-@@ -2908,20 +2994,28 @@ int stmmac_dvr_remove(struct net_device
- priv->hw->dma->stop_tx(priv->ioaddr);
-
- stmmac_set_mac(priv->ioaddr, false);
-- if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
-- priv->pcs != STMMAC_PCS_RTBI)
-- stmmac_mdio_unregister(ndev);
- netif_carrier_off(ndev);
- unregister_netdev(ndev);
- if (priv->stmmac_rst)
- reset_control_assert(priv->stmmac_rst);
-+ clk_disable_unprepare(priv->pclk);
- clk_disable_unprepare(priv->stmmac_clk);
-+ if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
-+ priv->pcs != STMMAC_PCS_RTBI)
-+ stmmac_mdio_unregister(ndev);
- free_netdev(ndev);
-
- return 0;
- }
-+EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
-
--#ifdef CONFIG_PM
-+/**
-+ * stmmac_suspend - suspend callback
-+ * @ndev: net device pointer
-+ * Description: this is the function to suspend the device and it is called
-+ * by the platform driver to stop the network queue, release the resources,
-+ * program the PMT register (for WoL), clean and release driver resources.
-+ */
- int stmmac_suspend(struct net_device *ndev)
- {
- struct stmmac_priv *priv = netdev_priv(ndev);
-@@ -2954,6 +3048,7 @@ int stmmac_suspend(struct net_device *nd
- stmmac_set_mac(priv->ioaddr, false);
- pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
-+ clk_disable(priv->pclk);
- clk_disable(priv->stmmac_clk);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-@@ -2963,7 +3058,14 @@ int stmmac_suspend(struct net_device *nd
- priv->oldduplex = -1;
- return 0;
- }
-+EXPORT_SYMBOL_GPL(stmmac_suspend);
-
-+/**
-+ * stmmac_resume - resume callback
-+ * @ndev: net device pointer
-+ * Description: when resume this function is invoked to setup the DMA and CORE
-+ * in a usable state.
-+ */
- int stmmac_resume(struct net_device *ndev)
- {
- struct stmmac_priv *priv = netdev_priv(ndev);
-@@ -2987,6 +3089,7 @@ int stmmac_resume(struct net_device *nde
- pinctrl_pm_select_default_state(priv->device);
- /* enable the clk prevously disabled */
- clk_enable(priv->stmmac_clk);
-+ clk_enable(priv->pclk);
- /* reset the phy so that it's ready */
- if (priv->mii)
- stmmac_mdio_reset(priv->mii);
-@@ -2995,7 +3098,7 @@ int stmmac_resume(struct net_device *nde
- netif_device_attach(ndev);
-
- init_dma_desc_rings(ndev, GFP_ATOMIC);
-- stmmac_hw_setup(ndev);
-+ stmmac_hw_setup(ndev, false);
- stmmac_init_tx_coalesce(priv);
-
- napi_enable(&priv->napi);
-@@ -3009,37 +3112,7 @@ int stmmac_resume(struct net_device *nde
-
- return 0;
- }
--#endif /* CONFIG_PM */
--
--/* Driver can be configured w/ and w/ both PCI and Platf drivers
-- * depending on the configuration selected.
-- */
--static int __init stmmac_init(void)
--{
-- int ret;
--
-- ret = stmmac_register_platform();
-- if (ret)
-- goto err;
-- ret = stmmac_register_pci();
-- if (ret)
-- goto err_pci;
-- return 0;
--err_pci:
-- stmmac_unregister_platform();
--err:
-- pr_err("stmmac: driver registration failed\n");
-- return ret;
--}
--
--static void __exit stmmac_exit(void)
--{
-- stmmac_unregister_platform();
-- stmmac_unregister_pci();
--}
--
--module_init(stmmac_init);
--module_exit(stmmac_exit);
-+EXPORT_SYMBOL_GPL(stmmac_resume);
-
- #ifndef MODULE
- static int __init stmmac_cmdline_opt(char *str)
-@@ -3094,6 +3167,35 @@ err:
- __setup("stmmaceth=", stmmac_cmdline_opt);
- #endif /* MODULE */
-
-+static int __init stmmac_init(void)
-+{
-+#ifdef CONFIG_DEBUG_FS
-+ /* Create debugfs main directory if it doesn't exist yet */
-+ if (!stmmac_fs_dir) {
-+ stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
-+
-+ if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
-+ pr_err("ERROR %s, debugfs create directory failed\n",
-+ STMMAC_RESOURCE_NAME);
-+
-+ return -ENOMEM;
-+ }
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+static void __exit stmmac_exit(void)
-+{
-+#ifdef CONFIG_DEBUG_FS
-+ debugfs_remove_recursive(stmmac_fs_dir);
-+#endif
-+}
-+
-+module_init(stmmac_init)
-+module_exit(stmmac_exit)
-+
- MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- MODULE_LICENSE("GPL");
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
-@@ -161,11 +161,16 @@ int stmmac_mdio_reset(struct mii_bus *bu
-
- if (!gpio_request(reset_gpio, "mdio-reset")) {
- gpio_direction_output(reset_gpio, active_low ? 1 : 0);
-- udelay(data->delays[0]);
-+ if (data->delays[0])
-+ msleep(DIV_ROUND_UP(data->delays[0], 1000));
-+
- gpio_set_value(reset_gpio, active_low ? 0 : 1);
-- udelay(data->delays[1]);
-+ if (data->delays[1])
-+ msleep(DIV_ROUND_UP(data->delays[1], 1000));
-+
- gpio_set_value(reset_gpio, active_low ? 1 : 0);
-- udelay(data->delays[2]);
-+ if (data->delays[2])
-+ msleep(DIV_ROUND_UP(data->delays[2], 1000));
- }
- }
- #endif
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
-@@ -24,38 +24,128 @@
- *******************************************************************************/
-
- #include <linux/pci.h>
-+#include <linux/dmi.h>
-+
- #include "stmmac.h"
-
--static struct plat_stmmacenet_data plat_dat;
--static struct stmmac_mdio_bus_data mdio_data;
--static struct stmmac_dma_cfg dma_cfg;
--
--static void stmmac_default_data(void)
--{
-- memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
--
-- plat_dat.bus_id = 1;
-- plat_dat.phy_addr = 0;
-- plat_dat.interface = PHY_INTERFACE_MODE_GMII;
-- plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
-- plat_dat.has_gmac = 1;
-- plat_dat.force_sf_dma_mode = 1;
--
-- mdio_data.phy_reset = NULL;
-- mdio_data.phy_mask = 0;
-- plat_dat.mdio_bus_data = &mdio_data;
--
-- dma_cfg.pbl = 32;
-- dma_cfg.burst_len = DMA_AXI_BLEN_256;
-- plat_dat.dma_cfg = &dma_cfg;
-+/*
-+ * This struct is used to associate PCI Function of MAC controller on a board,
-+ * discovered via DMI, with the address of PHY connected to the MAC. The
-+ * negative value of the address means that MAC controller is not connected
-+ * with PHY.
-+ */
-+struct stmmac_pci_dmi_data {
-+ const char *name;
-+ unsigned int func;
-+ int phy_addr;
-+};
-+
-+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;
-+};
-+
-+static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info)
-+{
-+ const char *name = dmi_get_system_info(DMI_BOARD_NAME);
-+ 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)
-+ return dmi->phy_addr;
-+ }
-+
-+ return -ENODEV;
-+}
-+
-+static void stmmac_default_data(struct plat_stmmacenet_data *plat)
-+{
-+ plat->bus_id = 1;
-+ plat->phy_addr = 0;
-+ plat->interface = PHY_INTERFACE_MODE_GMII;
-+ plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
-+ plat->has_gmac = 1;
-+ plat->force_sf_dma_mode = 1;
-+
-+ plat->mdio_bus_data->phy_reset = NULL;
-+ plat->mdio_bus_data->phy_mask = 0;
-+
-+ plat->dma_cfg->pbl = 32;
-+ plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
-+
-+ /* Set default value for multicast hash bins */
-+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
-+
-+ /* Set default value for unicast filter entries */
-+ plat->unicast_filter_entries = 1;
-+}
-+
-+static int quark_default_data(struct plat_stmmacenet_data *plat,
-+ struct stmmac_pci_info *info)
-+{
-+ struct pci_dev *pdev = info->pdev;
-+ int ret;
-+
-+ /*
-+ * 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;
-+
-+ plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
-+ plat->phy_addr = ret;
-+ plat->interface = PHY_INTERFACE_MODE_RMII;
-+ plat->clk_csr = 2;
-+ plat->has_gmac = 1;
-+ plat->force_sf_dma_mode = 1;
-+
-+ plat->mdio_bus_data->phy_reset = NULL;
-+ plat->mdio_bus_data->phy_mask = 0;
-+
-+ plat->dma_cfg->pbl = 16;
-+ plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
-+ plat->dma_cfg->fixed_burst = 1;
-
- /* Set default value for multicast hash bins */
-- plat_dat.multicast_filter_bins = HASH_TABLE_SIZE;
-+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
-
- /* Set default value for unicast filter entries */
-- plat_dat.unicast_filter_entries = 1;
-+ plat->unicast_filter_entries = 1;
-+
-+ 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,
-+ },
-+ {}
-+};
-+
-+static struct stmmac_pci_info quark_pci_info = {
-+ .setup = quark_default_data,
-+ .dmi = quark_pci_dmi_data,
-+};
-+
- /**
- * stmmac_pci_probe
- *
-@@ -71,64 +161,65 @@ static void stmmac_default_data(void)
- static int stmmac_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
- {
-- int ret = 0;
-- void __iomem *addr = NULL;
-- struct stmmac_priv *priv = NULL;
-+ struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
-+ struct plat_stmmacenet_data *plat;
-+ struct stmmac_resources res;
- int i;
-+ int ret;
-+
-+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
-+ if (!plat)
-+ return -ENOMEM;
-+
-+ plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
-+ sizeof(*plat->mdio_bus_data),
-+ GFP_KERNEL);
-+ if (!plat->mdio_bus_data)
-+ return -ENOMEM;
-+
-+ plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
-+ GFP_KERNEL);
-+ if (!plat->dma_cfg)
-+ return -ENOMEM;
-
- /* Enable pci device */
-- ret = pci_enable_device(pdev);
-+ ret = pcim_enable_device(pdev);
- if (ret) {
-- pr_err("%s : ERROR: failed to enable %s device\n", __func__,
-- pci_name(pdev));
-+ dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
-+ __func__);
- return ret;
- }
-- if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) {
-- pr_err("%s: ERROR: failed to get PCI region\n", __func__);
-- ret = -ENODEV;
-- goto err_out_req_reg_failed;
-- }
-
- /* Get the base address of device */
-- for (i = 0; i <= 5; i++) {
-+ for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
- if (pci_resource_len(pdev, i) == 0)
- continue;
-- addr = pci_iomap(pdev, i, 0);
-- if (addr == NULL) {
-- pr_err("%s: ERROR: cannot map register memory aborting",
-- __func__);
-- ret = -EIO;
-- goto err_out_map_failed;
-- }
-+ ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
-+ if (ret)
-+ return ret;
- break;
- }
-- pci_set_master(pdev);
--
-- stmmac_default_data();
-
-- priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
-- if (IS_ERR(priv)) {
-- pr_err("%s: main driver probe failed", __func__);
-- ret = PTR_ERR(priv);
-- goto err_out;
-- }
-- priv->dev->irq = pdev->irq;
-- priv->wol_irq = pdev->irq;
--
-- pci_set_drvdata(pdev, priv->dev);
-+ pci_set_master(pdev);
-
-- pr_debug("STMMAC platform driver registration completed");
-+ if (info) {
-+ info->pdev = pdev;
-+ if (info->setup) {
-+ ret = info->setup(plat, info);
-+ if (ret)
-+ return ret;
-+ }
-+ } else
-+ stmmac_default_data(plat);
-
-- return 0;
-+ pci_enable_msi(pdev);
-
--err_out:
-- pci_clear_master(pdev);
--err_out_map_failed:
-- pci_release_regions(pdev);
--err_out_req_reg_failed:
-- pci_disable_device(pdev);
-+ memset(&res, 0, sizeof(res));
-+ res.addr = pcim_iomap_table(pdev)[i];
-+ res.wol_irq = pdev->irq;
-+ res.irq = pdev->irq;
-
-- return ret;
-+ return stmmac_dvr_probe(&pdev->dev, plat, &res);
- }
-
- /**
-@@ -141,61 +232,55 @@ err_out_req_reg_failed:
- static void stmmac_pci_remove(struct pci_dev *pdev)
- {
- struct net_device *ndev = pci_get_drvdata(pdev);
-- struct stmmac_priv *priv = netdev_priv(ndev);
-
- stmmac_dvr_remove(ndev);
--
-- pci_iounmap(pdev, priv->ioaddr);
-- pci_release_regions(pdev);
-- pci_disable_device(pdev);
- }
-
--#ifdef CONFIG_PM
--static int stmmac_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-+#ifdef CONFIG_PM_SLEEP
-+static int stmmac_pci_suspend(struct device *dev)
- {
-+ struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
-- int ret;
--
-- ret = stmmac_suspend(ndev);
-- pci_save_state(pdev);
-- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-- return ret;
-+ return stmmac_suspend(ndev);
- }
-
--static int stmmac_pci_resume(struct pci_dev *pdev)
-+static int stmmac_pci_resume(struct device *dev)
- {
-+ struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
-
-- pci_set_power_state(pdev, PCI_D0);
-- pci_restore_state(pdev);
--
- return stmmac_resume(ndev);
- }
- #endif
-
-+static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
-+
- #define STMMAC_VENDOR_ID 0x700
-+#define STMMAC_QUARK_ID 0x0937
- #define STMMAC_DEVICE_ID 0x1108
-
- 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},
- {}
- };
-
- MODULE_DEVICE_TABLE(pci, stmmac_id_table);
-
--struct pci_driver stmmac_pci_driver = {
-+static struct pci_driver stmmac_pci_driver = {
- .name = STMMAC_RESOURCE_NAME,
- .id_table = stmmac_id_table,
- .probe = stmmac_pci_probe,
- .remove = stmmac_pci_remove,
--#ifdef CONFIG_PM
-- .suspend = stmmac_pci_suspend,
-- .resume = stmmac_pci_resume,
--#endif
-+ .driver = {
-+ .pm = &stmmac_pm_ops,
-+ },
- };
-
-+module_pci_driver(stmmac_pci_driver);
-+
- MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
- MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -23,41 +23,23 @@
- *******************************************************************************/
-
- #include <linux/platform_device.h>
-+#include <linux/module.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_net.h>
- #include <linux/of_device.h>
--#include "stmmac.h"
-+#include <linux/of_mdio.h>
-
--static const struct of_device_id stmmac_dt_ids[] = {
--#ifdef CONFIG_DWMAC_MESON
-- { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data},
--#endif
--#ifdef CONFIG_DWMAC_SUNXI
-- { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
--#endif
--#ifdef CONFIG_DWMAC_STI
-- { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
-- { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
-- { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
-- { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
--#endif
--#ifdef CONFIG_DWMAC_SOCFPGA
-- { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
--#endif
-- /* SoC specific glue layers should come before generic bindings */
-- { .compatible = "st,spear600-gmac"},
-- { .compatible = "snps,dwmac-3.610"},
-- { .compatible = "snps,dwmac-3.70a"},
-- { .compatible = "snps,dwmac-3.710"},
-- { .compatible = "snps,dwmac"},
-- { /* sentinel */ }
--};
--MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-+#include "stmmac.h"
-+#include "stmmac_platform.h"
-
- #ifdef CONFIG_OF
-
--/* This function validates the number of Multicast filtering bins specified
-+/**
-+ * dwmac1000_validate_mcast_bins - validates the number of Multicast filter bins
-+ * @mcast_bins: Multicast filtering bins
-+ * Description:
-+ * this function validates the number of Multicast filtering bins specified
- * by the configuration through the device tree. The Synopsys GMAC supports
- * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC
- * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds
-@@ -83,7 +65,11 @@ static int dwmac1000_validate_mcast_bins
- return x;
- }
-
--/* This function validates the number of Unicast address entries supported
-+/**
-+ * dwmac1000_validate_ucast_entries - validate the Unicast address entries
-+ * @ucast_entries: number of Unicast address entries
-+ * Description:
-+ * This function validates the number of Unicast address entries supported
- * by a particular Synopsys 10/100/1000 controller. The Synopsys controller
- * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter
- * logic. This function validates a valid, supported configuration is
-@@ -109,37 +95,25 @@ static int dwmac1000_validate_ucast_entr
- return x;
- }
-
--static int stmmac_probe_config_dt(struct platform_device *pdev,
-- struct plat_stmmacenet_data *plat,
-- const char **mac)
-+/**
-+ * stmmac_probe_config_dt - parse device-tree driver parameters
-+ * @pdev: platform_device structure
-+ * @plat: driver data platform structure
-+ * @mac: MAC address to use
-+ * Description:
-+ * this function is to read the driver parameters from device-tree and
-+ * set some private fields that will be used by the main at runtime.
-+ */
-+struct plat_stmmacenet_data *
-+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
- {
- struct device_node *np = pdev->dev.of_node;
-+ struct plat_stmmacenet_data *plat;
- struct stmmac_dma_cfg *dma_cfg;
-- const struct of_device_id *device;
-
-- if (!np)
-- return -ENODEV;
--
-- device = of_match_device(stmmac_dt_ids, &pdev->dev);
-- if (!device)
-- return -ENODEV;
--
-- if (device->data) {
-- const struct stmmac_of_data *data = device->data;
-- plat->has_gmac = data->has_gmac;
-- plat->enh_desc = data->enh_desc;
-- plat->tx_coe = data->tx_coe;
-- plat->rx_coe = data->rx_coe;
-- plat->bugged_jumbo = data->bugged_jumbo;
-- plat->pmt = data->pmt;
-- plat->riwt_off = data->riwt_off;
-- plat->fix_mac_speed = data->fix_mac_speed;
-- plat->bus_setup = data->bus_setup;
-- plat->setup = data->setup;
-- plat->free = data->free;
-- plat->init = data->init;
-- plat->exit = data->exit;
-- }
-+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
-+ if (!plat)
-+ return ERR_PTR(-ENOMEM);
-
- *mac = of_get_mac_address(np);
- plat->interface = of_get_phy_mode(np);
-@@ -155,13 +129,24 @@ static int stmmac_probe_config_dt(struct
- /* Default to phy auto-detection */
- plat->phy_addr = -1;
-
-+ /* If we find a phy-handle property, use it as the PHY */
-+ plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
-+
-+ /* If phy-handle is not specified, check if we have a fixed-phy */
-+ if (!plat->phy_node && of_phy_is_fixed_link(np)) {
-+ if ((of_phy_register_fixed_link(np) < 0))
-+ return ERR_PTR(-ENODEV);
-+
-+ plat->phy_node = of_node_get(np);
-+ }
-+
- /* "snps,phy-addr" is not a standard property. Mark it as deprecated
- * and warn of its use. Remove this when phy node support is added.
- */
- if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
- dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
-
-- if (plat->phy_bus_name)
-+ if (plat->phy_node || plat->phy_bus_name)
- plat->mdio_bus_data = NULL;
- else
- plat->mdio_bus_data =
-@@ -169,6 +154,10 @@ static int stmmac_probe_config_dt(struct
- sizeof(struct stmmac_mdio_bus_data),
- GFP_KERNEL);
-
-+ of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
-+
-+ of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
-+
- plat->force_sf_dma_mode =
- of_property_read_bool(np, "snps,force_sf_dma_mode");
-
-@@ -177,6 +166,12 @@ static int stmmac_probe_config_dt(struct
- */
- plat->maxmtu = JUMBO_LEN;
-
-+ /* Set default value for multicast hash bins */
-+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
-+
-+ /* Set default value for unicast filter entries */
-+ plat->unicast_filter_entries = 1;
-+
- /*
- * Currently only the properties needed on SPEAr600
- * are provided. All other properties should be added
-@@ -215,14 +210,19 @@ static int stmmac_probe_config_dt(struct
- if (of_find_property(np, "snps,pbl", NULL)) {
- dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
- GFP_KERNEL);
-- if (!dma_cfg)
-- return -ENOMEM;
-+ if (!dma_cfg) {
-+ of_node_put(np);
-+ return ERR_PTR(-ENOMEM);
-+ }
- plat->dma_cfg = dma_cfg;
- of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
- dma_cfg->fixed_burst =
- of_property_read_bool(np, "snps,fixed-burst");
- dma_cfg->mixed_burst =
- of_property_read_bool(np, "snps,mixed-burst");
-+ of_property_read_u32(np, "snps,burst_len", &dma_cfg->burst_len);
-+ if (dma_cfg->burst_len < 0 || dma_cfg->burst_len > 256)
-+ dma_cfg->burst_len = 0;
- }
- plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
- if (plat->force_thresh_dma_mode) {
-@@ -230,123 +230,60 @@ static int stmmac_probe_config_dt(struct
- pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set.");
- }
-
-- return 0;
-+ return plat;
- }
- #else
--static int stmmac_probe_config_dt(struct platform_device *pdev,
-- struct plat_stmmacenet_data *plat,
-- const char **mac)
-+struct plat_stmmacenet_data *
-+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
- {
-- return -ENOSYS;
-+ return ERR_PTR(-ENOSYS);
- }
- #endif /* CONFIG_OF */
-+EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
-
--/**
-- * stmmac_pltfr_probe
-- * @pdev: platform device pointer
-- * Description: platform_device probe function. It allocates
-- * the necessary resources and invokes the main to init
-- * the net device, register the mdio bus etc.
-- */
--static int stmmac_pltfr_probe(struct platform_device *pdev)
-+int stmmac_get_platform_resources(struct platform_device *pdev,
-+ struct stmmac_resources *stmmac_res)
- {
-- int ret = 0;
- struct resource *res;
-- struct device *dev = &pdev->dev;
-- void __iomem *addr = NULL;
-- struct stmmac_priv *priv = NULL;
-- struct plat_stmmacenet_data *plat_dat = NULL;
-- const char *mac = NULL;
--
-- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- addr = devm_ioremap_resource(dev, res);
-- if (IS_ERR(addr))
-- return PTR_ERR(addr);
--
-- plat_dat = dev_get_platdata(&pdev->dev);
--
-- if (!plat_dat)
-- plat_dat = devm_kzalloc(&pdev->dev,
-- sizeof(struct plat_stmmacenet_data),
-- GFP_KERNEL);
-- if (!plat_dat) {
-- pr_err("%s: ERROR: no memory", __func__);
-- return -ENOMEM;
-- }
--
-- /* Set default value for multicast hash bins */
-- plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
--
-- /* Set default value for unicast filter entries */
-- plat_dat->unicast_filter_entries = 1;
--
-- if (pdev->dev.of_node) {
-- ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
-- if (ret) {
-- pr_err("%s: main dt probe failed", __func__);
-- return ret;
-- }
-- }
--
-- /* Custom setup (if needed) */
-- if (plat_dat->setup) {
-- plat_dat->bsp_priv = plat_dat->setup(pdev);
-- if (IS_ERR(plat_dat->bsp_priv))
-- return PTR_ERR(plat_dat->bsp_priv);
-- }
--
-- /* Custom initialisation (if needed)*/
-- if (plat_dat->init) {
-- ret = plat_dat->init(pdev, plat_dat->bsp_priv);
-- if (unlikely(ret))
-- return ret;
-- }
-
-- priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
-- if (IS_ERR(priv)) {
-- pr_err("%s: main driver probe failed", __func__);
-- return PTR_ERR(priv);
-- }
-+ memset(stmmac_res, 0, sizeof(*stmmac_res));
-
-- /* Get MAC address if available (DT) */
-- if (mac)
-- memcpy(priv->dev->dev_addr, mac, ETH_ALEN);
--
-- /* Get the MAC information */
-- priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
-- if (priv->dev->irq < 0) {
-- if (priv->dev->irq != -EPROBE_DEFER) {
-- netdev_err(priv->dev,
-- "MAC IRQ configuration information not found\n");
-+ /* Get IRQ information early to have an ability to ask for deferred
-+ * probe if needed before we went too far with resource allocation.
-+ */
-+ stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
-+ if (stmmac_res->irq < 0) {
-+ if (stmmac_res->irq != -EPROBE_DEFER) {
-+ dev_err(&pdev->dev,
-+ "MAC IRQ configuration information not found\n");
- }
-- return priv->dev->irq;
-+ return stmmac_res->irq;
- }
-
-- /*
-- * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
-+ /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq
- * The external wake up irq can be passed through the platform code
- * named as "eth_wake_irq"
- *
- * In case the wake up interrupt is not passed from the platform
- * so the driver will continue to use the mac irq (ndev->irq)
- */
-- priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
-- if (priv->wol_irq < 0) {
-- if (priv->wol_irq == -EPROBE_DEFER)
-+ stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
-+ if (stmmac_res->wol_irq < 0) {
-+ if (stmmac_res->wol_irq == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-- priv->wol_irq = priv->dev->irq;
-+ stmmac_res->wol_irq = stmmac_res->irq;
- }
-
-- priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
-- if (priv->lpi_irq == -EPROBE_DEFER)
-+ stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
-+ if (stmmac_res->lpi_irq == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
-- platform_set_drvdata(pdev, priv->dev);
--
-- pr_debug("STMMAC platform driver registration completed");
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res);
-
-- return 0;
-+ return PTR_ERR_OR_ZERO(stmmac_res->addr);
- }
-+EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
-
- /**
- * stmmac_pltfr_remove
-@@ -354,7 +291,7 @@ static int stmmac_pltfr_probe(struct pla
- * Description: this function calls the main to free the net resources
- * and calls the platforms hook and release the resources (e.g. mem).
- */
--static int stmmac_pltfr_remove(struct platform_device *pdev)
-+int stmmac_pltfr_remove(struct platform_device *pdev)
- {
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct stmmac_priv *priv = netdev_priv(ndev);
-@@ -363,13 +300,18 @@ static int stmmac_pltfr_remove(struct pl
- if (priv->plat->exit)
- priv->plat->exit(pdev, priv->plat->bsp_priv);
-
-- if (priv->plat->free)
-- priv->plat->free(pdev, priv->plat->bsp_priv);
--
- return ret;
- }
-+EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
-
--#ifdef CONFIG_PM
-+#ifdef CONFIG_PM_SLEEP
-+/**
-+ * stmmac_pltfr_suspend
-+ * @dev: device pointer
-+ * Description: this function is invoked when suspend the driver and it direcly
-+ * call the main suspend function and then, if required, on some platform, it
-+ * can call an exit helper.
-+ */
- static int stmmac_pltfr_suspend(struct device *dev)
- {
- int ret;
-@@ -384,6 +326,13 @@ static int stmmac_pltfr_suspend(struct d
- return ret;
- }
-
-+/**
-+ * stmmac_pltfr_resume
-+ * @dev: device pointer
-+ * Description: this function is invoked when resume the driver before calling
-+ * the main resume function, on some platforms, it can call own init helper
-+ * if required.
-+ */
- static int stmmac_pltfr_resume(struct device *dev)
- {
- struct net_device *ndev = dev_get_drvdata(dev);
-@@ -395,23 +344,12 @@ static int stmmac_pltfr_resume(struct de
-
- return stmmac_resume(ndev);
- }
-+#endif /* CONFIG_PM_SLEEP */
-
--#endif /* CONFIG_PM */
--
--static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
-- stmmac_pltfr_suspend, stmmac_pltfr_resume);
--
--struct platform_driver stmmac_pltfr_driver = {
-- .probe = stmmac_pltfr_probe,
-- .remove = stmmac_pltfr_remove,
-- .driver = {
-- .name = STMMAC_RESOURCE_NAME,
-- .owner = THIS_MODULE,
-- .pm = &stmmac_pltfr_pm_ops,
-- .of_match_table = of_match_ptr(stmmac_dt_ids),
-- },
--};
-+SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend,
-+ stmmac_pltfr_resume);
-+EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
-
--MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
-+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
-@@ -0,0 +1,33 @@
-+/*******************************************************************************
-+ Copyright (C) 2007-2009 STMicroelectronics Ltd
-+
-+ This program is free software; you can redistribute it and/or modify it
-+ under the terms and conditions of the GNU General Public License,
-+ version 2, as published by the Free Software Foundation.
-+
-+ This program is distributed in the hope 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.
-+
-+ The full GNU General Public License is included in this distribution in
-+ the file called "COPYING".
-+
-+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-+*******************************************************************************/
-+
-+#ifndef __STMMAC_PLATFORM_H__
-+#define __STMMAC_PLATFORM_H__
-+
-+#include "stmmac.h"
-+
-+struct plat_stmmacenet_data *
-+stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);
-+
-+int stmmac_get_platform_resources(struct platform_device *pdev,
-+ struct stmmac_resources *stmmac_res);
-+
-+int stmmac_pltfr_remove(struct platform_device *pdev);
-+extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
-+
-+#endif /* __STMMAC_PLATFORM_H__ */