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