aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch
diff options
context:
space:
mode:
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 0000000000..f3b4262307
--- /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