summaryrefslogtreecommitdiff
path: root/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2017-09-21 22:10:08 +0200
committerHauke Mehrtens <hauke@hauke-m.de>2017-10-01 13:00:16 +0200
commited43a4d4ac195bf3c149805094b628a0d45f8880 (patch)
tree7e6d4475a48cc6b7a0de128714de468a753ba71d /target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch
parenta8f63a0717f553e0a1b37ee9212fc4cb2a801426 (diff)
downloadmtk-20170518-ed43a4d4ac195bf3c149805094b628a0d45f8880.zip
mtk-20170518-ed43a4d4ac195bf3c149805094b628a0d45f8880.tar.gz
mtk-20170518-ed43a4d4ac195bf3c149805094b628a0d45f8880.tar.bz2
sunxi: backport the stmmac driver from kernel 4.13
This adds support for the GMAC which is use in the A64 and other Allwinner chips by backporting the changes from the kernel versions 4.13. Some commits are not backported which are adding support for newly introduced APIs which are not available in kernel 4.9. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Diffstat (limited to 'target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch')
-rw-r--r--target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch2305
1 files changed, 2305 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch b/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch
new file mode 100644
index 0000000..f3b4262
--- /dev/null
+++ b/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch
@@ -0,0 +1,2305 @@
+--- a/Documentation/devicetree/bindings/net/stmmac.txt
++++ b/Documentation/devicetree/bindings/net/stmmac.txt
+@@ -49,6 +49,8 @@ Optional properties:
+ - snps,force_sf_dma_mode Force DMA to use the Store and Forward
+ mode for both tx and rx. This flag is
+ ignored if force_thresh_dma_mode is set.
++- snps,en-tx-lpi-clockgating Enable gating of the MAC TX clock during
++ TX low-power mode
+ - snps,multicast-filter-bins: Number of multicast filter hash bins
+ supported by this device instance
+ - snps,perfect-filter-entries: Number of perfect filter entries supported
+@@ -65,7 +67,6 @@ Optional properties:
+ - snps,wr_osr_lmt: max write outstanding req. limit
+ - snps,rd_osr_lmt: max read outstanding req. limit
+ - snps,kbbe: do not cross 1KiB boundary.
+- - snps,axi_all: align address
+ - snps,blen: this is a vector of supported burst length.
+ - snps,fb: fixed-burst
+ - snps,mb: mixed-burst
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -1,5 +1,5 @@
+ config STMMAC_ETH
+- tristate "STMicroelectronics 10/100/1000 Ethernet driver"
++ tristate "STMicroelectronics 10/100/1000/EQOS Ethernet driver"
+ depends on HAS_IOMEM && HAS_DMA
+ select MII
+ select PHYLIB
+@@ -7,9 +7,8 @@ config STMMAC_ETH
+ select PTP_1588_CLOCK
+ select RESET_CONTROLLER
+ ---help---
+- This is the driver for the Ethernet IPs are built around a
+- Synopsys IP Core and only tested on the STMicroelectronics
+- platforms.
++ This is the driver for the Ethernet IPs built around a
++ Synopsys IP Core.
+
+ if STMMAC_ETH
+
+@@ -29,6 +28,15 @@ config STMMAC_PLATFORM
+
+ if STMMAC_PLATFORM
+
++config DWMAC_DWC_QOS_ETH
++ tristate "Support for snps,dwc-qos-ethernet.txt DT binding."
++ select PHYLIB
++ select CRC32
++ select MII
++ depends on OF && HAS_DMA
++ help
++ Support for chips using the snps,dwc-qos-ethernet.txt DT binding.
++
+ config DWMAC_GENERIC
+ tristate "Generic driver for DWMAC"
+ default STMMAC_PLATFORM
+@@ -143,11 +151,11 @@ config STMMAC_PCI
+ tristate "STMMAC PCI bus support"
+ depends on STMMAC_ETH && PCI
+ ---help---
+- This is to select the Synopsys DWMAC available on PCI devices,
+- if you have a controller with this interface, say Y or M here.
++ This selects the platform specific bus support for the stmmac driver.
++ This driver was tested on XLINX XC2V3000 FF1152AMT0221
++ D1215994A VIRTEX FPGA board and SNPS QoS IPK Prototyping Kit.
+
+- This PCI support is tested on XLINX XC2V3000 FF1152AMT0221
+- D1215994A VIRTEX FPGA board.
++ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+ endif
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-alt
+ obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
+ obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o
+ obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
++obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o
+ obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
+ stmmac-platform-objs:= stmmac_platform.o
+ dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o
+--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
++++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+@@ -16,10 +16,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -71,7 +67,7 @@ struct stmmac_extra_stats {
+ unsigned long overflow_error;
+ unsigned long ipc_csum_error;
+ unsigned long rx_collision;
+- unsigned long rx_crc;
++ unsigned long rx_crc_errors;
+ unsigned long dribbling_bit;
+ unsigned long rx_length;
+ unsigned long rx_mii;
+@@ -323,6 +319,9 @@ struct dma_features {
+ /* TX and RX number of channels */
+ unsigned int number_rx_channel;
+ unsigned int number_tx_channel;
++ /* TX and RX number of queues */
++ unsigned int number_rx_queues;
++ unsigned int number_tx_queues;
+ /* Alternate (enhanced) DESC mode */
+ unsigned int enh_desc;
+ };
+@@ -340,7 +339,7 @@ struct dma_features {
+ /* Common MAC defines */
+ #define MAC_CTRL_REG 0x00000000 /* MAC Control */
+ #define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */
+-#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */
++#define MAC_ENABLE_RX 0x00000004 /* Receiver Enable */
+
+ /* Default LPI timers */
+ #define STMMAC_DEFAULT_LIT_LS 0x3E8
+@@ -417,7 +416,7 @@ struct stmmac_dma_ops {
+ /* Configure the AXI Bus Mode Register */
+ void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
+ /* Dump DMA registers */
+- void (*dump_regs) (void __iomem *ioaddr);
++ void (*dump_regs)(void __iomem *ioaddr, u32 *reg_space);
+ /* 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,
+@@ -454,8 +453,10 @@ struct stmmac_ops {
+ void (*core_init)(struct mac_device_info *hw, int mtu);
+ /* Enable and verify that the IPC module is supported */
+ int (*rx_ipc)(struct mac_device_info *hw);
++ /* Enable RX Queues */
++ void (*rx_queue_enable)(struct mac_device_info *hw, u32 queue);
+ /* Dump MAC registers */
+- void (*dump_regs)(struct mac_device_info *hw);
++ void (*dump_regs)(struct mac_device_info *hw, u32 *reg_space);
+ /* Handle extra events on specific interrupts hw dependent */
+ int (*host_irq_status)(struct mac_device_info *hw,
+ struct stmmac_extra_stats *x);
+@@ -471,7 +472,8 @@ struct stmmac_ops {
+ unsigned int reg_n);
+ void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+ unsigned int reg_n);
+- void (*set_eee_mode)(struct mac_device_info *hw);
++ void (*set_eee_mode)(struct mac_device_info *hw,
++ bool en_tx_lpi_clockgating);
+ void (*reset_eee_mode)(struct mac_device_info *hw);
+ void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
+ void (*set_eee_pls)(struct mac_device_info *hw, int link);
+--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
++++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
+@@ -11,10 +11,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h
++++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
+@@ -17,10 +17,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+@@ -0,0 +1,202 @@
++/*
++ * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver
++ *
++ * Copyright (C) 2016 Joao Pinto <jpinto@synopsys.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/device.h>
++#include <linux/ethtool.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++#include <linux/of_net.h>
++#include <linux/mfd/syscon.h>
++#include <linux/platform_device.h>
++#include <linux/stmmac.h>
++
++#include "stmmac_platform.h"
++
++static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
++ struct plat_stmmacenet_data *plat_dat)
++{
++ struct device_node *np = pdev->dev.of_node;
++ u32 burst_map = 0;
++ u32 bit_index = 0;
++ u32 a_index = 0;
++
++ if (!plat_dat->axi) {
++ plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL);
++
++ if (!plat_dat->axi)
++ return -ENOMEM;
++ }
++
++ plat_dat->axi->axi_lpi_en = of_property_read_bool(np, "snps,en-lpi");
++ if (of_property_read_u32(np, "snps,write-requests",
++ &plat_dat->axi->axi_wr_osr_lmt)) {
++ /**
++ * Since the register has a reset value of 1, if property
++ * is missing, default to 1.
++ */
++ plat_dat->axi->axi_wr_osr_lmt = 1;
++ } else {
++ /**
++ * If property exists, to keep the behavior from dwc_eth_qos,
++ * subtract one after parsing.
++ */
++ plat_dat->axi->axi_wr_osr_lmt--;
++ }
++
++ if (of_property_read_u32(np, "read,read-requests",
++ &plat_dat->axi->axi_rd_osr_lmt)) {
++ /**
++ * Since the register has a reset value of 1, if property
++ * is missing, default to 1.
++ */
++ plat_dat->axi->axi_rd_osr_lmt = 1;
++ } else {
++ /**
++ * If property exists, to keep the behavior from dwc_eth_qos,
++ * subtract one after parsing.
++ */
++ plat_dat->axi->axi_rd_osr_lmt--;
++ }
++ of_property_read_u32(np, "snps,burst-map", &burst_map);
++
++ /* converts burst-map bitmask to burst array */
++ for (bit_index = 0; bit_index < 7; bit_index++) {
++ if (burst_map & (1 << bit_index)) {
++ switch (bit_index) {
++ case 0:
++ plat_dat->axi->axi_blen[a_index] = 4; break;
++ case 1:
++ plat_dat->axi->axi_blen[a_index] = 8; break;
++ case 2:
++ plat_dat->axi->axi_blen[a_index] = 16; break;
++ case 3:
++ plat_dat->axi->axi_blen[a_index] = 32; break;
++ case 4:
++ plat_dat->axi->axi_blen[a_index] = 64; break;
++ case 5:
++ plat_dat->axi->axi_blen[a_index] = 128; break;
++ case 6:
++ plat_dat->axi->axi_blen[a_index] = 256; break;
++ default:
++ break;
++ }
++ a_index++;
++ }
++ }
++
++ /* dwc-qos needs GMAC4, AAL, TSO and PMT */
++ plat_dat->has_gmac4 = 1;
++ plat_dat->dma_cfg->aal = 1;
++ plat_dat->tso_en = 1;
++ plat_dat->pmt = 1;
++
++ return 0;
++}
++
++static int dwc_eth_dwmac_probe(struct platform_device *pdev)
++{
++ struct plat_stmmacenet_data *plat_dat;
++ struct stmmac_resources stmmac_res;
++ struct resource *res;
++ int ret;
++
++ memset(&stmmac_res, 0, sizeof(struct stmmac_resources));
++
++ /**
++ * Since stmmac_platform supports name IRQ only, basic platform
++ * resource initialization is done in the glue logic.
++ */
++ stmmac_res.irq = platform_get_irq(pdev, 0);
++ if (stmmac_res.irq < 0) {
++ if (stmmac_res.irq != -EPROBE_DEFER)
++ dev_err(&pdev->dev,
++ "IRQ configuration information not found\n");
++
++ return stmmac_res.irq;
++ }
++ stmmac_res.wol_irq = stmmac_res.irq;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ stmmac_res.addr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(stmmac_res.addr))
++ return PTR_ERR(stmmac_res.addr);
++
++ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
++ if (IS_ERR(plat_dat))
++ return PTR_ERR(plat_dat);
++
++ plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk");
++ if (IS_ERR(plat_dat->stmmac_clk)) {
++ dev_err(&pdev->dev, "apb_pclk clock not found.\n");
++ ret = PTR_ERR(plat_dat->stmmac_clk);
++ plat_dat->stmmac_clk = NULL;
++ goto err_remove_config_dt;
++ }
++ clk_prepare_enable(plat_dat->stmmac_clk);
++
++ plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk");
++ if (IS_ERR(plat_dat->pclk)) {
++ dev_err(&pdev->dev, "phy_ref_clk clock not found.\n");
++ ret = PTR_ERR(plat_dat->pclk);
++ plat_dat->pclk = NULL;
++ goto err_out_clk_dis_phy;
++ }
++ clk_prepare_enable(plat_dat->pclk);
++
++ ret = dwc_eth_dwmac_config_dt(pdev, plat_dat);
++ if (ret)
++ goto err_out_clk_dis_aper;
++
++ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
++ if (ret)
++ goto err_out_clk_dis_aper;
++
++ return 0;
++
++err_out_clk_dis_aper:
++ clk_disable_unprepare(plat_dat->pclk);
++err_out_clk_dis_phy:
++ clk_disable_unprepare(plat_dat->stmmac_clk);
++err_remove_config_dt:
++ stmmac_remove_config_dt(pdev, plat_dat);
++
++ return ret;
++}
++
++static int dwc_eth_dwmac_remove(struct platform_device *pdev)
++{
++ return stmmac_pltfr_remove(pdev);
++}
++
++static const struct of_device_id dwc_eth_dwmac_match[] = {
++ { .compatible = "snps,dwc-qos-ethernet-4.10", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
++
++static struct platform_driver dwc_eth_dwmac_driver = {
++ .probe = dwc_eth_dwmac_probe,
++ .remove = dwc_eth_dwmac_remove,
++ .driver = {
++ .name = "dwc-eth-dwmac",
++ .of_match_table = dwc_eth_dwmac_match,
++ },
++};
++module_platform_driver(dwc_eth_dwmac_driver);
++
++MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
++MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
++MODULE_LICENSE("GPL v2");
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+@@ -35,10 +35,6 @@
+
+ #define PRG_ETH0_TXDLY_SHIFT 5
+ #define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)
+-#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)
+-#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)
+-#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)
+-#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)
+
+ /* divider for the result of m250_sel */
+ #define PRG_ETH0_CLK_M250_DIV_SHIFT 7
+@@ -69,6 +65,8 @@ struct meson8b_dwmac {
+
+ struct clk_divider m25_div;
+ struct clk *m25_div_clk;
++
++ u32 tx_delay_ns;
+ };
+
+ static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
+@@ -179,11 +177,19 @@ static int meson8b_init_prg_eth(struct m
+ {
+ int ret;
+ unsigned long clk_rate;
++ u8 tx_dly_val = 0;
+
+ switch (dwmac->phy_mode) {
+ case PHY_INTERFACE_MODE_RGMII:
+- case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
++ /* TX clock delay in ns = "8ns / 4 * tx_dly_val" (where
++ * 8ns are exactly one cycle of the 125MHz RGMII TX clock):
++ * 0ns = 0x0, 2ns = 0x1, 4ns = 0x2, 6ns = 0x3
++ */
++ tx_dly_val = dwmac->tx_delay_ns >> 1;
++ /* fall through */
++
++ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ /* Generate a 25MHz clock for the PHY */
+ clk_rate = 25 * 1000 * 1000;
+@@ -196,9 +202,8 @@ static int meson8b_init_prg_eth(struct m
+ meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
+ PRG_ETH0_INVERTED_RMII_CLK, 0);
+
+- /* TX clock delay - all known boards use a 1/4 cycle delay */
+ meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
+- PRG_ETH0_TXDLY_QUARTER);
++ tx_dly_val << PRG_ETH0_TXDLY_SHIFT);
+ break;
+
+ case PHY_INTERFACE_MODE_RMII:
+@@ -284,6 +289,11 @@ static int meson8b_dwmac_probe(struct pl
+ goto err_remove_config_dt;
+ }
+
++ /* use 2ns as fallback since this value was previously hardcoded */
++ if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns",
++ &dwmac->tx_delay_ns))
++ dwmac->tx_delay_ns = 2;
++
+ ret = meson8b_init_clk(dwmac);
+ if (ret)
+ goto err_remove_config_dt;
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+@@ -302,6 +302,122 @@ static const struct rk_gmac_ops rk3288_o
+ .set_rmii_speed = rk3288_set_rmii_speed,
+ };
+
++#define RK3328_GRF_MAC_CON0 0x0900
++#define RK3328_GRF_MAC_CON1 0x0904
++
++/* RK3328_GRF_MAC_CON0 */
++#define RK3328_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
++#define RK3328_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
++
++/* RK3328_GRF_MAC_CON1 */
++#define RK3328_GMAC_PHY_INTF_SEL_RGMII \
++ (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
++#define RK3328_GMAC_PHY_INTF_SEL_RMII \
++ (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
++#define RK3328_GMAC_FLOW_CTRL GRF_BIT(3)
++#define RK3328_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
++#define RK3328_GMAC_SPEED_10M GRF_CLR_BIT(2)
++#define RK3328_GMAC_SPEED_100M GRF_BIT(2)
++#define RK3328_GMAC_RMII_CLK_25M GRF_BIT(7)
++#define RK3328_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7)
++#define RK3328_GMAC_CLK_125M (GRF_CLR_BIT(11) | GRF_CLR_BIT(12))
++#define RK3328_GMAC_CLK_25M (GRF_BIT(11) | GRF_BIT(12))
++#define RK3328_GMAC_CLK_2_5M (GRF_CLR_BIT(11) | GRF_BIT(12))
++#define RK3328_GMAC_RMII_MODE GRF_BIT(9)
++#define RK3328_GMAC_RMII_MODE_CLR GRF_CLR_BIT(9)
++#define RK3328_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
++#define RK3328_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
++#define RK3328_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
++#define RK3328_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(0)
++
++static void rk3328_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, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_PHY_INTF_SEL_RGMII |
++ RK3328_GMAC_RMII_MODE_CLR |
++ RK3328_GMAC_RXCLK_DLY_ENABLE |
++ RK3328_GMAC_TXCLK_DLY_ENABLE);
++
++ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0,
++ RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) |
++ RK3328_GMAC_CLK_TX_DL_CFG(tx_delay));
++}
++
++static void rk3328_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, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_PHY_INTF_SEL_RMII |
++ RK3328_GMAC_RMII_MODE);
++
++ /* set MAC to RMII mode */
++ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, GRF_BIT(11));
++}
++
++static void rk3328_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, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_CLK_2_5M);
++ else if (speed == 100)
++ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_CLK_25M);
++ else if (speed == 1000)
++ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_CLK_125M);
++ else
++ dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
++}
++
++static void rk3328_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, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_RMII_CLK_2_5M |
++ RK3328_GMAC_SPEED_10M);
++ else if (speed == 100)
++ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
++ RK3328_GMAC_RMII_CLK_25M |
++ RK3328_GMAC_SPEED_100M);
++ else
++ dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
++}
++
++static const struct rk_gmac_ops rk3328_ops = {
++ .set_to_rgmii = rk3328_set_to_rgmii,
++ .set_to_rmii = rk3328_set_to_rmii,
++ .set_rgmii_speed = rk3328_set_rgmii_speed,
++ .set_rmii_speed = rk3328_set_rmii_speed,
++};
++
+ #define RK3366_GRF_SOC_CON6 0x0418
+ #define RK3366_GRF_SOC_CON7 0x041c
+
+@@ -1006,6 +1122,7 @@ static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops,
+ static const struct of_device_id rk_gmac_dwmac_match[] = {
+ { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
+ { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
++ { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops },
+ { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
+ { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
+ { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+@@ -341,7 +341,7 @@ static int socfpga_dwmac_probe(struct pl
+ * mode. Create a copy of the core reset handle so it can be used by
+ * the driver later.
+ */
+- dwmac->stmmac_rst = stpriv->stmmac_rst;
++ dwmac->stmmac_rst = stpriv->plat->stmmac_rst;
+
+ ret = socfpga_dwmac_set_phy_mode(dwmac);
+ if (ret)
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+@@ -10,10 +10,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+@@ -16,10 +16,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -96,17 +92,13 @@ static int dwmac1000_rx_ipc_enable(struc
+ return !!(value & GMAC_CONTROL_IPC);
+ }
+
+-static void dwmac1000_dump_regs(struct mac_device_info *hw)
++static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+ int i;
+- pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
+
+- for (i = 0; i < 55; i++) {
+- int offset = i * 4;
+- pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
+- offset, readl(ioaddr + offset));
+- }
++ for (i = 0; i < 55; i++)
++ reg_space[i] = readl(ioaddr + i * 4);
+ }
+
+ static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
+@@ -347,11 +339,14 @@ static int dwmac1000_irq_status(struct m
+ return ret;
+ }
+
+-static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
++static void dwmac1000_set_eee_mode(struct mac_device_info *hw,
++ bool en_tx_lpi_clockgating)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+ u32 value;
+
++ /*TODO - en_tx_lpi_clockgating treatment */
++
+ /* Enable the link status receive on RGMII, SGMII ore SMII
+ * receive path and instruct the transmit to enter in LPI
+ * state.
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+@@ -16,10 +16,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -205,18 +201,14 @@ static void dwmac1000_dma_operation_mode
+ writel(csr6, ioaddr + DMA_CONTROL);
+ }
+
+-static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
++static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
+ {
+ int i;
+- pr_info(" DMA registers\n");
+- for (i = 0; i < 22; i++) {
+- if ((i < 9) || (i > 17)) {
+- int offset = i * 4;
+- pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i,
+- (DMA_BUS_MODE + offset),
+- readl(ioaddr + DMA_BUS_MODE + offset));
+- }
+- }
++
++ for (i = 0; i < 22; i++)
++ if ((i < 9) || (i > 17))
++ reg_space[DMA_BUS_MODE / 4 + i] =
++ readl(ioaddr + DMA_BUS_MODE + i * 4);
+ }
+
+ static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+@@ -18,10 +18,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -44,28 +40,18 @@ static void dwmac100_core_init(struct ma
+ #endif
+ }
+
+-static void dwmac100_dump_mac_regs(struct mac_device_info *hw)
++static void dwmac100_dump_mac_regs(struct mac_device_info *hw, u32 *reg_space)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+- pr_info("\t----------------------------------------------\n"
+- "\t DWMAC 100 CSR (base addr = 0x%p)\n"
+- "\t----------------------------------------------\n", ioaddr);
+- pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
+- readl(ioaddr + MAC_CONTROL));
+- pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
+- readl(ioaddr + MAC_ADDR_HIGH));
+- pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW,
+- readl(ioaddr + MAC_ADDR_LOW));
+- pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n",
+- MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH));
+- pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n",
+- MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW));
+- pr_info("\tflow control (offset 0x%x): 0x%08x\n",
+- MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL));
+- pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1,
+- readl(ioaddr + MAC_VLAN1));
+- pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
+- readl(ioaddr + MAC_VLAN2));
++
++ reg_space[MAC_CONTROL / 4] = readl(ioaddr + MAC_CONTROL);
++ reg_space[MAC_ADDR_HIGH / 4] = readl(ioaddr + MAC_ADDR_HIGH);
++ reg_space[MAC_ADDR_LOW / 4] = readl(ioaddr + MAC_ADDR_LOW);
++ reg_space[MAC_HASH_HIGH / 4] = readl(ioaddr + MAC_HASH_HIGH);
++ reg_space[MAC_HASH_LOW / 4] = readl(ioaddr + MAC_HASH_LOW);
++ reg_space[MAC_FLOW_CTRL / 4] = readl(ioaddr + MAC_FLOW_CTRL);
++ reg_space[MAC_VLAN1 / 4] = readl(ioaddr + MAC_VLAN1);
++ reg_space[MAC_VLAN2 / 4] = readl(ioaddr + MAC_VLAN2);
+ }
+
+ static int dwmac100_rx_ipc_enable(struct mac_device_info *hw)
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+@@ -18,10 +18,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -70,19 +66,18 @@ static void dwmac100_dma_operation_mode(
+ writel(csr6, ioaddr + DMA_CONTROL);
+ }
+
+-static void dwmac100_dump_dma_regs(void __iomem *ioaddr)
++static void dwmac100_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
+ {
+ int i;
+
+- pr_debug("DWMAC 100 DMA CSR\n");
+ for (i = 0; i < 9; i++)
+- pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i,
+- (DMA_BUS_MODE + i * 4),
+- readl(ioaddr + DMA_BUS_MODE + i * 4));
+-
+- pr_debug("\tCSR20 (0x%x): 0x%08x, CSR21 (0x%x): 0x%08x\n",
+- DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR),
+- DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR));
++ reg_space[DMA_BUS_MODE / 4 + i] =
++ readl(ioaddr + DMA_BUS_MODE + i * 4);
++
++ reg_space[DMA_CUR_TX_BUF_ADDR / 4] =
++ readl(ioaddr + DMA_CUR_TX_BUF_ADDR);
++ reg_space[DMA_CUR_RX_BUF_ADDR / 4] =
++ readl(ioaddr + DMA_CUR_RX_BUF_ADDR);
+ }
+
+ /* DMA controller has two counters to track the number of the missed frames. */
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+@@ -22,6 +22,7 @@
+ #define GMAC_HASH_TAB_32_63 0x00000014
+ #define GMAC_RX_FLOW_CTRL 0x00000090
+ #define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4)
++#define GMAC_RXQ_CTRL0 0x000000a0
+ #define GMAC_INT_STATUS 0x000000b0
+ #define GMAC_INT_EN 0x000000b4
+ #define GMAC_PCS_BASE 0x000000e0
+@@ -44,6 +45,11 @@
+
+ #define GMAC_MAX_PERFECT_ADDRESSES 128
+
++/* MAC RX Queue Enable */
++#define GMAC_RX_QUEUE_CLEAR(queue) ~(GENMASK(1, 0) << ((queue) * 2))
++#define GMAC_RX_AV_QUEUE_ENABLE(queue) BIT((queue) * 2)
++#define GMAC_RX_DCB_QUEUE_ENABLE(queue) BIT(((queue) * 2) + 1)
++
+ /* MAC Flow Control RX */
+ #define GMAC_RX_FLOW_CTRL_RFE BIT(0)
+
+@@ -84,6 +90,19 @@ enum power_event {
+ power_down = 0x00000001,
+ };
+
++/* Energy Efficient Ethernet (EEE) for GMAC4
++ *
++ * LPI status, timer and control register offset
++ */
++#define GMAC4_LPI_CTRL_STATUS 0xd0
++#define GMAC4_LPI_TIMER_CTRL 0xd4
++
++/* LPI control and status defines */
++#define GMAC4_LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable */
++#define GMAC4_LPI_CTRL_STATUS_LPITXA BIT(19) /* Enable LPI TX Automate */
++#define GMAC4_LPI_CTRL_STATUS_PLS BIT(17) /* PHY Link Status */
++#define GMAC4_LPI_CTRL_STATUS_LPIEN BIT(16) /* LPI Enable */
++
+ /* MAC Debug bitmap */
+ #define GMAC_DEBUG_TFCSTS_MASK GENMASK(18, 17)
+ #define GMAC_DEBUG_TFCSTS_SHIFT 17
+@@ -133,6 +152,8 @@ enum power_event {
+ /* MAC HW features2 bitmap */
+ #define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18)
+ #define GMAC_HW_FEAT_RXCHCNT GENMASK(15, 12)
++#define GMAC_HW_FEAT_TXQCNT GENMASK(9, 6)
++#define GMAC_HW_FEAT_RXQCNT GENMASK(3, 0)
+
+ /* MAC HW ADDR regs */
+ #define GMAC_HI_DCS GENMASK(18, 16)
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+@@ -59,19 +59,24 @@ static void dwmac4_core_init(struct mac_
+ writel(value, ioaddr + GMAC_INT_EN);
+ }
+
+-static void dwmac4_dump_regs(struct mac_device_info *hw)
++static void dwmac4_rx_queue_enable(struct mac_device_info *hw, u32 queue)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+- int i;
++ u32 value = readl(ioaddr + GMAC_RXQ_CTRL0);
+
+- pr_debug("\tDWMAC4 regs (base addr = 0x%p)\n", ioaddr);
++ value &= GMAC_RX_QUEUE_CLEAR(queue);
++ value |= GMAC_RX_AV_QUEUE_ENABLE(queue);
+
+- for (i = 0; i < GMAC_REG_NUM; i++) {
+- int offset = i * 4;
++ writel(value, ioaddr + GMAC_RXQ_CTRL0);
++}
+
+- pr_debug("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
+- offset, readl(ioaddr + offset));
+- }
++static void dwmac4_dump_regs(struct mac_device_info *hw, u32 *reg_space)
++{
++ void __iomem *ioaddr = hw->pcsr;
++ int i;
++
++ for (i = 0; i < GMAC_REG_NUM; i++)
++ reg_space[i] = readl(ioaddr + i * 4);
+ }
+
+ static int dwmac4_rx_ipc_enable(struct mac_device_info *hw)
+@@ -126,6 +131,65 @@ static void dwmac4_get_umac_addr(struct
+ GMAC_ADDR_LOW(reg_n));
+ }
+
++static void dwmac4_set_eee_mode(struct mac_device_info *hw,
++ bool en_tx_lpi_clockgating)
++{
++ void __iomem *ioaddr = hw->pcsr;
++ u32 value;
++
++ /* Enable the link status receive on RGMII, SGMII ore SMII
++ * receive path and instruct the transmit to enter in LPI
++ * state.
++ */
++ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
++ value |= GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA;
++
++ if (en_tx_lpi_clockgating)
++ value |= GMAC4_LPI_CTRL_STATUS_LPITCSE;
++
++ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
++}
++
++static void dwmac4_reset_eee_mode(struct mac_device_info *hw)
++{
++ void __iomem *ioaddr = hw->pcsr;
++ u32 value;
++
++ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
++ value &= ~(GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA);
++ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
++}
++
++static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
++{
++ void __iomem *ioaddr = hw->pcsr;
++ u32 value;
++
++ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
++
++ if (link)
++ value |= GMAC4_LPI_CTRL_STATUS_PLS;
++ else
++ value &= ~GMAC4_LPI_CTRL_STATUS_PLS;
++
++ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
++}
++
++static void dwmac4_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
++{
++ void __iomem *ioaddr = hw->pcsr;
++ int value = ((tw & 0xffff)) | ((ls & 0x3ff) << 16);
++
++ /* Program the timers in the LPI timer control register:
++ * LS: minimum time (ms) for which the link
++ * status from PHY should be ok before transmitting
++ * the LPI pattern.
++ * TW: minimum time (us) for which the core waits
++ * after it has stopped transmitting the LPI pattern.
++ */
++ writel(value, ioaddr + GMAC4_LPI_TIMER_CTRL);
++}
++
+ static void dwmac4_set_filter(struct mac_device_info *hw,
+ struct net_device *dev)
+ {
+@@ -392,12 +456,17 @@ static void dwmac4_debug(void __iomem *i
+ static const struct stmmac_ops dwmac4_ops = {
+ .core_init = dwmac4_core_init,
+ .rx_ipc = dwmac4_rx_ipc_enable,
++ .rx_queue_enable = dwmac4_rx_queue_enable,
+ .dump_regs = dwmac4_dump_regs,
+ .host_irq_status = dwmac4_irq_status,
+ .flow_ctrl = dwmac4_flow_ctrl,
+ .pmt = dwmac4_pmt,
+ .set_umac_addr = dwmac4_set_umac_addr,
+ .get_umac_addr = dwmac4_get_umac_addr,
++ .set_eee_mode = dwmac4_set_eee_mode,
++ .reset_eee_mode = dwmac4_reset_eee_mode,
++ .set_eee_timer = dwmac4_set_eee_timer,
++ .set_eee_pls = dwmac4_set_eee_pls,
+ .pcs_ctrl_ane = dwmac4_ctrl_ane,
+ .pcs_rane = dwmac4_rane,
+ .pcs_get_adv_lp = dwmac4_get_adv_lp,
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+@@ -103,7 +103,7 @@ static int dwmac4_wrback_get_rx_status(v
+ x->rx_mii++;
+
+ if (unlikely(rdes3 & RDES3_CRC_ERROR)) {
+- x->rx_crc++;
++ x->rx_crc_errors++;
+ stats->rx_crc_errors++;
+ }
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+@@ -127,53 +127,51 @@ static void dwmac4_dma_init(void __iomem
+ dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i);
+ }
+
+-static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel)
++static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel,
++ u32 *reg_space)
+ {
+- pr_debug(" Channel %d\n", channel);
+- pr_debug("\tDMA_CHAN_CONTROL, offset: 0x%x, val: 0x%x\n", 0,
+- readl(ioaddr + DMA_CHAN_CONTROL(channel)));
+- pr_debug("\tDMA_CHAN_TX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x4,
+- readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)));
+- pr_debug("\tDMA_CHAN_RX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x8,
+- readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)));
+- pr_debug("\tDMA_CHAN_TX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x14,
+- readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_RX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x1c,
+- readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_TX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x20,
+- readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_RX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x28,
+- readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_TX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x2c,
+- readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel)));
+- pr_debug("\tDMA_CHAN_RX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x30,
+- readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel)));
+- pr_debug("\tDMA_CHAN_INTR_ENA, offset: 0x%x, val: 0x%x\n", 0x34,
+- readl(ioaddr + DMA_CHAN_INTR_ENA(channel)));
+- pr_debug("\tDMA_CHAN_RX_WATCHDOG, offset: 0x%x, val: 0x%x\n", 0x38,
+- readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel)));
+- pr_debug("\tDMA_CHAN_SLOT_CTRL_STATUS, offset: 0x%x, val: 0x%x\n", 0x3c,
+- readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel)));
+- pr_debug("\tDMA_CHAN_CUR_TX_DESC, offset: 0x%x, val: 0x%x\n", 0x44,
+- readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel)));
+- pr_debug("\tDMA_CHAN_CUR_RX_DESC, offset: 0x%x, val: 0x%x\n", 0x4c,
+- readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel)));
+- pr_debug("\tDMA_CHAN_CUR_TX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x54,
+- readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_CUR_RX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x5c,
+- readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel)));
+- pr_debug("\tDMA_CHAN_STATUS, offset: 0x%x, val: 0x%x\n", 0x60,
+- readl(ioaddr + DMA_CHAN_STATUS(channel)));
++ reg_space[DMA_CHAN_CONTROL(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_CONTROL(channel));
++ reg_space[DMA_CHAN_TX_CONTROL(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_TX_CONTROL(channel));
++ reg_space[DMA_CHAN_RX_CONTROL(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_RX_CONTROL(channel));
++ reg_space[DMA_CHAN_TX_BASE_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel));
++ reg_space[DMA_CHAN_RX_BASE_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel));
++ reg_space[DMA_CHAN_TX_END_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel));
++ reg_space[DMA_CHAN_RX_END_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel));
++ reg_space[DMA_CHAN_TX_RING_LEN(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel));
++ reg_space[DMA_CHAN_RX_RING_LEN(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel));
++ reg_space[DMA_CHAN_INTR_ENA(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_INTR_ENA(channel));
++ reg_space[DMA_CHAN_RX_WATCHDOG(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel));
++ reg_space[DMA_CHAN_SLOT_CTRL_STATUS(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel));
++ reg_space[DMA_CHAN_CUR_TX_DESC(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel));
++ reg_space[DMA_CHAN_CUR_RX_DESC(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel));
++ reg_space[DMA_CHAN_CUR_TX_BUF_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel));
++ reg_space[DMA_CHAN_CUR_RX_BUF_ADDR(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel));
++ reg_space[DMA_CHAN_STATUS(channel) / 4] =
++ readl(ioaddr + DMA_CHAN_STATUS(channel));
+ }
+
+-static void dwmac4_dump_dma_regs(void __iomem *ioaddr)
++static void dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
+ {
+ int i;
+
+- pr_debug(" GMAC4 DMA registers\n");
+-
+ for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
+- _dwmac4_dump_dma_regs(ioaddr, i);
++ _dwmac4_dump_dma_regs(ioaddr, i, reg_space);
+ }
+
+ static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt)
+@@ -303,6 +301,11 @@ static void dwmac4_get_hw_feature(void _
+ ((hw_cap & GMAC_HW_FEAT_RXCHCNT) >> 12) + 1;
+ dma_cap->number_tx_channel =
+ ((hw_cap & GMAC_HW_FEAT_TXCHCNT) >> 18) + 1;
++ /* TX and RX number of queues */
++ dma_cap->number_rx_queues =
++ ((hw_cap & GMAC_HW_FEAT_RXQCNT) >> 0) + 1;
++ dma_cap->number_tx_queues =
++ ((hw_cap & GMAC_HW_FEAT_TXQCNT) >> 6) + 1;
+
+ /* IEEE 1588-2002 */
+ dma_cap->time_stamp = 0;
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+@@ -10,10 +10,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -21,6 +17,7 @@
+ *******************************************************************************/
+
+ #include <linux/io.h>
++#include <linux/iopoll.h>
+ #include "common.h"
+ #include "dwmac_dma.h"
+
+@@ -29,19 +26,16 @@
+ int dwmac_dma_reset(void __iomem *ioaddr)
+ {
+ u32 value = readl(ioaddr + DMA_BUS_MODE);
+- int limit;
++ int err;
+
+ /* DMA SW reset */
+ value |= DMA_BUS_MODE_SFT_RESET;
+ writel(value, ioaddr + DMA_BUS_MODE);
+- limit = 10;
+- while (limit--) {
+- if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
+- break;
+- mdelay(10);
+- }
+
+- if (limit < 0)
++ err = readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
++ !(value & DMA_BUS_MODE_SFT_RESET),
++ 100000, 10000);
++ if (err)
+ return -EBUSY;
+
+ return 0;
+@@ -102,7 +96,7 @@ static void show_tx_process_state(unsign
+ pr_debug("- TX (Stopped): Reset or Stop command\n");
+ break;
+ case 1:
+- pr_debug("- TX (Running):Fetching the Tx desc\n");
++ pr_debug("- TX (Running): Fetching the Tx desc\n");
+ break;
+ case 2:
+ pr_debug("- TX (Running): Waiting for end of tx\n");
+@@ -136,7 +130,7 @@ static void show_rx_process_state(unsign
+ pr_debug("- RX (Running): Fetching the Rx desc\n");
+ break;
+ case 2:
+- pr_debug("- RX (Running):Checking for end of pkt\n");
++ pr_debug("- RX (Running): Checking for end of pkt\n");
+ break;
+ case 3:
+ pr_debug("- RX (Running): Waiting for Rx pkt\n");
+@@ -246,7 +240,7 @@ void stmmac_set_mac_addr(void __iomem *i
+ unsigned long data;
+
+ data = (addr[5] << 8) | addr[4];
+- /* For MAC Addr registers se have to set the Address Enable (AE)
++ /* For MAC Addr registers we have to set the Address Enable (AE)
+ * bit that has no effect on the High Reg 0 where the bit 31 (MO)
+ * is RO.
+ */
+@@ -261,9 +255,9 @@ void stmmac_set_mac(void __iomem *ioaddr
+ u32 value = readl(ioaddr + MAC_CTRL_REG);
+
+ if (enable)
+- value |= MAC_RNABLE_RX | MAC_ENABLE_TX;
++ value |= MAC_ENABLE_RX | MAC_ENABLE_TX;
+ else
+- value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX);
++ value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX);
+
+ writel(value, ioaddr + MAC_CTRL_REG);
+ }
+--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
++++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -225,7 +221,7 @@ static int enh_desc_get_rx_status(void *
+ x->rx_mii++;
+
+ if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
+- x->rx_crc++;
++ x->rx_crc_errors++;
+ stats->rx_crc_errors++;
+ }
+ ret = discard_frame;
+--- a/drivers/net/ethernet/stmicro/stmmac/mmc.h
++++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
++++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -115,7 +111,7 @@ static int ndesc_get_rx_status(void *dat
+ stats->collisions++;
+ }
+ if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
+- x->rx_crc++;
++ x->rx_crc_errors++;
+ stats->rx_crc_errors++;
+ }
+ ret = discard_frame;
+--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
++++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+@@ -16,10 +16,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -10,10 +10,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -106,9 +102,6 @@ struct stmmac_priv {
+ u32 msg_enable;
+ 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;
+ int lpi_irq;
+@@ -120,8 +113,6 @@ struct stmmac_priv {
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_clock_ops;
+ unsigned int default_addend;
+- struct clk *clk_ptp_ref;
+- unsigned int clk_ptp_rate;
+ u32 adv_ts;
+ int use_riwt;
+ int irq_wake;
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -65,7 +61,7 @@ static const struct stmmac_stats stmmac_
+ STMMAC_STAT(overflow_error),
+ STMMAC_STAT(ipc_csum_error),
+ STMMAC_STAT(rx_collision),
+- STMMAC_STAT(rx_crc),
++ STMMAC_STAT(rx_crc_errors),
+ STMMAC_STAT(dribbling_bit),
+ STMMAC_STAT(rx_length),
+ STMMAC_STAT(rx_mii),
+@@ -439,32 +435,14 @@ static int stmmac_ethtool_get_regs_len(s
+ static void stmmac_ethtool_gregs(struct net_device *dev,
+ struct ethtool_regs *regs, void *space)
+ {
+- int i;
+ u32 *reg_space = (u32 *) space;
+
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ memset(reg_space, 0x0, REG_SPACE_SIZE);
+
+- if (!(priv->plat->has_gmac || priv->plat->has_gmac4)) {
+- /* MAC registers */
+- for (i = 0; i < 12; i++)
+- reg_space[i] = readl(priv->ioaddr + (i * 4));
+- /* DMA registers */
+- for (i = 0; i < 9; i++)
+- reg_space[i + 12] =
+- readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
+- reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR);
+- reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR);
+- } else {
+- /* MAC registers */
+- for (i = 0; i < 55; i++)
+- reg_space[i] = readl(priv->ioaddr + (i * 4));
+- /* DMA registers */
+- for (i = 0; i < 22; i++)
+- reg_space[i + 55] =
+- readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
+- }
++ priv->hw->mac->dump_regs(priv->hw, reg_space);
++ priv->hw->dma->dump_regs(priv->ioaddr, reg_space);
+ }
+
+ static void
+@@ -712,7 +690,7 @@ static int stmmac_ethtool_op_set_eee(str
+
+ static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
+ {
+- unsigned long clk = clk_get_rate(priv->stmmac_clk);
++ unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
+
+ if (!clk)
+ return 0;
+@@ -722,7 +700,7 @@ static u32 stmmac_usec2riwt(u32 usec, st
+
+ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
+ {
+- unsigned long clk = clk_get_rate(priv->stmmac_clk);
++ unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
+
+ if (!clk)
+ return 0;
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -13,10 +13,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -158,7 +154,7 @@ static void stmmac_clk_csr_set(struct st
+ {
+ u32 clk_rate;
+
+- clk_rate = clk_get_rate(priv->stmmac_clk);
++ clk_rate = clk_get_rate(priv->plat->stmmac_clk);
+
+ /* Platform provided default clk_csr would be assumed valid
+ * for all other cases except for the below mentioned ones.
+@@ -191,7 +187,7 @@ static void print_pkt(unsigned char *buf
+
+ static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
+ {
+- unsigned avail;
++ u32 avail;
+
+ if (priv->dirty_tx > priv->cur_tx)
+ avail = priv->dirty_tx - priv->cur_tx - 1;
+@@ -203,7 +199,7 @@ static inline u32 stmmac_tx_avail(struct
+
+ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv)
+ {
+- unsigned dirty;
++ u32 dirty;
+
+ if (priv->dirty_rx <= priv->cur_rx)
+ dirty = priv->cur_rx - priv->dirty_rx;
+@@ -216,7 +212,7 @@ static inline u32 stmmac_rx_dirty(struct
+ /**
+ * stmmac_hw_fix_mac_speed - callback for speed selection
+ * @priv: driver private structure
+- * Description: on some platforms (e.g. ST), some HW system configuraton
++ * Description: on some platforms (e.g. ST), some HW system configuration
+ * registers have to be set according to the link speed negotiated.
+ */
+ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
+@@ -239,7 +235,8 @@ static void stmmac_enable_eee_mode(struc
+ /* Check and enter in LPI mode */
+ if ((priv->dirty_tx == priv->cur_tx) &&
+ (priv->tx_path_in_lpi_mode == false))
+- priv->hw->mac->set_eee_mode(priv->hw);
++ priv->hw->mac->set_eee_mode(priv->hw,
++ priv->plat->en_tx_lpi_clockgating);
+ }
+
+ /**
+@@ -415,7 +412,7 @@ static void stmmac_get_rx_hwtstamp(struc
+ /**
+ * stmmac_hwtstamp_ioctl - control hardware timestamping.
+ * @dev: device pointer.
+- * @ifr: An IOCTL specefic structure, that can contain a pointer to
++ * @ifr: An IOCTL specific structure, that can contain a pointer to
+ * a proprietary structure used to pass information to the driver.
+ * Description:
+ * This function configures the MAC to enable/disable both outgoing(TX)
+@@ -606,7 +603,7 @@ static int stmmac_hwtstamp_ioctl(struct
+
+ /* program Sub Second Increment reg */
+ sec_inc = priv->hw->ptp->config_sub_second_increment(
+- priv->ptpaddr, priv->clk_ptp_rate,
++ priv->ptpaddr, priv->plat->clk_ptp_rate,
+ priv->plat->has_gmac4);
+ temp = div_u64(1000000000ULL, sec_inc);
+
+@@ -616,7 +613,7 @@ static int stmmac_hwtstamp_ioctl(struct
+ * where, freq_div_ratio = 1e9ns/sec_inc
+ */
+ temp = (u64)(temp << 32);
+- priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
++ priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
+ priv->hw->ptp->config_addend(priv->ptpaddr,
+ priv->default_addend);
+
+@@ -644,18 +641,6 @@ static int stmmac_init_ptp(struct stmmac
+ if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
+ return -EOPNOTSUPP;
+
+- /* Fall-back to main clock in case of no PTP ref is passed */
+- priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
+- if (IS_ERR(priv->clk_ptp_ref)) {
+- priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
+- priv->clk_ptp_ref = NULL;
+- netdev_dbg(priv->dev, "PTP uses main clock\n");
+- } else {
+- clk_prepare_enable(priv->clk_ptp_ref);
+- priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
+- netdev_dbg(priv->dev, "PTP rate %d\n", priv->clk_ptp_rate);
+- }
+-
+ priv->adv_ts = 0;
+ /* Check if adv_ts can be enabled for dwmac 4.x core */
+ if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp)
+@@ -682,8 +667,8 @@ static int stmmac_init_ptp(struct stmmac
+
+ static void stmmac_release_ptp(struct stmmac_priv *priv)
+ {
+- if (priv->clk_ptp_ref)
+- clk_disable_unprepare(priv->clk_ptp_ref);
++ if (priv->plat->clk_ptp_ref)
++ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+ stmmac_ptp_unregister(priv);
+ }
+
+@@ -704,7 +689,7 @@ static void stmmac_adjust_link(struct ne
+ int new_state = 0;
+ unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
+
+- if (phydev == NULL)
++ if (!phydev)
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -731,33 +716,36 @@ static void stmmac_adjust_link(struct ne
+ new_state = 1;
+ switch (phydev->speed) {
+ case 1000:
+- if (likely((priv->plat->has_gmac) ||
+- (priv->plat->has_gmac4)))
++ if (priv->plat->has_gmac ||
++ priv->plat->has_gmac4)
+ ctrl &= ~priv->hw->link.port;
+- stmmac_hw_fix_mac_speed(priv);
+ break;
+ case 100:
++ if (priv->plat->has_gmac ||
++ priv->plat->has_gmac4) {
++ ctrl |= priv->hw->link.port;
++ ctrl |= priv->hw->link.speed;
++ } else {
++ ctrl &= ~priv->hw->link.port;
++ }
++ break;
+ case 10:
+- if (likely((priv->plat->has_gmac) ||
+- (priv->plat->has_gmac4))) {
++ if (priv->plat->has_gmac ||
++ priv->plat->has_gmac4) {
+ ctrl |= priv->hw->link.port;
+- if (phydev->speed == SPEED_100) {
+- ctrl |= priv->hw->link.speed;
+- } else {
+- ctrl &= ~(priv->hw->link.speed);
+- }
++ ctrl &= ~(priv->hw->link.speed);
+ } else {
+ ctrl &= ~priv->hw->link.port;
+ }
+- stmmac_hw_fix_mac_speed(priv);
+ break;
+ default:
+ netif_warn(priv, link, priv->dev,
+- "Speed (%d) not 10/100\n",
+- phydev->speed);
++ "broken speed: %d\n", phydev->speed);
++ phydev->speed = SPEED_UNKNOWN;
+ break;
+ }
+-
++ if (phydev->speed != SPEED_UNKNOWN)
++ stmmac_hw_fix_mac_speed(priv);
+ priv->speed = phydev->speed;
+ }
+
+@@ -770,8 +758,8 @@ static void stmmac_adjust_link(struct ne
+ } else if (priv->oldlink) {
+ new_state = 1;
+ priv->oldlink = 0;
+- priv->speed = 0;
+- priv->oldduplex = -1;
++ priv->speed = SPEED_UNKNOWN;
++ priv->oldduplex = DUPLEX_UNKNOWN;
+ }
+
+ if (new_state && netif_msg_link(priv))
+@@ -833,8 +821,8 @@ static int stmmac_init_phy(struct net_de
+ int interface = priv->plat->interface;
+ int max_speed = priv->plat->max_speed;
+ priv->oldlink = 0;
+- priv->speed = 0;
+- priv->oldduplex = -1;
++ priv->speed = SPEED_UNKNOWN;
++ priv->oldduplex = DUPLEX_UNKNOWN;
+
+ if (priv->plat->phy_node) {
+ phydev = of_phy_connect(dev, priv->plat->phy_node,
+@@ -886,9 +874,7 @@ static int stmmac_init_phy(struct net_de
+ if (phydev->is_pseudo_fixed_link)
+ phydev->irq = PHY_POLL;
+
+- netdev_dbg(priv->dev, "%s: attached to PHY (UID 0x%x) Link = %d\n",
+- __func__, phydev->phy_id, phydev->link);
+-
++ phy_attached_info(phydev);
+ return 0;
+ }
+
+@@ -1014,7 +1000,7 @@ static void stmmac_free_rx_buffers(struc
+ * @dev: net device structure
+ * @flags: gfp flag.
+ * Description: this function initializes the DMA RX/TX descriptors
+- * and allocates the socket buffers. It suppors the chained and ring
++ * and allocates the socket buffers. It supports the chained and ring
+ * modes.
+ */
+ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
+@@ -1127,13 +1113,6 @@ static void dma_free_tx_skbufs(struct st
+ int i;
+
+ for (i = 0; i < DMA_TX_SIZE; i++) {
+- struct dma_desc *p;
+-
+- if (priv->extend_desc)
+- p = &((priv->dma_etx + i)->basic);
+- else
+- p = priv->dma_tx + i;
+-
+ if (priv->tx_skbuff_dma[i].buf) {
+ if (priv->tx_skbuff_dma[i].map_as_page)
+ dma_unmap_page(priv->device,
+@@ -1147,7 +1126,7 @@ static void dma_free_tx_skbufs(struct st
+ DMA_TO_DEVICE);
+ }
+
+- if (priv->tx_skbuff[i] != NULL) {
++ if (priv->tx_skbuff[i]) {
+ dev_kfree_skb_any(priv->tx_skbuff[i]);
+ priv->tx_skbuff[i] = NULL;
+ priv->tx_skbuff_dma[i].buf = 0;
+@@ -1271,6 +1250,28 @@ static void free_dma_desc_resources(stru
+ }
+
+ /**
++ * stmmac_mac_enable_rx_queues - Enable MAC rx queues
++ * @priv: driver private structure
++ * Description: It is used for enabling the rx queues in the MAC
++ */
++static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv)
++{
++ int rx_count = priv->dma_cap.number_rx_queues;
++ int queue = 0;
++
++ /* If GMAC does not have multiple queues, then this is not necessary*/
++ if (rx_count == 1)
++ return;
++
++ /**
++ * If the core is synthesized with multiple rx queues / multiple
++ * dma channels, then rx queues will be disabled by default.
++ * For now only rx queue 0 is enabled.
++ */
++ priv->hw->mac->rx_queue_enable(priv->hw, queue);
++}
++
++/**
+ * stmmac_dma_operation_mode - HW DMA operation mode
+ * @priv: driver private structure
+ * Description: it is used for configuring the DMA operation mode register in
+@@ -1671,10 +1672,6 @@ static int stmmac_hw_setup(struct net_de
+ /* Copy the MAC addr into the HW */
+ priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
+
+- /* If required, perform hw setup of the bus. */
+- if (priv->plat->bus_setup)
+- priv->plat->bus_setup(priv->ioaddr);
+-
+ /* PS and related bits will be programmed according to the speed */
+ if (priv->hw->pcs) {
+ int speed = priv->plat->mac_port_sel_speed;
+@@ -1691,6 +1688,10 @@ static int stmmac_hw_setup(struct net_de
+ /* Initialize the MAC Core */
+ priv->hw->mac->core_init(priv->hw, dev->mtu);
+
++ /* Initialize MAC RX Queues */
++ if (priv->hw->mac->rx_queue_enable)
++ stmmac_mac_enable_rx_queues(priv);
++
+ ret = priv->hw->mac->rx_ipc(priv->hw);
+ if (!ret) {
+ netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
+@@ -1711,8 +1712,10 @@ static int stmmac_hw_setup(struct net_de
+
+ if (init_ptp) {
+ ret = stmmac_init_ptp(priv);
+- if (ret)
+- netdev_warn(priv->dev, "fail to init PTP.\n");
++ if (ret == -EOPNOTSUPP)
++ netdev_warn(priv->dev, "PTP not supported by HW\n");
++ else if (ret)
++ netdev_warn(priv->dev, "PTP init failed\n");
+ }
+
+ #ifdef CONFIG_DEBUG_FS
+@@ -1726,11 +1729,6 @@ static int stmmac_hw_setup(struct net_de
+ priv->hw->dma->start_tx(priv->ioaddr);
+ priv->hw->dma->start_rx(priv->ioaddr);
+
+- /* Dump DMA/MAC registers */
+- if (netif_msg_hw(priv)) {
+- priv->hw->mac->dump_regs(priv->hw);
+- priv->hw->dma->dump_regs(priv->ioaddr);
+- }
+ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
+
+ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+@@ -2519,7 +2517,7 @@ static int stmmac_rx(struct stmmac_priv
+ if (unlikely(status == discard_frame)) {
+ priv->dev->stats.rx_errors++;
+ if (priv->hwts_rx_en && !priv->extend_desc) {
+- /* DESC2 & DESC3 will be overwitten by device
++ /* DESC2 & DESC3 will be overwritten by device
+ * with timestamp value, hence reinitialize
+ * them in stmmac_rx_refill() function so that
+ * device can reuse it.
+@@ -2542,7 +2540,7 @@ static int stmmac_rx(struct stmmac_priv
+
+ frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
+
+- /* If frame length is greather than skb buffer size
++ /* If frame length is greater than skb buffer size
+ * (preallocated during init) then the packet is
+ * ignored
+ */
+@@ -2669,7 +2667,7 @@ static int stmmac_poll(struct napi_struc
+
+ work_done = stmmac_rx(priv, budget);
+ if (work_done < budget) {
+- napi_complete(napi);
++ napi_complete_done(napi, work_done);
+ stmmac_enable_dma_irq(priv);
+ }
+ return work_done;
+@@ -2762,7 +2760,7 @@ static netdev_features_t stmmac_fix_feat
+ /* Some GMAC devices have a bugged Jumbo frame support that
+ * needs to have the Tx COE disabled for oversized frames
+ * (due to limited buffer sizes). In this case we disable
+- * the TX csum insertionin the TDES and not use SF.
++ * the TX csum insertion in the TDES and not use SF.
+ */
+ if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
+ features &= ~NETIF_F_CSUM_MASK;
+@@ -2908,9 +2906,7 @@ static void sysfs_display_ring(void *hea
+ struct dma_desc *p = (struct dma_desc *)head;
+
+ for (i = 0; i < size; i++) {
+- u64 x;
+ if (extend_desc) {
+- x = *(u64 *) ep;
+ seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, (unsigned int)virt_to_phys(ep),
+ le32_to_cpu(ep->basic.des0),
+@@ -2919,7 +2915,6 @@ static void sysfs_display_ring(void *hea
+ le32_to_cpu(ep->basic.des3));
+ ep++;
+ } else {
+- x = *(u64 *) p;
+ seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, (unsigned int)virt_to_phys(ep),
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+@@ -2989,7 +2984,7 @@ static int stmmac_sysfs_dma_cap_read(str
+ (priv->dma_cap.hash_filter) ? "Y" : "N");
+ seq_printf(seq, "\tMultiple MAC address registers: %s\n",
+ (priv->dma_cap.multi_addr) ? "Y" : "N");
+- seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
++ seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n",
+ (priv->dma_cap.pcs) ? "Y" : "N");
+ seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
+ (priv->dma_cap.sma_mdio) ? "Y" : "N");
+@@ -3265,44 +3260,8 @@ int stmmac_dvr_probe(struct device *devi
+ if ((phyaddr >= 0) && (phyaddr <= 31))
+ priv->plat->phy_addr = phyaddr;
+
+- priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
+- if (IS_ERR(priv->stmmac_clk)) {
+- netdev_warn(priv->dev, "%s: warning: cannot get CSR clock\n",
+- __func__);
+- /* If failed to obtain stmmac_clk and specific clk_csr value
+- * is NOT passed from the platform, probe fail.
+- */
+- if (!priv->plat->clk_csr) {
+- ret = PTR_ERR(priv->stmmac_clk);
+- goto error_clk_get;
+- } else {
+- priv->stmmac_clk = NULL;
+- }
+- }
+- 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)) {
+- if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
+- ret = -EPROBE_DEFER;
+- goto error_hw_init;
+- }
+- dev_info(priv->device, "no reset control found\n");
+- priv->stmmac_rst = NULL;
+- }
+- if (priv->stmmac_rst)
+- reset_control_deassert(priv->stmmac_rst);
++ if (priv->plat->stmmac_rst)
++ reset_control_deassert(priv->plat->stmmac_rst);
+
+ /* Init MAC and get the capabilities */
+ ret = stmmac_hw_init(priv);
+@@ -3388,10 +3347,6 @@ error_netdev_register:
+ error_mdio_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 ret;
+@@ -3417,10 +3372,10 @@ int stmmac_dvr_remove(struct device *dev
+ stmmac_set_mac(priv->ioaddr, false);
+ 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->plat->stmmac_rst)
++ reset_control_assert(priv->plat->stmmac_rst);
++ clk_disable_unprepare(priv->plat->pclk);
++ clk_disable_unprepare(priv->plat->stmmac_clk);
+ if (priv->hw->pcs != STMMAC_PCS_RGMII &&
+ priv->hw->pcs != STMMAC_PCS_TBI &&
+ priv->hw->pcs != STMMAC_PCS_RTBI)
+@@ -3469,14 +3424,14 @@ int stmmac_suspend(struct device *dev)
+ 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);
++ clk_disable(priv->plat->pclk);
++ clk_disable(priv->plat->stmmac_clk);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ priv->oldlink = 0;
+- priv->speed = 0;
+- priv->oldduplex = -1;
++ priv->speed = SPEED_UNKNOWN;
++ priv->oldduplex = DUPLEX_UNKNOWN;
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(stmmac_suspend);
+@@ -3509,9 +3464,9 @@ int stmmac_resume(struct device *dev)
+ priv->irq_wake = 0;
+ } else {
+ pinctrl_pm_select_default_state(priv->device);
+- /* enable the clk prevously disabled */
+- clk_enable(priv->stmmac_clk);
+- clk_enable(priv->pclk);
++ /* enable the clk previously disabled */
++ clk_enable(priv->plat->stmmac_clk);
++ clk_enable(priv->plat->pclk);
+ /* reset the phy so that it's ready */
+ if (priv->mii)
+ stmmac_mdio_reset(priv->mii);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+@@ -13,10 +13,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -24,13 +20,14 @@
+ Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ *******************************************************************************/
+
++#include <linux/io.h>
++#include <linux/iopoll.h>
+ #include <linux/mii.h>
+-#include <linux/phy.h>
+-#include <linux/slab.h>
+ #include <linux/of.h>
+ #include <linux/of_gpio.h>
+ #include <linux/of_mdio.h>
+-#include <asm/io.h>
++#include <linux/phy.h>
++#include <linux/slab.h>
+
+ #include "stmmac.h"
+
+@@ -42,22 +39,6 @@
+ #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
+ #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
+
+-static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
+-{
+- unsigned long curr;
+- unsigned long finish = jiffies + 3 * HZ;
+-
+- do {
+- curr = jiffies;
+- if (readl(ioaddr + mii_addr) & MII_BUSY)
+- cpu_relax();
+- else
+- return 0;
+- } while (!time_after_eq(curr, finish));
+-
+- return -EBUSY;
+-}
+-
+ /**
+ * stmmac_mdio_read
+ * @bus: points to the mii_bus structure
+@@ -74,7 +55,7 @@ static int stmmac_mdio_read(struct mii_b
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int mii_address = priv->hw->mii.addr;
+ unsigned int mii_data = priv->hw->mii.data;
+-
++ u32 v;
+ int data;
+ u32 value = MII_BUSY;
+
+@@ -86,12 +67,14 @@ static int stmmac_mdio_read(struct mii_b
+ if (priv->plat->has_gmac4)
+ value |= MII_GMAC4_READ;
+
+- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
++ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
++ 100, 10000))
+ return -EBUSY;
+
+ writel(value, priv->ioaddr + mii_address);
+
+- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
++ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
++ 100, 10000))
+ return -EBUSY;
+
+ /* Read the data from the MII data register */
+@@ -115,7 +98,7 @@ static int stmmac_mdio_write(struct mii_
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int mii_address = priv->hw->mii.addr;
+ unsigned int mii_data = priv->hw->mii.data;
+-
++ u32 v;
+ u32 value = MII_BUSY;
+
+ value |= (phyaddr << priv->hw->mii.addr_shift)
+@@ -130,7 +113,8 @@ static int stmmac_mdio_write(struct mii_
+ value |= MII_WRITE;
+
+ /* Wait until any existing MII operation is complete */
+- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
++ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
++ 100, 10000))
+ return -EBUSY;
+
+ /* Set the MII address register to write */
+@@ -138,7 +122,8 @@ static int stmmac_mdio_write(struct mii_
+ writel(value, priv->ioaddr + mii_address);
+
+ /* Wait until any existing MII operation is complete */
+- return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
++ return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
++ 100, 10000);
+ }
+
+ /**
+@@ -156,9 +141,9 @@ int stmmac_mdio_reset(struct mii_bus *bu
+
+ #ifdef CONFIG_OF
+ if (priv->device->of_node) {
+-
+ if (data->reset_gpio < 0) {
+ struct device_node *np = priv->device->of_node;
++
+ if (!np)
+ return 0;
+
+@@ -198,7 +183,7 @@ int stmmac_mdio_reset(struct mii_bus *bu
+
+ /* This is a workaround for problems with the STE101P PHY.
+ * It doesn't complete its reset until at least one clock cycle
+- * on MDC, so perform a dummy mdio read. To be upadted for GMAC4
++ * on MDC, so perform a dummy mdio read. To be updated for GMAC4
+ * if needed.
+ */
+ if (!priv->plat->has_gmac4)
+@@ -225,7 +210,7 @@ int stmmac_mdio_register(struct net_devi
+ return 0;
+
+ new_bus = mdiobus_alloc();
+- if (new_bus == NULL)
++ if (!new_bus)
+ return -ENOMEM;
+
+ if (mdio_bus_data->irqs)
+@@ -262,49 +247,48 @@ int stmmac_mdio_register(struct net_devi
+ found = 0;
+ for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
+ struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
+- if (phydev) {
+- int act = 0;
+- char irq_num[4];
+- char *irq_str;
+-
+- /*
+- * If an IRQ was provided to be assigned after
+- * the bus probe, do it here.
+- */
+- if ((mdio_bus_data->irqs == NULL) &&
+- (mdio_bus_data->probed_phy_irq > 0)) {
+- new_bus->irq[addr] =
+- mdio_bus_data->probed_phy_irq;
+- phydev->irq = mdio_bus_data->probed_phy_irq;
+- }
+-
+- /*
+- * If we're going to bind the MAC to this PHY bus,
+- * and no PHY number was provided to the MAC,
+- * use the one probed here.
+- */
+- if (priv->plat->phy_addr == -1)
+- priv->plat->phy_addr = addr;
+-
+- act = (priv->plat->phy_addr == addr);
+- switch (phydev->irq) {
+- case PHY_POLL:
+- irq_str = "POLL";
+- break;
+- case PHY_IGNORE_INTERRUPT:
+- irq_str = "IGNORE";
+- break;
+- default:
+- sprintf(irq_num, "%d", phydev->irq);
+- irq_str = irq_num;
+- break;
+- }
+- netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
+- phydev->phy_id, addr,
+- irq_str, phydev_name(phydev),
+- act ? " active" : "");
+- found = 1;
++ int act = 0;
++ char irq_num[4];
++ char *irq_str;
++
++ if (!phydev)
++ continue;
++
++ /*
++ * If an IRQ was provided to be assigned after
++ * the bus probe, do it here.
++ */
++ if (!mdio_bus_data->irqs &&
++ (mdio_bus_data->probed_phy_irq > 0)) {
++ new_bus->irq[addr] = mdio_bus_data->probed_phy_irq;
++ phydev->irq = mdio_bus_data->probed_phy_irq;
++ }
++
++ /*
++ * If we're going to bind the MAC to this PHY bus,
++ * and no PHY number was provided to the MAC,
++ * use the one probed here.
++ */
++ if (priv->plat->phy_addr == -1)
++ priv->plat->phy_addr = addr;
++
++ act = (priv->plat->phy_addr == addr);
++ switch (phydev->irq) {
++ case PHY_POLL:
++ irq_str = "POLL";
++ break;
++ case PHY_IGNORE_INTERRUPT:
++ irq_str = "IGNORE";
++ break;
++ default:
++ sprintf(irq_num, "%d", phydev->irq);
++ irq_str = irq_num;
++ break;
+ }
++ netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
++ phydev->phy_id, addr, irq_str, phydev_name(phydev),
++ act ? " active" : "");
++ found = 1;
+ }
+
+ if (!found && !mdio_node) {
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+@@ -121,7 +117,6 @@ static struct stmmac_axi *stmmac_axi_set
+ axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en");
+ axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm");
+ axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe");
+- axi->axi_axi_all = of_property_read_bool(np, "snps,axi_all");
+ axi->axi_fb = of_property_read_bool(np, "snps,axi_fb");
+ axi->axi_mb = of_property_read_bool(np, "snps,axi_mb");
+ axi->axi_rb = of_property_read_bool(np, "snps,axi_rb");
+@@ -181,10 +176,19 @@ static int stmmac_dt_phy(struct plat_stm
+ mdio = false;
+ }
+
+- /* If snps,dwmac-mdio is passed from DT, always register the MDIO */
+- for_each_child_of_node(np, plat->mdio_node) {
+- if (of_device_is_compatible(plat->mdio_node, "snps,dwmac-mdio"))
+- break;
++ /* exception for dwmac-dwc-qos-eth glue logic */
++ if (of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) {
++ plat->mdio_node = of_get_child_by_name(np, "mdio");
++ } else {
++ /**
++ * If snps,dwmac-mdio is passed from DT, always register
++ * the MDIO
++ */
++ for_each_child_of_node(np, plat->mdio_node) {
++ if (of_device_is_compatible(plat->mdio_node,
++ "snps,dwmac-mdio"))
++ break;
++ }
+ }
+
+ if (plat->mdio_node) {
+@@ -249,6 +253,9 @@ stmmac_probe_config_dt(struct platform_d
+ plat->force_sf_dma_mode =
+ of_property_read_bool(np, "snps,force_sf_dma_mode");
+
++ plat->en_tx_lpi_clockgating =
++ of_property_read_bool(np, "snps,en-tx-lpi-clockgating");
++
+ /* Set the maxmtu to a default of JUMBO_LEN in case the
+ * parameter is not present in the device tree.
+ */
+@@ -333,7 +340,54 @@ stmmac_probe_config_dt(struct platform_d
+
+ plat->axi = stmmac_axi_setup(pdev);
+
++ /* clock setup */
++ plat->stmmac_clk = devm_clk_get(&pdev->dev,
++ STMMAC_RESOURCE_NAME);
++ if (IS_ERR(plat->stmmac_clk)) {
++ dev_warn(&pdev->dev, "Cannot get CSR clock\n");
++ plat->stmmac_clk = NULL;
++ }
++ clk_prepare_enable(plat->stmmac_clk);
++
++ plat->pclk = devm_clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(plat->pclk)) {
++ if (PTR_ERR(plat->pclk) == -EPROBE_DEFER)
++ goto error_pclk_get;
++
++ plat->pclk = NULL;
++ }
++ clk_prepare_enable(plat->pclk);
++
++ /* Fall-back to main clock in case of no PTP ref is passed */
++ plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "clk_ptp_ref");
++ if (IS_ERR(plat->clk_ptp_ref)) {
++ plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
++ plat->clk_ptp_ref = NULL;
++ dev_warn(&pdev->dev, "PTP uses main clock\n");
++ } else {
++ clk_prepare_enable(plat->clk_ptp_ref);
++ plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
++ dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate);
++ }
++
++ plat->stmmac_rst = devm_reset_control_get(&pdev->dev,
++ STMMAC_RESOURCE_NAME);
++ if (IS_ERR(plat->stmmac_rst)) {
++ if (PTR_ERR(plat->stmmac_rst) == -EPROBE_DEFER)
++ goto error_hw_init;
++
++ dev_info(&pdev->dev, "no reset control found\n");
++ plat->stmmac_rst = NULL;
++ }
++
+ return plat;
++
++error_hw_init:
++ clk_disable_unprepare(plat->pclk);
++error_pclk_get:
++ clk_disable_unprepare(plat->stmmac_clk);
++
++ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ /**
+@@ -357,7 +411,7 @@ void stmmac_remove_config_dt(struct plat
+ struct plat_stmmacenet_data *
+ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
+ {
+- return ERR_PTR(-ENOSYS);
++ return ERR_PTR(-EINVAL);
+ }
+
+ void stmmac_remove_config_dt(struct platform_device *pdev,
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+@@ -12,10 +12,6 @@
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+- You should have received a copy of the GNU General Public License along with
+- this program; if not, write to the Free Software Foundation, Inc.,
+- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+-
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -103,7 +103,6 @@ struct stmmac_axi {
+ u32 axi_wr_osr_lmt;
+ u32 axi_rd_osr_lmt;
+ bool axi_kbbe;
+- bool axi_axi_all;
+ u32 axi_blen[AXI_BLEN];
+ bool axi_fb;
+ bool axi_mb;
+@@ -135,13 +134,18 @@ struct plat_stmmacenet_data {
+ int tx_fifo_size;
+ int rx_fifo_size;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+- void (*bus_setup)(void __iomem *ioaddr);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
+ void *bsp_priv;
++ struct clk *stmmac_clk;
++ struct clk *pclk;
++ struct clk *clk_ptp_ref;
++ unsigned int clk_ptp_rate;
++ struct reset_control *stmmac_rst;
+ struct stmmac_axi *axi;
+ int has_gmac4;
+ bool tso_en;
+ int mac_port_sel_speed;
++ bool en_tx_lpi_clockgating;
+ };
+ #endif