All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver
@ 2014-03-10 23:14 Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 1/9] MAINTAINERS: Add entry for Altera Triple Speed Ethernet Driver Vince Bridgers
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

V2: Address comments from initial RFC review.
    - The driver files were broken up by major sections of functionality.
      These include MSGDMA, SGDMA, Misc, and Main. 
    - Add patch for MAINTAINERS file, add the maintainer for this submission
    - Use 32-bit lower/upper physical address accessor functions so the driver
      is 64-bit ready.
    - Use standard bindings where applicable. Especially phy-addr, and change
      "altr,rx-fifo-depth" to "rx-fifo-depth" and "altr,tx-fifo-depth" to 
      "tx-fifo-depth".
    - Add use of max-frame-size property
    - Update bindings documents accordingly
    - Correct interrupt handler to use budget parameter in the convential way
    - Use macros consistently to define bit fields across files
    - Correct include exclusion macro in altera_msgdmahw.h (typo)
    - Remove use of barriers, these were not necessary since the DMA APIs
      ensure memory & buffer consistency
    - Remove use of netif_carrier_off in driver
    - move probing of phy from the open function to the probe function
    - use of_get_phy_mode instead of custom function
    - Use the .data field in the device structure to obtain a pointer
      to SGDMA or MSGDMA device specific properties and functions. 
    - remove custom function to access devicetree since Altera specific
      bindings requiring it's use have been deprecated in favor of 
      standard bindings. 

The Altera TSE is a 10/100/1000 Mbps Ethernet soft IP component that can be
configured and synthesized using Quartus, and programmed into Altera FPGAs.
Two types of soft DMA IP components are supported by this driver - the Altera
SGDMA and the MSGDMA. The MSGDMA DMA component is preferred over the SGDMA,
since the SGDMA will be deprecated in favor of the MSGDMA. Software supporting
both is provided for customers still using the SGDMA and to demonstrate how
multiple types of DMA engines may be supported by the TSE driver in the event
customers wish to develop their own custom soft DMA engine for particular
applications.

The design has been tested on Altera's Cyclone 4, 5, and Cyclone 5 SOC
development kits using an ARM A9 processor and an Altera NIOS2 processor.
Differences in CPU/DMA coherency management and address alignment are
addressed by proper use of driver APIs and semantics.

Patch 1/9 is for the MAINTAINERS modifications. Patch 2/9 is for the changes
required to the drivers/net/ethernet build files. Patches 3 and 4 are for the 
driver bindings and documentation. The remainder of the patches are for the
Altera Triple Speed Ethernet driver broken up by logical function, such as
build files, SGDMA, MSGDMA, Miscellaneous files, and the main driver source 
and header file. 

Thank you for the constructive comments so far, and I look forward to
completing this process.

Vince 

Vince Bridgers (9):
  MAINTAINERS: Add entry for Altera Triple Speed Ethernet Driver
  net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE
    driver
  dts: Add bindings for the Altera Triple Speed Ethernet driver
  Documentation: networking: Add Altera Ethernet (TSE) Documentation
  Altera TSE: Add Altera Ethernet Driver Makefile and Kconfig
  Altera TSE: Add Altera Ethernet Driver MSGDMA File Components
  Altera TSE: Add Altera Ethernet Driver SGDMA file components
  Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  Altera TSE: Add main and header file for Altera Ethernet Driver

 .../devicetree/bindings/net/altera_tse.txt         |  112 ++
 Documentation/networking/altera_tse.txt            |  119 ++
 MAINTAINERS                                        |    7 +
 drivers/net/ethernet/Kconfig                       |    1 +
 drivers/net/ethernet/Makefile                      |    1 +
 drivers/net/ethernet/altera/Kconfig                |    8 +
 drivers/net/ethernet/altera/Makefile               |    7 +
 drivers/net/ethernet/altera/altera_msgdma.c        |  203 +++
 drivers/net/ethernet/altera/altera_msgdma.h        |   34 +
 drivers/net/ethernet/altera/altera_msgdmahw.h      |  167 +++
 drivers/net/ethernet/altera/altera_sgdma.c         |  532 +++++++
 drivers/net/ethernet/altera/altera_sgdma.h         |   35 +
 drivers/net/ethernet/altera/altera_sgdmahw.h       |  124 ++
 drivers/net/ethernet/altera/altera_tse.h           |  486 ++++++
 drivers/net/ethernet/altera/altera_tse_ethtool.c   |  226 +++
 drivers/net/ethernet/altera/altera_tse_main.c      | 1546 ++++++++++++++++++++
 drivers/net/ethernet/altera/altera_utils.c         |   44 +
 drivers/net/ethernet/altera/altera_utils.h         |   27 +
 18 files changed, 3679 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/altera_tse.txt
 create mode 100644 Documentation/networking/altera_tse.txt
 create mode 100644 drivers/net/ethernet/altera/Kconfig
 create mode 100644 drivers/net/ethernet/altera/Makefile
 create mode 100644 drivers/net/ethernet/altera/altera_msgdma.c
 create mode 100644 drivers/net/ethernet/altera/altera_msgdma.h
 create mode 100644 drivers/net/ethernet/altera/altera_msgdmahw.h
 create mode 100644 drivers/net/ethernet/altera/altera_sgdma.c
 create mode 100644 drivers/net/ethernet/altera/altera_sgdma.h
 create mode 100644 drivers/net/ethernet/altera/altera_sgdmahw.h
 create mode 100644 drivers/net/ethernet/altera/altera_tse.h
 create mode 100644 drivers/net/ethernet/altera/altera_tse_ethtool.c
 create mode 100644 drivers/net/ethernet/altera/altera_tse_main.c
 create mode 100644 drivers/net/ethernet/altera/altera_utils.c
 create mode 100644 drivers/net/ethernet/altera/altera_utils.h

-- 
1.7.9.5


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

* [PATCH net-next v2 1/9] MAINTAINERS: Add entry for Altera Triple Speed Ethernet Driver
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
       [not found] ` <1394493277-2105-1-git-send-email-vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

Add a MAINTAINERS entry covering the Altera Triple Speed
Ethernet Driver, with support for the MSGDMA and SGDMA
soft DMA IP components.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Add a patch to update MAINTAINERS file, it was missed on the
      initial RFC submission.
---
 MAINTAINERS |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e4ee191..cfa0dfa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -536,6 +536,13 @@ S:	Odd Fixes
 L:	linux-alpha@vger.kernel.org
 F:	arch/alpha/
 
+ALTERA TRIPLE SPEED ETHERNET DRIVER
+M:	Vince Bridgers <vbridgers2013@gmail.com
+L:	netdev@vger.kernel.org
+L:	nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/net/ethernet/altera/
+
 ALTERA UART/JTAG UART SERIAL DRIVERS
 M:	Tobias Klauser <tklauser@distanz.ch>
 L:	linux-serial@vger.kernel.org
-- 
1.7.9.5

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

* [PATCH net-next v2 2/9] net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE driver
       [not found] ` <1394493277-2105-1-git-send-email-vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-03-10 23:14   ` Vince Bridgers
  2014-03-11 14:09     ` Sergei Shtylyov
  0 siblings, 1 reply; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w

This patch changes the Ethernet Makefile and Kconfig files to add the Altera
Ethernet driver component.

Signed-off-by: Vince Bridgers <vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
V2: - No change to Kconfig and Makefile from initial RFC review
---
 drivers/net/ethernet/Kconfig  |    1 +
 drivers/net/ethernet/Makefile |    1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 506b024..39484b5 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -22,6 +22,7 @@ source "drivers/net/ethernet/adaptec/Kconfig"
 source "drivers/net/ethernet/aeroflex/Kconfig"
 source "drivers/net/ethernet/allwinner/Kconfig"
 source "drivers/net/ethernet/alteon/Kconfig"
+source "drivers/net/ethernet/altera/Kconfig"
 source "drivers/net/ethernet/amd/Kconfig"
 source "drivers/net/ethernet/apple/Kconfig"
 source "drivers/net/ethernet/arc/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index c0b8789..adf61af 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
 obj-$(CONFIG_GRETH) += aeroflex/
 obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
 obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
+obj-$(CONFIG_ALTERA_TSE) += altera/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
 obj-$(CONFIG_NET_VENDOR_ARC) += arc/
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 1/9] MAINTAINERS: Add entry for Altera Triple Speed Ethernet Driver Vince Bridgers
       [not found] ` <1394493277-2105-1-git-send-email-vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-11  9:22   ` Mark Rutland
  2014-03-10 23:14 ` [PATCH net-next v2 4/9] Documentation: networking: Add Altera Ethernet (TSE) Documentation Vince Bridgers
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds a bindings description for the Altera Triple Speed Ethernet
(TSE) driver. The bindings support the legacy SGDMA soft IP as well as the
preferred MSGDMA soft IP. The TSE can be configured and synthesized in soft
logic using Altera's Quartus toolchain. Please consult the bindings document
for supported options.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Update bindings to use standard Ethernet and Phy bindings.
      Use standard "phy-addr" instead of Altera's "phy-addr".
      Use "rx-fifo-depth" and "tx-fifo-depth" instead of versions
      prepended with "altr," in units of 32-bit quantities.
      Add missing bindings to describe "altr,enable-hash" and
      "altr,enable-sup-addr".
---
 .../devicetree/bindings/net/altera_tse.txt         |  112 ++++++++++++++++++++
 1 file changed, 112 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/altera_tse.txt

diff --git a/Documentation/devicetree/bindings/net/altera_tse.txt b/Documentation/devicetree/bindings/net/altera_tse.txt
new file mode 100644
index 0000000..040e4e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/altera_tse.txt
@@ -0,0 +1,112 @@
+* Altera Triple-Speed Ethernet MAC driver (TSE)
+
+Required properties:
+- compatible: Should be "altr,tse-1.0" for legacy SGDMA based TSE, and should
+		be "altr,tse-msgdma-1.0" for the preferred MSGDMA based TSE.
+		ALTR is supported for legacy device trees, but is deprecated.
+		altr should be used for all new designs.
+- reg: Address and length of the register set for the device. It contains
+  the information of registers in the same order as described by reg-names
+- reg-names: Should contain the reg names
+  "control_port": MAC configuration space region
+  "tx_csr":       xDMA Tx dispatcher control and status space region
+  "tx_desc":      MSGDMA Tx dispatcher descriptor space region
+  "rx_csr" :      xDMA Rx dispatcher control and status space region
+  "rx_desc":      MSGDMA Rx dispatcher descriptor space region
+  "rx_resp":      MSGDMA Rx dispatcher response space region
+  "s1":		  SGDMA descriptor memory
+- interrupts: Should contain the TSE interrupts and it's mode.
+- interrupt-names: Should contain the interrupt names
+  "rx_irq":       xDMA Rx dispatcher interrupt
+  "tx_irq":       xDMA Tx dispatcher interrupt
+- rx-fifo-depth: MAC receive FIFO buffer depth in bytes
+- tx-fifo-depth: MAC transmit FIFO buffer depth in bytes
+- phy-mode: See ethernet.txt in the same directory.
+- phy-handle: See ethernet.txt in the same directory.
+- phy-addr: See ethernet.txt in the same directory. A configuration should
+		include phy-handle or phy-addr.
+- altr,enable-sup-addr: If 0, TSE has no supplemental addresses configured.
+			If 1, TSE supports additional unicast addresses.
+- altr,enable-hash: If 0, TSE does not support hash multicast filtering. If 1,
+			TSE supports a hash based multicast filter.
+
+-mdio device tree subnode: When the TSE has a phy connected to its local
+		mdio, there must be device tree subnode with the following
+		required properties:
+
+	- compatible: Must be "altr,tse-mdio".
+	- #address-cells: Must be <1>.
+	- #size-cells: Must be <0>.
+
+	For each phy on the mdio bus, there must be a node with the following
+	fields:
+
+	- reg: phy id used to communicate to phy.
+	- device_type: Must be "ethernet-phy".
+
+Optional properties:
+- local-mac-address: See ethernet.txt in the same directory.
+- max-frame-size: See ethernet.txt in the same directory.
+
+Example:
+
+	tse_sub_0_eth_tse_0: ethernet@0x100000000 {
+		compatible = "altr,tse-msgdma-1.0";
+		reg = < 0x00000001 0x00000000 0x00000400
+			0x00000001 0x00000460 0x00000020
+			0x00000001 0x00000480 0x00000020
+			0x00000001 0x000004A0 0x00000008
+			0x00000001 0x00000400 0x00000020
+			0x00000001 0x00000420 0x00000020 >;
+		reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
+		interrupt-parent = < &hps_0_arm_gic_0 >;
+		interrupts = < 0 41 4 0 40 4 >;
+		interrupt-names = "rx_irq", "tx_irq";
+		rx-fifo-depth = < 2048 >;
+		tx-fifo-depth = < 2048 >;
+		address-bits = < 48 >;
+		max-frame-size = < 1500 >;
+		local-mac-address = [ 00 00 00 00 00 00 ];
+		phy-mode = "gmii";
+		altr,enable-sup-addr = < 0 >;
+		altr,enable-hash = < 1 >;
+		phy-handle = < &phy0 >;
+		mdio@0 {
+			compatible = "altr,tse-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy0: ethernet-phy@0 {
+				reg = <0x0>;
+				device_type = "ethernet-phy";
+			};
+
+			phy1: ethernet-phy@1 {
+				reg = <0x1>;
+				device_type = "ethernet-phy";
+			};
+
+		};
+	};
+
+	tse_sub_1_eth_tse_0: ethernet@0x100001000 {
+		compatible = "altr,tse-msgdma-1.0";
+		reg = < 0x00000001 0x00001000 0x00000400
+			0x00000001 0x00001460 0x00000020
+			0x00000001 0x00001480 0x00000020
+			0x00000001 0x000014A0 0x00000008
+			0x00000001 0x00001400 0x00000020
+			0x00000001 0x00001420 0x00000020 >;
+		reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
+		interrupt-parent = < &hps_0_arm_gic_0 >;
+		interrupts = < 0 43 4 0 42 4 >;
+		interrupt-names = "rx_irq", "tx_irq";
+		rx-fifo-depth = < 2048 >;
+		tx-fifo-depth = < 2048 >;
+		address-bits = < 48 >;
+		max-frame-size = < 1500 >;
+		local-mac-address = [ 00 00 00 00 00 00 ];
+		phy-mode = "gmii";
+		altr,enable-sup-addr = < 0 >;
+		altr,enable-hash = < 1 >;
+		phy-handle = < &phy1 >;
+	};
-- 
1.7.9.5


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

* [PATCH net-next v2 4/9] Documentation: networking: Add Altera Ethernet (TSE) Documentation
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (2 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 5/9] Altera TSE: Add Altera Ethernet Driver Makefile and Kconfig Vince Bridgers
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds a bindings description for the Altera Triple Speed Ethernet
(TSE) driver. The bindings support the legacy SGDMA soft IP as well as the
preferred MSGDMA soft IP. The TSE can be configured and synthesized in soft
logic using Altera's Quartus toolchain. Please consult the bindings document
for supported options.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Minor edits. No substantial changes to this file.
---
 Documentation/networking/altera_tse.txt |  119 +++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100644 Documentation/networking/altera_tse.txt

diff --git a/Documentation/networking/altera_tse.txt b/Documentation/networking/altera_tse.txt
new file mode 100644
index 0000000..9c3810d
--- /dev/null
+++ b/Documentation/networking/altera_tse.txt
@@ -0,0 +1,119 @@
+       Altera Triple-Speed Ethernet MAC driver
+
+Copyright (C) 2008-2014 Altera Corporation
+
+This is the driver for the Altera Triple-Speed Ethernet (TSE) controllers
+using the SGDMA and MSGDMA soft DMA IP components. The driver uses the
+platform bus to obtain component resources. The designs used to test this
+driver were built for a Cyclone(R) V SOC FPGA board, a Cyclone(R) V FPGA board,
+and tested with ARM and NIOS processor hosts seperately. The anticipated use
+cases are simple communications between an embedded system and an external peer
+for status and simple configuration of the embedded system.
+
+For more information visit www.altera.com and www.rocketboards.org. Support
+forums for the driver may be found on www.rocketboards.org, and a design used
+to test this driver may be found there as well. Support is also available from
+the maintainer of this driver, found in MAINTAINERS.
+
+The Triple-Speed Ethernet, SGDMA, and MSGDMA components are all soft IP
+components that can be assembled and built into an FPGA using the Altera
+Quartus toolchain. Quartus 13.1 and 14.0 were used to build the design that
+this driver was tested against. The sopc2dts tool is used to create the
+device tree for the driver, and may be found at rocketboards.org.
+
+The driver probe function examines the device tree and determines if the
+Triple-Speed Ethernet instance is using an SGDMA or MSGDMA component. The
+probe function then installs the appropriate set of DMA routines to
+initialize, setup transmits, receives, and interrupt handling primitives for
+the respective configurations.
+
+The SGDMA component is to be deprecated in the near future (over the next 1-2
+years as of this writing in early 2014) in favor of the MSGDMA component.
+SGDMA support is included for existing designs and reference in case a
+developer wishes to support their own soft DMA logic and driver support. Any
+new designs should not use the SGDMA.
+
+The SGDMA supports only a single transmit or receive operation at a time, and
+therefore will not perform as well compared to the MSGDMA soft IP. Please
+visit www.altera.com for known, documented SGDMA errata.
+
+Scatter-gather DMA is not supported by the SGDMA or MSGDMA at this time.
+Scatter-gather DMA will be added to a future maintenance update to this
+driver.
+
+Jumbo frames are not supported at this time.
+
+The driver limits PHY operations to 10/100Mbps, and has not yet been fully
+tested for 1Gbps. This support will be added in a future maintenance update.
+
+1) Kernel Configuration
+The kernel configuration option is ALTERA_TSE:
+ Device Drivers ---> Network device support ---> Ethernet driver support --->
+ Altera Triple-Speed Ethernet MAC support (ALTERA_TSE)
+
+2) Driver parameters list:
+	debug: message level (0: no output, 16: all);
+	dma_rx_num: Number of descriptors in the RX list (default is 64);
+	dma_tx_num: Number of descriptors in the TX list (default is 64).
+
+3) Command line options
+Driver parameters can be also passed in command line by using:
+	altera_tse=dma_rx_num:128,dma_tx_num:512
+
+4) Driver information and notes
+
+4.1) Transmit process
+When the driver's transmit routine is called by the kernel, it sets up a
+transmit descriptor by calling the underlying DMA transmit routine (SGDMA or
+MSGDMA), and initites a transmit operation. Once the transmit is complete, an
+interrupt is driven by the transmit DMA logic. The driver handles the transmit
+completion in the context of the interrupt handling chain by recycling
+resource required to send and track the requested transmit operation.
+
+4.2) Receive process
+The driver will post receive buffers to the receive DMA logic during driver
+intialization. Receive buffers may or may not be queued depending upon the
+underlying DMA logic (MSGDMA is able queue receive buffers, SGDMA is not able
+to queue receive buffers to the SGDMA receive logic). When a packet is
+received, the DMA logic generates an interrupt. The driver handles a receive
+interrupt by obtaining the DMA receive logic status, reaping receive
+completions until no more receive completions are available.
+
+4.3) Interrupt Mitigation
+The driver is able to mitigate the number of its DMA interrupts
+using NAPI for receive operations. Interrupt mitigation is not yet supported
+for transmit operations, but will be added in a future maintenance release.
+
+4.4) Ethtool support
+Ethtool is supported. Driver statistics and internal errors can be taken using:
+ethtool -S ethX command. It is possible to dump registers etc.
+
+4.5) PHY Support
+The driver is compatible with PAL to work with PHY and GPHY devices.
+
+4.7) List of source files:
+ o Kconfig
+ o Makefile
+ o altera_tse_main.c: main network device driver
+ o altera_tse_ethtool.c: ethtool support
+ o altera_tse.h: private driver structure and common definitions
+ o altera_msgdma.h: MSGDMA implementation function definitions
+ o altera_sgdma.h: SGDMA implementation function definitions
+ o altera_msgdma.c: MSGDMA implementation
+ o altera_sgdma.c: SGDMA implementation
+ o altera_sgdmahw.h: SGDMA register and descriptor definitions
+ o altera_msgdmahw.h: MSGDMA register and descriptor definitions
+ o altera_utils.c: Driver utility functions
+ o altera_utils.h: Driver utility function definitions
+
+5) Debug Information
+
+The driver exports debug information such as internal statistics,
+debug information, MAC and DMA registers etc.
+
+A user may use the ethtool support to get statistics:
+e.g. using: ethtool -S ethX (that shows the statistics counters)
+or sees the MAC registers: e.g. using: ethtool -d ethX
+
+The developer can also use the "debug" module parameter to get
+further debug information.
-- 
1.7.9.5

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

* [PATCH net-next v2 5/9] Altera TSE: Add Altera Ethernet Driver Makefile and Kconfig
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (3 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 4/9] Documentation: networking: Add Altera Ethernet (TSE) Documentation Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 6/9] Altera TSE: Add Altera Ethernet Driver MSGDMA File Components Vince Bridgers
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds the Altera Triple Speed Ethernet Makfile and
Kconfig file.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Break up the driver files submission, no change to
      the Makefile or Kconfig file
---
 drivers/net/ethernet/altera/Kconfig  |    8 ++++++++
 drivers/net/ethernet/altera/Makefile |    7 +++++++
 2 files changed, 15 insertions(+)
 create mode 100644 drivers/net/ethernet/altera/Kconfig
 create mode 100644 drivers/net/ethernet/altera/Makefile

diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig
new file mode 100644
index 0000000..80c1ab7
--- /dev/null
+++ b/drivers/net/ethernet/altera/Kconfig
@@ -0,0 +1,8 @@
+config ALTERA_TSE
+	tristate "Altera Triple-Speed Ethernet MAC support"
+	select PHYLIB
+	---help---
+	  This driver supports the Altera Triple-Speed (TSE) Ethernet MAC.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called alteratse.
diff --git a/drivers/net/ethernet/altera/Makefile b/drivers/net/ethernet/altera/Makefile
new file mode 100644
index 0000000..d4a187e
--- /dev/null
+++ b/drivers/net/ethernet/altera/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Altera device drivers.
+#
+
+obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
+altera_tse-objs := altera_tse_main.o altera_tse_ethtool.o \
+altera_msgdma.o altera_sgdma.o altera_utils.o
-- 
1.7.9.5


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

* [PATCH net-next v2 6/9] Altera TSE: Add Altera Ethernet Driver MSGDMA File Components
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (4 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 5/9] Altera TSE: Add Altera Ethernet Driver Makefile and Kconfig Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 7/9] Altera TSE: Add Altera Ethernet Driver SGDMA file components Vince Bridgers
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds the MSGDMA soft IP support for the Altera Triple
Speed Ethernet driver.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Use 32-bit upper/lower physical address accessors per comments
      from Florian.
    - Break up the driver file submission into seperate patches
      broken up by functions in the driver.
---
 drivers/net/ethernet/altera/altera_msgdma.c   |  203 +++++++++++++++++++++++++
 drivers/net/ethernet/altera/altera_msgdma.h   |   34 +++++
 drivers/net/ethernet/altera/altera_msgdmahw.h |  167 ++++++++++++++++++++
 3 files changed, 404 insertions(+)
 create mode 100644 drivers/net/ethernet/altera/altera_msgdma.c
 create mode 100644 drivers/net/ethernet/altera/altera_msgdma.h
 create mode 100644 drivers/net/ethernet/altera/altera_msgdmahw.h

diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c
new file mode 100644
index 0000000..c04f7a2
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_msgdma.c
@@ -0,0 +1,203 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "altera_utils.h"
+#include "altera_tse.h"
+#include "altera_msgdmahw.h"
+
+/* No initialization work to do for MSGDMA */
+int msgdma_initialize(struct altera_tse_private *priv)
+{
+	return 0;
+}
+
+void msgdma_uninitialize(struct altera_tse_private *priv)
+{
+}
+
+void msgdma_reset(struct altera_tse_private *priv)
+{
+	int counter;
+	struct msgdma_csr *txcsr =
+		(struct msgdma_csr *)priv->tx_dma_csr;
+	struct msgdma_csr *rxcsr =
+		(struct msgdma_csr *)priv->rx_dma_csr;
+
+	/* Reset Rx mSGDMA */
+	iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status);
+	iowrite32(MSGDMA_CSR_CTL_RESET, &rxcsr->control);
+
+	counter = 0;
+	while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
+		if (tse_bit_is_clear(&rxcsr->status,
+				     MSGDMA_CSR_STAT_RESETTING))
+			break;
+		udelay(1);
+	}
+
+	if ((counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) &&
+	    (netif_msg_drv(priv)))
+		dev_warn(priv->device,
+			 "TSE Rx mSGDMA resetting bit never cleared!\n");
+
+	/* clear all status bits */
+	iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status);
+
+	/* Reset Tx mSGDMA */
+	iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status);
+	iowrite32(MSGDMA_CSR_CTL_RESET, &txcsr->control);
+
+	counter = 0;
+	while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
+		if (tse_bit_is_clear(&txcsr->status,
+				     MSGDMA_CSR_STAT_RESETTING))
+			break;
+		udelay(1);
+	}
+
+	if ((counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) &&
+	    (netif_msg_drv(priv)))
+		dev_warn(priv->device,
+			 "TSE Tx mSGDMA resetting bit never cleared!\n");
+
+	/* clear all status bits */
+	iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status);
+}
+
+void msgdma_disable_rxirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->rx_dma_csr;
+	tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+}
+
+void msgdma_enable_rxirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->rx_dma_csr;
+	tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+}
+
+void msgdma_disable_txirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->tx_dma_csr;
+	tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+}
+
+void msgdma_enable_txirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->tx_dma_csr;
+	tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+}
+
+void msgdma_clear_rxirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->rx_dma_csr;
+	iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status);
+}
+
+void msgdma_clear_txirq(struct altera_tse_private *priv)
+{
+	struct msgdma_csr *csr = priv->tx_dma_csr;
+	iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status);
+}
+
+/* return 0 to indicate transmit is pending */
+int msgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
+{
+	struct msgdma_extended_desc *desc = priv->tx_dma_desc;
+
+	iowrite32(lower_32_bits(buffer->dma_addr), &desc->read_addr_lo);
+	iowrite32(upper_32_bits(buffer->dma_addr), &desc->read_addr_hi);
+	iowrite32(0, &desc->write_addr_lo);
+	iowrite32(0, &desc->write_addr_hi);
+	iowrite32(buffer->len, &desc->len);
+	iowrite32(0, &desc->burst_seq_num);
+	iowrite32(MSGDMA_DESC_TX_STRIDE, &desc->stride);
+	iowrite32(MSGDMA_DESC_CTL_TX_SINGLE, &desc->control);
+	return 0;
+}
+
+u32 msgdma_tx_completions(struct altera_tse_private *priv)
+{
+	u32 ready = 0;
+	u32 inuse;
+	u32 status;
+	struct msgdma_csr *txcsr =
+		(struct msgdma_csr *)priv->tx_dma_csr;
+
+	/* Get number of sent descriptors */
+	inuse = ioread32(&txcsr->rw_fill_level) & 0xffff;
+
+	if (inuse) { /* Tx FIFO is not empty */
+		ready = priv->tx_prod - priv->tx_cons - inuse - 1;
+	} else {
+		/* Check for buffered last packet */
+		status = ioread32(&txcsr->status);
+		if (status & MSGDMA_CSR_STAT_BUSY)
+			ready = priv->tx_prod - priv->tx_cons - 1;
+		else
+			ready = priv->tx_prod - priv->tx_cons;
+	}
+	return ready;
+}
+
+/* Put buffer to the mSGDMA RX FIFO
+ */
+int msgdma_add_rx_desc(struct altera_tse_private *priv,
+			struct tse_buffer *rxbuffer)
+{
+	struct msgdma_extended_desc *desc = priv->rx_dma_desc;
+	u32 len = priv->rx_dma_buf_sz;
+	dma_addr_t dma_addr = rxbuffer->dma_addr;
+	u32 control = (MSGDMA_DESC_CTL_END_ON_EOP
+			| MSGDMA_DESC_CTL_END_ON_LEN
+			| MSGDMA_DESC_CTL_TR_COMP_IRQ
+			| MSGDMA_DESC_CTL_EARLY_IRQ
+			| MSGDMA_DESC_CTL_TR_ERR_IRQ
+			| MSGDMA_DESC_CTL_GO);
+
+	iowrite32(0, &desc->read_addr_lo);
+	iowrite32(0, &desc->read_addr_hi);
+	iowrite32(lower_32_bits(dma_addr), &desc->write_addr_lo);
+	iowrite32(upper_32_bits(dma_addr), &desc->write_addr_hi);
+	iowrite32(len, &desc->len);
+	iowrite32(0, &desc->burst_seq_num);
+	iowrite32(0x00010001, &desc->stride);
+	iowrite32(control, &desc->control);
+	return 1;
+}
+
+/* status is returned on upper 16 bits,
+ * length is returned in lower 16 bits
+ */
+u32 msgdma_rx_status(struct altera_tse_private *priv)
+{
+	u32 rxstatus = 0;
+	u32 pktlength;
+	u32 pktstatus;
+	struct msgdma_csr *rxcsr =
+		(struct msgdma_csr *)priv->rx_dma_csr;
+	struct msgdma_response *rxresp =
+		(struct msgdma_response *)priv->rx_dma_resp;
+
+	if (ioread32(&rxcsr->resp_fill_level) & 0xffff) {
+		pktlength = ioread32(&rxresp->bytes_transferred);
+		pktstatus = ioread32(&rxresp->status);
+		rxstatus = pktstatus;
+		rxstatus = rxstatus << 16;
+		rxstatus |= (pktlength & 0xffff);
+	}
+	return rxstatus;
+}
diff --git a/drivers/net/ethernet/altera/altera_msgdma.h b/drivers/net/ethernet/altera/altera_msgdma.h
new file mode 100644
index 0000000..7f0f5bf
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_msgdma.h
@@ -0,0 +1,34 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ALTERA_MSGDMA_H__
+#define __ALTERA_MSGDMA_H__
+
+void msgdma_reset(struct altera_tse_private *);
+void msgdma_enable_txirq(struct altera_tse_private *);
+void msgdma_enable_rxirq(struct altera_tse_private *);
+void msgdma_disable_rxirq(struct altera_tse_private *);
+void msgdma_disable_txirq(struct altera_tse_private *);
+void msgdma_clear_rxirq(struct altera_tse_private *);
+void msgdma_clear_txirq(struct altera_tse_private *);
+u32 msgdma_tx_completions(struct altera_tse_private *);
+int msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *);
+int msgdma_tx_buffer(struct altera_tse_private *, struct tse_buffer *);
+u32 msgdma_rx_status(struct altera_tse_private *);
+int msgdma_initialize(struct altera_tse_private *);
+void msgdma_uninitialize(struct altera_tse_private *);
+
+#endif /*  __ALTERA_MSGDMA_H__ */
diff --git a/drivers/net/ethernet/altera/altera_msgdmahw.h b/drivers/net/ethernet/altera/altera_msgdmahw.h
new file mode 100644
index 0000000..d7b59ba
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_msgdmahw.h
@@ -0,0 +1,167 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ALTERA_MSGDMAHW_H__
+#define __ALTERA_MSGDMAHW_H__
+
+/* mSGDMA standard descriptor format
+ */
+struct msgdma_desc {
+	u32 read_addr;	/* data buffer source address */
+	u32 write_addr;	/* data buffer destination address */
+	u32 len;	/* the number of bytes to transfer per descriptor */
+	u32 control;	/* characteristics of the transfer */
+};
+
+/* mSGDMA extended descriptor format
+ */
+struct msgdma_extended_desc {
+	u32 read_addr_lo;	/* data buffer source address low bits */
+	u32 write_addr_lo;	/* data buffer destination address low bits */
+	u32 len;		/* the number of bytes to transfer
+				 * per descriptor
+				 */
+	u32 burst_seq_num;	/* bit 31:24 write burst
+				 * bit 23:16 read burst
+				 * bit 15:0  sequence number
+				 */
+	u32 stride;		/* bit 31:16 write stride
+				 * bit 15:0  read stride
+				 */
+	u32 read_addr_hi;	/* data buffer source address high bits */
+	u32 write_addr_hi;	/* data buffer destination address high bits */
+	u32 control;		/* characteristics of the transfer */
+};
+
+/* mSGDMA descriptor control field bit definitions
+ */
+#define MSGDMA_DESC_CTL_SET_CH(x)	((x) & 0xff)
+#define MSGDMA_DESC_CTL_GEN_SOP		BIT(8)
+#define MSGDMA_DESC_CTL_GEN_EOP		BIT(9)
+#define MSGDMA_DESC_CTL_PARK_READS	BIT(10)
+#define MSGDMA_DESC_CTL_PARK_WRITES	BIT(11)
+#define MSGDMA_DESC_CTL_END_ON_EOP	BIT(12)
+#define MSGDMA_DESC_CTL_END_ON_LEN	BIT(13)
+#define MSGDMA_DESC_CTL_TR_COMP_IRQ	BIT(14)
+#define MSGDMA_DESC_CTL_EARLY_IRQ	BIT(15)
+#define MSGDMA_DESC_CTL_TR_ERR_IRQ	(0xff << 16)
+#define MSGDMA_DESC_CTL_EARLY_DONE	BIT(24)
+/* Writing ‘1’ to the ‘go’ bit commits the entire descriptor into the
+ * descriptor FIFO(s)
+ */
+#define MSGDMA_DESC_CTL_GO		BIT(31)
+
+/* Tx buffer control flags
+ */
+#define MSGDMA_DESC_CTL_TX_FIRST	(MSGDMA_DESC_CTL_GEN_SOP |	\
+					 MSGDMA_DESC_CTL_TR_ERR_IRQ |	\
+					 MSGDMA_DESC_CTL_GO)
+
+#define MSGDMA_DESC_CTL_TX_MIDDLE	(MSGDMA_DESC_CTL_TR_ERR_IRQ |	\
+					 MSGDMA_DESC_CTL_GO)
+
+#define MSGDMA_DESC_CTL_TX_LAST		(MSGDMA_DESC_CTL_GEN_EOP |	\
+					 MSGDMA_DESC_CTL_TR_COMP_IRQ |	\
+					 MSGDMA_DESC_CTL_TR_ERR_IRQ |	\
+					 MSGDMA_DESC_CTL_GO)
+
+#define MSGDMA_DESC_CTL_TX_SINGLE	(MSGDMA_DESC_CTL_GEN_SOP |	\
+					 MSGDMA_DESC_CTL_GEN_EOP |	\
+					 MSGDMA_DESC_CTL_TR_COMP_IRQ |	\
+					 MSGDMA_DESC_CTL_TR_ERR_IRQ |	\
+					 MSGDMA_DESC_CTL_GO)
+
+#define MSGDMA_DESC_CTL_RX_SINGLE	(MSGDMA_DESC_CTL_END_ON_EOP |	\
+					 MSGDMA_DESC_CTL_END_ON_LEN |	\
+					 MSGDMA_DESC_CTL_TR_COMP_IRQ |	\
+					 MSGDMA_DESC_CTL_EARLY_IRQ |	\
+					 MSGDMA_DESC_CTL_TR_ERR_IRQ |	\
+					 MSGDMA_DESC_CTL_GO)
+
+/* mSGDMA extended descriptor stride definitions
+ */
+#define MSGDMA_DESC_TX_STRIDE		(0x00010001)
+#define MSGDMA_DESC_RX_STRIDE		(0x00010001)
+
+/* mSGDMA dispatcher control and status register map
+ */
+struct msgdma_csr {
+	u32 status;		/* Read/Clear */
+	u32 control;		/* Read/Write */
+	u32 rw_fill_level;	/* bit 31:16 - write fill level
+				 * bit 15:0  - read fill level
+				 */
+	u32 resp_fill_level;	/* bit 15:0 */
+	u32 rw_seq_num;		/* bit 31:16 - write sequence number
+				 * bit 15:0  - read sequence number
+				 */
+	u32 pad[3];		/* reserved */
+};
+
+/* mSGDMA CSR status register bit definitions
+ */
+#define MSGDMA_CSR_STAT_BUSY			BIT(0)
+#define MSGDMA_CSR_STAT_DESC_BUF_EMPTY		BIT(1)
+#define MSGDMA_CSR_STAT_DESC_BUF_FULL		BIT(2)
+#define MSGDMA_CSR_STAT_RESP_BUF_EMPTY		BIT(3)
+#define MSGDMA_CSR_STAT_RESP_BUF_FULL		BIT(4)
+#define MSGDMA_CSR_STAT_STOPPED			BIT(5)
+#define MSGDMA_CSR_STAT_RESETTING		BIT(6)
+#define MSGDMA_CSR_STAT_STOPPED_ON_ERR		BIT(7)
+#define MSGDMA_CSR_STAT_STOPPED_ON_EARLY	BIT(8)
+#define MSGDMA_CSR_STAT_IRQ			BIT(9)
+#define MSGDMA_CSR_STAT_MASK			0x3FF
+#define MSGDMA_CSR_STAT_MASK_WITHOUT_IRQ	0x1FF
+
+#define MSGDMA_CSR_STAT_BUSY_GET(v)			GET_BIT_VALUE(v, 0)
+#define MSGDMA_CSR_STAT_DESC_BUF_EMPTY_GET(v)		GET_BIT_VALUE(v, 1)
+#define MSGDMA_CSR_STAT_DESC_BUF_FULL_GET(v)		GET_BIT_VALUE(v, 2)
+#define MSGDMA_CSR_STAT_RESP_BUF_EMPTY_GET(v)		GET_BIT_VALUE(v, 3)
+#define MSGDMA_CSR_STAT_RESP_BUF_FULL_GET(v)		GET_BIT_VALUE(v, 4)
+#define MSGDMA_CSR_STAT_STOPPED_GET(v)			GET_BIT_VALUE(v, 5)
+#define MSGDMA_CSR_STAT_RESETTING_GET(v)		GET_BIT_VALUE(v, 6)
+#define MSGDMA_CSR_STAT_STOPPED_ON_ERR_GET(v)		GET_BIT_VALUE(v, 7)
+#define MSGDMA_CSR_STAT_STOPPED_ON_EARLY_GET(v)		GET_BIT_VALUE(v, 8)
+#define MSGDMA_CSR_STAT_IRQ_GET(v)			GET_BIT_VALUE(v, 9)
+
+/* mSGDMA CSR control register bit definitions
+ */
+#define MSGDMA_CSR_CTL_STOP			BIT(0)
+#define MSGDMA_CSR_CTL_RESET			BIT(1)
+#define MSGDMA_CSR_CTL_STOP_ON_ERR		BIT(2)
+#define MSGDMA_CSR_CTL_STOP_ON_EARLY		BIT(3)
+#define MSGDMA_CSR_CTL_GLOBAL_INTR		BIT(4)
+#define MSGDMA_CSR_CTL_STOP_DESCS		BIT(5)
+
+/* mSGDMA CSR fill level bits
+ */
+#define MSGDMA_CSR_WR_FILL_LEVEL_GET(v)		(((v) & 0xffff0000) >> 16)
+#define MSGDMA_CSR_RD_FILL_LEVEL_GET(v)		((v) & 0x0000ffff)
+#define MSGDMA_CSR_RESP_FILL_LEVEL_GET(v)	((v) & 0x0000ffff)
+
+/* mSGDMA response register map
+ */
+struct msgdma_response {
+	u32 bytes_transferred;
+	u32 status;
+};
+
+/* mSGDMA response register bit definitions
+ */
+#define MSGDMA_RESP_EARLY_TERM	BIT(8)
+#define MSGDMA_RESP_ERR_MASK	0xFF
+
+#endif /* __ALTERA_MSGDMA_H__*/
-- 
1.7.9.5

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

* [PATCH net-next v2 7/9] Altera TSE: Add Altera Ethernet Driver SGDMA file components
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (5 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 6/9] Altera TSE: Add Altera Ethernet Driver MSGDMA File Components Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver Vince Bridgers
  2014-03-10 23:14 ` [PATCH net-next v2 9/9] Altera TSE: Add main and header file " Vince Bridgers
  8 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds the SGDMA soft IP support for the Altera Triple
Speed Ethernet driver.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Use 32-bit lower/upper physical address accessors per comments
      from Florian.
    - Break up driver file submission for initial review by logical
      function.
---
 drivers/net/ethernet/altera/altera_sgdma.c   |  532 ++++++++++++++++++++++++++
 drivers/net/ethernet/altera/altera_sgdma.h   |   35 ++
 drivers/net/ethernet/altera/altera_sgdmahw.h |  124 ++++++
 3 files changed, 691 insertions(+)
 create mode 100644 drivers/net/ethernet/altera/altera_sgdma.c
 create mode 100644 drivers/net/ethernet/altera/altera_sgdma.h
 create mode 100644 drivers/net/ethernet/altera/altera_sgdmahw.h

diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c
new file mode 100644
index 0000000..804f212
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_sgdma.c
@@ -0,0 +1,532 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/list.h>
+#include "altera_utils.h"
+#include "altera_tse.h"
+#include "altera_sgdmahw.h"
+#include "altera_sgdma.h"
+
+static void sgdma_descrip(struct sgdma_descrip *desc,
+			  struct sgdma_descrip *ndesc,
+			  dma_addr_t ndesc_phys,
+			  dma_addr_t raddr,
+			  dma_addr_t waddr,
+			  u16 length,
+			  int generate_eop,
+			  int rfixed,
+			  int wfixed);
+
+static int sgdma_async_write(struct altera_tse_private *priv,
+			      struct sgdma_descrip *desc);
+
+static int sgdma_async_read(struct altera_tse_private *priv);
+
+static dma_addr_t
+sgdma_txphysaddr(struct altera_tse_private *priv,
+		 struct sgdma_descrip *desc);
+
+static dma_addr_t
+sgdma_rxphysaddr(struct altera_tse_private *priv,
+		 struct sgdma_descrip *desc);
+
+static int sgdma_txbusy(struct altera_tse_private *priv);
+
+static int sgdma_rxbusy(struct altera_tse_private *priv);
+
+static void
+queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer);
+
+static void
+queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer);
+
+static struct tse_buffer *
+dequeue_tx(struct altera_tse_private *priv);
+
+static struct tse_buffer *
+dequeue_rx(struct altera_tse_private *priv);
+
+static struct tse_buffer *
+queue_rx_peekhead(struct altera_tse_private *priv);
+
+int sgdma_initialize(struct altera_tse_private *priv)
+{
+	priv->txctrlreg = SGDMA_CTRLREG_ILASTD;
+
+	priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP |
+		      SGDMA_CTRLREG_ILASTD;
+
+	INIT_LIST_HEAD(&priv->txlisthd);
+	INIT_LIST_HEAD(&priv->rxlisthd);
+
+	priv->rxdescphys = (dma_addr_t) 0;
+	priv->txdescphys = (dma_addr_t) 0;
+
+	priv->rxdescphys = dma_map_single(priv->device, priv->rx_dma_desc,
+					  priv->rxdescmem, DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(priv->device, priv->rxdescphys)) {
+		sgdma_uninitialize(priv);
+		dev_dbg(priv->device, "error mapping rx descriptor memory\n");
+		return -EINVAL;
+	}
+
+	priv->txdescphys = dma_map_single(priv->device, priv->rx_dma_desc,
+					  priv->rxdescmem, DMA_TO_DEVICE);
+
+	if (dma_mapping_error(priv->device, priv->txdescphys)) {
+		sgdma_uninitialize(priv);
+		dev_dbg(priv->device, "error mapping tx descriptor memory\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void sgdma_uninitialize(struct altera_tse_private *priv)
+{
+	if (priv->rxdescphys)
+		dma_unmap_single(priv->device, priv->rxdescphys,
+				 priv->rxdescmem, DMA_BIDIRECTIONAL);
+
+	if (priv->txdescphys)
+		dma_unmap_single(priv->device, priv->txdescphys,
+				 priv->txdescmem, DMA_TO_DEVICE);
+}
+
+/* This function resets the SGDMA controller and clears the
+ * descriptor memory used for transmits and receives.
+ */
+void sgdma_reset(struct altera_tse_private *priv)
+{
+	u32 *ptxdescripmem = (u32 *)priv->tx_dma_desc;
+	u32 txdescriplen   = priv->txdescmem;
+	u32 *prxdescripmem = (u32 *)priv->rx_dma_desc;
+	u32 rxdescriplen   = priv->rxdescmem;
+	struct sgdma_csr *ptxsgdma = (struct sgdma_csr *)priv->tx_dma_csr;
+	struct sgdma_csr *prxsgdma = (struct sgdma_csr *)priv->rx_dma_csr;
+
+	/* Initialize descriptor memory to 0 */
+	memset(ptxdescripmem, 0, txdescriplen);
+	memset(prxdescripmem, 0, rxdescriplen);
+
+	iowrite32(SGDMA_CTRLREG_RESET, &ptxsgdma->control);
+	iowrite32(0, &ptxsgdma->control);
+
+	iowrite32(SGDMA_CTRLREG_RESET, &prxsgdma->control);
+	iowrite32(0, &prxsgdma->control);
+}
+
+void sgdma_enable_rxirq(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
+	priv->rxctrlreg |= SGDMA_CTRLREG_INTEN;
+	tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
+}
+
+void sgdma_enable_txirq(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
+	priv->txctrlreg |= SGDMA_CTRLREG_INTEN;
+	tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
+}
+
+/* for SGDMA, RX interrupts remain enabled after enabling */
+void sgdma_disable_rxirq(struct altera_tse_private *priv)
+{
+}
+
+/* for SGDMA, TX interrupts remain enabled after enabling */
+void sgdma_disable_txirq(struct altera_tse_private *priv)
+{
+}
+
+void sgdma_clear_rxirq(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
+	tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
+}
+
+void sgdma_clear_txirq(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
+	tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
+}
+
+/* transmits buffer through SGDMA. Returns number of buffers
+ * transmitted, 0 if not possible.
+ *
+ * tx_lock is held by the caller
+ */
+int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
+{
+	int pktstx = 0;
+	struct sgdma_descrip *descbase =
+		(struct sgdma_descrip *)priv->tx_dma_desc;
+
+	struct sgdma_descrip *cdesc = &descbase[0];
+	struct sgdma_descrip *ndesc = &descbase[1];
+
+	/* wait 'til the tx sgdma is ready for the next transmit request */
+	if (sgdma_txbusy(priv))
+		return 0;
+
+	sgdma_descrip(cdesc,			/* current descriptor */
+		      ndesc,			/* next descriptor */
+		      sgdma_txphysaddr(priv, ndesc),
+		      buffer->dma_addr,		/* address of packet to xmit */
+		      0,			/* write addr 0 for tx dma */
+		      buffer->len,		/* length of packet */
+		      SGDMA_CONTROL_EOP,	/* Generate EOP */
+		      0,			/* read fixed */
+		      SGDMA_CONTROL_WR_FIXED);	/* Generate SOP */
+
+	pktstx = sgdma_async_write(priv, cdesc);
+
+	/* enqueue the request to the pending transmit queue */
+	queue_tx(priv, buffer);
+
+	return 1;
+}
+
+
+/* tx_lock held to protect access to queued tx list
+ */
+u32 sgdma_tx_completions(struct altera_tse_private *priv)
+{
+	u32 ready = 0;
+	struct sgdma_descrip *desc = (struct sgdma_descrip *)priv->tx_dma_desc;
+
+	if (!sgdma_txbusy(priv) &&
+	    ((desc->control & SGDMA_CONTROL_HW_OWNED) == 0) &&
+	    (dequeue_tx(priv))) {
+		ready = 1;
+	}
+
+	return ready;
+}
+
+int sgdma_add_rx_desc(struct altera_tse_private *priv,
+		      struct tse_buffer *rxbuffer)
+{
+	queue_rx(priv, rxbuffer);
+	return sgdma_async_read(priv);
+}
+
+/* status is returned on upper 16 bits,
+ * length is returned in lower 16 bits
+ */
+u32 sgdma_rx_status(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
+	struct sgdma_descrip *base = (struct sgdma_descrip *)priv->rx_dma_desc;
+	struct sgdma_descrip *desc = NULL;
+	int pktsrx;
+	unsigned int rxstatus = 0;
+	unsigned int pktlength = 0;
+	unsigned int pktstatus = 0;
+	struct tse_buffer *rxbuffer = NULL;
+
+	dma_sync_single_for_cpu(priv->device,
+				priv->rxdescphys,
+				priv->rxdescmem,
+				DMA_BIDIRECTIONAL);
+
+	desc = &base[0];
+	if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) ||
+	    (desc->status & SGDMA_STATUS_EOP)) {
+		pktlength = desc->bytes_xferred;
+		pktstatus = desc->status & 0x3f;
+		rxstatus = pktstatus;
+		rxstatus = rxstatus << 16;
+		rxstatus |= (pktlength & 0xffff);
+
+		desc->status = 0;
+
+		rxbuffer = dequeue_rx(priv);
+		if (rxbuffer == NULL)
+			dev_info(priv->device,
+				 "sgdma rx and rx queue empty!\n");
+
+		/* kick the rx sgdma after reaping this descriptor */
+		pktsrx = sgdma_async_read(priv);
+	}
+
+	return rxstatus;
+}
+
+
+/* Private functions */
+static void sgdma_descrip(struct sgdma_descrip *desc,
+			  struct sgdma_descrip *ndesc,
+			  dma_addr_t ndesc_phys,
+			  dma_addr_t raddr,
+			  dma_addr_t waddr,
+			  u16 length,
+			  int generate_eop,
+			  int rfixed,
+			  int wfixed)
+{
+	/* Clear the next descriptor as not owned by hardware */
+	u32 ctrl = ndesc->control;
+	ctrl &= ~SGDMA_CONTROL_HW_OWNED;
+	ndesc->control = ctrl;
+
+	ctrl = 0;
+	ctrl = SGDMA_CONTROL_HW_OWNED;
+	ctrl |= generate_eop;
+	ctrl |= rfixed;
+	ctrl |= wfixed;
+
+	/* Channel is implicitly zero, initialized to 0 by default */
+
+	desc->raddr = raddr;
+	desc->waddr = waddr;
+	desc->next = lower_32_bits(ndesc_phys);
+	desc->control = ctrl;
+	desc->status = 0;
+	desc->rburst = 0;
+	desc->wburst = 0;
+	desc->bytes = length;
+	desc->bytes_xferred = 0;
+}
+
+/* If hardware is busy, don't restart async read.
+ * if status register is 0 - meaning initial state, restart async read,
+ * probably for the first time when populating a receive buffer.
+ * If read status indicate not busy and a status, restart the async
+ * DMA read.
+ */
+static int sgdma_async_read(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
+	struct sgdma_descrip *descbase =
+		(struct sgdma_descrip *)priv->rx_dma_desc;
+
+	struct sgdma_descrip *cdesc = &descbase[0];
+	struct sgdma_descrip *ndesc = &descbase[1];
+
+	unsigned int sts = ioread32(&csr->status);
+	struct tse_buffer *rxbuffer = NULL;
+
+	if (!sgdma_rxbusy(priv)) {
+		rxbuffer = queue_rx_peekhead(priv);
+		if (rxbuffer == NULL)
+			return 0;
+
+		sgdma_descrip(cdesc,		/* current descriptor */
+			      ndesc,		/* next descriptor */
+			      sgdma_rxphysaddr(priv, ndesc),
+			      0,		/* read addr 0 for rx dma */
+			      rxbuffer->dma_addr, /* write addr for rx dma */
+			      0,		/* read 'til EOP */
+			      0,		/* EOP: NA for rx dma */
+			      0,		/* read fixed: NA for rx dma */
+			      0);		/* SOP: NA for rx DMA */
+
+		/* clear control and status */
+		iowrite32(0, &csr->control);
+
+		/* If statuc available, clear those bits */
+		if (sts & 0xf)
+			iowrite32(0xf, &csr->status);
+
+		dma_sync_single_for_device(priv->device,
+					   priv->rxdescphys,
+					   priv->rxdescmem,
+					   DMA_BIDIRECTIONAL);
+
+		iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
+			  &csr->next_descrip);
+
+		iowrite32((priv->rxctrlreg | SGDMA_CTRLREG_START),
+			  &csr->control);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int sgdma_async_write(struct altera_tse_private *priv,
+			     struct sgdma_descrip *desc)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
+
+	if (sgdma_txbusy(priv))
+		return 0;
+
+	/* clear control and status */
+	iowrite32(0, &csr->control);
+	iowrite32(0x1f, &csr->status);
+
+	dma_sync_single_for_device(priv->device, priv->txdescphys,
+				   priv->txdescmem, DMA_TO_DEVICE);
+
+	iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
+		  &csr->next_descrip);
+
+	iowrite32((priv->txctrlreg | SGDMA_CTRLREG_START),
+		  &csr->control);
+
+	return 1;
+}
+
+static dma_addr_t
+sgdma_txphysaddr(struct altera_tse_private *priv,
+		 struct sgdma_descrip *desc)
+{
+	dma_addr_t paddr = priv->txdescmem_busaddr;
+	dma_addr_t offs = (dma_addr_t)((dma_addr_t)desc -
+				(dma_addr_t)priv->tx_dma_desc);
+	return paddr + offs;
+}
+
+static dma_addr_t
+sgdma_rxphysaddr(struct altera_tse_private *priv,
+		 struct sgdma_descrip *desc)
+{
+	dma_addr_t paddr = priv->rxdescmem_busaddr;
+	dma_addr_t offs = (dma_addr_t)((dma_addr_t)desc -
+				(dma_addr_t)priv->rx_dma_desc);
+	return paddr + offs;
+}
+
+/* Function not used, here for debug purposes */
+void
+dumpdesc(struct altera_tse_private *priv,
+	 struct sgdma_descrip *desc, int index)
+{
+	dev_info(priv->device, "desc %x, index %d\n",
+		 (unsigned int)desc, index);
+	dev_info(priv->device, "    raddr  %x\n", desc->raddr);
+	dev_info(priv->device, "    pad1   %x\n", desc->pad1);
+	dev_info(priv->device, "    waddr  %x\n", desc->waddr);
+	dev_info(priv->device, "    pad2   %x\n", desc->pad2);
+	dev_info(priv->device, "    next   %x\n", desc->next);
+	dev_info(priv->device, "    pad3   %x\n", desc->pad3);
+	dev_info(priv->device, "    bytes  %x\n", desc->bytes);
+	dev_info(priv->device, "    rburst %x\n", desc->rburst);
+	dev_info(priv->device, "    wburst %x\n", desc->wburst);
+	dev_info(priv->device, "    xfer   %x\n", desc->bytes_xferred);
+	dev_info(priv->device, "    sts    %x\n", desc->status);
+	dev_info(priv->device, "    ctrl   %x\n", desc->control);
+}
+
+#define list_remove_head(list, entry, type, member)			\
+	do {								\
+		entry = NULL;						\
+		if (!list_empty(list)) {				\
+			entry = list_entry((list)->next, type, member);	\
+			list_del_init(&entry->member);			\
+		}							\
+	} while (0)
+
+#define list_peek_head(list, entry, type, member)			\
+	do {								\
+		entry = NULL;						\
+		if (!list_empty(list)) {				\
+			entry = list_entry((list)->next, type, member);	\
+		}							\
+	} while (0)
+
+/* adds a tse_buffer to the tail of a tx buffer list.
+ * assumes the caller is managing and holding a mutual exclusion
+ * primitive to avoid simultaneous pushes/pops to the list.
+ */
+static void
+queue_tx(struct altera_tse_private *priv, struct tse_buffer *buffer)
+{
+	list_add_tail(&buffer->lh, &priv->txlisthd);
+}
+
+
+/* adds a tse_buffer to the tail of a rx buffer list
+ * assumes the caller is managing and holding a mutual exclusion
+ * primitive to avoid simultaneous pushes/pops to the list.
+ */
+static void
+queue_rx(struct altera_tse_private *priv, struct tse_buffer *buffer)
+{
+	list_add_tail(&buffer->lh, &priv->rxlisthd);
+}
+
+/* dequeues a tse_buffer from the transmit buffer list, otherwise
+ * returns NULL if empty.
+ * assumes the caller is managing and holding a mutual exclusion
+ * primitive to avoid simultaneous pushes/pops to the list.
+ */
+static struct tse_buffer *
+dequeue_tx(struct altera_tse_private *priv)
+{
+	struct tse_buffer *buffer = NULL;
+	list_remove_head(&priv->txlisthd, buffer, struct tse_buffer, lh);
+	return buffer;
+}
+
+/* dequeues a tse_buffer from the receive buffer list, otherwise
+ * returns NULL if empty
+ * assumes the caller is managing and holding a mutual exclusion
+ * primitive to avoid simultaneous pushes/pops to the list.
+ */
+static struct tse_buffer *
+dequeue_rx(struct altera_tse_private *priv)
+{
+	struct tse_buffer *buffer = NULL;
+	list_remove_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
+	return buffer;
+}
+
+/* dequeues a tse_buffer from the receive buffer list, otherwise
+ * returns NULL if empty
+ * assumes the caller is managing and holding a mutual exclusion
+ * primitive to avoid simultaneous pushes/pops to the list while the
+ * head is being examined.
+ */
+static struct tse_buffer *
+queue_rx_peekhead(struct altera_tse_private *priv)
+{
+	struct tse_buffer *buffer = NULL;
+	list_peek_head(&priv->rxlisthd, buffer, struct tse_buffer, lh);
+	return buffer;
+}
+
+/* check and return rx sgdma status without polling
+ */
+static int sgdma_rxbusy(struct altera_tse_private *priv)
+{
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
+	return ioread32(&csr->status) & SGDMA_STSREG_BUSY;
+}
+
+/* waits for the tx sgdma to finish it's current operation, returns 0
+ * when it transitions to nonbusy, returns 1 if the operation times out
+ */
+static int sgdma_txbusy(struct altera_tse_private *priv)
+{
+	int delay = 0;
+	struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
+
+	/* if DMA is busy, wait for current transactino to finish */
+	while ((ioread32(&csr->status) & SGDMA_STSREG_BUSY) && (delay++ < 100))
+		udelay(1);
+
+	if (ioread32(&csr->status) & SGDMA_STSREG_BUSY) {
+		dev_dbg(priv->device, "timeout waiting for tx dma\n");
+		return 1;
+	}
+	return 0;
+}
diff --git a/drivers/net/ethernet/altera/altera_sgdma.h b/drivers/net/ethernet/altera/altera_sgdma.h
new file mode 100644
index 0000000..07d4717
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_sgdma.h
@@ -0,0 +1,35 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ALTERA_SGDMA_H__
+#define __ALTERA_SGDMA_H__
+
+void sgdma_reset(struct altera_tse_private *);
+void sgdma_enable_txirq(struct altera_tse_private *);
+void sgdma_enable_rxirq(struct altera_tse_private *);
+void sgdma_disable_rxirq(struct altera_tse_private *);
+void sgdma_disable_txirq(struct altera_tse_private *);
+void sgdma_clear_rxirq(struct altera_tse_private *);
+void sgdma_clear_txirq(struct altera_tse_private *);
+int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *);
+u32 sgdma_tx_completions(struct altera_tse_private *);
+int sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *);
+void sgdma_status(struct altera_tse_private *);
+u32 sgdma_rx_status(struct altera_tse_private *);
+int sgdma_initialize(struct altera_tse_private *);
+void sgdma_uninitialize(struct altera_tse_private *);
+
+#endif /*  __ALTERA_SGDMA_H__ */
diff --git a/drivers/net/ethernet/altera/altera_sgdmahw.h b/drivers/net/ethernet/altera/altera_sgdmahw.h
new file mode 100644
index 0000000..ba3334f
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_sgdmahw.h
@@ -0,0 +1,124 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ALTERA_SGDMAHW_H__
+#define __ALTERA_SGDMAHW_H__
+
+/* SGDMA descriptor structure */
+struct sgdma_descrip {
+	unsigned int	raddr; /* address of data to be read */
+	unsigned int	pad1;
+	unsigned int	waddr;
+	unsigned int    pad2;
+	unsigned int	next;
+	unsigned int	pad3;
+	unsigned short  bytes;
+	unsigned char   rburst;
+	unsigned char	wburst;
+	unsigned short	bytes_xferred;	/* 16 bits, bytes xferred */
+
+	/* bit 0: error
+	 * bit 1: length error
+	 * bit 2: crc error
+	 * bit 3: truncated error
+	 * bit 4: phy error
+	 * bit 5: collision error
+	 * bit 6: reserved
+	 * bit 7: status eop for recv case
+	 */
+	unsigned char	status;
+
+	/* bit 0: eop
+	 * bit 1: read_fixed
+	 * bit 2: write fixed
+	 * bits 3,4,5,6: Channel (always 0)
+	 * bit 7: hardware owned
+	 */
+	unsigned char	control;
+} __packed;
+
+
+#define SGDMA_STATUS_ERR		BIT(0)
+#define SGDMA_STATUS_LENGTH_ERR		BIT(1)
+#define SGDMA_STATUS_CRC_ERR		BIT(2)
+#define SGDMA_STATUS_TRUNC_ERR		BIT(3)
+#define SGDMA_STATUS_PHY_ERR		BIT(4)
+#define SGDMA_STATUS_COLL_ERR		BIT(5)
+#define SGDMA_STATUS_EOP		BIT(7)
+
+#define SGDMA_CONTROL_EOP		BIT(0)
+#define SGDMA_CONTROL_RD_FIXED		BIT(1)
+#define SGDMA_CONTROL_WR_FIXED		BIT(2)
+
+/* Channel is always 0, so just zero initialize it */
+
+#define SGDMA_CONTROL_HW_OWNED		BIT(7)
+
+/* SGDMA register space */
+struct sgdma_csr {
+	/* bit 0: error
+	 * bit 1: eop
+	 * bit 2: descriptor completed
+	 * bit 3: chain completed
+	 * bit 4: busy
+	 * remainder reserved
+	 */
+	u32	status;
+	u32	pad1[3];
+
+	/* bit 0: interrupt on error
+	 * bit 1: interrupt on eop
+	 * bit 2: interrupt after every descriptor
+	 * bit 3: interrupt after last descrip in a chain
+	 * bit 4: global interrupt enable
+	 * bit 5: starts descriptor processing
+	 * bit 6: stop core on dma error
+	 * bit 7: interrupt on max descriptors
+	 * bits 8-15: max descriptors to generate interrupt
+	 * bit 16: Software reset
+	 * bit 17: clears owned by hardware if 0, does not clear otherwise
+	 * bit 18: enables descriptor polling mode
+	 * bit 19-26: clocks before polling again
+	 * bit 27-30: reserved
+	 * bit 31: clear interrupt
+	 */
+	u32	control;
+	u32	pad2[3];
+	u32	next_descrip;
+	u32	pad3[3];
+};
+
+
+#define SGDMA_STSREG_ERR	BIT(0) /* Error */
+#define SGDMA_STSREG_EOP	BIT(1) /* EOP */
+#define SGDMA_STSREG_DESCRIP	BIT(2) /* Descriptor completed */
+#define SGDMA_STSREG_CHAIN	BIT(3) /* Chain completed */
+#define SGDMA_STSREG_BUSY	BIT(4) /* Controller busy */
+
+#define SGDMA_CTRLREG_IOE	BIT(0) /* Interrupt on error */
+#define SGDMA_CTRLREG_IOEOP	BIT(1) /* Interrupt on EOP */
+#define SGDMA_CTRLREG_IDESCRIP	BIT(2) /* Interrupt after every descriptor */
+#define SGDMA_CTRLREG_ILASTD	BIT(3) /* Interrupt after last descriptor */
+#define SGDMA_CTRLREG_INTEN	BIT(4) /* Global Interrupt enable */
+#define SGDMA_CTRLREG_START	BIT(5) /* starts descriptor processing */
+#define SGDMA_CTRLREG_STOPERR	BIT(6) /* stop on dma error */
+#define SGDMA_CTRLREG_INTMAX	BIT(7) /* Interrupt on max descriptors */
+#define SGDMA_CTRLREG_RESET	BIT(16)/* Software reset */
+#define SGDMA_CTRLREG_COBHW	BIT(17)/* Clears owned by hardware */
+#define SGDMA_CTRLREG_POLL	BIT(18)/* enables descriptor polling mode */
+#define SGDMA_CTRLREG_CLRINT	BIT(31)/* Clears interrupt */
+
+#endif /* __ALTERA_SGDMAHW_H__ */
-- 
1.7.9.5

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

* [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (6 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 7/9] Altera TSE: Add Altera Ethernet Driver SGDMA file components Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-11  0:38   ` Stephen Hemminger
  2014-03-11  0:40   ` Stephen Hemminger
  2014-03-10 23:14 ` [PATCH net-next v2 9/9] Altera TSE: Add main and header file " Vince Bridgers
  8 siblings, 2 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds miscellaneous files for the Altera Ethernet Driver,
including ethtool support.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Break up driver files for initial submission by logical function.
    - Change bus type in ethtool from "AVALON" to "platform"
---
 drivers/net/ethernet/altera/altera_tse_ethtool.c |  226 ++++++++++++++++++++++
 drivers/net/ethernet/altera/altera_utils.c       |   44 +++++
 drivers/net/ethernet/altera/altera_utils.h       |   27 +++
 3 files changed, 297 insertions(+)
 create mode 100644 drivers/net/ethernet/altera/altera_tse_ethtool.c
 create mode 100644 drivers/net/ethernet/altera/altera_utils.c
 create mode 100644 drivers/net/ethernet/altera/altera_utils.h

diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c
new file mode 100644
index 0000000..02821b6
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c
@@ -0,0 +1,226 @@
+/* Ethtool support for Altera Triple-Speed Ethernet MAC driver
+ * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
+ *
+ * Contributors:
+ *   Dalon Westergreen
+ *   Thomas Chou
+ *   Ian Abbott
+ *   Yuriy Kozlov
+ *   Tobias Klauser
+ *   Andriy Smolskyy
+ *   Roman Bulgakov
+ *   Dmytro Mytarchuk
+ *
+ * Original driver contributed by SLS.
+ * Major updates contributed by GlobalLogic
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+
+#include "altera_tse.h"
+
+#define TSE_STATS_LEN 31
+
+static char stat_gstrings[][ETH_GSTRING_LEN] = {
+	"aFramesTransmittedOK",
+	"aFramesReceivedOK",
+	"aFramesCheckSequenceErrors",
+	"aAlignmentErrors",
+	"aOctetsTransmittedOK",
+	"aOctetsReceivedOK",
+	"aTxPAUSEMACCtrlFrames",
+	"aRxPAUSEMACCtrlFrames",
+	"ifInErrors",
+	"ifOutErrors",
+	"ifInUcastPkts",
+	"ifInMulticastPkts",
+	"ifInBroadcastPkts",
+	"ifOutDiscards",
+	"ifOutUcastPkts",
+	"ifOutMulticastPkts",
+	"ifOutBroadcastPkts",
+	"etherStatsDropEvents",
+	"etherStatsOctets",
+	"etherStatsPkts",
+	"etherStatsUndersizePkts",
+	"etherStatsOversizePkts",
+	"etherStatsPkts64Octets",
+	"etherStatsPkts65to127Octets",
+	"etherStatsPkts128to255Octets",
+	"etherStatsPkts256to511Octets",
+	"etherStatsPkts512to1023Octets",
+	"etherStatsPkts1024to1518Octets",
+	"etherStatsPkts1519toXOctets",
+	"etherStatsJabbers",
+	"etherStatsFragments",
+};
+
+static void tse_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	u32 rev = ioread32(&priv->mac_dev->megacore_revision);
+
+	strcpy(info->driver, "Altera TSE MAC IP Driver");
+	strcpy(info->version, "v8.0");
+	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
+		 rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
+	sprintf(info->bus_info, "platform");
+}
+
+/* Fill in a buffer with the strings which correspond to the
+ * stats
+ */
+static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+	memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
+}
+
+static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
+			   u64 *buf)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct altera_tse_mac *mac = priv->mac_dev;
+	u64 ext;
+
+	buf[0] = (u64) ioread32(&mac->frames_transmitted_ok);
+	buf[1] = (u64) ioread32(&mac->frames_received_ok);
+	buf[2] = (u64) ioread32(&mac->frames_check_sequence_errors);
+	buf[3] = (u64) ioread32(&mac->alignment_errors);
+
+	/* Extended aOctetsTransmittedOK counter */
+	ext = (u64) ioread32(&mac->msb_octets_transmitted_ok) << 32;
+	ext |= (u64) ioread32(&mac->octets_transmitted_ok);
+	buf[4] = ext;
+
+	/* Extended aOctetsReceivedOK counter */
+	ext = (u64) ioread32(&mac->msb_octets_received_ok) << 32;
+	ext |= (u64) ioread32(&mac->octets_received_ok);
+	buf[5] = ext;
+
+	buf[6] = (u64) ioread32(&mac->tx_pause_mac_ctrl_frames);
+	buf[7] = (u64) ioread32(&mac->rx_pause_mac_ctrl_frames);
+	buf[8] = (u64) ioread32(&mac->if_in_errors);
+	buf[9] = (u64) ioread32(&mac->if_out_errors);
+	buf[10] = (u64) ioread32(&mac->if_in_ucast_pkts);
+	buf[11] = (u64) ioread32(&mac->if_in_multicast_pkts);
+	buf[12] = (u64) ioread32(&mac->if_in_broadcast_pkts);
+	buf[13] = (u64) ioread32(&mac->if_out_discards);
+	buf[14] = (u64) ioread32(&mac->if_out_ucast_pkts);
+	buf[15] = (u64) ioread32(&mac->if_out_multicast_pkts);
+	buf[16] = (u64) ioread32(&mac->if_out_broadcast_pkts);
+	buf[17] = (u64) ioread32(&mac->ether_stats_drop_events);
+
+	/* Extended etherStatsOctets counter */
+	ext = (u64) ioread32(&mac->msb_ether_stats_octets) << 32;
+	ext |= (u64) ioread32(&mac->ether_stats_octets);
+	buf[18] = ext;
+
+	buf[19] = (u64) ioread32(&mac->ether_stats_pkts);
+	buf[20] = (u64) ioread32(&mac->ether_stats_undersize_pkts);
+	buf[21] = (u64) ioread32(&mac->ether_stats_oversize_pkts);
+	buf[22] = (u64) ioread32(&mac->ether_stats_pkts_64_octets);
+	buf[23] = (u64) ioread32(&mac->ether_stats_pkts_65to127_octets);
+	buf[24] = (u64) ioread32(&mac->ether_stats_pkts_128to255_octets);
+	buf[25] = (u64) ioread32(&mac->ether_stats_pkts_256to511_octets);
+	buf[26] = (u64) ioread32(&mac->ether_stats_pkts_512to1023_octets);
+	buf[27] = (u64) ioread32(&mac->ether_stats_pkts_1024to1518_octets);
+	buf[28] = (u64) ioread32(&mac->ether_stats_pkts_1519tox_octets);
+	buf[29] = (u64) ioread32(&mac->ether_stats_jabbers);
+	buf[30] = (u64) ioread32(&mac->ether_stats_fragments);
+}
+
+static int tse_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return TSE_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static u32 tse_get_msglevel(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	return priv->msg_enable;
+}
+
+static void tse_set_msglevel(struct net_device *dev, uint32_t data)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	priv->msg_enable = data;
+}
+
+static int tse_reglen(struct net_device *dev)
+{
+	return sizeof(struct altera_tse_mac);
+}
+
+static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			 void *regbuf)
+{
+	int i;
+	struct altera_tse_private *priv = netdev_priv(dev);
+	u32 *tse_mac_regs = (u32 *)priv->mac_dev;
+	u32 *buf = (u32 *)regbuf;
+
+	for (i = 0; i < sizeof(struct altera_tse_mac) / sizeof(u32); i++)
+		buf[i] = ioread32(&tse_mac_regs[i]);
+}
+
+static int tse_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+
+	if (phydev == NULL)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static int tse_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+
+	if (phydev == NULL)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
+}
+
+static const struct ethtool_ops tse_ethtool_ops = {
+	.get_drvinfo = tse_get_drvinfo,
+	.get_regs_len = tse_reglen,
+	.get_regs = tse_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_settings = tse_get_settings,
+	.set_settings = tse_set_settings,
+	.get_strings = tse_gstrings,
+	.get_sset_count = tse_sset_count,
+	.get_ethtool_stats = tse_fill_stats,
+	.get_msglevel = tse_get_msglevel,
+	.set_msglevel = tse_set_msglevel,
+};
+
+void altera_tse_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &tse_ethtool_ops);
+}
diff --git a/drivers/net/ethernet/altera/altera_utils.c b/drivers/net/ethernet/altera/altera_utils.c
new file mode 100644
index 0000000..70fa13f
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_utils.c
@@ -0,0 +1,44 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "altera_tse.h"
+#include "altera_utils.h"
+
+void tse_set_bit(void __iomem *ioaddr, u32 bit_mask)
+{
+	u32 value = ioread32(ioaddr);
+	value |= bit_mask;
+	iowrite32(value, ioaddr);
+}
+
+void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask)
+{
+	u32 value = ioread32(ioaddr);
+	value &= ~bit_mask;
+	iowrite32(value, ioaddr);
+}
+
+int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask)
+{
+	u32 value = ioread32(ioaddr);
+	return (value & bit_mask) ? 1 : 0;
+}
+
+int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask)
+{
+	u32 value = ioread32(ioaddr);
+	return (value & bit_mask) ? 0 : 1;
+}
diff --git a/drivers/net/ethernet/altera/altera_utils.h b/drivers/net/ethernet/altera/altera_utils.h
new file mode 100644
index 0000000..ce1db36
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_utils.h
@@ -0,0 +1,27 @@
+/* Altera TSE SGDMA and MSGDMA Linux driver
+ * Copyright (C) 2014 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+
+#ifndef __ALTERA_UTILS_H__
+#define __ALTERA_UTILS_H__
+
+void tse_set_bit(void __iomem *ioaddr, u32 bit_mask);
+void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask);
+int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask);
+int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask);
+
+#endif /* __ALTERA_UTILS_H__*/
-- 
1.7.9.5


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

* [PATCH net-next v2 9/9] Altera TSE: Add main and header file for Altera Ethernet Driver
  2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
                   ` (7 preceding siblings ...)
  2014-03-10 23:14 ` [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver Vince Bridgers
@ 2014-03-10 23:14 ` Vince Bridgers
  2014-03-11  9:44   ` Mark Rutland
  8 siblings, 1 reply; 21+ messages in thread
From: Vince Bridgers @ 2014-03-10 23:14 UTC (permalink / raw)
  To: devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	vbridgers2013

This patch adds the main driver and header file for the Altera Triple
Speed Ethernet driver.

Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
---
V2: - Address all comments from initial RFC (thanks Florian!)
    - Moved asm/cacheflush.h to bottom of header includes
    - Remove barriers since DMA APIs ensure memory consistency
    - Add max-frame-size property
    - Use accessor function of_get_phy_mode instead of custom function
    - Remove custom function to access devicetree, use of APIs
    - Deprecate use of Altera devicetree properties where standard
      ones exist
    - Remove use of netif_carrier_off - not necessary where it was used
    - Move probing of phy to the probe routine instead of open
    - use ether_addr_copy instead of memcpy
---
 drivers/net/ethernet/altera/altera_tse.h      |  486 ++++++++
 drivers/net/ethernet/altera/altera_tse_main.c | 1546 +++++++++++++++++++++++++
 2 files changed, 2032 insertions(+)
 create mode 100644 drivers/net/ethernet/altera/altera_tse.h
 create mode 100644 drivers/net/ethernet/altera/altera_tse_main.c

diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h
new file mode 100644
index 0000000..f0e39b1
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_tse.h
@@ -0,0 +1,486 @@
+/* Altera Triple-Speed Ethernet MAC driver
+ * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
+ *
+ * Contributors:
+ *   Dalon Westergreen
+ *   Thomas Chou
+ *   Ian Abbott
+ *   Yuriy Kozlov
+ *   Tobias Klauser
+ *   Andriy Smolskyy
+ *   Roman Bulgakov
+ *   Dmytro Mytarchuk
+ *   Matthew Gerlach
+ *
+ * Original driver contributed by SLS.
+ * Major updates contributed by GlobalLogic
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ALTERA_TSE_H__
+#define __ALTERA_TSE_H__
+
+#define ALTERA_TSE_RESOURCE_NAME	"altera_tse"
+
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+
+#define ALTERA_TSE_SW_RESET_WATCHDOG_CNTR	10000
+#define ALTERA_TSE_MAC_FIFO_WIDTH		4	/* TX/RX FIFO width in
+							 * bytes
+							 */
+/* Rx FIFO default settings */
+#define ALTERA_TSE_RX_SECTION_EMPTY	16
+#define ALTERA_TSE_RX_SECTION_FULL	0
+#define ALTERA_TSE_RX_ALMOST_EMPTY	8
+#define ALTERA_TSE_RX_ALMOST_FULL	8
+
+/* Tx FIFO default settings */
+#define ALTERA_TSE_TX_SECTION_EMPTY	16
+#define ALTERA_TSE_TX_SECTION_FULL	0
+#define ALTERA_TSE_TX_ALMOST_EMPTY	8
+#define ALTERA_TSE_TX_ALMOST_FULL	3
+
+/* MAC function configuration default settings */
+#define ALTERA_TSE_TX_IPG_LENGTH	12
+
+#define GET_BIT_VALUE(v, bit)		(((v) >> (bit)) & 0x1)
+
+/* MAC Command_Config Register Bit Definitions
+ */
+#define MAC_CMDCFG_TX_ENA			BIT(0)
+#define MAC_CMDCFG_RX_ENA			BIT(1)
+#define MAC_CMDCFG_XON_GEN			BIT(2)
+#define MAC_CMDCFG_ETH_SPEED			BIT(3)
+#define MAC_CMDCFG_PROMIS_EN			BIT(4)
+#define MAC_CMDCFG_PAD_EN			BIT(5)
+#define MAC_CMDCFG_CRC_FWD			BIT(6)
+#define MAC_CMDCFG_PAUSE_FWD			BIT(7)
+#define MAC_CMDCFG_PAUSE_IGNORE			BIT(8)
+#define MAC_CMDCFG_TX_ADDR_INS			BIT(9)
+#define MAC_CMDCFG_HD_ENA			BIT(10)
+#define MAC_CMDCFG_EXCESS_COL			BIT(11)
+#define MAC_CMDCFG_LATE_COL			BIT(12)
+#define MAC_CMDCFG_SW_RESET			BIT(13)
+#define MAC_CMDCFG_MHASH_SEL			BIT(14)
+#define MAC_CMDCFG_LOOP_ENA			BIT(15)
+#define MAC_CMDCFG_TX_ADDR_SEL(v)		(((v) & 0x7) << 16)
+#define MAC_CMDCFG_MAGIC_ENA			BIT(19)
+#define MAC_CMDCFG_SLEEP			BIT(20)
+#define MAC_CMDCFG_WAKEUP			BIT(21)
+#define MAC_CMDCFG_XOFF_GEN			BIT(22)
+#define MAC_CMDCFG_CNTL_FRM_ENA			BIT(23)
+#define MAC_CMDCFG_NO_LGTH_CHECK		BIT(24)
+#define MAC_CMDCFG_ENA_10			BIT(25)
+#define MAC_CMDCFG_RX_ERR_DISC			BIT(26)
+#define MAC_CMDCFG_DISABLE_READ_TIMEOUT		BIT(27)
+#define MAC_CMDCFG_CNT_RESET			BIT(31)
+
+#define MAC_CMDCFG_TX_ENA_GET(v)		GET_BIT_VALUE(v, 0)
+#define MAC_CMDCFG_RX_ENA_GET(v)		GET_BIT_VALUE(v, 1)
+#define MAC_CMDCFG_XON_GEN_GET(v)		GET_BIT_VALUE(v, 2)
+#define MAC_CMDCFG_ETH_SPEED_GET(v)		GET_BIT_VALUE(v, 3)
+#define MAC_CMDCFG_PROMIS_EN_GET(v)		GET_BIT_VALUE(v, 4)
+#define MAC_CMDCFG_PAD_EN_GET(v)		GET_BIT_VALUE(v, 5)
+#define MAC_CMDCFG_CRC_FWD_GET(v)		GET_BIT_VALUE(v, 6)
+#define MAC_CMDCFG_PAUSE_FWD_GET(v)		GET_BIT_VALUE(v, 7)
+#define MAC_CMDCFG_PAUSE_IGNORE_GET(v)		GET_BIT_VALUE(v, 8)
+#define MAC_CMDCFG_TX_ADDR_INS_GET(v)		GET_BIT_VALUE(v, 9)
+#define MAC_CMDCFG_HD_ENA_GET(v)		GET_BIT_VALUE(v, 10)
+#define MAC_CMDCFG_EXCESS_COL_GET(v)		GET_BIT_VALUE(v, 11)
+#define MAC_CMDCFG_LATE_COL_GET(v)		GET_BIT_VALUE(v, 12)
+#define MAC_CMDCFG_SW_RESET_GET(v)		GET_BIT_VALUE(v, 13)
+#define MAC_CMDCFG_MHASH_SEL_GET(v)		GET_BIT_VALUE(v, 14)
+#define MAC_CMDCFG_LOOP_ENA_GET(v)		GET_BIT_VALUE(v, 15)
+#define MAC_CMDCFG_TX_ADDR_SEL_GET(v)		(((v) >> 16) & 0x7)
+#define MAC_CMDCFG_MAGIC_ENA_GET(v)		GET_BIT_VALUE(v, 19)
+#define MAC_CMDCFG_SLEEP_GET(v)			GET_BIT_VALUE(v, 20)
+#define MAC_CMDCFG_WAKEUP_GET(v)		GET_BIT_VALUE(v, 21)
+#define MAC_CMDCFG_XOFF_GEN_GET(v)		GET_BIT_VALUE(v, 22)
+#define MAC_CMDCFG_CNTL_FRM_ENA_GET(v)		GET_BIT_VALUE(v, 23)
+#define MAC_CMDCFG_NO_LGTH_CHECK_GET(v)		GET_BIT_VALUE(v, 24)
+#define MAC_CMDCFG_ENA_10_GET(v)		GET_BIT_VALUE(v, 25)
+#define MAC_CMDCFG_RX_ERR_DISC_GET(v)		GET_BIT_VALUE(v, 26)
+#define MAC_CMDCFG_DISABLE_READ_TIMEOUT_GET(v)	GET_BIT_VALUE(v, 27)
+#define MAC_CMDCFG_CNT_RESET_GET(v)		GET_BIT_VALUE(v, 31)
+
+/* MDIO registers within MAC register Space
+ */
+struct altera_tse_mdio {
+	unsigned int control;	/* PHY device operation control register */
+	unsigned int status;	/* PHY device operation status register */
+	unsigned int phy_id1;	/* Bits 31:16 of PHY identifier */
+	unsigned int phy_id2;	/* Bits 15:0 of PHY identifier */
+	unsigned int auto_negotiation_advertisement;	/* Auto-negotiation
+							 * advertisement
+							 * register
+							 */
+	unsigned int remote_partner_base_page_ability;
+
+	unsigned int reg6;
+	unsigned int reg7;
+	unsigned int reg8;
+	unsigned int reg9;
+	unsigned int rega;
+	unsigned int regb;
+	unsigned int regc;
+	unsigned int regd;
+	unsigned int rege;
+	unsigned int regf;
+	unsigned int reg10;
+	unsigned int reg11;
+	unsigned int reg12;
+	unsigned int reg13;
+	unsigned int reg14;
+	unsigned int reg15;
+	unsigned int reg16;
+	unsigned int reg17;
+	unsigned int reg18;
+	unsigned int reg19;
+	unsigned int reg1a;
+	unsigned int reg1b;
+	unsigned int reg1c;
+	unsigned int reg1d;
+	unsigned int reg1e;
+	unsigned int reg1f;
+};
+
+/* MAC register Space. Note that some of these registers may or may not be
+ * present depending upon options chosen by the user when the core was
+ * configured and built. Please consult the Altera Triple Speed Ethernet User
+ * Guide for details.
+ */
+struct altera_tse_mac {
+	/* Bits 15:0: MegaCore function revision (0x0800). Bit 31:16: Customer
+	 * specific revision
+	 */
+	unsigned int megacore_revision;
+	/* Provides a memory location for user applications to test the device
+	 * memory operation.
+	 */
+	unsigned int scratch_pad;
+	/* The host processor uses this register to control and configure the
+	 * MAC block
+	 */
+	unsigned int command_config;
+	/* 32-bit primary MAC address word 0 bits 0 to 31 of the primary
+	 * MAC address
+	 */
+	unsigned int mac_addr_0;
+	/* 32-bit primary MAC address word 1 bits 32 to 47 of the primary
+	 * MAC address
+	 */
+	unsigned int mac_addr_1;
+	/* 14-bit maximum frame length. The MAC receive logic */
+	unsigned int frm_length;
+	/* The pause quanta is used in each pause frame sent to a remote
+	 * Ethernet device, in increments of 512 Ethernet bit times
+	 */
+	unsigned int pause_quanta;
+	/* 12-bit receive FIFO section-empty threshold */
+	unsigned int rx_section_empty;
+	/* 12-bit receive FIFO section-full threshold */
+	unsigned int rx_section_full;
+	/* 12-bit transmit FIFO section-empty threshold */
+	unsigned int tx_section_empty;
+	/* 12-bit transmit FIFO section-full threshold */
+	unsigned int tx_section_full;
+	/* 12-bit receive FIFO almost-empty threshold */
+	unsigned int rx_almost_empty;
+	/* 12-bit receive FIFO almost-full threshold */
+	unsigned int rx_almost_full;
+	/* 12-bit transmit FIFO almost-empty threshold */
+	unsigned int tx_almost_empty;
+	/* 12-bit transmit FIFO almost-full threshold */
+	unsigned int tx_almost_full;
+	/* MDIO address of PHY Device 0. Bits 0 to 4 hold a 5-bit PHY address */
+	unsigned int mdio_phy0_addr;
+	/* MDIO address of PHY Device 1. Bits 0 to 4 hold a 5-bit PHY address */
+	unsigned int mdio_phy1_addr;
+
+	/* Bit[15:0]—16-bit holdoff quanta */
+	unsigned int holdoff_quant;
+
+	/* only if 100/1000 BaseX PCS, reserved otherwise */
+	unsigned int reserved1[5];
+
+	/* Minimum IPG between consecutive transmit frame in terms of bytes */
+	unsigned int tx_ipg_length;
+
+	/* IEEE 802.3 oEntity Managed Object Support */
+
+	/* The MAC addresses */
+	unsigned int mac_id_1;
+	unsigned int mac_id_2;
+
+	/* Number of frames transmitted without error including pause frames */
+	unsigned int frames_transmitted_ok;
+	/* Number of frames received without error including pause frames */
+	unsigned int frames_received_ok;
+	/* Number of frames received with a CRC error */
+	unsigned int frames_check_sequence_errors;
+	/* Frame received with an alignment error */
+	unsigned int alignment_errors;
+	/* Sum of payload and padding octets of frames transmitted without
+	 * error
+	 */
+	unsigned int octets_transmitted_ok;
+	/* Sum of payload and padding octets of frames received without error */
+	unsigned int octets_received_ok;
+
+	/* IEEE 802.3 oPausedEntity Managed Object Support */
+
+	/* Number of transmitted pause frames */
+	unsigned int tx_pause_mac_ctrl_frames;
+	/* Number of Received pause frames */
+	unsigned int rx_pause_mac_ctrl_frames;
+
+	/* IETF MIB (MIB-II) Object Support */
+
+	/* Number of frames received with error */
+	unsigned int if_in_errors;
+	/* Number of frames transmitted with error */
+	unsigned int if_out_errors;
+	/* Number of valid received unicast frames */
+	unsigned int if_in_ucast_pkts;
+	/* Number of valid received multicasts frames (without pause) */
+	unsigned int if_in_multicast_pkts;
+	/* Number of valid received broadcast frames */
+	unsigned int if_in_broadcast_pkts;
+	unsigned int if_out_discards;
+	/* The number of valid unicast frames transmitted */
+	unsigned int if_out_ucast_pkts;
+	/* The number of valid multicast frames transmitted,
+	 * excluding pause frames
+	 */
+	unsigned int if_out_multicast_pkts;
+	unsigned int if_out_broadcast_pkts;
+
+	/* IETF RMON MIB Object Support */
+
+	/* Counts the number of dropped packets due to internal errors
+	 * of the MAC client.
+	 */
+	unsigned int ether_stats_drop_events;
+	/* Total number of bytes received. Good and bad frames. */
+	unsigned int ether_stats_octets;
+	/* Total number of packets received. Counts good and bad packets. */
+	unsigned int ether_stats_pkts;
+	/* Number of packets received with less than 64 bytes. */
+	unsigned int ether_stats_undersize_pkts;
+	/* The number of frames received that are longer than the
+	 * value configured in the frm_length register
+	 */
+	unsigned int ether_stats_oversize_pkts;
+	/* Number of received packet with 64 bytes */
+	unsigned int ether_stats_pkts_64_octets;
+	/* Frames (good and bad) with 65 to 127 bytes */
+	unsigned int ether_stats_pkts_65to127_octets;
+	/* Frames (good and bad) with 128 to 255 bytes */
+	unsigned int ether_stats_pkts_128to255_octets;
+	/* Frames (good and bad) with 256 to 511 bytes */
+	unsigned int ether_stats_pkts_256to511_octets;
+	/* Frames (good and bad) with 512 to 1023 bytes */
+	unsigned int ether_stats_pkts_512to1023_octets;
+	/* Frames (good and bad) with 1024 to 1518 bytes */
+	unsigned int ether_stats_pkts_1024to1518_octets;
+
+	/* Any frame length from 1519 to the maximum length configured in the
+	 * frm_length register, if it is greater than 1518
+	 */
+	unsigned int ether_stats_pkts_1519tox_octets;
+	/* Too long frames with CRC error */
+	unsigned int ether_stats_jabbers;
+	/* Too short frames with CRC error */
+	unsigned int ether_stats_fragments;
+
+	unsigned int reserved2;
+
+	/* FIFO control register */
+	unsigned int tx_cmd_stat;
+	unsigned int rx_cmd_stat;
+
+	/* Extended Statistics Counters */
+	unsigned int msb_octets_transmitted_ok;
+	unsigned int msb_octets_received_ok;
+	unsigned int msb_ether_stats_octets;
+
+	unsigned int reserved3;
+
+	/* Multicast address resolution table, mapped in the controller address
+	 * space
+	 */
+	unsigned int hash_table[64];
+
+	/* Registers 0 to 31 within PHY device 0/1 connected to the MDIO PHY
+	 * management interface
+	 */
+	struct altera_tse_mdio mdio_phy0;
+	struct altera_tse_mdio mdio_phy1;
+
+	/* 4 Supplemental MAC Addresses */
+	unsigned int supp_mac_addr_0_0;
+	unsigned int supp_mac_addr_0_1;
+	unsigned int supp_mac_addr_1_0;
+	unsigned int supp_mac_addr_1_1;
+	unsigned int supp_mac_addr_2_0;
+	unsigned int supp_mac_addr_2_1;
+	unsigned int supp_mac_addr_3_0;
+	unsigned int supp_mac_addr_3_1;
+
+	unsigned int reserved4[8];
+
+	/* IEEE 1588v2 Feature */
+	unsigned int tx_period;
+	unsigned int tx_adjust_fns;
+	unsigned int tx_adjust_ns;
+	unsigned int rx_period;
+	unsigned int rx_adjust_fns;
+	unsigned int rx_adjust_ns;
+
+	unsigned int reserved5[42];
+};
+
+/* Transmit and Receive Command Registers Bit Definitions
+ */
+#define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC		BIT(17)
+#define ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16	BIT(18)
+#define ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16	BIT(25)
+
+/* Wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct tse_buffer {
+	struct list_head lh;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+	unsigned int len;
+	int mapped_as_page;
+};
+
+struct altera_tse_private;
+
+#define ALTERA_DTYPE_SGDMA 1
+#define ALTERA_DTYPE_MSGDMA 2
+
+/* standard DMA interface for SGDMA and MSGDMA */
+struct altera_dmaops {
+	int altera_dtype;
+	int dmamask;
+	void (*reset_dma)(struct altera_tse_private *);
+	void (*enable_txirq)(struct altera_tse_private *);
+	void (*enable_rxirq)(struct altera_tse_private *);
+	void (*disable_txirq)(struct altera_tse_private *);
+	void (*disable_rxirq)(struct altera_tse_private *);
+	void (*clear_txirq)(struct altera_tse_private *);
+	void (*clear_rxirq)(struct altera_tse_private *);
+	int (*tx_buffer)(struct altera_tse_private *, struct tse_buffer *);
+	u32 (*tx_completions)(struct altera_tse_private *);
+	int (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *);
+	u32 (*get_rx_status)(struct altera_tse_private *);
+	int (*init_dma)(struct altera_tse_private *);
+	void (*uninit_dma)(struct altera_tse_private *);
+};
+
+/* This structure is private to each device.
+ */
+struct altera_tse_private {
+	struct net_device *dev;
+	struct device *device;
+	struct napi_struct napi;
+
+	/* MAC address space */
+	struct altera_tse_mac *mac_dev;
+
+	/* TSE Revision */
+	u32	revision;
+
+	/* mSGDMA Rx Dispatcher address space */
+	void __iomem *rx_dma_csr;
+	void __iomem *rx_dma_desc;
+	void __iomem *rx_dma_resp;
+
+	/* mSGDMA Tx Dispatcher address space */
+	void __iomem *tx_dma_csr;
+	void __iomem *tx_dma_desc;
+
+	/* Rx buffers queue */
+	struct tse_buffer *rx_ring;
+	unsigned int rx_cons;
+	unsigned int rx_prod;
+	unsigned int rx_ring_size;
+	unsigned int rx_dma_buf_sz;
+
+	/* Tx ring buffer */
+	struct tse_buffer *tx_ring;
+	unsigned int tx_prod;
+	unsigned int tx_cons;
+	unsigned int tx_ring_size;
+
+	/* Interrupts */
+	unsigned int tx_irq;
+	unsigned int rx_irq;
+
+	/* RX/TX MAC FIFO configs */
+	unsigned int tx_fifo_depth;
+	unsigned int rx_fifo_depth;
+	unsigned int max_mtu;
+
+	/* Hash filter settings */
+	unsigned int hash_filter;
+	unsigned int added_unicast;
+
+	/* Descriptor memory info for managing SGDMA */
+	unsigned int txdescmem;
+	unsigned int rxdescmem;
+	dma_addr_t rxdescmem_busaddr;
+	dma_addr_t txdescmem_busaddr;
+	unsigned int txctrlreg;
+	unsigned int rxctrlreg;
+	dma_addr_t rxdescphys;
+	dma_addr_t txdescphys;
+
+	struct list_head txlisthd;
+	struct list_head rxlisthd;
+
+	/* MAC command_config register protection */
+	spinlock_t mac_cfg_lock;
+	/* Tx path protection */
+	spinlock_t tx_lock;
+	/* Rx DMA & interrupt control protection */
+	spinlock_t rxdma_irq_lock;
+
+	/* PHY */
+	int phy_addr;		/* PHY's MDIO address, -1 for autodetection */
+	phy_interface_t phy_iface;
+	struct mii_bus *mdio;
+	struct phy_device *phydev;
+	int oldspeed;
+	int oldduplex;
+	int oldlink;
+
+	/* ethtool msglvl option */
+	u32 msg_enable;
+
+	struct altera_dmaops *dmaops;
+};
+
+/* Function prototypes
+ */
+void altera_tse_set_ethtool_ops(struct net_device *);
+
+#endif /* __ALTERA_TSE_H__ */
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
new file mode 100644
index 0000000..51dcc44
--- /dev/null
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -0,0 +1,1546 @@
+/* Altera Triple-Speed Ethernet MAC driver
+ * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
+ *
+ * Contributors:
+ *   Dalon Westergreen
+ *   Thomas Chou
+ *   Ian Abbott
+ *   Yuriy Kozlov
+ *   Tobias Klauser
+ *   Andriy Smolskyy
+ *   Roman Bulgakov
+ *   Dmytro Mytarchuk
+ *   Matthew Gerlach
+ *
+ * Original driver contributed by SLS.
+ * Major updates contributed by GlobalLogic
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_device.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <asm/cacheflush.h>
+
+#include "altera_utils.h"
+#include "altera_tse.h"
+#include "altera_sgdma.h"
+#include "altera_msgdma.h"
+
+static atomic_t instance_count = ATOMIC_INIT(~0);
+/* Module parameters */
+static int debug = -1;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
+
+static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
+					NETIF_MSG_LINK | NETIF_MSG_IFUP |
+					NETIF_MSG_IFDOWN);
+
+#define RX_DESCRIPTORS 64
+static int dma_rx_num = RX_DESCRIPTORS;
+module_param(dma_rx_num, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dma_rx_num, "Number of descriptors in the RX list");
+
+#define TX_DESCRIPTORS 64
+static int dma_tx_num = TX_DESCRIPTORS;
+module_param(dma_tx_num, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dma_tx_num, "Number of descriptors in the TX list");
+
+
+#define POLL_PHY (-1)
+
+/* Make sure DMA buffer size is larger than the max frame size
+ * plus some alignment offset and a VLAN header. If the max frame size is
+ * 1518, a VLAN header would be additional 4 bytes and additional
+ * headroom for alignment is 2 bytes, 2048 is just fine.
+ */
+#define ALTERA_RXDMABUFFER_SIZE	2048
+
+/* Allow network stack to resume queueing packets after we've
+ * finished transmitting at least 1/4 of the packets in the queue.
+ */
+#define TSE_TX_THRESH(x)	(x->tx_ring_size / 4)
+
+#define TXQUEUESTOP_THRESHHOLD	2
+
+static struct of_device_id altera_tse_ids[];
+
+static inline u32 tse_tx_avail(struct altera_tse_private *priv)
+{
+	return priv->tx_cons + priv->tx_ring_size - priv->tx_prod - 1;
+}
+
+/* MDIO specific functions
+ */
+static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv;
+	unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0;
+	u32 data;
+
+	/* set MDIO address */
+	iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr);
+
+	/* get the data */
+	data = ioread32(&mdio_regs[regnum]) & 0xffff;
+	return data;
+}
+
+static int altera_tse_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+				 u16 value)
+{
+	struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv;
+	unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0;
+
+	/* set MDIO address */
+	iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr);
+
+	/* write the data */
+	iowrite32((u32) value, &mdio_regs[regnum]);
+	return 0;
+}
+
+static int altera_tse_mdio_create(struct net_device *dev, unsigned int id)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	int ret;
+	int i;
+	struct device_node *mdio_node;
+	struct mii_bus *mdio;
+
+	mdio_node = of_find_compatible_node(priv->device->of_node, NULL,
+		"altr,tse-mdio");
+
+	if (mdio_node) {
+		dev_dbg(priv->device, "FOUND MDIO subnode\n");
+	} else {
+		dev_dbg(priv->device, "NO MDIO subnode\n");
+		return 0;
+	}
+
+	mdio = mdiobus_alloc();
+	if (mdio == NULL) {
+		dev_err(priv->device, "Error allocating MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	mdio->name = ALTERA_TSE_RESOURCE_NAME;
+	mdio->read = &altera_tse_mdio_read;
+	mdio->write = &altera_tse_mdio_write;
+	snprintf(mdio->id, MII_BUS_ID_SIZE, "%s-%u", mdio->name, id);
+
+	mdio->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
+	if (mdio->irq == NULL) {
+		dev_err(priv->device, "%s: Cannot allocate memory\n", __func__);
+		ret = -ENOMEM;
+		goto out_free_mdio;
+	}
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		mdio->irq[i] = PHY_POLL;
+
+	mdio->priv = priv->mac_dev;
+	mdio->parent = priv->device;
+
+	ret = of_mdiobus_register(mdio, mdio_node);
+	if (ret != 0) {
+		dev_err(priv->device, "Cannot register MDIO bus %s\n",
+			mdio->id);
+		goto out_free_mdio_irq;
+	}
+
+	if (netif_msg_drv(priv))
+		dev_info(priv->device, "MDIO bus %s: created\n", mdio->id);
+
+	priv->mdio = mdio;
+	return 0;
+out_free_mdio_irq:
+	kfree(mdio->irq);
+out_free_mdio:
+	mdiobus_free(mdio);
+	mdio = NULL;
+	return ret;
+}
+
+static void altera_tse_mdio_destroy(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+
+	if (priv->mdio == NULL)
+		return;
+
+	if (netif_msg_drv(priv))
+		dev_info(priv->device, "MDIO bus %s: removed\n",
+			 priv->mdio->id);
+
+	mdiobus_unregister(priv->mdio);
+	kfree(priv->mdio->irq);
+	mdiobus_free(priv->mdio);
+	priv->mdio = NULL;
+}
+
+static int tse_init_rx_buffer(struct altera_tse_private *priv,
+			      struct tse_buffer *rxbuffer, int len)
+{
+	rxbuffer->skb = netdev_alloc_skb_ip_align(priv->dev, len);
+	if (!rxbuffer->skb) {
+		dev_err(priv->device, "%s: Rx init fails; skb is NULL\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	rxbuffer->dma_addr = dma_map_single(priv->device, rxbuffer->skb->data,
+						len,
+						DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(priv->device, rxbuffer->dma_addr)) {
+		dev_err(priv->device, "%s: DMA mapping error\n", __func__);
+		dev_kfree_skb_any(rxbuffer->skb);
+		return -EINVAL;
+	}
+	rxbuffer->len = len;
+	return 0;
+}
+
+static void tse_free_rx_buffer(struct altera_tse_private *priv,
+			       struct tse_buffer *rxbuffer)
+{
+	struct sk_buff *skb = rxbuffer->skb;
+	dma_addr_t dma_addr = rxbuffer->dma_addr;
+
+	if (skb != NULL) {
+		if (dma_addr)
+			dma_unmap_single(priv->device, dma_addr,
+					 rxbuffer->len,
+					 DMA_FROM_DEVICE);
+		dev_kfree_skb_any(skb);
+		rxbuffer->skb = NULL;
+		rxbuffer->dma_addr = 0;
+	}
+}
+
+/* Unmap and free Tx buffer resources
+ */
+static void tse_free_tx_buffer(struct altera_tse_private *priv,
+			       struct tse_buffer *buffer)
+{
+	if (buffer->dma_addr) {
+		if (buffer->mapped_as_page)
+			dma_unmap_page(priv->device, buffer->dma_addr,
+				       buffer->len, DMA_TO_DEVICE);
+		else
+			dma_unmap_single(priv->device, buffer->dma_addr,
+					 buffer->len, DMA_TO_DEVICE);
+		buffer->dma_addr = 0;
+	}
+	if (buffer->skb) {
+		dev_kfree_skb_any(buffer->skb);
+		buffer->skb = NULL;
+	}
+}
+
+static int alloc_init_skbufs(struct altera_tse_private *priv)
+{
+	unsigned int rx_descs = priv->rx_ring_size;
+	unsigned int tx_descs = priv->tx_ring_size;
+	int ret = -ENOMEM;
+	int i;
+
+	/* Create Rx ring buffer */
+	priv->rx_ring = kcalloc(rx_descs, sizeof(struct tse_buffer),
+				GFP_KERNEL);
+	if (!priv->rx_ring)
+		goto err_rx_ring;
+
+	/* Create Tx ring buffer */
+	priv->tx_ring = kcalloc(tx_descs, sizeof(struct tse_buffer),
+				GFP_KERNEL);
+	if (!priv->tx_ring)
+		goto err_tx_ring;
+
+	priv->tx_cons = 0;
+	priv->tx_prod = 0;
+
+	/* Init Rx ring */
+	for (i = 0; i < rx_descs; i++) {
+		ret = tse_init_rx_buffer(priv, &priv->rx_ring[i],
+					 priv->rx_dma_buf_sz);
+		if (ret)
+			goto err_init_rx_buffers;
+	}
+
+	priv->rx_cons = 0;
+	priv->rx_prod = 0;
+
+	return 0;
+err_init_rx_buffers:
+	while (--i >= 0)
+		tse_free_rx_buffer(priv, &priv->rx_ring[i]);
+	kfree(priv->tx_ring);
+err_tx_ring:
+	kfree(priv->rx_ring);
+err_rx_ring:
+	return ret;
+}
+
+static void free_skbufs(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	unsigned int rx_descs = priv->rx_ring_size;
+	unsigned int tx_descs = priv->tx_ring_size;
+	int i;
+
+	/* Release the DMA TX/RX socket buffers */
+	for (i = 0; i < rx_descs; i++)
+		tse_free_rx_buffer(priv, &priv->rx_ring[i]);
+	for (i = 0; i < tx_descs; i++)
+		tse_free_tx_buffer(priv, &priv->tx_ring[i]);
+
+
+	kfree(priv->tx_ring);
+}
+
+/* Reallocate the skb for the reception process
+ */
+static inline void tse_rx_refill(struct altera_tse_private *priv)
+{
+	unsigned int rxsize = priv->rx_ring_size;
+	unsigned int entry;
+	int ret;
+
+	for (; priv->rx_cons - priv->rx_prod > 0;
+			priv->rx_prod++) {
+		entry = priv->rx_prod % rxsize;
+		if (likely(priv->rx_ring[entry].skb == NULL)) {
+			ret = tse_init_rx_buffer(priv, &priv->rx_ring[entry],
+				priv->rx_dma_buf_sz);
+			if (unlikely(ret != 0)) {
+				dev_err(priv->device,
+					"%s: Cannot allocate skb\n", __func__);
+				break;
+			}
+			priv->dmaops->add_rx_desc(priv, &priv->rx_ring[entry]);
+			if (netif_msg_rx_status(priv))
+				dev_dbg(priv->device, "\trefill entry #%d\n",
+					entry);
+		}
+	}
+}
+
+/* Pull out the VLAN tag and fix up the packet
+ */
+static inline void tse_rx_vlan(struct net_device *dev, struct sk_buff *skb)
+{
+	struct ethhdr *eth_hdr;
+	u16 vid;
+	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	    !__vlan_get_tag(skb, &vid)) {
+		eth_hdr = (struct ethhdr *)skb->data;
+		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+		skb_pull(skb, VLAN_HLEN);
+		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
+	}
+}
+
+/* Receive a packet: retrieve and pass over to upper levels
+ */
+static int tse_rx(struct altera_tse_private *priv, int limit)
+{
+	unsigned int count = 0;
+	unsigned int next_entry;
+	struct sk_buff *skb;
+	unsigned int entry = priv->rx_cons % priv->rx_ring_size;
+	u32 rxstatus;
+	u16 pktlength;
+	u16 pktstatus;
+
+	while ((rxstatus = priv->dmaops->get_rx_status(priv)) != 0) {
+		pktstatus = rxstatus >> 16;
+		pktlength = rxstatus & 0xffff;
+
+		if ((pktstatus & 0xFF) || (pktlength == 0))
+			netdev_err(priv->dev,
+				   "RCV pktstatus %08X pktlength %08X\n",
+				   pktstatus, pktlength);
+
+		count++;
+		next_entry = (++priv->rx_cons) % priv->rx_ring_size;
+
+		skb = priv->rx_ring[entry].skb;
+		if (unlikely(!skb)) {
+			dev_err(priv->device,
+				"%s: Inconsistent Rx descriptor chain\n",
+				__func__);
+			priv->dev->stats.rx_dropped++;
+			break;
+		}
+		priv->rx_ring[entry].skb = NULL;
+
+		skb_put(skb, pktlength);
+
+		/* make cache consistent with receive packet buffer */
+		dma_sync_single_for_cpu(priv->device,
+					priv->rx_ring[entry].dma_addr,
+					priv->rx_ring[entry].len,
+					DMA_FROM_DEVICE);
+
+		dma_unmap_single(priv->device, priv->rx_ring[entry].dma_addr,
+				 priv->rx_ring[entry].len, DMA_FROM_DEVICE);
+
+		if (netif_msg_pktdata(priv)) {
+			dev_info(priv->device, "frame received %d bytes\n",
+				 pktlength);
+			print_hex_dump(KERN_ERR, "data: ", DUMP_PREFIX_OFFSET,
+				       16, 1, skb->data, pktlength, true);
+		}
+
+		tse_rx_vlan(priv->dev, skb);
+
+		skb->protocol = eth_type_trans(skb, priv->dev);
+		skb_checksum_none_assert(skb);
+
+		napi_gro_receive(&priv->napi, skb);
+
+		priv->dev->stats.rx_packets++;
+		priv->dev->stats.rx_bytes += pktlength;
+
+		entry = next_entry;
+	}
+
+	tse_rx_refill(priv);
+	return count;
+}
+
+/* Reclaim resources after transmission completes
+ */
+static int tse_tx_complete(struct altera_tse_private *priv)
+{
+	unsigned int txsize = priv->tx_ring_size;
+	u32 ready;
+	unsigned int entry;
+	struct tse_buffer *tx_buff;
+	int txcomplete = 0;
+
+	spin_lock(&priv->tx_lock);
+
+	ready = priv->dmaops->tx_completions(priv);
+
+	/* Free sent buffers */
+	while (ready && (priv->tx_cons != priv->tx_prod)) {
+		entry = priv->tx_cons % txsize;
+		tx_buff = &priv->tx_ring[entry];
+
+		if (netif_msg_tx_done(priv))
+			dev_dbg(priv->device, "%s: curr %d, dirty %d\n",
+				__func__, priv->tx_prod, priv->tx_cons);
+
+		if (likely(tx_buff->skb))
+			priv->dev->stats.tx_packets++;
+
+		tse_free_tx_buffer(priv, tx_buff);
+		priv->tx_cons++;
+
+		txcomplete++;
+		ready--;
+	}
+
+	if (unlikely(netif_queue_stopped(priv->dev) &&
+		     tse_tx_avail(priv) > TSE_TX_THRESH(priv))) {
+		netif_tx_lock(priv->dev);
+		if (netif_queue_stopped(priv->dev) &&
+		    tse_tx_avail(priv) > TSE_TX_THRESH(priv)) {
+			if (netif_msg_tx_done(priv))
+				dev_dbg(priv->device, "%s: restart transmit\n",
+					__func__);
+			netif_wake_queue(priv->dev);
+		}
+		netif_tx_unlock(priv->dev);
+	}
+
+	spin_unlock(&priv->tx_lock);
+	return txcomplete;
+}
+
+/* NAPI polling function
+ */
+static int tse_poll(struct napi_struct *napi, int budget)
+{
+	struct altera_tse_private *priv =
+			container_of(napi, struct altera_tse_private, napi);
+	int rxcomplete = 0;
+	int txcomplete = 0;
+	unsigned long int flags;
+
+	txcomplete = tse_tx_complete(priv);
+
+	rxcomplete = tse_rx(priv, budget);
+
+	if (rxcomplete >= budget || txcomplete > 0)
+		return rxcomplete;
+
+	napi_gro_flush(napi, false);
+	__napi_complete(napi);
+
+	dev_dbg(priv->device,
+		"NAPI Complete, did %d packets with budget %d\n",
+		txcomplete+rxcomplete, budget);
+
+	spin_lock_irqsave(&priv->rxdma_irq_lock, flags);
+	priv->dmaops->enable_rxirq(priv);
+	priv->dmaops->enable_txirq(priv);
+	spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags);
+	return rxcomplete + txcomplete;
+}
+
+/* DMA TX & RX FIFO interrupt routing
+ */
+static irqreturn_t altera_isr(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct altera_tse_private *priv;
+	unsigned long int flags;
+
+
+	if (unlikely(!dev)) {
+		pr_err("%s: invalid dev pointer\n", __func__);
+		return IRQ_NONE;
+	}
+	priv = netdev_priv(dev);
+
+	/* turn off desc irqs and enable napi rx */
+	spin_lock_irqsave(&priv->rxdma_irq_lock, flags);
+
+	if (likely(napi_schedule_prep(&priv->napi))) {
+		priv->dmaops->disable_rxirq(priv);
+		priv->dmaops->disable_txirq(priv);
+		__napi_schedule(&priv->napi);
+	}
+
+	/* reset IRQs */
+	priv->dmaops->clear_rxirq(priv);
+	priv->dmaops->clear_txirq(priv);
+
+	spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/* Transmit a packet (called by the kernel). Dispatches
+ * either the SGDMA method for transmitting or the
+ * MSGDMA method, assumes no scatter/gather support,
+ * implying an assumption that there's only one
+ * physically contiguous fragment starting at
+ * skb->data, for length of skb_headlen(skb).
+ */
+static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	unsigned int txsize = priv->tx_ring_size;
+	unsigned int entry;
+	struct tse_buffer *buffer = NULL;
+	int nfrags = skb_shinfo(skb)->nr_frags;
+	unsigned int nopaged_len = skb_headlen(skb);
+	enum netdev_tx ret = NETDEV_TX_OK;
+	dma_addr_t dma_addr;
+	int txcomplete = 0;
+
+	spin_lock_bh(&priv->tx_lock);
+
+	if (unlikely(tse_tx_avail(priv) < nfrags + 1)) {
+		if (!netif_queue_stopped(dev)) {
+			netif_stop_queue(dev);
+			/* This is a hard error, log it. */
+			dev_err(priv->device,
+				"%s: Tx list full when queue awake\n",
+				__func__);
+		}
+		ret = NETDEV_TX_BUSY;
+		goto out;
+	}
+
+	/* Map the first skb fragment */
+	entry = priv->tx_prod % txsize;
+	buffer = &priv->tx_ring[entry];
+
+	dma_addr = dma_map_single(priv->device, skb->data, nopaged_len,
+				  DMA_TO_DEVICE);
+	if (dma_mapping_error(priv->device, dma_addr)) {
+		dev_err(priv->device, "%s: DMA mapping error\n", __func__);
+		ret = NETDEV_TX_OK;
+		goto out;
+	}
+
+	buffer->skb = skb;
+	buffer->dma_addr = dma_addr;
+	buffer->len = nopaged_len;
+
+	/* Push data out of the cache hierarchy into main memory */
+	dma_sync_single_for_device(priv->device, buffer->dma_addr,
+				   buffer->len, DMA_TO_DEVICE);
+
+	txcomplete = priv->dmaops->tx_buffer(priv, buffer);
+
+	priv->tx_prod++;
+	dev->stats.tx_bytes += skb->len;
+
+	if (unlikely(tse_tx_avail(priv) <= TXQUEUESTOP_THRESHHOLD)) {
+		if (netif_msg_hw(priv))
+			dev_dbg(priv->device, "%s: stop transmitted packets\n",
+				__func__);
+		netif_stop_queue(dev);
+	}
+
+out:
+	spin_unlock_bh(&priv->tx_lock);
+
+	return ret;
+}
+
+/* Called every time the controller might need to be made
+ * aware of new link state.  The PHY code conveys this
+ * information through variables in the phydev structure, and this
+ * function converts those variables into the appropriate
+ * register values, and can bring down the device if needed.
+ */
+static void altera_tse_adjust_link(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+	int new_state = 0;
+
+	/* only change config if there is a link */
+	spin_lock(&priv->mac_cfg_lock);
+	if (phydev->link) {
+		/* Read old config */
+		u32 cfg_reg = ioread32(&priv->mac_dev->command_config);
+
+		/* Check duplex */
+		if (phydev->duplex != priv->oldduplex) {
+			new_state = 1;
+			if (!(phydev->duplex))
+				cfg_reg |= MAC_CMDCFG_HD_ENA;
+			else
+				cfg_reg &= ~MAC_CMDCFG_HD_ENA;
+
+			dev_dbg(priv->device, "%s: Link duplex = 0x%x\n",
+				dev->name, phydev->duplex);
+
+			priv->oldduplex = phydev->duplex;
+		}
+
+		/* Check speed */
+		if (phydev->speed != priv->oldspeed) {
+			new_state = 1;
+			switch (phydev->speed) {
+			case 1000:
+				cfg_reg |= MAC_CMDCFG_ETH_SPEED;
+				cfg_reg &= ~MAC_CMDCFG_ENA_10;
+				break;
+			case 100:
+				cfg_reg &= ~MAC_CMDCFG_ETH_SPEED;
+				cfg_reg &= ~MAC_CMDCFG_ENA_10;
+				break;
+			case 10:
+				cfg_reg &= ~MAC_CMDCFG_ETH_SPEED;
+				cfg_reg |= MAC_CMDCFG_ENA_10;
+				break;
+			default:
+				if (netif_msg_link(priv))
+					netdev_warn(dev, "Speed (%d) is not 10/100/1000!\n",
+						    phydev->speed);
+				break;
+			}
+			priv->oldspeed = phydev->speed;
+		}
+		iowrite32(cfg_reg, &priv->mac_dev->command_config);
+
+		if (!priv->oldlink) {
+			new_state = 1;
+			priv->oldlink = 1;
+		}
+	} else if (priv->oldlink) {
+		new_state = 1;
+		priv->oldlink = 0;
+		priv->oldspeed = 0;
+		priv->oldduplex = -1;
+	}
+
+	if (new_state && netif_msg_link(priv))
+		phy_print_status(phydev);
+
+	spin_unlock(&priv->mac_cfg_lock);
+}
+static struct phy_device *connect_local_phy(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
+	int ret;
+
+	if (priv->phy_addr != POLL_PHY) {
+		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
+			 priv->mdio->id, priv->phy_addr);
+
+		dev_dbg(priv->device, "trying to attach to %s\n", phy_id_fmt);
+
+		phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
+				     priv->phy_iface);
+		if (IS_ERR(phydev))
+			netdev_err(dev, "Could not attach to PHY\n");
+
+	} else {
+		phydev = phy_find_first(priv->mdio);
+		if (phydev == NULL) {
+			netdev_err(dev, "No PHY found\n");
+			return phydev;
+		}
+
+		ret = phy_connect_direct(dev, phydev, &altera_tse_adjust_link,
+				priv->phy_iface);
+		if (ret != 0) {
+			netdev_err(dev, "Could not attach to PHY\n");
+			phydev = NULL;
+		}
+	}
+	return phydev;
+}
+
+/* Initialize driver's PHY state, and attach to the PHY
+ */
+static int init_phy(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct phy_device *phydev;
+	struct device_node *phynode;
+
+	priv->oldlink = 0;
+	priv->oldspeed = 0;
+	priv->oldduplex = -1;
+
+	phynode = of_parse_phandle(priv->device->of_node, "phy-handle", 0);
+
+	if (!phynode) {
+		netdev_dbg(dev, "no phy-handle found\n");
+		if (!priv->mdio) {
+			netdev_err(dev,
+				   "No phy-handle nor local mdio specified\n");
+			return -ENODEV;
+		}
+		phydev = connect_local_phy(dev);
+	} else {
+		netdev_dbg(dev, "phy-handle found\n");
+		phydev = of_phy_connect(dev, phynode,
+			&altera_tse_adjust_link, 0, priv->phy_iface);
+	}
+
+	/* Stop Advertising 1000BASE Capability if interface is not GMII
+	 * Note: Checkpatch throws CHECKs for the camel case defines below,
+	 * it's ok to ignore.
+	 */
+	if ((priv->phy_iface == PHY_INTERFACE_MODE_MII) ||
+	    (priv->phy_iface == PHY_INTERFACE_MODE_RMII))
+		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
+					 SUPPORTED_1000baseT_Full);
+
+	/* Broken HW is sometimes missing the pull-up resistor on the
+	 * MDIO line, which results in reads to non-existent devices returning
+	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
+	 * device as well.
+	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
+	 */
+	if (phydev->phy_id == 0) {
+		netdev_err(dev, "Bad PHY UID 0x%08x\n", phydev->phy_id);
+		phy_disconnect(phydev);
+		return -ENODEV;
+	}
+
+	dev_dbg(priv->device, "attached to PHY %d UID 0x%08x Link = %d\n",
+		phydev->addr, phydev->phy_id, phydev->link);
+
+	priv->phydev = phydev;
+	return 0;
+}
+
+static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr)
+{
+	struct altera_tse_mac *mac = priv->mac_dev;
+	u32 msb;
+	u32 lsb;
+
+	msb = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+	lsb = ((addr[5] << 8) | addr[4]) & 0xffff;
+
+	/* Set primary MAC address */
+	iowrite32(msb, &mac->mac_addr_0);
+	iowrite32(lsb, &mac->mac_addr_1);
+}
+
+/* MAC software reset.
+ * When reset is triggered, the MAC function completes the current
+ * transmission or reception, and subsequently disables the transmit and
+ * receive logic, flushes the receive FIFO buffer, and resets the statistics
+ * counters.
+ */
+static int reset_mac(struct altera_tse_private *priv)
+{
+	void __iomem *cmd_cfg_reg = &priv->mac_dev->command_config;
+	int counter;
+	u32 dat;
+
+	dat = ioread32(cmd_cfg_reg);
+	dat &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA);
+	dat |= MAC_CMDCFG_SW_RESET | MAC_CMDCFG_CNT_RESET;
+	iowrite32(dat, cmd_cfg_reg);
+
+	counter = 0;
+	while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
+		if (tse_bit_is_clear(cmd_cfg_reg, MAC_CMDCFG_SW_RESET))
+			break;
+		udelay(1);
+	}
+
+	if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
+		if (netif_msg_drv(priv))
+			dev_warn(priv->device,
+				 "TSE MAC resetting bit never cleared!\n");
+		dat = ioread32(cmd_cfg_reg);
+		dat &= ~MAC_CMDCFG_SW_RESET;
+		iowrite32(dat, cmd_cfg_reg);
+		return -1;
+	}
+	return 0;
+}
+
+/* Initialize MAC core registers
+*/
+static int init_mac(struct altera_tse_private *priv)
+{
+	struct altera_tse_mac *mac = priv->mac_dev;
+	unsigned int cmd = 0;
+	u32 frm_length;
+
+	/* Setup Rx FIFO */
+	iowrite32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY,
+		  &mac->rx_section_empty);
+	iowrite32(ALTERA_TSE_RX_SECTION_FULL, &mac->rx_section_full);
+	iowrite32(ALTERA_TSE_RX_ALMOST_EMPTY, &mac->rx_almost_empty);
+	iowrite32(ALTERA_TSE_RX_ALMOST_FULL, &mac->rx_almost_full);
+
+	/* Setup Tx FIFO */
+	iowrite32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY,
+		  &mac->tx_section_empty);
+	iowrite32(ALTERA_TSE_TX_SECTION_FULL, &mac->tx_section_full);
+	iowrite32(ALTERA_TSE_TX_ALMOST_EMPTY, &mac->tx_almost_empty);
+	iowrite32(ALTERA_TSE_TX_ALMOST_FULL, &mac->tx_almost_full);
+
+	/* MAC Address Configuration */
+	tse_update_mac_addr(priv, priv->dev->dev_addr);
+
+	/* MAC Function Configuration */
+	frm_length = ETH_HLEN + priv->dev->mtu + ETH_FCS_LEN;
+	iowrite32(frm_length, &mac->frm_length);
+	iowrite32(ALTERA_TSE_TX_IPG_LENGTH, &mac->tx_ipg_length);
+
+	/* Disable RX/TX shift 16 for alignment of all received frames on 16-bit
+	 * start address
+	 */
+	tse_clear_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16);
+	tse_clear_bit(&mac->tx_cmd_stat, ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 |
+					 ALTERA_TSE_TX_CMD_STAT_OMIT_CRC);
+
+	/* Set the MAC options */
+	cmd = ioread32(&mac->command_config);
+	cmd |= MAC_CMDCFG_PAD_EN;	/* Padding Removal on Receive */
+	cmd &= ~MAC_CMDCFG_CRC_FWD;	/* CRC Removal */
+	cmd |= MAC_CMDCFG_RX_ERR_DISC;	/* Automatically discard frames
+					 * with CRC errors
+					 */
+	cmd |= MAC_CMDCFG_CNTL_FRM_ENA;
+	cmd &= ~MAC_CMDCFG_TX_ENA;
+	cmd &= ~MAC_CMDCFG_RX_ENA;
+	iowrite32(cmd, &mac->command_config);
+
+	if (netif_msg_hw(priv))
+		dev_dbg(priv->device,
+			"MAC post-initialization: CMD_CONFIG = 0x%08x\n", cmd);
+
+	return 0;
+}
+
+/* Start/stop MAC transmission logic
+ */
+static void tse_set_mac(struct altera_tse_private *priv, bool enable)
+{
+	struct altera_tse_mac *mac = priv->mac_dev;
+	u32 value = ioread32(&mac->command_config);
+
+	if (enable)
+		value |= MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA;
+	else
+		value &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA);
+
+	iowrite32(value, &mac->command_config);
+}
+
+/* Change the MTU
+ */
+static int tse_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	unsigned int max_mtu = priv->max_mtu;
+	unsigned int min_mtu = ETH_ZLEN + ETH_FCS_LEN;
+
+	if (netif_running(dev)) {
+		dev_err(priv->device, "must be stopped to change its MTU\n");
+		return -EBUSY;
+	}
+
+	if ((new_mtu < min_mtu) || (new_mtu > max_mtu)) {
+		netdev_err(dev, "invalid MTU, max MTU is: %u\n", max_mtu);
+		return -EINVAL;
+	}
+
+	dev->mtu = new_mtu;
+	netdev_update_features(dev);
+
+	return 0;
+}
+
+static void altera_tse_set_mcfilter(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct altera_tse_mac *mac = (struct altera_tse_mac *)priv->mac_dev;
+	int i;
+	struct netdev_hw_addr *ha;
+
+	/* clear the hash filter */
+	for (i = 0; i < 64; i++)
+		iowrite32(0, &(mac->hash_table[i]));
+
+	netdev_for_each_mc_addr(ha, dev) {
+		unsigned int hash = 0;
+		int mac_octet;
+
+		for (mac_octet = 5; mac_octet >= 0; mac_octet--) {
+			unsigned char xor_bit = 0;
+			unsigned char octet = ha->addr[mac_octet];
+			unsigned int bitshift;
+
+			for (bitshift = 0; bitshift < 8; bitshift++)
+				xor_bit ^= ((octet >> bitshift) & 0x01);
+
+			hash = (hash << 1) | xor_bit;
+		}
+		iowrite32(1, &(mac->hash_table[hash]));
+	}
+}
+
+
+static void altera_tse_set_mcfilterall(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct altera_tse_mac *mac = (struct altera_tse_mac *)priv->mac_dev;
+	int i;
+
+	/* set the hash filter */
+	for (i = 0; i < 64; i++)
+		iowrite32(1, &(mac->hash_table[i]));
+}
+
+/* Set or clear the multicast filter for this adaptor
+ */
+static void tse_set_rx_mode_hashfilter(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct altera_tse_mac *mac = priv->mac_dev;
+
+	spin_lock(&priv->mac_cfg_lock);
+
+	if (dev->flags & IFF_PROMISC)
+		tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+
+	if (dev->flags & IFF_ALLMULTI)
+		altera_tse_set_mcfilterall(dev);
+	else
+		altera_tse_set_mcfilter(dev);
+
+	spin_unlock(&priv->mac_cfg_lock);
+}
+
+/* Set or clear the multicast filter for this adaptor
+ */
+static void tse_set_rx_mode(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	struct altera_tse_mac *mac = priv->mac_dev;
+
+	spin_lock(&priv->mac_cfg_lock);
+
+	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
+	    !netdev_mc_empty(dev) || !netdev_uc_empty(dev))
+		tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+	else
+		tse_clear_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+
+	spin_unlock(&priv->mac_cfg_lock);
+}
+
+/* Open and initialize the interface
+ */
+static int tse_open(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	int ret = 0;
+	int i;
+	unsigned long int flags;
+
+	/* Reset and configure TSE MAC and probe associated PHY */
+	ret = priv->dmaops->init_dma(priv);
+	if (ret != 0) {
+		netdev_err(dev, "Cannot initialize DMA\n");
+		goto phy_error;
+	}
+
+	if (netif_msg_ifup(priv))
+		dev_warn(priv->device, "device MAC address %pM\n",
+			 dev->dev_addr);
+
+	if ((priv->revision < 0xd00) || (priv->revision > 0xe00))
+		dev_warn(priv->device, "TSE revision %x\n", priv->revision);
+
+	spin_lock(&priv->mac_cfg_lock);
+	ret = reset_mac(priv);
+	if (ret)
+		netdev_err(dev, "Cannot reset MAC core (error: %d)\n", ret);
+
+	ret = init_mac(priv);
+	spin_unlock(&priv->mac_cfg_lock);
+	if (ret) {
+		netdev_err(dev, "Cannot init MAC core (error: %d)\n", ret);
+		goto alloc_skbuf_error;
+	}
+
+	priv->dmaops->reset_dma(priv);
+
+	/* Create and initialize the TX/RX descriptors chains. */
+	priv->rx_ring_size = dma_rx_num;
+	priv->tx_ring_size = dma_tx_num;
+	ret = alloc_init_skbufs(priv);
+	if (ret) {
+		netdev_err(dev, "DMA descriptors initialization failed\n");
+		goto alloc_skbuf_error;
+	}
+
+
+	/* Register RX interrupt */
+	ret = request_irq(priv->rx_irq, altera_isr, IRQF_SHARED,
+			  dev->name, dev);
+	if (ret) {
+		netdev_err(dev, "Unable to register RX interrupt %d\n",
+			   priv->rx_irq);
+		goto init_error;
+	}
+
+	/* Register TX interrupt */
+	ret = request_irq(priv->tx_irq, altera_isr, IRQF_SHARED,
+			  dev->name, dev);
+	if (ret) {
+		netdev_err(dev, "Unable to register TX interrupt %d\n",
+			   priv->tx_irq);
+		goto tx_request_irq_error;
+	}
+
+	/* Enable DMA interrupts */
+	spin_lock_irqsave(&priv->rxdma_irq_lock, flags);
+	priv->dmaops->enable_rxirq(priv);
+	priv->dmaops->enable_txirq(priv);
+
+	/* Setup RX descriptor chain */
+	for (i = 0; i < priv->rx_ring_size; i++)
+		priv->dmaops->add_rx_desc(priv, &priv->rx_ring[i]);
+
+	spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags);
+
+	/* Start MAC Rx/Tx */
+	spin_lock(&priv->mac_cfg_lock);
+	tse_set_mac(priv, true);
+	spin_unlock(&priv->mac_cfg_lock);
+
+	if (priv->phydev)
+		phy_start(priv->phydev);
+
+	napi_enable(&priv->napi);
+	netif_start_queue(dev);
+
+	return 0;
+
+tx_request_irq_error:
+	free_irq(priv->rx_irq, dev);
+init_error:
+	free_skbufs(dev);
+alloc_skbuf_error:
+	if (priv->phydev) {
+		phy_disconnect(priv->phydev);
+		priv->phydev = NULL;
+	}
+phy_error:
+	return ret;
+}
+
+/* Stop TSE MAC interface and put the device in an inactive state
+ */
+static int tse_shutdown(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	int ret;
+	unsigned long int flags;
+
+	/* Stop and disconnect the PHY */
+	if (priv->phydev) {
+		phy_stop(priv->phydev);
+		phy_disconnect(priv->phydev);
+		priv->phydev = NULL;
+	}
+
+	netif_stop_queue(dev);
+	napi_disable(&priv->napi);
+
+	/* Disable DMA interrupts */
+	spin_lock_irqsave(&priv->rxdma_irq_lock, flags);
+	priv->dmaops->disable_rxirq(priv);
+	priv->dmaops->disable_txirq(priv);
+	spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags);
+
+	/* Free the IRQ lines */
+	free_irq(priv->rx_irq, dev);
+	free_irq(priv->tx_irq, dev);
+
+	/* disable and reset the MAC, empties fifo */
+	spin_lock(&priv->mac_cfg_lock);
+	spin_lock(&priv->tx_lock);
+
+	ret = reset_mac(priv);
+	if (ret)
+		netdev_err(dev, "Cannot reset MAC core (error: %d)\n", ret);
+	priv->dmaops->reset_dma(priv);
+	free_skbufs(dev);
+
+	spin_unlock(&priv->tx_lock);
+	spin_unlock(&priv->mac_cfg_lock);
+
+	priv->dmaops->uninit_dma(priv);
+
+	return 0;
+}
+
+static struct net_device_ops altera_tse_netdev_ops = {
+	.ndo_open		= tse_open,
+	.ndo_stop		= tse_shutdown,
+	.ndo_start_xmit		= tse_start_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_set_rx_mode	= tse_set_rx_mode,
+	.ndo_change_mtu		= tse_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+
+static int request_and_map(struct platform_device *pdev, const char *name,
+			   struct resource **res, void __iomem **ptr)
+{
+	struct resource *region;
+	struct device *device = &pdev->dev;
+
+	*res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+	if (*res == NULL) {
+		dev_err(device, "resource %s not defined\n", name);
+		return -ENODEV;
+	}
+
+	region = devm_request_mem_region(device, (*res)->start,
+					 resource_size(*res), dev_name(device));
+	if (region == NULL) {
+		dev_err(device, "unable to request %s\n", name);
+		return -EBUSY;
+	}
+
+	*ptr = devm_ioremap_nocache(device, region->start,
+				    resource_size(region));
+	if (*ptr == NULL) {
+		dev_err(device, "ioremap_nocache of %s failed!", name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* Probe Altera TSE MAC device
+ */
+static int altera_tse_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev;
+	int ret = -ENODEV;
+	struct resource *control_port;
+	struct resource *dma_res;
+	struct altera_tse_private *priv;
+	int len;
+	const unsigned char *macaddr;
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int descmap;
+	const struct of_device_id *of_id = NULL;
+
+	ndev = alloc_etherdev(sizeof(struct altera_tse_private));
+	if (!ndev) {
+		dev_err(&pdev->dev, "Could not allocate network device\n");
+		return -ENODEV;
+	}
+
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	priv = netdev_priv(ndev);
+	priv->device = &pdev->dev;
+	priv->dev = ndev;
+	priv->msg_enable = netif_msg_init(debug, default_msg_level);
+
+	of_id = of_match_device(altera_tse_ids, &pdev->dev);
+
+	if (of_id)
+		priv->dmaops = (struct altera_dmaops *)of_id->data;
+
+
+	if (priv->dmaops &&
+	    priv->dmaops->altera_dtype == ALTERA_DTYPE_SGDMA) {
+		ret = request_and_map(pdev, "s1", &dma_res,
+			      (void *)&descmap);
+		if (ret)
+			goto out_free;
+
+		priv->tx_dma_desc = (void *)descmap;
+		priv->txdescmem = resource_size(dma_res)/2;
+		priv->txdescmem_busaddr = dma_res->start;
+
+		priv->rx_dma_desc = (void *)(descmap+priv->txdescmem);
+		priv->rxdescmem = resource_size(dma_res)/2;
+		priv->rxdescmem_busaddr = dma_res->start + priv->txdescmem;
+
+		if (upper_32_bits(priv->rxdescmem_busaddr)) {
+			dev_dbg(priv->device,
+				"SGDMA bus addresses greater than 32-bits\n");
+			goto out_free;
+		}
+		if (upper_32_bits(priv->txdescmem_busaddr)) {
+			dev_dbg(priv->device,
+				"SGDMA bus addresses greater than 32-bits\n");
+			goto out_free;
+		}
+	} else if (priv->dmaops &&
+		   priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) {
+		ret = request_and_map(pdev, "rx_resp", &dma_res,
+				      (void *)&priv->rx_dma_resp);
+		if (ret)
+			goto out_free;
+
+		ret = request_and_map(pdev, "tx_desc", &dma_res,
+			      (void *)&priv->tx_dma_desc);
+		if (ret)
+			goto out_free;
+
+		priv->txdescmem = resource_size(dma_res);
+		priv->txdescmem_busaddr = dma_res->start;
+
+		ret = request_and_map(pdev, "rx_desc", &dma_res,
+			      (void *)&priv->rx_dma_desc);
+		if (ret)
+			goto out_free;
+
+		priv->rxdescmem = resource_size(dma_res);
+		priv->rxdescmem_busaddr = dma_res->start;
+
+	} else {
+		goto out_free;
+	}
+
+	if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask)))
+		dma_set_coherent_mask(priv->device,
+				      DMA_BIT_MASK(priv->dmaops->dmamask));
+	else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32)))
+		dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32));
+	else
+		goto out_free;
+
+	/* MAC address space */
+	ret = request_and_map(pdev, "control_port", &control_port,
+			      (void *)&priv->mac_dev);
+	if (ret)
+		goto out_free;
+
+	/* xSGDMA Rx Dispatcher address space */
+	ret = request_and_map(pdev, "rx_csr", &dma_res,
+			      (void *)&priv->rx_dma_csr);
+	if (ret)
+		goto out_free;
+
+
+	/* xSGDMA Tx Dispatcher address space */
+	ret = request_and_map(pdev, "tx_csr", &dma_res,
+			      (void *)&priv->tx_dma_csr);
+	if (ret)
+		goto out_free;
+
+
+	/* Rx IRQ */
+	priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq");
+	if (priv->rx_irq == -ENXIO) {
+		dev_err(&pdev->dev, "cannot obtain Rx IRQ\n");
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+	/* Tx IRQ */
+	priv->tx_irq = platform_get_irq_byname(pdev, "tx_irq");
+	if (priv->tx_irq == -ENXIO) {
+		dev_err(&pdev->dev, "cannot obtain Tx IRQ\n");
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+	/* get FIFO depths from device tree */
+	if (of_property_read_u32(pdev->dev.of_node, "rx-fifo-depth",
+				 &priv->rx_fifo_depth)) {
+		dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n");
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+	if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth",
+				 &priv->rx_fifo_depth)) {
+		dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n");
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+
+	/* get hash filter settings for this instance */
+	if (of_property_read_u32(pdev->dev.of_node, "altr,enable-hash",
+				 &priv->hash_filter)) {
+		dev_err(&pdev->dev, "cannot obtain altr,enable-hash\n");
+		priv->hash_filter = 0;
+	}
+
+	/* get supplemental address settings for this instance */
+	if (of_property_read_u32(pdev->dev.of_node, "altr,enable-sup-addr",
+				 &priv->added_unicast)) {
+		dev_err(&pdev->dev, "cannot obtain altr,enable-sup-addr\n");
+		priv->added_unicast = 0;
+	}
+
+	/* Max MTU is 1500, ETH_DATA_LEN */
+	priv->max_mtu = ETH_DATA_LEN;
+
+	/* Get the max mtu from the device tree. Note that the
+	 * "max-frame-size" parameter is actually max mtu. Definition
+	 * in the ePAPR v1.1 spec and usage differ, so go with usage.
+	 */
+	of_property_read_u32(pdev->dev.of_node, "max-frame-size",
+			     &priv->max_mtu);
+
+	/* The DMA buffer size already accounts for an alignment bias
+	 * to avoid unaligned access exceptions for the NIOS processor,
+	 */
+	priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE;
+
+	/* get default MAC address from device tree */
+	macaddr = of_get_property(pdev->dev.of_node, "local-mac-address", &len);
+	if (macaddr && len == ETH_ALEN)
+		ether_addr_copy(ndev->dev_addr, macaddr);
+
+	/* If we didn't get a valid address, generate a random one */
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		eth_hw_addr_random(ndev);
+
+	priv->phy_iface = of_get_phy_mode(np);
+
+	/* try to get PHY address from device tree, use PHY autodetection if
+	 * no valid address is given
+	 */
+	if (of_property_read_u32(pdev->dev.of_node, "phy-addr",
+				 &priv->phy_addr)) {
+		priv->phy_addr = POLL_PHY;
+	}
+
+	if (!((priv->phy_addr == POLL_PHY) ||
+	      ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) {
+		dev_err(&pdev->dev, "invalid phy-addr specified %d\n",
+			priv->phy_addr);
+		goto out_free;
+	}
+
+	/* Create/attach to MDIO bus */
+	ret = altera_tse_mdio_create(ndev,
+				     atomic_add_return(1, &instance_count));
+
+	if (ret)
+		goto out_free;
+
+	/* initialize netdev */
+	ether_setup(ndev);
+	ndev->mem_start = control_port->start;
+	ndev->mem_end = control_port->end;
+	ndev->netdev_ops = &altera_tse_netdev_ops;
+	altera_tse_set_ethtool_ops(ndev);
+
+	altera_tse_netdev_ops.ndo_set_rx_mode = tse_set_rx_mode;
+
+	if (priv->hash_filter)
+		altera_tse_netdev_ops.ndo_set_rx_mode =
+			tse_set_rx_mode_hashfilter;
+
+	/* Scatter/gather IO is not supported,
+	 * so it is turned off
+	 */
+	ndev->hw_features &= ~NETIF_F_SG;
+	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+
+	/* VLAN offloading of tagging, stripping and filtering is not
+	 * supported by hardware, but driver will accommodate the
+	 * extra 4-byte VLAN tag for processing by upper layers
+	 */
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+
+	/* setup NAPI interface */
+	netif_napi_add(ndev, &priv->napi, tse_poll, NAPI_POLL_WEIGHT);
+
+	spin_lock_init(&priv->mac_cfg_lock);
+	spin_lock_init(&priv->tx_lock);
+	spin_lock_init(&priv->rxdma_irq_lock);
+
+	ret = register_netdev(ndev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register TSE net device\n");
+		goto out_free_mdio;
+	}
+
+	platform_set_drvdata(pdev, ndev);
+
+	priv->revision = ioread32(&priv->mac_dev->megacore_revision);
+
+	if (netif_msg_probe(priv))
+		dev_info(&pdev->dev, "Altera TSE MAC version %d.%d at 0x%08lx irq %d/%d\n",
+			 (priv->revision >> 8) & 0xff,
+			 priv->revision & 0xff,
+			 (unsigned long) control_port->start, priv->rx_irq,
+			 priv->tx_irq);
+
+	ret = init_phy(ndev);
+	if (ret != 0) {
+		netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret);
+		goto out_free_mdio;
+	}
+	return 0;
+
+out_free_mdio:
+	altera_tse_mdio_destroy(ndev);
+out_free:
+	free_netdev(ndev);
+	return ret;
+}
+
+/* Remove Altera TSE MAC device
+ */
+static int altera_tse_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	altera_tse_mdio_destroy(ndev);
+	unregister_netdev(ndev);
+	free_netdev(ndev);
+
+	return 0;
+}
+
+struct altera_dmaops altera_dtype_sgdma = {
+	.altera_dtype = ALTERA_DTYPE_SGDMA,
+	.dmamask = 32,
+	.reset_dma = sgdma_reset,
+	.enable_txirq = sgdma_enable_txirq,
+	.enable_rxirq = sgdma_enable_rxirq,
+	.disable_txirq = sgdma_disable_txirq,
+	.disable_rxirq = sgdma_disable_rxirq,
+	.clear_txirq = sgdma_clear_txirq,
+	.clear_rxirq = sgdma_clear_rxirq,
+	.tx_buffer = sgdma_tx_buffer,
+	.tx_completions = sgdma_tx_completions,
+	.add_rx_desc = sgdma_add_rx_desc,
+	.get_rx_status = sgdma_rx_status,
+	.init_dma = sgdma_initialize,
+	.uninit_dma = sgdma_uninitialize,
+};
+
+struct altera_dmaops altera_dtype_msgdma = {
+	.altera_dtype = ALTERA_DTYPE_MSGDMA,
+	.dmamask = 64,
+	.reset_dma = msgdma_reset,
+	.enable_txirq = msgdma_enable_txirq,
+	.enable_rxirq = msgdma_enable_rxirq,
+	.disable_txirq = msgdma_disable_txirq,
+	.disable_rxirq = msgdma_disable_rxirq,
+	.clear_txirq = msgdma_clear_txirq,
+	.clear_rxirq = msgdma_clear_rxirq,
+	.tx_buffer = msgdma_tx_buffer,
+	.tx_completions = msgdma_tx_completions,
+	.add_rx_desc = msgdma_add_rx_desc,
+	.get_rx_status = msgdma_rx_status,
+	.init_dma = msgdma_initialize,
+	.uninit_dma = msgdma_uninitialize,
+};
+
+static struct of_device_id altera_tse_ids[] = {
+	{ .compatible = "altr,tse-msgdma-1.0", .data = &altera_dtype_msgdma, },
+	{ .compatible = "altr,tse-1.0", .data = &altera_dtype_sgdma, },
+	{ .compatible = "ALTR,tse-1.0", .data = &altera_dtype_sgdma, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_tse_ids);
+
+static struct platform_driver altera_tse_driver = {
+	.probe		= altera_tse_probe,
+	.remove		= altera_tse_remove,
+	.suspend	= NULL,
+	.resume		= NULL,
+	.driver		= {
+		.name	= ALTERA_TSE_RESOURCE_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = altera_tse_ids,
+	},
+};
+
+module_platform_driver(altera_tse_driver);
+
+MODULE_AUTHOR("Altera Corporation");
+MODULE_DESCRIPTION("Altera Triple Speed Ethernet MAC driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

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

* Re: [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-10 23:14 ` [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver Vince Bridgers
@ 2014-03-11  0:38   ` Stephen Hemminger
  2014-03-11 15:33     ` Vince Bridgers
  2014-03-11  0:40   ` Stephen Hemminger
  1 sibling, 1 reply; 21+ messages in thread
From: Stephen Hemminger @ 2014-03-11  0:38 UTC (permalink / raw)
  To: Vince Bridgers
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob

On Mon, 10 Mar 2014 18:14:36 -0500
Vince Bridgers <vbridgers2013@gmail.com> wrote:

> +static char stat_gstrings[][ETH_GSTRING_LEN] = {
> +	"aFramesTransmittedOK",
> +	"aFramesReceivedOK",
> +	"aFramesCheckSequenceErro

nit: should be const char

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

* Re: [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-10 23:14 ` [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver Vince Bridgers
  2014-03-11  0:38   ` Stephen Hemminger
@ 2014-03-11  0:40   ` Stephen Hemminger
  2014-03-11 15:35     ` Vince Bridgers
  1 sibling, 1 reply; 21+ messages in thread
From: Stephen Hemminger @ 2014-03-11  0:40 UTC (permalink / raw)
  To: Vince Bridgers
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob

On Mon, 10 Mar 2014 18:14:36 -0500
Vince Bridgers <vbridgers2013@gmail.com> wrote:

> +
> +	buf[0] = (u64) ioread32(&mac->frames_transmitted_ok);

The cast to u64 is not really necessary, C will do it for you.
You do need the cast to do the shift for the 64 bit values.

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

* Re: [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver
  2014-03-10 23:14 ` [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver Vince Bridgers
@ 2014-03-11  9:22   ` Mark Rutland
       [not found]     ` <20140311092222.GA31679-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Rutland @ 2014-03-11  9:22 UTC (permalink / raw)
  To: Vince Bridgers
  Cc: devicetree, netdev, linux-doc, robh+dt, Pawel Moll,
	ijc+devicetree, galak, rob

On Mon, Mar 10, 2014 at 11:14:31PM +0000, Vince Bridgers wrote:
> This patch adds a bindings description for the Altera Triple Speed Ethernet
> (TSE) driver. The bindings support the legacy SGDMA soft IP as well as the
> preferred MSGDMA soft IP. The TSE can be configured and synthesized in soft
> logic using Altera's Quartus toolchain. Please consult the bindings document
> for supported options.
> 
> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
> ---
> V2: - Update bindings to use standard Ethernet and Phy bindings.
>       Use standard "phy-addr" instead of Altera's "phy-addr".
>       Use "rx-fifo-depth" and "tx-fifo-depth" instead of versions
>       prepended with "altr," in units of 32-bit quantities.
>       Add missing bindings to describe "altr,enable-hash" and
>       "altr,enable-sup-addr".
> ---
>  .../devicetree/bindings/net/altera_tse.txt         |  112 ++++++++++++++++++++
>  1 file changed, 112 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/altera_tse.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/altera_tse.txt b/Documentation/devicetree/bindings/net/altera_tse.txt
> new file mode 100644
> index 0000000..040e4e7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/altera_tse.txt
> @@ -0,0 +1,112 @@
> +* Altera Triple-Speed Ethernet MAC driver (TSE)
> +
> +Required properties:
> +- compatible: Should be "altr,tse-1.0" for legacy SGDMA based TSE, and should
> +		be "altr,tse-msgdma-1.0" for the preferred MSGDMA based TSE.
> +		ALTR is supported for legacy device trees, but is deprecated.
> +		altr should be used for all new designs.
> +- reg: Address and length of the register set for the device. It contains
> +  the information of registers in the same order as described by reg-names
> +- reg-names: Should contain the reg names
> +  "control_port": MAC configuration space region
> +  "tx_csr":       xDMA Tx dispatcher control and status space region
> +  "tx_desc":      MSGDMA Tx dispatcher descriptor space region
> +  "rx_csr" :      xDMA Rx dispatcher control and status space region
> +  "rx_desc":      MSGDMA Rx dispatcher descriptor space region
> +  "rx_resp":      MSGDMA Rx dispatcher response space region
> +  "s1":		  SGDMA descriptor memory
> +- interrupts: Should contain the TSE interrupts and it's mode.
> +- interrupt-names: Should contain the interrupt names
> +  "rx_irq":       xDMA Rx dispatcher interrupt
> +  "tx_irq":       xDMA Tx dispatcher interrupt
> +- rx-fifo-depth: MAC receive FIFO buffer depth in bytes
> +- tx-fifo-depth: MAC transmit FIFO buffer depth in bytes
> +- phy-mode: See ethernet.txt in the same directory.
> +- phy-handle: See ethernet.txt in the same directory.
> +- phy-addr: See ethernet.txt in the same directory. A configuration should
> +		include phy-handle or phy-addr.
> +- altr,enable-sup-addr: If 0, TSE has no supplemental addresses configured.
> +			If 1, TSE supports additional unicast addresses.
> +- altr,enable-hash: If 0, TSE does not support hash multicast filtering. If 1,
> +			TSE supports a hash based multicast filter.

Why are these not booleans / empty properties?

If this is a hardware feature, "enable" sounds wrong -- these describe
the presence of a feature, not whether the system is expected to ernable
them.

How about altr,has-supplementary-unicast and
altr,has-hash-multicast-filter ?

> +
> +-mdio device tree subnode: When the TSE has a phy connected to its local
> +		mdio, there must be device tree subnode with the following
> +		required properties:
> +
> +	- compatible: Must be "altr,tse-mdio".
> +	- #address-cells: Must be <1>.
> +	- #size-cells: Must be <0>.
> +
> +	For each phy on the mdio bus, there must be a node with the following
> +	fields:
> +
> +	- reg: phy id used to communicate to phy.
> +	- device_type: Must be "ethernet-phy".
> +
> +Optional properties:
> +- local-mac-address: See ethernet.txt in the same directory.
> +- max-frame-size: See ethernet.txt in the same directory.
> +
> +Example:
> +
> +	tse_sub_0_eth_tse_0: ethernet@0x100000000 {

It would be nice to have a comma in the unit address between the two
32-bit halves, as we do for other dts where #address-cells = <2>. It
makes it easier to verify by inspection.

> +		compatible = "altr,tse-msgdma-1.0";
> +		reg = < 0x00000001 0x00000000 0x00000400
> +			0x00000001 0x00000460 0x00000020
> +			0x00000001 0x00000480 0x00000020
> +			0x00000001 0x000004A0 0x00000008
> +			0x00000001 0x00000400 0x00000020
> +			0x00000001 0x00000420 0x00000020 >;

Nit: please bracket list entries individually for consistency.

> +		reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
> +		interrupt-parent = < &hps_0_arm_gic_0 >;
> +		interrupts = < 0 41 4 0 40 4 >;

Please bracket these individually, it makes it far easy to see where one
ends and another begins.

Cheers,
Mark.

> +		interrupt-names = "rx_irq", "tx_irq";
> +		rx-fifo-depth = < 2048 >;
> +		tx-fifo-depth = < 2048 >;
> +		address-bits = < 48 >;
> +		max-frame-size = < 1500 >;
> +		local-mac-address = [ 00 00 00 00 00 00 ];
> +		phy-mode = "gmii";
> +		altr,enable-sup-addr = < 0 >;
> +		altr,enable-hash = < 1 >;
> +		phy-handle = < &phy0 >;
> +		mdio@0 {

Drop the unit-address for the mdio node. The parent has no address space
defined for it, and there's only one.

Cheers,
Mark.

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

* Re: [PATCH net-next v2 9/9] Altera TSE: Add main and header file for Altera Ethernet Driver
  2014-03-10 23:14 ` [PATCH net-next v2 9/9] Altera TSE: Add main and header file " Vince Bridgers
@ 2014-03-11  9:44   ` Mark Rutland
  2014-03-11 15:38     ` Vince Bridgers
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Rutland @ 2014-03-11  9:44 UTC (permalink / raw)
  To: Vince Bridgers
  Cc: devicetree, netdev, linux-doc, robh+dt, Pawel Moll,
	ijc+devicetree, galak, rob

On Mon, Mar 10, 2014 at 11:14:37PM +0000, Vince Bridgers wrote:
> This patch adds the main driver and header file for the Altera Triple
> Speed Ethernet driver.
> 
> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
> ---
> V2: - Address all comments from initial RFC (thanks Florian!)
>     - Moved asm/cacheflush.h to bottom of header includes
>     - Remove barriers since DMA APIs ensure memory consistency
>     - Add max-frame-size property
>     - Use accessor function of_get_phy_mode instead of custom function
>     - Remove custom function to access devicetree, use of APIs
>     - Deprecate use of Altera devicetree properties where standard
>       ones exist
>     - Remove use of netif_carrier_off - not necessary where it was used
>     - Move probing of phy to the probe routine instead of open
>     - use ether_addr_copy instead of memcpy
> ---
>  drivers/net/ethernet/altera/altera_tse.h      |  486 ++++++++
>  drivers/net/ethernet/altera/altera_tse_main.c | 1546 +++++++++++++++++++++++++
>  2 files changed, 2032 insertions(+)
>  create mode 100644 drivers/net/ethernet/altera/altera_tse.h
>  create mode 100644 drivers/net/ethernet/altera/altera_tse_main.c

[...]

> +static int altera_tse_mdio_create(struct net_device *dev, unsigned int id)
> +{
> +       struct altera_tse_private *priv = netdev_priv(dev);
> +       int ret;
> +       int i;
> +       struct device_node *mdio_node;
> +       struct mii_bus *mdio;
> +
> +       mdio_node = of_find_compatible_node(priv->device->of_node, NULL,
> +               "altr,tse-mdio");

This doesn't find a subnode, as the binding requires. This finds _any_
compatible node in the tree.

There doesn't seem to be an of_find_compatible_child_node, but you can
use for_each_child_of_node and of_device_is_compatible to achieve the
same effect.

[...]

> +static struct phy_device *connect_local_phy(struct net_device *dev)
> +{
> +       struct altera_tse_private *priv = netdev_priv(dev);
> +       struct phy_device *phydev = NULL;
> +       char phy_id_fmt[MII_BUS_ID_SIZE + 3];
> +       int ret;
> +
> +       if (priv->phy_addr != POLL_PHY) {
> +               snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
> +                        priv->mdio->id, priv->phy_addr);
> +
> +               dev_dbg(priv->device, "trying to attach to %s\n", phy_id_fmt);
> +
> +               phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
> +                                    priv->phy_iface);
> +               if (IS_ERR(phydev))
> +                       netdev_err(dev, "Could not attach to PHY\n");
> +
> +       } else {
> +               phydev = phy_find_first(priv->mdio);
> +               if (phydev == NULL) {
> +                       netdev_err(dev, "No PHY found\n");
> +                       return phydev;
> +               }
> +
> +               ret = phy_connect_direct(dev, phydev, &altera_tse_adjust_link,
> +                               priv->phy_iface);
> +               if (ret != 0) {
> +                       netdev_err(dev, "Could not attach to PHY\n");
> +                       phydev = NULL;
> +               }
> +       }
> +       return phydev;
> +}
> +
> +/* Initialize driver's PHY state, and attach to the PHY
> + */
> +static int init_phy(struct net_device *dev)
> +{
> +       struct altera_tse_private *priv = netdev_priv(dev);
> +       struct phy_device *phydev;
> +       struct device_node *phynode;
> +
> +       priv->oldlink = 0;
> +       priv->oldspeed = 0;
> +       priv->oldduplex = -1;
> +
> +       phynode = of_parse_phandle(priv->device->of_node, "phy-handle", 0);
> +
> +       if (!phynode) {
> +               netdev_dbg(dev, "no phy-handle found\n");
> +               if (!priv->mdio) {
> +                       netdev_err(dev,
> +                                  "No phy-handle nor local mdio specified\n");
> +                       return -ENODEV;
> +               }
> +               phydev = connect_local_phy(dev);
> +       } else {
> +               netdev_dbg(dev, "phy-handle found\n");
> +               phydev = of_phy_connect(dev, phynode,
> +                       &altera_tse_adjust_link, 0, priv->phy_iface);
> +       }

Be aware that of_phy_connect can return NULL (e.g. if the phy-handle
phandle pointed to a node that wasn't a phy). You'll want to check it's
not NULL before dereferencing it below.

The same seems to be true of connect_local_phy, so the check can be
shared.

[...]

> +       /* get hash filter settings for this instance */
> +       if (of_property_read_u32(pdev->dev.of_node, "altr,enable-hash",
> +                                &priv->hash_filter)) {
> +               dev_err(&pdev->dev, "cannot obtain altr,enable-hash\n");
> +               priv->hash_filter = 0;
> +       }
> +
> +       /* get supplemental address settings for this instance */
> +       if (of_property_read_u32(pdev->dev.of_node, "altr,enable-sup-addr",
> +                                &priv->added_unicast)) {
> +               dev_err(&pdev->dev, "cannot obtain altr,enable-sup-addr\n");
> +               priv->added_unicast = 0;
> +       }

Please change these to boolean/empty properties and use
of_property_read_bool.

> +
> +       /* Max MTU is 1500, ETH_DATA_LEN */
> +       priv->max_mtu = ETH_DATA_LEN;
> +
> +       /* Get the max mtu from the device tree. Note that the
> +        * "max-frame-size" parameter is actually max mtu. Definition
> +        * in the ePAPR v1.1 spec and usage differ, so go with usage.
> +        */
> +       of_property_read_u32(pdev->dev.of_node, "max-frame-size",
> +                            &priv->max_mtu);
> +
> +       /* The DMA buffer size already accounts for an alignment bias
> +        * to avoid unaligned access exceptions for the NIOS processor,
> +        */
> +       priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE;
> +
> +       /* get default MAC address from device tree */
> +       macaddr = of_get_property(pdev->dev.of_node, "local-mac-address", &len);
> +       if (macaddr && len == ETH_ALEN)
> +               ether_addr_copy(ndev->dev_addr, macaddr);

Any reason we couldn't use of_get_mac_address here? It also checks that
the address is valid.

Cheers,
Mark.

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

* Re: [PATCH net-next v2 2/9] net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE driver
  2014-03-10 23:14   ` [PATCH net-next v2 2/9] net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE driver Vince Bridgers
@ 2014-03-11 14:09     ` Sergei Shtylyov
  2014-03-11 15:46       ` Vince Bridgers
  0 siblings, 1 reply; 21+ messages in thread
From: Sergei Shtylyov @ 2014-03-11 14:09 UTC (permalink / raw)
  To: Vince Bridgers, devicetree, netdev, linux-doc
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob

Hello.

On 11-03-2014 3:14, Vince Bridgers wrote:

> This patch changes the Ethernet Makefile and Kconfig files to add the Altera
> Ethernet driver component.

> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
> ---
> V2: - No change to Kconfig and Makefile from initial RFC review

    Unfortunately, the order of patches seems wrong. This patch should be 
among the last.

> ---
>   drivers/net/ethernet/Kconfig  |    1 +
>   drivers/net/ethernet/Makefile |    1 +
>   2 files changed, 2 insertions(+)

> diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
> index 506b024..39484b5 100644
> --- a/drivers/net/ethernet/Kconfig
> +++ b/drivers/net/ethernet/Kconfig
> @@ -22,6 +22,7 @@ source "drivers/net/ethernet/adaptec/Kconfig"
>   source "drivers/net/ethernet/aeroflex/Kconfig"
>   source "drivers/net/ethernet/allwinner/Kconfig"
>   source "drivers/net/ethernet/alteon/Kconfig"
> +source "drivers/net/ethernet/altera/Kconfig"

    This file doesn't exist yet.

>   source "drivers/net/ethernet/amd/Kconfig"
>   source "drivers/net/ethernet/apple/Kconfig"
>   source "drivers/net/ethernet/arc/Kconfig"
> diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
> index c0b8789..adf61af 100644
> --- a/drivers/net/ethernet/Makefile
> +++ b/drivers/net/ethernet/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
>   obj-$(CONFIG_GRETH) += aeroflex/
>   obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
>   obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
> +obj-$(CONFIG_ALTERA_TSE) += altera/

    This directory doesn't exist yet.

WBR, Sergei


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

* Re: [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-11  0:38   ` Stephen Hemminger
@ 2014-03-11 15:33     ` Vince Bridgers
  0 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-11 15:33 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, Kumar Gala, Rob Landley

On Mon, Mar 10, 2014 at 7:38 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Mon, 10 Mar 2014 18:14:36 -0500
> Vince Bridgers <vbridgers2013@gmail.com> wrote:
>
>> +static char stat_gstrings[][ETH_GSTRING_LEN] = {
>> +     "aFramesTransmittedOK",
>> +     "aFramesReceivedOK",
>> +     "aFramesCheckSequenceErro
>
> nit: should be const char

Ok, will address.

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

* Re: [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-11  0:40   ` Stephen Hemminger
@ 2014-03-11 15:35     ` Vince Bridgers
  2014-03-11 15:51       ` David Laight
  0 siblings, 1 reply; 21+ messages in thread
From: Vince Bridgers @ 2014-03-11 15:35 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, Kumar Gala, Rob Landley

On Mon, Mar 10, 2014 at 7:40 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Mon, 10 Mar 2014 18:14:36 -0500
> Vince Bridgers <vbridgers2013@gmail.com> wrote:
>
>> +
>> +     buf[0] = (u64) ioread32(&mac->frames_transmitted_ok);
>
> The cast to u64 is not really necessary, C will do it for you.
> You do need the cast to do the shift for the 64 bit values.

Ok, understood. I generally add the cast so it's explicit, but I'll modify.

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

* Re: [PATCH net-next v2 9/9] Altera TSE: Add main and header file for Altera Ethernet Driver
  2014-03-11  9:44   ` Mark Rutland
@ 2014-03-11 15:38     ` Vince Bridgers
  0 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-11 15:38 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree, netdev, linux-doc, robh+dt, Pawel Moll,
	ijc+devicetree, galak, rob

On Tue, Mar 11, 2014 at 4:44 AM, Mark Rutland <mark.rutland@arm.com> wrote:
> On Mon, Mar 10, 2014 at 11:14:37PM +0000, Vince Bridgers wrote:
>> This patch adds the main driver and header file for the Altera Triple
>> Speed Ethernet driver.
>>
>> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
>> ---
>> V2: - Address all comments from initial RFC (thanks Florian!)
>>     - Moved asm/cacheflush.h to bottom of header includes
>>     - Remove barriers since DMA APIs ensure memory consistency
>>     - Add max-frame-size property
>>     - Use accessor function of_get_phy_mode instead of custom function
>>     - Remove custom function to access devicetree, use of APIs
>>     - Deprecate use of Altera devicetree properties where standard
>>       ones exist
>>     - Remove use of netif_carrier_off - not necessary where it was used
>>     - Move probing of phy to the probe routine instead of open
>>     - use ether_addr_copy instead of memcpy
>> ---
>>  drivers/net/ethernet/altera/altera_tse.h      |  486 ++++++++
>>  drivers/net/ethernet/altera/altera_tse_main.c | 1546 +++++++++++++++++++++++++
>>  2 files changed, 2032 insertions(+)
>>  create mode 100644 drivers/net/ethernet/altera/altera_tse.h
>>  create mode 100644 drivers/net/ethernet/altera/altera_tse_main.c
>
> [...]
>
>> +static int altera_tse_mdio_create(struct net_device *dev, unsigned int id)
>> +{
>> +       struct altera_tse_private *priv = netdev_priv(dev);
>> +       int ret;
>> +       int i;
>> +       struct device_node *mdio_node;
>> +       struct mii_bus *mdio;
>> +
>> +       mdio_node = of_find_compatible_node(priv->device->of_node, NULL,
>> +               "altr,tse-mdio");
>
> This doesn't find a subnode, as the binding requires. This finds _any_
> compatible node in the tree.
>
> There doesn't seem to be an of_find_compatible_child_node, but you can
> use for_each_child_of_node and of_device_is_compatible to achieve the
> same effect.

Double doh! Will address, thank you.

>
> [...]
>
>> +static struct phy_device *connect_local_phy(struct net_device *dev)
>> +{
>> +       struct altera_tse_private *priv = netdev_priv(dev);
>> +       struct phy_device *phydev = NULL;
>> +       char phy_id_fmt[MII_BUS_ID_SIZE + 3];
>> +       int ret;
>> +
>> +       if (priv->phy_addr != POLL_PHY) {
>> +               snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
>> +                        priv->mdio->id, priv->phy_addr);
>> +
>> +               dev_dbg(priv->device, "trying to attach to %s\n", phy_id_fmt);
>> +
>> +               phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
>> +                                    priv->phy_iface);
>> +               if (IS_ERR(phydev))
>> +                       netdev_err(dev, "Could not attach to PHY\n");
>> +
>> +       } else {
>> +               phydev = phy_find_first(priv->mdio);
>> +               if (phydev == NULL) {
>> +                       netdev_err(dev, "No PHY found\n");
>> +                       return phydev;
>> +               }
>> +
>> +               ret = phy_connect_direct(dev, phydev, &altera_tse_adjust_link,
>> +                               priv->phy_iface);
>> +               if (ret != 0) {
>> +                       netdev_err(dev, "Could not attach to PHY\n");
>> +                       phydev = NULL;
>> +               }
>> +       }
>> +       return phydev;
>> +}
>> +
>> +/* Initialize driver's PHY state, and attach to the PHY
>> + */
>> +static int init_phy(struct net_device *dev)
>> +{
>> +       struct altera_tse_private *priv = netdev_priv(dev);
>> +       struct phy_device *phydev;
>> +       struct device_node *phynode;
>> +
>> +       priv->oldlink = 0;
>> +       priv->oldspeed = 0;
>> +       priv->oldduplex = -1;
>> +
>> +       phynode = of_parse_phandle(priv->device->of_node, "phy-handle", 0);
>> +
>> +       if (!phynode) {
>> +               netdev_dbg(dev, "no phy-handle found\n");
>> +               if (!priv->mdio) {
>> +                       netdev_err(dev,
>> +                                  "No phy-handle nor local mdio specified\n");
>> +                       return -ENODEV;
>> +               }
>> +               phydev = connect_local_phy(dev);
>> +       } else {
>> +               netdev_dbg(dev, "phy-handle found\n");
>> +               phydev = of_phy_connect(dev, phynode,
>> +                       &altera_tse_adjust_link, 0, priv->phy_iface);
>> +       }
>
> Be aware that of_phy_connect can return NULL (e.g. if the phy-handle
> phandle pointed to a node that wasn't a phy). You'll want to check it's
> not NULL before dereferencing it below.
>
> The same seems to be true of connect_local_phy, so the check can be
> shared.

Doh! Will address, thank you.

>
> [...]
>
>> +       /* get hash filter settings for this instance */
>> +       if (of_property_read_u32(pdev->dev.of_node, "altr,enable-hash",
>> +                                &priv->hash_filter)) {
>> +               dev_err(&pdev->dev, "cannot obtain altr,enable-hash\n");
>> +               priv->hash_filter = 0;
>> +       }
>> +
>> +       /* get supplemental address settings for this instance */
>> +       if (of_property_read_u32(pdev->dev.of_node, "altr,enable-sup-addr",
>> +                                &priv->added_unicast)) {
>> +               dev_err(&pdev->dev, "cannot obtain altr,enable-sup-addr\n");
>> +               priv->added_unicast = 0;
>> +       }
>
> Please change these to boolean/empty properties and use
> of_property_read_bool.

Will do, thank you.

>
>> +
>> +       /* Max MTU is 1500, ETH_DATA_LEN */
>> +       priv->max_mtu = ETH_DATA_LEN;
>> +
>> +       /* Get the max mtu from the device tree. Note that the
>> +        * "max-frame-size" parameter is actually max mtu. Definition
>> +        * in the ePAPR v1.1 spec and usage differ, so go with usage.
>> +        */
>> +       of_property_read_u32(pdev->dev.of_node, "max-frame-size",
>> +                            &priv->max_mtu);
>> +
>> +       /* The DMA buffer size already accounts for an alignment bias
>> +        * to avoid unaligned access exceptions for the NIOS processor,
>> +        */
>> +       priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE;
>> +
>> +       /* get default MAC address from device tree */
>> +       macaddr = of_get_property(pdev->dev.of_node, "local-mac-address", &len);
>> +       if (macaddr && len == ETH_ALEN)
>> +               ether_addr_copy(ndev->dev_addr, macaddr);
>
> Any reason we couldn't use of_get_mac_address here? It also checks that
> the address is valid.

No reason, an oversight. I'll address.

>
> Cheers,
> Mark.

Thank you for taking the time to review and comment. I'll address the
comments and respin the patch.

All the best,

Vince

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

* Re: [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver
       [not found]     ` <20140311092222.GA31679-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
@ 2014-03-11 15:44       ` Vince Bridgers
  0 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-11 15:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	Pawel Moll, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ

On Tue, Mar 11, 2014 at 4:22 AM, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> wrote:
> On Mon, Mar 10, 2014 at 11:14:31PM +0000, Vince Bridgers wrote:
>> This patch adds a bindings description for the Altera Triple Speed Ethernet
>> (TSE) driver. The bindings support the legacy SGDMA soft IP as well as the
>> preferred MSGDMA soft IP. The TSE can be configured and synthesized in soft
>> logic using Altera's Quartus toolchain. Please consult the bindings document
>> for supported options.
>>
>> Signed-off-by: Vince Bridgers <vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>> V2: - Update bindings to use standard Ethernet and Phy bindings.
>>       Use standard "phy-addr" instead of Altera's "phy-addr".
>>       Use "rx-fifo-depth" and "tx-fifo-depth" instead of versions
>>       prepended with "altr," in units of 32-bit quantities.
>>       Add missing bindings to describe "altr,enable-hash" and
>>       "altr,enable-sup-addr".
>> ---
>>  .../devicetree/bindings/net/altera_tse.txt         |  112 ++++++++++++++++++++
>>  1 file changed, 112 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/net/altera_tse.txt
>>
>> diff --git a/Documentation/devicetree/bindings/net/altera_tse.txt b/Documentation/devicetree/bindings/net/altera_tse.txt
>> new file mode 100644
>> index 0000000..040e4e7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/net/altera_tse.txt
>> @@ -0,0 +1,112 @@
>> +* Altera Triple-Speed Ethernet MAC driver (TSE)
>> +
>> +Required properties:
>> +- compatible: Should be "altr,tse-1.0" for legacy SGDMA based TSE, and should
>> +             be "altr,tse-msgdma-1.0" for the preferred MSGDMA based TSE.
>> +             ALTR is supported for legacy device trees, but is deprecated.
>> +             altr should be used for all new designs.
>> +- reg: Address and length of the register set for the device. It contains
>> +  the information of registers in the same order as described by reg-names
>> +- reg-names: Should contain the reg names
>> +  "control_port": MAC configuration space region
>> +  "tx_csr":       xDMA Tx dispatcher control and status space region
>> +  "tx_desc":      MSGDMA Tx dispatcher descriptor space region
>> +  "rx_csr" :      xDMA Rx dispatcher control and status space region
>> +  "rx_desc":      MSGDMA Rx dispatcher descriptor space region
>> +  "rx_resp":      MSGDMA Rx dispatcher response space region
>> +  "s1":                SGDMA descriptor memory
>> +- interrupts: Should contain the TSE interrupts and it's mode.
>> +- interrupt-names: Should contain the interrupt names
>> +  "rx_irq":       xDMA Rx dispatcher interrupt
>> +  "tx_irq":       xDMA Tx dispatcher interrupt
>> +- rx-fifo-depth: MAC receive FIFO buffer depth in bytes
>> +- tx-fifo-depth: MAC transmit FIFO buffer depth in bytes
>> +- phy-mode: See ethernet.txt in the same directory.
>> +- phy-handle: See ethernet.txt in the same directory.
>> +- phy-addr: See ethernet.txt in the same directory. A configuration should
>> +             include phy-handle or phy-addr.
>> +- altr,enable-sup-addr: If 0, TSE has no supplemental addresses configured.
>> +                     If 1, TSE supports additional unicast addresses.
>> +- altr,enable-hash: If 0, TSE does not support hash multicast filtering. If 1,
>> +                     TSE supports a hash based multicast filter.
>
> Why are these not booleans / empty properties?
>
> If this is a hardware feature, "enable" sounds wrong -- these describe
> the presence of a feature, not whether the system is expected to ernable
> them.
>
> How about altr,has-supplementary-unicast and
> altr,has-hash-multicast-filter ?

These were defined in the context of thinking these properties could
take on different values - for example, unicast filtering could take
on the value of the number of unicast addresses supported, and hash
could take on the value of the number of hash bins supported in
hardware - but that's not how it turned out. These property names did
not change accordingly.

I'll follow your suggestion, thank you for catching this.

>
>> +
>> +-mdio device tree subnode: When the TSE has a phy connected to its local
>> +             mdio, there must be device tree subnode with the following
>> +             required properties:
>> +
>> +     - compatible: Must be "altr,tse-mdio".
>> +     - #address-cells: Must be <1>.
>> +     - #size-cells: Must be <0>.
>> +
>> +     For each phy on the mdio bus, there must be a node with the following
>> +     fields:
>> +
>> +     - reg: phy id used to communicate to phy.
>> +     - device_type: Must be "ethernet-phy".
>> +
>> +Optional properties:
>> +- local-mac-address: See ethernet.txt in the same directory.
>> +- max-frame-size: See ethernet.txt in the same directory.
>> +
>> +Example:
>> +
>> +     tse_sub_0_eth_tse_0: ethernet@0x100000000 {
>
> It would be nice to have a comma in the unit address between the two
> 32-bit halves, as we do for other dts where #address-cells = <2>. It
> makes it easier to verify by inspection.

I'll address, thank you.

>
>> +             compatible = "altr,tse-msgdma-1.0";
>> +             reg = < 0x00000001 0x00000000 0x00000400
>> +                     0x00000001 0x00000460 0x00000020
>> +                     0x00000001 0x00000480 0x00000020
>> +                     0x00000001 0x000004A0 0x00000008
>> +                     0x00000001 0x00000400 0x00000020
>> +                     0x00000001 0x00000420 0x00000020 >;
>
> Nit: please bracket list entries individually for consistency.

I'll address, thank you.

>
>> +             reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
>> +             interrupt-parent = < &hps_0_arm_gic_0 >;
>> +             interrupts = < 0 41 4 0 40 4 >;
>
> Please bracket these individually, it makes it far easy to see where one
> ends and another begins.

I'll address, thank you.

>
> Cheers,
> Mark.
>
>> +             interrupt-names = "rx_irq", "tx_irq";
>> +             rx-fifo-depth = < 2048 >;
>> +             tx-fifo-depth = < 2048 >;
>> +             address-bits = < 48 >;
>> +             max-frame-size = < 1500 >;
>> +             local-mac-address = [ 00 00 00 00 00 00 ];
>> +             phy-mode = "gmii";
>> +             altr,enable-sup-addr = < 0 >;
>> +             altr,enable-hash = < 1 >;
>> +             phy-handle = < &phy0 >;
>> +             mdio@0 {
>
> Drop the unit-address for the mdio node. The parent has no address space
> defined for it, and there's only one.

Understood, we went by examples that exist in other bindings already.
I'll address, thank you for catching this.

>
> Cheers,
> Mark.

Thank you for taking the time to review and comment. I'll address your
comments and respin.

All the best,

Vince
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH net-next v2 2/9] net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE driver
  2014-03-11 14:09     ` Sergei Shtylyov
@ 2014-03-11 15:46       ` Vince Bridgers
  0 siblings, 0 replies; 21+ messages in thread
From: Vince Bridgers @ 2014-03-11 15:46 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, Kumar Gala, Rob Landley

Hi Sergei,

On Tue, Mar 11, 2014 at 9:09 AM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Hello.
>
>
> On 11-03-2014 3:14, Vince Bridgers wrote:
>
>> This patch changes the Ethernet Makefile and Kconfig files to add the
>> Altera
>> Ethernet driver component.
>
>
>> Signed-off-by: Vince Bridgers <vbridgers2013@gmail.com>
>> ---
>> V2: - No change to Kconfig and Makefile from initial RFC review
>
>
>    Unfortunately, the order of patches seems wrong. This patch should be
> among the last.
>
>
>> ---
>>   drivers/net/ethernet/Kconfig  |    1 +
>>   drivers/net/ethernet/Makefile |    1 +
>>   2 files changed, 2 insertions(+)
>
>
>> diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
>> index 506b024..39484b5 100644
>> --- a/drivers/net/ethernet/Kconfig
>> +++ b/drivers/net/ethernet/Kconfig
>> @@ -22,6 +22,7 @@ source "drivers/net/ethernet/adaptec/Kconfig"
>>   source "drivers/net/ethernet/aeroflex/Kconfig"
>>   source "drivers/net/ethernet/allwinner/Kconfig"
>>   source "drivers/net/ethernet/alteon/Kconfig"
>> +source "drivers/net/ethernet/altera/Kconfig"
>
>
>    This file doesn't exist yet.
>
>
>>   source "drivers/net/ethernet/amd/Kconfig"
>>   source "drivers/net/ethernet/apple/Kconfig"
>>   source "drivers/net/ethernet/arc/Kconfig"
>> diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
>> index c0b8789..adf61af 100644
>> --- a/drivers/net/ethernet/Makefile
>> +++ b/drivers/net/ethernet/Makefile
>> @@ -8,6 +8,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
>>   obj-$(CONFIG_GRETH) += aeroflex/
>>   obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
>>   obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
>> +obj-$(CONFIG_ALTERA_TSE) += altera/
>
>
>    This directory doesn't exist yet.
>
> WBR, Sergei
>

Understood, this was an oversight on my part when I created the
patchset. I'll address and respin.

Thank you for taking the time to review and comment,

All the best,

Vince

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

* RE: [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver
  2014-03-11 15:35     ` Vince Bridgers
@ 2014-03-11 15:51       ` David Laight
  0 siblings, 0 replies; 21+ messages in thread
From: David Laight @ 2014-03-11 15:51 UTC (permalink / raw)
  To: 'Vince Bridgers', Stephen Hemminger
  Cc: devicetree, netdev, linux-doc, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, Kumar Gala, Rob Landley

From: Vince Bridgers
> On Mon, Mar 10, 2014 at 7:40 PM, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> > On Mon, 10 Mar 2014 18:14:36 -0500
> > Vince Bridgers <vbridgers2013@gmail.com> wrote:
> >
> >> +
> >> +     buf[0] = (u64) ioread32(&mac->frames_transmitted_ok);
> >
> > The cast to u64 is not really necessary, C will do it for you.
> > You do need the cast to do the shift for the 64 bit values.
> 
> Ok, understood. I generally add the cast so it's explicit, but I'll modify.

The problem is that the cast will allow incorrect code to compile.
eg, you might have a pointer, not an integer.

Many years ago I got caught out by a #define like the following:
#define foo(ptr) { int s = splhi(); do_foo((void *)ptr); splx(s); }
My code crashed because I'd called foo(s).
Now that #define is broken in so many ways, but the (void *) cast
stopped the compiler erroring one of them.

	David




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

end of thread, other threads:[~2014-03-11 15:51 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-10 23:14 [PATCH net-next v2 0/9] Altera Triple Speed Ethernet (TSE) Driver Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 1/9] MAINTAINERS: Add entry for Altera Triple Speed Ethernet Driver Vince Bridgers
     [not found] ` <1394493277-2105-1-git-send-email-vbridgers2013-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-03-10 23:14   ` [PATCH net-next v2 2/9] net: ethernet: Change Ethernet Makefile and Kconfig for Altera TSE driver Vince Bridgers
2014-03-11 14:09     ` Sergei Shtylyov
2014-03-11 15:46       ` Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 3/9] dts: Add bindings for the Altera Triple Speed Ethernet driver Vince Bridgers
2014-03-11  9:22   ` Mark Rutland
     [not found]     ` <20140311092222.GA31679-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
2014-03-11 15:44       ` Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 4/9] Documentation: networking: Add Altera Ethernet (TSE) Documentation Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 5/9] Altera TSE: Add Altera Ethernet Driver Makefile and Kconfig Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 6/9] Altera TSE: Add Altera Ethernet Driver MSGDMA File Components Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 7/9] Altera TSE: Add Altera Ethernet Driver SGDMA file components Vince Bridgers
2014-03-10 23:14 ` [PATCH net-next v2 8/9] Altera TSE: Add Miscellaneous Files for Altera Ethernet Driver Vince Bridgers
2014-03-11  0:38   ` Stephen Hemminger
2014-03-11 15:33     ` Vince Bridgers
2014-03-11  0:40   ` Stephen Hemminger
2014-03-11 15:35     ` Vince Bridgers
2014-03-11 15:51       ` David Laight
2014-03-10 23:14 ` [PATCH net-next v2 9/9] Altera TSE: Add main and header file " Vince Bridgers
2014-03-11  9:44   ` Mark Rutland
2014-03-11 15:38     ` Vince Bridgers

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.