linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver
@ 2013-12-21  3:42 Iyappan Subramanian
  2013-12-21  3:42 ` [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation Iyappan Subramanian
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

APM X-Gene SoC Ethernet subsystem communicates with a central Queue Manager
 (QMTM) using messages for transmit, receive and allocating data buffers.
 There are multiple ethernet interfaces in APM X-Gene SoC.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
Iyappan Subramanian (5):
  Documentation: APM X-Gene SoC Ethernet DTS binding documentation
  arm64: dts: APM X-Gene SoC Ethernet device tree nodes
  drivers: net: APM X-Gene SoC Ethernet base driver
  drivers: net: APM X-Gene SoC Ethernet driver error handling
  drivers: net: APM X-Gene SoC Ethernet driver ethtool support

 .../devicetree/bindings/net/apm-xgene-enet.txt     |   67 +
 MAINTAINERS                                        |    7 +
 arch/arm64/boot/dts/apm-mustang.dts                |    8 +
 arch/arm64/boot/dts/apm-storm.dtsi                 |   19 +
 drivers/net/ethernet/Kconfig                       |    1 +
 drivers/net/ethernet/Makefile                      |    1 +
 drivers/net/ethernet/apm/Kconfig                   |    1 +
 drivers/net/ethernet/apm/Makefile                  |    5 +
 drivers/net/ethernet/apm/xgene/Kconfig             |   10 +
 drivers/net/ethernet/apm/xgene/Makefile            |   12 +
 drivers/net/ethernet/apm/xgene/xgene_enet_common.c |  497 ++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_common.h |  450 ++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h    |  427 ++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_err.c    |  715 +++++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_mac.c    |  520 +++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   | 1609 ++++++++++++++++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  177 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_tools.c  |  296 ++++
 18 files changed, 4822 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/apm-xgene-enet.txt
 create mode 100644 drivers/net/ethernet/apm/Kconfig
 create mode 100644 drivers/net/ethernet/apm/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_common.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_common.h
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_err.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.h
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_tools.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
@ 2013-12-21  3:42 ` Iyappan Subramanian
  2013-12-22  9:40   ` Arnd Bergmann
  2013-12-21  3:42 ` [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes Iyappan Subramanian
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

Documentation explaining dts nodes.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
 .../devicetree/bindings/net/apm-xgene-enet.txt     |   67 ++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/apm-xgene-enet.txt

diff --git a/Documentation/devicetree/bindings/net/apm-xgene-enet.txt b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
new file mode 100644
index 0000000..8b88b74
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
@@ -0,0 +1,67 @@
+APM X-Gene SoC Ethernet nodes
+
+Ethernet nodes are defined to describe on-chip ethernet interfaces in
+APM X-Gene SoC. Ethernet subsystem communicates with a central Queue Manager
+(QMTM) using messages for transmit, receive and allocating data buffers.
+There are multiple ethernet interfaces in APM X-Gene SoC. Each ethernet
+interface has its own node. Its corresponding clock nodes are shown below.
+
+Required properties:
+- compatible		: Shall be "apm,xgene-enet"
+- reg			: First memory resource shall be the Ethernet CSR
+			  memory resource for indirect MAC access.
+			  Second memory resource shall be the Ethernet CSR
+			  memory resource.
+			  Third memory resource shall be the Ethernet CSR
+			  memory resource for indirect MII access.
+- slave-name		: Shall be QMTM slave name.
+- interrupts		: First interrupt resource shall be the Ethernet global
+			  Error interrupt.
+			: Second interrupt resource shall be the Ethernet MAC
+			  Error interrupt.
+			: Third interrupt resource shall be the Ethernet QM
+			  interface interrupt.
+- clocks		: Reference to the clock entry.
+- local-mac-address	: Shall be ethernet mac address.
+- max-frame-size	: Shall be maximum ethernet frame size.
+- devid			: Shall be ethernet interface number.
+- phyid			: Shall be ethernet MII phy address.
+- phy-mode		: Shall be ethernet MII mode.
+
+Optional properties:
+- status		: Shall be "ok" if enabled or "disabled" if disabled.
+			  Default is "ok".
+
+Example:
+	eth8clk: eth8clk {
+		compatible = "apm,xgene-device-clock";
+		clock-names = "eth8clk";
+		status = "ok";
+	};
+
+	menet: ethernet@17020000 {
+		compatible = "apm,xgene-enet";
+		status = "disabled";
+		reg = <0x0 0x17020000 0x0 0x30>,
+		      <0x0 0x17020000 0x0 0x10000>,
+		      <0x0 0x17020000 0x0 0x20>;
+		slave-name = "RGMII";
+		interrupts = <0x0 0x38 0x4>,
+			     <0x0 0x39 0x4>,
+			     <0x0 0x3a 0x4>;
+		clocks = <&eth8clk 0>;
+		local-mac-address = <0x0 0x11 0x3a 0x8a 0x5a 0x78>;
+		max-frame-size = <0x233a>;
+		devid = <8>;
+		phyid = <3>;
+		phy-mode = "rgmii";
+	};
+
+/* Board-specific peripheral configurations */
+aliases {
+	ethernet0 = &menet;
+};
+
+&menet {
+        status = "ok";
+};
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
  2013-12-21  3:42 ` [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation Iyappan Subramanian
@ 2013-12-21  3:42 ` Iyappan Subramanian
  2014-01-24 17:01   ` Mark Salter
  2013-12-21  3:42 ` [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver Iyappan Subramanian
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

Device tree files for APM X-Gene SoC Ethernet.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
 arch/arm64/boot/dts/apm-mustang.dts |    8 ++++++++
 arch/arm64/boot/dts/apm-storm.dtsi  |   19 +++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
index 1247ca1..ccb2771 100644
--- a/arch/arm64/boot/dts/apm-mustang.dts
+++ b/arch/arm64/boot/dts/apm-mustang.dts
@@ -17,6 +17,10 @@
 	model = "APM X-Gene Mustang board";
 	compatible = "apm,mustang", "apm,xgene-storm";
 
+        aliases {
+                ethernet0 = &menet;
+        };
+
 	chosen { };
 
 	memory {
@@ -24,3 +28,7 @@
 		reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
 	};
 };
+
+&menet {
+        status = "ok";
+};
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index f64f946..9c7b8cd 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -204,5 +204,24 @@
 			#clock-cells = <1>;
 			clocks = <&qmlclk 0>;
 		};
+
+		menet: ethernet@17020000 {
+			compatible = "apm,xgene-enet";
+			status = "disabled";
+			reg = <0x0 0x17020000 0x0 0x30>,
+			      <0x0 0x17020000 0x0 0x10000>,
+			      <0x0 0x17020000 0x0 0x20>;
+			slave-name = "RGMII";
+			interrupts = <0x0 0x38 0x4>,
+				     <0x0 0x39 0x4>,
+				     <0x0 0x3a 0x4>;
+			#clock-cells = <1>;
+			clocks = <&eth8clk 0>;
+			local-mac-address = <0x0 0x11 0x3a 0x8a 0x5a 0x78>;
+			max-frame-size = <0x233a>;
+			devid = <8>;
+			phyid = <3>;
+			phy-mode = "rgmii";
+		};
 	};
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
  2013-12-21  3:42 ` [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation Iyappan Subramanian
  2013-12-21  3:42 ` [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes Iyappan Subramanian
@ 2013-12-21  3:42 ` Iyappan Subramanian
  2013-12-21 21:11   ` Greg KH
  2013-12-21  3:42 ` [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling Iyappan Subramanian
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

Ethernet base device driver for APM X-Gene SoC.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
 MAINTAINERS                                        |    7 +
 drivers/net/ethernet/Kconfig                       |    1 +
 drivers/net/ethernet/Makefile                      |    1 +
 drivers/net/ethernet/apm/Kconfig                   |    1 +
 drivers/net/ethernet/apm/Makefile                  |    5 +
 drivers/net/ethernet/apm/xgene/Kconfig             |   10 +
 drivers/net/ethernet/apm/xgene/Makefile            |   10 +
 drivers/net/ethernet/apm/xgene/xgene_enet_common.c |  497 ++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_common.h |  450 ++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h    |  162 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_mac.c    |  520 +++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   | 1581 ++++++++++++++++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  172 +++
 13 files changed, 3417 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/Kconfig
 create mode 100644 drivers/net/ethernet/apm/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_common.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_common.h
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.c
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 920cae8..01340e5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -672,6 +672,13 @@ S:	Maintained
 F:	drivers/misc/xgene/
 F:	include/misc/xgene/xgene_qmtm.h
 
+APPLIEDMICRO (APM) X-GENE SOC ETHERNET DRIVER
+M:	Keyur Chudgar <kchudgar@apm.com>
+M:	Iyappan Subramanian <isubramanian@apm.com>
+M:	Ravi Patel <rapatel@apm.com>
+S:	Maintained
+F:	drivers/net/ethernet/apm/
+
 APTINA CAMERA SENSOR PLL
 M:	Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 506b024..f0c4315 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -17,6 +17,7 @@ config MDIO
 config SUNGEM_PHY
 	tristate
 
+source "drivers/net/ethernet/apm/Kconfig"
 source "drivers/net/ethernet/3com/Kconfig"
 source "drivers/net/ethernet/adaptec/Kconfig"
 source "drivers/net/ethernet/aeroflex/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index c0b8789..bc0d4a5 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_GRETH) += aeroflex/
 obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
 obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_XGENE) += apm/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
 obj-$(CONFIG_NET_VENDOR_ARC) += arc/
 obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
new file mode 100644
index 0000000..ec63d70
--- /dev/null
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -0,0 +1 @@
+source "drivers/net/ethernet/apm/xgene/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile b/drivers/net/ethernet/apm/Makefile
new file mode 100644
index 0000000..65ce32a
--- /dev/null
+++ b/drivers/net/ethernet/apm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for APM X-GENE Ethernet driver.
+#
+
+obj-$(CONFIG_NET_XGENE) += xgene/
diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
new file mode 100644
index 0000000..c6ac5f9
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Kconfig
@@ -0,0 +1,10 @@
+config NET_XGENE
+	tristate "APM X-Gene Ethernet Driver"
+	depends on XGENE_QMTM
+	select PHYLIB
+	default y
+	help
+	  This is the Ethernet driver for APM X-Gene SoC.
+
+	  To compile this driver as a module, choose M here. This module will
+	  be called xgene_enet.
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
new file mode 100644
index 0000000..16dfc6c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for APM X-GENE Ethernet driver.
+#
+
+xgene-enet-objs := \
+		xgene_enet_common.o	\
+		xgene_enet_mac.o	\
+		xgene_enet_main.o
+
+obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_common.c b/drivers/net/ethernet/apm/xgene/xgene_enet_common.c
new file mode 100644
index 0000000..279f3cd
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_common.c
@@ -0,0 +1,497 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_common.h"
+#include "xgene_enet_csr.h"
+
+/* Indirect Address - read/write commands */
+#define PHY_ADDR_WR(src)		(((u32)(src) < 8) & 0x00001f00)
+#define REG_ADDR_WR(src)		(((u32)(src)) & 0x0000001f)
+
+int xgene_enet_wr(struct xgene_enet_priv *priv, u8 block_id,
+		  u32 reg_offset, u32 value)
+{
+	u32 cmd_done;
+	u32 indirect = 0;
+	int wait;
+	void *addr_reg_offst, *cmd_reg_offst, *wr_reg_offst;
+	void *cmd_done_reg_offst;
+
+	switch (block_id) {
+	case BLOCK_ETH_CSR:
+		addr_reg_offst = priv->eth_csr_addr_v + reg_offset;
+		pr_debug("ETH CSR write\n");
+		break;
+
+	case BLOCK_ETH_MDIO_CSR:
+		addr_reg_offst = priv->vmii_base + reg_offset
+		    + BLOCK_ETH_CSR_OFFSET;
+		pr_debug("BLOCK_ETH_MDIO_CSR write 0x%p\n", addr_reg_offst);
+		break;
+
+	case BLOCK_ETH_CLE:
+		addr_reg_offst = priv->eth_cle_addr_v + reg_offset;
+		pr_debug("ETH CLE write\n");
+		break;
+
+	case BLOCK_ETH_QMI:
+		addr_reg_offst = priv->eth_qmi_addr_v + reg_offset;
+		pr_debug("ETH QMI write\n");
+		break;
+
+	case BLOCK_ETH_SDS_CSR:
+		addr_reg_offst = priv->eth_sds_csr_addr_v + reg_offset;
+		pr_debug("ETH SDS CSR write\n");
+		break;
+
+	case BLOCK_ETH_CLKRST_CSR:
+		addr_reg_offst = priv->eth_clkrst_csr_addr_v + reg_offset;
+		pr_debug("ETH CLKRST CSR write\n");
+		break;
+
+	case BLOCK_ETH_DIAG_CSR:
+		addr_reg_offst = priv->eth_diag_csr_addr_v + reg_offset;
+		pr_debug("ETH DIAG CSR write\n");
+		break;
+
+	case BLOCK_MCX_MAC:
+	case BLOCK_ETH_INTPHY:
+		addr_reg_offst = priv->mcx_mac_addr_v + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->mcx_mac_addr_v + MAC_COMMAND_REG_OFFSET;
+		wr_reg_offst = priv->mcx_mac_addr_v + MAC_WRITE_REG_OFFSET;
+		cmd_done_reg_offst = priv->mcx_mac_addr_v
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX MAC/Internal PHY write\n");
+		break;
+
+	case BLOCK_ETH_EXTPHY:
+		addr_reg_offst = priv->vmii_base + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->vmii_base + MAC_COMMAND_REG_OFFSET;
+		wr_reg_offst = priv->vmii_base + MAC_WRITE_REG_OFFSET;
+		cmd_done_reg_offst = priv->vmii_base
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX MAC/External PHY write\n");
+		break;
+
+	case BLOCK_MCX_STATS:
+		addr_reg_offst = priv->mcx_stats_addr_v + STAT_ADDR_REG_OFFSET;
+		cmd_reg_offst =
+		    priv->mcx_stats_addr_v + STAT_COMMAND_REG_OFFSET;
+		wr_reg_offst = priv->mcx_stats_addr_v + STAT_WRITE_REG_OFFSET;
+		cmd_done_reg_offst = priv->mcx_stats_addr_v
+		    + STAT_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX STATS write\n");
+		break;
+
+	case BLOCK_MCX_MAC_CSR:
+		addr_reg_offst = priv->mcx_mac_csr_addr_v + reg_offset;
+		pr_debug("MCX MAC CSR write\n");
+		break;
+
+	case BLOCK_SATA_ENET_CSR:
+		addr_reg_offst = priv->sata_enet_csr_addr_v + reg_offset;
+		pr_debug("SATA ENET CSR write\n");
+		break;
+
+	case BLOCK_AXG_MAC:
+		addr_reg_offst = priv->axg_mac_addr_v + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->axg_mac_addr_v + MAC_COMMAND_REG_OFFSET;
+		wr_reg_offst = priv->axg_mac_addr_v + MAC_WRITE_REG_OFFSET;
+		cmd_done_reg_offst = priv->axg_mac_addr_v
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("AXG MAC write\n");
+		break;
+
+	case BLOCK_AXG_STATS:
+		addr_reg_offst = priv->axg_stats_addr_v + STAT_ADDR_REG_OFFSET;
+		cmd_reg_offst =
+		    priv->axg_stats_addr_v + STAT_COMMAND_REG_OFFSET;
+		wr_reg_offst = priv->axg_stats_addr_v + STAT_WRITE_REG_OFFSET;
+		cmd_done_reg_offst = priv->axg_stats_addr_v
+		    + STAT_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("AXG STATS write\n");
+		break;
+
+	case BLOCK_AXG_MAC_CSR:
+		addr_reg_offst = priv->axg_mac_csr_addr_v + reg_offset;
+		pr_debug("AXG MAC CSR write\n");
+		break;
+
+	case BLOCK_XGENET_PCS:
+		addr_reg_offst = priv->xgenet_pcs_addr_v + reg_offset;
+		pr_debug("XGENET PCS write\n");
+		break;
+
+	case BLOCK_XGENET_MDIO_CSR:
+		addr_reg_offst = priv->xgenet_mdio_csr_addr_v + reg_offset;
+		pr_debug("XGENET MDIO CSR write\n");
+		break;
+
+	default:
+		pr_err("Invalid blockid in write reg: %d\n", block_id);
+		return -1;
+	}
+
+	if (indirect) {
+		xgene_enet_wr32(addr_reg_offst, reg_offset);
+		xgene_enet_wr32(wr_reg_offst, value);
+		xgene_enet_wr32(cmd_reg_offst, XGENE_ENET_WR_CMD);
+		pr_debug("Indirect write: addr: 0x%X, value: 0x%X\n",
+			 reg_offset, value);
+
+		/* wait upto 5 us for completion */
+		wait = 5;
+		do {
+			xgene_enet_rd32(cmd_done_reg_offst, &cmd_done);
+			usleep_range(1, 2);
+		} while (--wait && !cmd_done);
+		if (!wait) {
+			pr_err("Write failed for blk: %d\n", block_id);
+			BUG();
+		}
+
+		xgene_enet_wr32(cmd_reg_offst, 0);
+	} else {
+		xgene_enet_wr32(addr_reg_offst, value);
+		pr_debug("Direct write addr: 0x%p, value: 0x%X\n",
+			 addr_reg_offst, value);
+	}
+
+	return 0;
+}
+
+int xgene_enet_rd(struct xgene_enet_priv *priv, u8 block_id,
+		  u32 reg_offset, u32 *value)
+{
+	u32 cmd_done;
+	u32 indirect = 0;
+	int wait;
+	void *addr_reg_offst, *cmd_reg_offst, *rd_reg_offst;
+	void *cmd_done_reg_offst;
+
+	switch (block_id) {
+	case BLOCK_ETH_CSR:
+		addr_reg_offst = priv->eth_csr_addr_v + reg_offset;
+		pr_debug("ETH CSR read\n");
+		break;
+
+	case BLOCK_ETH_MDIO_CSR:
+		addr_reg_offst = priv->vmii_base + reg_offset
+		    + BLOCK_ETH_CSR_OFFSET;
+		pr_debug("BLOCK_ETH_MDIO_CSR read 0x%p\n", addr_reg_offst);
+		break;
+
+	case BLOCK_ETH_CLE:
+		addr_reg_offst = priv->eth_cle_addr_v + reg_offset;
+		pr_debug("ETH CLE read\n");
+		break;
+
+	case BLOCK_ETH_QMI:
+		addr_reg_offst = priv->eth_qmi_addr_v + reg_offset;
+		pr_debug("ETH QMI read\n");
+		break;
+
+	case BLOCK_ETH_SDS_CSR:
+		addr_reg_offst = priv->eth_sds_csr_addr_v + reg_offset;
+		pr_debug("ETH SDS CSR read\n");
+		break;
+
+	case BLOCK_ETH_CLKRST_CSR:
+		addr_reg_offst = priv->eth_clkrst_csr_addr_v + reg_offset;
+		pr_debug("ETH CLKRST CSR read\n");
+		break;
+
+	case BLOCK_ETH_DIAG_CSR:
+		addr_reg_offst = priv->eth_diag_csr_addr_v + reg_offset;
+		pr_debug("ETH DIAG CSR read\n");
+		break;
+
+	case BLOCK_MCX_MAC:
+	case BLOCK_ETH_INTPHY:
+		addr_reg_offst = priv->mcx_mac_addr_v + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->mcx_mac_addr_v + MAC_COMMAND_REG_OFFSET;
+		rd_reg_offst = priv->mcx_mac_addr_v + MAC_READ_REG_OFFSET;
+		cmd_done_reg_offst = priv->mcx_mac_addr_v
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX MAC/Internal PHY read\n");
+		break;
+
+	case BLOCK_ETH_EXTPHY:
+		addr_reg_offst = priv->vmii_base + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->vmii_base + MAC_COMMAND_REG_OFFSET;
+		rd_reg_offst = priv->vmii_base + MAC_READ_REG_OFFSET;
+		cmd_done_reg_offst = priv->vmii_base
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX MAC/External PHY read\n");
+		break;
+
+	case BLOCK_MCX_STATS:
+		addr_reg_offst = priv->mcx_stats_addr_v + STAT_ADDR_REG_OFFSET;
+		cmd_reg_offst =
+		    priv->mcx_stats_addr_v + STAT_COMMAND_REG_OFFSET;
+		rd_reg_offst = priv->mcx_stats_addr_v + STAT_READ_REG_OFFSET;
+		cmd_done_reg_offst = priv->mcx_stats_addr_v
+		    + STAT_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("MCX STATS read\n");
+		break;
+
+	case BLOCK_MCX_MAC_CSR:
+		addr_reg_offst = priv->mcx_mac_csr_addr_v + reg_offset;
+		pr_debug("MCX MAC CSR read\n");
+		break;
+
+	case BLOCK_SATA_ENET_CSR:
+		addr_reg_offst = priv->sata_enet_csr_addr_v + reg_offset;
+		pr_debug("SATA ENET CSR read\n");
+		break;
+
+	case BLOCK_AXG_MAC:
+		addr_reg_offst = priv->axg_mac_addr_v + MAC_ADDR_REG_OFFSET;
+		cmd_reg_offst = priv->axg_mac_addr_v + MAC_COMMAND_REG_OFFSET;
+		rd_reg_offst = priv->axg_mac_addr_v + MAC_READ_REG_OFFSET;
+		cmd_done_reg_offst = priv->axg_mac_addr_v
+		    + MAC_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("AXG MAC read\n");
+		break;
+
+	case BLOCK_AXG_STATS:
+		addr_reg_offst = priv->axg_stats_addr_v + STAT_ADDR_REG_OFFSET;
+		cmd_reg_offst =
+		    priv->axg_stats_addr_v + STAT_COMMAND_REG_OFFSET;
+		rd_reg_offst = priv->axg_stats_addr_v + STAT_READ_REG_OFFSET;
+		cmd_done_reg_offst = priv->axg_stats_addr_v
+		    + STAT_COMMAND_DONE_REG_OFFSET;
+		indirect = 1;
+		pr_debug("AXG STATS read\n");
+		break;
+
+	case BLOCK_AXG_MAC_CSR:
+		addr_reg_offst = priv->axg_mac_csr_addr_v + reg_offset;
+		pr_debug("AXG MAC CSR read\n");
+		break;
+
+	case BLOCK_XGENET_PCS:
+		addr_reg_offst = priv->xgenet_pcs_addr_v + reg_offset;
+		pr_debug("XGENET PCS read\n");
+		break;
+
+	case BLOCK_XGENET_MDIO_CSR:
+		addr_reg_offst = priv->xgenet_mdio_csr_addr_v + reg_offset;
+		pr_debug("XGENET MDIO CSR read\n");
+		break;
+
+	default:
+		pr_err("Invalid blockid in read reg: %d\n", block_id);
+		return -1;
+	}
+
+	if (indirect) {
+		xgene_enet_wr32(addr_reg_offst, reg_offset);
+		xgene_enet_wr32(cmd_reg_offst, XGENE_ENET_RD_CMD);
+		pr_debug("Indirect read: addr: 0x%X\n", reg_offset);
+
+		/* wait upto 5 us for completion */
+		wait = 5;
+		do {
+			xgene_enet_rd32(cmd_done_reg_offst, &cmd_done);
+		} while (--wait && !cmd_done);
+		if (!wait) {
+			pr_err("Read failed for blk: %d\n", block_id);
+			BUG();
+		}
+
+		xgene_enet_rd32(rd_reg_offst, value);
+		pr_debug("Indirect read value: 0x%X\n", *value);
+
+		xgene_enet_wr32(cmd_reg_offst, 0);
+	} else {
+		xgene_enet_rd32(addr_reg_offst, value);
+		pr_debug("Direct read addr: 0x%p, value: 0x%X\n",
+			 addr_reg_offst, *value);
+	}
+
+	return 0;
+}
+
+void xgene_genericmiiphy_write(struct xgene_enet_priv *priv, u8 phy_id,
+			       unsigned char reg, u32 data)
+{
+	u32 value;
+	int wait;
+	u32 blockid = BLOCK_ETH_EXTPHY;
+
+	if (priv->port == MENET)
+		phy_id = priv->phy_addr;
+
+	/* All PHYs lie on MII bus of Port0 MAC due to this
+	 * each port should access its PHY through Port0 MAC.
+	 * Hence we allow access to PHY_ID associated with this
+	 * port only.
+	 */
+
+	/* Write PHY number and address in MII Mgmt Address */
+	value = PHY_ADDR_WR(phy_id) | REG_ADDR_WR(reg);
+	pr_debug("Write MII_MGMT_ADDRESS phy_id=0x%x, reg=0x%x, value=0x%x\n",
+		 phy_id, reg << 2, value);
+	xgene_enet_wr(priv, blockid, MII_MGMT_ADDRESS_ADDR, value);
+
+	/* Write 16 bit data to MII MGMT CONTROL */
+	value = PHY_CONTROL_WR(data);
+	pr_debug("Write MII_MGMT_CONTROL phy_id=0x%x, reg=0x%x, value=0x%x\n",
+		 phy_id, reg << 2, value);
+	xgene_enet_wr(priv, blockid, MII_MGMT_CONTROL_ADDR, value);
+
+	/* wait upto 20 us for completion */
+	wait = 20;
+	do {
+		xgene_enet_rd(priv, blockid, MII_MGMT_INDICATORS_ADDR, &value);
+		usleep_range(1, 2);
+	} while (--wait && (value & BUSY_MASK));
+	if (!wait)
+		pr_err("MII_MGMT write failed\n");
+}
+
+void xgene_genericmiiphy_read(struct xgene_enet_priv *priv, u8 phy_id,
+			      unsigned char reg, u32 *data)
+{
+	u32 value;
+	u32 blockid = BLOCK_ETH_EXTPHY;
+	int wait;
+
+	if (priv->port == MENET)
+		phy_id = priv->phy_addr;
+
+	/* All PHYs lie on MII bus of Port0 MAC due to this
+	 * each port should access its PHY through Port0 MAC.
+	 * Hence we allow access to PHY_ID associated with this
+	 * port only.
+	 */
+
+	/* Write PHY number and address in MII Mgmt Address */
+	value = PHY_ADDR_WR(phy_id) | REG_ADDR_WR(reg);
+	pr_debug("Write MII_MGMT_ADDR phy_id=0x%x, reg=0x%x, value=0x%x\n",
+		 phy_id, reg << 2, value);
+	xgene_enet_wr(priv, blockid, MII_MGMT_ADDRESS_ADDR, value);
+
+	/* Write read command */
+	xgene_enet_wr(priv, blockid, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+
+	/* wait upto 20 us for completion */
+	wait = 20;
+	do {
+		xgene_enet_rd(priv, blockid, MII_MGMT_INDICATORS_ADDR, &value);
+		if (!(value & BUSY_MASK))
+			break;
+		usleep_range(1, 2);
+	} while (--wait && (value & BUSY_MASK));
+
+	xgene_enet_rd(priv, blockid, MII_MGMT_STATUS_ADDR, data);
+
+	/* reset mii_mgmt_command register */
+	xgene_enet_wr(priv, blockid, MII_MGMT_COMMAND_ADDR, 0);
+}
+
+inline void xgene_enet_port_reset(struct xgene_enet_priv *priv)
+{
+	if (priv->port_reset)
+		priv->port_reset(priv);
+}
+
+inline void xgene_enet_mac_reset(struct xgene_enet_priv *priv)
+{
+	if (priv->mac_reset)
+		priv->mac_reset(priv);
+}
+
+inline int xgene_enet_mac_init(struct xgene_enet_priv *priv,
+			       unsigned char *dev_addr, int speed, int mtu,
+			       int crc)
+{
+	int rc = 0;
+	if (priv->mac_init)
+		rc = priv->mac_init(priv, dev_addr, speed, mtu, crc);
+	return rc;
+}
+
+inline void xgene_enet_mac_tx_state(struct xgene_enet_priv *priv, u32 enable)
+{
+	if (priv->mac_tx_state)
+		priv->mac_tx_state(priv, enable);
+}
+
+inline void xgene_enet_mac_rx_state(struct xgene_enet_priv *priv, u32 enable)
+{
+	if (priv->mac_rx_state)
+		priv->mac_rx_state(priv, enable);
+}
+
+inline void xgene_enet_mac_change_mtu(struct xgene_enet_priv *priv, u32 new_mtu)
+{
+	if (priv->mac_change_mtu)
+		priv->mac_change_mtu(priv, new_mtu);
+}
+
+inline void xgene_enet_mac_set_ipg(struct xgene_enet_priv *priv, u16 ipg)
+{
+	if (priv->mac_set_ipg)
+		priv->mac_set_ipg(priv, ipg);
+}
+
+inline void xgene_enet_get_stats(struct xgene_enet_priv *priv,
+				 struct xgene_enet_detailed_stats *stats)
+{
+	if (priv->get_stats)
+		priv->get_stats(priv, stats);
+}
+
+inline void xgene_enet_set_mac_addr(struct xgene_enet_priv *priv,
+				    unsigned char *dev_addr)
+{
+	if (priv->set_mac_addr)
+		priv->set_mac_addr(priv, dev_addr);
+}
+
+inline void xgene_enet_cle_bypass(struct xgene_enet_priv *priv,
+				  u32 dstqid, u32 fpsel)
+{
+	if (priv->cle_bypass)
+		priv->cle_bypass(priv, dstqid, fpsel);
+}
+
+inline void xgene_enet_tx_offload(struct xgene_enet_priv *priv,
+				  u32 command, u32 value)
+{
+	if (priv->tx_offload)
+		priv->tx_offload(priv, command, value);
+}
+
+inline void xgene_enet_port_shutdown(struct xgene_enet_priv *priv)
+{
+	if (priv->port_shutdown)
+		priv->port_shutdown(priv);
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_common.h b/drivers/net/ethernet/apm/xgene/xgene_enet_common.h
new file mode 100644
index 0000000..4b0bfad
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_common.h
@@ -0,0 +1,450 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel rapatel@apm.com>
+ *		Iyappan Subramanian isubramanian@apm.com>
+ *		Fushen Chen fchen@apm.com>
+ *		Keyur Chudgar kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __XGENE_ENET_COMMON_H__
+#define __XGENE_ENET_COMMON_H__
+
+#include <misc/xgene/xgene_qmtm.h>
+#define MAX_LOOP_POLL_CNT	10
+
+#ifndef UDP_HDR_SIZE
+#define UDP_HDR_SIZE		2
+#endif
+
+/* Ethernet & XGENET port ids */
+enum eth_port_ids {
+	ENET_0 = 0,
+	ENET_1,
+	ENET_2,
+	ENET_3,
+	XGENET_0,
+	XGENET_1,
+	XGENET_2,
+	XGENET_3,
+	MENET,
+	MAX_ENET_PORTS
+};
+
+/* TSO Parameters */
+#define TSO_ENABLE		1
+#define TSO_ENABLE_MASK		1
+#define TSO_CHKSUM_ENABLE	1
+#define TSO_INS_CRC_ENABLE	1
+#define TSO_IPPROTO_TCP		1
+#define TSO_IPPROTO_UDP		0
+#define TSO_IP_HLEN_MASK	0X3F
+#define TSO_TCP_HLEN_MASK	0X3F
+#define TSO_ETH_HLEN_MASK	0XFF
+#define TSO_MSS_MASK		0X3	/* 2b */
+#define DEFAULT_TCP_MSS		1448
+
+enum {
+	XGENE_ENET_MSS0 = 0,
+	XGENE_ENET_MSS1,
+	XGENE_ENET_MSS2,
+	XGENE_ENET_MSS3,
+	XGENE_ENET_TSO_CFG,
+	XGENE_ENET_INSERT_VLAN
+};
+
+/* TYPE_SEL for Ethernt egress message */
+#define TYPE_SEL_WORK_MSG	1U
+
+/* Blocks for defined regions */
+enum {
+	BLOCK_ETH_CSR = 1,
+	BLOCK_ETH_CLE,
+	BLOCK_ETH_QMI,
+	BLOCK_ETH_SDS_CSR,
+	BLOCK_ETH_CLKRST_CSR,
+	BLOCK_ETH_DIAG_CSR,
+	BLOCK_ETH_MDIO_CSR,
+	BLOCK_ETH_INTPHY,
+	BLOCK_ETH_EXTPHY,
+	BLOCK_MCX_MAC,
+	BLOCK_MCX_STATS,
+	BLOCK_MCX_MAC_CSR,
+	BLOCK_SATA_ENET_CSR,
+	BLOCK_AXG_MAC,
+	BLOCK_AXG_STATS,
+	BLOCK_AXG_MAC_CSR,
+	BLOCK_XGENET_PCS,
+	BLOCK_XGENET_MDIO_CSR,
+	BLOCK_ETH_MAX
+};
+
+/* Direct Address mode */
+#define BLOCK_ETH_CSR_OFFSET		0x2000
+#define BLOCK_ETH_CLE_OFFSET		0x6000
+#define BLOCK_ETH_QMI_OFFSET		0x9000
+#define BLOCK_ETH_SDS_CSR_OFFSET	0xA000
+#define BLOCK_ETH_CLKRST_CSR_OFFSET	0xC000
+#define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000
+
+/* Indirect & Direct  Address mode for MCX_MAC and AXG_MAC */
+#define BLOCK_ETH_MAC_OFFSET		0x0000
+#define BLOCK_ETH_STATS_OFFSET		0x0014
+#define BLOCK_ETH_MAC_CSR_OFFSET	0x2800
+
+#define BLOCK_SATA_ENET_CSR_OFFSET	0x7000
+
+/* Constants for indirect registers */
+#define MAC_ADDR_REG_OFFSET		0
+#define MAC_COMMAND_REG_OFFSET		4
+#define MAC_WRITE_REG_OFFSET		8
+#define MAC_READ_REG_OFFSET		12
+#define MAC_COMMAND_DONE_REG_OFFSET	16
+
+#define STAT_ADDR_REG_OFFSET		0
+#define STAT_COMMAND_REG_OFFSET		4
+#define STAT_WRITE_REG_OFFSET		8
+#define STAT_READ_REG_OFFSET		12
+#define STAT_COMMAND_DONE_REG_OFFSET	16
+
+/* Address PE_MCXMAC  Registers */
+#define MII_MGMT_COMMAND_ADDR                                        0x00000024
+#define MII_MGMT_ADDRESS_ADDR                                        0x00000028
+#define MII_MGMT_CONTROL_ADDR                                        0x0000002c
+#define MII_MGMT_STATUS_ADDR                                         0x00000030
+#define MII_MGMT_INDICATORS_ADDR                                     0x00000034
+
+#define INT_PHY_ADDR	0x1E
+
+#define BUSY_MASK                                                    0x00000001
+#define READ_CYCLE_MASK                                              0x00000001
+#define PHY_CONTROL_WR(src)                         (((u32)(src)) & 0x0000ffff)
+
+#define HW_MTU(m) ((m) + 12 + 2 + 4 /* MAC + CRC */)
+
+enum xgene_enum_speed {
+	XGENE_ENET_SPEED_0 = 0xffff,
+	XGENE_ENET_SPEED_10 = 10,
+	XGENE_ENET_SPEED_100 = 100,
+	XGENE_ENET_SPEED_1000 = 1000,
+	XGENE_ENET_SPEED_10000 = 10000
+};
+
+enum xgene_enet_mode {
+	HALF_DUPLEX = 1,
+	FULL_DUPLEX = 2
+};
+
+enum xgene_enet_phy_mode {
+	PHY_MODE_NONE,
+	PHY_MODE_RGMII,
+	PHY_MODE_SGMII,
+	PHY_MODE_XGMII
+};
+
+enum xgene_enet_cmd {
+	XGENE_ENET_WR_CMD = 0x80000000,
+	XGENE_ENET_RD_CMD = 0x40000000
+};
+
+#define CMU 0
+
+/* ===== MII definitions ===== */
+
+#define MII_CRC_LEN		0x4	/* CRC length in bytes */
+#define MII_ETH_MAX_PCK_SZ      (ETHERMTU + SIZEOF_ETHERHEADER          \
+				 + MII_CRC_LEN)
+#define MII_MAX_PHY_NUM		0x20	/* max number of attached PHYs */
+#define MII_MAX_REG_NUM         0x20	/* max number of registers */
+
+#define MII_CTRL_REG		0x0	/* Control Register */
+#define MII_STAT_REG		0x1	/* Status Register */
+#define MII_PHY_ID1_REG		0x2	/* PHY identifier 1 Register */
+#define MII_PHY_ID2_REG		0x3	/* PHY identifier 2 Register */
+#define MII_AN_ADS_REG		0x4	/* Auto-Negotiation       */
+					/* Advertisement Register */
+#define MII_AN_PRTN_REG		0x5	/* Auto-Negotiation         */
+					/* partner ability Register */
+#define MII_AN_EXP_REG		0x6	/* Auto-Negotiation   */
+					/* Expansion Register */
+#define MII_AN_NEXT_REG		0x7	/* Auto-Negotiation            */
+					/* next-page transmit Register */
+
+#define MII_AN_PRTN_NEXT_REG	0x8	/* Link partner received next page */
+#define MII_MASSLA_CTRL_REG	0x9	/* MATER-SLAVE control register */
+#define MII_MASSLA_STAT_REG	0xa	/* MATER-SLAVE status register */
+#define MII_EXT_STAT_REG	0xf	/* Extented status register */
+
+/* MII control register bit  */
+#define MII_CR_1000		0x0040	/* 1 = 1000mb when
+					* MII_CR_100 is also 1
+					*/
+#define MII_CR_COLL_TEST	0x0080	/* collision test */
+#define MII_CR_FDX		0x0100	/* FDX =1, half duplex =0 */
+#define MII_CR_RESTART		0x0200	/* restart auto negotiation */
+#define MII_CR_ISOLATE		0x0400	/* isolate PHY from MII */
+#define MII_CR_POWER_DOWN	0x0800	/* power down */
+#define MII_CR_AUTO_EN		0x1000	/* auto-negotiation enable */
+#define MII_CR_100		0x2000	/* 0 = 10mb, 1 = 100mb */
+#define MII_CR_LOOPBACK		0x4000	/* 0 = normal, 1 = loopback */
+#define MII_CR_RESET		0x8000	/* 0 = normal, 1 = PHY reset */
+#define MII_CR_NORM_EN		0x0000	/* just enable the PHY */
+#define MII_CR_DEF_0_MASK       0xca7f	/* they must return zero */
+#define MII_CR_RES_MASK		0x003f	/* reserved bits,return zero */
+
+/* MII Status register bit definitions */
+#define MII_SR_LINK_STATUS	0x0004	/* link Status -- 1 = link */
+#define MII_SR_AUTO_SEL		0x0008	/* auto speed select capable */
+#define MII_SR_REMOTE_FAULT     0x0010	/* Remote fault detect */
+#define MII_SR_AUTO_NEG         0x0020	/* auto negotiation complete */
+#define MII_SR_EXT_STS		0x0100	/* extended sts in reg 15 */
+#define MII_SR_T2_HALF_DPX	0x0200	/* 100baseT2 HD capable */
+#define MII_SR_T2_FULL_DPX	0x0400	/* 100baseT2 FD capable */
+#define MII_SR_10T_HALF_DPX     0x0800	/* 10BaseT HD capable */
+#define MII_SR_10T_FULL_DPX     0x1000	/* 10BaseT FD capable */
+#define MII_SR_TX_HALF_DPX      0x2000	/* TX HD capable */
+#define MII_SR_TX_FULL_DPX      0x4000	/* TX FD capable */
+#define MII_SR_T4               0x8000	/* T4 capable */
+#define MII_SR_ABIL_MASK        0xff80	/* abilities mask */
+#define MII_SR_EXT_CAP          0x0001	/* extended capabilities */
+#define MII_SR_SPEED_SEL_MASK	0xf800	/* Mask to extract just speed
+					 * capabilities  from status
+					 * register.
+					 */
+
+/* MII AN advertisement Register bit definition */
+#define MII_ANAR_10TX_HD        0x0020
+#define MII_ANAR_10TX_FD        0x0040
+#define MII_ANAR_100TX_HD       0x0080
+#define MII_ANAR_100TX_FD       0x0100
+#define MII_ANAR_100T_4         0x0200
+#define MII_ANAR_PAUSE          0x0400
+#define MII_ANAR_ASM_PAUSE      0x0800
+#define MII_ANAR_REMORT_FAULT   0x2000
+#define MII_ANAR_NEXT_PAGE      0x8000
+#define MII_ANAR_PAUSE_MASK     0x0c00
+
+/* MII Link Code word  bit definitions */
+#define MII_BP_FAULT	0x2000	/* remote fault */
+#define MII_BP_ACK	0x4000	/* acknowledge */
+#define MII_BP_NP	0x8000	/* nexp page is supported */
+
+/* MII Next Page bit definitions */
+#define MII_NP_TOGGLE	0x0800	/* toggle bit */
+#define MII_NP_ACK2	0x1000	/* acknowledge two */
+#define MII_NP_MSG	0x2000	/* message page */
+#define MII_NP_ACK1	0x4000	/* acknowledge one */
+#define MII_NP_NP	0x8000	/* nexp page will follow */
+
+/* MII Master-Slave Control register bit definition */
+#define MII_MASSLA_CTRL_1000T_HD    0x100
+#define MII_MASSLA_CTRL_1000T_FD    0x200
+#define MII_MASSLA_CTRL_PORT_TYPE   0x400
+#define MII_MASSLA_CTRL_CONFIG_VAL  0x800
+#define MII_MASSLA_CTRL_CONFIG_EN   0x1000
+
+/* MII Master-Slave Status register bit definition */
+#define MII_MASSLA_STAT_LP1000T_HD  0x400
+#define MII_MASSLA_STAT_LP1000T_FD  0x800
+#define MII_MASSLA_STAT_REMOTE_RCV  0x1000
+#define MII_MASSLA_STAT_LOCAL_RCV   0x2000
+#define MII_MASSLA_STAT_CONF_RES    0x4000
+#define MII_MASSLA_STAT_CONF_FAULT  0x8000
+
+/* these values may be used in the default phy mode field of the load
+ * string, since that is used to force the operating mode of the PHY
+ * in case any attempt to establish the link failed.
+ */
+
+#define PHY_10BASE_T            0x00	/* 10 Base-T */
+#define PHY_10BASE_T_FDX        0x01	/* 10 Base Tx, full duplex */
+#define PHY_100BASE_TX          0x02	/* 100 Base Tx */
+#define PHY_100BASE_TX_FDX      0x03	/* 100 Base TX, full duplex */
+#define PHY_100BASE_T4          0x04	/* 100 Base T4 */
+#define PHY_AN_ENABLE		0x05	/* re-enable auto-negotiation */
+
+#define MII_AN_TBL_MAX		20	/* max number of entries in the table */
+
+/* Realtek PHY definitions */
+#define PHY_SPEED_RES			3
+#define PHY_SPEED_1000			2
+#define PHY_SPEED_100			1
+#define PHY_SPEED_10			0
+#define RTL_PHYSR_ADR			0X11
+#define RTL_PHYSR_SPEED_RD(src)		(((src) & 0x0000C000) >> 14)
+#define RTL_PHYSR_LINK_RD(src)		(((src) & 0x00000400) >> 10)
+
+#define RTL_PHYSR_ADR           0X11
+
+/* LErr(3b) Decoding */
+enum xgene_enet_lerr {
+	ENET_NO_ERR = 0,	/* No Error */
+	ENET_AXI_WR_ERR = 1,	/* AXI write data error due to RSIF */
+	ENET_ING_CRC_ERR = 2,	/* Rx packet had CRC */
+	ENET_AXI_RD_ERR = 3,	/* AXI read data error when processing
+				 * a work message in TSIF
+				 */
+	ENET_LL_RD_ERR = 4,	/* AXI Link List read error when
+				 * processing a work message in TSIF
+				 */
+	ENET_ING_ERR = 5,	/* Rx packet had ingress processing error */
+	ENET_CHKSUM_ERR = 5,	/* Checksum error */
+	ENET_BAD_MSG_ERR = 6,	/* Bad message to subsytem */
+	ENET_MISC_ERR = 7,	/* Other ingress processing error */
+	ENET_MAC_TRUNC_ERR = 7,	/* MAX truncated */
+	ENET_MAC_LEN_ERR = 8,	/* Packet length error */
+	ENET_PKT_LESS64_ERR = 9,	/* MAC length lesser than 64B */
+	ENET_MAC_OVERRUN_ERR = 10,	/* FIFO overrun on ingress */
+	ENET_UNISEC_CHKSUM_ERR = 11,	/* Rx pacekt checksum error */
+	ENET_UNISEC_LEN_ERR = 12,	/* Rx pkt length mismatch QM message */
+	ENET_UNISEC_ICV_ERR = 13,	/* Rx pkt ICV error */
+	ENET_UNISEC_PROTO_ERR = 14,	/* Rx pkt protocol field mismatch */
+	ENET_FP_TIMEOUT_ERR = 15	/* Free pool buffer timeout */
+};
+
+/* Error TX/RX Statistics - maintained by software */
+struct xgene_mac_error_stats {
+	u64 rx_hw_errors;
+	u64 rx_hw_overrun;
+	u64 tx_dropped;
+};
+
+struct xgene_enet_rx_stats {
+	u32 rx_byte_count;	/* Receive Byte Counter */
+	u32 rx_packet_count;	/* Receive Packet Counter */
+	u32 rx_fcs_err_count;	/* Receive FCS Error Counter */
+	u32 rx_alignment_err_pkt_count;	/* Rx Alignment Err Packet Counter */
+	u32 rx_frm_len_err_pkt_count;	/* Rx Frame Len Err Packet Counter */
+	u32 rx_undersize_pkt_count;	/* Receive Undersize Packet Counter */
+	u32 rx_oversize_pkt_count;	/* Receive Oversize Packet Counter */
+	u32 rx_drop_pkt_count;	/* Receive Drop Packet Counter */
+};
+
+struct xgene_enet_tx_stats {
+	u32 tx_byte_count;	/* Tx Byte cnt */
+	u32 tx_pkt_count;	/* Tx pkt cnt */
+	u32 tx_drop_frm_count;	/* Tx Drop Frame cnt */
+	u32 tx_fcs_err_frm_count;	/* Tx FCS Error Frame cnt */
+	u32 tx_undersize_frm_count;	/* Tx Undersize Frame cnt */
+};
+
+struct xgene_enet_detailed_stats {
+	struct xgene_enet_rx_stats rx_stats;
+	struct xgene_enet_tx_stats tx_stats;
+	struct xgene_mac_error_stats estats;
+};
+
+/* Ethernet private structure */
+struct xgene_enet_priv {
+	void *eth_csr_addr_v;
+	void *eth_cle_addr_v;
+	void *eth_qmi_addr_v;
+	void *eth_sds_csr_addr_v;
+	void *eth_clkrst_csr_addr_v;
+	void *eth_diag_csr_addr_v;
+	void *mcx_mac_addr_v;
+	void *mcx_stats_addr_v;
+	void *mcx_mac_csr_addr_v;
+	void *sata_enet_csr_addr_v;
+	void *axg_mac_addr_v;
+	void *axg_stats_addr_v;
+	void *axg_mac_csr_addr_v;
+	void *xgenet_pcs_addr_v;
+	void *xgenet_mdio_csr_addr_v;
+
+	u64 paddr_base;		/* Base physical address of device */
+	void *vaddr_base;	/* Base Virtual address for the device */
+	u64 ppaddr_base;	/* Per port physical address of device */
+	void *vpaddr_base;	/* Per port Virtual address of device */
+	void *vmii_base;	/* Base MII Virtual address of device */
+
+	u32 phy_addr;		/* Virtual address for PHY */
+	u32 phy_mode;
+	u32 port;
+	u32 speed;		/* Forced Link Speed */
+	u32 link_status;
+	u32 crc;
+	u32 autoneg_set;
+	u32 mac_to_mac;		/* Tell traffic is MAC-to-MAC */
+	u32 desired_speed;	/* In case of MAC-to-MAC, no autoneg,
+				 * tell the desired speed to setup
+				 */
+	u32 phyless;		/* PHY stays away from board on
+				 * common server board design
+				 */
+	u32 force_serdes_reset;	/* Force analog reset till stable state */
+
+	/* Function pointers */
+	void (*port_reset) (struct xgene_enet_priv *priv);
+	int (*phy_autoneg_done) (struct xgene_enet_priv *priv);
+	void (*phy_link_mode) (struct xgene_enet_priv *priv,
+			       u32 *speed, u32 *state);
+	void (*mac_reset) (struct xgene_enet_priv *priv);
+	int (*mac_init) (struct xgene_enet_priv *priv,
+			 unsigned char *dev_addr, int speed, int mtu, int crc);
+	void (*mac_rx_state) (struct xgene_enet_priv *priv, u32 enable);
+	void (*mac_tx_state) (struct xgene_enet_priv *priv, u32 enable);
+	void (*mac_change_mtu) (struct xgene_enet_priv *priv, u32 new_mtu);
+	void (*mac_set_ipg) (struct xgene_enet_priv *priv, u16 new_ipg);
+	void (*get_stats) (struct xgene_enet_priv *priv,
+			   struct xgene_enet_detailed_stats *stats);
+	void (*set_mac_addr) (struct xgene_enet_priv *priv,
+			      unsigned char *dev_addr);
+	void (*cle_bypass) (struct xgene_enet_priv *priv, u32 dstqid,
+			    u32 fpsel);
+	void (*tx_offload) (struct xgene_enet_priv *priv, u32 command,
+			    u32 value);
+	void (*qmi_assoc) (struct xgene_enet_priv *priv);
+	void (*port_shutdown) (struct xgene_enet_priv *priv);
+};
+
+int xgene_enet_wr(struct xgene_enet_priv *priv, u8 block_id,
+		  u32 reg_offset, u32 value);
+
+int xgene_enet_rd(struct xgene_enet_priv *priv, u8 block_id,
+		  u32 reg_offset, u32 *value);
+
+void xgene_enet_port_reset(struct xgene_enet_priv *priv);
+
+/* This function resets the entire part of MAC and minimal init for phy access
+ * It will put both Transmit and Receive MAC Control block in reset
+ * and then init.
+ */
+void xgene_enet_mac_reset(struct xgene_enet_priv *priv);
+
+int xgene_enet_mac_init(struct xgene_enet_priv *priv, unsigned char *dev_addr,
+			int speed, int mtu, int crc);
+
+void xgene_enet_mac_rx_state(struct xgene_enet_priv *priv, u32 enable);
+void xgene_enet_mac_tx_state(struct xgene_enet_priv *priv, u32 enable);
+
+void xgene_enet_mac_change_mtu(struct xgene_enet_priv *priv, u32 new_mtu);
+void xgene_enet_mac_set_ipg(struct xgene_enet_priv *priv, u16 ipg);
+
+void xgene_enet_set_mac_addr(struct xgene_enet_priv *priv,
+			     unsigned char *dev_addr);
+
+void xgene_enet_cle_bypass(struct xgene_enet_priv *priv, u32 dstqid, u32 fpsel);
+
+void xgene_enet_tx_offload(struct xgene_enet_priv *priv,
+			   u32 command, u32 value);
+
+void xgene_enet_port_shutdown(struct xgene_enet_priv *priv);
+enum xgene_qmtm_qaccess xgene_enet_get_qacess(void);
+void xgene_genericmiiphy_read(struct xgene_enet_priv *priv, u8 phy_id,
+			      unsigned char reg, u32 *data);
+void xgene_genericmiiphy_write(struct xgene_enet_priv *priv, u8 phy_id,
+			       unsigned char reg, u32 data);
+
+void xgene_enet_get_stats(struct xgene_enet_priv *priv,
+			  struct xgene_enet_detailed_stats *detailed_stats);
+#endif /* __XGENE_ENET_COMMON_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
new file mode 100644
index 0000000..c6b49c9
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
@@ -0,0 +1,162 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __XGENE_ENET_CSR_H__
+#define __XGENE_ENET_CSR_H__
+
+#define ENET_SPARE_CFG_REG_ADDR                                      0x00000750
+#define RSIF_CONFIG_REG_ADDR                                         0x00000010
+#define RSIF_RAM_DBG_REG0_ADDR                                       0x00000048
+#define RGMII_REG_0_ADDR                                             0x000007e0
+#define CFG_LINK_AGGR_RESUME_0_ADDR                                  0x000007c8
+#define DEBUG_REG_ADDR                                               0x00000700
+#define CFG_BYPASS_ADDR                                              0x00000294
+#define CLE_BYPASS_REG0_0_ADDR                                       0x00000490
+#define CLE_BYPASS_REG1_0_ADDR                                       0x00000494
+#define CLE_BYPASS_REG8_0_ADDR                                       0x000004b0
+#define TSIF_MSS_REG0_0_ADDR                                         0x00000108
+#define TSIF_MSS_REG1_0_ADDR                                         0x00000110
+#define TSO_CFG_0_ADDR                                               0x00000314
+#define TSO_CFG_INSERT_VLAN_0_ADDR                                   0x0000031c
+#define CFG_RSIF_FPBUFF_TIMEOUT_EN_WR(src)      (((u32)(src)<<31) & 0x80000000)
+#define CFG_TSIF_MSS_SZ10_SET(dst, src) \
+	(((dst) & ~0x3fff0000) | (((u32)(src)<<16) & 0x3fff0000))
+#define CFG_TSIF_MSS_SZ00_SET(dst, src) \
+	(((dst) & ~0x00003fff) | (((u32)(src)) & 0x00003fff))
+#define CFG_TSIF_MSS_SZ20_SET(dst, src) \
+	(((dst) & ~0x00003fff) | (((u32)(src)) & 0x00003fff))
+#define CFG_TSIF_MSS_SZ30_SET(dst, src) \
+	(((dst) & ~0x3fff0000) | (((u32)(src)<<16) & 0x3fff0000))
+#define RESUME_TX_WR(src)                           (((u32)(src)) & 0x00000001)
+#define CFG_SPEED_1250_WR(src)                  (((u32)(src)<<24) & 0x01000000)
+#define CFG_TXCLK_MUXSEL0_WR(src)               (((u32)(src)<<29) & 0xe0000000)
+#define TX_PORT0_WR(src)                            (((u32)(src)) & 0x00000001)
+#define CFG_BYPASS_UNISEC_TX_WR(src)             (((u32)(src)<<2) & 0x00000004)
+#define CFG_BYPASS_UNISEC_RX_WR(src)             (((u32)(src)<<1) & 0x00000002)
+#define CFG_CLE_BYPASS_EN0_SET(dst, src) \
+	(((dst) & ~0x80000000) | (((u32)(src)<<31) & 0x80000000))
+#define CFG_CLE_IP_PROTOCOL0_SET(dst, src) \
+	(((dst) & ~0x00030000) | (((u32)(src)<<16) & 0x00030000))
+#define CFG_CLE_DSTQID0_SET(dst, src) \
+	(((dst) & ~0x00000fff) | (((u32)(src)) & 0x00000fff))
+#define CFG_CLE_FPSEL0_SET(dst, src) \
+	(((dst) & ~0x000f0000) | (((u32)(src)<<16) & 0x000f0000))
+#define CFG_CLE_HENQNUM0_SET(dst, src) \
+	(((dst) & ~0x0fff0000) | (((u32)(src)<<16) & 0x0fff0000))
+#define ICM_CONFIG0_REG_0_ADDR                                       0x00000400
+#define ICM_CONFIG2_REG_0_ADDR                                       0x00000410
+#define ECM_CONFIG0_REG_0_ADDR                                       0x00000500
+#define RX_DV_GATE_REG_0_ADDR                                        0x000005fc
+#define TX_DV_GATE_EN0_SET(dst, src) \
+	(((dst) & ~0x00000004) | (((u32)(src)<<2) & 0x00000004))
+#define RX_DV_GATE_EN0_SET(dst, src) \
+	(((dst) & ~0x00000002) | (((u32)(src)<<1) & 0x00000002))
+#define RESUME_RX0_SET(dst, src) \
+	(((dst) & ~0x00000001) | (((u32)(src)) & 0x00000001))
+#define ENET_CFGSSQMIWQASSOC_ADDR                                 0x000000e0
+#define ENET_CFGSSQMIFPQASSOC_ADDR                                0x000000dc
+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR                          0x000000f0
+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR                           0x000000f4
+#define ENET_CLKEN_ADDR                                              0x00000008
+#define ENET_SRST_ADDR                                               0x00000000
+#define CSR0_RESET_WR(src)                          (((u32)(src)) & 0x00000001)
+#define ENET0_RESET_WR(src)                      (((u32)(src)<<1) & 0x00000002)
+#define CSR1_RESET_WR(src)                       (((u32)(src)<<2) & 0x00000004)
+#define ENET1_RESET_WR(src)                      (((u32)(src)<<3) & 0x00000008)
+#define CSR0_CLKEN_WR(src)                          (((u32)(src)) & 0x00000001)
+#define ENET0_CLKEN_WR(src)                      (((u32)(src)<<1) & 0x00000002)
+#define CSR1_CLKEN_WR(src)                       (((u32)(src)<<2) & 0x00000004)
+#define ENET1_CLKEN_WR(src)                      (((u32)(src)<<3) & 0x00000008)
+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR                            0x00000070
+#define ENET_BLOCK_MEM_RDY_ADDR                                   0x00000074
+#define MAC_CONFIG_1_ADDR                                            0x00000000
+#define MAC_CONFIG_2_ADDR                                            0x00000004
+#define MAX_FRAME_LEN_ADDR                                           0x00000010
+#define MII_MGMT_CONFIG_ADDR                                         0x00000020
+#define MII_MGMT_COMMAND_ADDR                                        0x00000024
+#define MII_MGMT_ADDRESS_ADDR                                        0x00000028
+#define MII_MGMT_CONTROL_ADDR                                        0x0000002c
+#define MII_MGMT_STATUS_ADDR                                         0x00000030
+#define MII_MGMT_INDICATORS_ADDR                                     0x00000034
+#define INTERFACE_CONTROL_ADDR                                       0x00000038
+#define STATION_ADDR0_ADDR                                           0x00000040
+#define STATION_ADDR1_ADDR                                           0x00000044
+#define SCAN_CYCLE_MASK                                              0x00000002
+#define SOFT_RESET1_MASK                                             0x80000000
+#define MAX_FRAME_LEN_SET(dst, src) \
+	(((dst) & ~0x0000ffff) | (((u32)(src)) & 0x0000ffff))
+#define PHY_ADDR_SET(dst, src) \
+	(((dst) & ~0x00001f00) | (((u32)(src)<<8) & 0x00001f00))
+#define REG_ADDR_SET(dst, src) \
+	(((dst) & ~0x0000001f) | (((u32)(src)) & 0x0000001f))
+#define RESET_TX_FUN1_WR(src)                   (((u32)(src)<<16) & 0x00010000)
+#define RESET_RX_FUN1_WR(src)                   (((u32)(src)<<17) & 0x00020000)
+#define RESET_TX_MC1_WR(src)                    (((u32)(src)<<18) & 0x00040000)
+#define RESET_RX_MC1_WR(src)                    (((u32)(src)<<19) & 0x00080000)
+#define SIM_RESET1_WR(src)                      (((u32)(src)<<30) & 0x40000000)
+#define SOFT_RESET1_WR(src)                     (((u32)(src)<<31) & 0x80000000)
+#define TX_EN1_WR(src)                              (((u32)(src)) & 0x00000001)
+#define RX_EN1_WR(src)                           (((u32)(src)<<2) & 0x00000004)
+#define TX_FLOW_EN1_WR(src)                      (((u32)(src)<<4) & 0x00000010)
+#define LOOP_BACK1_WR(src)                       (((u32)(src)<<8) & 0x00000100)
+#define RX_FLOW_EN1_WR(src)                      (((u32)(src)<<5) & 0x00000020)
+#define ENET_LHD_MODE_WR(src)                (((u32)(src)<<25) & 0x02000000)
+#define ENET_GHD_MODE_WR(src)                (((u32)(src)<<26) & 0x04000000)
+#define FULL_DUPLEX2_WR(src)                        (((u32)(src)) & 0x00000001)
+#define LENGTH_CHECK2_WR(src)                    (((u32)(src)<<4) & 0x00000010)
+#define HUGE_FRAME_EN2_WR(src)                   (((u32)(src)<<5) & 0x00000020)
+#define ENET_INTERFACE_MODE2_WR(src)          (((u32)(src)<<8) & 0x00000300)
+#define PAD_CRC2_WR(src)                         (((u32)(src)<<2) & 0x00000004)
+#define CRC_EN2_WR(src)                          (((u32)(src)<<1) & 0x00000002)
+#define PREAMBLE_LENGTH2_WR(src)                (((u32)(src)<<12) & 0x0000f000)
+#define MAX_FRAME_LEN_WR(src)                       (((u32)(src)) & 0x0000ffff)
+#define MGMT_CLOCK_SEL_SET(dst, src) \
+	(((dst) & ~0x00000007) | (((u32)(src)) & 0x00000007))
+#define RX_EN1_SET(dst, src) \
+	(((dst) & ~0x00000004) | (((u32)(src)<<2) & 0x00000004))
+#define TX_EN1_SET(dst, src) \
+	(((dst) & ~0x00000001) | (((u32)(src)) & 0x00000001))
+#define SCAN_AUTO_INCR_MASK                                          0x00000020
+#define RBYT_ADDR                                                    0x00000027
+#define RPKT_ADDR                                                    0x00000028
+#define RFCS_ADDR                                                    0x00000029
+#define RALN_ADDR                                                    0x0000002f
+#define RFLR_ADDR                                                    0x00000030
+#define RUND_ADDR                                                    0x00000033
+#define ROVR_ADDR                                                    0x00000034
+#define RDRP_ADDR                                                    0x00000037
+#define TBYT_ADDR                                                    0x00000038
+#define TPKT_ADDR                                                    0x00000039
+#define TDRP_ADDR                                                    0x00000045
+#define TFCS_ADDR                                                    0x00000047
+#define TUND_ADDR                                                    0x0000004a
+#define RX_BYTE_CNTR_MASK                                            0x7fffffff
+#define RX_PKT_CNTR_MASK                                             0x7fffffff
+#define RX_FCS_ERROR_CNTR_MASK                                       0x0000ffff
+#define RX_ALIGN_ERR_CNTR_MASK                                       0x0000ffff
+#define RX_LEN_ERR_CNTR_MASK                                         0x0000ffff
+#define RX_UNDRSIZE_PKT_CNTR_MASK                                    0x0000ffff
+#define RX_OVRSIZE_PKT_CNTR_MASK                                     0x0000ffff
+#define RX_DROPPED_PKT_CNTR_MASK                                     0x0000ffff
+#define TX_BYTE_CNTR_MASK                                            0x7fffffff
+#define TX_PKT_CNTR_MASK                                             0x7fffffff
+#define TX_DROP_FRAME_CNTR_MASK                                      0x0000ffff
+#define TX_FCS_ERROR_CNTR_MASK                                       0x00000fff
+#define TX_UNDSIZE_FRAME_CNTR_MASK                                   0x00000fff
+
+#endif /* __XGENE_ENET_CSR_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_mac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_mac.c
new file mode 100644
index 0000000..68f8851
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_mac.c
@@ -0,0 +1,520 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_csr.h"
+
+static void xgene_gmac_set_mac_addr(struct xgene_enet_priv *priv,
+				    unsigned char *dev_addr)
+{
+	u32 a_hi = *(u32 *)&dev_addr[0];
+	u32 a_lo = (u32) *(u16 *)&dev_addr[4];
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, STATION_ADDR0_ADDR, a_hi);
+
+	a_lo <<= 16;
+	a_lo |= (priv->phy_addr & 0xFFFF);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, STATION_ADDR1_ADDR, a_lo);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_priv *priv)
+{
+	u32 data;
+	int wait;
+
+	xgene_enet_wr(priv, BLOCK_ETH_DIAG_CSR,
+			ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+	/* check for at leaset 1 ms */
+	wait = 1000;
+	do {
+		xgene_enet_rd(priv, BLOCK_ETH_DIAG_CSR,
+			ENET_BLOCK_MEM_RDY_ADDR, &data);
+		usleep_range(1, 100);
+	} while (--wait && data != 0xffffffff);
+	if (!wait) {
+		pr_err("Failed to release memory from shutdown\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void xgene_gmac_change_mtu(struct xgene_enet_priv *priv, u32 new_mtu)
+{
+	u32 data;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAX_FRAME_LEN_ADDR, &data);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAX_FRAME_LEN_ADDR,
+		      MAX_FRAME_LEN_SET(data, new_mtu));
+}
+
+static void xgene_gmac_phy_enable_scan_cycle(struct xgene_enet_priv *priv,
+					     int enable)
+{
+	u32 val;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MII_MGMT_COMMAND_ADDR, &val);
+	if (enable)
+		val |= SCAN_CYCLE_MASK;
+	else
+		val &= ~SCAN_CYCLE_MASK;
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MII_MGMT_COMMAND_ADDR, val);
+
+	/* Program phy address start scan from 0 and register at address 0x1 */
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MII_MGMT_ADDRESS_ADDR, &val);
+	val = PHY_ADDR_SET(val, 0);
+	val = REG_ADDR_SET(val, 1);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MII_MGMT_ADDRESS_ADDR, val);
+}
+
+static void xgene_gmac_reset(struct xgene_enet_priv *priv)
+{
+	u32 value;
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &value);
+	if (!(value & SOFT_RESET1_MASK))
+		return;
+
+	value = RESET_TX_FUN1_WR(1)
+	    | RESET_RX_FUN1_WR(1)
+	    | RESET_TX_MC1_WR(1)
+	    | RESET_RX_MC1_WR(1)
+	    | SIM_RESET1_WR(1)
+	    | SOFT_RESET1_WR(1);
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, value);
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &value);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, 0);
+}
+
+int xgene_gmac_init(struct xgene_enet_priv *priv, unsigned char *dev_addr,
+		    int speed, int mtu, int crc)
+{
+	u32 value, temp;
+	u32 addr_hi, addr_lo;
+
+	u32 interface_control;
+	u32 mac_config_2;
+	u32 rgmii;
+	u32 icm_config0 = 0x0008503f;
+	u32 icm_config2 = 0x0010000f;
+	u32 ecm_config0 = 0x00000032;
+	u32 enet_spare_cfg = 0x00006040;
+
+	/* Reset subsystem */
+	value = RESET_TX_FUN1_WR(1)
+	    | RESET_RX_FUN1_WR(1)
+	    | RESET_TX_MC1_WR(1)
+	    | RESET_RX_MC1_WR(1)
+	    | SIM_RESET1_WR(1)
+	    | SOFT_RESET1_WR(1);
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, value);
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &temp);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, 0);
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &temp);
+
+	value = TX_EN1_WR(1)
+	    | RX_EN1_WR(1)
+	    | TX_FLOW_EN1_WR(0)
+	    | LOOP_BACK1_WR(0)
+	    | RX_FLOW_EN1_WR(0);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, value);
+	xgene_enet_rd(priv, BLOCK_ETH_CSR,
+		      ENET_SPARE_CFG_REG_ADDR, &enet_spare_cfg);
+
+	if (speed == XGENE_ENET_SPEED_10) {
+		interface_control = ENET_LHD_MODE_WR(0)
+		    | ENET_GHD_MODE_WR(0);
+		mac_config_2 = FULL_DUPLEX2_WR(1)
+		    | LENGTH_CHECK2_WR(0)
+		    | HUGE_FRAME_EN2_WR(0)
+		    | ENET_INTERFACE_MODE2_WR(1)	/* 10Mbps */
+		    |PAD_CRC2_WR(crc)
+		    | CRC_EN2_WR(crc)
+		    | PREAMBLE_LENGTH2_WR(7);
+		rgmii = 0;
+		icm_config0 = 0x0000503f;
+		icm_config2 = 0x000101f4;
+		ecm_config0 = 0x600032;
+		enet_spare_cfg = enet_spare_cfg | (0x0000c040);
+	} else if (speed == XGENE_ENET_SPEED_100) {
+		interface_control = ENET_LHD_MODE_WR(1);
+		mac_config_2 = FULL_DUPLEX2_WR(1)
+		    | LENGTH_CHECK2_WR(0)
+		    | HUGE_FRAME_EN2_WR(0)
+		    | ENET_INTERFACE_MODE2_WR(1)	/* 100Mbps */
+		    |PAD_CRC2_WR(crc)
+		    | CRC_EN2_WR(crc)
+		    | PREAMBLE_LENGTH2_WR(7);
+		rgmii = 0;
+		icm_config0 = 0x0004503f;
+		icm_config2 = 0x00010050;
+		ecm_config0 = 0x600032;
+		enet_spare_cfg = enet_spare_cfg | (0x0000c040);
+	} else {
+		interface_control = ENET_GHD_MODE_WR(1);
+		mac_config_2 = FULL_DUPLEX2_WR(1)
+		    | LENGTH_CHECK2_WR(0)
+		    | HUGE_FRAME_EN2_WR(0)
+		    | ENET_INTERFACE_MODE2_WR(2)	/* 1Gbps */
+		    |PAD_CRC2_WR(crc)
+		    | CRC_EN2_WR(crc)
+		    | PREAMBLE_LENGTH2_WR(7);
+		rgmii = CFG_SPEED_1250_WR(1) | CFG_TXCLK_MUXSEL0_WR(4);
+		icm_config0 = 0x0008503f;
+		icm_config2 = 0x0001000f;
+		ecm_config0 = 0x32;
+		enet_spare_cfg = (enet_spare_cfg & ~0x0000c000)
+		    | (0x00000040);
+	}
+
+	enet_spare_cfg |= 0x00006040;
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_2_ADDR, mac_config_2);
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, INTERFACE_CONTROL_ADDR,
+		      interface_control);
+
+	value = MAX_FRAME_LEN_WR(0x0600);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAX_FRAME_LEN_ADDR, value);
+
+	/* Program the station MAC address */
+	addr_hi = *(u32 *) &dev_addr[0];
+	addr_lo = *(u16 *) &dev_addr[4];
+	addr_lo <<= 16;
+	addr_lo |= (priv->phy_addr & 0xFFFF);
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, STATION_ADDR0_ADDR, addr_hi);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, STATION_ADDR1_ADDR, addr_lo);
+
+	/* Adjust MDC clock frequency */
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MII_MGMT_CONFIG_ADDR, &value);
+	value = MGMT_CLOCK_SEL_SET(value, 7);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MII_MGMT_CONFIG_ADDR, value);
+
+	/* Enable drop if FP not available */
+	xgene_enet_rd(priv, BLOCK_ETH_CSR, RSIF_CONFIG_REG_ADDR, &value);
+	value |= CFG_RSIF_FPBUFF_TIMEOUT_EN_WR(1);
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, RSIF_CONFIG_REG_ADDR, value);
+
+	/* Rtype should be copied from FP */
+	value = 0;
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, RSIF_RAM_DBG_REG0_ADDR, value);
+	/* Initialize RGMII PHY */
+	if (priv->phy_mode == PHY_MODE_RGMII)
+		xgene_enet_wr(priv, BLOCK_ETH_CSR, RGMII_REG_0_ADDR, rgmii);
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR, ICM_CONFIG0_REG_0_ADDR,
+		      icm_config0);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR, ICM_CONFIG2_REG_0_ADDR,
+		      icm_config2);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR, ECM_CONFIG0_REG_0_ADDR,
+		      ecm_config0);
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, ENET_SPARE_CFG_REG_ADDR,
+		      enet_spare_cfg);
+
+	/* Rx-Tx traffic resume */
+	xgene_enet_wr(priv, BLOCK_ETH_CSR,
+		      CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0_WR(0x1));
+
+	if (speed != XGENE_ENET_SPEED_10 && speed != XGENE_ENET_SPEED_100) {
+		xgene_enet_rd(priv, BLOCK_ETH_CSR, DEBUG_REG_ADDR, &value);
+		value |= CFG_BYPASS_UNISEC_TX_WR(1)
+		    | CFG_BYPASS_UNISEC_RX_WR(1);
+		xgene_enet_wr(priv, BLOCK_ETH_CSR, DEBUG_REG_ADDR, value);
+	}
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC_CSR, RX_DV_GATE_REG_0_ADDR, &value);
+	value = TX_DV_GATE_EN0_SET(value, 0);
+	value = RX_DV_GATE_EN0_SET(value, 0);
+	value = RESUME_RX0_SET(value, 1);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR, RX_DV_GATE_REG_0_ADDR, value);
+
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, CFG_BYPASS_ADDR, RESUME_TX_WR(1));
+	return 0;
+}
+
+/* Start Statistics related functions */
+static void xgene_gmac_get_rx_stats(struct xgene_enet_priv *priv,
+				    struct xgene_enet_rx_stats *rx_stat)
+{
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RBYT_ADDR,
+		      &rx_stat->rx_byte_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RPKT_ADDR,
+		      &rx_stat->rx_packet_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RDRP_ADDR,
+		      &rx_stat->rx_drop_pkt_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RFCS_ADDR,
+		      &rx_stat->rx_fcs_err_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RFLR_ADDR,
+		      &rx_stat->rx_frm_len_err_pkt_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RALN_ADDR,
+		      &rx_stat->rx_alignment_err_pkt_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, ROVR_ADDR,
+		      &rx_stat->rx_oversize_pkt_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, RUND_ADDR,
+		      &rx_stat->rx_undersize_pkt_count);
+
+	rx_stat->rx_byte_count &= RX_BYTE_CNTR_MASK;
+	rx_stat->rx_packet_count &= RX_PKT_CNTR_MASK;
+	rx_stat->rx_drop_pkt_count &= RX_DROPPED_PKT_CNTR_MASK;
+	rx_stat->rx_fcs_err_count &= RX_FCS_ERROR_CNTR_MASK;
+	rx_stat->rx_frm_len_err_pkt_count &= RX_LEN_ERR_CNTR_MASK;
+	rx_stat->rx_alignment_err_pkt_count &= RX_ALIGN_ERR_CNTR_MASK;
+	rx_stat->rx_oversize_pkt_count &= RX_OVRSIZE_PKT_CNTR_MASK;
+	rx_stat->rx_undersize_pkt_count &= RX_UNDRSIZE_PKT_CNTR_MASK;
+}
+
+static void xgene_gmac_get_tx_stats(struct xgene_enet_priv *priv,
+				    struct xgene_enet_tx_stats *tx_stats)
+{
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, TBYT_ADDR,
+		      &tx_stats->tx_byte_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, TPKT_ADDR,
+		      &tx_stats->tx_pkt_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, TDRP_ADDR,
+		      &tx_stats->tx_drop_frm_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, TFCS_ADDR,
+		      &tx_stats->tx_fcs_err_frm_count);
+	xgene_enet_rd(priv, BLOCK_MCX_STATS, TUND_ADDR,
+		      &tx_stats->tx_undersize_frm_count);
+
+	tx_stats->tx_byte_count &= TX_BYTE_CNTR_MASK;
+	tx_stats->tx_pkt_count &= TX_PKT_CNTR_MASK;
+	tx_stats->tx_drop_frm_count &= TX_DROP_FRAME_CNTR_MASK;
+	tx_stats->tx_fcs_err_frm_count &= TX_FCS_ERROR_CNTR_MASK;
+	tx_stats->tx_undersize_frm_count &= TX_UNDSIZE_FRAME_CNTR_MASK;
+}
+
+static void xgene_gmac_get_detailed_stats(struct xgene_enet_priv *priv,
+		struct xgene_enet_detailed_stats *stats)
+{
+	xgene_gmac_get_rx_stats(priv, &(stats->rx_stats));
+	xgene_gmac_get_tx_stats(priv, &(stats->tx_stats));
+}
+
+/* Configure Ethernet QMI: WQ and FPQ association to QML */
+static void xgene_enet_config_qmi_assoc(struct xgene_enet_priv *priv)
+{
+	xgene_enet_wr(priv, BLOCK_ETH_QMI, ENET_CFGSSQMIWQASSOC_ADDR,
+		      0xffffffff);
+	xgene_enet_wr(priv, BLOCK_ETH_QMI, ENET_CFGSSQMIFPQASSOC_ADDR,
+		      0xffffffff);
+	xgene_enet_wr(priv, BLOCK_ETH_QMI, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR,
+		      0xffffffff);
+	xgene_enet_wr(priv, BLOCK_ETH_QMI, ENET_CFGSSQMIQMLITEWQASSOC_ADDR,
+		      0xffffffff);
+}
+
+static void xgene_enet_cle_bypass_mode_cfg(struct xgene_enet_priv *priv,
+					   u32 cle_dstqid, u32 cle_fpsel)
+{
+	u32 reg;
+
+	xgene_enet_rd(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG0_0_ADDR, &reg);
+	reg = CFG_CLE_BYPASS_EN0_SET(reg, 1);
+	reg = CFG_CLE_IP_PROTOCOL0_SET(reg, 3);
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG0_0_ADDR, reg);
+
+	xgene_enet_rd(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG1_0_ADDR, &reg);
+	reg = CFG_CLE_DSTQID0_SET(reg, cle_dstqid);
+	reg = CFG_CLE_FPSEL0_SET(reg, cle_fpsel);
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG1_0_ADDR, reg);
+
+	xgene_enet_rd(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG8_0_ADDR, &reg);
+	reg = CFG_CLE_HENQNUM0_SET(reg, cle_dstqid);
+	xgene_enet_wr(priv, BLOCK_ETH_CSR, CLE_BYPASS_REG8_0_ADDR, reg);
+}
+
+static void xgene_gmac_rx_state(struct xgene_enet_priv *priv, u32 enable)
+{
+	u32 data, rx_en;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &data);
+	rx_en = (enable) ? RX_EN1_SET(data, 1) : RX_EN1_SET(data, 0);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, rx_en);
+}
+
+static void xgene_gmac_tx_state(struct xgene_enet_priv *priv, u32 enable)
+{
+	u32 data, tx_en;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &data);
+	tx_en = (enable) ? TX_EN1_SET(data, 1) : TX_EN1_SET(data, 0);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, tx_en);
+}
+
+static void xgene_gmac_tx_offload(struct xgene_enet_priv *priv,
+				  u32 command, u32 value)
+{
+	u32 data;
+
+	switch (priv->port) {
+	case MENET:
+		switch (command) {
+			/* TCP MSS 0 */
+		case XGENE_ENET_MSS0:
+			xgene_enet_rd(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG0_0_ADDR, &data);
+			xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG0_0_ADDR,
+				      CFG_TSIF_MSS_SZ00_SET(data, value));
+			break;
+			/* TCP MSS 1 */
+		case XGENE_ENET_MSS1:
+			xgene_enet_rd(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG0_0_ADDR, &data);
+			xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG0_0_ADDR,
+				      CFG_TSIF_MSS_SZ10_SET(data, value));
+			break;
+			/* TCP MSS 2 */
+		case XGENE_ENET_MSS2:
+			xgene_enet_rd(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG1_0_ADDR, &data);
+			xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG1_0_ADDR,
+				      CFG_TSIF_MSS_SZ20_SET(data, value));
+			break;
+			/* TCP MSS 3 */
+		case XGENE_ENET_MSS3:
+			xgene_enet_rd(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG1_0_ADDR, &data);
+			xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				      TSIF_MSS_REG1_0_ADDR,
+				      CFG_TSIF_MSS_SZ30_SET(data, value));
+			break;
+			/* Program TSO config */
+		case XGENE_ENET_TSO_CFG:
+			xgene_enet_wr(priv, BLOCK_ETH_CSR, TSO_CFG_0_ADDR,
+				      value);
+			break;
+			/* Insert Inser tVLAN TAG */
+		case XGENE_ENET_INSERT_VLAN:
+			xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				      TSO_CFG_INSERT_VLAN_0_ADDR, value);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void xgene_enet_clkrst_cfg(struct xgene_enet_priv *priv)
+{
+	u32 data;
+
+	/* disable all clocks */
+	data = CSR0_CLKEN_WR(0) | ENET0_CLKEN_WR(0) |
+	    CSR1_CLKEN_WR(0) | ENET1_CLKEN_WR(0);
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_CLKEN_ADDR, data);
+
+	/* enable all clocks */
+	data = CSR0_CLKEN_WR(1) | ENET0_CLKEN_WR(1) |
+	    CSR1_CLKEN_WR(1) | ENET1_CLKEN_WR(1);
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_CLKEN_ADDR, data);
+
+	/* put csr and core reset */
+	data = CSR0_RESET_WR(1) | ENET0_RESET_WR(1) |
+	    CSR1_RESET_WR(1) | ENET1_RESET_WR(1);
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_SRST_ADDR, data);
+
+	/* release csr and core reset */
+	data = CSR0_RESET_WR(0) | ENET0_RESET_WR(0) |
+	    CSR1_RESET_WR(0) | ENET1_RESET_WR(0);
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_SRST_ADDR, data);
+
+	xgene_enet_ecc_init(priv);
+}
+
+static void xgene_gport_reset(struct xgene_enet_priv *priv)
+{
+	u32 val;
+
+	xgene_enet_clkrst_cfg(priv);
+	xgene_enet_config_qmi_assoc(priv);
+
+	/* Enable auto-incr for scanning */
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MII_MGMT_CONFIG_ADDR, &val);
+	val |= SCAN_AUTO_INCR_MASK;
+	val = MGMT_CLOCK_SEL_SET(val, 1);
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MII_MGMT_CONFIG_ADDR, val);
+	xgene_gmac_phy_enable_scan_cycle(priv, 1);
+}
+
+static void xgene_gport_shutdown(struct xgene_enet_priv *priv)
+{
+	u32 clk, rst;
+
+	rst = CSR0_RESET_WR(1) | ENET0_RESET_WR(1);
+	clk = CSR0_CLKEN_WR(0) | ENET0_CLKEN_WR(0);
+
+	/* reset ethernet csr, core and disable clock */
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_SRST_ADDR, rst);
+	xgene_enet_wr(priv, BLOCK_ETH_CLKRST_CSR, ENET_CLKEN_ADDR, clk);
+}
+
+void xgene_enet_init_priv(struct xgene_enet_priv *priv)
+{
+	void *gbl_vaddr = priv->vaddr_base;
+	void *port_vaddr = priv->vpaddr_base;
+
+	/* Initialize base addresses for direct access */
+	priv->eth_csr_addr_v = gbl_vaddr + BLOCK_ETH_CSR_OFFSET;
+	priv->eth_cle_addr_v = gbl_vaddr + BLOCK_ETH_CLE_OFFSET;
+	priv->eth_qmi_addr_v = gbl_vaddr + BLOCK_ETH_QMI_OFFSET;
+	priv->eth_sds_csr_addr_v = gbl_vaddr + BLOCK_ETH_SDS_CSR_OFFSET;
+	priv->eth_clkrst_csr_addr_v = gbl_vaddr + BLOCK_ETH_CLKRST_CSR_OFFSET;
+	priv->eth_diag_csr_addr_v = gbl_vaddr + BLOCK_ETH_DIAG_CSR_OFFSET;
+
+	/* Initialize per port base addr for indirect & direct MCX MAC access */
+	priv->mcx_mac_addr_v = port_vaddr + BLOCK_ETH_MAC_OFFSET;
+	priv->mcx_stats_addr_v = port_vaddr + BLOCK_ETH_STATS_OFFSET;
+	priv->mcx_mac_csr_addr_v = gbl_vaddr + BLOCK_ETH_MAC_CSR_OFFSET;
+	priv->sata_enet_csr_addr_v = gbl_vaddr + BLOCK_SATA_ENET_CSR_OFFSET;
+
+	/* Enable autonegotiation by default */
+	priv->autoneg_set = 1;
+
+	pr_debug("         ETH%d VADDR: 0x%p\n", priv->port, priv->vpaddr_base);
+	pr_debug("           ETH VADDR: 0x%p\n", priv->vaddr_base);
+	pr_debug("       ETH CSR VADDR: 0x%p\n", priv->eth_csr_addr_v);
+	pr_debug("       ETH CLE VADDR: 0x%p\n", priv->eth_cle_addr_v);
+	pr_debug("       ETH QMI VADDR: 0x%p\n", priv->eth_qmi_addr_v);
+	pr_debug("   ETH SDS CSR VADDR: 0x%p\n", priv->eth_sds_csr_addr_v);
+	pr_debug("ETH CLKRST CSR VADDR: 0x%p\n", priv->eth_clkrst_csr_addr_v);
+	pr_debug("      ETH DIAG VADDR: 0x%p\n", priv->eth_diag_csr_addr_v);
+	pr_debug("       MAC MII VADDR: 0x%p\n", priv->vmii_base);
+	pr_debug("       MCX MAC VADDR: 0x%p\n", priv->mcx_mac_addr_v);
+	pr_debug("      MCX STAT VADDR: 0x%p\n", priv->mcx_stats_addr_v);
+	pr_debug("   MCX MAC CSR VADDR: 0x%p\n", priv->mcx_mac_csr_addr_v);
+	pr_debug(" SATA ENET CSR VADDR: 0x%p\n", priv->sata_enet_csr_addr_v);
+
+	/* Initialize priv handlers */
+	priv->port_reset = xgene_gport_reset;
+	priv->mac_reset = xgene_gmac_reset;
+	priv->mac_init = xgene_gmac_init;
+	priv->mac_rx_state = xgene_gmac_rx_state;
+	priv->mac_tx_state = xgene_gmac_tx_state;
+	priv->mac_change_mtu = xgene_gmac_change_mtu;
+	priv->set_mac_addr = xgene_gmac_set_mac_addr;
+	priv->cle_bypass = xgene_enet_cle_bypass_mode_cfg;
+	priv->tx_offload = xgene_gmac_tx_offload;
+	priv->port_shutdown = xgene_gport_shutdown;
+	priv->get_stats = xgene_gmac_get_detailed_stats;
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
new file mode 100644
index 0000000..2aa1808
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -0,0 +1,1581 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_csr.h"
+
+inline void xgene_enet_wr32(void *addr, u32 data)
+{
+	pr_debug("Write addr 0x%p data 0x%08X\n", addr, data);
+	writel(data, (void __iomem *)addr);
+}
+
+inline void xgene_enet_rd32(void *addr, u32 *data)
+{
+	*data = readl((void __iomem *)addr);
+	pr_debug("data 0x%08X\n", *data);
+}
+
+inline u32 xgene_enet_get_port(struct xgene_enet_pdev *pdev)
+{
+	return pdev->priv.port;
+}
+
+inline phys_addr_t xgene_enet_enc_addr(void *vaddr)
+{
+	return __pa(vaddr);
+}
+
+inline void *xgene_enet_dec_addr(phys_addr_t paddr)
+{
+	return __va(paddr);
+}
+
+inline void xgene_enet_set_skb_data(struct xgene_qmtm_msg16 *msg16,
+				    struct sk_buff *skb)
+{
+	u64 pa;
+
+	pa = xgene_enet_enc_addr((void *)skb);
+	msg16->UserInfo = (u32) pa;
+	pa >>= 32;
+	msg16->Rv6 = (u8) pa;
+	msg16->Rv2 = (u8) (pa >> 6);
+
+	pa = xgene_enet_enc_addr(skb->data);
+	msg16->DataAddr = pa;
+}
+
+inline struct sk_buff *xgene_enet_get_skb(struct xgene_qmtm_msg16 *msg16)
+{
+	u64 pa = ((u64) msg16->Rv2 << 6) | (u64) msg16->Rv6;
+	pa <<= 32;
+	pa |= (u64) msg16->UserInfo;
+	return (struct sk_buff *)xgene_enet_dec_addr(pa);
+}
+
+static int xgene_enet_init_fp(struct xgene_enet_qcontext *c2e, u32 nbuf)
+{
+	struct xgene_enet_pdev *pdev = c2e->pdev;
+	struct sk_buff *skb;
+	struct xgene_qmtm_msg16 *msg16;
+	u32 i;
+
+	/* Initializing common fields */
+	for (i = 0; i < c2e->qdesc->count; i++) {
+		msg16 = &c2e->qdesc->msg16[i];
+		memset(msg16, 0, sizeof(struct xgene_qmtm_msg16));
+		msg16->C = 1;
+		msg16->BufDataLen = xgene_qmtm_encode_bufdatalen(c2e->buf_size);
+		msg16->FPQNum = c2e->eqnum;
+		msg16->PB = 0;
+		msg16->HB = 1;
+	}
+
+	if (nbuf > c2e->qdesc->count) {
+		netdev_warn(pdev->ndev,
+			    "Limiting number of skb alloc to queue size\n");
+		nbuf = c2e->qdesc->count;
+	}
+
+	for (i = 0; i < nbuf; i++) {
+		msg16 = &c2e->qdesc->msg16[i];
+		skb = dev_alloc_skb(c2e->buf_size);
+		if (unlikely(!skb)) {
+			netdev_err(pdev->ndev,
+				   "Failed to allocate new skb size %d",
+				   c2e->buf_size);
+			return -ENOMEM;
+		}
+		skb_reserve(skb, NET_IP_ALIGN);
+		xgene_enet_set_skb_data(msg16, skb);
+	}
+
+	writel(nbuf, c2e->qdesc->command);
+
+	if (nbuf == c2e->qdesc->count)
+		nbuf = 0;
+	c2e->qdesc->qtail = nbuf;
+
+	return 0;
+}
+
+static int xgene_enet_refill_fp(struct xgene_enet_qcontext *c2e, u32 nbuf)
+{
+	register u32 qtail = c2e->qdesc->qtail;
+	struct xgene_enet_pdev *pdev = c2e->pdev;
+	u32 i;
+
+	for (i = 0; i < nbuf; i++) {
+		struct sk_buff *skb;
+		struct xgene_qmtm_msg16 *msg16 = &c2e->qdesc->msg16[qtail];
+
+		msg16->BufDataLen = xgene_qmtm_encode_bufdatalen(c2e->buf_size);
+		skb = dev_alloc_skb(c2e->buf_size);
+		if (unlikely(!skb)) {
+			netdev_err(pdev->ndev,
+				   "Failed to allocate new skb size %d",
+				   c2e->buf_size);
+			return -ENOMEM;
+		}
+		skb_reserve(skb, NET_IP_ALIGN);
+		xgene_enet_set_skb_data(msg16, skb);
+		if (++qtail == c2e->qdesc->count)
+			qtail = 0;
+	}
+
+	writel(nbuf, c2e->qdesc->command);
+	c2e->qdesc->qtail = qtail;
+
+	return 0;
+}
+
+static void xgene_enet_deinit_fp(struct xgene_enet_qcontext *c2e, int qid)
+{
+	u32 qtail = c2e->qdesc->qtail;
+	u32 count = c2e->qdesc->count;
+	u32 command = 0;
+	struct xgene_enet_pdev *pdev = c2e->pdev;
+	struct xgene_qmtm_msg16 *msg16;
+	struct xgene_qmtm_qinfo qinfo;
+	struct sk_buff *skb;
+	int i;
+
+	memset(&qinfo, 0, sizeof(qinfo));
+	qinfo.qmtm = pdev->sdev->qmtm;
+	qinfo.queue_id = qid;
+	xgene_qmtm_read_qstate(&qinfo);
+
+	for (i = 0; i < qinfo.nummsgs; i++) {
+		if (qtail == 0)
+			qtail = count;
+
+		qtail--;
+		msg16 = &c2e->qdesc->msg16[qtail];
+		if (msg16->UserInfo) {
+			skb = xgene_enet_get_skb(msg16);
+			kfree_skb(skb);
+		}
+		command--;
+	}
+
+	writel(command, c2e->qdesc->command);
+	c2e->qdesc->qtail = qtail;
+}
+
+static int xgene_enet_change_mtu(struct net_device *ndev, int new_mtu)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+	int eth_running;
+
+	if (HW_MTU(new_mtu) < XGENE_ENET_MIN_MTU
+	    || HW_MTU(new_mtu) > XGENE_ENET_MAX_MTU) {
+		netdev_err(ndev, "Invalid MTU: %d\n", new_mtu);
+		return -EINVAL;
+	}
+
+	netdev_info(ndev, "changing MTU from %d to %d\n", ndev->mtu, new_mtu);
+	eth_running = netif_running(ndev);
+	if (eth_running) {
+		netif_stop_queue(ndev);
+		xgene_enet_mac_rx_state(priv, 0);
+		xgene_enet_mac_tx_state(priv, 0);
+	}
+	ndev->mtu = new_mtu;
+	xgene_enet_mac_change_mtu(priv, HW_MTU(new_mtu));
+	if (eth_running) {
+		xgene_enet_mac_rx_state(priv, 1);
+		xgene_enet_mac_tx_state(priv, 1);
+		netif_start_queue(ndev);
+	}
+	return 0;
+}
+
+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_enet_pdev *pdev = bus->priv;
+	struct xgene_enet_priv *priv = &pdev->priv;
+	u32 regval1;
+
+	xgene_genericmiiphy_read(priv, mii_id, regnum, &regval1);
+	pr_debug("%s: bus=%d reg=%d val=%x\n", __func__, mii_id,
+		 regnum, regval1);
+	return (int)regval1;
+}
+
+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+				 u16 regval)
+{
+	struct xgene_enet_pdev *pdev = bus->priv;
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	pr_debug("%s: bus=%d reg=%d val=%x\n", __func__, mii_id,
+		 regnum, regval);
+	xgene_genericmiiphy_write(priv, mii_id, regnum, regval);
+
+	return 0;
+}
+
+static void xgene_enet_mdio_link_change(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+	struct phy_device *phydev = pdev->phy_dev;
+	int status_change = 0;
+
+	if (phydev->link) {
+		if (pdev->phy_speed != phydev->speed) {
+			xgene_enet_mac_init(priv, ndev->dev_addr, phydev->speed,
+					    HW_MTU(ndev->mtu), priv->crc);
+			pdev->phy_speed = phydev->speed;
+			status_change = 1;
+		}
+	}
+
+	if (phydev->link != pdev->phy_link) {
+		if (!phydev->link)
+			pdev->phy_speed = 0;
+		pdev->phy_link = phydev->link;
+		status_change = 1;
+	}
+
+	if (status_change) {
+		xgene_enet_mac_rx_state(priv, phydev->link);
+		xgene_enet_mac_tx_state(priv, phydev->link);
+		if (phydev->link)
+			netdev_info(ndev, "%s: link up %d Mbps\n",
+				    ndev->name, phydev->speed);
+		else
+			netdev_info(ndev, "%s: link down\n", ndev->name);
+	}
+}
+
+static int xgene_enet_mdio_probe(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct phy_device *phydev = NULL;
+	int phy_addr;
+
+	/* find the first phy */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (pdev->mdio_bus->phy_map[phy_addr]) {
+			phydev = pdev->mdio_bus->phy_map[phy_addr];
+			break;
+		}
+	}
+
+	if (!phydev) {
+		netdev_info(ndev, "%s: no PHY found\n", ndev->name);
+		return -1;
+	}
+
+	/* attach the mac to the phy */
+	phydev = phy_connect(ndev, dev_name(&phydev->dev),
+			     &xgene_enet_mdio_link_change,
+			     PHY_INTERFACE_MODE_RGMII);
+
+	pdev->phy_link = 0;
+	pdev->phy_speed = 0;
+
+	if (IS_ERR(phydev)) {
+		pdev->phy_dev = NULL;
+		netdev_err(ndev, "%s: Could not attach to PHY\n", ndev->name);
+		return PTR_ERR(phydev);
+	}
+	pdev->phy_dev = phydev;
+
+	netdev_info(ndev, "%s: phy_id=0x%08x phy_drv=\"%s\"",
+		    ndev->name, phydev->phy_id, phydev->drv->name);
+
+	return 0;
+}
+
+static int xgene_enet_mdio_remove(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev =
+	    (struct xgene_enet_pdev *)netdev_priv(ndev);
+	struct mii_bus *mdio_bus;
+
+	mdio_bus = pdev->mdio_bus;
+	mdiobus_unregister(mdio_bus);
+	mdiobus_free(mdio_bus);
+	pdev->mdio_bus = NULL;
+
+	return 0;
+}
+
+static inline u32 xgene_enet_hdr_len(const void *data)
+{
+	const struct ethhdr *eth = data;
+	return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+irqreturn_t xgene_enet_e2c_irq(const int irq, void *data)
+{
+	struct xgene_enet_qcontext *e2c = (struct xgene_enet_qcontext *)data;
+
+	if (napi_schedule_prep(&e2c->napi)) {
+		disable_irq_nosync(irq);
+		__napi_schedule(&e2c->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int xgene_enet_tx_completion(struct xgene_enet_qcontext *e2c,
+				    struct xgene_qmtm_msg32 *msg32_1)
+{
+	struct sk_buff *skb;
+	int rc = 0;
+
+	skb = (struct sk_buff *)xgene_enet_dec_addr(
+			msg32_1->msgup16.H0Info_msb);
+
+	if (likely(skb)) {
+		dev_kfree_skb_any(skb);
+	} else {
+		netdev_info(e2c->pdev->ndev, "completion skb is NULL\n");
+		rc = -1;
+	}
+
+	return rc;
+}
+
+static inline u16 xgene_enet_select_queue(struct net_device *ndev,
+					  struct sk_buff *skb)
+{
+	return skb_tx_hash(ndev, skb);
+}
+
+/* Checksum offload processing */
+static int xgene_enet_checksum_offload(struct net_device *ndev,
+				       struct sk_buff *skb,
+				       struct xgene_qmtm_msg_up16 *msg_up16)
+{
+	u32 maclen, nr_frags, ihl;
+	struct iphdr *iph;
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	int rc = 0;
+
+	if (unlikely(!(ndev->features & NETIF_F_IP_CSUM)))
+		goto out;
+
+	if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
+	    unlikely(skb->protocol != htons(ETH_P_8021Q)))
+		goto out;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	maclen = xgene_enet_hdr_len(skb->data);
+	iph = ip_hdr(skb);
+	ihl = ip_hdrlen(skb) >> 2;
+
+	if (unlikely(iph->frag_off & htons(IP_MF | IP_OFFSET)))
+		goto out;
+
+	if (likely(iph->protocol == IPPROTO_TCP)) {
+		int xhlen, mss_len;
+		u32 mss, all_hdr_len;
+
+		xhlen = tcp_hdrlen(skb) / 4;
+		msg_up16->H0Info_lsb |=
+		    (xhlen & TSO_TCP_HLEN_MASK) |
+		    ((ihl & TSO_IP_HLEN_MASK) << 6) |
+		    (TSO_CHKSUM_ENABLE << 22) | (TSO_IPPROTO_TCP << 24);
+
+		netdev_dbg(ndev,
+			   "Checksum Offload H0Info 0x%llX H1Info 0x%0llX\n",
+			   (unsigned long long)msg_up16->H0Info_lsb,
+			   (unsigned long long)msg_up16->H0Info_msb);
+
+		if (unlikely(!(ndev->features & NETIF_F_TSO)))
+			goto out;
+
+		/* TCP Segmentation offload processing */
+		mss = skb_shinfo(skb)->gso_size;
+		all_hdr_len = maclen + ip_hdrlen(skb) + tcp_hdrlen(skb);
+		mss_len = skb->len - all_hdr_len;
+
+		/* HW requires all header resides in the first buffer */
+		if (nr_frags && (skb_headlen(skb) < all_hdr_len)) {
+			netdev_err(ndev,
+				   "Unsupported header len location by Eth HW\n");
+			pdev->stats.estats.tx_dropped++;
+			dev_kfree_skb(skb);
+			rc = -1;
+			goto out;
+		}
+
+		if (!mss || mss_len <= mss)
+			goto out;
+
+		if (mss != pdev->mss) {
+			xgene_enet_tx_offload(&pdev->priv, XGENE_ENET_MSS0,
+					      mss);
+			pdev->mss = mss;
+		}
+
+		msg_up16->H0Info_lsb |= ((0 & TSO_MSS_MASK) << 20) |
+		    ((TSO_ENABLE & TSO_ENABLE_MASK) << 23);
+		netdev_dbg(ndev, "TSO H0Info 0x%llX H1Info 0x%0llX mss %d\n",
+			   (unsigned long long)msg_up16->H0Info_lsb,
+			   (unsigned long long)msg_up16->H0Info_msb, mss);
+	} else if (iph->protocol == IPPROTO_UDP) {
+		msg_up16->H0Info_lsb |= (UDP_HDR_SIZE & TSO_TCP_HLEN_MASK)
+		    | ((ihl & TSO_IP_HLEN_MASK) << 6)
+		    | (TSO_CHKSUM_ENABLE << 22)
+		    | (TSO_IPPROTO_UDP << 24);
+		netdev_dbg(ndev, "Csum Offload H0Info 0x%llX H1Info 0x%0llX\n",
+			   (unsigned long long)msg_up16->H0Info_lsb,
+			   (unsigned long long)msg_up16->H0Info_msb);
+	} else {
+		msg_up16->H0Info_lsb |= ((ihl & TSO_IP_HLEN_MASK) << 6);
+	}
+out:
+	return rc;
+}
+
+static void xgene_enet_process_frags(struct net_device *ndev,
+				     struct xgene_qmtm_msg16 *msg16,
+				     struct xgene_enet_qcontext *c2e,
+				     struct sk_buff *skb)
+{
+	struct xgene_qmtm_msg_up16 *msg_up16;
+	struct xgene_qmtm_msg_ext32 *msg32_2;
+	struct xgene_qmtm_msg_ext8 *ext_msg;
+	struct xgene_qmtm_msg_ll8 *ext_msg_ll8;
+	u32 qtail = c2e->qdesc->qtail;
+	phys_addr_t paddr = virt_to_phys(skb->data);
+	u32 nr_frags = skb_shinfo(skb)->nr_frags;
+	skb_frag_t *frag = NULL;
+	u8 *vaddr = NULL;
+	int frag_no = 0, len = 0, offset = 0;
+	int ell_bcnt = 0, ell_cnt = 0, i;
+
+	msg_up16 = (struct xgene_qmtm_msg_up16 *)&msg16[1];
+	msg32_2 = (struct xgene_qmtm_msg_ext32 *)&c2e->qdesc->msg32[qtail];
+
+	if (++qtail == c2e->qdesc->count)
+		qtail = 0;
+
+	memset(msg32_2, 0, sizeof(struct xgene_qmtm_msg_ext32));
+
+	/* First Fragment, 64B message */
+	msg16->BufDataLen = xgene_qmtm_encode_datalen(skb_headlen(skb));
+	msg16->DataAddr = paddr;
+	msg16->NV = 1;
+
+	/* 2nd, 3rd, and 4th fragments */
+	ext_msg = &msg32_2->msg8_1;
+
+	/* Terminate next pointers, will be updated later as required */
+	msg32_2->msg8_2.NxtBufDataLength = 0x7800;
+	msg32_2->msg8_3.NxtBufDataLength = 0x7800;
+	msg32_2->msg8_4.NxtBufDataLength = 0x7800;
+
+	for (i = 0; i < 3 && frag_no < nr_frags; i++) {
+		if (!vaddr) {
+			frag = &skb_shinfo(skb)->frags[frag_no];
+			len = frag->size;
+			vaddr = skb_frag_address(frag);
+			offset = 0;
+			netdev_dbg(ndev, "SKB Frag[%d] 0x%p len %d\n",
+				   frag_no, vaddr, len);
+		}
+		paddr = virt_to_phys(vaddr + offset);
+		ext_msg->NxtDataAddr = paddr;
+
+		if (len <= 16 * 1024) {
+			/* Encode using 16K buffer size format */
+			ext_msg->NxtBufDataLength =
+			    xgene_qmtm_encode_datalen(len);
+			vaddr = NULL;
+			frag_no++;
+		} else {
+			len -= 16 * 1024;
+			offset += 16 * 1024;
+			/* Encode using 16K buffer size format */
+			ext_msg->NxtBufDataLength = 0;
+		}
+
+		netdev_dbg(ndev, "Frag[%d] PADDR 0x%llX len %d\n", i,
+			   (unsigned long long)ext_msg->NxtDataAddr,
+			   ext_msg->NxtBufDataLength);
+		ext_msg = (struct xgene_qmtm_msg_ext8 *)
+		    (((u8 *) msg32_2) + (8 * ((i + 1) ^ 1)));
+	}
+
+	/* Determine no more fragment, last one, or more than one */
+	if (!vaddr) {
+		/* Check next fragment */
+		if (frag_no >= nr_frags) {
+			goto out;
+		} else {
+			frag = &skb_shinfo(skb)->frags[frag_no];
+			if (frag->size <= 16 * 1024
+			    && (frag_no + 1) >= nr_frags)
+				goto one_more_frag;
+			else
+				goto more_than_one_frag;
+		}
+	} else if (len <= 16 * 1024) {
+		/* Current fragment <= 16K, check if last fragment */
+		if ((frag_no + 1) >= nr_frags)
+			goto one_more_frag;
+		else
+			goto more_than_one_frag;
+	} else {
+		/* Current fragment requires two pointers */
+		goto more_than_one_frag;
+	}
+
+one_more_frag:
+	if (!vaddr) {
+		frag = &skb_shinfo(skb)->frags[frag_no];
+		len = frag->size;
+		vaddr = skb_frag_address(frag);
+		offset = 0;
+		netdev_dbg(ndev, "SKB Frag[%d] 0x%p len %d\n",
+			   frag_no, vaddr, len);
+	}
+
+	paddr = virt_to_phys(vaddr + offset);
+	ext_msg->NxtDataAddr = paddr;
+	/* Encode using 16K buffer size format */
+	ext_msg->NxtBufDataLength = xgene_qmtm_encode_datalen(len);
+	netdev_dbg(ndev, "Frag[%d] PADDR 0x%llX len %d\n", i,
+		   (unsigned long long)ext_msg->NxtDataAddr,
+		   ext_msg->NxtBufDataLength);
+	goto out;
+
+more_than_one_frag:
+	msg16->LL = 1;		/* Extended link list */
+	ext_msg_ll8 = &msg32_2->msg8_ll;
+	ext_msg = &c2e->msg8[qtail * 256];
+	memset(ext_msg, 0, 255 * sizeof(struct xgene_qmtm_msg_ext8));
+	paddr = virt_to_phys(ext_msg);
+	ext_msg_ll8->NxtDataPtr = paddr;
+
+	for (i = 0; i < 255 && frag_no < nr_frags;) {
+		if (vaddr == NULL) {
+			frag = &skb_shinfo(skb)->frags[frag_no];
+			len = frag->size;
+			vaddr = skb_frag_address(frag);
+			offset = 0;
+			netdev_dbg(ndev, "SKB Frag[%d] 0x%p len %d\n",
+				   frag_no, vaddr, len);
+		}
+		paddr = virt_to_phys(vaddr + offset);
+		ext_msg[i ^ 1].NxtDataAddr = paddr;
+
+		if (len <= 16 * 1024) {
+			/* Encode using 16K buffer size format */
+			ext_msg[i ^ 1].NxtBufDataLength =
+			    xgene_qmtm_encode_datalen(len);
+			ell_bcnt += len;
+			vaddr = NULL;
+			frag_no++;
+		} else {
+			len -= 16 * 1024;
+			offset += 16 * 1024;
+			ell_bcnt += 16 * 1024;
+		}
+
+		ell_cnt++;
+		netdev_dbg(ndev, "Frag ELL[%d] PADDR 0x%llX len %d\n", i,
+			   (unsigned long long)ext_msg[i ^ 1].NxtDataAddr,
+			   ext_msg[i ^ 1].NxtBufDataLength);
+		i++;
+	}
+
+	/* Encode the extended link list byte count and link count */
+	ext_msg_ll8->NxtLinkListength = ell_cnt;
+	msg_up16->TotDataLengthLinkListLSBs = (ell_bcnt & 0xFFF);
+	ext_msg_ll8->TotDataLengthLinkListMSBs = ((ell_bcnt & 0xFF000) >> 12);
+
+out:
+	c2e->qdesc->qtail = qtail;
+}
+
+/* Packet transmit function */
+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+					 struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_qcontext *c2e = pdev->tx[skb->queue_mapping];
+	struct xgene_qmtm_msg16 *msg16;
+	struct xgene_qmtm_msg_up16 *msg_up16;
+	u32 nr_frags = skb_shinfo(skb)->nr_frags;
+	u32 nummsgs = (readl(c2e->nummsgs) & 0x1fffe) >> 1;
+	u32 cmd = 1;
+
+	msg16 =
+	    (struct xgene_qmtm_msg16 *)&c2e->qdesc->msg32[c2e->qdesc->qtail];
+	msg_up16 = (struct xgene_qmtm_msg_up16 *)&msg16[1];
+
+	if (nummsgs > pdev->tx_cqt_hi) {
+		do {
+			nummsgs = (readl(c2e->nummsgs) & 0x1fffe) >> 1;
+		} while (nummsgs < pdev->tx_cqt_low);
+	}
+
+	if (++c2e->qdesc->qtail == c2e->qdesc->count)
+		c2e->qdesc->qtail = 0;
+
+	memset(msg16, 0, sizeof(struct xgene_qmtm_msg32));
+
+	if (likely(nr_frags == 0)) {
+		skb->len = (skb->len < 60) ? 60 : skb->len;
+		msg16->BufDataLen = xgene_qmtm_encode_datalen(skb->len);
+		msg16->DataAddr = virt_to_phys(skb->data);
+	} else {
+		xgene_enet_process_frags(ndev, msg16, c2e, skb);
+		cmd = 2;
+	}
+
+	msg_up16->H0Info_msb = xgene_enet_enc_addr((void *)skb);
+	msg_up16->H0Enq_Num = c2e->eqnum;
+	msg16->C = 1;
+
+	/* Set TYPE_SEL for egress work message */
+	msg_up16->H0Info_lsb = (u64) TYPE_SEL_WORK_MSG << 44;
+
+	/* Enable CRC insertion */
+	if (!pdev->priv.crc)
+		msg_up16->H0Info_lsb |= (u64) ((u64) TSO_INS_CRC_ENABLE << 35);
+
+	/* Setup mac header length H0Info */
+	msg_up16->H0Info_lsb |=
+	    ((xgene_enet_hdr_len(skb->data) & TSO_ETH_HLEN_MASK) << 12);
+
+	if (unlikely(xgene_enet_checksum_offload(ndev, skb, msg_up16)))
+		return NETDEV_TX_OK;
+
+	/* xmit: Push the work message to ENET HW */
+	netdev_dbg(ndev, "TX CQID %d Addr 0x%llx len %d\n",
+		   msg_up16->H0Enq_Num,
+		   (unsigned long long)msg16->DataAddr, msg16->BufDataLen);
+	writel(cmd, c2e->qdesc->command);
+
+	ndev->trans_start = jiffies;
+	return NETDEV_TX_OK;
+}
+
+int xgene_enet_check_skb(struct net_device *ndev,
+			 struct sk_buff *skb,
+			 struct xgene_qmtm_msg32 *msg32_1, u32 qid)
+{
+	struct xgene_qmtm_msg16 *msg16 = &msg32_1->msg16;
+	u32 UserInfo = msg16->UserInfo;
+	u8 NV = msg16->NV;
+	int rc = 0;
+
+	if (unlikely(!skb)) {
+		netdev_err(ndev, "ENET skb NULL UserInfo %d QID %d FP 0x%x\n",
+			   UserInfo, qid, msg16->FPQNum);
+		print_hex_dump(KERN_INFO, "QM msg:",
+			       DUMP_PREFIX_ADDRESS, 16, 4, msg32_1,
+			       NV ? 64 : 32, 1);
+		rc = -1;
+		goto out;
+	}
+
+	if (unlikely(!skb->head) || unlikely(!skb->data)) {
+		netdev_err(ndev, "ENET skb 0x%p head 0x%p data 0x%p FP 0x%x\n",
+			   skb, skb->head, skb->data, msg16->FPQNum);
+		print_hex_dump(KERN_INFO, "QM msg:",
+			       DUMP_PREFIX_ADDRESS, 16, 4, msg32_1,
+			       NV ? 64 : 32, 1);
+		rc = -1;
+		goto out;
+	}
+
+	if (unlikely(skb->len)) {
+		netdev_err(ndev, "ENET skb 0x%p len %d FP 0x%x\n", skb,
+			   skb->len, msg16->FPQNum);
+		print_hex_dump(KERN_INFO, "QM msg:",
+			       DUMP_PREFIX_ADDRESS, 16, 4, msg32_1,
+			       NV ? 64 : 32, 1);
+		rc = -1;
+		goto out;
+	}
+
+out:
+	return rc;
+}
+
+inline void xgene_enet_skip_csum(struct sk_buff *skb)
+{
+	struct iphdr *iph = (struct iphdr *)skb->data;
+	if (likely(!(iph->frag_off & htons(IP_MF | IP_OFFSET)))
+	    || likely(iph->protocol != IPPROTO_TCP
+		      && iph->protocol != IPPROTO_UDP)) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+}
+
+/* Process received frame */
+static int xgene_enet_rx_frame(struct xgene_enet_qcontext *e2c,
+			       struct xgene_qmtm_msg32 *msg32_1)
+{
+	struct xgene_enet_qcontext *c2e = e2c->c2e_skb;
+	struct xgene_enet_pdev *pdev = e2c->pdev;
+	struct net_device *ndev = pdev->ndev;
+	struct xgene_qmtm_msg16 *msg16 = &msg32_1->msg16;
+	struct sk_buff *skb = NULL;
+	u32 data_len = xgene_qmtm_decode_datalen(msg16->BufDataLen);
+	u8 NV = msg16->NV;
+	u8 LErr = ((u8) msg16->ELErr << 3) | msg16->LErr;
+	u32 UserInfo = msg16->UserInfo;
+	u32 qid = pdev->qm_queues.rx[e2c->queue_index].qid;
+
+	if (unlikely(UserInfo == 0)) {
+		netdev_err(ndev, "ENET UserInfo NULL QID %d FP 0x%x\n",
+			   qid, msg16->FPQNum);
+		print_hex_dump(KERN_INFO, "QM msg:",
+			       DUMP_PREFIX_ADDRESS, 16, 4, msg32_1,
+			       NV ? 64 : 32, 1);
+		goto err_refill;
+	}
+
+	skb = xgene_enet_get_skb(msg16);
+	if (unlikely(xgene_enet_check_skb(ndev, skb, msg32_1, qid)))
+		goto err_refill;
+
+	/* Check for error, if packet received with error */
+	if (unlikely(LErr)) {
+		if (LErr == 0x15)	/* ignore rx queue full error */
+			goto process_pkt;
+		if (LErr == 0x10 || LErr == 0x11) {
+			LErr = 0;
+			goto process_pkt;
+		}
+		if (LErr == 0x10 || LErr == 5) {
+			LErr = 0;
+			goto process_pkt;
+		}
+
+		netdev_dbg(ndev, "ENET LErr 0x%x skb 0x%p FP 0x%x\n",
+			   LErr, skb, msg16->FPQNum);
+		print_hex_dump(KERN_ERR, "QM Msg: ",
+			       DUMP_PREFIX_ADDRESS, 16, 4, msg32_1,
+			       NV ? 64 : 32, 1);
+		goto err_refill;
+	}
+
+process_pkt:
+	prefetch(skb->data - NET_IP_ALIGN);
+
+	if (likely(!NV)) {
+		/* Strip off CRC as HW isn't doing this */
+		data_len -= 4;
+		skb_put(skb, data_len);
+		netdev_dbg(ndev, "RX port %d SKB len %d\n",
+			   xgene_enet_get_port(pdev), data_len);
+	}
+
+	if (--e2c->c2e_count == 0) {
+		xgene_enet_refill_fp(c2e, 32);
+		e2c->c2e_count = 32;
+	}
+
+	if (pdev->num_rx_queues > 1)
+		skb_record_rx_queue(skb, e2c->queue_index);
+
+	skb->protocol = eth_type_trans(skb, ndev);
+	if (likely(ndev->features & NETIF_F_IP_CSUM)
+	    && likely(LErr == 0)
+	    && likely(skb->protocol == htons(ETH_P_IP))) {
+		xgene_enet_skip_csum(skb);
+	}
+
+	napi_gro_receive(&e2c->napi, skb);
+	return 0;
+
+err_refill:
+	if (skb != NULL)
+		dev_kfree_skb_any(skb);
+
+	xgene_enet_refill_fp(e2c->c2e_skb, 1);
+
+	if (LErr != 0x15)
+		pdev->stats.estats.rx_hw_errors++;
+	else
+		pdev->stats.estats.rx_hw_overrun++;
+
+	return -1;
+}
+
+static int xgene_enet_dequeue_msg(struct xgene_enet_qcontext *e2c, int budget)
+{
+	u32 processed = 0;
+	u32 command = 0;
+	u32 qhead = e2c->qdesc->qhead;
+	u32 count = e2c->qdesc->count;
+	u16 nummsgs;
+
+	while (budget--) {
+		struct xgene_qmtm_msg32 *msg32_1 = &e2c->qdesc->msg32[qhead];
+		struct xgene_qmtm_msg_ext32 *msg32_2 = NULL;
+
+		if (unlikely(((u32 *) msg32_1)[EMPTY_SLOT_INDEX] == EMPTY_SLOT))
+			break;
+
+		command--;
+
+		if (msg32_1->msg16.FPQNum)
+			xgene_enet_rx_frame(e2c, msg32_1);
+		else
+			xgene_enet_tx_completion(e2c, msg32_1);
+
+		if (++qhead == count)
+			qhead = 0;
+
+		if (msg32_1->msg16.NV) {
+			msg32_2 = (struct xgene_qmtm_msg_ext32 *)
+			    &e2c->qdesc->msg32[qhead];
+			if (unlikely(((u32 *) msg32_2)[EMPTY_SLOT_INDEX]
+				     == EMPTY_SLOT)) {
+				command++;
+				if (!qhead)
+					qhead = count;
+				qhead--;
+				break;
+			}
+			command--;
+			if (++qhead == count)
+				qhead = 0;
+		}
+
+		((u32 *) msg32_1)[EMPTY_SLOT_INDEX] = EMPTY_SLOT;
+		if (msg32_2)
+			((u32 *) msg32_2)[EMPTY_SLOT_INDEX] = EMPTY_SLOT;
+		processed++;
+	}
+
+	do {
+		nummsgs = (readl(e2c->nummsgs) & 0x1fffe) >> 1;
+	} while (nummsgs < (1 + ~command));
+	writel(command, e2c->qdesc->command);
+	e2c->qdesc->qhead = qhead;
+
+	return processed;
+}
+
+static int xgene_enet_napi(struct napi_struct *napi, const int budget)
+{
+	struct xgene_enet_qcontext *e2c =
+	    container_of(napi, struct xgene_enet_qcontext, napi);
+	int processed = xgene_enet_dequeue_msg(e2c, budget);
+
+	if (processed != budget) {
+		napi_complete(napi);
+		enable_irq(e2c->qdesc->irq);
+	}
+
+	return processed;
+}
+
+static void xgene_enet_timeout(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	xgene_enet_mac_reset(&pdev->priv);
+}
+
+static void xgene_enet_napi_add(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		netif_napi_add(pdev->ndev, &pdev->rx[qindex]->napi,
+			       xgene_enet_napi, 64);
+}
+
+static void xgene_enet_napi_del(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		netif_napi_del(&pdev->rx[qindex]->napi);
+}
+
+static void xgene_enet_napi_enable(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		napi_enable(&pdev->rx[qindex]->napi);
+}
+
+static void xgene_enet_napi_disable(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		napi_disable(&pdev->rx[qindex]->napi);
+}
+
+static void xgene_enet_irq_enable(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		enable_irq(pdev->rx[qindex]->qdesc->irq);
+}
+
+static void xgene_enet_irq_disable_all(struct xgene_enet_pdev *pdev)
+{
+	u32 qindex;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		disable_irq_nosync(pdev->rx[qindex]->qdesc->irq);
+}
+
+static int xgene_enet_open(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	xgene_enet_napi_enable(pdev);
+	xgene_enet_irq_enable(pdev);
+
+	netif_tx_start_all_queues(ndev);
+	netif_carrier_on(ndev);
+
+	if (pdev->phy_dev)
+		phy_start(pdev->phy_dev);
+
+	xgene_enet_mac_tx_state(priv, 1);
+	xgene_enet_mac_rx_state(priv, 1);
+
+	return 0;
+}
+
+static int xgene_enet_close(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+	u32 qindex;
+
+	netif_tx_stop_all_queues(ndev);
+	netif_carrier_off(ndev);
+	netif_tx_disable(ndev);
+
+	if (pdev->phy_dev)
+		phy_stop(pdev->phy_dev);
+
+	xgene_enet_mac_tx_state(priv, 0);
+	xgene_enet_mac_rx_state(priv, 0);
+
+	xgene_enet_irq_disable_all(pdev);
+	xgene_enet_napi_disable(pdev);
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++)
+		xgene_enet_dequeue_msg(pdev->rx[qindex], -1);
+
+	return 0;
+}
+
+static struct xgene_enet_qcontext *xgene_enet_allocq(struct xgene_enet_pdev
+						     *pdev,
+						     struct xgene_qmtm_qinfo
+						     *qinfo,
+						     struct xgene_qmtm_sdev
+						     *sdev, u8 qtype, u8 qsize)
+{
+	struct xgene_enet_qcontext *qc;
+
+	memset(qinfo, 0, sizeof(struct xgene_qmtm_qinfo));
+	qinfo->sdev = sdev;
+	qinfo->qaccess = QACCESS_ALT;
+	qinfo->qtype = qtype;
+	qinfo->qsize = qsize;
+	qinfo->flags = XGENE_SLAVE_DEFAULT_FLAGS;
+
+	if (xgene_qmtm_set_qinfo(qinfo)) {
+		netdev_err(pdev->ndev, "Could not allocate queue\n");
+		return NULL;
+	}
+
+	qc = (struct xgene_enet_qcontext *)
+	    kmalloc(sizeof(struct xgene_enet_qcontext),
+		    GFP_KERNEL | __GFP_ZERO);
+	qc->nummsgs = &(((u32 *) qinfo->qfabric)[1]);
+	qc->qdesc = qinfo->qdesc;
+	qc->pdev = pdev;
+
+	return qc;
+}
+
+static int xgene_enet_qconfig(struct xgene_enet_pdev *pdev)
+{
+	struct xgene_qmtm_qinfo qinfo;
+	struct xgene_qmtm_sdev *sdev = pdev->sdev;
+	struct xgene_qmtm_sdev *idev = pdev->sdev->idev;
+	int qmtm_ip = sdev->qmtm_ip;
+	int port = pdev->priv.port;
+	int rc = 0;
+	u32 qindex;
+	struct xgene_enet_qcontext *e2c;
+	struct xgene_enet_qcontext *c2e;
+
+	memset(&pdev->qm_queues, 0, sizeof(struct eth_queue_ids));
+	pdev->qm_queues.qm_ip = qmtm_ip;
+
+	for (qindex = 0; qindex < pdev->num_tx_queues; qindex++) {
+		/* Allocate EGRESS work queues from CPUx to ETHx */
+		c2e = xgene_enet_allocq(pdev, &qinfo, sdev,
+					      QTYPE_PQ, QSIZE_64KB);
+		if (!c2e)
+			goto out;
+
+		pdev->qm_queues.tx[qindex].qid = qinfo.queue_id;
+
+		/* Setup TX Frame cpu_to_enet info */
+		c2e->msg8 =
+		    (struct xgene_qmtm_msg_ext8 *)
+		    kmalloc(sizeof(struct xgene_qmtm_msg_ext8) * 256 *
+			    c2e->qdesc->count, GFP_KERNEL);
+		c2e->queue_index = qindex;
+		pdev->tx[qindex] = c2e;
+		/* Assign TX completn queue threshold based on rx queue size */
+		pdev->tx_cqt_hi = c2e->qdesc->count / 4;
+		pdev->tx_cqt_low = pdev->tx_cqt_low / 16;
+	}
+
+	pdev->qm_queues.default_tx_qid = pdev->qm_queues.tx[0].qid;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++) {
+		/* Allocate INGRESS work queue from ETHx to CPUx */
+		u8 qsize = QSIZE_512KB;
+		e2c = xgene_enet_allocq(pdev, &qinfo, idev,
+					      QTYPE_PQ, qsize);
+		if (!e2c)
+			goto out;
+
+		pdev->qm_queues.rx[qindex].qid = qinfo.queue_id;
+		e2c->queue_index = qindex;
+		snprintf(e2c->irq_name, sizeof(e2c->irq_name), "%s-rx%d",
+			 pdev->ndev->name, qindex);
+		e2c->c2e_count = 1;
+		pdev->rx[qindex] = e2c;
+
+		/* Allocate free pool for ETHx from CPUx */
+		c2e = xgene_enet_allocq(pdev, &qinfo, sdev,
+					      QTYPE_FP, QSIZE_16KB);
+		if (!c2e)
+			goto out;
+
+		pdev->qm_queues.rx_fp[qindex].qid = qinfo.queue_id;
+		pdev->qm_queues.rx_fp[qindex].pbn = qinfo.pbn;
+
+		c2e->eqnum = QMTM_QUEUE_ID(qmtm_ip, qinfo.queue_id);
+		c2e->buf_size = XGENE_ENET_PKT_BUF_SIZE;
+		pdev->rx_skb_pool[qindex] = c2e;
+		pdev->rx[qindex]->c2e_skb = pdev->rx_skb_pool[qindex];
+
+		/* Configure free pool */
+		xgene_enet_init_fp(pdev->rx_skb_pool[qindex],
+				   pdev->rx_buff_cnt);
+	}
+
+	for (qindex = 0; qindex < pdev->num_tx_queues; qindex++) {
+		u32 cqindex = pdev->num_tx_queues - qindex - 1;
+		u32 rqindex = qindex % pdev->num_rx_queues;
+
+		pdev->tx[cqindex]->nummsgs = pdev->rx[rqindex]->nummsgs;
+		pdev->tx[cqindex]->eqnum = QMTM_QUEUE_ID(qmtm_ip,
+							 pdev->qm_queues.
+							 rx[rqindex].qid);
+	}
+
+	pdev->qm_queues.default_hw_tx_qid = pdev->qm_queues.hw_tx[0].qid;
+	pdev->qm_queues.default_rx_qid = pdev->qm_queues.rx[0].qid;
+	pdev->qm_queues.default_rx_fp_qid = pdev->qm_queues.rx_fp[0].qid;
+	pdev->qm_queues.default_rx_fp_pbn = pdev->qm_queues.rx_fp[0].pbn;
+	pdev->qm_queues.default_rx_nxtfp_qid = pdev->qm_queues.rx_nxtfp[0].qid;
+	pdev->qm_queues.default_rx_nxtfp_pbn = pdev->qm_queues.rx_nxtfp[0].pbn;
+
+	netdev_dbg(pdev->ndev, "Port %d CQID %d FP %d FP PBN %d\n",
+		   port, pdev->qm_queues.default_comp_qid,
+		   pdev->qm_queues.default_rx_fp_qid,
+		   pdev->qm_queues.default_rx_fp_pbn);
+
+out:
+	return rc;
+}
+
+static void xgene_enet_delete_queue(struct xgene_enet_pdev *pdev)
+{
+	struct xgene_qmtm_qinfo qinfo;
+	u32 qindex;
+	u8 qmtm_ip = pdev->sdev->qmtm_ip;
+	u16 queue_id;
+
+	qinfo.qmtm_ip = qmtm_ip;
+
+	for (qindex = 0; qindex < pdev->num_tx_queues; qindex++) {
+		queue_id = pdev->qm_queues.tx[qindex].qid;
+
+		if (queue_id) {
+			qinfo.queue_id = queue_id;
+			xgene_qmtm_clr_qinfo(&qinfo);
+		}
+	}
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++) {
+		queue_id = pdev->qm_queues.rx[qindex].qid;
+
+		if (queue_id) {
+			qinfo.queue_id = queue_id;
+			xgene_qmtm_clr_qinfo(&qinfo);
+		}
+
+		queue_id = pdev->qm_queues.rx_fp[qindex].qid;
+
+		if (queue_id) {
+			qinfo.queue_id = queue_id;
+			xgene_qmtm_clr_qinfo(&qinfo);
+		}
+	}
+}
+
+static struct net_device_stats *xgene_enet_stats(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &(pdev->priv);
+	struct net_device_stats *nst = &pdev->nstats;
+	struct xgene_enet_detailed_stats detailed_stats;
+	struct xgene_enet_rx_stats *rx_stats;
+	struct xgene_enet_tx_stats *tx_stats;
+	u32 pkt_bytes, crc_bytes = 4;
+
+	memset(&detailed_stats, 0, sizeof(struct xgene_enet_detailed_stats));
+
+	rx_stats = &detailed_stats.rx_stats;
+	tx_stats = &detailed_stats.tx_stats;
+
+	local_irq_disable();
+	xgene_enet_get_stats(priv, &detailed_stats);
+
+	pkt_bytes = rx_stats->rx_byte_count;
+	pkt_bytes -= (rx_stats->rx_packet_count * crc_bytes);
+	nst->rx_packets += rx_stats->rx_packet_count;
+	nst->rx_bytes += pkt_bytes;
+
+	pkt_bytes = tx_stats->tx_byte_count;
+	pkt_bytes -= (tx_stats->tx_pkt_count * crc_bytes);
+	nst->tx_packets += tx_stats->tx_pkt_count;
+	nst->tx_bytes += pkt_bytes;
+
+	nst->rx_dropped += rx_stats->rx_drop_pkt_count;
+	nst->tx_dropped += tx_stats->tx_drop_frm_count;
+
+	nst->rx_crc_errors += rx_stats->rx_fcs_err_count;
+	nst->rx_length_errors += rx_stats->rx_frm_len_err_pkt_count;
+	nst->rx_frame_errors += rx_stats->rx_alignment_err_pkt_count;
+	nst->rx_over_errors += (rx_stats->rx_oversize_pkt_count
+				+ pdev->stats.estats.rx_hw_overrun);
+
+	nst->rx_errors += (rx_stats->rx_fcs_err_count
+			   + rx_stats->rx_frm_len_err_pkt_count
+			   + rx_stats->rx_oversize_pkt_count
+			   + rx_stats->rx_undersize_pkt_count
+			   + pdev->stats.estats.rx_hw_overrun
+			   + pdev->stats.estats.rx_hw_errors);
+
+	nst->tx_errors += tx_stats->tx_fcs_err_frm_count +
+	    tx_stats->tx_undersize_frm_count;
+
+	local_irq_enable();
+
+	pdev->stats.estats.rx_hw_errors = 0;
+	pdev->stats.estats.rx_hw_overrun = 0;
+
+	return nst;
+}
+
+static int xgene_enet_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &(pdev->priv);
+	struct sockaddr *addr = p;
+
+	if (netif_running(ndev))
+		return -EBUSY;
+
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+	xgene_enet_set_mac_addr(priv, (unsigned char *)(ndev->dev_addr));
+	return 0;
+}
+
+/* net_device_ops structure for data path ethernet */
+static const struct net_device_ops apm_dnetdev_ops = {
+	.ndo_open = xgene_enet_open,
+	.ndo_stop = xgene_enet_close,
+	.ndo_select_queue = xgene_enet_select_queue,
+	.ndo_start_xmit = xgene_enet_start_xmit,
+	.ndo_tx_timeout = xgene_enet_timeout,
+	.ndo_get_stats = xgene_enet_stats,
+	.ndo_change_mtu = xgene_enet_change_mtu,
+	.ndo_set_mac_address = xgene_enet_set_mac_address,
+};
+
+static void xgene_enet_register_irq(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev;
+	struct device *dev;
+	u32 qindex;
+
+	pdev = (struct xgene_enet_pdev *)netdev_priv(ndev);
+	dev = &pdev->plat_dev->dev;
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++) {
+		if (devm_request_irq(dev, pdev->rx[qindex]->qdesc->irq,
+				xgene_enet_e2c_irq, 0,
+				pdev->rx[qindex]->irq_name,
+				(void *)pdev->rx[qindex]) != 0) {
+			netdev_err(ndev, "request_irq failed %d for RX Frame\n",
+				   pdev->rx[qindex]->qdesc->irq);
+			return;
+		}
+
+		/* Disable interrupts for RX queue mailboxes */
+		disable_irq_nosync(pdev->rx[qindex]->qdesc->irq);
+	}
+}
+
+static int xgene_enet_get_resources(struct xgene_enet_pdev *pdev)
+{
+	struct platform_device *plat_dev;
+	struct net_device *ndev;
+	struct device *dev;
+	struct xgene_enet_priv *priv;
+	struct xgene_qmtm_sdev *sdev;
+	struct xgene_enet_platform_data pdata;
+	struct resource *res;
+	u64 csr_paddr;
+	void *csr_addr;
+	int i, rc;
+
+	plat_dev = pdev->plat_dev;
+	dev = &plat_dev->dev;
+	ndev = pdev->ndev;
+	priv = &pdev->priv;
+
+	rc = of_property_read_u32(plat_dev->dev.of_node, "devid",
+				  &pdata.port_id);
+	if (rc || pdata.port_id >= MAX_ENET_PORTS) {
+		dev_err(dev, "No device ID or invalid value %d\n",
+			pdata.port_id);
+		goto out;
+	}
+	priv->port = pdata.port_id;
+
+	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+		rc = -ENODEV;
+		goto out;
+	}
+	csr_paddr = res->start;
+	csr_addr = devm_ioremap(&plat_dev->dev, csr_paddr, resource_size(res));
+	priv->ppaddr_base = csr_paddr;
+	priv->vpaddr_base = csr_addr;
+
+	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(dev, "Unable to retrieve ENET Global CSR region\n");
+		rc = -ENODEV;
+		goto out;
+	}
+	csr_paddr = res->start;
+	csr_addr = devm_ioremap(&plat_dev->dev, csr_paddr, resource_size(res));
+	priv->paddr_base = csr_paddr;
+	priv->vaddr_base = csr_addr;
+
+	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_err(dev, "Unable to retrieve ENET MII access region\n");
+		rc = -ENODEV;
+		goto out;
+	}
+	csr_paddr = res->start;
+	csr_addr = devm_ioremap(&plat_dev->dev, csr_paddr, resource_size(res));
+	priv->vmii_base = csr_addr;
+
+	rc = of_property_read_string(plat_dev->dev.of_node, "slave-name",
+				     &pdata.sname);
+
+	sdev = xgene_qmtm_get_sdev((char *)pdata.sname);
+	if (!sdev) {
+		dev_err(dev, "QMTM Slave %s error\n", pdata.sname);
+		rc = -ENODEV;
+		goto out;
+	}
+	pdev->sdev = sdev;
+
+	rc = of_property_read_u32(plat_dev->dev.of_node, "phyid",
+				  &pdata.phy_id);
+	if (rc || pdata.phy_id > 0x1F) {
+		dev_err(dev, "No phy ID or invalid value in DTS\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	priv->phy_addr = pdata.phy_id;
+
+	rc = of_property_read_u8_array(plat_dev->dev.of_node,
+				       "local-mac-address", pdata.ethaddr,
+				       ARRAY_SIZE(pdata.ethaddr));
+	if (rc) {
+		dev_err(dev, "Can't get Device MAC address\n");
+	} else {
+		for (i = 0; i < ETH_ALEN; i++)
+			ndev->dev_addr[i] = pdata.ethaddr[i] & 0xff;
+	}
+
+	pdev->clk = clk_get(&plat_dev->dev, NULL);
+
+	if (IS_ERR(pdev->clk))
+		dev_err(&plat_dev->dev, "can't get clock\n");
+	else if (clk_prepare_enable(pdev->clk))
+		dev_err(&plat_dev->dev, "clock prepare enable failed");
+
+	priv->phy_mode = PHY_MODE_RGMII;
+	pdev->rx_buff_cnt = XGENE_NUM_PKT_BUF;
+
+out:
+	return rc;
+}
+
+static int xgene_enet_init_hw(struct xgene_enet_pdev *pdev)
+{
+	struct net_device *ndev;
+	struct xgene_enet_priv *priv;
+	struct mii_bus *mdio_bus;
+	int rc = 0;
+
+	ndev = pdev->ndev;
+	priv = &pdev->priv;
+
+	xgene_enet_port_reset(priv);
+
+	/* To ensure no packet enters the system, disable Rx/Tx */
+	xgene_enet_mac_tx_state(priv, 0);
+	xgene_enet_mac_rx_state(priv, 0);
+
+	ndev->netdev_ops = &apm_dnetdev_ops;
+
+	ndev->features |= NETIF_F_IP_CSUM;
+	ndev->features |= NETIF_F_TSO | NETIF_F_SG;
+	pdev->mss = DEFAULT_TCP_MSS;
+	xgene_enet_tx_offload(priv, XGENE_ENET_MSS0, pdev->mss);
+	ndev->features |= NETIF_F_GRO;
+
+	/* Ethtool checks the capabilities/features in hw_features flag */
+	ndev->hw_features = ndev->features;
+
+	rc = register_netdev(ndev);
+	if (rc) {
+		netdev_err(ndev, "Failed to register net dev(%d)!\n", rc);
+		goto out;
+	}
+
+	rc = xgene_enet_qconfig(pdev);
+	if (rc) {
+		netdev_err(ndev, "Error in QM configuration\n");
+		goto out;
+	}
+
+	xgene_enet_napi_add(pdev);
+
+	xgene_enet_cle_bypass(priv, QMTM_QUEUE_ID(pdev->sdev->qmtm_ip,
+						  pdev->qm_queues.
+						  default_rx_qid),
+			      pdev->qm_queues.default_rx_fp_pbn - 0x20);
+
+	/* Default MAC initialization */
+	xgene_enet_mac_init(priv, ndev->dev_addr, SPEED_1000,
+			    HW_MTU(ndev->mtu), priv->crc);
+
+	/* Setup MDIO bus */
+	mdio_bus = mdiobus_alloc();
+	if (!mdio_bus) {
+		netdev_err(ndev, "Not able to allocate memory for MDIO bus\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	pdev->mdio_bus = mdio_bus;
+	mdio_bus->name = "APM Ethernet MII Bus";
+	mdio_bus->read = xgene_enet_mdio_read;
+	mdio_bus->write = xgene_enet_mdio_write;
+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%x", priv->port);
+	mdio_bus->priv = pdev;
+	mdio_bus->parent = &ndev->dev;
+	mdio_bus->phy_mask = ~(1 << priv->phy_addr);
+	rc = mdiobus_register(mdio_bus);
+	if (rc) {
+		netdev_err(ndev, "Failed to register MDIO bus(%d)!\n", rc);
+		return rc;
+	}
+
+	rc = xgene_enet_mdio_probe(ndev);
+	xgene_enet_register_irq(ndev);
+
+out:
+	return rc;
+}
+
+static int xgene_enet_probe(struct platform_device *plat_dev)
+{
+	struct net_device *ndev;
+	struct xgene_enet_pdev *pdev;
+	struct device *dev;
+	struct xgene_enet_priv *priv;
+	u32 num_tx_queues, num_rx_queues;
+	int rc;
+
+	dev = &plat_dev->dev;
+	num_tx_queues = MAX_TX_QUEUES;
+	num_rx_queues = MAX_RX_QUEUES;
+
+	ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdev),
+				  num_tx_queues, num_rx_queues);
+
+	if (!ndev) {
+		dev_err(dev, "Not able to allocate memory for netdev\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	pdev = (struct xgene_enet_pdev *)netdev_priv(ndev);
+	priv = &pdev->priv;
+	pdev->ndev = ndev;
+	pdev->num_tx_queues = num_tx_queues;
+	pdev->num_rx_queues = num_rx_queues;
+	pdev->plat_dev = plat_dev;
+	pdev->node = plat_dev->dev.of_node;
+	SET_NETDEV_DEV(ndev, &plat_dev->dev);
+	dev_set_drvdata(&plat_dev->dev, pdev);
+
+	xgene_enet_get_resources(pdev);
+
+	xgene_enet_init_priv(priv);
+	rc = xgene_enet_init_hw(pdev);
+
+out:
+	return rc;
+}
+
+static int xgene_enet_remove(struct platform_device *plat_dev)
+{
+	struct xgene_enet_pdev *pdev;
+	struct xgene_enet_priv *priv;
+	struct net_device *ndev;
+	int port;
+	u32 qindex;
+	u8 qmtm_ip;
+
+	pdev = platform_get_drvdata(plat_dev);
+	qmtm_ip = pdev->sdev->qmtm_ip;
+	ndev = pdev->ndev;
+	priv = &pdev->priv;
+
+	port = xgene_enet_get_port(pdev);
+
+	/* Stop any traffic and disable MAC */
+	xgene_enet_mac_rx_state(priv, 0);
+	xgene_enet_mac_tx_state(priv, 0);
+
+	if (netif_running(ndev)) {
+		netif_device_detach(ndev);
+		netif_stop_queue(ndev);
+		xgene_enet_napi_disable(pdev);
+	}
+
+	xgene_enet_napi_del(pdev);
+	xgene_enet_mdio_remove(ndev);
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++) {
+		if (pdev->qm_queues.rx_fp[qindex].qid > 0)
+			xgene_enet_deinit_fp(pdev->rx_skb_pool[qindex],
+					     pdev->qm_queues.rx_fp[qindex].qid);
+	}
+
+	xgene_enet_delete_queue(pdev);
+
+	for (qindex = 0; qindex < pdev->num_rx_queues; qindex++) {
+		kfree(pdev->rx_skb_pool[qindex]);
+		kfree(pdev->rx[qindex]);
+	}
+	for (qindex = 0; qindex < pdev->num_tx_queues; qindex++) {
+		kfree(pdev->tx[qindex]->msg8);
+		kfree(pdev->tx[qindex]);
+	}
+
+	unregister_netdev(ndev);
+	xgene_enet_port_shutdown(priv);
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+static struct of_device_id xgene_enet_match[] = {
+	{
+	 .compatible = "apm,xgene-enet",
+	 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_enet_match);
+
+static struct platform_driver xgene_enet_driver = {
+	.driver = {
+		   .name = XGENE_ENET_DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   .of_match_table = xgene_enet_match,
+		   },
+	.probe = xgene_enet_probe,
+	.remove = xgene_enet_remove,
+};
+
+static int __init xgene_enet_init(void)
+{
+	if (!platform_driver_register(&xgene_enet_driver))
+		pr_info("%s v%s loaded\n", XGENE_ENET_DRIVER_DESC,
+				XGENE_ENET_DRIVER_VERSION);
+
+	return 0;
+}
+
+static void __exit xgene_enet_exit(void)
+{
+	platform_driver_unregister(&xgene_enet_driver);
+	pr_info("%s v%s unloaded\n", XGENE_ENET_DRIVER_DESC,
+			XGENE_ENET_DRIVER_VERSION);
+}
+
+module_init(xgene_enet_init);
+module_exit(xgene_enet_exit);
+
+MODULE_DESCRIPTION(XGENE_ENET_DRIVER_DESC);
+MODULE_VERSION(XGENE_ENET_DRIVER_VERSION);
+MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
new file mode 100644
index 0000000..15ea995
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -0,0 +1,172 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __XGENE_ENET_MAIN_H__
+#define __XGENE_ENET_MAIN_H__
+
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/tcp.h>
+#include <linux/interrupt.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+#include <linux/io.h>
+#include <misc/xgene/xgene_qmtm.h>
+#include "xgene_enet_common.h"
+
+#define XGENE_ENET_DRIVER_NAME "xgene-enet"
+#define XGENE_ENET_DRIVER_VERSION "1.0"
+#define XGENE_ENET_DRIVER_DESC "APM X-Gene SoC Ethernet driver"
+
+#define XGENE_ENET_MIN_MTU		64
+#define XGENE_ENET_MAX_MTU		10000
+
+/* Note: PKT_BUF_SIZE & PKT_NXTBUF_SIZE has to be one of the following:
+ * 256, 1K, 2K, 4K, 16K for ethernet to work with optimum performance.
+ */
+#define XGENE_ENET_PKT_BUF_SIZE		2048
+#define XGENE_NUM_PKT_BUF		256
+
+/* define Enet system struct */
+struct xgene_enet_dev {
+	int refcnt;
+	struct timer_list link_poll_timer;
+	int ipp_loaded;
+	int ipp_hw_mtu;
+};
+
+enum xgene_enet_phy_poll_interval {
+	PHY_POLL_LINK_ON = HZ,
+	PHY_POLL_LINK_OFF = (HZ / 5)
+};
+
+enum xgene_enet_debug_cmd {
+	XGENE_ENET_READ_CMD,
+	XGENE_ENET_WRITE_CMD,
+	XGENE_ENET_MAX_CMD
+};
+
+#define MAX_TX_QUEUES 1
+#define MAX_RX_QUEUES 1
+
+/* This is soft flow context of queue */
+struct xgene_enet_qcontext {
+	struct xgene_enet_pdev *pdev;
+	struct xgene_qmtm_qdesc *qdesc;
+	struct xgene_qmtm_msg_ext8 *msg8;
+	u32 *nummsgs;
+	unsigned int queue_index;
+	unsigned int eqnum;
+	u32 buf_size;
+	unsigned int c2e_count;
+	struct xgene_enet_qcontext *c2e_skb;
+	struct xgene_enet_qcontext *c2e_page;
+	struct napi_struct napi;
+	char irq_name[16];
+};
+
+/* Queues related parameters per Enet port */
+#define ENET_MAX_PBN	8
+#define ENET_MAX_QSEL	8
+
+struct eth_wqids {
+	u16 qtype;
+	u16 qid;
+	u16 arb;
+	u16 qcount;
+	u16 qsel[ENET_MAX_QSEL];
+};
+
+struct eth_fqids {
+	u16 qid;
+	u16 pbn;
+};
+
+struct eth_queue_ids {
+	u16 default_tx_qid;
+	u16 tx_count;
+	u16 tx_idx;
+	struct eth_wqids tx[ENET_MAX_PBN];
+	u16 default_rx_qid;
+	u16 rx_count;
+	u16 rx_idx;
+	struct eth_wqids rx[ENET_MAX_PBN];
+	u16 default_rx_fp_qid;
+	u16 default_rx_fp_pbn;
+	struct eth_fqids rx_fp[ENET_MAX_PBN];
+	u16 default_rx_nxtfp_qid;
+	u16 default_rx_nxtfp_pbn;
+	struct eth_fqids rx_nxtfp[ENET_MAX_PBN];
+	struct eth_fqids hw_fp;
+	u16 default_hw_tx_qid;
+	struct eth_fqids hw_tx[ENET_MAX_PBN];
+	struct eth_wqids comp[ENET_MAX_PBN];
+	u16 default_comp_qid;
+	u32 qm_ip;
+};
+
+struct xgene_enet_platform_data {
+	u32 port_id;
+	const char *sname;
+	u32 phy_id;
+	u8 ethaddr[6];
+};
+
+/* APM ethernet per port data */
+struct xgene_enet_pdev {
+	struct net_device *ndev;
+	struct mii_bus *mdio_bus;
+	struct phy_device *phy_dev;
+	int phy_link;
+	int phy_speed;
+	struct clk *clk;
+	struct device_node *node;
+	struct platform_device *plat_dev;
+	struct xgene_qmtm_sdev *sdev;
+	struct xgene_enet_qcontext *tx[MAX_TX_QUEUES];
+	struct xgene_enet_qcontext *rx_skb_pool[MAX_RX_QUEUES];
+	u32 num_tx_queues;
+	struct xgene_enet_qcontext *rx[MAX_RX_QUEUES];
+	struct xgene_enet_qcontext *tx_completion[MAX_TX_QUEUES];
+	u32 num_rx_queues;
+	struct net_device_stats nstats;
+	struct xgene_enet_detailed_stats stats;
+	char *dev_name;
+	int uc_count;
+	struct eth_queue_ids qm_queues;
+	u32 rx_buff_cnt, tx_cqt_low, tx_cqt_hi;
+	int mss;
+	struct xgene_enet_priv priv;
+};
+
+/* Ethernet raw register write, read routines */
+void xgene_enet_wr32(void *addr, u32 data);
+void xgene_enet_rd32(void *addr, u32 *data);
+
+u32 xgene_enet_get_port(struct xgene_enet_pdev *pdev);
+
+void xgene_enet_init_priv(struct xgene_enet_priv *priv);
+
+int xgene_enet_parse_error(u8 LErr, int qid);
+void xgene_enet_register_err_irqs(struct net_device *ndev);
+
+#endif /* __XGENE_ENET_MAIN_H__ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
                   ` (2 preceding siblings ...)
  2013-12-21  3:42 ` [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver Iyappan Subramanian
@ 2013-12-21  3:42 ` Iyappan Subramanian
  2013-12-22  9:34   ` Arnd Bergmann
  2013-12-21  3:42 ` [PATCH 5/5] drivers: net: APM X-Gene SoC Ethernet driver ethtool support Iyappan Subramanian
  2013-12-22  9:35 ` [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Arnd Bergmann
  5 siblings, 1 reply; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

Error handling and error interrupt handler code.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
 drivers/net/ethernet/apm/xgene/Makefile          |    3 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h  |  265 +++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_err.c  |  715 ++++++++++++++++++++++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c |   27 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |    4 +
 5 files changed, 1011 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_err.c

diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
index 16dfc6c..091547e 100644
--- a/drivers/net/ethernet/apm/xgene/Makefile
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -5,6 +5,7 @@
 xgene-enet-objs := \
 		xgene_enet_common.o	\
 		xgene_enet_mac.o	\
-		xgene_enet_main.o
+		xgene_enet_main.o	\
+		xgene_enet_err.o
 
 obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
index c6b49c9..858d155 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
@@ -19,6 +19,13 @@
 #ifndef __XGENE_ENET_CSR_H__
 #define __XGENE_ENET_CSR_H__
 
+#define RSIF_INT_REG0_ADDR                                           0x00000054
+#define RSIF_FINT_REG0_ADDR                                          0x0000005c
+#define TSIF_INT_REG0_ADDR                                           0x0000012c
+#define TSIF_FINT_REG0_ADDR                                          0x00000134
+#define TSO_INT_REG0_ADDR                                            0x00000324
+#define SPI2SAP_INT_REG0_ADDR                                        0x00000448
+#define RX_TX_BUF_CHKSM_INT_REG0_ADDR                                0x0000052c
 #define ENET_SPARE_CFG_REG_ADDR                                      0x00000750
 #define RSIF_CONFIG_REG_ADDR                                         0x00000010
 #define RSIF_RAM_DBG_REG0_ADDR                                       0x00000048
@@ -33,7 +40,108 @@
 #define TSIF_MSS_REG1_0_ADDR                                         0x00000110
 #define TSO_CFG_0_ADDR                                               0x00000314
 #define TSO_CFG_INSERT_VLAN_0_ADDR                                   0x0000031c
-#define CFG_RSIF_FPBUFF_TIMEOUT_EN_WR(src)      (((u32)(src)<<31) & 0x80000000)
+#define CFG_RSIF_FPBUFF_TIMEOUT_EN_WR(src) \
+	(((u32)(src)<<31) & 0x80000000)
+#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_MASK                 0x20000000
+#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x20000000)>>29)
+#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_MASK                0x10000000
+#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x10000000)>>28)
+#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK               0x08000000
+#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x08000000)>>27)
+#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK              0x04000000
+#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x04000000)>>26)
+#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK            0x02000000
+#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x02000000)>>25)
+#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK           0x01000000
+#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x01000000)>>24)
+#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK                  0x00800000
+#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00800000)>>23)
+#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK                 0x00400000
+#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00400000)>>22)
+#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_MASK                   0x00200000
+#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00200000)>>21)
+#define RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK                  0x00100000
+#define RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00100000)>>20)
+#define RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT10_MASK                  0x00080000
+#define RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00080000)>>19)
+#define RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK                 0x00040000
+#define RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00040000)>>18)
+#define RSIF_BUF_FIFO_OVERFL_INTR_RXPRT10_MASK                       0x00020000
+#define RSIF_BUF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00020000)>>17)
+#define RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT10_MASK                      0x00010000
+#define RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
+	(((src) & 0x00010000)>>16)
+#define ENET_RSIF_PLC_CLEBUFF_FIFO_OVERFL_INTR0_MASK              0x00008000
+#define ENET_RSIF_PLC_CLEBUFF_FIFO_OVERFL_INTR0_RD(src) \
+	(((src) & 0x00008000)>>15)
+#define ENET_RSIF_PLC_CLEBUFF_FIFO_UNDERFL_INTR0_RD(src) \
+	(((src) & 0x00004000)>>14)
+#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT00_MASK                0x00001000
+#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00001000)>>12)
+#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT00_MASK                 0x00002000
+#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00002000)>>13)
+#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK               0x00000800
+#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000800)>>11)
+#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK              0x00000400
+#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000400)>>10)
+#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK            0x00000200
+#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000200)>>9)
+#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK           0x00000100
+#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000100)>>8)
+#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK                  0x00000080
+#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(src) (((src) & 0x00000080)>>7)
+#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK                 0x00000040
+#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000040)>>6)
+#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT00_MASK                   0x00000020
+#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT00_RD(src) (((src) & 0x00000020)>>5)
+#define RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK                  0x00000010
+#define RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) (((src) & 0x00000010)>>4)
+#define RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT00_MASK                  0x00000008
+#define RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT00_RD(src) (((src) & 0x00000008)>>3)
+#define RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK                 0x00000004
+#define RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(src) \
+	(((src) & 0x00000004)>>2)
+#define RSIF_BUF_FIFO_OVERFL_INTR_RXPRT00_MASK                       0x00000002
+#define RSIF_BUF_FIFO_OVERFL_INTR_RXPRT00_RD(src)     (((src) & 0x00000002)>>1)
+#define RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT00_MASK                      0x00000001
+#define RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT00_RD(src)       (((src) & 0x00000001))
+#define RSIF_SS_MIRRORERR_INTR_RXPRT10_MASK                          0x00080000
+#define RSIF_SS_MIRRORERR_INTR_RXPRT10_RD(src)       (((src) & 0x00080000)>>19)
+#define RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT10_RD(src)  (((src) & 0x00040000)>>18)
+#define RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT10_MASK                     0x00020000
+#define RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT10_RD(src)  (((src) & 0x00020000)>>17)
+#define RSIF_SS_AXI_WRERR_INTR_RXPRT10_MASK                          0x00010000
+#define RSIF_SS_AXI_WRERR_INTR_RXPRT10_RD(src)       (((src) & 0x00010000)>>16)
+#define RSIF_SS_MIRRORERR_INTR_RXPRT00_MASK                          0x00000010
+#define RSIF_SS_MIRRORERR_INTR_RXPRT00_RD(src)        (((src) & 0x00000010)>>4)
+#define RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT00_MASK                     0x00000008
+#define RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT00_RD(src)   (((src) & 0x00000008)>>3)
+#define RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT00_MASK                     0x00000004
+#define RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT00_RD(src)   (((src) & 0x00000004)>>2)
+#define RSIF_SS_AXI_WRERR_INTR_RXPRT00_MASK                          0x00000002
+#define RSIF_SS_AXI_WRERR_INTR_RXPRT00_RD(src)        (((src) & 0x00000002)>>1)
+#define STS_RSIF_PLC_DROP0_MASK                                      0x00000001
+#define STS_RSIF_PLC_DROP0_RD(src)                       (((src) & 0x00000001))
 #define CFG_TSIF_MSS_SZ10_SET(dst, src) \
 	(((dst) & ~0x3fff0000) | (((u32)(src)<<16) & 0x3fff0000))
 #define CFG_TSIF_MSS_SZ00_SET(dst, src) \
@@ -42,7 +150,99 @@
 	(((dst) & ~0x00003fff) | (((u32)(src)) & 0x00003fff))
 #define CFG_TSIF_MSS_SZ30_SET(dst, src) \
 	(((dst) & ~0x3fff0000) | (((u32)(src)<<16) & 0x3fff0000))
+#define TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT10_MASK                     0x00200000
+#define TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT10_RD(src)  (((src) & 0x00200000)>>21)
+#define TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT10_MASK                    0x00100000
+#define TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT10_RD(src) (((src) & 0x00100000)>>20)
+#define TSIF_RRM_FIFO_OVERFL_INTR_PRT10_MASK                         0x00080000
+#define TSIF_RRM_FIFO_OVERFL_INTR_PRT10_RD(src)      (((src) & 0x00080000)>>19)
+#define TSIF_RRM_FIFO_UNDERFL_INTR_PRT10_MASK                        0x00040000
+#define TSIF_RRM_FIFO_UNDERFL_INTR_PRT10_RD(src)     (((src) & 0x00040000)>>18)
+#define TSIF_AMABUF_FIFO_OVERFL_INTR_PRT10_MASK                      0x00020000
+#define TSIF_AMABUF_FIFO_OVERFL_INTR_PRT10_RD(src)   (((src) & 0x00020000)>>17)
+#define TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT10_MASK                     0x00010000
+#define TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT10_RD(src)  (((src) & 0x00010000)>>16)
+#define TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT00_MASK                     0x00000020
+#define TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT00_RD(src)   (((src) & 0x00000020)>>5)
+#define TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT00_MASK                    0x00000010
+#define TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT00_RD(src)  (((src) & 0x00000010)>>4)
+#define TSIF_RRM_FIFO_OVERFL_INTR_PRT00_MASK                         0x00000008
+#define TSIF_RRM_FIFO_OVERFL_INTR_PRT00_RD(src)       (((src) & 0x00000008)>>3)
+#define TSIF_RRM_FIFO_UNDERFL_INTR_PRT00_MASK                        0x00000004
+#define TSIF_RRM_FIFO_UNDERFL_INTR_PRT00_RD(src)      (((src) & 0x00000004)>>2)
+#define TSIF_AMABUF_FIFO_OVERFL_INTR_PRT00_MASK                      0x00000002
+#define TSIF_AMABUF_FIFO_OVERFL_INTR_PRT00_RD(src)    (((src) & 0x00000002)>>1)
+#define TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT00_MASK                     0x00000001
+#define TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT00_RD(src)      (((src) & 0x00000001))
+#define TSIF_SS_AXI_LLRDERR_INTR_PRT10_MASK                          0x00040000
+#define TSIF_SS_AXI_LLRDERR_INTR_PRT10_RD(src)       (((src) & 0x00040000)>>18)
+#define TSIF_SS_AXI_RDERR_INTR_PRT10_MASK                            0x00020000
+#define TSIF_SS_AXI_RDERR_INTR_PRT10_RD(src)         (((src) & 0x00020000)>>17)
+#define TSIF_SS_BAD_MSG_INTR_PRT10_MASK                              0x00010000
+#define TSIF_SS_BAD_MSG_INTR_PRT10_RD(src)           (((src) & 0x00010000)>>16)
+#define TSIF_SS_AXI_LLRDERR_INTR_PRT00_MASK                          0x00000004
+#define TSIF_SS_AXI_LLRDERR_INTR_PRT00_RD(src)        (((src) & 0x00000004)>>2)
+#define TSIF_SS_AXI_RDERR_INTR_PRT00_MASK                            0x00000002
+#define TSIF_SS_AXI_RDERR_INTR_PRT00_RD(src)          (((src) & 0x00000002)>>1)
+#define TSIF_SS_BAD_MSG_INTR_PRT00_MASK                              0x00000001
+#define TSIF_SS_BAD_MSG_INTR_PRT00_RD(src)               (((src) & 0x00000001))
 #define RESUME_TX_WR(src)                           (((u32)(src)) & 0x00000001)
+#define MB_TTF_FIFO_OVERFL_INTR_PRT10_RD(src)        (((src) & 0x00200000)>>21)
+#define MB_TTF_FIFO_OVERFL_INTR_PRT10_MASK                           0x00200000
+#define MB_TTF_FIFO_UNDERFL_INTR_PRT10_RD(src)       (((src) & 0x00100000)>>20)
+#define MB_TTF_FIFO_UNDERFL_INTR_PRT10_MASK                          0x00100000
+#define MH_DEALLOC_FIFO_OVERFL_INTR_PRT10_RD(src)    (((src) & 0x00080000)>>19)
+#define MH_DEALLOC_FIFO_OVERFL_INTR_PRT10_MASK                       0x00080000
+#define MH_DEALLOC_FIFO_UNDERFL_INTR_PRT10_RD(src)   (((src) & 0x00040000)>>18)
+#define MH_DEALLOC_FIFO_UNDERFL_INTR_PRT10_MASK                      0x00040000
+#define MH_FIFO_OVERFL_INTR_PRT10_RD(src)            (((src) & 0x00020000)>>17)
+#define MH_FIFO_OVERFL_INTR_PRT10_MASK                               0x00020000
+#define MH_FIFO_UNDERFL_INTR_PRT10_RD(src)           (((src) & 0x00010000)>>16)
+#define MH_FIFO_UNDERFL_INTR_PRT10_MASK                              0x00010000
+#define MB_TTF_FIFO_OVERFL_INTR_PRT00_RD(src)         (((src) & 0x00000020)>>5)
+#define MB_TTF_FIFO_OVERFL_INTR_PRT00_MASK                           0x00000020
+#define MB_TTF_FIFO_UNDERFL_INTR_PRT00_RD(src)        (((src) & 0x00000010)>>4)
+#define MB_TTF_FIFO_UNDERFL_INTR_PRT00_MASK                          0x00000010
+#define MH_DEALLOC_FIFO_OVERFL_INTR_PRT00_RD(src)     (((src) & 0x00000008)>>3)
+#define MH_DEALLOC_FIFO_OVERFL_INTR_PRT00_MASK                       0x00000008
+#define MH_DEALLOC_FIFO_UNDERFL_INTR_PRT00_RD(src)    (((src) & 0x00000004)>>2)
+#define MH_DEALLOC_FIFO_UNDERFL_INTR_PRT00_MASK                      0x00000004
+#define MH_FIFO_OVERFL_INTR_PRT00_RD(src)             (((src) & 0x00000002)>>1)
+#define MH_FIFO_OVERFL_INTR_PRT00_MASK                               0x00000002
+#define MH_FIFO_UNDERFL_INTR_PRT00_RD(src)               (((src) & 0x00000001))
+#define MH_FIFO_UNDERFL_INTR_PRT00_MASK                              0x00000001
+#define MACIF_FIFO_OVERFL_INTR_RXPRT10_RD(src)       (((src) & 0x00020000)>>17)
+#define MACIF_FIFO_OVERFL_INTR_RXPRT10_MASK                          0x00020000
+#define MACIF_FIFO_OVERFL_INTR_RXPRT00_RD(src)        (((src) & 0x00000002)>>1)
+#define MACIF_FIFO_OVERFL_INTR_RXPRT00_MASK                          0x00000002
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT10_RD(src)      (((src) & 0x00010000)>>16)
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT10_MASK                         0x00010000
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT00_RD(src)          (((src) & 0x00000001))
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT00_MASK                         0x00000001
+#define RXBUF_PAUSE_INTR_PORT10_RD(src)              (((src) & 0x00400000)>>22)
+#define RXBUF_PAUSE_INTR_PORT10_MASK                                 0x00400000
+#define RX_CHKSUM_INTR_PORT10_RD(src)                (((src) & 0x00200000)>>21)
+#define RX_CHKSUM_INTR_PORT10_MASK                                   0x00200000
+#define TX_CHKSUM_INTR_PORT10_RD(src)                (((src) & 0x00100000)>>20)
+#define TX_CHKSUM_INTR_PORT10_MASK                                   0x00100000
+#define RXBUF_FIFO_OVERFL_INTR_PRT10_RD(src)         (((src) & 0x00080000)>>19)
+#define RXBUF_FIFO_OVERFL_INTR_PRT10_MASK                            0x00080000
+#define RXBUF_FIFO_UNDERFL_INTR_PRT10_RD(src)        (((src) & 0x00040000)>>18)
+#define RXBUF_FIFO_UNDERFL_INTR_PRT10_MASK                           0x00040000
+#define TXBUF_FIFO_OVERFL_INTR_PRT10_RD(src)         (((src) & 0x00020000)>>17)
+#define TXBUF_FIFO_UNDERFL_INTR_PRT10_RD(src)        (((src) & 0x00010000)>>16)
+#define RXBUF_PAUSE_INTR_PORT00_RD(src)               (((src) & 0x00000040)>>6)
+#define RX_CHKSUM_INTR_PORT00_RD(src)                 (((src) & 0x00000020)>>5)
+#define RX_CHKSUM_INTR_PORT00_MASK                                   0x00000020
+#define RXBUF_PAUSE_INTR_PORT00_MASK                                 0x00000040
+#define TX_CHKSUM_INTR_PORT00_RD(src)                 (((src) & 0x00000010)>>4)
+#define TX_CHKSUM_INTR_PORT00_MASK                                   0x00000010
+#define RXBUF_FIFO_OVERFL_INTR_PRT00_RD(src)          (((src) & 0x00000008)>>3)
+#define RXBUF_FIFO_OVERFL_INTR_PRT00_MASK                            0x00000008
+#define RXBUF_FIFO_UNDERFL_INTR_PRT00_RD(src)         (((src) & 0x00000004)>>2)
+#define RXBUF_FIFO_UNDERFL_INTR_PRT00_MASK                           0x00000004
+#define TXBUF_FIFO_OVERFL_INTR_PRT00_RD(src)          (((src) & 0x00000002)>>1)
+#define TXBUF_FIFO_UNDERFL_INTR_PRT00_RD(src)            (((src) & 0x00000001))
 #define CFG_SPEED_1250_WR(src)                  (((u32)(src)<<24) & 0x01000000)
 #define CFG_TXCLK_MUXSEL0_WR(src)               (((u32)(src)<<29) & 0xe0000000)
 #define TX_PORT0_WR(src)                            (((u32)(src)) & 0x00000001)
@@ -58,6 +258,8 @@
 	(((dst) & ~0x000f0000) | (((u32)(src)<<16) & 0x000f0000))
 #define CFG_CLE_HENQNUM0_SET(dst, src) \
 	(((dst) & ~0x0fff0000) | (((u32)(src)<<16) & 0x0fff0000))
+#define MAC_INT_REG0_ADDR                                            0x00000514
+#define MAC_INT_REG1_ADDR                                            0x0000051c
 #define ICM_CONFIG0_REG_0_ADDR                                       0x00000400
 #define ICM_CONFIG2_REG_0_ADDR                                       0x00000410
 #define ECM_CONFIG0_REG_0_ADDR                                       0x00000500
@@ -68,10 +270,69 @@
 	(((dst) & ~0x00000002) | (((u32)(src)<<1) & 0x00000002))
 #define RESUME_RX0_SET(dst, src) \
 	(((dst) & ~0x00000001) | (((u32)(src)) & 0x00000001))
+#define ICM_DATA_FIFO_UNDERFL_INTR_PRT10_RD(src)     (((src) & 0x01000000)>>24)
+#define ICM_DATA_FIFO_UNDERFL_INTR_PRT10_MASK                        0x01000000
+#define ICM_DATA_FIFO_OVERFL_INTR_PRT10_MASK                         0x00800000
+#define ICM_CTRL_FIFO_OVERFL_INTR_PRT00_RD(src)       (((src) & 0x00000020)>>5)
+#define ICM_CTRL_FIFO_OVERFL_INTR_PRT00_MASK                         0x00000020
+#define ICM_CTRL_FIFO_OVERFL_INTR_PRT10_RD(src)      (((src) & 0x00200000)>>21)
+#define ICM_CTRL_FIFO_OVERFL_INTR_PRT10_MASK                         0x00200000
+#define ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_RD(src)     (((src) & 0x00400000)>>22)
+#define ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_MASK                        0x00400000
+#define ICM_CTRL_FIFO_UNDERFL_INTR_PRT00_RD(src)      (((src) & 0x00000040)>>6)
+#define ICM_CTRL_FIFO_UNDERFL_INTR_PRT00_MASK                        0x00000040
+#define ICM_DATA_FIFO_OVERFL_INTR_PRT00_RD(src)       (((src) & 0x00000080)>>7)
+#define ICM_DATA_FIFO_OVERFL_INTR_PRT10_RD(src)      (((src) & 0x00800000)>>23)
+#define ICM_DATA_FIFO_OVERFL_INTR_PRT00_MASK                         0x00000080
+#define ICM_DATA_FIFO_UNDERFL_INTR_PRT00_RD(src)      (((src) & 0x00000100)>>8)
+#define ICM_DATA_FIFO_UNDERFL_INTR_PRT00_MASK                        0x00000100
+#define ECM_DATA_FIFO_UNDERN_INTR_PRT00_RD(src)       (((src) & 0x00000010)>>4)
+#define ECM_DATA_FIFO_UNDERN_INTR_PRT00_MASK                         0x00000010
+#define ECM_DATA_FIFO_UNDERN_INTR_PRT10_RD(src)      (((src) & 0x00100000)>>20)
+#define ECM_DATA_FIFO_UNDERN_INTR_PRT10_MASK                         0x00100000
+#define ECM_DATA_FIFO_UNDERFL_INTR_PRT10_RD(src)     (((src) & 0x00080000)>>19)
+#define ECM_DATA_FIFO_UNDERFL_INTR_PRT10_MASK                        0x00080000
+#define ECM_DATA_FIFO_OVERFL_INTR_PRT10_RD(src)      (((src) & 0x00040000)>>18)
+#define ECM_DATA_FIFO_OVERFL_INTR_PRT10_MASK                         0x00040000
+#define CARRY_PORT01_RD(src)                             (((src) & 0x00000001))
+#define CARRY_PORT01_MASK                                            0x00000001
+#define LINKDOWN_PORT11_RD(src)                       (((src) & 0x00000008)>>3)
+#define LINKDOWN_PORT11_MASK                                         0x00000008
+#define CARRY_PORT11_RD(src)                          (((src) & 0x00000004)>>2)
+#define CARRY_PORT11_MASK                                            0x00000004
+#define LINKDOWN_PORT01_RD(src)                       (((src) & 0x00000002)>>1)
+#define LINKDOWN_PORT01_MASK                                         0x00000002
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT00_F2_RD(src)    (((src) & 0x00000002)>>1)
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT00_F2_MASK                      0x00000002
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT10_F2_RD(src)   (((src) & 0x00020000)>>17)
+#define MACIF_FIFO_UNDERFL_INTR_RXPRT10_F2_MASK                      0x00020000
+#define MACIF_FIFO_OVERFL_INTR_RXPRT00_F2_RD(src)        (((src) & 0x00000001))
+#define MACIF_FIFO_OVERFL_INTR_RXPRT00_F2_MASK                       0x00000001
+#define MACIF_FIFO_OVERFL_INTR_RXPRT10_F2_RD(src)    (((src) & 0x00010000)>>16)
+#define MACIF_FIFO_OVERFL_INTR_RXPRT10_F2_MASK                       0x00010000
+#define ECM_DATA_FIFO_UNDERFL_INTR_PRT00_RD(src)      (((src) & 0x00000008)>>3)
+#define ECM_DATA_FIFO_UNDERFL_INTR_PRT00_MASK                        0x00000008
+#define ECM_DATA_FIFO_OVERFL_INTR_PRT00_RD(src)       (((src) & 0x00000004)>>2)
+#define ECM_DATA_FIFO_OVERFL_INTR_PRT00_MASK                         0x00000004
+#define ENET_STSSSQMIINT0_ADDR                                    0x0000009c
+#define ENET_STSSSQMIINT1_ADDR                                    0x000000a4
+#define ENET_STSSSQMIINT2_ADDR                                    0x000000ac
+#define ENET_STSSSQMIINT3_ADDR                                    0x000000b4
+#define ENET_STSSSQMIINT4_ADDR                                    0x000000bc
 #define ENET_CFGSSQMIWQASSOC_ADDR                                 0x000000e0
 #define ENET_CFGSSQMIFPQASSOC_ADDR                                0x000000dc
 #define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR                          0x000000f0
 #define ENET_CFGSSQMIQMLITEWQASSOC_ADDR                           0x000000f4
+#define ENET_FPOVERFLOW0_RD(src)                      (((src) & 0xffffffff))
+#define ENET_WQOVERFLOW1_RD(src)                      (((src) & 0xffffffff))
+#define ENET_FPUNDERRUN2_RD(src)                      (((src) & 0xffffffff))
+#define ENET_WQUNDERRUN3_RD(src)                      (((src) & 0xffffffff))
+#define ENET_AXIWCMR_SLVERR4_RD(src)               (((src) & 0x00000002)>>1)
+#define ENET_AXIWCMR_SLVERR4_MASK                                 0x00000002
+#define ENET_FPOVERFLOW0_MASK                                     0xffffffff
+#define ENET_WQOVERFLOW1_MASK                                     0xffffffff
+#define ENET_FPUNDERRUN2_MASK                                     0xffffffff
+#define ENET_WQUNDERRUN3_MASK                                     0xffffffff
 #define ENET_CLKEN_ADDR                                              0x00000008
 #define ENET_SRST_ADDR                                               0x00000000
 #define CSR0_RESET_WR(src)                          (((u32)(src)) & 0x00000001)
@@ -159,4 +420,4 @@
 #define TX_FCS_ERROR_CNTR_MASK                                       0x00000fff
 #define TX_UNDSIZE_FRAME_CNTR_MASK                                   0x00000fff
 
-#endif /* __XGENE_ENET_CSR_H__ */
+#endif  /* __XGENE_ENET_CSR_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_err.c b/drivers/net/ethernet/apm/xgene/xgene_enet_err.c
new file mode 100644
index 0000000..5be6531
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_err.c
@@ -0,0 +1,715 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Fushen Chen <fchen@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_csr.h"
+
+int xgene_enet_parse_error(u8 LErr, int qid)
+{
+	/* QM Error */
+	switch (LErr) {
+	case 1:
+		pr_err("LErr[%d] QID %d: QM msg size error\n", LErr, qid);
+		return 0;
+	case 2:
+		pr_err("LErr[%d] QID %d: QM msg hop count error\n", LErr, qid);
+		return 0;
+	case 3:
+		pr_err("LErr[%d] QID %d: enqueue to virtual queue error\n",
+		       LErr, qid);
+		return 0;
+	case 4:
+		pr_err("LErr[%d] QID %d: enqueue to disable queue error\n",
+		       LErr, qid);
+		return 0;
+	case 5:
+		pr_debug("LErr[%d] QID %d: queue overfill error\n", LErr, qid);
+		return 1;
+	case 6:
+		pr_err("LErr[%d] QID %d: QM enqueue error\n", LErr, qid);
+		return 0;
+	case 7:
+		pr_err("LErr[%d] QID %d: QM dequeue error\n", LErr, qid);
+		return 0;
+	}
+	return 0;
+}
+
+static irqreturn_t xgene_enet_qmi_err_irq(int irq, void *dev_instance)
+{
+	struct xgene_enet_pdev *pdev;
+	struct xgene_enet_priv *priv;
+	int rc;
+	u32 data;
+	u32 int_mask = 0;
+
+	pdev = netdev_priv(dev_instance);
+	priv = &pdev->priv;
+	pr_err("Received Ethernet QMI Error Interrupt\n");
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, ENET_STSSSQMIINT0_ADDR, &data);
+	if (data) {
+		pr_err("Received STSSSQMIINT0 Error intr\n");
+		if (ENET_FPOVERFLOW0_RD(data)) {
+			pr_err("FP PB overflow indication:0x%08X\n", data);
+			int_mask |= ENET_FPOVERFLOW0_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   ENET_STSSSQMIINT0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, ENET_STSSSQMIINT1_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received STSSSQMIINT1 Error Interrupt\n");
+		if (ENET_WQOVERFLOW1_RD(data)) {
+			pr_err("WQ PB overflow indication:0x%08X\n", data);
+			int_mask |= ENET_WQOVERFLOW1_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   ENET_STSSSQMIINT1_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, ENET_STSSSQMIINT2_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received STSSSQMIINT2  Error Interrupt\n");
+		if (ENET_FPUNDERRUN2_RD(data)) {
+			pr_err("FP PB underrun indication:0x%08X\n", data);
+			int_mask |= ENET_FPUNDERRUN2_MASK;
+		}
+
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   ENET_STSSSQMIINT2_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, ENET_STSSSQMIINT3_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received STSSSQMIINT3 Error Interrupt\n");
+		if (ENET_WQUNDERRUN3_RD(data)) {
+			pr_err("WQ PB underrun indication:0x%08X\n", data);
+			int_mask |= ENET_WQUNDERRUN3_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   ENET_STSSSQMIINT3_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, ENET_STSSSQMIINT4_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received STSSSQMIINT4 Error Interrupt\n");
+		if (ENET_AXIWCMR_SLVERR4_RD(data)) {
+			pr_err("AXI slave error on write  master channel\n");
+			int_mask |= ENET_AXIWCMR_SLVERR4_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   ENET_STSSSQMIINT4_ADDR, int_mask);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t xgene_enet_mac_err_irq(int irq, void *dev_instance)
+{
+	struct xgene_enet_pdev *pdev;
+	struct xgene_enet_priv *priv;
+	int rc;
+	u32 data;
+	u32 int_mask = 0;
+
+	pdev = netdev_priv(dev_instance);
+	priv = &pdev->priv;
+	pr_err("Received Ethernet MAC Error Interrupt\n");
+
+	rc = xgene_enet_rd(priv, BLOCK_MCX_MAC_CSR, MAC_INT_REG0_ADDR, &data);
+	if (data) {
+		pr_err("Received MAC Error Interrupt\n");
+
+		if (ICM_DATA_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("RxPort1 ICM Data fifo underflow intr\n");
+			int_mask |= ICM_DATA_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (ICM_DATA_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("RxPort1 ICM Data fifo overflow intr\n");
+			int_mask |= ICM_DATA_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("RxPort1 ICM Ctrl fifo underflow intr\n");
+			int_mask |= ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (ICM_CTRL_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("RxPort1 ICM Ctrl fifo overflow intr\n");
+			int_mask |= ICM_CTRL_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (ECM_DATA_FIFO_UNDERN_INTR_PRT10_RD(data)) {
+			pr_err("RxPort1 ECM Data fifo underrun intr\n");
+			int_mask |= ECM_DATA_FIFO_UNDERN_INTR_PRT10_MASK;
+		}
+		if (ECM_DATA_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("TxPort1 ECM Data fifo underflow intr\n");
+			int_mask |= ECM_DATA_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (ECM_DATA_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("TxPort1 ECM Data fifo overflow intr\n");
+			int_mask |= ECM_DATA_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (MACIF_FIFO_UNDERFL_INTR_RXPRT10_F2_RD(data)) {
+			pr_err("RxPort1 Mac i/f fifo underflow intr\n");
+			int_mask |= MACIF_FIFO_UNDERFL_INTR_RXPRT10_F2_MASK;
+		}
+		if (MACIF_FIFO_OVERFL_INTR_RXPRT10_F2_RD(data)) {
+			pr_err("RxPort1 Mac i/f fifo overflow intr\n");
+			int_mask |= MACIF_FIFO_OVERFL_INTR_RXPRT10_F2_MASK;
+		}
+		if (ICM_DATA_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("RxPort0 ICM Data fifo underflow intr\n");
+			int_mask |= ICM_DATA_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (ICM_DATA_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("RxPort0 ICM Data fifo overflow intr\n");
+			int_mask |= ICM_DATA_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (ICM_CTRL_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("RxPort0 ICM Ctrl fifo underflow intr\n");
+			int_mask |= ICM_CTRL_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (ICM_CTRL_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("RxPort0 ICM Ctrl fifo overflow Interrupt\n");
+			int_mask |= ICM_CTRL_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (ECM_DATA_FIFO_UNDERN_INTR_PRT00_RD(data)) {
+			pr_err("RxPort0 ECM Data fifo underrun interrupt\n");
+			int_mask |= ECM_DATA_FIFO_UNDERN_INTR_PRT00_MASK;
+		}
+		if (ECM_DATA_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("TxPort0 ECM Data fifo underflow interrupt\n");
+			int_mask |= ECM_DATA_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (ECM_DATA_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("TxPort0 ECM Data fifo overflow interrupt\n");
+			int_mask |= ECM_DATA_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (MACIF_FIFO_UNDERFL_INTR_RXPRT00_F2_RD(data)) {
+			pr_err("RxPort0 Mac i/f fifo underflow interrupt\n");
+			int_mask |= MACIF_FIFO_UNDERFL_INTR_RXPRT00_F2_MASK;
+		}
+		if (MACIF_FIFO_OVERFL_INTR_RXPRT00_F2_RD(data)) {
+			pr_err("RxPort0 Mac i/f fifo overflow interrupt\n");
+			int_mask |= MACIF_FIFO_OVERFL_INTR_RXPRT00_F2_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR,
+				   MAC_INT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_MCX_MAC_CSR, MAC_INT_REG1_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received MAC Error Interrupt1\n");
+		if (LINKDOWN_PORT11_RD(data)) {
+			pr_err("Port1:Link Down intr\n");
+			int_mask |= LINKDOWN_PORT11_MASK;
+		}
+		if (CARRY_PORT11_RD(data)) {
+			pr_err("Carry Intr for Status Reg Overflow for Port 1\n");
+			int_mask |= CARRY_PORT11_MASK;
+		}
+		if (LINKDOWN_PORT01_RD(data)) {
+			pr_err("Port0:Link Down intr\n");
+			int_mask |= LINKDOWN_PORT01_MASK;
+		}
+		if (CARRY_PORT01_RD(data)) {
+			pr_err("Carry Intr for Status Reg Overflow for Port 0\n");
+			int_mask |= CARRY_PORT01_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_MCX_MAC_CSR,
+				   MAC_INT_REG1_ADDR, int_mask);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t xgene_enet_err_irq(int irq, void *dev_instance)
+{
+	struct xgene_enet_pdev *pdev;
+	struct xgene_enet_priv *priv;
+	int rc;
+	u32 data;
+	u32 int_mask = 0;
+
+	pdev = netdev_priv(dev_instance);
+	priv = &pdev->priv;
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, RSIF_INT_REG0_ADDR, &data);
+	if (data) {
+		pr_err("Received RSIF Error Interrupt\n");
+		if (RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 Local Rxbuff FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 Local Rxbuff FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 chksum buff FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 chksum buffer FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 timestamp buffer FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 timestamp FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 err buffer FIFO overflow intr\n");
+			int_mask |= RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 err buffer FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 classifier buffer FIFO overflow intr\n");
+			int_mask |= RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 classifier buffer FIFO underflow intr\n");
+			int_mask |= RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 ctrl buffer FIFO overflow intr\n");
+			int_mask |= RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err(" Rx port1 ctrl buffer FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_BUF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 buffer FIFO overflow intr\n");
+			int_mask |= RSIF_BUF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 buffer FIFO underflow intr\n");
+			int_mask |= RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (ENET_RSIF_PLC_CLEBUFF_FIFO_OVERFL_INTR0_RD(data)) {
+			pr_err("Policer CLE FIFO overflow intr\n");
+			int_mask |=
+			    ENET_RSIF_PLC_CLEBUFF_FIFO_OVERFL_INTR0_MASK;
+		}
+		if (ENET_RSIF_PLC_CLEBUFF_FIFO_UNDERFL_INTR0_RD(data)) {
+			pr_err("Policer CLE FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 Local Rx buffer FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 Local Rx buffer FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 chksum buffer FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 chksum buffer FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 timestamp buffer FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 timestamp FIFO underflow intr\n");
+			int_mask |=
+			    RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 err buffer FIFO overflow intr\n");
+			int_mask |= RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 err buffer FIFO underflow interrupt\n");
+			int_mask |=
+			    RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 classifier buffer FIFO overflow intr\n");
+			int_mask |= RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+
+		if (RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 classifier buffer FIFO underflow intr\n");
+			int_mask |= RSIF_CLEBUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 ctrl buffer FIFO overflow intr\n");
+			int_mask |= RSIF_CTRLBUFF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 ctrl buffer FIFO overflow intr\n");
+			int_mask |=
+			    RSIF_CTRLBUFF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_BUF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 buffer FIFO overflow intr\n");
+			int_mask |= RSIF_BUF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 buffer FIFO underflow intr\n");
+			int_mask |= RSIF_BUF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   RSIF_INT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, RSIF_FINT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received RSIF Error2 Interrupt\n");
+		if (RSIF_SS_MIRRORERR_INTR_RXPRT10_RD(data)) {
+			pr_err("Mirror buffer address offset/length do ");
+			pr_err("not match with normal xfr address ");
+			pr_err("offset/length in port1\n");
+			int_mask |= RSIF_SS_MIRRORERR_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT10_RD(data)) {
+			pr_err("Split boundary cannot be accomodated ");
+			pr_err("in the firt buffer in port1\n");
+			int_mask |= RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT10_RD(data)) {
+			pr_err("Packet dropped by RSIF because ");
+			pr_err("freepool buffer was NOT available from ");
+			pr_err("QMI on port1\n");
+			int_mask |= RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_SS_AXI_WRERR_INTR_RXPRT10_RD(data)) {
+			pr_err("AXI write error on port1\n");
+			int_mask |= RSIF_SS_AXI_WRERR_INTR_RXPRT10_MASK;
+		}
+		if (RSIF_SS_MIRRORERR_INTR_RXPRT00_RD(data)) {
+			pr_err("Mirror buffer address offset/length ");
+			pr_err("do not match with normal xfr address ");
+			pr_err("offset/length in port0\n");
+			int_mask |= RSIF_SS_MIRRORERR_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT00_RD(data)) {
+			pr_err("Split boundary cannot be accomodated ");
+			pr_err("in the firt buffer in port0\n");
+			int_mask |= RSIF_SS_SPLIT_BOUNDARY_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT00_RD(data)) {
+			pr_err("Packet dropped by RSIF because ");
+			pr_err("freepool buffer was NOT available from ");
+			pr_err("QMI on port0\n");
+			int_mask |= RSIF_SS_FPBUFF_TIMEOUT_INTR_RXPRT00_MASK;
+		}
+		if (RSIF_SS_AXI_WRERR_INTR_RXPRT00_RD(data)) {
+			pr_err("AXI write error on port0\n");
+			int_mask |= RSIF_SS_AXI_WRERR_INTR_RXPRT00_MASK;
+		}
+		if (STS_RSIF_PLC_DROP0_RD(data)) {
+			pr_err("Packet dropped by policer\n");
+			int_mask |= STS_RSIF_PLC_DROP0_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   RSIF_FINT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, TSIF_INT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received TSIF Error Interrupt\n");
+		if (TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 RDM buffer FIFO overflow interrupt\n");
+			int_mask |= TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 RDM buffer FIFO underflow interrupt\n");
+			int_mask |= TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (TSIF_RRM_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 RRM buffer FIFO overflow intr\n");
+			int_mask |= TSIF_RRM_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (TSIF_RRM_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 RRM buffer FIFO underflow intr\n");
+			int_mask |= TSIF_RRM_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (TSIF_AMABUF_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 AMA buffer FIFO overflow intr\n");
+			int_mask |= TSIF_AMABUF_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 AMA buffer FIFO underflow intr\n");
+			int_mask |= TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+
+		if (TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 RDM buffer FIFO overflow intr\n");
+			int_mask |= TSIF_RDMBUFF_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 RDM buffer FIFO underflow intr\n");
+			int_mask |= TSIF_RDMBUFF_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (TSIF_RRM_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 RRM buffer FIFO overflow intr\n");
+			int_mask |= TSIF_RRM_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (TSIF_RRM_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 RRM buffer FIFO underflow intr\n");
+			int_mask |= TSIF_RRM_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (TSIF_AMABUF_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 AMA buffer FIFO overflow intr\n");
+			int_mask |= TSIF_AMABUF_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 AMA buffer FIFO underflow intr\n");
+			int_mask |= TSIF_AMABUF_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   TSIF_INT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, TSIF_FINT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received TSIF Error Interrupt\n");
+		if (TSIF_SS_AXI_LLRDERR_INTR_PRT10_RD(data)) {
+			pr_err("AXI error when reading data from port1\n");
+			int_mask |= TSIF_SS_AXI_LLRDERR_INTR_PRT10_MASK;
+		}
+		if (TSIF_SS_AXI_RDERR_INTR_PRT10_RD(data)) {
+			pr_err("AXI error when reading data from port1\n");
+			int_mask |= TSIF_SS_AXI_RDERR_INTR_PRT10_MASK;
+		}
+		if (TSIF_SS_BAD_MSG_INTR_PRT10_RD(data)) {
+			pr_err("Bad message received by TSIF on port1\n");
+			int_mask |= TSIF_SS_BAD_MSG_INTR_PRT10_MASK;
+		}
+		if (TSIF_SS_AXI_LLRDERR_INTR_PRT00_RD(data)) {
+			pr_err("AXI error when reading data from port0\n");
+			int_mask |= TSIF_SS_AXI_LLRDERR_INTR_PRT00_MASK;
+		}
+		if (TSIF_SS_AXI_RDERR_INTR_PRT00_RD(data)) {
+			pr_err("AXI error when reading data from port0\n");
+			int_mask |= TSIF_SS_AXI_RDERR_INTR_PRT00_MASK;
+		}
+		if (TSIF_SS_BAD_MSG_INTR_PRT00_RD(data)) {
+			pr_err("Bad message received by TSIF on port0\n");
+			int_mask |= TSIF_SS_BAD_MSG_INTR_PRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   TSIF_FINT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, TSO_INT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received TSO Error Interrupt\n");
+		if (MB_TTF_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 tso_txbuff FIFO overflow intr\n");
+			int_mask |= MB_TTF_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (MB_TTF_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 tso_txbuff FIFO underflow intr\n");
+			int_mask |= MB_TTF_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (MH_DEALLOC_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 Dealloc FIFO overflow intr\n");
+			int_mask |= MH_DEALLOC_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (MH_DEALLOC_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 Dealloc FIFO underflow intr\n");
+			int_mask |= MH_DEALLOC_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (MH_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 Message Hold FIFO overflow intr\n");
+			int_mask |= MH_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (MH_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Tx port1 Message Hold FIFO underflow intr\n");
+			int_mask |= MH_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (MB_TTF_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 tso_txbuff FIFO overflow intr\n");
+			int_mask |= MB_TTF_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (MB_TTF_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 tso_txbuff FIFO underflow intr\n");
+			int_mask |= MB_TTF_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (MH_DEALLOC_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port0 Dealloc FIFO overflow intr\n");
+			int_mask |= MH_DEALLOC_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (MH_DEALLOC_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port1 Dealloc FIFO underflow intr\n");
+			int_mask |= MH_DEALLOC_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (MH_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port1 Message Hold FIFO overflow intr\n");
+			int_mask |= MH_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (MH_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Tx port1 Message Hold FIFO underflow intr\n");
+			int_mask |= MH_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   TSO_INT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR, SPI2SAP_INT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received SPI2SAP Error Interrupt\n");
+		if (MACIF_FIFO_OVERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 SAP FIFO overflow intr\n");
+			int_mask |= MACIF_FIFO_OVERFL_INTR_RXPRT10_MASK;
+		}
+		if (MACIF_FIFO_UNDERFL_INTR_RXPRT10_RD(data)) {
+			pr_err("Rx port1 SAP FIFO underflow intr\n");
+			int_mask |= MACIF_FIFO_UNDERFL_INTR_RXPRT10_MASK;
+		}
+		if (MACIF_FIFO_OVERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 SAP FIFO overflow intr\n");
+			int_mask |= MACIF_FIFO_OVERFL_INTR_RXPRT00_MASK;
+		}
+		if (MACIF_FIFO_UNDERFL_INTR_RXPRT00_RD(data)) {
+			pr_err("Rx port0 SAP FIFO underflow intr\n");
+			int_mask |= MACIF_FIFO_UNDERFL_INTR_RXPRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   SPI2SAP_INT_REG0_ADDR, int_mask);
+	}
+	rc = xgene_enet_rd(priv, BLOCK_ETH_CSR,
+			   RX_TX_BUF_CHKSM_INT_REG0_ADDR, &data);
+	int_mask = 0;
+	if (data) {
+		pr_err("Received RX/TX Buffer Checksum Error Interrupt\n");
+		if (RXBUF_PAUSE_INTR_PORT10_RD(data)) {
+			pr_err("Rx port1 Pause interrupt\n");
+			int_mask |= RXBUF_PAUSE_INTR_PORT10_MASK;
+		}
+		if (RX_CHKSUM_INTR_PORT10_RD(data)) {
+			pr_err("Rx port1 Chksum Error intr\n");
+			int_mask |= RX_CHKSUM_INTR_PORT10_MASK;
+		}
+		if (TX_CHKSUM_INTR_PORT10_RD(data)) {
+			pr_err("Tx port1 Chksum Error intr\n");
+			int_mask |= TX_CHKSUM_INTR_PORT10_MASK;
+		}
+		if (RXBUF_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Rx port1 rx buffer FIFO  overflow intr\n");
+			int_mask |= RXBUF_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (RXBUF_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Rx port1 rx buffer FIFO  underflow intr\n");
+			int_mask |= RXBUF_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (TXBUF_FIFO_OVERFL_INTR_PRT10_RD(data)) {
+			pr_err("Rx port1 rx buffer FIFO  overflow intr\n");
+			int_mask |= RXBUF_FIFO_OVERFL_INTR_PRT10_MASK;
+		}
+		if (TXBUF_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
+			pr_err("Rx port1 rx buffer FIFO  underflow intr\n");
+			int_mask |= RXBUF_FIFO_UNDERFL_INTR_PRT10_MASK;
+		}
+		if (RXBUF_PAUSE_INTR_PORT00_RD(data)) {
+			pr_err("Rx port0 Pause interrupt\n");
+			int_mask |= RXBUF_PAUSE_INTR_PORT00_MASK;
+		}
+		if (RX_CHKSUM_INTR_PORT00_RD(data)) {
+			pr_err("Rx port0 Chksum Error intr\n");
+			int_mask |= RX_CHKSUM_INTR_PORT00_MASK;
+		}
+		if (TX_CHKSUM_INTR_PORT00_RD(data)) {
+			pr_err("Tx port0 Chksum Error intr\n");
+			int_mask |= TX_CHKSUM_INTR_PORT00_MASK;
+		}
+		if (RXBUF_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Rx port0 rx buffer FIFO  overflow intr\n");
+			int_mask |= RXBUF_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (RXBUF_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Rx port0 rx buffer FIFO  underflow intr\n");
+			int_mask |= RXBUF_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		if (TXBUF_FIFO_OVERFL_INTR_PRT00_RD(data)) {
+			pr_err("Rx port0 rx buffer FIFO  overflow intr\n");
+			int_mask |= RXBUF_FIFO_OVERFL_INTR_PRT00_MASK;
+		}
+		if (TXBUF_FIFO_UNDERFL_INTR_PRT00_RD(data)) {
+			pr_err("Rx port0 rx buffer FIFO  underflow intr\n");
+			int_mask |= RXBUF_FIFO_UNDERFL_INTR_PRT00_MASK;
+		}
+		/* Clear intrstatus bits, its COW */
+		rc = xgene_enet_wr(priv, BLOCK_ETH_CSR,
+				   RX_TX_BUF_CHKSM_INT_REG0_ADDR, int_mask);
+	}
+	return IRQ_HANDLED;
+}
+
+void xgene_enet_register_err_irqs(struct net_device *ndev)
+{
+	struct xgene_enet_pdev *pdev;
+	struct device *dev;
+
+	pdev = (struct xgene_enet_pdev *)netdev_priv(ndev);
+	dev = &pdev->plat_dev->dev;
+
+	if ((devm_request_irq(dev, pdev->enet_err_irq, xgene_enet_err_irq,
+			 IRQF_SHARED, ndev->name, ndev)) != 0)
+		netdev_err(ndev, "Failed to reg Enet Error IRQ %d\n",
+			   pdev->enet_err_irq);
+	if ((devm_request_irq(dev, pdev->enet_mac_err_irq,
+			 xgene_enet_mac_err_irq, IRQF_SHARED,
+			 ndev->name, ndev)) != 0)
+		netdev_err(ndev, "Failed to reg Enet MAC Error IRQ %d\n",
+			   pdev->enet_mac_err_irq);
+	if ((devm_request_irq(dev, pdev->enet_qmi_err_irq,
+			 xgene_enet_qmi_err_irq,
+			 IRQF_SHARED, ndev->name, ndev)) != 0)
+		netdev_err(ndev, "Failed to reg Enet QMI Error IRQ %d\n",
+			   pdev->enet_qmi_err_irq);
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 2aa1808..90f53b8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -770,6 +770,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_qcontext *e2c,
 			goto process_pkt;
 		}
 
+		xgene_enet_parse_error(LErr, qid);
 		netdev_dbg(ndev, "ENET LErr 0x%x skb 0x%p FP 0x%x\n",
 			   LErr, skb, msg16->FPQNum);
 		print_hex_dump(KERN_ERR, "QM Msg: ",
@@ -1258,6 +1259,8 @@ static void xgene_enet_register_irq(struct net_device *ndev)
 		/* Disable interrupts for RX queue mailboxes */
 		disable_irq_nosync(pdev->rx[qindex]->qdesc->irq);
 	}
+
+	xgene_enet_register_err_irqs(ndev);
 }
 
 static int xgene_enet_get_resources(struct xgene_enet_pdev *pdev)
@@ -1330,6 +1333,30 @@ static int xgene_enet_get_resources(struct xgene_enet_pdev *pdev)
 	}
 	pdev->sdev = sdev;
 
+	pdata.irq = platform_get_irq(plat_dev, 0);
+	if (pdata.irq <= 0) {
+		dev_err(dev, "Unable to get ENET Error IRQ\n");
+		rc = pdata.irq;
+		goto out;
+	}
+	pdev->enet_err_irq = pdata.irq;
+
+	pdata.irq = platform_get_irq(plat_dev, 1);
+	if (pdata.irq <= 0) {
+		dev_err(dev, "Unable to get ENET MAC Error IRQ\n");
+		rc = pdata.irq;
+		goto out;
+	}
+	pdev->enet_mac_err_irq = pdata.irq;
+
+	pdata.irq = platform_get_irq(plat_dev, 2);
+	if (pdata.irq <= 0) {
+		dev_err(dev, "Unable to get ENET QMI Error IRQ\n");
+		rc = pdata.irq;
+		goto out;
+	}
+	pdev->enet_qmi_err_irq = pdata.irq;
+
 	rc = of_property_read_u32(plat_dev->dev.of_node, "phyid",
 				  &pdata.phy_id);
 	if (rc || pdata.phy_id > 0x1F) {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 15ea995..b25bb37 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -127,6 +127,7 @@ struct eth_queue_ids {
 struct xgene_enet_platform_data {
 	u32 port_id;
 	const char *sname;
+	int irq;
 	u32 phy_id;
 	u8 ethaddr[6];
 };
@@ -155,6 +156,9 @@ struct xgene_enet_pdev {
 	struct eth_queue_ids qm_queues;
 	u32 rx_buff_cnt, tx_cqt_low, tx_cqt_hi;
 	int mss;
+	unsigned int enet_err_irq;
+	unsigned int enet_mac_err_irq;
+	unsigned int enet_qmi_err_irq;
 	struct xgene_enet_priv priv;
 };
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/5] drivers: net: APM X-Gene SoC Ethernet driver ethtool support
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
                   ` (3 preceding siblings ...)
  2013-12-21  3:42 ` [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling Iyappan Subramanian
@ 2013-12-21  3:42 ` Iyappan Subramanian
  2013-12-22  9:35 ` [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Arnd Bergmann
  5 siblings, 0 replies; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-21  3:42 UTC (permalink / raw)
  To: davem
  Cc: gregkh, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Iyappan Subramanian, Ravi Patel, Keyur Chudgar

Ethtool support for APM X-Gene SoC ethernet driver.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Ravi Patel <rapatel@apm.com>
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
---
 drivers/net/ethernet/apm/xgene/Makefile           |    3 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_csr.h   |    4 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |    1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |    1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_tools.c |  296 +++++++++++++++++++++
 5 files changed, 304 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_tools.c

diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
index 091547e..472710d 100644
--- a/drivers/net/ethernet/apm/xgene/Makefile
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -6,6 +6,7 @@ xgene-enet-objs := \
 		xgene_enet_common.o	\
 		xgene_enet_mac.o	\
 		xgene_enet_main.o	\
-		xgene_enet_err.o
+		xgene_enet_err.o	\
+		xgene_enet_tools.o
 
 obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
index 858d155..5ca0d81 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_csr.h
@@ -357,6 +357,10 @@
 #define INTERFACE_CONTROL_ADDR                                       0x00000038
 #define STATION_ADDR0_ADDR                                           0x00000040
 #define STATION_ADDR1_ADDR                                           0x00000044
+#define RX_FLOW_EN1_MASK                                             0x00000020
+#define TX_FLOW_EN1_MASK                                             0x00000010
+#define RX_FLOW_EN1_RD(src)                           (((src) & 0x00000020)>>5)
+#define TX_FLOW_EN1_RD(src)                           (((src) & 0x00000010)>>4)
 #define SCAN_CYCLE_MASK                                              0x00000002
 #define SOFT_RESET1_MASK                                             0x80000000
 #define MAX_FRAME_LEN_SET(dst, src) \
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 90f53b8..77d3fd8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1416,6 +1416,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdev *pdev)
 
 	/* Ethtool checks the capabilities/features in hw_features flag */
 	ndev->hw_features = ndev->features;
+	SET_ETHTOOL_OPS(ndev, &xgene_ethtool_ops);
 
 	rc = register_netdev(ndev);
 	if (rc) {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index b25bb37..b95f129 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -173,4 +173,5 @@ void xgene_enet_init_priv(struct xgene_enet_priv *priv);
 int xgene_enet_parse_error(u8 LErr, int qid);
 void xgene_enet_register_err_irqs(struct net_device *ndev);
 
+extern const struct ethtool_ops xgene_ethtool_ops;
 #endif /* __XGENE_ENET_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_tools.c b/drivers/net/ethernet/apm/xgene/xgene_enet_tools.c
new file mode 100644
index 0000000..d99f42b
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_tools.c
@@ -0,0 +1,296 @@
+/* AppliedMicro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Authors:	Hrishikesh Karanjikar <hkaranjikar@apm.com>
+ *		Ravi Patel <rapatel@apm.com>
+ *		Iyappan Subramanian <isubramanian@apm.com>
+ *		Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include "xgene_enet_csr.h"
+#include "xgene_enet_main.h"
+
+struct xgene_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+static const struct xgene_stats xgene_gstrings_stats[] = {
+	{ "rx_bytes",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_byte_count),
+		offsetof(struct xgene_enet_pdev, stats.rx_stats.rx_byte_count)
+	},
+	{ "rx_packets",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_packet_count),
+		offsetof(struct xgene_enet_pdev, stats.rx_stats.rx_packet_count)
+	},
+	{ "rx_fcs_err",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_fcs_err_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_fcs_err_count)
+	},
+	{ "rx_alignment_err",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_alignment_err_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_alignment_err_pkt_count)
+	},
+	{ "rx_frm_len_err",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_frm_len_err_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_frm_len_err_pkt_count)
+	},
+	{ "rx_undersize",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_undersize_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_undersize_pkt_count)
+	},
+	{ "rx_oversize",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_oversize_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_oversize_pkt_count)
+	},
+	{ "rx_drop",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.rx_stats.rx_drop_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.rx_stats.rx_drop_pkt_count)
+	},
+	{ "tx_bytes",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.tx_stats.tx_byte_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.tx_stats.tx_byte_count)
+	},
+	{ "tx_packets",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.tx_stats.tx_pkt_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.tx_stats.tx_pkt_count)
+	},
+	{ "tx_drop",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.tx_stats.tx_drop_frm_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.tx_stats.tx_drop_frm_count)
+	},
+	{ "tx_fcs_err",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.tx_stats.tx_fcs_err_frm_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.tx_stats.tx_fcs_err_frm_count)
+	},
+	{ "tx_undersize",
+		FIELD_SIZEOF(struct xgene_enet_pdev,
+			stats.tx_stats.tx_undersize_frm_count),
+		offsetof(struct xgene_enet_pdev,
+			stats.tx_stats.tx_undersize_frm_count)
+	},
+};
+
+#define XGENE_GLOBAL_STATS_LEN ARRAY_SIZE(xgene_gstrings_stats)
+
+/* Ethtool APIs */
+static int xgene_ethtool_get_settings(struct net_device *ndev,
+		struct ethtool_cmd *cmd)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct phy_device *phydev = pdev->phy_dev;
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	if (priv->phy_mode == PHY_MODE_RGMII) {
+		if (!phydev)
+			return -ENODEV;
+		return phy_ethtool_gset(phydev, cmd);
+	}
+	return 0;
+}
+
+static int xgene_ethtool_set_settings(struct net_device *ndev,
+		struct ethtool_cmd *cmd)
+{
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct phy_device *phydev = pdev->phy_dev;
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	if (priv->phy_mode == PHY_MODE_RGMII) {
+		if (!phydev)
+			return -ENODEV;
+		return phy_ethtool_sset(phydev, cmd);
+	}
+	return 0;
+}
+
+static int xgene_ethtool_set_pauseparam(struct net_device *ndev,
+		struct ethtool_pauseparam *pp)
+{
+	u32 data;
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &data);
+
+	/* Modify value to set or reset rx flow control */
+	if (pp->rx_pause)
+		data |= RX_FLOW_EN1_MASK;
+	else
+		data &= ~RX_FLOW_EN1_MASK;
+
+	/* Modify value to set or reset tx flow control */
+	if (pp->tx_pause)
+		data |= TX_FLOW_EN1_MASK;
+	else
+		data &= ~TX_FLOW_EN1_MASK;
+
+	xgene_enet_wr(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, data);
+
+	return 0;
+}
+
+static void xgene_ethtool_get_pauseparam(struct net_device *ndev,
+		struct ethtool_pauseparam *pp)
+{
+	u32 data;
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &data);
+	pp->rx_pause = RX_FLOW_EN1_RD(data);
+
+	xgene_enet_rd(priv, BLOCK_MCX_MAC, MAC_CONFIG_1_ADDR, &data);
+	pp->tx_pause = TX_FLOW_EN1_RD(data);
+}
+
+static int xgene_ethtool_nway_reset(struct net_device *ndev)
+{
+	u32 data = 0, retry = 0;
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+
+	if (priv->phy_mode == PHY_MODE_RGMII)
+		mutex_lock(&pdev->mdio_bus->mdio_lock);
+
+	/* Power-down PHY */
+	data = MII_CR_POWER_DOWN;
+	xgene_genericmiiphy_write(priv, priv->phy_addr,
+			MII_CTRL_REG, data);
+
+	/* Power-up PHY */
+	data = 0x0;
+	xgene_genericmiiphy_write(priv, priv->phy_addr,
+			MII_CTRL_REG, data);
+
+	/* Reset PHY */
+	data = MII_CR_RESET;
+	xgene_genericmiiphy_write(priv, priv->phy_addr,
+			MII_CTRL_REG, data);
+
+	/* PHY reset may take 100 ms */
+	retry = 100;
+	do {
+		xgene_genericmiiphy_read(priv, priv->phy_addr,
+			MII_CTRL_REG, &data);
+		usleep_range(1000, 2000);
+	} while (--retry && (data & MII_CR_RESET));
+
+	xgene_genericmiiphy_write(priv, priv->phy_addr, MII_CTRL_REG,
+			MII_CR_AUTO_EN|MII_CR_RESTART|MII_CR_FDX);
+
+	priv->autoneg_set = 1;
+	priv->speed = XGENE_ENET_SPEED_1000;
+	priv->mac_init(priv, ndev->dev_addr, priv->speed,
+			HW_MTU(ndev->mtu), priv->crc);
+
+	if (priv->phy_mode == PHY_MODE_RGMII)
+		mutex_unlock(&pdev->mdio_bus->mdio_lock);
+
+	return 0;
+}
+
+static void xgene_get_strings(struct net_device *ndev, u32 stringset,
+		    u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_TEST:
+	case ETH_SS_STATS:
+		for (i = 0; i < XGENE_GLOBAL_STATS_LEN; i++) {
+			memcpy(p, xgene_gstrings_stats[i].stat_string,
+					ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static int xgene_get_sset_count(struct net_device *ndev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_TEST:
+		return XGENE_GLOBAL_STATS_LEN;
+	case ETH_SS_STATS:
+		return XGENE_GLOBAL_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+}
+
+static void xgene_ethtool_get_ethtool_stats(struct net_device *ndev,
+		struct ethtool_stats *ethtool_stats,
+		u64 *data)
+{
+
+	struct xgene_enet_pdev *pdev = netdev_priv(ndev);
+	struct xgene_enet_priv *priv = &pdev->priv;
+	struct xgene_enet_detailed_stats *stats = &pdev->stats;
+	int i;
+
+	xgene_enet_get_stats(priv, stats);
+	for (i = 0; i < XGENE_GLOBAL_STATS_LEN; i++) {
+		char *p = (char *)pdev + xgene_gstrings_stats[i].stat_offset;
+		data[i] = (xgene_gstrings_stats[i].sizeof_stat ==
+				sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	}
+}
+
+static void xgene_ethtool_get_drvinfo(struct net_device *ndev,
+		struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, ndev->name);
+	strcpy(info->version, XGENE_ENET_DRIVER_VERSION);
+	strcpy(info->fw_version, "N/A");
+}
+
+const struct ethtool_ops xgene_ethtool_ops = {
+	.get_settings = xgene_ethtool_get_settings,
+	.set_settings = xgene_ethtool_set_settings,
+	.get_drvinfo = xgene_ethtool_get_drvinfo,
+	.nway_reset = xgene_ethtool_nway_reset,
+	.get_pauseparam = xgene_ethtool_get_pauseparam,
+	.set_pauseparam = xgene_ethtool_set_pauseparam,
+	.get_ethtool_stats = xgene_ethtool_get_ethtool_stats,
+	.get_sset_count = xgene_get_sset_count,
+	.get_strings = xgene_get_strings,
+	.get_link = ethtool_op_get_link,
+};
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver
  2013-12-21  3:42 ` [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver Iyappan Subramanian
@ 2013-12-21 21:11   ` Greg KH
  0 siblings, 0 replies; 14+ messages in thread
From: Greg KH @ 2013-12-21 21:11 UTC (permalink / raw)
  To: Iyappan Subramanian
  Cc: davem, netdev, linux-kernel, devicetree, linux-arm-kernel, jcm,
	patches, Ravi Patel, Keyur Chudgar

On Fri, Dec 20, 2013 at 07:42:54PM -0800, Iyappan Subramanian wrote:
> Ethernet base device driver for APM X-Gene SoC.

Why is this a platform driver and not a bus driver for a xgene device?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling
  2013-12-21  3:42 ` [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling Iyappan Subramanian
@ 2013-12-22  9:34   ` Arnd Bergmann
  0 siblings, 0 replies; 14+ messages in thread
From: Arnd Bergmann @ 2013-12-22  9:34 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Iyappan Subramanian, davem, devicetree, gregkh, patches,
	linux-kernel, netdev, jcm, Keyur Chudgar, Ravi Patel

On Saturday 21 December 2013, Iyappan Subramanian wrote:

> +#define CFG_RSIF_FPBUFF_TIMEOUT_EN_WR(src) \
> +	(((u32)(src)<<31) & 0x80000000)
> +#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_MASK                 0x20000000
> +#define RSIF_LCL_RXBUF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x20000000)>>29)
> +#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_MASK                0x10000000
> +#define RSIF_LCL_RXBUF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x10000000)>>28)
> +#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK               0x08000000
> +#define RSIF_CHKSUM_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x08000000)>>27)
> +#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK              0x04000000
> +#define RSIF_CHKSUM_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x04000000)>>26)
> +#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK            0x02000000
> +#define RSIF_TIMESTAMP_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x02000000)>>25)
> +#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK           0x01000000
> +#define RSIF_TIMESTAMP_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x01000000)>>24)
> +#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_MASK                  0x00800000
> +#define RSIF_ERR_BUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x00800000)>>23)
> +#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_MASK                 0x00400000
> +#define RSIF_ERR_BUFF_FIFO_UNDERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x00400000)>>22)
> +#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_MASK                   0x00200000
> +#define RSIF_CLEBUFF_FIFO_OVERFL_INTR_RXPRT10_RD(src) \
> +	(((src) & 0x00200000)>>21)

I think you can just remove all the above obfuscation, since all you ever
do is this:

> +	rc = xgene_enet_rd(priv, BLOCK_MCX_MAC_CSR, MAC_INT_REG0_ADDR, &data);
> +	if (data) {
> +		pr_err("Received MAC Error Interrupt\n");
> +
> +		if (ICM_DATA_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
> +			pr_err("RxPort1 ICM Data fifo underflow intr\n");
> +			int_mask |= ICM_DATA_FIFO_UNDERFL_INTR_PRT10_MASK;
> +		}
> +		if (ICM_DATA_FIFO_OVERFL_INTR_PRT10_RD(data)) {
> +			pr_err("RxPort1 ICM Data fifo overflow intr\n");
> +			int_mask |= ICM_DATA_FIFO_OVERFL_INTR_PRT10_MASK;
> +		}
> +		if (ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_RD(data)) {
> +			pr_err("RxPort1 ICM Ctrl fifo underflow intr\n");
> +			int_mask |= ICM_CTRL_FIFO_UNDERFL_INTR_PRT10_MASK;
> +		}
> +		if (ICM_CTRL_FIFO_OVERFL_INTR_PRT10_RD(data)) {
> +			pr_err("RxPort1 ICM Ctrl fifo overflow intr\n");
> +			int_mask |= ICM_CTRL_FIFO_OVERFL_INTR_PRT10_MASK;
> +		}
> +		if (ECM_DATA_FIFO_UNDERN_INTR_PRT10_RD(data)) {
> +			pr_err("RxPort1 ECM Data fifo underrun intr\n");
> +			int_mask |= ECM_DATA_FIFO_UNDERN_INTR_PRT10_MASK;
> +		}

So there is one string you print per bit. Just use an array of strings
and for_each_set_bit() loop.

	Arnd

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver
  2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
                   ` (4 preceding siblings ...)
  2013-12-21  3:42 ` [PATCH 5/5] drivers: net: APM X-Gene SoC Ethernet driver ethtool support Iyappan Subramanian
@ 2013-12-22  9:35 ` Arnd Bergmann
  2013-12-23 16:32   ` Iyappan Subramanian
  5 siblings, 1 reply; 14+ messages in thread
From: Arnd Bergmann @ 2013-12-22  9:35 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Iyappan Subramanian, davem, devicetree, gregkh, patches,
	linux-kernel, netdev, jcm, Keyur Chudgar, Ravi Patel

On Saturday 21 December 2013, Iyappan Subramanian wrote:
> Iyappan Subramanian (5):
>   Documentation: APM X-Gene SoC Ethernet DTS binding documentation
>   arm64: dts: APM X-Gene SoC Ethernet device tree nodes
>   drivers: net: APM X-Gene SoC Ethernet base driver
>   drivers: net: APM X-Gene SoC Ethernet driver error handling
>   drivers: net: APM X-Gene SoC Ethernet driver ethtool support

The third patch (the actual driver) didn't make it to the ARM mailing list.
Maybe it's too large?

	Arnd

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation
  2013-12-21  3:42 ` [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation Iyappan Subramanian
@ 2013-12-22  9:40   ` Arnd Bergmann
  0 siblings, 0 replies; 14+ messages in thread
From: Arnd Bergmann @ 2013-12-22  9:40 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Iyappan Subramanian, davem, devicetree, gregkh, patches,
	linux-kernel, netdev, jcm, Keyur Chudgar, Ravi Patel

On Saturday 21 December 2013, Iyappan Subramanian wrote:
> @@ -0,0 +1,67 @@
> +APM X-Gene SoC Ethernet nodes
> +
> +Ethernet nodes are defined to describe on-chip ethernet interfaces in
> +APM X-Gene SoC. Ethernet subsystem communicates with a central Queue Manager
> +(QMTM) using messages for transmit, receive and allocating data buffers.
> +There are multiple ethernet interfaces in APM X-Gene SoC. Each ethernet
> +interface has its own node. Its corresponding clock nodes are shown below.
> +
> +Required properties:
> +- compatible		: Shall be "apm,xgene-enet"
> +- reg			: First memory resource shall be the Ethernet CSR
> +			  memory resource for indirect MAC access.
> +			  Second memory resource shall be the Ethernet CSR
> +			  memory resource.
> +			  Third memory resource shall be the Ethernet CSR
> +			  memory resource for indirect MII access.

What is a "CSR"?

> +- interrupts		: First interrupt resource shall be the Ethernet global
> +			  Error interrupt.
> +			: Second interrupt resource shall be the Ethernet MAC
> +			  Error interrupt.
> +			: Third interrupt resource shall be the Ethernet QM
> +			  interface interrupt.

No regular interrupts?

> +- clocks		: Reference to the clock entry.
> +- local-mac-address	: Shall be ethernet mac address.
> +- max-frame-size	: Shall be maximum ethernet frame size.
> +- devid			: Shall be ethernet interface number.
> +- phyid			: Shall be ethernet MII phy address.
> +- phy-mode		: Shall be ethernet MII mode.

Can you explain what the interface number is for?

Is the phy actually part of the ethernet device? Since it has its
own register range, it seems likely that it's actually a separate
device that just happens to be used together with the mac and should
have its own device node and driver.

	Arnd

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver
  2013-12-22  9:35 ` [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Arnd Bergmann
@ 2013-12-23 16:32   ` Iyappan Subramanian
  0 siblings, 0 replies; 14+ messages in thread
From: Iyappan Subramanian @ 2013-12-23 16:32 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: davem, devicetree, gregkh, patches, linux-kernel, netdev, jcm,
	Keyur Chudgar, Ravi Patel

Yes.  My third patch didn't make it to the linux-arm-kernel mailing list
due to size.  I am waiting for the moderator's approval to get it posted.

Thanks,
Iyappan

Your mail to 'linux-arm-kernel' with the subject

    [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver

Is being held until the list moderator can review it for approval.

The reason it is being held:

    Message body is too big: 112640 bytes with a limit of 100 KB

Either the message will get posted to the list, or you will receive
notification of the moderator's decision.  If you would like to cancel
this posting, please visit the following URL:


http://lists.infradead.org/mailman/confirm/linux-arm-kernel/0aca8492f9ca29
055149ebf4058771fd701fd928


-----Original Message-----
From: Arnd Bergmann [mailto:arnd@arndb.de]
Sent: Sunday, December 22, 2013 1:36 AM
To: linux-arm-kernel@lists.infradead.org
Cc: Iyappan Subramanian; davem@davemloft.net; devicetree@vger.kernel.org;
gregkh@linuxfoundation.org; patches@apm.com; linux-kernel@vger.kernel.org;
netdev@vger.kernel.org; jcm@redhat.com; Keyur Chudgar; Ravi Patel
Subject: Re: [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC
Ethernet base driver

On Saturday 21 December 2013, Iyappan Subramanian wrote:
> Iyappan Subramanian (5):
>   Documentation: APM X-Gene SoC Ethernet DTS binding documentation
>   arm64: dts: APM X-Gene SoC Ethernet device tree nodes
>   drivers: net: APM X-Gene SoC Ethernet base driver
>   drivers: net: APM X-Gene SoC Ethernet driver error handling
>   drivers: net: APM X-Gene SoC Ethernet driver ethtool support

The third patch (the actual driver) didn't make it to the ARM mailing
list.
Maybe it's too large?

	Arnd

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes
  2013-12-21  3:42 ` [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes Iyappan Subramanian
@ 2014-01-24 17:01   ` Mark Salter
  2014-04-11 20:03     ` Iyappan Subramanian
  0 siblings, 1 reply; 14+ messages in thread
From: Mark Salter @ 2014-01-24 17:01 UTC (permalink / raw)
  To: Iyappan Subramanian
  Cc: davem, gregkh, netdev, linux-kernel, devicetree,
	linux-arm-kernel, jcm, patches, Ravi Patel, Keyur Chudgar

On Fri, 2013-12-20 at 19:42 -0800, Iyappan Subramanian wrote:
> Device tree files for APM X-Gene SoC Ethernet.
> 
> Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
> Signed-off-by: Ravi Patel <rapatel@apm.com>
> Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
> ---
>  arch/arm64/boot/dts/apm-mustang.dts |    8 ++++++++
>  arch/arm64/boot/dts/apm-storm.dtsi  |   19 +++++++++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
> index 1247ca1..ccb2771 100644
> --- a/arch/arm64/boot/dts/apm-mustang.dts
> +++ b/arch/arm64/boot/dts/apm-mustang.dts
> @@ -17,6 +17,10 @@
>  	model = "APM X-Gene Mustang board";
>  	compatible = "apm,mustang", "apm,xgene-storm";
>  
> +        aliases {
> +                ethernet0 = &menet;
> +        };
> +
>  	chosen { };
>  
>  	memory {
> @@ -24,3 +28,7 @@
>  		reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
>  	};
>  };
> +
> +&menet {
> +        status = "ok";
> +};
> diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
> index f64f946..9c7b8cd 100644
> --- a/arch/arm64/boot/dts/apm-storm.dtsi
> +++ b/arch/arm64/boot/dts/apm-storm.dtsi
> @@ -204,5 +204,24 @@
>  			#clock-cells = <1>;
>  			clocks = <&qmlclk 0>;
>  		};
> +
> +		menet: ethernet@17020000 {
> +			compatible = "apm,xgene-enet";
> +			status = "disabled";
> +			reg = <0x0 0x17020000 0x0 0x30>,
> +			      <0x0 0x17020000 0x0 0x10000>,
> +			      <0x0 0x17020000 0x0 0x20>;
> +			slave-name = "RGMII";
> +			interrupts = <0x0 0x38 0x4>,
> +				     <0x0 0x39 0x4>,
> +				     <0x0 0x3a 0x4>;
> +			#clock-cells = <1>;
> +			clocks = <&eth8clk 0>;
> +			local-mac-address = <0x0 0x11 0x3a 0x8a 0x5a 0x78>;

Shouldn't this be a byte string?:

			local-mac-address = [ 00 11 3a 8a 5a 78 ];

> +			max-frame-size = <0x233a>;
> +			devid = <8>;
> +			phyid = <3>;
> +			phy-mode = "rgmii";
> +		};
>  	};
>  };



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes
  2014-01-24 17:01   ` Mark Salter
@ 2014-04-11 20:03     ` Iyappan Subramanian
  2014-05-09 15:29       ` Alex Bennée
  0 siblings, 1 reply; 14+ messages in thread
From: Iyappan Subramanian @ 2014-04-11 20:03 UTC (permalink / raw)
  To: Mark Salter
  Cc: davem, Greg KH, netdev, linux-kernel, devicetree,
	linux-arm-kernel, jcm, patches, Ravi Patel, Keyur Chudgar

Hi Mark,

Thanks for the review comment and I apologize for not replying sooner.

We are completely redesigning the ethernet driver to make it simple
and cleaner and will be posted shortly.

Please find my response by searching for isubrama:

Thanks,
Iyappan

On Fri, Jan 24, 2014 at 9:01 AM, Mark Salter <msalter@redhat.com> wrote:
> On Fri, 2013-12-20 at 19:42 -0800, Iyappan Subramanian wrote:
>> Device tree files for APM X-Gene SoC Ethernet.
>>
>> Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
>> Signed-off-by: Ravi Patel <rapatel@apm.com>
>> Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
>> ---
>>  arch/arm64/boot/dts/apm-mustang.dts |    8 ++++++++
>>  arch/arm64/boot/dts/apm-storm.dtsi  |   19 +++++++++++++++++++
>>  2 files changed, 27 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
>> index 1247ca1..ccb2771 100644
>> --- a/arch/arm64/boot/dts/apm-mustang.dts
>> +++ b/arch/arm64/boot/dts/apm-mustang.dts
>> @@ -17,6 +17,10 @@
>>       model = "APM X-Gene Mustang board";
>>       compatible = "apm,mustang", "apm,xgene-storm";
>>
>> +        aliases {
>> +                ethernet0 = &menet;
>> +        };
>> +
>>       chosen { };
>>
>>       memory {
>> @@ -24,3 +28,7 @@
>>               reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
>>       };
>>  };
>> +
>> +&menet {
>> +        status = "ok";
>> +};
>> diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
>> index f64f946..9c7b8cd 100644
>> --- a/arch/arm64/boot/dts/apm-storm.dtsi
>> +++ b/arch/arm64/boot/dts/apm-storm.dtsi
>> @@ -204,5 +204,24 @@
>>                       #clock-cells = <1>;
>>                       clocks = <&qmlclk 0>;
>>               };
>> +
>> +             menet: ethernet@17020000 {
>> +                     compatible = "apm,xgene-enet";
>> +                     status = "disabled";
>> +                     reg = <0x0 0x17020000 0x0 0x30>,
>> +                           <0x0 0x17020000 0x0 0x10000>,
>> +                           <0x0 0x17020000 0x0 0x20>;
>> +                     slave-name = "RGMII";
>> +                     interrupts = <0x0 0x38 0x4>,
>> +                                  <0x0 0x39 0x4>,
>> +                                  <0x0 0x3a 0x4>;
>> +                     #clock-cells = <1>;
>> +                     clocks = <&eth8clk 0>;
>> +                     local-mac-address = <0x0 0x11 0x3a 0x8a 0x5a 0x78>;
>
> Shouldn't this be a byte string?:
isubrama:
Agree.  I changed the driver.
>
>                         local-mac-address = [ 00 11 3a 8a 5a 78 ];
>
>> +                     max-frame-size = <0x233a>;
>> +                     devid = <8>;
>> +                     phyid = <3>;
>> +                     phy-mode = "rgmii";
>> +             };
>>       };
>>  };
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes
  2014-04-11 20:03     ` Iyappan Subramanian
@ 2014-05-09 15:29       ` Alex Bennée
  0 siblings, 0 replies; 14+ messages in thread
From: Alex Bennée @ 2014-05-09 15:29 UTC (permalink / raw)
  To: Iyappan Subramanian
  Cc: Mark Salter, davem, Greg KH, netdev, linux-kernel, devicetree,
	linux-arm-kernel, jcm, patches, Ravi Patel, Keyur Chudgar


Iyappan Subramanian <isubramanian@apm.com> writes:

> Hi Mark,
>
> Thanks for the review comment and I apologize for not replying sooner.
>
> We are completely redesigning the ethernet driver to make it simple
> and cleaner and will be posted shortly.

Hi Iyappan,

Did this ever get posted? I'm trying to get a close-to-HEAD kernel up
and running on our APM hardware but have run afoul of the differences
between the latest XGENE_MBOX patch set and the older NET_XGENE patch
set.

If it's not long away then I shall wait a bit otherwise I'll see if the
missing bits can be forward ported from our working
3.8.0-mustang_sw_1.08.12-beta_rc.jcm15 kernel (purely for testing
purposes).

Do you have a public tree where your latest kernels are visible?

Cheers,

--
Alex Bennée
QEMU/KVM Hacker for Linaro


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-05-09 15:47 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-21  3:42 [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Iyappan Subramanian
2013-12-21  3:42 ` [PATCH 1/5] Documentation: APM X-Gene SoC Ethernet DTS binding documentation Iyappan Subramanian
2013-12-22  9:40   ` Arnd Bergmann
2013-12-21  3:42 ` [PATCH 2/5] arm64: dts: APM X-Gene SoC Ethernet device tree nodes Iyappan Subramanian
2014-01-24 17:01   ` Mark Salter
2014-04-11 20:03     ` Iyappan Subramanian
2014-05-09 15:29       ` Alex Bennée
2013-12-21  3:42 ` [PATCH 3/5] drivers: net: APM X-Gene SoC Ethernet base driver Iyappan Subramanian
2013-12-21 21:11   ` Greg KH
2013-12-21  3:42 ` [PATCH 4/5] drivers: net: APM X-Gene SoC Ethernet driver error handling Iyappan Subramanian
2013-12-22  9:34   ` Arnd Bergmann
2013-12-21  3:42 ` [PATCH 5/5] drivers: net: APM X-Gene SoC Ethernet driver ethtool support Iyappan Subramanian
2013-12-22  9:35 ` [PATCH 0/5] drivers: net: Adding support for APM X-Gene SoC Ethernet base driver Arnd Bergmann
2013-12-23 16:32   ` Iyappan Subramanian

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).