mirror of https://github.com/hak5/openwrt-owl.git
2356 lines
71 KiB
Diff
2356 lines
71 KiB
Diff
|
--- 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
|
||
|
@@ -16,6 +16,7 @@ if STMMAC_ETH
|
||
|
config STMMAC_PLATFORM
|
||
|
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 driver.
|
||
|
@@ -26,6 +27,95 @@ config STMMAC_PLATFORM
|
||
|
|
||
|
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
|
||
|
+ tristate "Amlogic Meson dwmac support"
|
||
|
+ default ARCH_MESON
|
||
|
+ depends on OF
|
||
|
+ help
|
||
|
+ Support for Ethernet controller on Amlogic Meson SoCs.
|
||
|
+
|
||
|
+ This selects the Amlogic Meson SoC glue layer support for
|
||
|
+ 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
|
||
|
+ tristate "SOCFPGA dwmac support"
|
||
|
+ default ARCH_SOCFPGA
|
||
|
+ depends on OF
|
||
|
+ select MFD_SYSCON
|
||
|
+ help
|
||
|
+ Support for ethernet controller on Altera SOCFPGA
|
||
|
+
|
||
|
+ This selects the Altera SOCFPGA SoC glue layer support
|
||
|
+ for the stmmac device driver. This driver is used for
|
||
|
+ arria5 and cyclone5 FPGA SoCs.
|
||
|
+
|
||
|
+config DWMAC_STI
|
||
|
+ tristate "STi GMAC support"
|
||
|
+ default ARCH_STI
|
||
|
+ depends on OF
|
||
|
+ select MFD_SYSCON
|
||
|
+ ---help---
|
||
|
+ Support for ethernet controller on STi SOCs.
|
||
|
+
|
||
|
+ This selects STi SoC glue layer support for the stmmac
|
||
|
+ 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
|
||
|
tristate "STMMAC PCI bus support"
|
||
|
depends on STMMAC_ETH && PCI
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
|
||
|
@@ -4,9 +4,17 @@ stmmac-objs:= stmmac_main.o stmmac_ethto
|
||
|
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
|
||
|
mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y)
|
||
|
|
||
|
-obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
|
||
|
-stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \
|
||
|
- dwmac-sti.o dwmac-socfpga.o dwmac-rk.o
|
||
|
+# 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
|
||
|
--- /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,6 +15,7 @@
|
||
|
#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>
|
||
|
|
||
|
@@ -46,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 ERR_CAST(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");
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
|
||
|
@@ -22,17 +22,31 @@
|
||
|
#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;
|
||
|
@@ -60,103 +74,228 @@ struct rk_priv_data {
|
||
|
|
||
|
#define RK3288_GRF_SOC_CON1 0x0248
|
||
|
#define RK3288_GRF_SOC_CON3 0x0250
|
||
|
-#define RK3288_GRF_GPIO3D_E 0x01ec
|
||
|
-#define RK3288_GRF_GPIO4A_E 0x01f0
|
||
|
-#define RK3288_GRF_GPIO4B_E 0x01f4
|
||
|
|
||
|
/*RK3288_GRF_SOC_CON1*/
|
||
|
-#define GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
|
||
|
-#define GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8))
|
||
|
-#define GMAC_FLOW_CTRL GRF_BIT(9)
|
||
|
-#define GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9)
|
||
|
-#define GMAC_SPEED_10M GRF_CLR_BIT(10)
|
||
|
-#define GMAC_SPEED_100M GRF_BIT(10)
|
||
|
-#define GMAC_RMII_CLK_25M GRF_BIT(11)
|
||
|
-#define GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11)
|
||
|
-#define GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
|
||
|
-#define GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13))
|
||
|
-#define GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13))
|
||
|
-#define GMAC_RMII_MODE GRF_BIT(14)
|
||
|
-#define GMAC_RMII_MODE_CLR GRF_CLR_BIT(14)
|
||
|
+#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 GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
|
||
|
-#define GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
|
||
|
-#define GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
||
|
-#define GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
||
|
-#define GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
|
||
|
-#define GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
||
|
+#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 set_to_rgmii(struct rk_priv_data *bsp_priv,
|
||
|
- int tx_delay, int rx_delay)
|
||
|
+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, "%s: Missing rockchip,grf property\n", __func__);
|
||
|
+ dev_err(dev, "Missing rockchip,grf property\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
||
|
- GMAC_PHY_INTF_SEL_RGMII | GMAC_RMII_MODE_CLR);
|
||
|
+ RK3288_GMAC_PHY_INTF_SEL_RGMII |
|
||
|
+ RK3288_GMAC_RMII_MODE_CLR);
|
||
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
|
||
|
- GMAC_RXCLK_DLY_ENABLE | GMAC_TXCLK_DLY_ENABLE |
|
||
|
- GMAC_CLK_RX_DL_CFG(rx_delay) |
|
||
|
- GMAC_CLK_TX_DL_CFG(tx_delay));
|
||
|
+ 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 set_to_rmii(struct rk_priv_data *bsp_priv)
|
||
|
+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, "%s: Missing rockchip,grf property\n", __func__);
|
||
|
+ dev_err(dev, "Missing rockchip,grf property\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
||
|
- GMAC_PHY_INTF_SEL_RMII | GMAC_RMII_MODE);
|
||
|
+ RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
|
||
|
}
|
||
|
|
||
|
-static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||
|
+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, "%s: Missing rockchip,grf property\n", __func__);
|
||
|
+ dev_err(dev, "Missing rockchip,grf property\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (speed == 10)
|
||
|
- regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_2_5M);
|
||
|
+ 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, GMAC_CLK_25M);
|
||
|
+ 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, GMAC_CLK_125M);
|
||
|
+ 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 set_rmii_speed(struct rk_priv_data *bsp_priv, int 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, "%s: Missing rockchip,grf property\n", __func__);
|
||
|
+ dev_err(dev, "Missing rockchip,grf property\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (speed == 10) {
|
||
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
||
|
- GMAC_RMII_CLK_2_5M | GMAC_SPEED_10M);
|
||
|
+ RK3288_GMAC_RMII_CLK_2_5M |
|
||
|
+ RK3288_GMAC_SPEED_10M);
|
||
|
} else if (speed == 100) {
|
||
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
||
|
- GMAC_RMII_CLK_25M | GMAC_SPEED_100M);
|
||
|
+ 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;
|
||
|
@@ -165,46 +304,46 @@ static int gmac_clk_init(struct rk_priv_
|
||
|
|
||
|
bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
|
||
|
if (IS_ERR(bsp_priv->mac_clk_rx))
|
||
|
- dev_err(dev, "%s: cannot get clock %s\n",
|
||
|
- __func__, "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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "stmmaceth");
|
||
|
+ 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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "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, "%s: cannot get clock %s\n",
|
||
|
- __func__, "clk_mac_refout");
|
||
|
+ dev_err(dev, "cannot get clock %s\n",
|
||
|
+ "clk_mac_refout");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bsp_priv->clock_input) {
|
||
|
- dev_info(dev, "%s: clock input from PHY\n", __func__);
|
||
|
+ 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);
|
||
|
@@ -291,26 +430,25 @@ static int phy_power_on(struct rk_priv_d
|
||
|
struct device *dev = &bsp_priv->pdev->dev;
|
||
|
|
||
|
if (!ldo) {
|
||
|
- dev_err(dev, "%s: no regulator found\n", __func__);
|
||
|
+ dev_err(dev, "no regulator found\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (enable) {
|
||
|
ret = regulator_enable(ldo);
|
||
|
if (ret)
|
||
|
- dev_err(dev, "%s: fail to enable phy-supply\n",
|
||
|
- __func__);
|
||
|
+ dev_err(dev, "fail to enable phy-supply\n");
|
||
|
} else {
|
||
|
ret = regulator_disable(ldo);
|
||
|
if (ret)
|
||
|
- dev_err(dev, "%s: fail to disable phy-supply\n",
|
||
|
- __func__);
|
||
|
+ dev_err(dev, "fail to disable phy-supply\n");
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-static void *rk_gmac_setup(struct platform_device *pdev)
|
||
|
+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;
|
||
|
@@ -323,6 +461,7 @@ static void *rk_gmac_setup(struct platfo
|
||
|
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)) {
|
||
|
@@ -336,12 +475,11 @@ static void *rk_gmac_setup(struct platfo
|
||
|
|
||
|
ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
|
||
|
if (ret) {
|
||
|
- dev_err(dev, "%s: Can not read property: clock_in_out.\n",
|
||
|
- __func__);
|
||
|
+ dev_err(dev, "Can not read property: clock_in_out.\n");
|
||
|
bsp_priv->clock_input = true;
|
||
|
} else {
|
||
|
- dev_info(dev, "%s: clock input or output? (%s).\n",
|
||
|
- __func__, strings);
|
||
|
+ dev_info(dev, "clock input or output? (%s).\n",
|
||
|
+ strings);
|
||
|
if (!strcmp(strings, "input"))
|
||
|
bsp_priv->clock_input = true;
|
||
|
else
|
||
|
@@ -351,22 +489,22 @@ static void *rk_gmac_setup(struct platfo
|
||
|
ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
|
||
|
if (ret) {
|
||
|
bsp_priv->tx_delay = 0x30;
|
||
|
- dev_err(dev, "%s: Can not read property: tx_delay.", __func__);
|
||
|
- dev_err(dev, "%s: set tx_delay to 0x%x\n",
|
||
|
- __func__, bsp_priv->tx_delay);
|
||
|
+ 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, "%s: TX delay(0x%x).\n", __func__, value);
|
||
|
+ 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, "%s: Can not read property: rx_delay.", __func__);
|
||
|
- dev_err(dev, "%s: set rx_delay to 0x%x\n",
|
||
|
- __func__, bsp_priv->rx_delay);
|
||
|
+ 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, "%s: RX delay(0x%x).\n", __func__, value);
|
||
|
+ dev_info(dev, "RX delay(0x%x).\n", value);
|
||
|
bsp_priv->rx_delay = value;
|
||
|
}
|
||
|
|
||
|
@@ -376,13 +514,14 @@ static void *rk_gmac_setup(struct platfo
|
||
|
|
||
|
/*rmii or rgmii*/
|
||
|
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
|
||
|
- dev_info(dev, "%s: init for RGMII\n", __func__);
|
||
|
- set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay);
|
||
|
+ 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, "%s: init for RMII\n", __func__);
|
||
|
- set_to_rmii(bsp_priv);
|
||
|
+ dev_info(dev, "init for RMII\n");
|
||
|
+ bsp_priv->ops->set_to_rmii(bsp_priv);
|
||
|
} else {
|
||
|
- dev_err(dev, "%s: NO interface defined!\n", __func__);
|
||
|
+ dev_err(dev, "NO interface defined!\n");
|
||
|
}
|
||
|
|
||
|
gmac_clk_init(bsp_priv);
|
||
|
@@ -420,17 +559,68 @@ static void rk_fix_speed(void *priv, uns
|
||
|
struct device *dev = &bsp_priv->pdev->dev;
|
||
|
|
||
|
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
|
||
|
- set_rgmii_speed(bsp_priv, speed);
|
||
|
+ bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
|
||
|
else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
|
||
|
- set_rmii_speed(bsp_priv, speed);
|
||
|
+ bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
|
||
|
else
|
||
|
dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
|
||
|
}
|
||
|
|
||
|
-const struct stmmac_of_data rk3288_gmac_data = {
|
||
|
- .has_gmac = 1,
|
||
|
- .fix_mac_speed = rk_fix_speed,
|
||
|
- .setup = rk_gmac_setup,
|
||
|
- .init = rk_gmac_init,
|
||
|
- .exit = rk_gmac_exit,
|
||
|
+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
|
||
|
@@ -175,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;
|
||
|
@@ -257,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
|
||
|
@@ -17,9 +17,11 @@
|
||
|
#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"
|
||
|
@@ -127,6 +129,11 @@ struct sti_dwmac {
|
||
|
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[] = {
|
||
|
@@ -221,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;
|
||
|
@@ -240,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;
|
||
|
}
|
||
|
@@ -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,
|
||
|
+};
|
||
|
+
|
||
|
+static const struct sti_dwmac_of_data stid127_dwmac_data = {
|
||
|
+ .fix_retime_src = stid127_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 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
|
||
|
@@ -18,7 +18,9 @@
|
||
|
|
||
|
#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>
|
||
|
|
||
|
@@ -31,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
|
||
|
|
||
|
@@ -130,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/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;
|
||
|
@@ -135,9 +143,9 @@ void stmmac_ptp_unregister(struct stmmac
|
||
|
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);
|
||
|
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||
|
@@ -52,6 +52,7 @@
|
||
|
#include "stmmac_ptp.h"
|
||
|
#include "stmmac.h"
|
||
|
#include <linux/reset.h>
|
||
|
+#include <linux/of_mdio.h>
|
||
|
|
||
|
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
|
||
|
|
||
|
@@ -816,18 +817,25 @@ 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_OR_NULL(phydev)) {
|
||
|
pr_err("%s: Could not attach to PHY\n", dev->name);
|
||
|
@@ -851,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;
|
||
|
}
|
||
|
@@ -978,13 +986,11 @@ static int stmmac_init_rx_buffers(struct
|
||
|
{
|
||
|
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,
|
||
|
@@ -2803,16 +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:
|
||
|
- * on success the new private structure is returned, otherwise the error
|
||
|
- * pointer.
|
||
|
+ * 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;
|
||
|
@@ -2820,7 +2825,7 @@ struct stmmac_priv *stmmac_dvr_probe(str
|
||
|
|
||
|
ndev = alloc_etherdev(sizeof(struct stmmac_priv));
|
||
|
if (!ndev)
|
||
|
- return ERR_PTR(-ENOMEM);
|
||
|
+ return -ENOMEM;
|
||
|
|
||
|
SET_NETDEV_DEV(ndev, device);
|
||
|
|
||
|
@@ -2831,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();
|
||
|
@@ -2947,7 +2961,7 @@ struct stmmac_priv *stmmac_dvr_probe(str
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- return priv;
|
||
|
+ return 0;
|
||
|
|
||
|
error_mdio_register:
|
||
|
unregister_netdev(ndev);
|
||
|
@@ -2960,7 +2974,7 @@ error_pclk_get:
|
||
|
error_clk_get:
|
||
|
free_netdev(ndev);
|
||
|
|
||
|
- return ERR_PTR(ret);
|
||
|
+ return ret;
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
|
||
|
|
||
|
--- 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
|
||
|
@@ -163,7 +163,7 @@ static int stmmac_pci_probe(struct pci_d
|
||
|
{
|
||
|
struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
|
||
|
struct plat_stmmacenet_data *plat;
|
||
|
- struct stmmac_priv *priv;
|
||
|
+ struct stmmac_resources res;
|
||
|
int i;
|
||
|
int ret;
|
||
|
|
||
|
@@ -214,19 +214,12 @@ static int stmmac_pci_probe(struct pci_d
|
||
|
|
||
|
pci_enable_msi(pdev);
|
||
|
|
||
|
- priv = stmmac_dvr_probe(&pdev->dev, plat, pcim_iomap_table(pdev)[i]);
|
||
|
- if (IS_ERR(priv)) {
|
||
|
- dev_err(&pdev->dev, "%s: main driver probe failed\n", __func__);
|
||
|
- return PTR_ERR(priv);
|
||
|
- }
|
||
|
- priv->dev->irq = pdev->irq;
|
||
|
- priv->wol_irq = pdev->irq;
|
||
|
-
|
||
|
- pci_set_drvdata(pdev, priv->dev);
|
||
|
-
|
||
|
- dev_dbg(&pdev->dev, "STMMAC PCI driver registration completed\n");
|
||
|
+ memset(&res, 0, sizeof(res));
|
||
|
+ res.addr = pcim_iomap_table(pdev)[i];
|
||
|
+ res.wol_irq = pdev->irq;
|
||
|
+ res.irq = pdev->irq;
|
||
|
|
||
|
- return 0;
|
||
|
+ return stmmac_dvr_probe(&pdev->dev, plat, &res);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||
|
@@ -28,29 +28,11 @@
|
||
|
#include <linux/of.h>
|
||
|
#include <linux/of_net.h>
|
||
|
#include <linux/of_device.h>
|
||
|
+#include <linux/of_mdio.h>
|
||
|
|
||
|
#include "stmmac.h"
|
||
|
#include "stmmac_platform.h"
|
||
|
|
||
|
-static const struct of_device_id stmmac_dt_ids[] = {
|
||
|
- /* SoC specific glue layers should come before generic bindings */
|
||
|
- { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data},
|
||
|
- { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data},
|
||
|
- { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
|
||
|
- { .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},
|
||
|
- { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
|
||
|
- { .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);
|
||
|
-
|
||
|
#ifdef CONFIG_OF
|
||
|
|
||
|
/**
|
||
|
@@ -122,37 +104,16 @@ static int dwmac1000_validate_ucast_entr
|
||
|
* 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.
|
||
|
*/
|
||
|
-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)
|
||
|
{
|
||
|
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);
|
||
|
@@ -168,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 =
|
||
|
@@ -194,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
|
||
|
@@ -232,8 +210,10 @@ 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 =
|
||
|
@@ -250,45 +230,34 @@ 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 - platform driver probe.
|
||
|
- * @pdev: platform device pointer
|
||
|
- * Description: platform_device probe function. It is to allocate
|
||
|
- * the necessary platform resources, invoke custom helper (if required) and
|
||
|
- * invoke the main probe function.
|
||
|
- */
|
||
|
-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;
|
||
|
- int irq, wol_irq, lpi_irq;
|
||
|
+
|
||
|
+ memset(stmmac_res, 0, sizeof(*stmmac_res));
|
||
|
|
||
|
/* Get IRQ information early to have an ability to ask for deferred
|
||
|
* probe if needed before we went too far with resource allocation.
|
||
|
*/
|
||
|
- irq = platform_get_irq_byname(pdev, "macirq");
|
||
|
- if (irq < 0) {
|
||
|
- if (irq != -EPROBE_DEFER) {
|
||
|
- dev_err(dev,
|
||
|
+ 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 irq;
|
||
|
+ return stmmac_res->irq;
|
||
|
}
|
||
|
|
||
|
/* On some platforms e.g. SPEAr the wake up irq differs from the mac irq
|
||
|
@@ -298,82 +267,23 @@ static int stmmac_pltfr_probe(struct pla
|
||
|
* In case the wake up interrupt is not passed from the platform
|
||
|
* so the driver will continue to use the mac irq (ndev->irq)
|
||
|
*/
|
||
|
- wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
|
||
|
- if (wol_irq < 0) {
|
||
|
- if (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;
|
||
|
- wol_irq = irq;
|
||
|
+ stmmac_res->wol_irq = stmmac_res->irq;
|
||
|
}
|
||
|
|
||
|
- lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
|
||
|
- if (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;
|
||
|
|
||
|
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;
|
||
|
+ stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res);
|
||
|
|
||
|
- /* 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);
|
||
|
- }
|
||
|
-
|
||
|
- /* Copy IRQ values to priv structure which is now avaialble */
|
||
|
- priv->dev->irq = irq;
|
||
|
- priv->wol_irq = wol_irq;
|
||
|
- priv->lpi_irq = lpi_irq;
|
||
|
-
|
||
|
- /* Get MAC address if available (DT) */
|
||
|
- if (mac)
|
||
|
- memcpy(priv->dev->dev_addr, mac, ETH_ALEN);
|
||
|
-
|
||
|
- platform_set_drvdata(pdev, priv->dev);
|
||
|
-
|
||
|
- pr_debug("STMMAC platform driver registration completed");
|
||
|
-
|
||
|
- return 0;
|
||
|
+ return PTR_ERR_OR_ZERO(stmmac_res->addr);
|
||
|
}
|
||
|
+EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
|
||
|
|
||
|
/**
|
||
|
* stmmac_pltfr_remove
|
||
|
@@ -381,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);
|
||
|
@@ -390,11 +300,9 @@ 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_SLEEP
|
||
|
/**
|
||
|
@@ -438,21 +346,10 @@ static int stmmac_pltfr_resume(struct de
|
||
|
}
|
||
|
#endif /* CONFIG_PM_SLEEP */
|
||
|
|
||
|
-static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
|
||
|
- stmmac_pltfr_suspend, stmmac_pltfr_resume);
|
||
|
-
|
||
|
-static struct platform_driver stmmac_pltfr_driver = {
|
||
|
- .probe = stmmac_pltfr_probe,
|
||
|
- .remove = stmmac_pltfr_remove,
|
||
|
- .driver = {
|
||
|
- .name = STMMAC_RESOURCE_NAME,
|
||
|
- .pm = &stmmac_pltfr_pm_ops,
|
||
|
- .of_match_table = of_match_ptr(stmmac_dt_ids),
|
||
|
- },
|
||
|
-};
|
||
|
-
|
||
|
-module_platform_driver(stmmac_pltfr_driver);
|
||
|
+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");
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
|
||
|
@@ -19,11 +19,15 @@
|
||
|
#ifndef __STMMAC_PLATFORM_H__
|
||
|
#define __STMMAC_PLATFORM_H__
|
||
|
|
||
|
-extern const struct stmmac_of_data meson6_dwmac_data;
|
||
|
-extern const struct stmmac_of_data sun7i_gmac_data;
|
||
|
-extern const struct stmmac_of_data stih4xx_dwmac_data;
|
||
|
-extern const struct stmmac_of_data stid127_dwmac_data;
|
||
|
-extern const struct stmmac_of_data socfpga_gmac_data;
|
||
|
-extern const struct stmmac_of_data rk3288_gmac_data;
|
||
|
+#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__ */
|
||
|
--- 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;
|
||
|
@@ -118,30 +119,8 @@ struct plat_stmmacenet_data {
|
||
|
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
|