c528f49
From patchwork Mon May  1 12:45:01 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,
c528f49
 01/20] net: stmmac: export stmmac_set_mac_addr/stmmac_get_mac_addr
c0853e1
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706455
c528f49
Message-Id: <20170501124520.3769-2-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:01 +0200
c0853e1
58a0e11
Thoses symbol will be needed for the dwmac-sun8i ethernet driver.
58a0e11
For letting it to be build as module, they need to be exported.
c0853e1
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
58a0e11
 drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 3 ++-
58a0e11
 1 file changed, 2 insertions(+), 1 deletion(-)
58a0e11
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
c528f49
index 38f9430..67af0bd 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
58a0e11
@@ -248,6 +248,7 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
58a0e11
 	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
58a0e11
 	writel(data, ioaddr + low);
58a0e11
 }
58a0e11
+EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
58a0e11
 
58a0e11
 /* Enable disable MAC RX/TX */
58a0e11
 void stmmac_set_mac(void __iomem *ioaddr, bool enable)
58a0e11
@@ -279,4 +280,4 @@ void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
58a0e11
 	addr[4] = hi_addr & 0xff;
58a0e11
 	addr[5] = (hi_addr >> 8) & 0xff;
58a0e11
 }
58a0e11
-
58a0e11
+EXPORT_SYMBOL_GPL(stmmac_get_mac_addr);
c528f49
c528f49
From patchwork Mon May  1 12:45:02 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,02/20] net: stmmac: add optional setup function
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706501
c528f49
Message-Id: <20170501124520.3769-3-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:02 +0200
c528f49
c528f49
Instead of adding more ifthen logic for adding a new mac_device_info
58a0e11
setup function, it is easier to add a function pointer to the function
58a0e11
needed.
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
58a0e11
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++-
c528f49
 include/linux/stmmac.h                            | 1 +
c528f49
 2 files changed, 4 insertions(+), 1 deletion(-)
c0853e1
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
c528f49
index cd8c601..b82ab64 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
c528f49
@@ -3947,7 +3947,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
58a0e11
 	struct mac_device_info *mac;
58a0e11
 
58a0e11
 	/* Identify the MAC HW device */
58a0e11
-	if (priv->plat->has_gmac) {
58a0e11
+	if (priv->plat->setup) {
58a0e11
+		mac = priv->plat->setup(priv);
58a0e11
+	} else if (priv->plat->has_gmac) {
58a0e11
 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
58a0e11
 		mac = dwmac1000_setup(priv->ioaddr,
58a0e11
 				      priv->plat->multicast_filter_bins,
58a0e11
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
c528f49
index 3921cb9..8bb550b 100644
58a0e11
--- a/include/linux/stmmac.h
58a0e11
+++ b/include/linux/stmmac.h
c528f49
@@ -177,6 +177,7 @@ struct plat_stmmacenet_data {
58a0e11
 	void (*fix_mac_speed)(void *priv, unsigned int speed);
58a0e11
 	int (*init)(struct platform_device *pdev, void *priv);
58a0e11
 	void (*exit)(struct platform_device *pdev, void *priv);
c528f49
+	struct mac_device_info *(*setup)(void *priv);
58a0e11
 	void *bsp_priv;
58a0e11
 	struct clk *stmmac_clk;
58a0e11
 	struct clk *pclk;
c528f49
c528f49
From patchwork Mon May  1 12:45:03 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,
c528f49
 03/20] dt-bindings: net: Add DT bindings documentation for Allwinner
58a0e11
 dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706457
c528f49
Message-Id: <20170501124520.3769-4-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:03 +0200
58a0e11
58a0e11
This patch adds documentation for Device-Tree bindings for the
58a0e11
Allwinner dwmac-sun8i driver.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Acked-by: Rob Herring <robh@kernel.org>
58a0e11
---
58a0e11
 .../devicetree/bindings/net/dwmac-sun8i.txt        | 77 ++++++++++++++++++++++
58a0e11
 1 file changed, 77 insertions(+)
58a0e11
 create mode 100644 Documentation/devicetree/bindings/net/dwmac-sun8i.txt
58a0e11
58a0e11
diff --git a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
58a0e11
new file mode 100644
c528f49
index 0000000..05cd067
58a0e11
--- /dev/null
58a0e11
+++ b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
58a0e11
@@ -0,0 +1,77 @@
58a0e11
+* Allwinner sun8i GMAC ethernet controller
58a0e11
+
58a0e11
+This device is a platform glue layer for stmmac.
58a0e11
+Please see stmmac.txt for the other unchanged properties.
58a0e11
+
58a0e11
+Required properties:
58a0e11
+- compatible: should be one of the following string:
58a0e11
+		"allwinner,sun8i-a83t-emac"
58a0e11
+		"allwinner,sun8i-h3-emac"
58a0e11
+		"allwinner,sun50i-a64-emac"
58a0e11
+- reg: address and length of the register for the device.
58a0e11
+- interrupts: interrupt for the device
58a0e11
+- interrupt-names: should be "macirq"
58a0e11
+- clocks: A phandle to the reference clock for this device
58a0e11
+- clock-names: should be "stmmaceth"
58a0e11
+- resets: A phandle to the reset control for this device
58a0e11
+- reset-names: should be "stmmaceth"
58a0e11
+- phy-mode: See ethernet.txt
58a0e11
+- phy-handle: See ethernet.txt
58a0e11
+- #address-cells: shall be 1
58a0e11
+- #size-cells: shall be 0
58a0e11
+- syscon: A phandle to the syscon of the SoC with one of the following
58a0e11
+ compatible string:
58a0e11
+  - allwinner,sun8i-h3-system-controller
c528f49
+  - allwinner,sun50i-a64-system-controller
58a0e11
+  - allwinner,sun8i-a83t-system-controller
58a0e11
+
58a0e11
+Optional properties:
c528f49
+- allwinner,tx-delay-ps: TX clock delay chain value in ps. Range value is 0-700. Default is 0)
c528f49
+- allwinner,rx-delay-ps: RX clock delay chain value in ps. Range value is 0-3100. Default is 0)
c528f49
+Both delay properties need to be a multiple of 100.
58a0e11
+
58a0e11
+Optional properties for "allwinner,sun8i-h3-emac":
58a0e11
+- allwinner,leds-active-low: EPHY LEDs are active low
58a0e11
+
58a0e11
+Required child node of emac:
58a0e11
+- mdio bus node: should be named mdio
58a0e11
+
58a0e11
+Required properties of the mdio node:
58a0e11
+- #address-cells: shall be 1
58a0e11
+- #size-cells: shall be 0
58a0e11
+
58a0e11
+The device node referenced by "phy" or "phy-handle" should be a child node
58a0e11
+of the mdio node. See phy.txt for the generic PHY bindings.
58a0e11
+
58a0e11
+Required properties of the phy node with "allwinner,sun8i-h3-emac":
58a0e11
+- clocks: a phandle to the reference clock for the EPHY
58a0e11
+- resets: a phandle to the reset control for the EPHY
58a0e11
+
58a0e11
+Example:
58a0e11
+
58a0e11
+emac: ethernet@1c0b000 {
58a0e11
+	compatible = "allwinner,sun8i-h3-emac";
58a0e11
+	syscon = <&syscon>;
58a0e11
+	reg = <0x01c0b000 0x104>;
58a0e11
+	interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
58a0e11
+	interrupt-names = "macirq";
58a0e11
+	resets = <&ccu RST_BUS_EMAC>;
58a0e11
+	reset-names = "stmmaceth";
58a0e11
+	clocks = <&ccu CLK_BUS_EMAC>;
58a0e11
+	clock-names = "stmmaceth";
58a0e11
+	#address-cells = <1>;
58a0e11
+	#size-cells = <0>;
58a0e11
+
58a0e11
+	phy = <&int_mii_phy>;
58a0e11
+	phy-mode = "mii";
58a0e11
+	allwinner,leds-active-low;
58a0e11
+	mdio: mdio {
58a0e11
+		#address-cells = <1>;
58a0e11
+		#size-cells = <0>;
58a0e11
+		int_mii_phy: ethernet-phy@1 {
58a0e11
+			reg = <1>;
58a0e11
+			clocks = <&ccu CLK_BUS_EPHY>;
58a0e11
+			resets = <&ccu RST_BUS_EPHY>;
58a0e11
+		};
58a0e11
+	};
58a0e11
+};
c528f49
c528f49
From patchwork Mon May  1 12:45:04 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5, 04/20] dt-bindings: syscon: Add DT bindings documentation for
c528f49
 Allwinner syscon
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706469
c528f49
Message-Id: <20170501124520.3769-5-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:04 +0200
c528f49
c528f49
This patch adds documentation for Device-Tree bindings for the
c528f49
syscon present in allwinner devices.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
58a0e11
 .../devicetree/bindings/misc/allwinner,syscon.txt     | 19 +++++++++++++++++++
58a0e11
 1 file changed, 19 insertions(+)
58a0e11
 create mode 100644 Documentation/devicetree/bindings/misc/allwinner,syscon.txt
58a0e11
58a0e11
diff --git a/Documentation/devicetree/bindings/misc/allwinner,syscon.txt b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt
58a0e11
new file mode 100644
c528f49
index 0000000..cb57691
58a0e11
--- /dev/null
58a0e11
+++ b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt
58a0e11
@@ -0,0 +1,19 @@
58a0e11
+* Allwinner sun8i system controller
58a0e11
+
58a0e11
+This file describes the bindings for the system controller present in
58a0e11
+Allwinner SoC H3, A83T and A64.
58a0e11
+The principal function of this syscon is to control EMAC PHY choice and
58a0e11
+config.
58a0e11
+
58a0e11
+Required properties for the system controller:
58a0e11
+- reg: address and length of the register for the device.
58a0e11
+- compatible: should be "syscon" and one of the following string:
58a0e11
+		"allwinner,sun8i-h3-system-controller"
c528f49
+		"allwinner,sun50i-a64-system-controller"
58a0e11
+		"allwinner,sun8i-a83t-system-controller"
58a0e11
+
58a0e11
+Example:
c528f49
+syscon: syscon@1c00000 {
c528f49
+	compatible = "allwinner,sun8i-h3-system-controller", "syscon";
58a0e11
+	reg = <0x01c00000 0x1000>;
58a0e11
+};
c528f49
c528f49
From patchwork Mon May  1 12:45:05 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,05/20] net: stmmac: Add dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706473
c528f49
Message-Id: <20170501124520.3769-6-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:05 +0200
58a0e11
58a0e11
The dwmac-sun8i is a heavy hacked version of stmmac hardware by
58a0e11
allwinner.
58a0e11
In fact the only common part is the descriptor management and the first
58a0e11
register function.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
58a0e11
 drivers/net/ethernet/stmicro/stmmac/Kconfig        |  11 +
58a0e11
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   1 +
c528f49
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c  | 973 +++++++++++++++++++++
c528f49
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  29 +
58a0e11
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   9 +-
58a0e11
 include/linux/stmmac.h                             |   1 +
c528f49
 6 files changed, 1022 insertions(+), 2 deletions(-)
58a0e11
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
58a0e11
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
58a0e11
index cfbe363..85c0e41 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
58a0e11
@@ -145,6 +145,17 @@ config DWMAC_SUNXI
58a0e11
 	  This selects Allwinner SoC glue layer support for the
58a0e11
 	  stmmac device driver. This driver is used for A20/A31
58a0e11
 	  GMAC ethernet controller.
58a0e11
+
58a0e11
+config DWMAC_SUN8I
58a0e11
+	tristate "Allwinner sun8i GMAC support"
58a0e11
+	default ARCH_SUNXI
58a0e11
+	depends on OF && (ARCH_SUNXI || COMPILE_TEST)
58a0e11
+	---help---
58a0e11
+	  Support for Allwinner H3 A83T A64 EMAC ethernet controllers.
58a0e11
+
58a0e11
+	  This selects Allwinner SoC glue layer support for the
58a0e11
+	  stmmac device driver. This driver is used for H3/A83T/A64
58a0e11
+	  EMAC ethernet controller.
58a0e11
 endif
c0853e1
 
58a0e11
 config STMMAC_PCI
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
58a0e11
index 700c603..fd4937a 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
58a0e11
@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
58a0e11
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
58a0e11
 obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
58a0e11
 obj-$(CONFIG_DWMAC_SUNXI)	+= dwmac-sunxi.o
58a0e11
+obj-$(CONFIG_DWMAC_SUN8I)	+= dwmac-sun8i.o
58a0e11
 obj-$(CONFIG_DWMAC_DWC_QOS_ETH)	+= dwmac-dwc-qos-eth.o
58a0e11
 obj-$(CONFIG_DWMAC_GENERIC)	+= dwmac-generic.o
58a0e11
 stmmac-platform-objs:= stmmac_platform.o
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
c0853e1
new file mode 100644
c528f49
index 0000000..66eb980
c0853e1
--- /dev/null
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
c528f49
@@ -0,0 +1,973 @@
c0853e1
+/*
58a0e11
+ * dwmac-sun8i.c - Allwinner sun8i DWMAC specific glue layer
c0853e1
+ *
58a0e11
+ * Copyright (C) 2017 Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
+ *
58a0e11
+ * This program is free software; you can redistribute it and/or modify
58a0e11
+ * it under the terms of the GNU General Public License as published by
58a0e11
+ * the Free Software Foundation; either version 2 of the License, or
58a0e11
+ * (at your option) any later version.
c0853e1
+ *
58a0e11
+ * This program is distributed in the hope that it will be useful,
58a0e11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58a0e11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
58a0e11
+ * GNU General Public License for more details.
c0853e1
+ */
58a0e11
+
c0853e1
+#include <linux/clk.h>
58a0e11
+#include <linux/io.h>
c0853e1
+#include <linux/iopoll.h>
58a0e11
+#include <linux/mfd/syscon.h>
c0853e1
+#include <linux/module.h>
c0853e1
+#include <linux/of_device.h>
c0853e1
+#include <linux/of_mdio.h>
c0853e1
+#include <linux/of_net.h>
c0853e1
+#include <linux/phy.h>
c0853e1
+#include <linux/platform_device.h>
58a0e11
+#include <linux/regulator/consumer.h>
c0853e1
+#include <linux/regmap.h>
58a0e11
+#include <linux/stmmac.h>
c0853e1
+
58a0e11
+#include "stmmac.h"
58a0e11
+#include "stmmac_platform.h"
c0853e1
+
58a0e11
+/* General notes on dwmac-sun8i:
58a0e11
+ * Locking: no locking is necessary in this file because all necessary locking
58a0e11
+ *		is done in the "stmmac files"
58a0e11
+ */
c0853e1
+
58a0e11
+/* struct emac_variant - Descrive dwmac-sun8i hardware variant
58a0e11
+ * @default_syscon_value:	The default value of the EMAC register in syscon
58a0e11
+ *				This value is used for disabling properly EMAC
58a0e11
+ *				and used as a good starting value in case of the
58a0e11
+ *				boot process(uboot) leave some stuff.
58a0e11
+ * @internal_phy:		Does the MAC embed an internal PHY
58a0e11
+ * @support_mii:		Does the MAC handle MII
58a0e11
+ * @support_rmii:		Does the MAC handle RMII
58a0e11
+ * @support_rgmii:		Does the MAC handle RGMII
c0853e1
+ */
c0853e1
+struct emac_variant {
c0853e1
+	u32 default_syscon_value;
c0853e1
+	int internal_phy;
c0853e1
+	bool support_mii;
c0853e1
+	bool support_rmii;
c0853e1
+	bool support_rgmii;
c0853e1
+};
c0853e1
+
58a0e11
+/* struct sunxi_priv_data - hold all sunxi private data
58a0e11
+ * @tx_clk:	reference to MAC TX clock
58a0e11
+ * @ephy_clk:	reference to the optional EPHY clock for the internal PHY
58a0e11
+ * @regulator:	reference to the optional regulator
58a0e11
+ * @rst_ephy:	reference to the optional EPHY reset for the internal PHY
58a0e11
+ * @variant:	reference to the current board variant
58a0e11
+ * @regmap:	regmap for using the syscon
58a0e11
+ * @use_internal_phy: Does the current PHY choice imply using the internal PHY
58a0e11
+ */
58a0e11
+struct sunxi_priv_data {
58a0e11
+	struct clk *tx_clk;
58a0e11
+	struct clk *ephy_clk;
58a0e11
+	struct regulator *regulator;
58a0e11
+	struct reset_control *rst_ephy;
58a0e11
+	const struct emac_variant *variant;
58a0e11
+	struct regmap *regmap;
58a0e11
+	bool use_internal_phy;
58a0e11
+};
58a0e11
+
c0853e1
+static const struct emac_variant emac_variant_h3 = {
c0853e1
+	.default_syscon_value = 0x58000,
c0853e1
+	.internal_phy = PHY_INTERFACE_MODE_MII,
c0853e1
+	.support_mii = true,
c0853e1
+	.support_rmii = true,
c0853e1
+	.support_rgmii = true
c0853e1
+};
c0853e1
+
c0853e1
+static const struct emac_variant emac_variant_a83t = {
c0853e1
+	.default_syscon_value = 0,
c0853e1
+	.internal_phy = 0,
c0853e1
+	.support_mii = true,
c0853e1
+	.support_rgmii = true
c0853e1
+};
c0853e1
+
c0853e1
+static const struct emac_variant emac_variant_a64 = {
c0853e1
+	.default_syscon_value = 0,
c0853e1
+	.internal_phy = 0,
c0853e1
+	.support_mii = true,
c0853e1
+	.support_rmii = true,
c0853e1
+	.support_rgmii = true
c0853e1
+};
c0853e1
+
58a0e11
+#define EMAC_BASIC_CTL0 0x00
58a0e11
+#define EMAC_BASIC_CTL1 0x04
58a0e11
+#define EMAC_INT_STA    0x08
58a0e11
+#define EMAC_INT_EN     0x0C
58a0e11
+#define EMAC_TX_CTL0    0x10
58a0e11
+#define EMAC_TX_CTL1    0x14
58a0e11
+#define EMAC_TX_FLOW_CTL        0x1C
58a0e11
+#define EMAC_TX_DESC_LIST 0x20
58a0e11
+#define EMAC_RX_CTL0    0x24
58a0e11
+#define EMAC_RX_CTL1    0x28
58a0e11
+#define EMAC_RX_DESC_LIST 0x34
58a0e11
+#define EMAC_RX_FRM_FLT 0x38
58a0e11
+#define EMAC_MDIO_CMD   0x48
58a0e11
+#define EMAC_MDIO_DATA  0x4C
58a0e11
+#define EMAC_MACADDR_HI(reg) (0x50 + (reg) * 8)
58a0e11
+#define EMAC_MACADDR_LO(reg) (0x54 + (reg) * 8)
58a0e11
+#define EMAC_TX_DMA_STA 0xB0
58a0e11
+#define EMAC_TX_CUR_DESC        0xB4
58a0e11
+#define EMAC_TX_CUR_BUF 0xB8
58a0e11
+#define EMAC_RX_DMA_STA 0xC0
58a0e11
+#define EMAC_RX_CUR_DESC        0xC4
58a0e11
+#define EMAC_RX_CUR_BUF 0xC8
58a0e11
+
58a0e11
+/* Use in EMAC_BASIC_CTL1 */
58a0e11
+#define EMAC_BURSTLEN_SHIFT		24
58a0e11
+
58a0e11
+/* Used in EMAC_RX_FRM_FLT */
58a0e11
+#define EMAC_FRM_FLT_RXALL              BIT(0)
58a0e11
+#define EMAC_FRM_FLT_CTL                BIT(13)
58a0e11
+#define EMAC_FRM_FLT_MULTICAST          BIT(16)
c0853e1
+
58a0e11
+/* Used in RX_CTL1*/
58a0e11
+#define EMAC_RX_MD              BIT(1)
58a0e11
+#define EMAC_RX_TH_MASK		GENMASK(4, 5)
58a0e11
+#define EMAC_RX_TH_32		0
58a0e11
+#define EMAC_RX_TH_64		(0x1 << 4)
58a0e11
+#define EMAC_RX_TH_96		(0x2 << 4)
58a0e11
+#define EMAC_RX_TH_128		(0x3 << 4)
58a0e11
+#define EMAC_RX_DMA_EN  BIT(30)
58a0e11
+#define EMAC_RX_DMA_START       BIT(31)
c0853e1
+
58a0e11
+/* Used in TX_CTL1*/
58a0e11
+#define EMAC_TX_MD              BIT(1)
58a0e11
+#define EMAC_TX_NEXT_FRM        BIT(2)
58a0e11
+#define EMAC_TX_TH_MASK		GENMASK(8, 10)
58a0e11
+#define EMAC_TX_TH_64		0
58a0e11
+#define EMAC_TX_TH_128		(0x1 << 8)
58a0e11
+#define EMAC_TX_TH_192		(0x2 << 8)
58a0e11
+#define EMAC_TX_TH_256		(0x3 << 8)
58a0e11
+#define EMAC_TX_DMA_EN  BIT(30)
58a0e11
+#define EMAC_TX_DMA_START       BIT(31)
c0853e1
+
58a0e11
+/* Used in RX_CTL0 */
58a0e11
+#define EMAC_RX_RECEIVER_EN             BIT(31)
58a0e11
+#define EMAC_RX_DO_CRC BIT(27)
58a0e11
+#define EMAC_RX_FLOW_CTL_EN             BIT(16)
c0853e1
+
58a0e11
+/* Used in TX_CTL0 */
58a0e11
+#define EMAC_TX_TRANSMITTER_EN  BIT(31)
58a0e11
+
58a0e11
+/* Used in EMAC_TX_FLOW_CTL */
58a0e11
+#define EMAC_TX_FLOW_CTL_EN             BIT(0)
58a0e11
+
58a0e11
+/* Used in EMAC_INT_STA */
58a0e11
+#define EMAC_TX_INT             BIT(0)
58a0e11
+#define EMAC_TX_DMA_STOP_INT    BIT(1)
58a0e11
+#define EMAC_TX_BUF_UA_INT      BIT(2)
58a0e11
+#define EMAC_TX_TIMEOUT_INT     BIT(3)
58a0e11
+#define EMAC_TX_UNDERFLOW_INT   BIT(4)
58a0e11
+#define EMAC_TX_EARLY_INT       BIT(5)
58a0e11
+#define EMAC_RX_INT             BIT(8)
58a0e11
+#define EMAC_RX_BUF_UA_INT      BIT(9)
58a0e11
+#define EMAC_RX_DMA_STOP_INT    BIT(10)
58a0e11
+#define EMAC_RX_TIMEOUT_INT     BIT(11)
58a0e11
+#define EMAC_RX_OVERFLOW_INT    BIT(12)
58a0e11
+#define EMAC_RX_EARLY_INT       BIT(13)
58a0e11
+#define EMAC_RGMII_STA_INT      BIT(16)
58a0e11
+
58a0e11
+#define MAC_ADDR_TYPE_DST BIT(31)
c0853e1
+
58a0e11
+/* H3 specific bits for EPHY */
58a0e11
+#define H3_EPHY_ADDR_SHIFT	20
58a0e11
+#define H3_EPHY_LED_POL		BIT(17) /* 1: active low, 0: active high */
58a0e11
+#define H3_EPHY_SHUTDOWN	BIT(16) /* 1: shutdown, 0: power up */
58a0e11
+#define H3_EPHY_SELECT		BIT(15) /* 1: internal PHY, 0: external PHY */
c0853e1
+
58a0e11
+/* H3/A64 specific bits */
58a0e11
+#define SYSCON_RMII_EN		BIT(13) /* 1: enable RMII (overrides EPIT) */
c0853e1
+
58a0e11
+/* Generic system control EMAC_CLK bits */
58a0e11
+#define SYSCON_ETXDC_MASK		GENMASK(2, 0)
58a0e11
+#define SYSCON_ETXDC_SHIFT		10
58a0e11
+#define SYSCON_ERXDC_MASK		GENMASK(4, 0)
58a0e11
+#define SYSCON_ERXDC_SHIFT		5
58a0e11
+/* EMAC PHY Interface Type */
58a0e11
+#define SYSCON_EPIT			BIT(2) /* 1: RGMII, 0: MII */
58a0e11
+#define SYSCON_ETCS_MASK		GENMASK(1, 0)
58a0e11
+#define SYSCON_ETCS_MII		0x0
58a0e11
+#define SYSCON_ETCS_EXT_GMII	0x1
58a0e11
+#define SYSCON_ETCS_INT_GMII	0x2
58a0e11
+#define SYSCON_EMAC_REG		0x30
c0853e1
+
58a0e11
+/* sun8i_dwmac_dma_reset() - reset the EMAC
58a0e11
+ * Called from stmmac via stmmac_dma_ops->reset
58a0e11
+ */
58a0e11
+static int sun8i_dwmac_dma_reset(void __iomem *ioaddr)
c0853e1
+{
58a0e11
+	writel(0, ioaddr + EMAC_RX_CTL1);
58a0e11
+	writel(0, ioaddr + EMAC_TX_CTL1);
58a0e11
+	writel(0, ioaddr + EMAC_RX_FRM_FLT);
58a0e11
+	writel(0, ioaddr + EMAC_RX_DESC_LIST);
58a0e11
+	writel(0, ioaddr + EMAC_TX_DESC_LIST);
58a0e11
+	writel(0, ioaddr + EMAC_INT_EN);
58a0e11
+	writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
58a0e11
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+/* sun8i_dwmac_dma_init() - initialize the EMAC
58a0e11
+ * Called from stmmac via stmmac_dma_ops->init
c0853e1
+ */
58a0e11
+static void sun8i_dwmac_dma_init(void __iomem *ioaddr,
58a0e11
+				 struct stmmac_dma_cfg *dma_cfg,
58a0e11
+				 u32 dma_tx, u32 dma_rx, int atds)
c0853e1
+{
58a0e11
+	/* Write TX and RX descriptors address */
58a0e11
+	writel(dma_rx, ioaddr + EMAC_RX_DESC_LIST);
58a0e11
+	writel(dma_tx, ioaddr + EMAC_TX_DESC_LIST);
c0853e1
+
58a0e11
+	writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
58a0e11
+	writel(0x1FFFFFF, ioaddr + EMAC_INT_STA);
c0853e1
+}
c0853e1
+
58a0e11
+/* sun8i_dwmac_dump_regs() - Dump EMAC address space
58a0e11
+ * Called from stmmac_dma_ops->dump_regs
58a0e11
+ * Used for ethtool
58a0e11
+ */
58a0e11
+static void sun8i_dwmac_dump_regs(void __iomem *ioaddr, u32 *reg_space)
c0853e1
+{
58a0e11
+	int i;
c0853e1
+
58a0e11
+	for (i = 0; i < 0xC8; i += 4) {
58a0e11
+		if (i == 0x32 || i == 0x3C)
58a0e11
+			continue;
58a0e11
+		reg_space[i / 4] = readl(ioaddr + i);
c0853e1
+	}
c0853e1
+}
c0853e1
+
58a0e11
+/* sun8i_dwmac_dump_mac_regs() - Dump EMAC address space
58a0e11
+ * Called from stmmac_ops->dump_regs
58a0e11
+ * Used for ethtool
58a0e11
+ */
58a0e11
+static void sun8i_dwmac_dump_mac_regs(struct mac_device_info *hw,
58a0e11
+				      u32 *reg_space)
c0853e1
+{
58a0e11
+	int i;
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
c0853e1
+
58a0e11
+	for (i = 0; i < 0xC8; i += 4) {
58a0e11
+		if (i == 0x32 || i == 0x3C)
58a0e11
+			continue;
58a0e11
+		reg_space[i / 4] = readl(ioaddr + i);
58a0e11
+	}
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan)
c0853e1
+{
58a0e11
+	writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
58a0e11
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan)
58a0e11
+{
58a0e11
+	writel(0, ioaddr + EMAC_INT_EN);
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan)
c0853e1
+{
c0853e1
+	u32 v;
c0853e1
+
c528f49
+	v = readl(ioaddr + EMAC_TX_CTL1);
c528f49
+	v |= EMAC_TX_DMA_START;
c528f49
+	v |= EMAC_TX_DMA_EN;
c528f49
+	writel(v, ioaddr + EMAC_TX_CTL1);
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr)
c0853e1
+{
c0853e1
+	u32 v;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_TX_CTL1);
c0853e1
+	v |= EMAC_TX_DMA_START;
c0853e1
+	v |= EMAC_TX_DMA_EN;
c528f49
+	writel(v, ioaddr + EMAC_TX_CTL1);
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan)
c0853e1
+{
c0853e1
+	u32 v;
c0853e1
+
c528f49
+	v = readl(ioaddr + EMAC_TX_CTL1);
c528f49
+	v &= ~EMAC_TX_DMA_EN;
c528f49
+	writel(v, ioaddr + EMAC_TX_CTL1);
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan)
c0853e1
+{
c0853e1
+	u32 v;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_RX_CTL1);
58a0e11
+	v |= EMAC_RX_DMA_START;
58a0e11
+	v |= EMAC_RX_DMA_EN;
58a0e11
+	writel(v, ioaddr + EMAC_RX_CTL1);
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan)
c0853e1
+{
58a0e11
+	u32 v;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_RX_CTL1);
58a0e11
+	v &= ~EMAC_RX_DMA_EN;
58a0e11
+	writel(v, ioaddr + EMAC_RX_CTL1);
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_dma_interrupt(void __iomem *ioaddr,
c528f49
+				     struct stmmac_extra_stats *x, u32 chan)
c0853e1
+{
58a0e11
+	u32 v;
58a0e11
+	int ret = 0;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_INT_STA);
c0853e1
+
58a0e11
+	if (v & EMAC_TX_INT) {
58a0e11
+		ret |= handle_tx;
58a0e11
+		x->tx_normal_irq_n++;
c0853e1
+	}
c0853e1
+
58a0e11
+	if (v & EMAC_TX_DMA_STOP_INT)
58a0e11
+		x->tx_process_stopped_irq++;
c0853e1
+
58a0e11
+	if (v & EMAC_TX_BUF_UA_INT)
58a0e11
+		x->tx_process_stopped_irq++;
c0853e1
+
58a0e11
+	if (v & EMAC_TX_TIMEOUT_INT)
58a0e11
+		ret |= tx_hard_error;
c0853e1
+
58a0e11
+	if (v & EMAC_TX_UNDERFLOW_INT) {
58a0e11
+		ret |= tx_hard_error;
58a0e11
+		x->tx_undeflow_irq++;
c0853e1
+	}
c0853e1
+
58a0e11
+	if (v & EMAC_TX_EARLY_INT)
58a0e11
+		x->tx_early_irq++;
c0853e1
+
58a0e11
+	if (v & EMAC_RX_INT) {
58a0e11
+		ret |= handle_rx;
58a0e11
+		x->rx_normal_irq_n++;
c0853e1
+	}
c0853e1
+
58a0e11
+	if (v & EMAC_RX_BUF_UA_INT)
58a0e11
+		x->rx_buf_unav_irq++;
c0853e1
+
58a0e11
+	if (v & EMAC_RX_DMA_STOP_INT)
58a0e11
+		x->rx_process_stopped_irq++;
c0853e1
+
58a0e11
+	if (v & EMAC_RX_TIMEOUT_INT)
58a0e11
+		ret |= tx_hard_error;
c0853e1
+
58a0e11
+	if (v & EMAC_RX_OVERFLOW_INT) {
58a0e11
+		ret |= tx_hard_error;
58a0e11
+		x->rx_overflow_irq++;
c0853e1
+	}
c0853e1
+
58a0e11
+	if (v & EMAC_RX_EARLY_INT)
58a0e11
+		x->rx_early_irq++;
58a0e11
+
58a0e11
+	if (v & EMAC_RGMII_STA_INT)
58a0e11
+		x->irq_rgmii_n++;
c0853e1
+
58a0e11
+	writel(v, ioaddr + EMAC_INT_STA);
c0853e1
+
58a0e11
+	return ret;
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_dma_operation_mode(void __iomem *ioaddr, int txmode,
58a0e11
+					   int rxmode, int rxfifosz)
c0853e1
+{
58a0e11
+	u32 v;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_TX_CTL1);
58a0e11
+	if (txmode == SF_DMA_MODE) {
58a0e11
+		v |= EMAC_TX_MD;
58a0e11
+		/* Undocumented bit (called TX_NEXT_FRM in BSP), the original
58a0e11
+		 * comment is
58a0e11
+		 * "Operating on second frame increase the performance
58a0e11
+		 * especially when transmit store-and-forward is used."
58a0e11
+		 */
58a0e11
+		v |= EMAC_TX_NEXT_FRM;
58a0e11
+	} else {
58a0e11
+		v &= ~EMAC_TX_MD;
58a0e11
+		v &= ~EMAC_TX_TH_MASK;
58a0e11
+		if (txmode < 64)
58a0e11
+			v |= EMAC_TX_TH_64;
58a0e11
+		else if (txmode < 128)
58a0e11
+			v |= EMAC_TX_TH_128;
58a0e11
+		else if (txmode < 192)
58a0e11
+			v |= EMAC_TX_TH_192;
58a0e11
+		else if (txmode < 256)
58a0e11
+			v |= EMAC_TX_TH_256;
58a0e11
+	}
58a0e11
+	writel(v, ioaddr + EMAC_TX_CTL1);
58a0e11
+
58a0e11
+	v = readl(ioaddr + EMAC_RX_CTL1);
58a0e11
+	if (rxmode == SF_DMA_MODE) {
58a0e11
+		v |= EMAC_RX_MD;
58a0e11
+	} else {
58a0e11
+		v &= ~EMAC_RX_MD;
58a0e11
+		v &= ~EMAC_RX_TH_MASK;
58a0e11
+		if (rxmode < 32)
58a0e11
+			v |= EMAC_RX_TH_32;
58a0e11
+		else if (rxmode < 64)
58a0e11
+			v |= EMAC_RX_TH_64;
58a0e11
+		else if (rxmode < 96)
58a0e11
+			v |= EMAC_RX_TH_96;
58a0e11
+		else if (rxmode < 128)
58a0e11
+			v |= EMAC_RX_TH_128;
58a0e11
+	}
58a0e11
+	writel(v, ioaddr + EMAC_RX_CTL1);
58a0e11
+}
c0853e1
+
58a0e11
+static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = {
58a0e11
+	.reset = sun8i_dwmac_dma_reset,
58a0e11
+	.init = sun8i_dwmac_dma_init,
58a0e11
+	.dump_regs = sun8i_dwmac_dump_regs,
58a0e11
+	.dma_mode = sun8i_dwmac_dma_operation_mode,
58a0e11
+	.enable_dma_transmission = sun8i_dwmac_enable_dma_transmission,
58a0e11
+	.enable_dma_irq = sun8i_dwmac_enable_dma_irq,
58a0e11
+	.disable_dma_irq = sun8i_dwmac_disable_dma_irq,
58a0e11
+	.start_tx = sun8i_dwmac_dma_start_tx,
58a0e11
+	.stop_tx = sun8i_dwmac_dma_stop_tx,
58a0e11
+	.start_rx = sun8i_dwmac_dma_start_rx,
58a0e11
+	.stop_rx = sun8i_dwmac_dma_stop_rx,
58a0e11
+	.dma_interrupt = sun8i_dwmac_dma_interrupt,
58a0e11
+};
c0853e1
+
58a0e11
+static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
58a0e11
+{
58a0e11
+	struct sunxi_priv_data *gmac = priv;
58a0e11
+	int ret;
c0853e1
+
58a0e11
+	if (gmac->regulator) {
58a0e11
+		ret = regulator_enable(gmac->regulator);
58a0e11
+		if (ret) {
58a0e11
+			dev_err(&pdev->dev, "Fail to enable regulator\n");
58a0e11
+			return ret;
c0853e1
+		}
58a0e11
+	}
c0853e1
+
58a0e11
+	ret = clk_prepare_enable(gmac->tx_clk);
58a0e11
+	if (ret) {
58a0e11
+		if (gmac->regulator)
58a0e11
+			regulator_disable(gmac->regulator);
58a0e11
+		dev_err(&pdev->dev, "Could not enable AHB clock\n");
58a0e11
+		return ret;
58a0e11
+	}
c0853e1
+
58a0e11
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu)
c0853e1
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
58a0e11
+	u32 v;
58a0e11
+
58a0e11
+	v = (8 << EMAC_BURSTLEN_SHIFT); /* burst len */
58a0e11
+	writel(v, ioaddr + EMAC_BASIC_CTL1);
c0853e1
+}
c0853e1
+
c528f49
+static void sun8i_dwmac_set_mac(void __iomem *ioaddr, bool enable)
c528f49
+{
c528f49
+	u32 t, r;
c528f49
+
c528f49
+	t = readl(ioaddr + EMAC_TX_CTL0);
c528f49
+	r = readl(ioaddr + EMAC_RX_CTL0);
c528f49
+	if (enable) {
c528f49
+		t |= EMAC_TX_TRANSMITTER_EN;
c528f49
+		r |= EMAC_RX_RECEIVER_EN;
c528f49
+	} else {
c528f49
+		t &= ~EMAC_TX_TRANSMITTER_EN;
c528f49
+		r &= ~EMAC_RX_RECEIVER_EN;
c528f49
+	}
c528f49
+	writel(t, ioaddr + EMAC_TX_CTL0);
c528f49
+	writel(r, ioaddr + EMAC_RX_CTL0);
c528f49
+}
c528f49
+
c528f49
+/* Set MAC address at slot reg_n
c528f49
+ * All slot > 0 need to be enabled with MAC_ADDR_TYPE_DST
c528f49
+ * If addr is NULL, clear the slot
c528f49
+ */
58a0e11
+static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw,
58a0e11
+				      unsigned char *addr,
58a0e11
+				      unsigned int reg_n)
c0853e1
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
58a0e11
+	u32 v;
c0853e1
+
c528f49
+	if (!addr) {
c528f49
+		writel(0, ioaddr + EMAC_MACADDR_HI(reg_n));
c528f49
+		return;
c528f49
+	}
c528f49
+
58a0e11
+	stmmac_set_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n),
58a0e11
+			    EMAC_MACADDR_LO(reg_n));
58a0e11
+	if (reg_n > 0) {
58a0e11
+		v = readl(ioaddr + EMAC_MACADDR_HI(reg_n));
58a0e11
+		v |= MAC_ADDR_TYPE_DST;
58a0e11
+		writel(v, ioaddr + EMAC_MACADDR_HI(reg_n));
c0853e1
+	}
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_get_umac_addr(struct mac_device_info *hw,
58a0e11
+				      unsigned char *addr,
58a0e11
+				      unsigned int reg_n)
c0853e1
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
c0853e1
+
58a0e11
+	stmmac_get_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n),
58a0e11
+			    EMAC_MACADDR_LO(reg_n));
58a0e11
+}
c0853e1
+
58a0e11
+/* caution this function must return non 0 to work */
58a0e11
+static int sun8i_dwmac_rx_ipc_enable(struct mac_device_info *hw)
58a0e11
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
58a0e11
+	u32 v;
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_RX_CTL0);
58a0e11
+	v |= EMAC_RX_DO_CRC;
58a0e11
+	writel(v, ioaddr + EMAC_RX_CTL0);
c0853e1
+
58a0e11
+	return 1;
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_set_filter(struct mac_device_info *hw,
58a0e11
+				   struct net_device *dev)
c0853e1
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
58a0e11
+	u32 v;
c528f49
+	int i = 1;
58a0e11
+	struct netdev_hw_addr *ha;
c528f49
+	int macaddrs = netdev_uc_count(dev) + netdev_mc_count(dev) + 1;
c0853e1
+
c528f49
+	v = EMAC_FRM_FLT_CTL;
c0853e1
+
58a0e11
+	if (dev->flags & IFF_PROMISC) {
58a0e11
+		v = EMAC_FRM_FLT_RXALL;
58a0e11
+	} else if (dev->flags & IFF_ALLMULTI) {
c528f49
+		v |= EMAC_FRM_FLT_MULTICAST;
c528f49
+	} else if (macaddrs <= hw->unicast_filter_entries) {
c528f49
+		if (!netdev_mc_empty(dev)) {
c528f49
+			netdev_for_each_mc_addr(ha, dev) {
c528f49
+				sun8i_dwmac_set_umac_addr(hw, ha->addr, i);
c528f49
+				i++;
c528f49
+			}
58a0e11
+		}
c528f49
+		if (!netdev_uc_empty(dev)) {
c528f49
+			netdev_for_each_uc_addr(ha, dev) {
c528f49
+				sun8i_dwmac_set_umac_addr(hw, ha->addr, i);
c528f49
+				i++;
c528f49
+			}
c528f49
+		}
c528f49
+	} else {
58a0e11
+		netdev_info(dev, "Too many address, switching to promiscuous\n");
58a0e11
+		v = EMAC_FRM_FLT_RXALL;
58a0e11
+	}
c528f49
+
c528f49
+	/* Disable unused address filter slots */
c528f49
+	while (i < hw->unicast_filter_entries)
c528f49
+		sun8i_dwmac_set_umac_addr(hw, NULL, i++);
c528f49
+
58a0e11
+	writel(v, ioaddr + EMAC_RX_FRM_FLT);
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_flow_ctrl(struct mac_device_info *hw,
c528f49
+				  unsigned int duplex, unsigned int fc,
c528f49
+				  unsigned int pause_time, u32 tx_cnt)
c0853e1
+{
58a0e11
+	void __iomem *ioaddr = hw->pcsr;
58a0e11
+	u32 v;
58a0e11
+
58a0e11
+	v = readl(ioaddr + EMAC_RX_CTL0);
58a0e11
+	if (fc == FLOW_AUTO)
58a0e11
+		v |= EMAC_RX_FLOW_CTL_EN;
58a0e11
+	else
58a0e11
+		v &= ~EMAC_RX_FLOW_CTL_EN;
58a0e11
+	writel(v, ioaddr + EMAC_RX_CTL0);
c0853e1
+
58a0e11
+	v = readl(ioaddr + EMAC_TX_FLOW_CTL);
58a0e11
+	if (fc == FLOW_AUTO)
58a0e11
+		v |= EMAC_TX_FLOW_CTL_EN;
58a0e11
+	else
58a0e11
+		v &= ~EMAC_TX_FLOW_CTL_EN;
58a0e11
+	writel(v, ioaddr + EMAC_TX_FLOW_CTL);
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_reset(struct stmmac_priv *priv)
c0853e1
+{
58a0e11
+	u32 v;
58a0e11
+	int err;
c0853e1
+
58a0e11
+	v = readl(priv->ioaddr + EMAC_BASIC_CTL1);
58a0e11
+	writel(v | 0x01, priv->ioaddr + EMAC_BASIC_CTL1);
c0853e1
+
58a0e11
+	err = readl_poll_timeout(priv->ioaddr + EMAC_BASIC_CTL1, v,
58a0e11
+				 !(v & 0x01), 100, 10000);
c0853e1
+
58a0e11
+	if (err) {
58a0e11
+		dev_err(priv->device, "EMAC reset timeout\n");
58a0e11
+		return -EFAULT;
c0853e1
+	}
58a0e11
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
c0853e1
+{
58a0e11
+	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
58a0e11
+	struct device_node *node = priv->device->of_node;
c0853e1
+	int ret;
c0853e1
+	u32 reg, val;
c0853e1
+
58a0e11
+	regmap_read(gmac->regmap, SYSCON_EMAC_REG, &val;;
58a0e11
+	reg = gmac->variant->default_syscon_value;
58a0e11
+	if (reg != val)
58a0e11
+		dev_warn(priv->device,
58a0e11
+			 "Current syscon value is not the default %x (expect %x)\n",
58a0e11
+			 val, reg);
c0853e1
+
58a0e11
+	if (gmac->variant->internal_phy) {
58a0e11
+		if (!gmac->use_internal_phy) {
c0853e1
+			/* switch to external PHY interface */
c0853e1
+			reg &= ~H3_EPHY_SELECT;
c0853e1
+		} else {
c0853e1
+			reg |= H3_EPHY_SELECT;
c0853e1
+			reg &= ~H3_EPHY_SHUTDOWN;
58a0e11
+			dev_dbg(priv->device, "Select internal_phy %x\n", reg);
c0853e1
+
58a0e11
+			if (of_property_read_bool(priv->plat->phy_node,
c0853e1
+						  "allwinner,leds-active-low"))
c0853e1
+				reg |= H3_EPHY_LED_POL;
58a0e11
+			else
58a0e11
+				reg &= ~H3_EPHY_LED_POL;
c0853e1
+
58a0e11
+			ret = of_mdio_parse_addr(priv->device,
58a0e11
+						 priv->plat->phy_node);
c0853e1
+			if (ret < 0) {
58a0e11
+				dev_err(priv->device, "Could not parse MDIO addr\n");
c0853e1
+				return ret;
c0853e1
+			}
c0853e1
+			/* of_mdio_parse_addr returns a valid (0 ~ 31) PHY
c0853e1
+			 * address. No need to mask it again.
c0853e1
+			 */
c0853e1
+			reg |= ret << H3_EPHY_ADDR_SHIFT;
c0853e1
+		}
c0853e1
+	}
c0853e1
+
c528f49
+	if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) {
c528f49
+		if (val % 100) {
c528f49
+			dev_err(priv->device, "tx-delay must be a multiple of 100\n");
c528f49
+			return -EINVAL;
c528f49
+		}
c528f49
+		val /= 100;
58a0e11
+		dev_dbg(priv->device, "set tx-delay to %x\n", val);
c0853e1
+		if (val <= SYSCON_ETXDC_MASK) {
c0853e1
+			reg &= ~(SYSCON_ETXDC_MASK << SYSCON_ETXDC_SHIFT);
c0853e1
+			reg |= (val << SYSCON_ETXDC_SHIFT);
c0853e1
+		} else {
58a0e11
+			dev_err(priv->device, "Invalid TX clock delay: %d\n",
58a0e11
+				val);
58a0e11
+			return -EINVAL;
c0853e1
+		}
c0853e1
+	}
c0853e1
+
c528f49
+	if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) {
c528f49
+		if (val % 100) {
c528f49
+			dev_err(priv->device, "rx-delay must be a multiple of 100\n");
c528f49
+			return -EINVAL;
c528f49
+		}
c528f49
+		val /= 100;
58a0e11
+		dev_dbg(priv->device, "set rx-delay to %x\n", val);
c0853e1
+		if (val <= SYSCON_ERXDC_MASK) {
c0853e1
+			reg &= ~(SYSCON_ERXDC_MASK << SYSCON_ERXDC_SHIFT);
c0853e1
+			reg |= (val << SYSCON_ERXDC_SHIFT);
c0853e1
+		} else {
58a0e11
+			dev_err(priv->device, "Invalid RX clock delay: %d\n",
58a0e11
+				val);
58a0e11
+			return -EINVAL;
c0853e1
+		}
c0853e1
+	}
c0853e1
+
c0853e1
+	/* Clear interface mode bits */
c0853e1
+	reg &= ~(SYSCON_ETCS_MASK | SYSCON_EPIT);
58a0e11
+	if (gmac->variant->support_rmii)
c0853e1
+		reg &= ~SYSCON_RMII_EN;
c0853e1
+
58a0e11
+	switch (priv->plat->interface) {
c0853e1
+	case PHY_INTERFACE_MODE_MII:
c0853e1
+		/* default */
c0853e1
+		break;
c0853e1
+	case PHY_INTERFACE_MODE_RGMII:
c0853e1
+		reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
c0853e1
+		break;
c0853e1
+	case PHY_INTERFACE_MODE_RMII:
c0853e1
+		reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII;
c0853e1
+		break;
c0853e1
+	default:
58a0e11
+		dev_err(priv->device, "Unsupported interface mode: %s",
58a0e11
+			phy_modes(priv->plat->interface));
c0853e1
+		return -EINVAL;
c0853e1
+	}
c0853e1
+
58a0e11
+	regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg);
c0853e1
+
c0853e1
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac)
c0853e1
+{
58a0e11
+	u32 reg = gmac->variant->default_syscon_value;
c0853e1
+
58a0e11
+	regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg);
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv)
c0853e1
+{
58a0e11
+	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
c0853e1
+	int ret;
c0853e1
+
c528f49
+	if (!gmac->use_internal_phy)
c528f49
+		return 0;
c528f49
+
c528f49
+	ret = clk_prepare_enable(gmac->ephy_clk);
c528f49
+	if (ret) {
c528f49
+		dev_err(priv->device, "Cannot enable ephy\n");
c528f49
+		return ret;
c0853e1
+	}
c0853e1
+
c528f49
+	ret = reset_control_deassert(gmac->rst_ephy);
c528f49
+	if (ret) {
c528f49
+		dev_err(priv->device, "Cannot deassert ephy\n");
c528f49
+		clk_disable_unprepare(gmac->ephy_clk);
c528f49
+		return ret;
c0853e1
+	}
c0853e1
+
c0853e1
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_unpower_internal_phy(struct sunxi_priv_data *gmac)
c0853e1
+{
c528f49
+	if (!gmac->use_internal_phy)
c528f49
+		return 0;
c528f49
+
c528f49
+	clk_disable_unprepare(gmac->ephy_clk);
c528f49
+	reset_control_assert(gmac->rst_ephy);
c0853e1
+	return 0;
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_power_phy(struct stmmac_priv *priv)
c0853e1
+{
58a0e11
+	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
58a0e11
+	int ret;
c0853e1
+
58a0e11
+	ret = sun8i_dwmac_power_internal_phy(priv);
58a0e11
+	if (ret)
58a0e11
+		return ret;
c0853e1
+
58a0e11
+	ret = sun8i_dwmac_set_syscon(priv);
58a0e11
+	if (ret)
58a0e11
+		goto error_phy;
c0853e1
+
58a0e11
+	ret = sun8i_dwmac_reset(priv);
58a0e11
+	if (ret)
58a0e11
+		goto error_phy;
c0853e1
+	return 0;
58a0e11
+
58a0e11
+error_phy:
58a0e11
+	sun8i_dwmac_unset_syscon(gmac);
58a0e11
+	sun8i_dwmac_unpower_internal_phy(gmac);
58a0e11
+	return ret;
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_unpower_phy(struct sunxi_priv_data *gmac)
c0853e1
+{
58a0e11
+	sun8i_dwmac_unset_syscon(gmac);
58a0e11
+	sun8i_dwmac_unpower_internal_phy(gmac);
c0853e1
+}
c0853e1
+
58a0e11
+static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv)
c0853e1
+{
58a0e11
+	struct sunxi_priv_data *gmac = priv;
c0853e1
+
58a0e11
+	sun8i_unpower_phy(gmac);
c0853e1
+
58a0e11
+	clk_disable_unprepare(gmac->tx_clk);
c0853e1
+
58a0e11
+	if (gmac->regulator)
58a0e11
+		regulator_disable(gmac->regulator);
c0853e1
+}
c0853e1
+
58a0e11
+static const struct stmmac_ops sun8i_dwmac_ops = {
58a0e11
+	.core_init = sun8i_dwmac_core_init,
c528f49
+	.set_mac = sun8i_dwmac_set_mac,
58a0e11
+	.dump_regs = sun8i_dwmac_dump_mac_regs,
58a0e11
+	.rx_ipc = sun8i_dwmac_rx_ipc_enable,
58a0e11
+	.set_filter = sun8i_dwmac_set_filter,
58a0e11
+	.flow_ctrl = sun8i_dwmac_flow_ctrl,
58a0e11
+	.set_umac_addr = sun8i_dwmac_set_umac_addr,
58a0e11
+	.get_umac_addr = sun8i_dwmac_get_umac_addr,
58a0e11
+};
c0853e1
+
c528f49
+static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
c0853e1
+{
58a0e11
+	struct mac_device_info *mac;
c528f49
+	struct stmmac_priv *priv = ppriv;
58a0e11
+	int ret;
c0853e1
+
58a0e11
+	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
58a0e11
+	if (!mac)
58a0e11
+		return NULL;
58a0e11
+
58a0e11
+	ret = sun8i_power_phy(priv);
58a0e11
+	if (ret)
58a0e11
+		return NULL;
58a0e11
+
58a0e11
+	mac->pcsr = priv->ioaddr;
58a0e11
+	mac->mac = &sun8i_dwmac_ops;
58a0e11
+	mac->dma = &sun8i_dwmac_dma_ops;
58a0e11
+
58a0e11
+	mac->link.port = 0;
58a0e11
+	mac->link.duplex = BIT(0);
58a0e11
+	mac->link.speed = 1;
58a0e11
+	mac->mii.addr = EMAC_MDIO_CMD;
58a0e11
+	mac->mii.data = EMAC_MDIO_DATA;
58a0e11
+	mac->mii.reg_shift = 4;
58a0e11
+	mac->mii.reg_mask = GENMASK(8, 4);
58a0e11
+	mac->mii.addr_shift = 12;
58a0e11
+	mac->mii.addr_mask = GENMASK(16, 12);
58a0e11
+	mac->mii.clk_csr_shift = 20;
58a0e11
+	mac->mii.clk_csr_mask = GENMASK(22, 20);
58a0e11
+	mac->unicast_filter_entries = 8;
58a0e11
+
58a0e11
+	/* Synopsys Id is not available */
58a0e11
+	priv->synopsys_id = 0;
58a0e11
+
58a0e11
+	return mac;
c0853e1
+}
c0853e1
+
58a0e11
+static int sun8i_dwmac_probe(struct platform_device *pdev)
c0853e1
+{
58a0e11
+	struct plat_stmmacenet_data *plat_dat;
58a0e11
+	struct stmmac_resources stmmac_res;
58a0e11
+	struct sunxi_priv_data *gmac;
58a0e11
+	struct device *dev = &pdev->dev;
58a0e11
+	int ret;
c0853e1
+
58a0e11
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
58a0e11
+	if (ret)
58a0e11
+		return ret;
c0853e1
+
58a0e11
+	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
58a0e11
+	if (IS_ERR(plat_dat))
58a0e11
+		return PTR_ERR(plat_dat);
c0853e1
+
58a0e11
+	gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
58a0e11
+	if (!gmac)
58a0e11
+		return -ENOMEM;
c0853e1
+
58a0e11
+	gmac->variant = of_device_get_match_data(&pdev->dev);
58a0e11
+	if (!gmac->variant) {
c528f49
+		dev_err(&pdev->dev, "Missing dwmac-sun8i variant\n");
58a0e11
+		return -EINVAL;
c0853e1
+	}
c0853e1
+
58a0e11
+	gmac->tx_clk = devm_clk_get(dev, "stmmaceth");
58a0e11
+	if (IS_ERR(gmac->tx_clk)) {
c528f49
+		dev_err(dev, "Could not get TX clock\n");
58a0e11
+		return PTR_ERR(gmac->tx_clk);
c0853e1
+	}
c0853e1
+
58a0e11
+	/* Optional regulator for PHY */
58a0e11
+	gmac->regulator = devm_regulator_get_optional(dev, "phy");
58a0e11
+	if (IS_ERR(gmac->regulator)) {
58a0e11
+		if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
58a0e11
+			return -EPROBE_DEFER;
c528f49
+		dev_info(dev, "No regulator found\n");
58a0e11
+		gmac->regulator = NULL;
c0853e1
+	}
c0853e1
+
58a0e11
+	gmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
58a0e11
+						       "syscon");
58a0e11
+	if (IS_ERR(gmac->regmap)) {
58a0e11
+		ret = PTR_ERR(gmac->regmap);
c528f49
+		dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
58a0e11
+		return ret;
c0853e1
+	}
c0853e1
+
58a0e11
+	plat_dat->interface = of_get_phy_mode(dev->of_node);
58a0e11
+	if (plat_dat->interface == gmac->variant->internal_phy) {
58a0e11
+		dev_info(&pdev->dev, "Will use internal PHY\n");
58a0e11
+		gmac->use_internal_phy = true;
58a0e11
+		gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0);
58a0e11
+		if (IS_ERR(gmac->ephy_clk)) {
58a0e11
+			ret = PTR_ERR(gmac->ephy_clk);
c528f49
+			dev_err(&pdev->dev, "Cannot get EPHY clock: %d\n", ret);
58a0e11
+			return -EINVAL;
58a0e11
+		}
c0853e1
+
58a0e11
+		gmac->rst_ephy = of_reset_control_get(plat_dat->phy_node, NULL);
58a0e11
+		if (IS_ERR(gmac->rst_ephy)) {
58a0e11
+			ret = PTR_ERR(gmac->rst_ephy);
58a0e11
+			if (ret == -EPROBE_DEFER)
58a0e11
+				return ret;
58a0e11
+			dev_err(&pdev->dev, "No EPHY reset control found %d\n",
58a0e11
+				ret);
58a0e11
+			return -EINVAL;
58a0e11
+		}
c0853e1
+	} else {
58a0e11
+		dev_info(&pdev->dev, "Will use external PHY\n");
58a0e11
+		gmac->use_internal_phy = false;
c0853e1
+	}
c0853e1
+
58a0e11
+	/* platform data specifying hardware features and callbacks.
58a0e11
+	 * hardware features were copied from Allwinner drivers.
58a0e11
+	 */
58a0e11
+	plat_dat->rx_coe = STMMAC_RX_COE_TYPE2;
58a0e11
+	plat_dat->tx_coe = 1;
58a0e11
+	plat_dat->has_sun8i = true;
58a0e11
+	plat_dat->bsp_priv = gmac;
58a0e11
+	plat_dat->init = sun8i_dwmac_init;
58a0e11
+	plat_dat->exit = sun8i_dwmac_exit;
58a0e11
+	plat_dat->setup = sun8i_dwmac_setup;
58a0e11
+
58a0e11
+	ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv);
58a0e11
+	if (ret)
58a0e11
+		return ret;
c0853e1
+
58a0e11
+	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
58a0e11
+	if (ret)
58a0e11
+		sun8i_dwmac_exit(pdev, plat_dat->bsp_priv);
c0853e1
+
58a0e11
+	return ret;
c0853e1
+}
c0853e1
+
58a0e11
+static const struct of_device_id sun8i_dwmac_match[] = {
c0853e1
+	{ .compatible = "allwinner,sun8i-h3-emac",
58a0e11
+		.data = &emac_variant_h3 },
58a0e11
+	{ .compatible = "allwinner,sun8i-a83t-emac",
58a0e11
+		.data = &emac_variant_a83t },
c0853e1
+	{ .compatible = "allwinner,sun50i-a64-emac",
58a0e11
+		.data = &emac_variant_a64 },
58a0e11
+	{ }
c0853e1
+};
58a0e11
+MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
58a0e11
+
58a0e11
+static struct platform_driver sun8i_dwmac_driver = {
58a0e11
+	.probe  = sun8i_dwmac_probe,
58a0e11
+	.remove = stmmac_pltfr_remove,
58a0e11
+	.driver = {
c528f49
+		.name           = "dwmac-sun8i",
58a0e11
+		.pm		= &stmmac_pltfr_pm_ops,
58a0e11
+		.of_match_table = sun8i_dwmac_match,
c0853e1
+	},
c0853e1
+};
58a0e11
+module_platform_driver(sun8i_dwmac_driver);
c0853e1
+
58a0e11
+MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com>");
58a0e11
+MODULE_DESCRIPTION("Allwinner sun8i DWMAC specific glue layer");
c0853e1
+MODULE_LICENSE("GPL");
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
c528f49
index b82ab64..39777a7 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
c528f49
@@ -235,6 +235,17 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
58a0e11
 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
58a0e11
 			priv->clk_csr = STMMAC_CSR_250_300M;
58a0e11
 	}
58a0e11
+
58a0e11
+	if (priv->plat->has_sun8i) {
58a0e11
+		if (clk_rate > 160000000)
58a0e11
+			priv->clk_csr = 0x03;
58a0e11
+		else if (clk_rate > 80000000)
58a0e11
+			priv->clk_csr = 0x02;
58a0e11
+		else if (clk_rate > 40000000)
58a0e11
+			priv->clk_csr = 0x01;
58a0e11
+		else
58a0e11
+			priv->clk_csr = 0;
58a0e11
+	}
58a0e11
 }
c0853e1
 
58a0e11
 static void print_pkt(unsigned char *buf, int len)
c528f49
@@ -784,6 +795,14 @@ static void stmmac_adjust_link(struct net_device *dev)
58a0e11
 	if (phydev->link) {
58a0e11
 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
58a0e11
 
c528f49
+		/* dwmac-sun8i handle loopback in MAC_CTRL_REG */
c528f49
+		if (priv->plat->has_sun8i) {
c528f49
+			if (dev->features & NETIF_F_LOOPBACK)
c528f49
+				ctrl |= BIT(1);
c528f49
+			else
c528f49
+				ctrl &= ~BIT(1);
c528f49
+		}
58a0e11
+
58a0e11
 		/* Now we make sure that we can be in full duplex mode.
58a0e11
 		 * If not, we operate in half-duplex mode. */
58a0e11
 		if (phydev->duplex != priv->oldduplex) {
c528f49
@@ -800,6 +819,8 @@ static void stmmac_adjust_link(struct net_device *dev)
58a0e11
 
58a0e11
 		if (phydev->speed != priv->speed) {
58a0e11
 			new_state = 1;
58a0e11
+			if (priv->plat->has_sun8i)
58a0e11
+				ctrl &= ~GENMASK(3, 2);
58a0e11
 			switch (phydev->speed) {
58a0e11
 			case 1000:
58a0e11
 				if (priv->plat->has_gmac ||
c528f49
@@ -811,6 +832,8 @@ static void stmmac_adjust_link(struct net_device *dev)
58a0e11
 				    priv->plat->has_gmac4) {
58a0e11
 					ctrl |= priv->hw->link.port;
58a0e11
 					ctrl |= priv->hw->link.speed;
58a0e11
+				} else if (priv->plat->has_sun8i) {
58a0e11
+					ctrl |= 3 << 2;
58a0e11
 				} else {
58a0e11
 					ctrl &= ~priv->hw->link.port;
58a0e11
 				}
c528f49
@@ -820,6 +843,8 @@ static void stmmac_adjust_link(struct net_device *dev)
58a0e11
 				    priv->plat->has_gmac4) {
58a0e11
 					ctrl |= priv->hw->link.port;
58a0e11
 					ctrl &= ~(priv->hw->link.speed);
58a0e11
+				} else if (priv->plat->has_sun8i) {
58a0e11
+					ctrl |= 2 << 2;
58a0e11
 				} else {
58a0e11
 					ctrl &= ~priv->hw->link.port;
58a0e11
 				}
c528f49
@@ -3969,6 +3994,10 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
58a0e11
 
58a0e11
 	priv->hw = mac;
58a0e11
 
58a0e11
+	/* dwmac-sun8i only work in chain mode */
58a0e11
+	if (priv->plat->has_sun8i)
58a0e11
+		chain_mode = 1;
58a0e11
+
58a0e11
 	/* To use the chained or ring mode */
58a0e11
 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
58a0e11
 		priv->hw->mode = &dwmac4_ring_mode_ops;
58a0e11
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
c528f49
index 7fc3a1e..3840529 100644
58a0e11
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
58a0e11
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
c528f49
@@ -309,6 +309,12 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
58a0e11
 			 struct device_node *np, struct device *dev)
58a0e11
 {
58a0e11
 	bool mdio = true;
58a0e11
+	static const struct of_device_id need_mdio_ids[] = {
58a0e11
+		{ .compatible = "snps,dwc-qos-ethernet-4.10" },
58a0e11
+		{ .compatible = "allwinner,sun8i-a83t-emac" },
58a0e11
+		{ .compatible = "allwinner,sun8i-h3-emac" },
58a0e11
+		{ .compatible = "allwinner,sun50i-a64-emac" },
c0853e1
+	};
58a0e11
 
58a0e11
 	/* If phy-handle property is passed from DT, use it as the PHY */
58a0e11
 	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
c528f49
@@ -325,8 +331,7 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
58a0e11
 		mdio = false;
58a0e11
 	}
58a0e11
 
58a0e11
-	/* exception for dwmac-dwc-qos-eth glue logic */
58a0e11
-	if (of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) {
58a0e11
+	if (of_match_node(need_mdio_ids, np)) {
58a0e11
 		plat->mdio_node = of_get_child_by_name(np, "mdio");
58a0e11
 	} else {
58a0e11
 		/**
58a0e11
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
c528f49
index 8bb550b..108739f 100644
58a0e11
--- a/include/linux/stmmac.h
58a0e11
+++ b/include/linux/stmmac.h
c528f49
@@ -186,6 +186,7 @@ struct plat_stmmacenet_data {
58a0e11
 	struct reset_control *stmmac_rst;
58a0e11
 	struct stmmac_axi *axi;
58a0e11
 	int has_gmac4;
58a0e11
+	bool has_sun8i;
58a0e11
 	bool tso_en;
58a0e11
 	int mac_port_sel_speed;
58a0e11
 	bool en_tx_lpi_clockgating;
c528f49
c528f49
From patchwork Mon May  1 12:45:06 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,
c528f49
 06/20] arm: sun8i: sunxi-h3-h5: Add dt node for the syscon control
c0853e1
 module
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706459
c528f49
Message-Id: <20170501124520.3769-7-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:06 +0200
c0853e1
c0853e1
This patch add the dt node for the syscon register present on the
58a0e11
Allwinner H3/H5
c0853e1
c0853e1
Only two register are present in this syscon and the only one useful is
58a0e11
the one dedicated to EMAC clock..
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
58a0e11
 arch/arm/boot/dts/sunxi-h3-h5.dtsi | 6 ++++++
58a0e11
 1 file changed, 6 insertions(+)
c0853e1
58a0e11
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
c528f49
index 1aeeacb..d9691fc 100644
58a0e11
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
58a0e11
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
c528f49
@@ -83,6 +83,12 @@
c0853e1
 		#size-cells = <1>;
c0853e1
 		ranges;
c0853e1
 
c528f49
+		syscon: syscon@1c00000 {
c528f49
+			compatible = "allwinner,sun8i-h3-system-controller",
c528f49
+				"syscon";
c0853e1
+			reg = <0x01c00000 0x1000>;
c0853e1
+		};
c0853e1
+
c0853e1
 		dma: dma-controller@01c02000 {
c0853e1
 			compatible = "allwinner,sun8i-h3-dma";
c0853e1
 			reg = <0x01c02000 0x1000>;
c528f49
c528f49
From patchwork Mon May  1 12:45:07 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,07/20] arm: sun8i: sunxi-h3-h5: add dwmac-sun8i ethernet driver
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706465
c528f49
Message-Id: <20170501124520.3769-8-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:07 +0200
c0853e1
58a0e11
The dwmac-sun8i is an ethernet MAC hardware that support 10/100/1000
c0853e1
speed.
c0853e1
58a0e11
This patch enable the dwmac-sun8i on Allwinner H3/H5 SoC Device-tree.
58a0e11
SoC H3/H5 have an internal PHY, so optionals syscon and ephy are set.
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
c528f49
 arch/arm/boot/dts/sunxi-h3-h5.dtsi | 34 ++++++++++++++++++++++++++++++++++
c528f49
 1 file changed, 34 insertions(+)
c0853e1
58a0e11
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
c528f49
index d9691fc..45a9a30 100644
58a0e11
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
58a0e11
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
c528f49
@@ -285,6 +285,14 @@
58a0e11
 			interrupt-controller;
58a0e11
 			#interrupt-cells = <3>;
58a0e11
 
c528f49
+			emac_rgmii_pins: emac0 {
58a0e11
+				pins = "PD0", "PD1", "PD2", "PD3", "PD4",
c528f49
+				       "PD5", "PD7", "PD8", "PD9", "PD10",
c528f49
+				       "PD12", "PD13", "PD15", "PD16", "PD17";
58a0e11
+				function = "emac";
58a0e11
+				drive-strength = <40>;
58a0e11
+			};
58a0e11
+
58a0e11
 			i2c0_pins: i2c0 {
58a0e11
 				pins = "PA11", "PA12";
58a0e11
 				function = "i2c0";
c528f49
@@ -381,6 +389,32 @@
58a0e11
 			clocks = <&osc24M>;
c0853e1
 		};
c0853e1
 
c0853e1
+		emac: ethernet@1c30000 {
c0853e1
+			compatible = "allwinner,sun8i-h3-emac";
c0853e1
+			syscon = <&syscon>;
c0853e1
+			reg = <0x01c30000 0x104>;
c0853e1
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
58a0e11
+			interrupt-names = "macirq";
c0853e1
+			resets = <&ccu RST_BUS_EMAC>;
58a0e11
+			reset-names = "stmmaceth";
c0853e1
+			clocks = <&ccu CLK_BUS_EMAC>;
58a0e11
+			clock-names = "stmmaceth";
c0853e1
+			#address-cells = <1>;
c0853e1
+			#size-cells = <0>;
c0853e1
+			status = "disabled";
c0853e1
+
c0853e1
+			mdio: mdio {
c0853e1
+				#address-cells = <1>;
c0853e1
+				#size-cells = <0>;
c0853e1
+				int_mii_phy: ethernet-phy@1 {
c528f49
+					compatible = "ethernet-phy-ieee802.3-c22";
c528f49
+					reg = <1>;
c528f49
+					clocks = <&ccu CLK_BUS_EPHY>;
c528f49
+					resets = <&ccu RST_BUS_EPHY>;
c0853e1
+				};
c0853e1
+			};
c0853e1
+		};
c0853e1
+
58a0e11
 		spi0: spi@01c68000 {
58a0e11
 			compatible = "allwinner,sun8i-h3-spi";
58a0e11
 			reg = <0x01c68000 0x1000>;
58a0e11
c528f49
From patchwork Mon May  1 12:45:08 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,08/20] arm: sun8i: orangepi-pc: Enable dwmac-sun8i
c0853e1
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706463
c528f49
Message-Id: <20170501124520.3769-9-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:08 +0200
58a0e11
58a0e11
The dwmac-sun8i hardware is present on the Orange PI PC.
c0853e1
It uses the internal PHY.
c0853e1
c0853e1
This patch create the needed emac node.
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
c0853e1
 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 ++++++++
c0853e1
 1 file changed, 8 insertions(+)
c0853e1
c0853e1
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
c528f49
index f148111..52e6575 100644
c0853e1
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
c0853e1
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
c528f49
@@ -52,6 +52,7 @@
c528f49
 	compatible = "xunlong,orangepi-pc", "allwinner,sun8i-h3";
c0853e1
 
c0853e1
 	aliases {
c0853e1
+		ethernet0 = &emac;
c528f49
 		serial0 = &uart;;
c0853e1
 	};
c0853e1
 
c528f49
@@ -109,6 +110,13 @@
c0853e1
 	status = "okay";
c0853e1
 };
c528f49
 
c0853e1
+&emac {
c0853e1
+	phy-handle = <&int_mii_phy>;
c0853e1
+	phy-mode = "mii";
c0853e1
+	allwinner,leds-active-low;
c0853e1
+	status = "okay";
c0853e1
+};
c528f49
+
c528f49
 &ir {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&ir_pins_a>;
c528f49
c528f49
From patchwork Mon May  1 12:45:09 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,09/20] arm: sun8i: orangepi-zero: Enable dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706461
c528f49
Message-Id: <20170501124520.3769-10-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:09 +0200
58a0e11
c528f49
The dwmac-sun8i hardware is present on the Orange PI Zero.
58a0e11
It uses the internal PHY.
58a0e11
58a0e11
This patch create the needed emac node.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
c528f49
 arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts | 8 ++++++++
58a0e11
 1 file changed, 8 insertions(+)
c0853e1
c528f49
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
c528f49
index 9e8b082..dd3525a 100644
c528f49
--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
c528f49
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
c528f49
@@ -57,6 +57,7 @@
c528f49
 	aliases {
58a0e11
 		serial0 = &uart;;
58a0e11
 		/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
58a0e11
+		ethernet0 = &emac;
c528f49
 		ethernet1 = &xr819;
58a0e11
 	};
58a0e11
 
c528f49
@@ -103,6 +104,13 @@
58a0e11
 	status = "okay";
58a0e11
 };
c528f49
 
58a0e11
+&emac {
58a0e11
+	phy-handle = <&int_mii_phy>;
58a0e11
+	phy-mode = "mii";
58a0e11
+	allwinner,leds-active-low;
58a0e11
+	status = "okay";
58a0e11
+};
c528f49
+
c528f49
 &mmc0 {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&mmc0_pins_a>;
c528f49
c528f49
From patchwork Mon May  1 12:45:10 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,10/20] arm: sun8i: orangepi-one: Enable dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706471
c528f49
Message-Id: <20170501124520.3769-11-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:10 +0200
c0853e1
58a0e11
The dwmac-sun8i hardware is present on the Orange PI One.
c0853e1
It uses the internal PHY.
c0853e1
c0853e1
This patch create the needed emac node.
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
c0853e1
 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 8 ++++++++
c0853e1
 1 file changed, 8 insertions(+)
c0853e1
c0853e1
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
c528f49
index 5fea430..6880268 100644
c0853e1
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
c0853e1
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
c528f49
@@ -52,6 +52,7 @@
c528f49
 	compatible = "xunlong,orangepi-one", "allwinner,sun8i-h3";
c0853e1
 
c0853e1
 	aliases {
c0853e1
+		ethernet0 = &emac;
c528f49
 		serial0 = &uart;;
c0853e1
 	};
c0853e1
 
c528f49
@@ -97,6 +98,13 @@
c0853e1
 	status = "okay";
c0853e1
 };
c0853e1
 
c0853e1
+&emac {
c0853e1
+	phy-handle = <&int_mii_phy>;
c0853e1
+	phy-mode = "mii";
c0853e1
+	allwinner,leds-active-low;
c0853e1
+	status = "okay";
c0853e1
+};
c0853e1
+
c0853e1
 &mmc0 {
c0853e1
 	pinctrl-names = "default";
c0853e1
 	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
c528f49
c528f49
From patchwork Mon May  1 12:45:11 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,11/20] arm: sun8i: orangepi-2: Enable dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706467
c528f49
Message-Id: <20170501124520.3769-12-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:11 +0200
c528f49
c528f49
The dwmac-sun8i hardware is present on the Orange PI 2.
c528f49
It uses the internal PHY.
c0853e1
c528f49
This patch create the needed emac node.
c0853e1
c0853e1
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
c0853e1
---
c528f49
 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 ++++++++
c528f49
 1 file changed, 8 insertions(+)
c0853e1
c528f49
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
c528f49
index 5b6d145..cedd326 100644
c528f49
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
c528f49
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
c528f49
@@ -54,6 +54,7 @@
c528f49
 	aliases {
c528f49
 		serial0 = &uart;;
c528f49
 		/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
c528f49
+		ethernet0 = &emac;
c528f49
 		ethernet1 = &rtl8189;
58a0e11
 	};
c0853e1
 
c528f49
@@ -108,6 +109,13 @@
c528f49
 	status = "okay";
c0853e1
 };
58a0e11
 
c0853e1
+&emac {
c528f49
+	phy-handle = <&int_mii_phy>;
c528f49
+	phy-mode = "mii";
c0853e1
+	allwinner,leds-active-low;
c0853e1
+	status = "okay";
c0853e1
+};
c528f49
+
c528f49
 &ir {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&ir_pins_a>;
c528f49
c528f49
From patchwork Mon May  1 12:45:12 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,
c528f49
 12/20] arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active
c528f49
 high
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706481
c528f49
Message-Id: <20170501124520.3769-13-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:12 +0200
58a0e11
58a0e11
On the Orange Pi PC Plus, the polarity of the LEDs on the RJ45 Ethernet
58a0e11
port were changed from active low to active high.
58a0e11
58a0e11
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
58a0e11
 arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5 +++++
58a0e11
 1 file changed, 5 insertions(+)
58a0e11
58a0e11
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
c528f49
index 8b93f5c..a10281b 100644
58a0e11
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
58a0e11
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
c528f49
@@ -53,6 +53,11 @@
c528f49
 	};
58a0e11
 };
c528f49
 
58a0e11
+&emac {
58a0e11
+	/* LEDs changed to active high on the plus */
58a0e11
+	/delete-property/ allwinner,leds-active-low;
58a0e11
+};
c528f49
+
c528f49
 &mmc1 {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&mmc1_pins_a>;
c528f49
c528f49
From patchwork Mon May  1 12:45:13 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5, 13/20] arm64: allwinner: sun50i-a64: Add dt node for the syscon
c528f49
 control module
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706477
c528f49
Message-Id: <20170501124520.3769-14-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:13 +0200
58a0e11
58a0e11
This patch add the dt node for the syscon register present on the
58a0e11
Allwinner A64.
58a0e11
58a0e11
Only two register are present in this syscon and the only one useful is
58a0e11
the one dedicated to EMAC clock.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
58a0e11
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 ++++++
58a0e11
 1 file changed, 6 insertions(+)
58a0e11
58a0e11
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
c528f49
index c7f669f..d7341ba 100644
58a0e11
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
58a0e11
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
c528f49
@@ -129,6 +129,12 @@
58a0e11
 		#size-cells = <1>;
58a0e11
 		ranges;
58a0e11
 
c528f49
+		syscon: syscon@1c00000 {
c528f49
+			compatible = "allwinner,sun50i-a64-system-controller",
c528f49
+				"syscon";
58a0e11
+			reg = <0x01c00000 0x1000>;
58a0e11
+		};
58a0e11
+
58a0e11
 		mmc0: mmc@1c0f000 {
58a0e11
 			compatible = "allwinner,sun50i-a64-mmc";
58a0e11
 			reg = <0x01c0f000 0x1000>;
c528f49
c528f49
From patchwork Mon May  1 12:45:14 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,
c528f49
 14/20] arm64: allwinner: sun50i-a64: add dwmac-sun8i Ethernet driver
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706485
c528f49
Message-Id: <20170501124520.3769-15-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:14 +0200
58a0e11
58a0e11
The dwmac-sun8i is an Ethernet MAC that supports 10/100/1000 Mbit
58a0e11
connections. It is very similar to the device found in the Allwinner
58a0e11
H3, but lacks the internal 100 Mbit PHY and its associated control
58a0e11
bits.
58a0e11
This adds the necessary bits to the Allwinner A64 SoC .dtsi, but keeps
58a0e11
it disabled at this level.
c0853e1
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
c528f49
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 35 +++++++++++++++++++++++++++
c528f49
 1 file changed, 35 insertions(+)
58a0e11
58a0e11
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
c528f49
index d7341ba..18b3642 100644
58a0e11
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
58a0e11
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
c528f49
@@ -287,6 +287,21 @@
58a0e11
 				bias-pull-up;
58a0e11
 			};
58a0e11
 
58a0e11
+			rmii_pins: rmii_pins {
c528f49
+				pins = "PD10", "PD11", "PD13", "PD14", "PD17",
c528f49
+				       "PD18", "PD19", "PD20", "PD22", "PD23";
58a0e11
+				function = "emac";
58a0e11
+				drive-strength = <40>;
58a0e11
+			};
58a0e11
+
58a0e11
+			rgmii_pins: rgmii_pins {
c528f49
+				pins = "PD8", "PD9", "PD10", "PD11", "PD12",
c528f49
+				       "PD13", "PD15", "PD16", "PD17", "PD18",
c528f49
+				       "PD19", "PD20", "PD21", "PD22", "PD23";
58a0e11
+				function = "emac";
58a0e11
+				drive-strength = <40>;
58a0e11
+			};
58a0e11
+
58a0e11
 			uart0_pins_a: uart0@0 {
58a0e11
 				pins = "PB8", "PB9";
58a0e11
 				function = "uart0";
c528f49
@@ -391,6 +406,26 @@
58a0e11
 			#size-cells = <0>;
58a0e11
 		};
58a0e11
 
58a0e11
+		emac: ethernet@1c30000 {
58a0e11
+			compatible = "allwinner,sun50i-a64-emac";
58a0e11
+			syscon = <&syscon>;
58a0e11
+			reg = <0x01c30000 0x100>;
58a0e11
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
58a0e11
+			interrupt-names = "macirq";
58a0e11
+			resets = <&ccu RST_BUS_EMAC>;
58a0e11
+			reset-names = "stmmaceth";
58a0e11
+			clocks = <&ccu CLK_BUS_EMAC>;
58a0e11
+			clock-names = "stmmaceth";
58a0e11
+			status = "disabled";
58a0e11
+			#address-cells = <1>;
58a0e11
+			#size-cells = <0>;
58a0e11
+
58a0e11
+			mdio: mdio {
58a0e11
+				#address-cells = <1>;
58a0e11
+				#size-cells = <0>;
58a0e11
+			};
58a0e11
+		};
58a0e11
+
58a0e11
 		gic: interrupt-controller@1c81000 {
58a0e11
 			compatible = "arm,gic-400";
58a0e11
 			reg = <0x01c81000 0x1000>,
c528f49
c528f49
From patchwork Mon May  1 12:45:15 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,15/20] arm64: allwinner: pine64: Enable dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706489
c528f49
Message-Id: <20170501124520.3769-16-clabbe.montjoie@gmail.com>
58a0e11
To: robh+dt@kernel.org, mark.rutland@arm.com,
c528f49
 maxime.ripard@free-electrons.com, wens@csie.org,
c528f49
 linux@armlinux.org.uk, catalin.marinas@arm.com,
c528f49
 will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com
c528f49
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
c528f49
 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
c528f49
 Corentin Labbe <clabbe.montjoie@gmail.com>
c528f49
Date: Mon,  1 May 2017 14:45:15 +0200
58a0e11
58a0e11
The dwmac-sun8i hardware is present on the pine64
58a0e11
It uses an external PHY via RMII.
58a0e11
58a0e11
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
58a0e11
---
c528f49
 arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 16 ++++++++++++++++
c528f49
 1 file changed, 16 insertions(+)
58a0e11
58a0e11
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
c528f49
index c680ed3..3b491c0 100644
58a0e11
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
58a0e11
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
c528f49
@@ -70,6 +70,15 @@
58a0e11
 	status = "okay";
58a0e11
 };
c528f49
 
58a0e11
+&emac {
58a0e11
+	pinctrl-names = "default";
58a0e11
+	pinctrl-0 = <&rmii_pins>;
58a0e11
+	phy-mode = "rmii";
58a0e11
+	phy-handle = <&ext_rmii_phy1>;
58a0e11
+	status = "okay";
58a0e11
+
58a0e11
+};
c528f49
+
c528f49
 &i2c1 {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&i2c1_pins>;
c528f49
@@ -80,6 +89,13 @@
c528f49
 	bias-pull-up;
c528f49
 };
c528f49
 
c528f49
+&mdio {
c528f49
+	ext_rmii_phy1: ethernet-phy@1 {
c528f49
+		compatible = "ethernet-phy-ieee802.3-c22";
c528f49
+		reg = <1>;
c528f49
+	};
c528f49
+};
c528f49
+
c528f49
 &mmc0 {
c528f49
 	pinctrl-names = "default";
c528f49
 	pinctrl-0 = <&mmc0_pins>;
c528f49
c528f49
From patchwork Mon May  1 12:45:16 2017
58a0e11
Content-Type: text/plain; charset="utf-8"
58a0e11
MIME-Version: 1.0
58a0e11
Content-Transfer-Encoding: 7bit
c528f49
Subject: [v5,16/20] arm64: allwinner: pine64-plus: Enable dwmac-sun8i
58a0e11
From: Corentin LABBE <clabbe.montjoie@gmail.com>
c528f49
X-Patchwork-Id: 9706511