diff options
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.patch | 2305 |
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 |