You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/12/23 19:56:35 UTC

[incubator-nuttx] branch master updated (e26daf9 -> ace6e70)

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from e26daf9  STM32 FLASH latency is calculated based on Vin.
     new 4ce99f3  arch: imx6: Fix style warnings in imx_memorymap.h
     new 1725e50  arch: imx6: Fix peripheral IP offsets in AIPS-2
     new ace6e70  arch: imx6: Add imx_enet driver

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/imx6/Kconfig                          |  40 +
 arch/arm/src/imx6/Make.defs                        |   4 +
 .../imxrt_enet.h => imx6/hardware/imx_enet.h}      | 452 ++++++-----
 arch/arm/src/imx6/hardware/imx_memorymap.h         | 214 +++---
 .../src/{imxrt/imxrt_enet.c => imx6/imx_enet.c}    | 856 +++++++++------------
 .../src/{imxrt/imxrt_flexcan.h => imx6/imx_enet.h} |  75 +-
 .../sabre-6quad/configs/{nsh => netnsh}/defconfig  |  43 +-
 7 files changed, 842 insertions(+), 842 deletions(-)
 copy arch/arm/src/{imxrt/hardware/imxrt_enet.h => imx6/hardware/imx_enet.h} (65%)
 copy arch/arm/src/{imxrt/imxrt_enet.c => imx6/imx_enet.c} (71%)
 copy arch/arm/src/{imxrt/imxrt_flexcan.h => imx6/imx_enet.h} (60%)
 copy boards/arm/imx6/sabre-6quad/configs/{nsh => netnsh}/defconfig (66%)


[incubator-nuttx] 01/03: arch: imx6: Fix style warnings in imx_memorymap.h

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 4ce99f324e8d65745c19816dde029a33912b91b6
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Wed Dec 23 18:37:36 2020 +0900

    arch: imx6: Fix style warnings in imx_memorymap.h
---
 arch/arm/src/imx6/hardware/imx_memorymap.h | 86 +++++++++++++++---------------
 1 file changed, 42 insertions(+), 44 deletions(-)

diff --git a/arch/arm/src/imx6/hardware/imx_memorymap.h b/arch/arm/src/imx6/hardware/imx_memorymap.h
index 1926e2d..ed79b2b 100644
--- a/arch/arm/src/imx6/hardware/imx_memorymap.h
+++ b/arch/arm/src/imx6/hardware/imx_memorymap.h
@@ -47,9 +47,19 @@
 #include <nuttx/config.h>
 #include <arch/imx6/chip.h>
 
+/* i.MX6 Virtual (mapped) Memory Map
+ *
+ * board_memorymap.h contains special mappings that are needed when a ROM
+ * memory map is used.  It is included in this odd location because it depends
+ * on some the virtual address definitions provided above.
+ */
+
+#include <arch/board/board_memorymap.h>
+
 /************************************************************************************
  * Pre-processor Definitions
  ************************************************************************************/
+
 /* Decimal configuration values may exceed 2Gb and, hence, overflow to negative
  * values unless we force them to unsigned long:
  */
@@ -57,7 +67,7 @@
 #define __CONCAT(a,b) a ## b
 #define MKULONG(a) __CONCAT(a,ul)
 
-/* Overview *****************************************************************
+/* Overview *************************************************************************
  *
  *  i.MX6 Physical (unmapped) Memory Map
  *  - i.MX6 System 1MB PSECTIONS
@@ -94,9 +104,10 @@
  *  Page table start addresses
  *  Base address of the interrupt vector table
  *
- ****************************************************************************/
+ ************************************************************************************/
+
+/* i.MX6 Physical (unmapped) Memory Map *********************************************/
 
-/* i.MX6 Physical (unmapped) Memory Map *************************************/
 /* i.MX6 System PSECTIONS */
 
 #define IMX_ROMCP_PSECTION       0x00000000  /* 00000000-00017fff  96 KB Boot ROM (ROMCP) */
@@ -146,6 +157,7 @@
 #define IMX_GPU2D_OFFSET         0x00034000  /* 00034000-00037fff  16 KB GPU 2D (GC320) */
 #define IMX_DTCP_OFFSET          0x00038000  /* 00038000-0003bfff  16 KB DTCP */
                                              /* 0003c000-000fffff 784 KB Reserved */
+
 /* i.MX6 OCRAM PSECTION Offsets */
 
 #define IMX_OCRAM_OFFSET         0x00000000  /* 00000000-0003ffff  0.25 MB OCRAM 256 KB */
@@ -170,7 +182,8 @@
 
 /* i.MX6 AIPS-1 PSECTION Offsets */
 
-                                             /* 00000000 00003fff Reserved for SDMA internal registers 16 KB */
+/* 00000000 00003fff Reserved for SDMA internal registers 16 KB */
+
 #define IMX_SPDIF_OFFSET         0x00004000  /* 00004000 00007fff SPDIF 16 KB */
 #define IMX_ECSPI1_OFFSET        0x00008000  /* 00008000 0000bfff eCSPI1 16 KB */
 #define IMX_ECSPI2_OFFSET        0x0000c000  /* 0000c000 0000ffff eCSPI2 16KB */
@@ -195,7 +208,9 @@
 #define IMX_CAN1_OFFSET          0x00090000  /* 00090000 00093fff CAN1 16 KB */
 #define IMX_CAN2_OFFSET          0x00094000  /* 00094000 00097fff CAN2 16 KB */
 #define IMX_GPT_OFFSET           0x00098000  /* 00098000 0009bfff GPT 16 KB */
+
 #define IMX_GPIO_OFFSET(n)       (0x0009c000 + ((n) << 14)) /* n=0..6 */
+
 #define IMX_GPIO1_OFFSET         0x0009c000  /* 0009c000 0009ffff GPIO1 16 KB */
 #define IMX_GPIO2_OFFSET         0x000a0000  /* 000a0000 000a3fff GPIO2 16 KB */
 #define IMX_GPIO3_OFFSET         0x000a4000  /* 000a4000 000a7fff GPIO3 16 KB */
@@ -228,6 +243,7 @@
                                              /* 000f4000 000f7fff Reserved 16 KB */
                                              /* 000f8000 000fbfff Reserved 16 KB */
                                              /* 000fc000 000fffff AIPS-1 Reserved 16 KB */
+
 /* i.MX6 AIPS-2 PSECTION Offsets */
 
 #define IMX_CAAM_OFFSET          0x00100000  /* 00100000 0210ffff CAAM 64 KB */
@@ -304,6 +320,7 @@
 #define IMX_OPENVG_OFFSET        0x00204000  /* 00204000-02207fff  16 KB OpenVG (GC355) */
 #define IMX_MIPIHSI_OFFSET       0x00208000  /* 00208000-0220bfff  16 KB MIPIHSI */
                                              /* 0020c000-000fffff   2 MB Reserved */
+
 /* i.MX6 DMA Physical Base Addresses */
 
 #define IMX_CAAMRAM_PBASE        (IMX_DMA_PSECTION+IMX_CAAMRAM_OFFSET)
@@ -478,9 +495,10 @@
                                              /* 0220c000-023fffff   2 MB Reserved */
 #define IMX_IPU1_SECSIZE       (4*1024*1024) /* 02600000-029fffff   4 MB IPU-1 */
 #define IMX_IPU2_SECSIZE       (4*1024*1024) /* 02a00000-02dfffff   4 MB IPU-2 */
+
 #define IMX_EIM_SECSIZE     MKULONG(CONFIG_IMX_EIM_SIZE) /* 08000000-0fffffff 128 MB EIM - (NOR/SRAM) */
 #define IMX_MMDCDDR_SECSIZE MKULONG(CONFIG_IMX_DDR_SIZE) /* 10000000-ffffffff 3840 MB MMDC-DDR Controller */
-                                             /* 10000000-7fffffff 1792 MB */
+                                                         /* 10000000-7fffffff 1792 MB */
 
 /* Convert size in bytes to number of sections (in Mb). */
 
@@ -536,15 +554,6 @@
 #define IMX_EIM_MMUFLAGS         MMU_ROMFLAGS /* REVISIT */
 #define IMX_MMDCDDR_MMUFLAGS     MMU_MEMFLAGS
 
-/* i.MX6 Virtual (mapped) Memory Map
- *
- * board_memorymap.h contains special mappings that are needed when a ROM
- * memory map is used.  It is included in this odd location because it depends
- * on some the virtual address definitions provided above.
- */
-
-#include <arch/board/board_memorymap.h>
-
 /* i.MX6 Virtual (mapped) Memory Map.  These are the mappings that will
  * be created if the page table lies in RAM.  If the platform has another,
  * read-only, pre-initialized page table (perhaps in ROM), then the board.h
@@ -799,43 +808,44 @@
 #    error "Only one of PGTABLE_BASE_PADDR or PGTABLE_BASE_VADDR is defined"
 #  endif
 
-  /* A sanity check, if the configuration says that the page table is read-only
-   * and pre-initialized (maybe ROM), then it should have also defined both of
-   * the page table base addresses.
-   */
+/* A sanity check, if the configuration says that the page table is read-only
+ * and pre-initialized (maybe ROM), then it should have also defined both of
+ * the page table base addresses.
+ */
 
 #  ifdef CONFIG_ARCH_ROMPGTABLE
 #    error "CONFIG_ARCH_ROMPGTABLE defined; PGTABLE_BASE_P/VADDR not defined"
 #  endif
 
-  /* We must declare the page table at the bottom or at the top of OCRAM. */
-  /* Yes.. do the vectors lie in low memory? */
+/* We must declare the page table at the bottom or at the top of OCRAM.
+ * Yes.. do the vectors lie in low memory?
+ */
 
 #  ifdef CONFIG_ARCH_LOWVECTORS
 
-  /* In this case, page table must lie at the top 16Kb of OCRAM. */
+/* In this case, page table must lie at the top 16Kb of OCRAM. */
 
 #    define PGTABLE_BASE_PADDR    (IMX_OCRAM_PBASE + IMX_OCRAM_SIZE - PGTABLE_SIZE)
 #    define PGTABLE_BASE_VADDR    (IMX_OCRAM_VBASE + IMX_OCRAM_SIZE - PGTABLE_SIZE)
 #    define PGTABLE_IN_HIGHSRAM   1
 
-  /* We will force the IDLE stack to precede the page table */
+/* We will force the IDLE stack to precede the page table */
 
 #    define IDLE_STACK_PBASE      (PGTABLE_BASE_PADDR - CONFIG_IDLETHREAD_STACKSIZE)
 #    define IDLE_STACK_VBASE      (PGTABLE_BASE_VADDR - CONFIG_IDLETHREAD_STACKSIZE)
 
 #  else /* CONFIG_ARCH_LOWVECTORS */
 
-  /* Otherwise, the vectors lie at another location (perhaps in NOR FLASH,
-   * perhaps elsewhere in OCRAM).  The page table will then be positioned
-   * at the first 16Kb of SRAM.
-   */
+/* Otherwise, the vectors lie at another location (perhaps in NOR FLASH,
+ * perhaps elsewhere in OCRAM).  The page table will then be positioned
+ * at the first 16Kb of SRAM.
+ */
 
 #    define PGTABLE_BASE_PADDR    IMX_OCRAM_PBASE
 #    define PGTABLE_BASE_VADDR    IMX_OCRAM_VBASE
 #    define PGTABLE_IN_LOWSRAM    1
 
-   /* We will force the IDLE stack to follow the page table */
+/* We will force the IDLE stack to follow the page table */
 
 #    define IDLE_STACK_PBASE      (PGTABLE_BASE_PADDR + PGTABLE_SIZE)
 #    define IDLE_STACK_VBASE      (PGTABLE_BASE_VADDR + PGTABLE_SIZE)
@@ -867,21 +877,21 @@
 
 #else /* !PGTABLE_BASE_PADDR || !PGTABLE_BASE_VADDR */
 
-  /* Sanity check.. if one is defined, both should be defined */
+/* Sanity check.. if one is defined, both should be defined */
 
 #  if !defined(PGTABLE_BASE_PADDR) || !defined(PGTABLE_BASE_VADDR)
 #    error "One of PGTABLE_BASE_PADDR or PGTABLE_BASE_VADDR is undefined"
 #  endif
 
-  /* The page table then lies at the beginning of the OSSRAM and
-   * the IDLE stack follows immediately.
-   */
+/* The page table then lies at the beginning of the OSSRAM and
+ * the IDLE stack follows immediately.
+ */
 
 #    define PGTABLE_BASE_PADDR    IMX_OCRAM_PBASE
 #    define PGTABLE_BASE_VADDR    IMX_OCRAM_VBASE
 #    define PGTABLE_IN_LOWSRAM    1
 
-   /* We will force the IDLE stack to follow the page table */
+/* We will force the IDLE stack to follow the page table */
 
 #    define IDLE_STACK_PBASE      (PGTABLE_BASE_PADDR + PGTABLE_SIZE)
 #    define IDLE_STACK_VBASE      (PGTABLE_BASE_VADDR + PGTABLE_SIZE)
@@ -1031,16 +1041,4 @@
 
 #endif
 
-/************************************************************************************
- * Public Types
- ************************************************************************************/
-
-/************************************************************************************
- * Public Data
- ************************************************************************************/
-
-/************************************************************************************
- * Public Functions
- ************************************************************************************/
-
 #endif /* __ARCH_ARM_SRC_IMX6_HARDWARE_IMX_MEMORYMAP_H */


[incubator-nuttx] 03/03: arch: imx6: Add imx_enet driver

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit ace6e70f5774ebf04f798b9d209eb947cd0eb3b3
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Wed Dec 23 19:27:49 2020 +0900

    arch: imx6: Add imx_enet driver
    
    Summary:
    - This commit adds imx_enet driver derived from imxrt_enet
    
    Impact:
    - imx6 only
    
    Testing:
    - Tested with sabre-6quad:netnsh
    - NOTE: telnetd works with QEMU
---
 arch/arm/src/imx6/Kconfig                          |   40 +
 arch/arm/src/imx6/Make.defs                        |    4 +
 arch/arm/src/imx6/hardware/imx_enet.h              |  701 ++++++
 arch/arm/src/imx6/imx_enet.c                       | 2549 ++++++++++++++++++++
 arch/arm/src/imx6/imx_enet.h                       |  108 +
 .../arm/imx6/sabre-6quad/configs/netnsh/defconfig  |   88 +
 6 files changed, 3490 insertions(+)

diff --git a/arch/arm/src/imx6/Kconfig b/arch/arm/src/imx6/Kconfig
index e9ad1e5..b71c49d 100644
--- a/arch/arm/src/imx6/Kconfig
+++ b/arch/arm/src/imx6/Kconfig
@@ -120,8 +120,47 @@ config IMX6_SPI2
 	default n
 	select SPI
 
+config IMX6_ENET
+	bool "Ethernet"
+	default n
+	select ARCH_HAVE_PHY
+	select ARCH_PHY_INTERRUPT
+	select ARCH_HAVE_NETDEV_STATISTICS
+
 endmenu # iMX Peripheral Selection
 
+menu "Ethernet Configuration"
+	depends on IMX6_ENET
+
+config IMX_ENET_NRXBUFFERS
+	int "Number Rx buffers"
+	default 6
+
+config IMX_ENET_NTXBUFFERS
+	int "Number Tx buffers"
+	default 2
+
+config IMX_ENET_ENHANCEDBD
+	bool # not optional
+	default n
+
+config IMX_ENET_NETHIFS
+	int  # Not optional
+	default 1
+
+config IMX_ENET_PHYINIT
+	bool "Board-specific PHY Initialization"
+	default n
+	---help---
+		Some boards require specialized initialization of the PHY before it
+		can be used.  This may include such things as configuring GPIOs,
+		resetting the PHY, etc.  If CONFIG_IMX_ENET_PHYINIT is defined in
+		the configuration then the board specific logic must provide
+		imx_phy_boardinitialize();  The i.MX6 ENET driver will call this
+		function one time before it first uses the PHY.
+
+endmenu # IMX_ENET
+
 config IMX_DDR_SIZE
 	int "Installed DRAM size (bytes)"
 	default 268435456
@@ -152,4 +191,5 @@ config IMX6_BOOT_SRAM
 	select BOOT_RUNFROMEXTSRAM
 
 endchoice # i.MX6 Boot Configuration
+
 endif # ARCH_CHIP_IMX6
diff --git a/arch/arm/src/imx6/Make.defs b/arch/arm/src/imx6/Make.defs
index eb84c44..bedf7fb 100644
--- a/arch/arm/src/imx6/Make.defs
+++ b/arch/arm/src/imx6/Make.defs
@@ -143,3 +143,7 @@ endif
 ifeq ($(CONFIG_IMX6_ECSPI),y)
 CHIP_CSRCS += imx_ecspi.c
 endif
+
+ifeq ($(CONFIG_IMX6_ENET),y)
+CHIP_CSRCS += imx_enet.c
+endif
diff --git a/arch/arm/src/imx6/hardware/imx_enet.h b/arch/arm/src/imx6/hardware/imx_enet.h
new file mode 100644
index 0000000..34a649c
--- /dev/null
+++ b/arch/arm/src/imx6/hardware/imx_enet.h
@@ -0,0 +1,701 @@
+/************************************************************************************
+ * arch/arm/src/imx6/hardware/imx_enet.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_IMX6_HARDWARE_IMX_ENET_H
+#define __ARCH_ARM_SRC_IMX6_HARDWARE_IMX_ENET_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+#define IMX_ENET_HAS_DBSWAP 1
+
+/* Register Offsets *****************************************************************/
+
+#define IMX_ENET_EIR_OFFSET      0x0004 /* Interrupt Event Register */
+#define IMX_ENET_EIMR_OFFSET     0x0008 /* Interrupt Mask Register */
+#define IMX_ENET_RDAR_OFFSET     0x0010 /* Receive Descriptor Active Register */
+#define IMX_ENET_TDAR_OFFSET     0x0014 /* Transmit Descriptor Active Register */
+#define IMX_ENET_ECR_OFFSET      0x0024 /* Ethernet Control Register */
+#define IMX_ENET_MMFR_OFFSET     0x0040 /* MII Management Frame Register */
+#define IMX_ENET_MSCR_OFFSET     0x0044 /* MII Speed Control Register */
+#define IMX_ENET_MIBC_OFFSET     0x0064 /* MIB Control Register */
+#define IMX_ENET_RCR_OFFSET      0x0084 /* Receive Control Register */
+#define IMX_ENET_TCR_OFFSET      0x00c4 /* Transmit Control Register */
+#define IMX_ENET_PALR_OFFSET     0x00e4 /* Physical Address Lower Register */
+#define IMX_ENET_PAUR_OFFSET     0x00e8 /* Physical Address Upper Register */
+#define IMX_ENET_OPD_OFFSET      0x00ec /* Opcode/Pause Duration Register */
+
+#if 0
+#define IMX_ENET_TXIC_OFFSET     0x00f0 /* Transmit Interrupt Coalescing Register */
+#define IMX_ENET_RXIC_OFFSET     0x0100 /* Receive Interrupt Coalescing Register */
+#endif
+
+#define IMX_ENET_IAUR_OFFSET     0x0118 /* Descriptor Individual Upper Address Register */
+#define IMX_ENET_IALR_OFFSET     0x011c /* Descriptor Individual Lower Address Register */
+#define IMX_ENET_GAUR_OFFSET     0x0120 /* Descriptor Group Upper Address Register */
+#define IMX_ENET_GALR_OFFSET     0x0124 /* Descriptor Group Lower Address Register */
+#define IMX_ENET_TFWR_OFFSET     0x0144 /* Transmit FIFO Watermark Register */
+#define IMX_ENET_RDSR_OFFSET     0x0180 /* Receive Descriptor Ring Start Register */
+#define IMX_ENET_TDSR_OFFSET     0x0184 /* Transmit Buffer Descriptor Ring Start Register */
+#define IMX_ENET_MRBR_OFFSET     0x0188 /* Maximum Receive Buffer Size Register */
+#define IMX_ENET_RSFL_OFFSET     0x0190 /* Receive FIFO Section Full Threshold */
+#define IMX_ENET_RSEM_OFFSET     0x0194 /* Receive FIFO Section Empty Threshold */
+#define IMX_ENET_RAEM_OFFSET     0x0198 /* Receive FIFO Almost Empty Threshold */
+#define IMX_ENET_RAFL_OFFSET     0x019c /* Receive FIFO Almost Full Threshold */
+#define IMX_ENET_TSEM_OFFSET     0x01a0 /* Transmit FIFO Section Empty Threshold */
+#define IMX_ENET_TAEM_OFFSET     0x01a4 /* Transmit FIFO Almost Empty Threshold */
+#define IMX_ENET_TAFL_OFFSET     0x01a8 /* Transmit FIFO Almost Full Threshold */
+#define IMX_ENET_TIPG_OFFSET     0x01ac /* Transmit Inter-Packet Gap */
+#define IMX_ENET_FTRL_OFFSET     0x01b0 /* Frame Truncation Length */
+#define IMX_ENET_TACC_OFFSET     0x01c0 /* Transmit Accelerator Function Configuration */
+#define IMX_ENET_RACC_OFFSET     0x01c4 /* Receive Accelerator Function Configuration */
+
+/* TODO: statistic registers: 0x02xx */
+
+#define IMX_ENET_ATCR_OFFSET     0x0400 /* Timer Control Register */
+#define IMX_ENET_ATVR_OFFSET     0x0404 /* Timer Value Register */
+#define IMX_ENET_ATOFF_OFFSET    0x0408 /* Timer Offset Register */
+#define IMX_ENET_ATPER_OFFSET    0x040c /* Timer Period Register */
+#define IMX_ENET_ATCOR_OFFSET    0x0410 /* Timer Correction Register */
+#define IMX_ENET_ATINC_OFFSET    0x0414 /* Time-Stamping Clock Period Register */
+#define IMX_ENET_ATSTMP_OFFSET   0x0418 /* Timestamp of Last Transmitted Frame */
+
+#define IMX_ENET_TGSR_OFFSET     0x0604 /* Timer Global Status Register */
+#define IMX_ENET_TCSR0_OFFSET    0x0608 /* Timer Control Status Register */
+#define IMX_ENET_TCCR0_OFFSET    0x060c /* Timer Compare Capture Register */
+#define IMX_ENET_TCSR1_OFFSET    0x0610 /* Timer Control Status Register */
+#define IMX_ENET_TCCR1_OFFSET    0x0614 /* Timer Compare Capture Register */
+#define IMX_ENET_TCSR2_OFFSET    0x0618 /* Timer Control Status Register */
+#define IMX_ENET_TCCR2_OFFSET    0x061c /* Timer Compare Capture Register */
+#define IMX_ENET_TCSR3_OFFSET    0x0620 /* Timer Control Status Register */
+#define IMX_ENET_TCCR3_OFFSET    0x0624 /* Timer Compare Capture Register */
+
+/* Register Addresses ***************************************************************/
+
+#define IMX_ENET_EIR             (IMX_ENET_VBASE+IMX_ENET_EIR_OFFSET)
+#define IMX_ENET_EIMR            (IMX_ENET_VBASE+IMX_ENET_EIMR_OFFSET)
+#define IMX_ENET_RDAR            (IMX_ENET_VBASE+IMX_ENET_RDAR_OFFSET)
+#define IMX_ENET_TDAR            (IMX_ENET_VBASE+IMX_ENET_TDAR_OFFSET)
+#define IMX_ENET_ECR             (IMX_ENET_VBASE+IMX_ENET_ECR_OFFSET)
+#define IMX_ENET_MMFR            (IMX_ENET_VBASE+IMX_ENET_MMFR_OFFSET)
+#define IMX_ENET_MSCR            (IMX_ENET_VBASE+IMX_ENET_MSCR_OFFSET)
+#define IMX_ENET_MIBC            (IMX_ENET_VBASE+IMX_ENET_MIBC_OFFSET)
+#define IMX_ENET_RCR             (IMX_ENET_VBASE+IMX_ENET_RCR_OFFSET)
+#define IMX_ENET_TCR             (IMX_ENET_VBASE+IMX_ENET_TCR_OFFSET)
+#define IMX_ENET_PALR            (IMX_ENET_VBASE+IMX_ENET_PALR_OFFSET)
+#define IMX_ENET_PAUR            (IMX_ENET_VBASE+IMX_ENET_PAUR_OFFSET)
+#define IMX_ENET_OPD             (IMX_ENET_VBASE+IMX_ENET_OPD_OFFSET)
+#define IMX_ENET_IAUR            (IMX_ENET_VBASE+IMX_ENET_IAUR_OFFSET)
+#define IMX_ENET_IALR            (IMX_ENET_VBASE+IMX_ENET_IALR_OFFSET)
+#define IMX_ENET_GAUR            (IMX_ENET_VBASE+IMX_ENET_GAUR_OFFSET)
+#define IMX_ENET_GALR            (IMX_ENET_VBASE+IMX_ENET_GALR_OFFSET)
+#define IMX_ENET_TFWR            (IMX_ENET_VBASE+IMX_ENET_TFWR_OFFSET)
+#define IMX_ENET_RDSR            (IMX_ENET_VBASE+IMX_ENET_RDSR_OFFSET)
+#define IMX_ENET_TDSR            (IMX_ENET_VBASE+IMX_ENET_TDSR_OFFSET)
+#define IMX_ENET_MRBR            (IMX_ENET_VBASE+IMX_ENET_MRBR_OFFSET)
+#define IMX_ENET_RSFL            (IMX_ENET_VBASE+IMX_ENET_RSFL_OFFSET)
+#define IMX_ENET_RSEM            (IMX_ENET_VBASE+IMX_ENET_RSEM_OFFSET)
+#define IMX_ENET_RAEM            (IMX_ENET_VBASE+IMX_ENET_RAEM_OFFSET)
+#define IMX_ENET_RAFL            (IMX_ENET_VBASE+IMX_ENET_RAFL_OFFSET)
+#define IMX_ENET_TSEM            (IMX_ENET_VBASE+IMX_ENET_TSEM_OFFSET)
+#define IMX_ENET_TAEM            (IMX_ENET_VBASE+IMX_ENET_TAEM_OFFSET)
+#define IMX_ENET_TAFL            (IMX_ENET_VBASE+IMX_ENET_TAFL_OFFSET)
+#define IMX_ENET_TIPG            (IMX_ENET_VBASE+IMX_ENET_TIPG_OFFSET)
+#define IMX_ENET_FTRL            (IMX_ENET_VBASE+IMX_ENET_FTRL_OFFSET)
+#define IMX_ENET_TACC            (IMX_ENET_VBASE+IMX_ENET_TACC_OFFSET)
+#define IMX_ENET_RACC            (IMX_ENET_VBASE+IMX_ENET_RACC_OFFSET)
+
+#define IMX_ENET_ATCR            (IMX_ENET_VBASE+IMX_ENET_ATCR_OFFSET)
+#define IMX_ENET_ATVR            (IMX_ENET_VBASE+IMX_ENET_ATVR_OFFSET)
+#define IMX_ENET_ATOFF           (IMX_ENET_VBASE+IMX_ENET_ATOFF_OFFSET)
+#define IMX_ENET_ATPER           (IMX_ENET_VBASE+IMX_ENET_ATPER_OFFSET)
+#define IMX_ENET_ATCOR           (IMX_ENET_VBASE+IMX_ENET_ATCOR_OFFSET)
+#define IMX_ENET_ATINC           (IMX_ENET_VBASE+IMX_ENET_ATINC_OFFSET)
+#define IMX_ENET_ATSTMP          (IMX_ENET_VBASE+IMX_ENET_ATSTMP_OFFSET)
+
+#define IMX_ENET_TGSR            (IMX_ENET_VBASE+IMX_ENET_TGSR_OFFSET)
+#define IMX_ENET_TCSR0           (IMX_ENET_VBASE+IMX_ENET_TCSR0_OFFSET)
+#define IMX_ENET_TCCR0           (IMX_ENET_VBASE+IMX_ENET_TCCR0_OFFSET)
+#define IMX_ENET_TCSR1           (IMX_ENET_VBASE+IMX_ENET_TCSR1_OFFSET)
+#define IMX_ENET_TCCR1           (IMX_ENET_VBASE+IMX_ENET_TCCR1_OFFSET)
+#define IMX_ENET_TCSR2           (IMX_ENET_VBASE+IMX_ENET_TCSR2_OFFSET)
+#define IMX_ENET_TCCR2           (IMX_ENET_VBASE+IMX_ENET_TCCR2_OFFSET)
+#define IMX_ENET_TCSR3           (IMX_ENET_VBASE+IMX_ENET_TCSR3_OFFSET)
+#define IMX_ENET_TCCR3           (IMX_ENET_VBASE+IMX_ENET_TCCR3_OFFSET)
+
+/* Register Bit Definitions *********************************************************/
+
+/* Interrupt Event Register, Interrupt Mask Register */
+
+/* Bits 0-14: Reserved */
+#define ENET_INT_TS_TIMER            (1 << 15) /* Bit 15: Timestamp timer */
+#define ENET_INT_TS_AVAIL            (1 << 16) /* Bit 16: Transmit timestamp available */
+#define ENET_INT_WAKEUP              (1 << 17) /* Bit 17: Node wake-up request indication */
+#define ENET_INT_PLR                 (1 << 18) /* Bit 18: Payload receive error */
+#define ENET_INT_UN                  (1 << 19) /* Bit 19: Transmit FIFO underrun */
+#define ENET_INT_RL                  (1 << 20) /* Bit 20: Collision Retry Limit */
+#define ENET_INT_LC                  (1 << 21) /* Bit 21: Late Collision */
+#define ENET_INT_EBERR               (1 << 22) /* Bit 22: Ethernet Bus Error */
+#define ENET_INT_MII                 (1 << 23) /* Bit 23: MII Interrupt */
+#define ENET_INT_RXB                 (1 << 24) /* Bit 24: Receive Buffer Interrupt */
+#define ENET_INT_RXF                 (1 << 25) /* Bit 25: Receive Frame Interrupt */
+#define ENET_INT_TXB                 (1 << 26) /* Bit 26: Transmit Buffer Interrupt */
+#define ENET_INT_TXF                 (1 << 27) /* Bit 27: Transmit Frame Interrupt */
+#define ENET_INT_GRA                 (1 << 28) /* Bit 28: Graceful Stop Complete */
+#define ENET_INT_BABT                (1 << 29) /* Bit 29: Babbling Transmit Error */
+#define ENET_INT_BABR                (1 << 30) /* Bit 30: Babbling Receive Error */
+                                               /* Bit 31: Reserved */
+
+/* Receive Descriptor Active Register */
+
+/* Bits 0-23: Reserved */
+#define ENET_RDAR                    (1 << 24) /* Bit 24: Receive descriptor active */
+                                               /* Bits 25-31: Reserved */
+
+/* Transmit Descriptor Active Register */
+
+/* Bits 0-23: Reserved */
+#define ENET_TDAR                    (1 << 24) /* Bit 24: Transmit descriptor active */
+                                               /* Bits 25-31: Reserved */
+
+/* Ethernet Control Register */
+
+#define ENET_ECR_RESET               (1 << 0)  /* Bit 0:  Ethernet MAC reset */
+#define ENET_ECR_ETHEREN             (1 << 1)  /* Bit 1:  Ethernet enable */
+#define ENET_ECR_MAGICEN             (1 << 2)  /* Bit 2:  Magic packet detection enable */
+#define ENET_ECR_SLEEP               (1 << 3)  /* Bit 3:  Sleep mode enable */
+#define ENET_ECR_EN1588              (1 << 4)  /* Bit 4:  EN1588 enable */
+                                               /* Bit 5: Reserved */
+#define ENET_ECR_DBGEN               (1 << 6)  /* Bit 6:  Debug enable */
+#define ENET_ECR_STOPEN              (1 << 7)  /* Bit 7:  STOPEN Signal Control */
+#ifdef IMX_ENET_HAS_DBSWAP
+#define ENET_ECR_DBSWP               (1 << 8)  /* Bit 8:  Swap bytes */
+#endif
+                                               /* Bits 9-31: Reserved */
+#define ECR_RESV_VAL                 (7 << 28) /* Reserve val to write */
+
+/* MII Management Frame Register */
+
+#define ENET_MMFR_DATA_SHIFT         (0)       /* Bits 0-15: Management frame data */
+#define ENET_MMFR_DATA_MASK          (0xffff << ENET_MMFR_DATA_SHIFT)
+#define ENET_MMFR_TA_SHIFT           (16)      /* Bits 16-17: Turn around */
+#define ENET_MMFR_TA_MASK            (3 << ENET_MMFR_TA_SHIFT)
+#define ENET_MMFR_RA_SHIFT           (18)      /* Bits 18-22: Register address */
+#define ENET_MMFR_RA_MASK            (31 << ENET_MMFR_RA_SHIFT)
+#define ENET_MMFR_PA_SHIFT           (23)      /* Bits 23-27: PHY address */
+#define ENET_MMFR_PA_MASK            (31 << ENET_MMFR_PA_SHIFT)
+#define ENET_MMFR_OP_SHIFT           (28)      /* Bits 28-29: Operation code */
+#define ENET_MMFR_OP_MASK            (3 << ENET_MMFR_OP_SHIFT)
+#define ENET_MMFR_OP_WRNOTMII        (0 << ENET_MMFR_OP_SHIFT) /* Write frame, not MII compliant */
+#define ENET_MMFR_OP_WRMII           (1 << ENET_MMFR_OP_SHIFT) /* Write frame, MII management frame */
+#define ENET_MMFR_OP_RDMII           (2 << ENET_MMFR_OP_SHIFT) /* Read frame, MII management frame */
+#define ENET_MMFR_OP_RdNOTMII        (3 << ENET_MMFR_OP_SHIFT) /* Read frame, not MII compliant */
+#define ENET_MMFR_ST_SHIFT           (30)                      /* Bits 30-31: Start of frame delimiter */
+#define ENET_MMFR_ST_MASK            (3 << ENET_MMFR_ST_SHIFT)
+
+/* MII Speed Control Register */
+
+/* Bit 0: Reserved */
+#define ENET_MSCR_MII_SPEED_SHIFT    (1)       /* Bits 1-6: MII speed */
+#define ENET_MSCR_MII_SPEED_MASK     (63 << ENET_MSCR_MII_SPEED_SHIFT)
+#define ENET_MSCR_DIS_PRE            (1 << 7)  /* Bit 7:  Disable preamble */
+#define ENET_MSCR_HOLDTIME_SHIFT     (8)       /* Bits 8-10: Holdtime on MDIO output */
+#define ENET_MSCR_HOLDTIME_MASK      (7 << ENET_MSCR_HOLDTIME_SHIFT)
+#define ENET_MSCR_HOLDTIME_1CYCLE    (0 << ENET_MSCR_HOLDTIME_SHIFT) /* 1 internal module clock cycle */
+#define ENET_MSCR_HOLDTIME_2CYCLES   (1 << ENET_MSCR_HOLDTIME_SHIFT) /* 2 internal module clock cycles */
+#define ENET_MSCR_HOLDTIME_3CYCLES   (2 << ENET_MSCR_HOLDTIME_SHIFT) /* 3 internal module clock cycles */
+#define ENET_MSCR_HOLDTIME_8CYCLES   (7 << ENET_MSCR_HOLDTIME_SHIFT) /* 8 internal module clock cycles */
+                                                                     /* Bits 11-31: Reserved */
+
+/* MIB Control Register */
+
+/* Bits 0-28: Reserved */
+#define ENET_MIBC_MIB_CLEAR          (1 << 29) /* Bit 29: MIB clear */
+#define ENET_MIBC_MIB_IDLE           (1 << 30) /* Bit 30: MIB idle */
+#define ENET_MIBC_MIB_DIS            (1 << 31) /* Bit 31: Disable MIB logic */
+
+/* Receive Control Register */
+
+#define ENET_RCR_LOOP                (1 << 0)  /* Bit 0:  Internal loopback */
+#define ENET_RCR_DRT                 (1 << 1)  /* Bit 1:  Disable receive on transmit */
+#define ENET_RCR_MII_MODE            (1 << 2)  /* Bit 2:  Media independent interface mode */
+#define ENET_RCR_PROM                (1 << 3)  /* Bit 3:  Promiscuous mode */
+#define ENET_RCR_BC_REJ              (1 << 4)  /* Bit 4:  Broadcast frame reject */
+#define ENET_RCR_FCE                 (1 << 5)  /* Bit 5:  Flow control enable */
+                                               /* Bits 6-7: Reserved */
+#define ENET_RCR_RMII_MODE           (1 << 8)  /* Bit 8: RMII mode enable */
+#define ENET_RCR_RMII_10T            (1 << 9)  /* Bit 9: Enables 10-Mbps mode of the RMII */
+                                               /* Bits 10-11: Reserved */
+#define ENET_RCR_PADEN               (1 << 12) /* Bit 12: Enable frame padding remove on receive */
+#define ENET_RCR_PAUFWD              (1 << 13) /* Bit 13: Terminate/forward pause frames */
+#define ENET_RCR_CRCFWD              (1 << 14) /* Bit 14: Terminate/forward received CRC */
+#define ENET_RCR_CFEN                (1 << 15) /* Bit 15: MAC control frame enable */
+#define ENET_RCR_MAX_FL_SHIFT        (16)      /* Bits 16-29: Maximum frame length */
+#define ENET_RCR_MAX_FL_MASK         (0x3fff << ENET_RCR_MAX_FL_SHIFT)
+#define ENET_RCR_NLC                 (1 << 30) /* Bit 30: Payload length check disable */
+#define ENET_RCR_GRS                 (1 << 31) /* Bit 31: Graceful receive stopped */
+
+/* Transmit Control Register */
+
+#define ENET_TCR_GTS                 (1 << 0)  /* Bit 0:  Graceful transmit stop */
+                                               /* Bit 1: Reserved */
+#define ENET_TCR_ADDINS              (1 << 8)  /* Bit 8:  Set MAC address on transmit */
+#define ENET_TCR_FDEN                (1 << 2)  /* Bit 2:  Full duplex enable */
+#define ENET_TCR_TFC_PAUSE           (1 << 3)  /* Bit 3:  Transmit frame control pause */
+#define ENET_TCR_RFC_PAUSE           (1 << 4)  /* Bit 4:  Receive frame control pause */
+#define ENET_TCR_ADDSEL_SHIFT        (5)       /* Bits 5-7: Source MAC address select on transmit */
+#define ENET_TCR_ADDSEL_MASK         (7 << ENET_TCR_ADDSEL_SHIFT)
+#define ENET_TCR_ADDSEL_PADDR12      (0 << ENET_TCR_ADDSEL_SHIFT) /* Node MAC address programmed on PADDR1/2 registers */
+#define ENET_TCR_CRCFWD              (1 << 9)                     /* Bit 9:  Forward frame from application with CRC */
+                                                                  /* Bits 10-31: Reserved */
+
+/* Physical Address Lower/Upper Register (32-bits of 48-address) */
+
+/* Physical Address Upper Register */
+
+#define ENET_PAUR_TYPE_SHIFT         (0)       /* Bits 0-15: Type field in PAUSE frame */
+#define ENET_PAUR_TYPE_MASK          (0xffff << ENET_PAUR_TYPE_MASK)
+#define ENET_PAUR_PADDR2_SHIFT       (16)      /* Bits 16-31: Bytes 4 and 5 of the 6-byte address */
+#define ENET_PAUR_PADDR2_MASK        (0xffff << ENET_PAUR_PADDR2_SHIFT)
+
+/* Opcode/Pause Duration Register */
+
+#define ENET_OPD_PAUSE_DUR_SHIFT     (0)       /* Bits 0-15: Pause duration */
+#define ENET_OPD_PAUSE_DUR_MASK      (0xffff << ENET_OPD_PAUSE_DUR_SHIFT)
+#define ENET_OPD_OPCODE_SHIFT        (16)      /* Bits 16-31: Opcode field in PAUSE frames */
+#define ENET_OPD_OPCODE_MASK         (0xffff << ENET_OPD_OPCODE_SHIFT)
+
+/* Descriptor Individual Upper/Lower Address Register
+ * (64-bit address in two 32-bit registers)
+ * Descriptor Group Upper/Lower Address Register
+ * (64-bit address in two 32-bit registers)
+ */
+
+#if 0
+/* Transmit Interrupt Coalescing Register */
+
+#define ENET_TXIC_ICTT_SHIFT         (0)       /* Bits 0-15: Interrupt coalescing timer threshold */
+#define ENET_TXIC_ICTT_SHIFT_MASK    (0xffff << ENET_TXIC_ICTT_SHIFT)
+                                               /* Bits 16-19: Reserved */
+#define ENET_TXIC_ICFT_SHIFT         (20)      /* Bits 0-15: Interrupt coalescing timer threshold */
+#define ENET_TXIC_ICFT_SHIFT_MASK    (0xff << ENET_TXIC_ICFT_SHIFT)
+#define ENET_TXIC_ICTT_ICCS          (1 << 30) /* Bit 30: Interrupt Coalescing Timer Clock Source Select */
+#define ENET_TXIC_ICTT_ICEN          (1 << 31) /* Bit 31: Eable/disabel Interrupt Coalescing */
+
+/* Receive Interrupt Coalescing Register */
+
+#define ENET_RXIC_ICTT_SHIFT         (0)       /* Bits 0-15: Interrupt coalescing timer threshold */
+#define ENET_RXIC_ICTT_SHIFT_MASK    (0xffff << ENET_TXIC_ICTT_SHIFT)
+                                               /* Bits 16-19: Reserved */
+#define ENET_RXIC_ICFT_SHIFT         (20)      /* Bits 0-15: Interrupt coalescing timer threshold */
+#define ENET_RXIC_ICFT_SHIFT_MASK    (0xff << ENET_TXIC_ICFT_SHIFT)
+#define ENET_RXIC_ICTT_ICCS          (1 << 30) /* Bit 30: Interrupt Coalescing Timer Clock Source Select */
+#define ENET_RXIC_ICTT_ICEN          (1 << 31) /* Bit 31: Eable/disabel Interrupt Coalescing */
+
+#endif /* if 0 */
+
+/* Transmit FIFO Watermark Register */
+
+#define ENET_TFWR_TFWR_SHIFT         (0)       /* Bits 0-5: Transmit FIFO write */
+                                               /* Bits 6-7: Reserved */
+#define ENET_TFWR_TFWR_MASK          (63 << ENET_TFWR_TFWR_SHIFT)
+#define ENET_TFWR_STRFWD             (1 << 8)  /* Bit 8: Store and forward enable */
+                                               /* Bits 9-31: Reserved */
+
+/* Receive Descriptor Ring Start Register */
+
+/* Bits 0-2: Reserved */
+#define ENET_RDSR_SHIFT              (3)       /* Bits 3-31: Start of the receive buffer descriptor queue */
+#define ENET_RDSR_MASK               (0xfffffff8)
+
+/* Transmit Buffer Descriptor Ring Start Register */
+
+/* Bits 0-2: Reserved */
+#define ENET_TDSR_SHIFT              (3)       /* Bits 3-31: Start of the transmit buffer descriptor queue */
+#define ENET_TDSR_MASK               (0xfffffff8)
+
+/* Maximum Receive Buffer Size Register */
+
+/* Bits 14-31: Reserved */
+#define ENET_MRBR_SHIFT              (4)       /* Bits 4-11: Receive buffer size in bytes */
+#define ENET_MRBR_MASK               (0x7f << ENET_MRBR_SHIFT)
+                                               /* Bits 0-3: Reserved */
+
+/* Receive FIFO Section Full Threshold */
+
+/* Bits 8-31: Reserved */
+#define ENET_RSFL_SHIFT              (0)       /* Bits 0-7: Value of receive FIFO section full threshold */
+#define ENET_RSFL_MASK               (0xff << ENET_RSFL_SHIFT)
+
+/* Receive FIFO Section Empty Threshold */
+
+#define ENET_RSEM_SHIFT              (0)       /* Bits 0-7: Value of the receive FIFO section empty threshold */
+#define ENET_RSEM_MASK               (0xff << ENET_RSEM_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Receive FIFO Almost Empty Threshold */
+
+#define ENET_RAEM_SHIFT              (0)       /* Bits 0-7: Value of the receive FIFO almost empty threshold */
+#define ENET_RAEM_MASK               (0xff << ENET_RAEM_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Receive FIFO Almost Full Threshold */
+
+#define ENET_RAFL_SHIFT              (0)       /* Bits 0-7: Value of the receive FIFO almost full threshold */
+#define ENET_RAFL_MASK               (0xff << ENET_RAFL_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Transmit FIFO Section Empty Threshold */
+
+#define ENET_TSEM_SHIFT              (0)       /* Bits 0-7: Value of the transmit FIFO section empty threshold */
+#define ENET_TSEM_MASK               (0xff << ENET_TSEM_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Transmit FIFO Almost Empty Threshold */
+
+#define ENET_TAEM_SHIFT              (0)       /* Bits 0-7: Value of the transmit FIFO section empty threshold */
+#define ENET_TAEM_MASK               (0xff << ENET_TAEM_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Transmit FIFO Almost Full Threshold */
+
+#define ENET_TAFL_SHIFT              (0)       /* Bits 0-7: Value of the transmit FIFO section empty threshold */
+#define ENET_TAFL_MASK               (0xff << ENET_TAFL_SHIFT)
+                                               /* Bits 8-31: Reserved */
+
+/* Transmit Inter-Packet Gap */
+
+#define ENET_TIPG_SHIFT              (0)       /* Bits 0-4: Value of the transmit FIFO section empty threshold */
+#define ENET_TIPG_MASK               (31 << ENET_TIPG_SHIFT)
+                                               /* Bits 5-31: Reserved */
+
+/* Frame Truncation Length */
+
+#define ENET_FTRL_SHIFT              (0)       /* Bits 0-13: Value of the transmit FIFO section empty threshold */
+#define ENET_FTRL_MASK               (0x3fff << ENET_FTRL_SHIFT)
+                                               /* Bits 14-31: Reserved */
+
+/* Transmit Accelerator Function Configuration */
+
+#define ENET_TACC_SHIFT16            (1 << 0)  /* Bit 0:  TX FIFO shift-16 */
+                                               /* Bits 1-2: Reserved */
+#define ENET_TACC_IPCHK              (1 << 3)  /* Bit 3:  Enables insertion of IP header checksum */
+#define ENET_TACC_PROCHK             (1 << 4)  /* Bit 4:  Enables insertion of protocol checksum */
+                                               /* Bits 5-31: Reserved */
+
+/* Receive Accelerator Function Configuration */
+
+#define ENET_RACC_PADREM             (1 << 0)  /* Bit 0: Enable padding removal for short IP frames */
+#define ENET_RACC_IPDIS              (1 << 1)  /* Bit 1: Enable discard of frames with wrong IPv4 header checksum */
+#define ENET_RACC_PRODIS             (1 << 2)  /* Bit 2: Enable discard of frames with wrong protocol checksum */
+                                               /* Bits 3-5: Reserved */
+#define ENET_RACC_LINEDIS            (1 << 6)  /* Bit 6: Enable discard of frames with MAC layer errors */
+#define ENET_RACC_SHIFT16            (1 << 7)  /* Bit 7: RX FIFO shift-16 */
+                                               /* Bits 8-31: Reserved */
+
+/* Timer Control Register */
+
+#define ENET_ATCR_EN                 (1 << 0)  /* Bit 0:  Enable timer */
+                                               /* Bit 1:  Reserved */
+#define ENET_ATCR_OFFEN              (1 << 2)  /* Bit 2:  Enable one-shot offset event */
+#define ENET_ATCR_OFFRST             (1 << 3)  /* Bit 3:  Reset timer on offset event */
+#define ENET_ATCR_PEREN              (1 << 4)  /* Bit 4:  Enable periodical event */
+                                               /* Bits 5-6: Reserved */
+#define ENET_ATCR_PINPER             (1 << 7)  /* Bit 7:  Enables event signal output assertion on period event */
+                                               /* Bit 8:  Reserved */
+#define ENET_ATCR_RESTART            (1 << 9)  /* Bit 9:  Reset timer */
+                                               /* Bit 10: Reserved */
+#define ENET_ATCR_CAPTURE            (1 << 11) /* Bit 11: Capture timer value */
+                                               /* Bit 12: Reserved */
+#define ENET_ATCR_SLAVE              (1 << 13) /* Bit 13: Enable timer slave mode */
+                                               /* Bits 14-31: Reserved */
+
+/* Timer Value Register (32-bit timer value)
+ * Timer Offset Register (32-bit offset value)
+ * Timer Period Register (32-bit timer period)
+ */
+
+/* Timer Correction Register */
+
+#define ENET_ATCOR_MASK              (0x7fffffff) /* Bits 0-3: Correction counter wrap-around value */
+                                                  /* Bit 31: Reserved */
+
+/* Time-Stamping Clock Period Register */
+
+#define ENET_ATINC_INC_SHIFT         (0)       /* Bits 0-6: Clock period of the timestamping clock (ts_clk) in nanoseconds */
+#define ENET_ATINC_INC_MASK          (0x7f << ENET_ATINC_INC_SHIFT)
+                                               /* Bit 7: Reserved */
+#define ENET_ATINC_INC_CORR_SHIFT    (8)       /* Bits 8-14: Correction increment value */
+#define ENET_ATINC_INC_CORR_MASK     (0x7f << ENET_ATINC_INC_CORR_SHIFT)
+                                               /* Bits 15-31: Reserved */
+
+/* Timestamp of Last Transmitted Frame (32-bit timestamp) */
+
+/* Timer Global Status Register */
+
+#define ENET_TGSR_TF0                (1 << 0)  /* Bit 0:  Copy of Timer Flag for channel 0 */
+#define ENET_TGSR_TF1                (1 << 1)  /* Bit 1:  Copy of Timer Flag for channel 1 */
+#define ENET_TGSR_TF2                (1 << 2)  /* Bit 2:  Copy of Timer Flag for channel 2 */
+#define ENET_TGSR_TF3                (1 << 3)  /* Bit 3:  Copy of Timer Flag for channel 3 */
+                                               /* Bits 14-31: Reserved */
+
+/* Timer Control Status Register n */
+
+#define ENET_TCSR_TDRE               (1 << 0)  /* Bit 0:  Timer DMA Request Enable */
+                                               /* Bit 1: Reserved */
+#define ENET_TCSR_TMODE_SHIFT        (2)       /* Bits 2-5: Timer Mode */
+#define ENET_TCSR_TMODE_MASK         (15 << ENET_TCSR_TMODE_SHIFT)
+#define ENET_TCSR_TMODE_DISABLED     (0 << ENET_TCSR_TMODE_SHIFT)  /* Disabled */
+#define ENET_TCSR_TMODE_ICRISING     (1 << ENET_TCSR_TMODE_SHIFT)  /* Input Capture on rising edge */
+#define ENET_TCSR_TMODE_ICFALLLING   (2 << ENET_TCSR_TMODE_SHIFT)  /* Input Capture on falling edge */
+#define ENET_TCSR_TMODE_ICBOTH       (3 << ENET_TCSR_TMODE_SHIFT)  /* Input Capture on both edges */
+#define ENET_TCSR_TMODE_OCSW         (4 << ENET_TCSR_TMODE_SHIFT)  /* Output Compare, S/W only */
+#define ENET_TCSR_TMODE_OCTOGGLE     (5 << ENET_TCSR_TMODE_SHIFT)  /* Output Compare, toggle on compare */
+#define ENET_TCSR_TMODE_OCCLR        (6 << ENET_TCSR_TMODE_SHIFT)  /* Output Compare, clear on compare */
+#define ENET_TCSR_TMODE_OCSET        (7 << ENET_TCSR_TMODE_SHIFT)  /*  Output Compare, set on compare */
+#define ENET_TCSR_TMODE_OCSETCLR     (9 << ENET_TCSR_TMODE_SHIFT)  /* Output Compare, set on compare, clear on overflow */
+#define ENET_TCSR_TMODE_OCCLRSET     (10 << ENET_TCSR_TMODE_SHIFT) /*  Output Compare, clear on compare, set on overflow */
+#define ENET_TCSR_TMODE_PCPULSEL     (14 << ENET_TCSR_TMODE_SHIFT) /* Output Compare, pulse low on compare */
+#define ENET_TCSR_TMODE_PCPULSEH     (15 << ENET_TCSR_TMODE_SHIFT) /* Output Compare, pulse high on compare */
+
+#define ENET_TCSR_TIE                (1 << 6)  /* Bit 6:  Timer interrupt enable */
+#define ENET_TCSR_TF                 (1 << 7)  /* Bit 7:  Timer Flag */
+                                               /* Bits 8-31: Reserved */
+
+/* Timer Compare Capture Register (32-bit compare value) */
+
+/* Buffer Descriptors ***************************************************************/
+
+/* Endian-independent descriptor offsets */
+
+#define DESC_STATUS1_OFFSET          (0)
+#define DESC_LENGTH_OFFSET           (2)
+#define DESC_DATAPTR_OFFSET          (4)
+#define DESC_LEGACY_LEN              (8)
+
+#define DESC_STATUS2_OFFSET          (8)
+#define DESC_LENPROTO_OFFSET         (12)
+#define DESC_CHECKSUM_OFFSET         (14)
+#define DESC_BDU_OFFSET              (16)
+#define DESC_TIMESTAMP_OFFSET        (20)
+#define DESC_ENHANCED_LEN            (32)
+
+/* Legacy/Common TX Buffer Descriptor Bit Definitions.
+ *
+ *   The descriptors are represented by structures  Unfortunately, when the
+ *   structures are overlaid on the data, the bytes are reversed because
+ *   the underlying hardware writes the data in big-endian byte order.
+ */
+
+#ifdef IMX_ENET_HAS_DBSWAP
+# ifndef CONFIG_ENDIAN_BIG
+#  define IMX_USE_DBSWAP
+# endif
+#else
+# ifndef CONFIG_ENDIAN_BIG
+#  define IMX_BUFFERS_SWAP
+# endif
+#endif
+
+#ifndef IMX_BUFFERS_SWAP
+#  define TXDESC_ABC                 (1 << 9)  /* Legacy */
+#  define TXDESC_TC                  (1 << 10) /* Common */
+#  define TXDESC_L                   (1 << 11) /* Common */
+#  define TXDESC_TO2                 (1 << 12) /* Common */
+#  define TXDESC_W                   (1 << 13) /* Common */
+#  define TXDESC_TO1                 (1 << 14) /* Common */
+#  define TXDESC_R                   (1 << 15) /* Common */
+#else
+#  define TXDESC_ABC                 (1 << 1)  /* Legacy */
+#  define TXDESC_TC                  (1 << 2)  /* Common */
+#  define TXDESC_L                   (1 << 3)  /* Common */
+#  define TXDESC_TO2                 (1 << 4)  /* Common */
+#  define TXDESC_W                   (1 << 5)  /* Common */
+#  define TXDESC_TO1                 (1 << 6)  /* Common */
+#  define TXDESC_R                   (1 << 7)  /* Common */
+#endif
+
+/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
+
+#ifndef IMX_BUFFERS_SWAP
+#  define TXDESC_TSE                 (1 << 8)
+#  define TXDESC_OE                  (1 << 9)
+#  define TXDESC_LCE                 (1 << 10)
+#  define TXDESC_FE                  (1 << 11)
+#  define TXDESC_EE                  (1 << 12)
+#  define TXDESC_UE                  (1 << 13)
+#  define TXDESC_TXE                 (1 << 15)
+
+#  define TXDESC_IINS                (1 << 27)
+#  define TXDESC_PINS                (1 << 28)
+#  define TXDESC_TS                  (1 << 29)
+#  define TXDESC_INT                 (1 << 30)
+
+#  define TXDESC_BDU                 (1 << 31)
+#else
+#  define TXDESC_IINS                (1 << 3)
+#  define TXDESC_PINS                (1 << 4)
+#  define TXDESC_TS                  (1 << 5)
+#  define TXDESC_INT                 (1 << 6)
+
+#  define TXDESC_TSE                 (1 << 16)
+#  define TXDESC_OE                  (1 << 17)
+#  define TXDESC_LCE                 (1 << 18)
+#  define TXDESC_FE                  (1 << 19)
+#  define TXDESC_EE                  (1 << 20)
+#  define TXDESC_UE                  (1 << 21)
+#  define TXDESC_TXE                 (1 << 23)
+
+#  define TXDESC_BDU                 (1 << 7)
+#endif
+
+/* Legacy (and Common) RX Buffer Descriptor Bit Definitions */
+
+#ifndef IMX_BUFFERS_SWAP
+#  define RXDESC_TR                  (1 << 0)
+#  define RXDESC_OV                  (1 << 1)
+#  define RXDESC_CR                  (1 << 2)
+#  define RXDESC_NO                  (1 << 4)
+#  define RXDESC_LG                  (1 << 5)
+#  define RXDESC_MC                  (1 << 6)
+#  define RXDESC_BC                  (1 << 7)
+#  define RXDESC_M                   (1 << 8)
+#  define RXDESC_L                   (1 << 11)
+#  define RXDESC_R02                 (1 << 12)
+#  define RXDESC_W                   (1 << 13)
+#  define RXDESC_R01                 (1 << 14)
+#  define RXDESC_E                   (1 << 15)
+#else
+#  define RXDESC_M                   (1 << 0)
+#  define RXDESC_L                   (1 << 3)
+#  define RXDESC_R02                 (1 << 4)
+#  define RXDESC_W                   (1 << 5)
+#  define RXDESC_R01                 (1 << 6)
+#  define RXDESC_E                   (1 << 7)
+#  define RXDESC_TR                  (1 << 8)
+#  define RXDESC_OV                  (1 << 9)
+#  define RXDESC_CR                  (1 << 10)
+#  define RXDESC_NO                  (1 << 12)
+#  define RXDESC_LG                  (1 << 13)
+#  define RXDESC_MC                  (1 << 14)
+#  define RXDESC_BC                  (1 << 15)
+#endif
+
+/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
+
+#ifndef IMX_BUFFERS_SWAP
+#  define RXDESC_FRAG                (1 << 0)
+#  define RXDESC_IPV6                (1 << 1)
+#  define RXDESC_VLAN                (1 << 2)
+#  define RXDESC_PCR                 (1 << 4)
+#  define RXDESC_ICE                 (1 << 5)
+#  define RXDESC_INT                 (1 << 23)
+#  define RXDESC_UC                  (1 << 24)
+#  define RXDESC_CE                  (1 << 25)
+#  define RXDESC_PE                  (1 << 26)
+#  define RXDESC_ME                  (1 << 31)
+
+#  define RXDESC_BDU                 (1 << 31)
+#else
+#  define RXDESC_UC                  (1 << 0)
+#  define RXDESC_CE                  (1 << 1)
+#  define RXDESC_PE                  (1 << 2)
+#  define RXDESC_ME                  (1 << 7)
+#  define RXDESC_INT                 (1 << 15)
+#  define RXDESC_FRAG                (1 << 24)
+#  define RXDESC_IPV6                (1 << 25)
+#  define RXDESC_VLAN                (1 << 26)
+#  define RXDESC_PCR                 (1 << 28)
+#  define RXDESC_ICE                 (1 << 29)
+
+#  define RXDESC_BDU                 (1 << 7)
+#endif
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/* Buffer Descriptors ***************************************************************/
+
+/* Legacy Buffer Descriptor */
+
+#ifdef CONFIG_ENET_ENHANCEDBD
+#ifdef IMX_USE_DBSWAP
+/* When DBSWP is used to swap the bytes in hardware, it is done 32-bits
+ * at a time.  Therefore, all 16 bit elements need to be swapped to
+ * compensate.
+ */
+
+struct enet_desc_s
+{
+  uint16_t length;      /* Data length */
+  uint16_t status1;     /* Control and status */
+  uint8_t  *data;       /* Buffer address */
+  uint32_t status2;     /* Extended status */
+  uint16_t checksum;    /* Payload checksum */
+  uint16_t lenproto;    /* Header length + Protocol type */
+  uint32_t bdu;         /* BDU */
+  uint32_t timestamp;   /* Time stamp */
+  uint32_t reserved1;   /* unused */
+  uint32_t reserved2;   /* unused */
+};
+#else
+struct enet_desc_s
+{
+  uint16_t status1;     /* Control and status */
+  uint16_t length;      /* Data length */
+  uint8_t  *data;       /* Buffer address */
+  uint32_t status2;     /* Extended status */
+  uint16_t lenproto;    /* Header length + Protocol type */
+  uint16_t checksum;    /* Payload checksum */
+  uint32_t bdu;         /* BDU */
+  uint32_t timestamp;   /* Time stamp */
+  uint32_t reserved1;   /* unused */
+  uint32_t reserved2;   /* unused */
+};
+#endif /* IMX_USE_DBSWAP */
+#else /* CONFIG_ENET_ENHANCEDBD */
+#ifdef IMX_USE_DBSWAP
+struct enet_desc_s
+{
+  uint16_t length;      /* Data length */
+  uint16_t status1;     /* Control and status */
+  uint8_t  *data;       /* Buffer address */
+};
+#else
+struct enet_desc_s
+{
+  uint16_t status1;     /* Control and status */
+  uint16_t length;      /* Data length */
+  uint8_t  *data;       /* Buffer address */
+};
+#endif /* IMX_USE_DBSWAP */
+#endif /* CONFIG_ENET_ENHANCEDBD */
+
+#endif /* __ARCH_ARM_SRC_IMX6_HARDWARE_IMX_ENET_H */
diff --git a/arch/arm/src/imx6/imx_enet.c b/arch/arm/src/imx6/imx_enet.c
new file mode 100644
index 0000000..e460e6e
--- /dev/null
+++ b/arch/arm/src/imx6/imx_enet.c
@@ -0,0 +1,2549 @@
+/****************************************************************************
+ * arch/arm/src/imx6/imx_enet.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <nuttx/wdog.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/signal.h>
+#include <nuttx/net/mii.h>
+#include <nuttx/net/arp.h>
+#include <nuttx/net/phy.h>
+#include <nuttx/net/netdev.h>
+
+#ifdef CONFIG_NET_PKT
+#  include <nuttx/net/pkt.h>
+#endif
+
+#include "arm_arch.h"
+#include "gic.h"
+#include "chip.h"
+#include "imx_config.h"
+#include "hardware/imx_enet.h"
+#include "hardware/imx_ccm.h"
+#include "hardware/imx_pinmux.h"
+
+#if 0
+#include "imx_periphclks.h"
+#endif
+
+#include "imx_gpio.h"
+#include "imx_enet.h"
+
+#ifdef CONFIG_IMX6_ENET
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If processing is not done at the interrupt level, then work queue support
+ * is required.
+ */
+
+#if !defined(CONFIG_SCHED_WORKQUEUE)
+#  error Work queue support is required
+#else
+
+  /* Select work queue.  Always use the LP work queue if available.  If not,
+   * then LPWORK will re-direct to the HP work queue.
+   *
+   * NOTE:  However, the network should NEVER run on the high priority work
+   * queue!  That queue is intended only to service short back end interrupt
+   * processing that never suspends.  Suspending the high priority work queue
+   * may bring the system to its knees!
+   */
+
+#  define ETHWORK LPWORK
+#endif
+
+/* CONFIG_IMX_ENET_NETHIFS determines the number of physical interfaces
+ * that will be supported.
+ */
+
+#if CONFIG_IMX_ENET_NETHIFS != 1
+#  error "CONFIG_IMX_ENET_NETHIFS must be one for now"
+#endif
+
+#if CONFIG_IMX_ENET_NTXBUFFERS < 1
+#  error "Need at least one TX buffer"
+#endif
+
+#if CONFIG_IMX_ENET_NRXBUFFERS < 1
+#  error "Need at least one RX buffer"
+#endif
+
+#define NENET_NBUFFERS \
+  (CONFIG_IMX_ENET_NTXBUFFERS + CONFIG_IMX_ENET_NRXBUFFERS)
+
+/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
+ * second.
+ */
+
+#define IMX_WDDELAY     (1 * CLK_TCK)
+
+/* Align assuming that the D-Cache is enabled (probably 32-bytes).
+ *
+ * REVISIT: The size of descriptors and buffers must also be in even units
+ * of the cache line size  That is because the operations to clean and
+ * invalidate the cache will operate on a full 32-byte cache line.  If
+ * CONFIG_ENET_ENHANCEDBD is selected, then the size of the descriptor is
+ * 32-bytes (and probably already the correct size for the cache line);
+ * otherwise, the size of the descriptors much smaller, only 8 bytes.
+ */
+
+#define ENET_ALIGN        32 /* TODO */
+#define ENET_ALIGN_MASK   (ENET_ALIGN - 1)
+#define ENET_ALIGN_UP(n)  (((n) + ENET_ALIGN_MASK) & ~ENET_ALIGN_MASK)
+
+/* TX timeout = 1 minute */
+
+#define IMX_TXTIMEOUT   (60 * CLK_TCK)
+#define MII_MAXPOLLS      (0x1ffff)
+#define LINK_WAITUS       (500 * 1000)
+#define LINK_NLOOPS       (10)
+
+/* PHY definitions.
+ *
+ * The selected PHY must be selected from the drivers/net/Kconfig PHY menu.
+ * A description of the PHY must be provided here.  That description must
+ * include:
+ *
+ * 1. BOARD_PHY_NAME: A PHY name string (for debug output),
+ * 2. BOARD_PHYID1 and BOARD_PHYID2: The PHYID1 and PHYID2 values (from
+ *    include/nuttx/net/mii.h)
+ * 3. BOARD_PHY_STATUS:  The address of the status register to use when
+ *    querying link status (from include/nuttx/net/mii.h)
+ * 4. BOARD_PHY_ADDRThe PHY broadcast address of 0 is selected.  This
+ *    should be fine as long as there is only a single PHY.
+ * 5. BOARD_PHY_10BASET:  A macro that can convert the status register
+ *    value into a boolean: true=10Base-T, false=Not 10Base-T
+ * 6. BOARD_PHY_100BASET:  A macro that can convert the status register
+ *    value into a boolean: true=100Base-T, false=Not 100Base-T
+ * 7. BOARD_PHY_ISDUPLEX:  A macro that can convert the status register
+ *    value into a boolean: true=duplex mode, false=half-duplex mode
+ *
+ */
+
+/* TODO:
+ * KSZ9021RN gigabit ethernet phy for sabrelite
+ * AR8031 gigabit ethernet phy for sabre-6quad
+ */
+
+#if defined(CONFIG_ETH0_PHY_KSZ8081)
+#  define BOARD_PHY_NAME        "KSZ8081"
+#  define BOARD_PHYID1          MII_PHYID1_KSZ8081
+#  define BOARD_PHYID2          MII_PHYID2_KSZ8081
+#  define BOARD_PHY_STATUS      MII_KSZ8081_PHYCTRL1
+#  define BOARD_PHY_ADDR        (0)
+#  define BOARD_PHY_10BASET(s)  (((s) & MII_PHYCTRL1_MODE_10HDX) != 0)
+#  define BOARD_PHY_100BASET(s) (((s) & MII_PHYCTRL1_MODE_100HDX) != 0)
+#  define BOARD_PHY_ISDUPLEX(s) (((s) & MII_PHYCTRL1_MODE_DUPLEX) != 0)
+#elif defined(CONFIG_ETH0_PHY_LAN8720)
+#  define BOARD_PHY_NAME        "LAN8720"
+#  define BOARD_PHYID1          MII_PHYID1_LAN8720
+#  define BOARD_PHYID2          MII_PHYID2_LAN8720
+#  define BOARD_PHY_STATUS      MII_LAN8720_SCSR
+#  define BOARD_PHY_ADDR        (1)
+#  define BOARD_PHY_10BASET(s)  (((s)&MII_LAN8720_SPSCR_10MBPS) != 0)
+#  define BOARD_PHY_100BASET(s) (((s)&MII_LAN8720_SPSCR_100MBPS) != 0)
+#  define BOARD_PHY_ISDUPLEX(s) (((s)&MII_LAN8720_SPSCR_DUPLEX) != 0)
+#else
+#  error "Unrecognized or missing PHY selection"
+#endif
+
+/* Estimate the MII_SPEED in order to get an MDC close to 2.5MHz,
+ * based on the internal module (ENET) clock:
+ *
+ *   MII_SPEED = ENET_FREQ/5000000 -1
+ *
+ * For example, if ENET_FREQ_MHZ=120 (MHz):
+ *
+ *   MII_SPEED = 120000000/5000000 -1
+ *             = 23
+ */
+
+#define IMX_MII_SPEED  0x38 /* 100Mbs. Revisit and remove hardcoded value */
+#if IMX_MII_SPEED > 63
+#  error "IMX_MII_SPEED is out-of-range"
+#endif
+
+/* Interrupt groups */
+
+#define RX_INTERRUPTS     (ENET_INT_RXF | ENET_INT_RXB)
+#define TX_INTERRUPTS      ENET_INT_TXF
+#define ERROR_INTERRUPTS  (ENET_INT_UN    | ENET_INT_RL   | ENET_INT_LC | \
+                           ENET_INT_EBERR | ENET_INT_BABT | ENET_INT_BABR)
+
+/* The subset of errors that require us to reset the hardware - this list
+ * may need to be revisited if it's found that some error above leads to a
+ * locking up of the Ethernet interface.
+ */
+
+#define CRITICAL_ERROR    (ENET_INT_UN | ENET_INT_RL | ENET_INT_EBERR)
+
+/* This is a helper pointer for accessing
+ * the contents of the Ethernet header
+ */
+
+#define BUF ((struct eth_hdr_s *)priv->dev.d_buf)
+
+#define IMX_BUF_SIZE  ENET_ALIGN_UP(CONFIG_NET_ETH_PKTSIZE)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* The imx_driver_s encapsulates all state information for a single hardware
+ * interface
+ */
+
+struct imx_driver_s
+{
+  bool bifup;                  /* true:ifup false:ifdown */
+  uint8_t txtail;              /* The oldest busy TX descriptor */
+  uint8_t txhead;              /* The next TX descriptor to use */
+  uint8_t rxtail;              /* The next RX descriptor to use */
+  uint8_t phyaddr;             /* Selected PHY address */
+  struct wdog_s txpoll;        /* TX poll timer */
+  struct wdog_s txtimeout;     /* TX timeout timer */
+  struct work_s irqwork;       /* For deferring interrupt work to the work queue */
+  struct work_s pollwork;      /* For deferring poll work to the work queue */
+  struct enet_desc_s *txdesc;  /* A pointer to the list of TX descriptor */
+  struct enet_desc_s *rxdesc;  /* A pointer to the list of RX descriptors */
+
+  /* This holds the information visible to the NuttX network */
+
+  struct net_driver_s dev;     /* Interface understood by the network */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct imx_driver_s g_enet[CONFIG_IMX_ENET_NETHIFS];
+
+/* The DMA descriptors.  A unaligned uint8_t is used to allocate the
+ * memory; 16 is added to assure that we can meet the descriptor alignment
+ * requirements.
+ */
+
+static uint8_t g_desc_pool[NENET_NBUFFERS * sizeof(struct enet_desc_s)]
+               __attribute__((aligned(ENET_ALIGN)));
+
+/* The DMA buffers.  Again, A unaligned uint8_t is used to allocate the
+ * memory; 16 is added to assure that we can meet the descriptor alignment
+ * requirements.
+ */
+
+static uint8_t g_buffer_pool[NENET_NBUFFERS * IMX_BUF_SIZE]
+               __attribute__((aligned(ENET_ALIGN)));
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Utility functions */
+
+#ifndef IMXRT_BUFFERS_SWAP
+#  define imx_swap32(value) (value)
+#  define imx_swap16(value) (value)
+#else
+#if 0 /* Use builtins if the compiler supports them */
+static inline uint32_t imx_swap32(uint32_t value);
+static inline uint16_t imx_swap16(uint16_t value);
+#else
+#  define imx_swap32 __builtin_bswap32
+#  define imx_swap16 __builtin_bswap16
+#endif
+#endif
+
+/* Common TX logic */
+
+static bool imx_txringfull(FAR struct imx_driver_s *priv);
+static int  imx_transmit(FAR struct imx_driver_s *priv);
+static int  imx_txpoll(struct net_driver_s *dev);
+
+/* Interrupt handling */
+
+static void imx_dispatch(FAR struct imx_driver_s *priv);
+static void imx_receive(FAR struct imx_driver_s *priv);
+static void imx_txdone(FAR struct imx_driver_s *priv);
+
+static void imx_enet_interrupt_work(FAR void *arg);
+static int  imx_enet_interrupt(int irq, FAR void *context, FAR void *arg);
+
+/* Watchdog timer expirations */
+
+static void imx_txtimeout_work(FAR void *arg);
+static void imx_txtimeout_expiry(wdparm_t arg);
+
+static void imx_poll_work(FAR void *arg);
+static void imx_polltimer_expiry(wdparm_t arg);
+
+/* NuttX callback functions */
+
+static int  imx_ifup(struct net_driver_s *dev);
+static int  imx_ifdown(struct net_driver_s *dev);
+
+static void imx_txavail_work(FAR void *arg);
+static int  imx_txavail(struct net_driver_s *dev);
+
+/* Internal ifup function that allows phy reset to be optional */
+
+static int imx_ifup_action(struct net_driver_s *dev, bool resetphy);
+
+#ifdef CONFIG_NET_MCASTGROUP
+static int  imx_addmac(struct net_driver_s *dev,
+              FAR const uint8_t *mac);
+static int  imx_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
+#endif
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int  imx_ioctl(struct net_driver_s *dev, int cmd,
+            unsigned long arg);
+#endif
+
+/* PHY/MII support */
+
+#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
+static int imx_phyintenable(struct imx_driver_s *priv);
+#endif
+static inline void imx_initmii(struct imx_driver_s *priv);
+
+#if 0 /* TODO */
+static int imx_writemii(struct imx_driver_s *priv, uint8_t phyaddr,
+             uint8_t regaddr, uint16_t data);
+static int imx_readmii(struct imx_driver_s *priv, uint8_t phyaddr,
+             uint8_t regaddr, uint16_t *data);
+#endif
+
+static int imx_initphy(struct imx_driver_s *priv, bool renogphy);
+
+/* Initialization */
+
+static void imx_initbuffers(struct imx_driver_s *priv);
+static void imx_reset(struct imx_driver_s *priv);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: imx_txringfull
+ *
+ * Description:
+ *   Check if all of the TX descriptors are in use.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   true is the TX ring is full; false if there are free slots at the
+ *   head index.
+ *
+ ****************************************************************************/
+
+static bool imx_txringfull(FAR struct imx_driver_s *priv)
+{
+  uint8_t txnext;
+
+  /* Check if there is room in the hardware to hold another outgoing
+   * packet.  The ring is full if incrementing the head pointer would
+   * collide with the tail pointer.
+   */
+
+  txnext = priv->txhead + 1;
+  if (txnext >= CONFIG_IMX_ENET_NTXBUFFERS)
+    {
+      txnext = 0;
+    }
+
+  return priv->txtail == txnext;
+}
+
+/****************************************************************************
+ * Function: imx_transmit
+ *
+ * Description:
+ *   Start hardware transmission.  Called either from the txdone interrupt
+ *   handling or from watchdog based polling.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int imx_transmit(FAR struct imx_driver_s *priv)
+{
+  struct enet_desc_s *txdesc;
+  irqstate_t flags;
+  uint32_t regval;
+  uint8_t *buf;
+
+  /* Since this can be called from imx_receive, it is possible that
+   * the transmit queue is full, so check for that now.  If this is the
+   * case, the outgoing packet will be dropped (e.g. an ARP reply)
+   */
+
+  if (imx_txringfull(priv))
+    {
+      return -EBUSY;
+    }
+
+  /* When we get here the TX descriptor should show that the previous
+   * transfer has  completed.  If we get here, then we are committed to
+   * sending a packet; Higher level logic must have assured that there is
+   * no transmission in progress.
+   */
+
+  txdesc = &priv->txdesc[priv->txhead];
+  priv->txhead++;
+  if (priv->txhead >= CONFIG_IMX_ENET_NTXBUFFERS)
+    {
+      priv->txhead = 0;
+    }
+
+#ifdef CONFIG_DEBUG_ASSERTIONS
+  up_invalidate_dcache((uintptr_t)txdesc,
+                       (uintptr_t)txdesc + sizeof(struct enet_desc_s));
+
+  DEBUGASSERT(priv->txtail != priv->txhead &&
+             (txdesc->status1 & TXDESC_R) == 0);
+#endif
+
+  /* Increment statistics */
+
+  NETDEV_TXPACKETS(&priv->dev);
+
+  /* Setup the buffer descriptor for transmission: address=priv->dev.d_buf,
+   * length=priv->dev.d_len
+   */
+
+  txdesc->length   = imx_swap16(priv->dev.d_len);
+#ifdef CONFIG_IMX_ENETENHANCEDBD
+  txdesc->bdu      = 0x00000000;
+  txdesc->status2  = TXDESC_INT | TXDESC_TS; /* | TXDESC_IINS | TXDESC_PINS; */
+#endif
+  txdesc->status1 |= (TXDESC_R | TXDESC_L | TXDESC_TC);
+
+  buf = (uint8_t *)imx_swap32((uint32_t)priv->dev.d_buf);
+  if (priv->rxdesc[priv->rxtail].data == buf)
+    {
+      struct enet_desc_s *rxdesc = &priv->rxdesc[priv->rxtail];
+
+      /* Data was written into the RX buffer, so swap the TX and RX buffers */
+
+      DEBUGASSERT((rxdesc->status1 & RXDESC_E) == 0);
+      rxdesc->data = txdesc->data;
+      txdesc->data = buf;
+    }
+  else
+    {
+      DEBUGASSERT(txdesc->data == buf);
+    }
+
+  /* Make the following operations atomic */
+
+  flags = spin_lock_irqsave();
+
+  /* Enable TX interrupts */
+
+  regval  = getreg32(IMX_ENET_EIMR);
+  regval |= TX_INTERRUPTS;
+  putreg32(regval, IMX_ENET_EIMR);
+
+  /* Setup the TX timeout watchdog (perhaps restarting the timer) */
+
+  wd_start(&priv->txtimeout, IMX_TXTIMEOUT,
+           imx_txtimeout_expiry, (wdparm_t)priv);
+
+  /* Start the TX transfer (if it was not already waiting for buffers) */
+
+  putreg32(ENET_TDAR, IMX_ENET_TDAR);
+
+  spin_unlock_irqrestore(flags);
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_txpoll
+ *
+ * Description:
+ *   The transmitter is available, check if the network has any outgoing
+ *   packets ready to send.  This is a callback from devif_poll().
+ *   devif_poll() may be called:
+ *
+ *   1. When the preceding TX packet send is complete,
+ *   2. When the preceding TX packet send timesout and the interface is reset
+ *   3. During normal TX polling
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int imx_txpoll(struct net_driver_s *dev)
+{
+  FAR struct imx_driver_s *priv =
+    (FAR struct imx_driver_s *)dev->d_private;
+
+  /* If the polling resulted in data that should be sent out on the network,
+   * the field d_len is set to a value > 0.
+   */
+
+  if (priv->dev.d_len > 0)
+    {
+      /* Look up the destination MAC address and add it to the Ethernet
+       * header.
+       */
+
+#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NET_IPv6
+      if (IFF_IS_IPv4(priv->dev.d_flags))
+#endif
+        {
+          arp_out(&priv->dev);
+        }
+#endif /* CONFIG_NET_IPv4 */
+
+#ifdef CONFIG_NET_IPv6
+#ifdef CONFIG_NET_IPv4
+      else
+#endif
+        {
+          neighbor_out(&priv->dev);
+        }
+#endif /* CONFIG_NET_IPv6 */
+
+      if (!devif_loopback(&priv->dev))
+        {
+          /* Send the packet */
+
+          imx_transmit(priv);
+          priv->dev.d_buf = (uint8_t *)
+            imx_swap32((uint32_t)priv->txdesc[priv->txhead].data);
+
+          /* Check if there is room in the device to hold another packet. If
+           * not, return a non-zero value to terminate the poll.
+           */
+
+          if (imx_txringfull(priv))
+            {
+              return -EBUSY;
+            }
+        }
+    }
+
+  /* If zero is returned, the polling will continue until
+   * all connections have been examined.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Function: imx_dispatch
+ *
+ * Description:
+ *   A new Rx packet was received; dispatch that packet to the network layer
+ *   as necessary.
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static inline void imx_dispatch(FAR struct imx_driver_s *priv)
+{
+  /* Update statistics */
+
+  NETDEV_RXPACKETS(&priv->dev);
+
+#ifdef CONFIG_NET_PKT
+  /* When packet sockets are enabled, feed the frame into the packet tap */
+
+  pkt_input(&priv->dev);
+#endif
+
+#ifdef CONFIG_NET_IPv4
+  /* Check for an IPv4 packet */
+
+  if (BUF->type == HTONS(ETHTYPE_IP))
+    {
+      ninfo("IPv4 frame\n");
+      NETDEV_RXIPV4(&priv->dev);
+
+      /* Handle ARP on input then give the IPv4 packet to the network
+       * layer
+       */
+
+      arp_ipin(&priv->dev);
+      ipv4_input(&priv->dev);
+
+      /* If the above function invocation resulted in data that should be
+       * sent out on the network, the field  d_len will set to a value > 0.
+       */
+
+      if (priv->dev.d_len > 0)
+        {
+          /* Update the Ethernet header with the correct MAC address */
+
+#ifdef CONFIG_NET_IPv6
+          if (IFF_IS_IPv4(priv->dev.d_flags))
+#endif
+            {
+              arp_out(&priv->dev);
+            }
+#ifdef CONFIG_NET_IPv6
+          else
+            {
+              neighbor_out(&priv->dev);
+            }
+#endif
+
+          /* And send the packet */
+
+          imx_transmit(priv);
+        }
+    }
+  else
+#endif
+#ifdef CONFIG_NET_IPv6
+  /* Check for an IPv6 packet */
+
+  if (BUF->type == HTONS(ETHTYPE_IP6))
+    {
+      ninfo("Iv6 frame\n");
+      NETDEV_RXIPV6(&priv->dev);
+
+      /* Give the IPv6 packet to the network layer */
+
+      ipv6_input(&priv->dev);
+
+      /* If the above function invocation resulted in data that should be
+       * sent out on the network, the field  d_len will set to a value > 0.
+       */
+
+      if (priv->dev.d_len > 0)
+        {
+          /* Update the Ethernet header with the correct MAC address */
+
+#ifdef CONFIG_NET_IPv4
+          if (IFF_IS_IPv4(priv->dev.d_flags))
+            {
+              arp_out(&priv->dev);
+            }
+          else
+#endif
+#ifdef CONFIG_NET_IPv6
+            {
+              neighbor_out(&priv->dev);
+            }
+#endif
+
+          /* And send the packet */
+
+          imx_transmit(priv);
+        }
+    }
+  else
+#endif
+#ifdef CONFIG_NET_ARP
+  /* Check for an ARP packet */
+
+  if (BUF->type == htons(ETHTYPE_ARP))
+    {
+      NETDEV_RXARP(&priv->dev);
+      arp_arpin(&priv->dev);
+
+      /* If the above function invocation resulted in data that should
+       * be sent out on the network, the field  d_len will set to a
+       * value > 0.
+       */
+
+      if (priv->dev.d_len > 0)
+        {
+          imx_transmit(priv);
+        }
+    }
+#endif
+  else
+    {
+      NETDEV_RXDROPPED(&priv->dev);
+    }
+}
+
+/****************************************************************************
+ * Function: imx_receive
+ *
+ * Description:
+ *   An interrupt was received indicating the availability of a new RX packet
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void imx_receive(FAR struct imx_driver_s *priv)
+{
+  struct enet_desc_s *rxdesc;
+  bool received;
+
+  /* Loop while there are received packets to be processed */
+
+  do
+    {
+      /* Invalidate the Rx descriptor.  Since it has been modified via DMA,
+       * we must assure that we must invalid any cached values and re-read
+       * the descriptor from the memory.
+       */
+
+      rxdesc = &priv->rxdesc[priv->rxtail];
+      up_invalidate_dcache((uintptr_t)rxdesc,
+                           (uintptr_t)rxdesc + sizeof(struct enet_desc_s));
+
+      /* Check if the data buffer associated with the descriptor has
+       * been filled with valid data.
+       */
+
+      received = ((rxdesc->status1 & RXDESC_E) == 0);
+      if (received)
+        {
+          /* Copy the buffer pointer to priv->dev.d_buf.  Set amount of data
+           * in priv->dev.d_len
+           */
+
+          priv->dev.d_len = imx_swap16(rxdesc->length);
+          priv->dev.d_buf = (uint8_t *)imx_swap32((uint32_t)rxdesc->data);
+
+          /* Invalidate the buffer so that the correct packet will be re-read
+           * from memory when the packet content is accessed.
+           */
+
+          up_invalidate_dcache((uintptr_t)priv->dev.d_buf,
+                               (uintptr_t)priv->dev.d_buf + priv->dev.d_len);
+
+          /* Dispatch (or drop) the newly received packet */
+
+          imx_dispatch(priv);
+
+          /* Point the packet buffer back to the next Tx buffer that will be
+           * used during the next write.  If the write queue is full, then
+           * this will point at an active buffer, which must not be written
+           * to.  This is OK because devif_poll won't be called unless the
+           * queue is not full.
+           */
+
+          priv->dev.d_buf = (uint8_t *)
+            imx_swap32((uint32_t)priv->txdesc[priv->txhead].data);
+          rxdesc->status1 |= RXDESC_E;
+
+          /* Update the index to the next descriptor */
+
+          priv->rxtail++;
+          if (priv->rxtail >= CONFIG_IMX_ENET_NRXBUFFERS)
+            {
+              priv->rxtail = 0;
+            }
+
+          /* Indicate that there have been empty receive buffers produced */
+
+          putreg32(ENET_RDAR, IMX_ENET_RDAR);
+        }
+    }
+  while (received);
+}
+
+/****************************************************************************
+ * Function: imx_txdone
+ *
+ * Description:
+ *   An interrupt was received indicating that the last TX packet(s) is done
+ *
+ * Input Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void imx_txdone(FAR struct imx_driver_s *priv)
+{
+  struct enet_desc_s *txdesc;
+  uint32_t regval;
+  bool txdone;
+
+  /* We are here because a transmission completed, so the watchdog can be
+   * canceled.
+   */
+
+  wd_cancel(&priv->txtimeout);
+
+  /* Verify that the oldest descriptor descriptor completed */
+
+  do
+    {
+      /* Invalidate the Tx descriptor.  Since status information has been
+       * modified via DMA, we must assure that we must invalid any cached
+       * values and re-read the descriptor from the memory.
+       */
+
+      txdesc = &priv->txdesc[priv->txtail];
+      up_invalidate_dcache((uintptr_t)txdesc,
+                           (uintptr_t)txdesc + sizeof(struct enet_desc_s));
+
+      txdone = false;
+      if ((txdesc->status1 & TXDESC_R) == 0 && priv->txtail != priv->txhead)
+        {
+          /* Yes.. bump up the tail pointer, making space for a new TX
+           * descriptor.
+           */
+
+          priv->txtail++;
+          if (priv->txtail >= CONFIG_IMX_ENET_NTXBUFFERS)
+            {
+              priv->txtail = 0;
+            }
+
+          /* Update statistics */
+
+          NETDEV_TXDONE(&priv->dev);
+          txdone = true;
+        }
+    }
+  while (txdone);
+
+  /* Are there other transmissions queued? */
+
+  if (priv->txtail == priv->txhead)
+    {
+      /* No.. Cancel the TX timeout and disable further Tx interrupts. */
+
+      wd_cancel(&priv->txtimeout);
+
+      regval  = getreg32(IMX_ENET_EIMR);
+      regval &= ~TX_INTERRUPTS;
+      putreg32(regval, IMX_ENET_EIMR);
+    }
+
+  /* There should be space for a new TX in any event.  Poll the network for
+   * new XMIT data
+   */
+
+  devif_poll(&priv->dev, imx_txpoll);
+}
+
+/****************************************************************************
+ * Function: imx_enet_interrupt_work
+ *
+ * Description:
+ *   Perform interrupt related work from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() was called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void imx_enet_interrupt_work(FAR void *arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+  uint32_t pending;
+#ifdef CONFIG_NET_MCASTGROUP
+  uint32_t gaurstore;
+  uint32_t galrstore;
+#endif
+
+  /* Process pending Ethernet interrupts */
+
+  net_lock();
+
+  /* Get the set of unmasked, pending interrupt. */
+
+  pending = getreg32(IMX_ENET_EIR) & getreg32(IMX_ENET_EIMR);
+
+  /* Clear the pending interrupts */
+
+  putreg32(pending, IMX_ENET_EIR);
+
+  /* Check for errors */
+
+  if (pending & ERROR_INTERRUPTS)
+    {
+      /* An error has occurred, update statistics */
+
+      NETDEV_ERRORS(&priv->dev);
+
+      nerr("ERROR: Network interface error occurred (0x%08X)\n",
+           (pending & ERROR_INTERRUPTS));
+    }
+
+  if (pending & CRITICAL_ERROR)
+    {
+      nerr("Critical error, restarting Ethernet interface\n");
+
+      /* Bring the Ethernet chip down and back up but with no need to
+       * reset/renegotiate the phy.
+       */
+
+#ifdef CONFIG_NET_MCASTGROUP
+      /* Just before we pull the rug lets make sure we retain the
+       * multicast hash table.
+       */
+
+      gaurstore = getreg32(IMX_ENET_GAUR);
+      galrstore = getreg32(IMX_ENET_GALR);
+#endif
+
+      imx_ifdown(&priv->dev);
+      imx_ifup_action(&priv->dev, false);
+
+#ifdef CONFIG_NET_MCASTGROUP
+      /* Now write the multicast table back */
+
+      putreg32(gaurstore, IMX_ENET_GAUR);
+      putreg32(galrstore, IMX_ENET_GALR);
+#endif
+
+      /* Then poll the network for new XMIT data */
+
+      devif_poll(&priv->dev, imx_txpoll);
+    }
+  else
+    {
+      /* Check for the receipt of a packet */
+
+      if ((pending & ENET_INT_RXF) != 0)
+        {
+          /* A packet has been received, call imx_receive() to handle the
+           * packet.
+           */
+
+          imx_receive(priv);
+        }
+
+      /* Check if a packet transmission has completed */
+
+      if ((pending & ENET_INT_TXF) != 0)
+        {
+          /* Call imx_txdone to handle the end of transfer even.  NOTE
+           * that this may disable further Tx interrupts if there are no
+           * pending transmissions.
+           */
+
+          imx_txdone(priv);
+        }
+    }
+
+  net_unlock();
+
+  /* Re-enable Ethernet interrupts */
+
+#if 0
+  up_enable_irq(IMX_IRQ_ENET0TMR);
+#endif
+  up_enable_irq(IMX_IRQ_ENET0);
+}
+
+/****************************************************************************
+ * Function: imx_enet_interrupt
+ *
+ * Description:
+ *   Three interrupt sources will vector this this function:
+ *   1. Ethernet MAC transmit interrupt handler
+ *   2. Ethernet MAC receive interrupt handler
+ *   3.
+ *
+ * Input Parameters:
+ *   irq     - Number of the IRQ that generated the interrupt
+ *   context - Interrupt register state save info (architecture-specific)
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int imx_enet_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+  register FAR struct imx_driver_s *priv = &g_enet[0];
+
+  /* Disable further Ethernet interrupts.  Because Ethernet interrupts are
+   * also disabled if the TX timeout event occurs, there can be no race
+   * condition here.
+   */
+
+  up_disable_irq(IMX_IRQ_ENET0);
+
+  /* Schedule to perform the interrupt processing on the worker thread. */
+
+  work_queue(ETHWORK, &priv->irqwork, imx_enet_interrupt_work, priv, 0);
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_txtimeout_work
+ *
+ * Description:
+ *   Perform TX timeout related work from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void imx_txtimeout_work(FAR void *arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+
+  /* Increment statistics and dump debug info */
+
+  net_lock();
+  nerr("Resetting interface\n");
+
+  NETDEV_TXTIMEOUTS(&priv->dev);
+
+  /* Take the interface down and bring it back up.  That is the most
+   * aggressive hardware reset.
+   */
+
+  imx_ifdown(&priv->dev);
+  imx_ifup_action(&priv->dev, false);
+
+  /* Then poll the network for new XMIT data */
+
+  devif_poll(&priv->dev, imx_txpoll);
+  net_unlock();
+}
+
+/****************************************************************************
+ * Function: imx_txtimeout_expiry
+ *
+ * Description:
+ *   Our TX watchdog timed out.  Called from the timer interrupt handler.
+ *   The last TX never completed.  Reset the hardware and start again.
+ *
+ * Input Parameters:
+ *   argc - The number of available arguments
+ *   arg  - The first argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void imx_txtimeout_expiry(wdparm_t arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+
+  /* Disable further Ethernet interrupts.  This will prevent some race
+   * conditions with interrupt work.  There is still a potential race
+   * condition with interrupt work that is already queued and in progress.
+   */
+
+  up_disable_irq(IMX_IRQ_ENET0);
+
+  /* Schedule to perform the TX timeout processing on the worker thread,
+   * canceling any pending interrupt work.
+   */
+
+  work_queue(ETHWORK, &priv->irqwork, imx_txtimeout_work, priv, 0);
+}
+
+/****************************************************************************
+ * Function: imx_poll_work
+ *
+ * Description:
+ *   Perform periodic polling from the worker thread
+ *
+ * Input Parameters:
+ *   arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ *   OK on success
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void imx_poll_work(FAR void *arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+
+  /* Check if there is there is a transmission in progress.
+   * We cannot perform the TX poll if he are unable to accept
+   * another packet for transmission.
+   */
+
+  net_lock();
+  if (!imx_txringfull(priv))
+    {
+      /* If so, update TCP timing states and poll the network for new XMIT
+       * data. Hmmm.. might be bug here.  Does this mean if there is a
+       * transmit in progress, we will missing TCP time state updates?
+       */
+
+      devif_timer(&priv->dev, IMX_WDDELAY, imx_txpoll);
+    }
+
+  /* Setup the watchdog poll timer again in any case */
+
+  wd_start(&priv->txpoll, IMX_WDDELAY,
+           imx_polltimer_expiry, (wdparm_t)priv);
+  net_unlock();
+}
+
+/****************************************************************************
+ * Function: imx_polltimer_expiry
+ *
+ * Description:
+ *   Periodic timer handler.  Called from the timer interrupt handler.
+ *
+ * Input Parameters:
+ *   argc - The number of available arguments
+ *   arg  - The first argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void imx_polltimer_expiry(wdparm_t arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+
+  /* Schedule to perform the poll processing on the worker thread. */
+
+  work_queue(ETHWORK, &priv->pollwork, imx_poll_work, priv, 0);
+}
+
+/****************************************************************************
+ * Function: imx_ifup_action
+ *
+ * Description:
+ *   Internal action routine to bring up the Ethernet interface
+ *   which makes the resetting of the phy (which takes considerable time)
+ *   optional.
+ *
+ * Input Parameters:
+ *   dev      - Reference to the NuttX driver state structure
+ *   resetphy - Flag indicating if Phy is to be reset. If not then the
+ *              phy configuration is just re-loaded into the ethernet
+ *              interface
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int imx_ifup_action(struct net_driver_s *dev, bool resetphy)
+{
+  FAR struct imx_driver_s *priv =
+    (FAR struct imx_driver_s *)dev->d_private;
+  uint8_t *mac = dev->d_mac.ether.ether_addr_octet;
+  uint32_t regval;
+  int ret;
+
+  ninfo("Bringing up: %d.%d.%d.%d\n",
+        (int)dev->d_ipaddr & 0xff,
+        (int)(dev->d_ipaddr >> 8) & 0xff,
+        (int)(dev->d_ipaddr >> 16) & 0xff,
+        (int)dev->d_ipaddr >> 24);
+
+  /* Initialize ENET buffers */
+
+  imx_initbuffers(priv);
+
+  /* Configure the MII interface */
+
+  imx_initmii(priv);
+
+  /* Set the MAC address */
+
+  putreg32((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3],
+           IMX_ENET_PALR);
+  putreg32((mac[4] << 24) | (mac[5] << 16), IMX_ENET_PAUR);
+
+  /* Configure the PHY */
+
+  ret = imx_initphy(priv, resetphy);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to configure the PHY: %d\n", ret);
+      return ret;
+    }
+
+  /* Handle promiscuous mode */
+
+#ifdef CONFIG_NET_PROMISCUOUS
+  regval = getreg32(IMX_ENET_RCR);
+  regval |= ENET_RCR_PROM;
+  putreg32(regval, IMX_ENET_RCR);
+#endif
+
+  /* Select legacy of enhanced buffer descriptor format */
+
+#ifdef CONFIG_IMX_ENETENHANCEDBD
+  putreg32(ENET_ECR_EN1588, IMX_ENET_ECR);
+#else
+  putreg32(0, IMX_ENET_ECR);
+#endif
+
+  /* Set the RX buffer size */
+
+  putreg32(IMX_BUF_SIZE, IMX_ENET_MRBR);
+
+  /* Point to the start of the circular RX buffer descriptor queue */
+
+  putreg32((uint32_t)priv->rxdesc, IMX_ENET_RDSR);
+
+  /* Point to the start of the circular TX buffer descriptor queue */
+
+  putreg32((uint32_t)priv->txdesc, IMX_ENET_TDSR);
+
+  /* And enable the MAC itself */
+
+  regval  = getreg32(IMX_ENET_ECR);
+  regval |= ENET_ECR_ETHEREN
+#ifdef IMX_USE_DBSWAP
+         | ENET_ECR_DBSWP
+#endif
+        ;
+  putreg32(regval, IMX_ENET_ECR);
+
+  /* Indicate that there have been empty receive buffers produced */
+
+  putreg32(ENET_RDAR, IMX_ENET_RDAR);
+
+  /* Set and activate a timer process */
+
+  wd_start(&priv->txpoll, IMX_WDDELAY,
+           imx_polltimer_expiry, (wdparm_t)priv);
+
+  /* Clear all pending ENET interrupt */
+
+  putreg32(RX_INTERRUPTS | ERROR_INTERRUPTS | TX_INTERRUPTS, IMX_ENET_EIR);
+
+  /* Enable RX and error interrupts at the controller (TX interrupts are
+   * still disabled).
+   */
+
+  putreg32(RX_INTERRUPTS | ERROR_INTERRUPTS,
+           IMX_ENET_EIMR);
+
+  /* Mark the interrupt "up" and enable interrupts at the NVIC */
+
+  priv->bifup = true;
+
+#if 0
+  up_enable_irq(IMX_IRQ_ENET0TMR);
+#endif
+  up_enable_irq(IMX_IRQ_ENET0);
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_ifup
+ *
+ * Description:
+ *   NuttX Callback: Bring up the Ethernet interface when an IP address is
+ *   provided
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int imx_ifup(struct net_driver_s *dev)
+{
+  /* The externally available ifup action includes resetting the phy */
+
+  return imx_ifup_action(dev, true);
+}
+
+/****************************************************************************
+ * Function: imx_ifdown
+ *
+ * Description:
+ *   NuttX Callback: Stop the interface.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int imx_ifdown(struct net_driver_s *dev)
+{
+  FAR struct imx_driver_s *priv =
+    (FAR struct imx_driver_s *)dev->d_private;
+  irqstate_t flags;
+
+  ninfo("Taking down: %d.%d.%d.%d\n",
+        (int)(dev->d_ipaddr & 0xff),
+        (int)((dev->d_ipaddr >> 8) & 0xff),
+        (int)((dev->d_ipaddr >> 16) & 0xff),
+        (int)(dev->d_ipaddr >> 24));
+
+  /* Flush and disable the Ethernet interrupts at the NVIC */
+
+  flags = enter_critical_section();
+
+  up_disable_irq(IMX_IRQ_ENET0);
+  putreg32(0, IMX_ENET_EIMR);
+
+  /* Cancel the TX poll timer and TX timeout timers */
+
+  wd_cancel(&priv->txpoll);
+  wd_cancel(&priv->txtimeout);
+
+  /* Put the EMAC in its reset, non-operational state.  This should be
+   * a known configuration that will guarantee the imx_ifup() always
+   * successfully brings the interface back up.
+   */
+
+  imx_reset(priv);
+
+  /* Mark the device "down" */
+
+  priv->bifup = false;
+  leave_critical_section(flags);
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_txavail_work
+ *
+ * Description:
+ *   Perform an out-of-cycle poll on the worker thread.
+ *
+ * Input Parameters:
+ *   arg - Reference to the NuttX driver state structure (cast to void*)
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called on the higher priority worker thread.
+ *
+ ****************************************************************************/
+
+static void imx_txavail_work(FAR void *arg)
+{
+  FAR struct imx_driver_s *priv = (FAR struct imx_driver_s *)arg;
+
+  /* Ignore the notification if the interface is not yet up */
+
+  net_lock();
+  if (priv->bifup)
+    {
+      /* Check if there is room in the hardware to hold another outgoing
+       * packet.
+       */
+
+      if (!imx_txringfull(priv))
+        {
+          /* No, there is space for another transfer.  Poll the network for
+           * new XMIT data.
+           */
+
+          devif_timer(&priv->dev, 0, imx_txpoll);
+        }
+    }
+
+  net_unlock();
+}
+
+/****************************************************************************
+ * Function: imx_txavail
+ *
+ * Description:
+ *   Driver callback invoked when new TX data is available.  This is a
+ *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX
+ *   latency.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called in normal user mode
+ *
+ ****************************************************************************/
+
+static int imx_txavail(struct net_driver_s *dev)
+{
+  FAR struct imx_driver_s *priv =
+    (FAR struct imx_driver_s *)dev->d_private;
+
+  /* Is our single work structure available?  It may not be if there are
+   * pending interrupt actions and we will have to ignore the Tx
+   * availability action.
+   */
+
+  if (work_available(&priv->pollwork))
+    {
+      /* Schedule to serialize the poll on the worker thread. */
+
+      work_queue(ETHWORK, &priv->pollwork, imx_txavail_work, priv, 0);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_calcethcrc
+ *
+ * Description:
+ *   Function to calculate the CRC used by IMX to check an Ethernet frame
+ *
+ * Input Parameters:
+ *   data   - the data to be checked
+ *   length - length of the data
+ *
+ * Returned Value:
+ *   crc32
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_MCASTGROUP
+static uint32_t imx_calcethcrc(const uint8_t *data, size_t length)
+{
+  uint32_t crc    = 0xffffffffu;
+  uint32_t count1 = 0;
+  uint32_t count2 = 0;
+
+  /* Calculates the CRC-32 polynomial on the multicast group address. */
+
+  for (count1 = 0; count1 < length; count1++)
+    {
+      uint8_t c = data[count1];
+
+      for (count2 = 0; count2 < 0x08u; count2++)
+        {
+          if ((c ^ crc) & 1U)
+            {
+              crc >>= 1U;
+              c   >>= 1U;
+              crc  ^= 0xedb88320u;
+            }
+          else
+            {
+              crc >>= 1U;
+              c   >>= 1U;
+            }
+        }
+    }
+
+  return crc;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_enet_hash_index
+ *
+ * Description:
+ *   Function to find the hash index for multicast address filter
+ *
+ * Input Parameters:
+ *   mac  - The MAC address
+ *
+ * Returned Value:
+ *   hash index
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_MCASTGROUP
+static uint32_t imx_enet_hash_index(const uint8_t *mac)
+{
+  uint32_t crc;
+  uint32_t hashindex;
+
+  ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+  crc = imx_calcethcrc(mac, 6);
+  hashindex = (crc >> 26) & 0x3f;
+
+  return hashindex;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_addmac
+ *
+ * Description:
+ *   NuttX Callback: Add the specified MAC address to the hardware multicast
+ *   address filtering
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *   mac  - The MAC address to be added
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_MCASTGROUP
+static int imx_addmac(struct net_driver_s *dev, FAR const uint8_t *mac)
+{
+  uint32_t hashindex;
+  uint32_t temp;
+  uint32_t registeraddress;
+
+  hashindex = imx_enet_hash_index(mac);
+
+  /* Add the MAC address to the hardware multicast routing table */
+
+  if (hashindex > 31)
+    {
+      registeraddress = IMX_ENET_GAUR;
+      hashindex      -= 32;
+    }
+  else
+    {
+      registeraddress = IMX_ENET_GALR;
+    }
+
+  temp  = getreg32(registeraddress);
+  temp |= 1 << hashindex;
+  putreg32(temp, registeraddress);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_rmmac
+ *
+ * Description:
+ *   NuttX Callback: Remove the specified MAC address from the hardware
+ *   multicast address filtering
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *   mac  - The MAC address to be removed
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_MCASTGROUP
+static int imx_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
+{
+  uint32_t hashindex;
+  uint32_t temp;
+  uint32_t registeraddress;
+
+  /* Remove the MAC address from the hardware multicast routing table */
+
+  hashindex = imx_enet_hash_index(mac);
+
+  if (hashindex > 31)
+    {
+      registeraddress = IMX_ENET_GAUR;
+      hashindex      -= 32;
+    }
+  else
+    {
+      registeraddress = IMX_ENET_GALR;
+    }
+
+  temp  = getreg32(registeraddress);
+  temp &= ~(1 << hashindex);
+  putreg32(temp, registeraddress);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_ioctl
+ *
+ * Description:
+ *   PHY ioctl command handler
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *   cmd  - ioctl command
+ *   arg  - Argument accompanying the command
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int imx_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
+{
+#ifdef CONFIG_NETDEV_PHY_IOCTL
+  FAR struct imx_driver_s *priv =
+    (FAR struct imx_driver_s *)dev->d_private;
+#endif
+  int ret;
+
+  switch (cmd)
+    {
+#ifdef CONFIG_NETDEV_PHY_IOCTL
+#ifdef CONFIG_ARCH_PHY_INTERRUPT
+      case SIOCMIINOTIFY: /* Set up for PHY event notifications */
+        {
+          struct mii_ioctl_notify_s *req =
+            (struct mii_ioctl_notify_s *)((uintptr_t)arg);
+
+          ret = phy_notify_subscribe(dev->d_ifname, req->pid, &req->event);
+          if (ret == OK)
+            {
+              /* Enable PHY link up/down interrupts */
+
+              ret = imx_phyintenable(priv);
+            }
+        }
+        break;
+#endif
+
+      case SIOCGMIIPHY: /* Get MII PHY address */
+        {
+          struct mii_ioctl_data_s *req =
+            (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          req->phy_id = priv->phyaddr;
+          ret = OK;
+        }
+        break;
+
+      case SIOCGMIIREG: /* Get register from MII PHY */
+        {
+          struct mii_ioctl_data_s *req =
+            (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          ret = imx_readmii(priv, req->phy_id, req->reg_num, &req->val_out);
+        }
+        break;
+
+      case SIOCSMIIREG: /* Set register in MII PHY */
+        {
+          struct mii_ioctl_data_s *req =
+            (struct mii_ioctl_data_s *)((uintptr_t)arg);
+          ret = imx_writemii(priv, req->phy_id, req->reg_num, req->val_in);
+        }
+        break;
+#endif /* CONFIG_NETDEV_PHY_IOCTL */
+
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  return ret;
+}
+#endif /* CONFIG_NETDEV_IOCTL */
+
+/****************************************************************************
+ * Function: imx_phyintenable
+ *
+ * Description:
+ *  Enable link up/down PHY interrupts.  The interrupt protocol is like this:
+ *
+ *  - Interrupt status is cleared when the interrupt is enabled.
+ *  - Interrupt occurs.  Interrupt is disabled (at the processor level) when
+ *    is received.
+ *  - Interrupt status is cleared when the interrupt is re-enabled.
+ *
+ * Input Parameters:
+ *   priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ *   OK on success; Negated errno (-ETIMEDOUT) on failure.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
+static int imx_phyintenable(struct imx_driver_s *priv)
+{
+#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \
+    defined(CONFIG_ETH0_PHY_KSZ8081)
+  uint16_t phyval;
+  int ret;
+
+  /* Read the interrupt status register in order to clear any pending
+   * interrupts
+   */
+
+  ret = imx_readmii(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval);
+  if (ret == OK)
+    {
+      /* Enable link up/down interrupts */
+
+      ret = imx_writemii(priv, priv->phyaddr, MII_KSZ8081_INT,
+                           (MII_KSZ80X1_INT_LDEN | MII_KSZ80X1_INT_LUEN));
+    }
+
+  return ret;
+#else
+#  error Unrecognized PHY
+  return -ENOSYS;
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_initmii
+ *
+ * Description:
+ *   Configure the MII interface
+ *
+ * Input Parameters:
+ *   priv - Reference to the private ENET driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void imx_initmii(struct imx_driver_s *priv)
+{
+  /* Speed is based on the peripheral (bus) clock; hold time is 2 module
+   * clock.  This hold time value may need to be increased on some platforms
+   */
+
+  putreg32(ENET_MSCR_HOLDTIME_2CYCLES |
+           IMX_MII_SPEED << ENET_MSCR_MII_SPEED_SHIFT,
+           IMX_ENET_MSCR);
+}
+
+/****************************************************************************
+ * Function: imx_writemii
+ *
+ * Description:
+ *   Write a 16-bit value to a PHY register.
+ *
+ * Input Parameters:
+ *   priv - Reference to the private ENET driver state structure
+ *   phyaddr - The PHY address
+ *   regaddr - The PHY register address
+ *   data    - The data to write to the PHY register
+ *
+ * Returned Value:
+ *   Zero on success, a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#if 0 /* TODO */
+static int imx_writemii(struct imx_driver_s *priv, uint8_t phyaddr,
+                        uint8_t regaddr, uint16_t data)
+{
+  int timeout;
+
+  /* Clear the MII interrupt bit */
+
+  putreg32(ENET_INT_MII, IMX_ENET_EIR);
+
+  /* Initiate the MII Management write */
+
+  putreg32(data |
+           2 << ENET_MMFR_TA_SHIFT |
+           (uint32_t)regaddr << ENET_MMFR_RA_SHIFT |
+           (uint32_t)phyaddr << ENET_MMFR_PA_SHIFT |
+           ENET_MMFR_OP_WRMII |
+           1 << ENET_MMFR_ST_SHIFT,
+           IMX_ENET_MMFR);
+
+  /* Wait for the transfer to complete */
+
+  for (timeout = 0; timeout < MII_MAXPOLLS; timeout++)
+    {
+      if ((getreg32(IMX_ENET_EIR) & ENET_INT_MII) != 0)
+        {
+          break;
+        }
+    }
+
+  /* Check for a timeout */
+
+  if (timeout == MII_MAXPOLLS)
+    {
+      return -ETIMEDOUT;
+    }
+
+  /* Clear the MII interrupt bit */
+
+  putreg32(ENET_INT_MII, IMX_ENET_EIR);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_reademii
+ *
+ * Description:
+ *   Read a 16-bit value from a PHY register.
+ *
+ * Input Parameters:
+ *   priv    - Reference to the private ENET driver state structure
+ *   phyaddr - The PHY address
+ *   regaddr - The PHY register address
+ *   data    - A pointer to the location to return the data
+ *
+ * Returned Value:
+ *   Zero on success, a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#if 0 /* TODO */
+static int imx_readmii(struct imx_driver_s *priv, uint8_t phyaddr,
+                           uint8_t regaddr, uint16_t *data)
+{
+  int timeout;
+
+  /* Clear the MII interrupt bit */
+
+  putreg32(ENET_INT_MII, IMX_ENET_EIR);
+
+  /* Initiate the MII Management read */
+
+  putreg32(2 << ENET_MMFR_TA_SHIFT |
+           (uint32_t)regaddr << ENET_MMFR_RA_SHIFT |
+           (uint32_t)phyaddr << ENET_MMFR_PA_SHIFT |
+           ENET_MMFR_OP_RDMII |
+           1 << ENET_MMFR_ST_SHIFT,
+           IMX_ENET_MMFR);
+
+  /* Wait for the transfer to complete */
+
+  for (timeout = 0; timeout < MII_MAXPOLLS; timeout++)
+    {
+      if ((getreg32(IMX_ENET_EIR) & ENET_INT_MII) != 0)
+        {
+          break;
+        }
+    }
+
+  /* Check for a timeout */
+
+  if (timeout >= MII_MAXPOLLS)
+    {
+      nerr("ERROR: Timed out waiting for transfer to complete\n");
+      return -ETIMEDOUT;
+    }
+
+  /* Clear the MII interrupt bit */
+
+  putreg32(ENET_INT_MII, IMX_ENET_EIR);
+
+  /* And return the MII data */
+
+  *data = (uint16_t)(getreg32(IMX_ENET_MMFR) & ENET_MMFR_DATA_MASK);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: imx_initphy
+ *
+ * Description:
+ *   Configure the PHY
+ *
+ * Input Parameters:
+ *   priv     - Reference to the private ENET driver state structure
+ *   renogphy - Flag indicating if to perform negotiation of the link
+ *
+ * Returned Value:
+ *   Zero (OK) returned on success; a negated errno value is returned on any
+ *   failure;
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static inline int imx_initphy(struct imx_driver_s *priv, bool renogphy)
+{
+#if 0 /* TODO */
+  uint32_t rcr;
+  uint32_t tcr;
+  uint32_t racc;
+  uint16_t phydata;
+  uint8_t phyaddr    = BOARD_PHY_ADDR;
+  int retries;
+  int ret;
+
+  if (renogphy)
+    {
+      /* Loop (potentially infinitely?) until we successfully communicate
+       * with the PHY. This is 'standard stuff' that should work for any PHY
+       * - we are not communicating with it's 'special' registers
+       * at this point.
+       */
+
+      ninfo("%s: Try phyaddr: %u\n", BOARD_PHY_NAME, phyaddr);
+
+      /* Try to read PHYID1 few times using this address */
+
+      retries = 0;
+      do
+        {
+          nxsig_usleep(LINK_WAITUS);
+
+          ninfo("%s: Read PHYID1, retries=%d\n",
+                BOARD_PHY_NAME, retries + 1);
+
+          phydata = 0xffff;
+          ret     = imx_readmii(priv, phyaddr, MII_PHYID1, &phydata);
+        }
+      while ((ret < 0 || phydata == 0xffff) && ++retries < 3);
+
+      if (retries >= 3)
+        {
+          nerr("ERROR: Failed to read %s PHYID1 at address %d\n",
+               BOARD_PHY_NAME, phyaddr);
+          return -ENOENT;
+        }
+
+      ninfo("%s: Using PHY address %u\n", BOARD_PHY_NAME, phyaddr);
+      priv->phyaddr = phyaddr;
+
+      /* Verify PHYID1.  Compare OUI bits 3-18 */
+
+      ninfo("%s: PHYID1: %04x\n", BOARD_PHY_NAME, phydata);
+      if (phydata != BOARD_PHYID1)
+        {
+          nerr("ERROR: PHYID1=%04x incorrect for %s.  Expected %04x\n",
+               phydata, BOARD_PHY_NAME, BOARD_PHYID1);
+          return -ENXIO;
+        }
+
+      /* Read PHYID2 */
+
+      ret = imx_readmii(priv, phyaddr, MII_PHYID2, &phydata);
+      if (ret < 0)
+        {
+          nerr("ERROR: Failed to read %s PHYID2: %d\n", BOARD_PHY_NAME, ret);
+          return ret;
+        }
+
+      ninfo("%s: PHYID2: %04x\n", BOARD_PHY_NAME, phydata);
+
+      /* Verify PHYID2:  Compare OUI bits 19-24 and the 6-bit model number
+       * (ignoring the 4-bit revision number).
+       */
+
+      if ((phydata & 0xfff0) != (BOARD_PHYID2 & 0xfff0))
+        {
+          nerr("ERROR: PHYID2=%04x incorrect for %s.  Expected %04x\n",
+               (phydata & 0xfff0), BOARD_PHY_NAME, (BOARD_PHYID2 & 0xfff0));
+          return -ENXIO;
+        }
+
+#ifdef CONFIG_ETH0_PHY_KSZ8081
+      /* Reset PHY */
+
+      imx_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET);
+
+      /* Set RMII mode */
+
+      ret = imx_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata);
+      if (ret < 0)
+        {
+          nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n");
+          return ret;
+        }
+
+      /* Indicate 50MHz clock */
+
+      imx_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2,
+                     (phydata | (1 << 7)));
+
+      /* Switch off NAND Tree mode (in case it was set via pinning) */
+
+      ret = imx_readmii(priv, phyaddr, MII_KSZ8081_OMSO, &phydata);
+      if (ret < 0)
+        {
+          nerr("ERROR: Failed to read MII_KSZ8081_OMSO: %d\n", ret);
+          return ret;
+        }
+
+      imx_writemii(priv, phyaddr, MII_KSZ8081_OMSO,
+                     (phydata & ~(1 << 5)));
+
+      /* Set Ethernet led to green = activity and yellow = link and  */
+
+      ret = imx_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata);
+      if (ret < 0)
+        {
+          nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n");
+          return ret;
+        }
+
+      imx_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2,
+                     (phydata | (1 << 4)));
+
+#elif defined (CONFIG_ETH0_PHY_LAN8720)
+      /* Make sure that PHY comes up in correct mode when it's reset */
+
+      imx_writemii(priv, phyaddr, MII_LAN8720_MODES,
+                     MII_LAN8720_MODES_RESV | MII_LAN8720_MODES_ALL |
+                     MII_LAN8720_MODES_PHYAD(BOARD_PHY_ADDR));
+
+      /* ...and reset PHY */
+
+      imx_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET);
+#endif
+
+      /* Start auto negotiation */
+
+      ninfo("%s: Start Autonegotiation...\n",  BOARD_PHY_NAME);
+      imx_writemii(priv, phyaddr, MII_MCR,
+                     (MII_MCR_ANRESTART | MII_MCR_ANENABLE));
+
+      /* Wait for auto negotiation to complete */
+
+      for (retries = 0; retries < LINK_NLOOPS; retries++)
+        {
+          ret = imx_readmii(priv, phyaddr, MII_MSR, &phydata);
+          if (ret < 0)
+            {
+              nerr("ERROR: Failed to read %s MII_MSR: %d\n",
+                    BOARD_PHY_NAME, ret);
+              return ret;
+            }
+
+          if (phydata & MII_MSR_ANEGCOMPLETE)
+            {
+              break;
+            }
+
+          nxsig_usleep(LINK_WAITUS);
+        }
+
+      if (phydata & MII_MSR_ANEGCOMPLETE)
+        {
+          ninfo("%s: Autonegotiation complete\n",  BOARD_PHY_NAME);
+          ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata);
+        }
+      else
+        {
+          /* TODO: Autonegotiation has right now failed. Maybe the Eth cable
+           * is not connected.  PHY chip have mechanisms to configure link
+           * OK. We should leave autconf on, and find a way to re-configure
+           * MCU whenever the link is ready.
+           */
+
+          ninfo("%s: Autonegotiation failed [%d] (is cable plugged-in ?), "
+                "default to 10Mbs mode\n", \
+                BOARD_PHY_NAME, retries);
+
+          /* Stop auto negotiation */
+
+          imx_writemii(priv, phyaddr, MII_MCR, 0);
+        }
+    }
+
+  /* When we get here we have a (negotiated) speed and duplex. This is also
+   * the point we enter if renegotiation is turned off, so have multiple
+   * attempts at reading the status register in case the PHY isn't awake
+   * properly.
+   */
+
+  retries = 0;
+  do
+    {
+      phydata = 0xffff;
+      ret = imx_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata);
+    }
+  while ((ret < 0 || phydata == 0xffff) && ++retries < 3);
+
+  /* If we didn't successfully read anything and we haven't tried a physical
+   * renegotiation then lets do that
+   */
+
+  if (retries >= 3)
+    {
+      if (renogphy == false)
+        {
+          /* Give things one more chance with renegotiation turned on */
+
+          return imx_initphy(priv, true);
+        }
+      else
+        {
+          /* That didn't end well, just give up */
+
+          nerr("ERROR: Failed to read %s BOARD_PHY_STATUS[%02x]: %d\n",
+               BOARD_PHY_NAME, BOARD_PHY_STATUS, ret);
+          return ret;
+        }
+    }
+
+  ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata);
+
+  /* Set up the transmit and receive control registers based on the
+   * configuration and the auto negotiation results.
+   */
+
+#ifdef CONFIG_IMX_ENETUSEMII
+  rcr = ENET_RCR_CRCFWD |
+        CONFIG_NET_ETH_PKTSIZE << ENET_RCR_MAX_FL_SHIFT |
+        ENET_RCR_MII_MODE;
+#else
+  rcr = ENET_RCR_RMII_MODE | ENET_RCR_CRCFWD |
+        CONFIG_NET_ETH_PKTSIZE << ENET_RCR_MAX_FL_SHIFT |
+        ENET_RCR_MII_MODE;
+#endif
+  tcr = 0;
+
+  putreg32(rcr, IMX_ENET_RCR);
+  putreg32(tcr, IMX_ENET_TCR);
+
+  /* Enable Discard Of Frames With MAC Layer Errors.
+   * Enable Discard Of Frames With Wrong Protocol Checksum.
+   * Bit 1: Enable discard of frames with wrong IPv4 header checksum.
+   */
+
+  racc = ENET_RACC_PRODIS | ENET_RACC_LINEDIS | ENET_RACC_IPDIS;
+  putreg32(racc, IMX_ENET_RACC);
+
+  /* Setup half or full duplex */
+
+  if (BOARD_PHY_ISDUPLEX(phydata))
+    {
+      /* Full duplex */
+
+      ninfo("%s: Full duplex\n",  BOARD_PHY_NAME);
+      tcr |= ENET_TCR_FDEN;
+    }
+  else
+    {
+      /* Half duplex */
+
+      ninfo("%s: Half duplex\n",  BOARD_PHY_NAME);
+      rcr |= ENET_RCR_DRT;
+    }
+
+  if (BOARD_PHY_10BASET(phydata))
+    {
+      /* 10 Mbps */
+
+      ninfo("%s: 10 Base-T\n",  BOARD_PHY_NAME);
+      rcr |= ENET_RCR_RMII_10T;
+    }
+  else if (BOARD_PHY_100BASET(phydata))
+    {
+      /* 100 Mbps */
+
+      ninfo("%s: 100 Base-T\n",  BOARD_PHY_NAME);
+    }
+  else
+    {
+      /* This might happen if Autonegotiation did not complete(?) */
+
+      nerr("ERROR: Neither 10- nor 100-BaseT reported: PHY STATUS=%04x\n",
+           phydata);
+      return -EIO;
+    }
+
+  putreg32(rcr, IMX_ENET_RCR);
+  putreg32(tcr, IMX_ENET_TCR);
+#endif
+  return OK;
+}
+
+/****************************************************************************
+ * Function: imx_initbuffers
+ *
+ * Description:
+ *   Initialize ENET buffers and descriptors
+ *
+ * Input Parameters:
+ *   priv - Reference to the private ENET driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void imx_initbuffers(struct imx_driver_s *priv)
+{
+  uintptr_t addr;
+  int i;
+
+  /* Get an aligned TX descriptor (array) address */
+
+  addr         = (uintptr_t)g_desc_pool;
+  priv->txdesc = (struct enet_desc_s *)addr;
+
+  /* Get an aligned RX descriptor (array) address */
+
+  addr        +=  CONFIG_IMX_ENET_NTXBUFFERS * sizeof(struct enet_desc_s);
+  priv->rxdesc = (struct enet_desc_s *)addr;
+
+  /* Get the beginning of the first aligned buffer */
+
+  addr         = (uintptr_t)g_buffer_pool;
+
+  /* Then fill in the TX descriptors */
+
+  for (i = 0; i < CONFIG_IMX_ENET_NTXBUFFERS; i++)
+    {
+      priv->txdesc[i].status1 = 0;
+      priv->txdesc[i].length  = 0;
+      priv->txdesc[i].data    = (uint8_t *)imx_swap32((uint32_t)addr);
+#ifdef CONFIG_IMX_ENETENHANCEDBD
+      priv->txdesc[i].status2 = TXDESC_IINS | TXDESC_PINS;
+#endif
+      addr                   += IMX_BUF_SIZE;
+    }
+
+  /* Then fill in the RX descriptors */
+
+  for (i = 0; i < CONFIG_IMX_ENET_NRXBUFFERS; i++)
+    {
+      priv->rxdesc[i].status1 = RXDESC_E;
+      priv->rxdesc[i].length  = 0;
+      priv->rxdesc[i].data    = (uint8_t *)imx_swap32((uint32_t)addr);
+#ifdef CONFIG_IMX_ENETENHANCEDBD
+      priv->rxdesc[i].bdu     = 0;
+      priv->rxdesc[i].status2 = RXDESC_INT;
+#endif
+      addr                   += IMX_BUF_SIZE;
+    }
+
+  /* Set the wrap bit in the last descriptors to form a ring */
+
+  priv->txdesc[CONFIG_IMX_ENET_NTXBUFFERS - 1].status1 |= TXDESC_W;
+  priv->rxdesc[CONFIG_IMX_ENET_NRXBUFFERS - 1].status1 |= RXDESC_W;
+
+  /* We start with RX descriptor 0 and with no TX descriptors in use */
+
+  priv->txtail = 0;
+  priv->txhead = 0;
+  priv->rxtail = 0;
+
+  /* Initialize the packet buffer, which is used when sending */
+
+  priv->dev.d_buf =
+    (uint8_t *)imx_swap32((uint32_t)priv->txdesc[priv->txhead].data);
+}
+
+/****************************************************************************
+ * Function: imx_reset
+ *
+ * Description:
+ *   Put the EMAC in the non-operational, reset state
+ *
+ * Input Parameters:
+ *   priv - Reference to the private ENET driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void imx_reset(struct imx_driver_s *priv)
+{
+  unsigned int i;
+
+  /* Set the reset bit and clear the enable bit */
+
+  putreg32(ENET_ECR_RESET, IMX_ENET_ECR);
+
+  /* Wait at least 8 clock cycles */
+
+  for (i = 0; i < 10; i++)
+    {
+      asm volatile ("nop");
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: imx_netinitialize
+ *
+ * Description:
+ *   Initialize the Ethernet controller and driver
+ *
+ * Input Parameters:
+ *   intf - In the case where there are multiple EMACs, this value
+ *          identifies which EMAC is to be initialized.
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int imx_netinitialize(int intf)
+{
+  struct imx_driver_s *priv;
+#ifdef CONFIG_NET_ETHERNET
+  uint32_t uidl  = 0;
+  uint32_t uidml = 0;
+  uint8_t *mac;
+#endif
+  int ret;
+
+  /* Get the interface structure associated with this interface number. */
+
+  DEBUGASSERT(intf < CONFIG_IMX_ENET_NETHIFS);
+  priv = &g_enet[intf];
+
+#if 0 /* TODO */
+  uint32_t regval;
+
+  /* Enable ENET1_TX_CLK_DIR (Provides 50MHz clk OUT to PHY) */
+
+  regval = getreg32(IMX_IOMUXC_GPR_GPR1);
+  regval |= GPR_GPR1_ENET1_TX_CLK_OUT_EN;
+  putreg32(regval, IMX_IOMUXC_GPR_GPR1);
+
+  /* Enable the ENET clock.  Clock is on during all modes,
+   * except STOP mode.
+   */
+
+  imx_clockall_enet();
+
+  /* Configure all ENET/MII pins */
+
+  imx_config_gpio(GPIO_ENET_MDIO);
+  imx_config_gpio(GPIO_ENET_MDC);
+  imx_config_gpio(GPIO_ENET_RX_EN);
+  imx_config_gpio(GPIO_ENET_RX_DATA00);
+  imx_config_gpio(GPIO_ENET_RX_DATA01);
+  imx_config_gpio(GPIO_ENET_TX_DATA00);
+  imx_config_gpio(GPIO_ENET_TX_DATA01);
+  imx_config_gpio(GPIO_ENET_TX_CLK);
+  imx_config_gpio(GPIO_ENET_TX_EN);
+#ifdef GPIO_ENET_RX_ER
+  imx_config_gpio(GPIO_ENET_RX_ER);
+#endif
+
+#endif /* TODO */
+
+  /* Attach the Ethernet MAC IEEE 1588 timer interrupt handler */
+
+#if 0
+  if (irq_attach(IMX_IRQ_ENET0TMR, imx_tmrinterrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach ENET0TMR IRQ\n");
+      return -EAGAIN;
+    }
+#endif
+
+  /* Attach the Ethernet interrupt handler */
+
+  if (irq_attach(IMX_IRQ_ENET0, imx_enet_interrupt, NULL))
+    {
+      /* We could not attach the ISR to the interrupt */
+
+      nerr("ERROR: Failed to attach ENET0 IRQ\n");
+      return -EAGAIN;
+    }
+
+  /* Configure as a (high) level interrupt */
+
+  arm_gic_irq_trigger(IMX_IRQ_ENET0, false);
+
+  /* Initialize the driver structure */
+
+  memset(priv, 0, sizeof(struct imx_driver_s));
+  priv->dev.d_ifup    = imx_ifup;     /* I/F up (new IP address) callback */
+  priv->dev.d_ifdown  = imx_ifdown;   /* I/F down callback */
+  priv->dev.d_txavail = imx_txavail;  /* New TX data callback */
+#ifdef CONFIG_NET_MCASTGROUP
+  priv->dev.d_addmac  = imx_addmac;   /* Add multicast MAC address */
+  priv->dev.d_rmmac   = imx_rmmac;    /* Remove multicast MAC address */
+#endif
+#ifdef CONFIG_NETDEV_IOCTL
+  priv->dev.d_ioctl   = imx_ioctl;    /* Support PHY ioctl() calls */
+#endif
+  priv->dev.d_private = g_enet;       /* Used to recover private state from dev */
+
+#ifdef CONFIG_NET_ETHERNET
+  /* Determine a semi-unique MAC address from MCU UID
+   * We use UID Low and Mid Low registers to get 64 bits, from which we keep
+   * 48 bits.  We then force unicast and locally administered bits
+   * (b0 and b1, 1st octet)
+   */
+
+  /* hardcoded offset: todo: need proper header file */
+
+#if 0 /* TODO */
+  uidl   = getreg32(IMX_OCOTP_BASE + 0x410);
+  uidml  = getreg32(IMX_OCOTP_BASE + 0x420);
+#endif
+
+  mac    = priv->dev.d_mac.ether.ether_addr_octet;
+
+  uidml |= 0x00000200;
+  uidml &= 0x0000feff;
+
+  mac[0] = (uidml & 0x0000ff00) >> 8;
+  mac[1] = (uidml & 0x000000ff);
+  mac[2] = (uidl &  0xff000000) >> 24;
+  mac[3] = (uidl &  0x00ff0000) >> 16;
+  mac[4] = (uidl &  0x0000ff00) >> 8;
+  mac[5] = (uidl &  0x000000ff);
+#endif
+
+#ifdef CONFIG_IMX_ENET_PHYINIT
+  /* Perform any necessary, one-time, board-specific PHY initialization */
+
+  ret = imx_phy_boardinitialize(0);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to initialize the PHY: %d\n", ret);
+      return ret;
+    }
+#endif
+
+  /* Put the interface in the down state.  This usually amounts to resetting
+   * the device and/or calling imx_ifdown().
+   */
+
+  imx_ifdown(&priv->dev);
+
+  /* Register the device with the OS so that socket IOCTLs can be performed */
+
+  netdev_register(&priv->dev, NET_LL_ETHERNET);
+
+  UNUSED(ret);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_netinitialize
+ *
+ * Description:
+ *   Initialize the first network interface.  If there are more than one
+ *   interface in the chip, then board-specific logic will have to provide
+ *   this function to determine which, if any, Ethernet controllers should
+ *   be initialized.
+ *
+ ****************************************************************************/
+
+#if CONFIG_IMX_ENET_NETHIFS == 1 && !defined(CONFIG_NETDEV_LATEINIT)
+void arm_netinitialize(void)
+{
+  imx_netinitialize(0);
+}
+#endif
+
+#endif /* CONFIG_IMX_ENET */
diff --git a/arch/arm/src/imx6/imx_enet.h b/arch/arm/src/imx6/imx_enet.h
new file mode 100644
index 0000000..b8e59e0
--- /dev/null
+++ b/arch/arm/src/imx6/imx_enet.h
@@ -0,0 +1,108 @@
+/************************************************************************************
+ * arch/arm/src/imx6/imx_enet.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_IMX6_IMX_ENET_H
+#define __ARCH_ARM_SRC_IMX6_IMX_ENET_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "hardware/imx_enet.h"
+
+#ifdef CONFIG_IMX_ENET
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Definitions for use with imx_phy_boardinitialize */
+
+#define EMAC_INTF 0
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Function: up_netinitialize
+ *
+ * Description:
+ *   Initialize the first network interface.  If there are more than one
+ *   interface in the chip, then board-specific logic will have to provide
+ *   this function to determine which, if any, Ethernet controllers should
+ *   be initialized.  Also prototyped in up_internal.h.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *   Called very early in the initialization sequence.
+ *
+ ************************************************************************************/
+
+void up_netinitialize(void);
+
+/************************************************************************************
+ * Function: imx_phy_boardinitialize
+ *
+ * Description:
+ *   Some boards require specialized initialization of the PHY before it can be
+ *   used.  This may include such things as configuring GPIOs, resetting the PHY,
+ *   etc.  If CONFIG_IMX_ENET_PHYINIT is defined in the configuration then the
+ *   board specific logic must provide imx_phyinitialize();  The i.MX RT Ethernet
+ *   driver will call this function one time before it first uses the PHY.
+ *
+ * Input Parameters:
+ *   intf - Always zero for now.
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_IMX_ENET_PHYINIT
+int imx_phy_boardinitialize(int intf);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_IMX_ENET */
+#endif /* __ARCH_ARM_SRC_IMX6_IMX_ENET_H */
diff --git a/boards/arm/imx6/sabre-6quad/configs/netnsh/defconfig b/boards/arm/imx6/sabre-6quad/configs/netnsh/defconfig
new file mode 100644
index 0000000..b53d32a
--- /dev/null
+++ b/boards/arm/imx6/sabre-6quad/configs/netnsh/defconfig
@@ -0,0 +1,88 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="sabre-6quad"
+CONFIG_ARCH_BOARD_SABRE_6QUAD=y
+CONFIG_ARCH_BUTTONS=y
+CONFIG_ARCH_CHIP="imx6"
+CONFIG_ARCH_CHIP_IMX6=y
+CONFIG_ARCH_CHIP_IMX6_6QUAD=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_IRQBUTTONS=y
+CONFIG_ARCH_LOWVECTORS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=99369
+CONFIG_BOOT_RUNFROMSDRAM=y
+CONFIG_BUILTIN=y
+CONFIG_CLOCK_MONOTONIC=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_NET=y
+CONFIG_DEBUG_NET_ERROR=y
+CONFIG_DEBUG_NET_WARN=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ETH0_PHY_KSZ8081=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IMX6_ENET=y
+CONFIG_IMX6_UART1=y
+CONFIG_IMX_DDR_SIZE=1073741824
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MAX_TASKS=16
+CONFIG_NET=y
+CONFIG_NETDB_DNSCLIENT=y
+CONFIG_NETDB_DNSCLIENT_ENTRIES=4
+CONFIG_NETDB_DNSSERVER_NOADDR=y
+CONFIG_NETINIT_DRIPADDR=0x0a000201
+CONFIG_NETINIT_IPADDR=0x0a00020f
+CONFIG_NETINIT_NOMAC=y
+CONFIG_NETUTILS_DHCPC=y
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NETUTILS_TFTPC=y
+CONFIG_NETUTILS_WEBCLIENT=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_ETH_PKTSIZE=1500
+CONFIG_NET_ICMP=y
+CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_MAX_LISTENPORTS=8
+CONFIG_NET_STATISTICS=y
+CONFIG_NET_TCP=y
+CONFIG_NET_UDP=y
+CONFIG_NET_UDP_CHECKSUMS=y
+CONFIG_NFILE_DESCRIPTORS=8
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=1073741824
+CONFIG_RAM_START=0x10000000
+CONFIG_RAM_VSTART=0x10000000
+CONFIG_RAW_BINARY=y
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKPRIORITY=192
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=23
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2020
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART1_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"


[incubator-nuttx] 02/03: arch: imx6: Fix peripheral IP offsets in AIPS-2

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 1725e50a134b4a5612d55bd047857c7ff03940c6
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Wed Dec 23 19:10:15 2020 +0900

    arch: imx6: Fix peripheral IP offsets in AIPS-2
    
    Summary:
    - This commit fixes peripheral IP offsets in AIPS-2
    
    Impact:
    - No impact because there is no drivers
    
    Testing:
    - Tested with sabre-6quad:nsh and sabre-6quad:smp
---
 arch/arm/src/imx6/hardware/imx_memorymap.h | 128 ++++++++++++++---------------
 1 file changed, 64 insertions(+), 64 deletions(-)

diff --git a/arch/arm/src/imx6/hardware/imx_memorymap.h b/arch/arm/src/imx6/hardware/imx_memorymap.h
index ed79b2b..40629b4 100644
--- a/arch/arm/src/imx6/hardware/imx_memorymap.h
+++ b/arch/arm/src/imx6/hardware/imx_memorymap.h
@@ -246,73 +246,73 @@
 
 /* i.MX6 AIPS-2 PSECTION Offsets */
 
-#define IMX_CAAM_OFFSET          0x00100000  /* 00100000 0210ffff CAAM 64 KB */
-                                             /* 00110000 0213ffff Reserved 192 KB */
-#define IMX_DAP_OFFSET           0x00140000  /* 00140000 00160fff ARM Cortex A9 MPCore / DAP 132 KB (See below) */
-                                             /* 00161000 0017bfff ARM Cortex A9 MPCore - Reserved 108 KB */
-#define IMX_AIPS2CGF_OFFSET      0x0017c000  /* 0017c000 0017ffff AIPS-2 configuration 16 KB */
-                                             /* 00180000 00183fff Reserved 16 KB */
-#define IMX_USBOH3_OFFSET        0x00184000  /* 00184000 00187fff USBOH3 (USB) 16 KB */
-#define IMX_ENET_OFFSET          0x00188000  /* 00188000 0018bfff ENET 16 KB */
-#define IMX_MLB150_OFFSET        0x0018c000  /* 0018c000 0018ffff MLB150 16 KB */
-#define IMX_USDHC1_OFFSET        0x00190000  /* 00190000 00193fff uSDHC1 16 KB */
-#define IMX_USDHC2_OFFSET        0x00194000  /* 00194000 00197fff uSDHC2 16 KB */
-#define IMX_USDHC3_OFFSET        0x00198000  /* 00198000 0019bfff uSDHC3 16 KB */
-#define IMX_USDHC4_OFFSET        0x0019c000  /* 0019c000 0019ffff uSDHC4 16 KB */
-#define IMX_I2C1_OFFSET          0x001a0000  /* 001a0000 001a3fff I2C1 16 KB */
-#define IMX_I2C2_OFFSET          0x001a4000  /* 001a4000 001a7fff I2C2 16 KB */
-#define IMX_I2C3_OFFSET          0x001a8000  /* 001a8000 001abfff I2C3 16 KB */
-#define IMX_ROMCP_OFFSET         0x001ac000  /* 001ac000 001affff ROMCP 16 KB */
-#define IMX_MMDC_OFFSET          0x001b0000  /* 001b0000 001b3fff MMDC 16 KB */
-#define IMX_MMDCP1_OFFSET        0x001b4000  /* 001b4000 001b7fff MMDC (port 1) 16 KB */
-#define IMX_EIM_OFFSET           0x001b8000  /* 001b8000 001bbfff EIM 16 KB */
-#define IMX_OCOTPCTRL_OFFSET     0x001bc000  /* 001bc000 001bffff OCOTPCTRL 16 KB */
-#define IMX_CSU_OFFSET           0x001c0000  /* 001c0000 001c3fff CSU 16 KB */
-                                             /* 001c4000 001c7fff Reserved */
-                                             /* 001c8000 Reserved */
-                                             /* 001cc000 Reserved */
-#define IMX_TZASC1_OFFSET        0x001d0000  /* 001d0000 001d3fff TZASC1 16 KB */
-#define IMX_TZASC2_OFFSET        0x001d4000  /* 001d4000 001d7fff TZASC2 16 KB */
-#define IMX_AUDMUX_OFFSET        0x001d8000  /* 001d8000 001dbfff AUDMUX 16 KB */
-#define IMX_MIPICSI_OFFSET       0x001dc000  /* 001dc000 001dffff MIPI (CSI port) 16 KB */
-#define IMX_MIPIDSI_OFFSET       0x001e0000  /* 001e0000 001e3fff MIPI (DSI port) 16 KB */
-#define IMX_VDOA_OFFSET          0x001e4000  /* 001e4000 001e7fff VDOA 16 KB */
-#define IMX_UART2_OFFSET         0x001e8000  /* 001e8000 001ebfff UART2 16 KB */
-#define IMX_UART3_OFFSET         0x001ec000  /* 001ec000 001effff UART3 16 KB */
-#define IMX_UART4_OFFSET         0x001f0000  /* 001f0000 001f3fff UART4 16 KB */
-#define IMX_UART5_OFFSET         0x001f4000  /* 001f4000 001f7fff UART5 16 KB */
-                                             /* 001f8000 001fbfff Reserved 16 KB */
+#define IMX_CAAM_OFFSET          0x00000000  /* 00000000 0000ffff CAAM 64 KB */
+                                             /* 00010000 0003ffff Reserved 192 KB */
+#define IMX_DAP_OFFSET           0x00040000  /* 00040000 00060fff ARM Cortex A9 MPCore / DAP 132 KB (See below) */
+                                             /* 00061000 0007bfff ARM Cortex A9 MPCore - Reserved 108 KB */
+#define IMX_AIPS2CGF_OFFSET      0x0007c000  /* 0007c000 0007ffff AIPS-2 configuration 16 KB */
+                                             /* 00080000 00083fff Reserved 16 KB */
+#define IMX_USBOH3_OFFSET        0x00084000  /* 00084000 00087fff USBOH3 (USB) 16 KB */
+#define IMX_ENET_OFFSET          0x00088000  /* 00088000 0008bfff ENET 16 KB */
+#define IMX_MLB150_OFFSET        0x0008c000  /* 0008c000 0008ffff MLB150 16 KB */
+#define IMX_USDHC1_OFFSET        0x00090000  /* 00090000 00093fff uSDHC1 16 KB */
+#define IMX_USDHC2_OFFSET        0x00094000  /* 00094000 00097fff uSDHC2 16 KB */
+#define IMX_USDHC3_OFFSET        0x00098000  /* 00098000 0009bfff uSDHC3 16 KB */
+#define IMX_USDHC4_OFFSET        0x0009c000  /* 0009c000 0009ffff uSDHC4 16 KB */
+#define IMX_I2C1_OFFSET          0x000a0000  /* 000a0000 000a3fff I2C1 16 KB */
+#define IMX_I2C2_OFFSET          0x000a4000  /* 000a4000 000a7fff I2C2 16 KB */
+#define IMX_I2C3_OFFSET          0x000a8000  /* 000a8000 000abfff I2C3 16 KB */
+#define IMX_ROMCP_OFFSET         0x000ac000  /* 000ac000 000affff ROMCP 16 KB */
+#define IMX_MMDC_OFFSET          0x000b0000  /* 000b0000 000b3fff MMDC 16 KB */
+#define IMX_MMDCP1_OFFSET        0x000b4000  /* 000b4000 000b7fff MMDC (port 1) 16 KB */
+#define IMX_EIM_OFFSET           0x000b8000  /* 000b8000 000bbfff EIM 16 KB */
+#define IMX_OCOTPCTRL_OFFSET     0x000bc000  /* 000bc000 000bffff OCOTPCTRL 16 KB */
+#define IMX_CSU_OFFSET           0x000c0000  /* 000c0000 000c3fff CSU 16 KB */
+                                             /* 000c4000 000c7fff Reserved */
+                                             /* 000c8000 Reserved */
+                                             /* 000cc000 Reserved */
+#define IMX_TZASC1_OFFSET        0x000d0000  /* 000d0000 000d3fff TZASC1 16 KB */
+#define IMX_TZASC2_OFFSET        0x000d4000  /* 000d4000 000d7fff TZASC2 16 KB */
+#define IMX_AUDMUX_OFFSET        0x000d8000  /* 000d8000 000dbfff AUDMUX 16 KB */
+#define IMX_MIPICSI_OFFSET       0x000dc000  /* 000dc000 000dffff MIPI (CSI port) 16 KB */
+#define IMX_MIPIDSI_OFFSET       0x000e0000  /* 000e0000 000e3fff MIPI (DSI port) 16 KB */
+#define IMX_VDOA_OFFSET          0x000e4000  /* 000e4000 000e7fff VDOA 16 KB */
+#define IMX_UART2_OFFSET         0x000e8000  /* 000e8000 000ebfff UART2 16 KB */
+#define IMX_UART3_OFFSET         0x000ec000  /* 000ec000 000effff UART3 16 KB */
+#define IMX_UART4_OFFSET         0x000f0000  /* 000f0000 000f3fff UART4 16 KB */
+#define IMX_UART5_OFFSET         0x000f4000  /* 000f4000 000f7fff UART5 16 KB */
+                                             /* 000f8000 000fbfff Reserved 16 KB */
 
 /* i.MX6 DAP AIPS-2 PSECTION Offsets */
 
-#define IMX_DAPROM_OFFSET        0x00140000  /* 00140000 00140fff 4 KB DAP ROM Table */
-#define IMX_ETB_OFFSET           0x00141000  /* 00141000 00141fff 4 KB ETB */
-#define IMX_EXTCTI_OFFSET        0x00142000  /* 00142000 00142fff 4 KB ext. CTI */
-#define IMX_TPIU_OFFSET          0x00143000  /* 00143000 00143fff 4 KB TPIU */
-#define IMX_FUNNEL_OFFSET        0x00144000  /* 00144000 00144fff 4 KB FUNNEL */
-                                             /* 00145000 0014efff 40 KB Reserved */
-#define IMX_CA9INTEG_OFFSET      0x0014f000  /* 0014f000 0014ffff 4 KB CA9-INTEG */
-#define IMX_CPUDBG_OFFSET(n)     (0x00150000 + ((n) << 13))
-#define IMX_CPUPMU_OFFSET(n)     (0x00151000 + ((n) << 13))
-#define IMX_CPU0DBG_OFFSET       0x00150000  /* 00150000 00150fff 4 KB CPU0 Debug I/F */
-#define IMX_CPU0PMU_OFFSET       0x00151000  /* 00151000 00151fff 4 KB CPU0 PMU */
-#define IMX_CPU1DBG_OFFSET       0x00152000  /* 00152000 00152fff 4 KB CPU1 Debug I/F */
-#define IMX_CPU1PMC_OFFSET       0x00153000  /* 00153000 00153fff 4 KB CPU1 PMU */
-#define IMX_CPU2DBG_OFFSET       0x00154000  /* 00154000 00154fff 4 KB CPU2 Debug I/F */
-#define IMX_CPU2PMU_OFFSET       0x00155000  /* 00155000 00155fff 4 KB CPU2 PMU */
-#define IMX_CPU3DBG_OFFSET       0x00156000  /* 00156000 00156fff 4 KB CPU3 Debug I/F */
-#define IMX_CPU3PMU_OFFSET       0x00157000  /* 00157000 00157fff 4 KB CPU3 PMU */
-#define IMX_CTI_OFFSET(n)        (0x00158000 + ((n) << 12))
-#define IMX_CTI0_OFFSET          0x00158000  /* 00158000 00158fff 4 KB CTI0 */
-#define IMX_CTI1_OFFSET          0x00159000  /* 00159000 00159fff 4 KB CTI1 */
-#define IMX_CTI2_OFFSET          0x0015a000  /* 0015a000 0015afff 4 KB CTI2 */
-#define IMX_CTI3_OFFSET          0x0015b000  /* 0015b000 0015bfff 4 KB CTI3 */
-#define IMX_PTM_OFFSET(n)        (0x0015c000 + ((n) << 12))
-#define IMX_PTM0_OFFSET          0x0015c000  /* 0015c000 0015cfff 4 KB PTM0 */
-#define IMX_PTM1_OFFSET          0x0015d000  /* 0015d000 0015dfff 4 KB PTM1 */
-#define IMX_PTM2_OFFSET          0x0015e000  /* 0015e000 0015efff 4 KB PTM2 */
-#define IMX_PTM3_OFFSET          0x0015f000  /* 0015f000 0015ffff 4 KB PTM3 */
-#define IMX_PLATCTRL_OFFSET      0x00160000  /* 00160000 00160fff 4 KB Platform Control */
+#define IMX_DAPROM_OFFSET        0x00040000  /* 00040000 00040fff 4 KB DAP ROM Table */
+#define IMX_ETB_OFFSET           0x00041000  /* 00041000 00041fff 4 KB ETB */
+#define IMX_EXTCTI_OFFSET        0x00042000  /* 00042000 00042fff 4 KB ext. CTI */
+#define IMX_TPIU_OFFSET          0x00043000  /* 00043000 00043fff 4 KB TPIU */
+#define IMX_FUNNEL_OFFSET        0x00044000  /* 00044000 00044fff 4 KB FUNNEL */
+                                             /* 00045000 0004efff 40 KB Reserved */
+#define IMX_CA9INTEG_OFFSET      0x0004f000  /* 0004f000 0004ffff 4 KB CA9-INTEG */
+#define IMX_CPUDBG_OFFSET(n)     (0x00050000 + ((n) << 13))
+#define IMX_CPUPMU_OFFSET(n)     (0x00051000 + ((n) << 13))
+#define IMX_CPU0DBG_OFFSET       0x00050000  /* 00050000 00050fff 4 KB CPU0 Debug I/F */
+#define IMX_CPU0PMU_OFFSET       0x00051000  /* 00051000 00051fff 4 KB CPU0 PMU */
+#define IMX_CPU1DBG_OFFSET       0x00052000  /* 00052000 00052fff 4 KB CPU1 Debug I/F */
+#define IMX_CPU1PMC_OFFSET       0x00053000  /* 00053000 00053fff 4 KB CPU1 PMU */
+#define IMX_CPU2DBG_OFFSET       0x00054000  /* 00054000 00054fff 4 KB CPU2 Debug I/F */
+#define IMX_CPU2PMU_OFFSET       0x00055000  /* 00055000 00055fff 4 KB CPU2 PMU */
+#define IMX_CPU3DBG_OFFSET       0x00056000  /* 00056000 00056fff 4 KB CPU3 Debug I/F */
+#define IMX_CPU3PMU_OFFSET       0x00057000  /* 00057000 00057fff 4 KB CPU3 PMU */
+#define IMX_CTI_OFFSET(n)        (0x00058000 + ((n) << 12))
+#define IMX_CTI0_OFFSET          0x00058000  /* 00058000 00058fff 4 KB CTI0 */
+#define IMX_CTI1_OFFSET          0x00059000  /* 00059000 00059fff 4 KB CTI1 */
+#define IMX_CTI2_OFFSET          0x0005a000  /* 0005a000 0005afff 4 KB CTI2 */
+#define IMX_CTI3_OFFSET          0x0005b000  /* 0005b000 0005bfff 4 KB CTI3 */
+#define IMX_PTM_OFFSET(n)        (0x0005c000 + ((n) << 12))
+#define IMX_PTM0_OFFSET          0x0005c000  /* 0005c000 0005cfff 4 KB PTM0 */
+#define IMX_PTM1_OFFSET          0x0005d000  /* 0005d000 0005dfff 4 KB PTM1 */
+#define IMX_PTM2_OFFSET          0x0005e000  /* 0005e000 0005efff 4 KB PTM2 */
+#define IMX_PTM3_OFFSET          0x0005f000  /* 0005f000 0005ffff 4 KB PTM3 */
+#define IMX_PLATCTRL_OFFSET      0x00060000  /* 00060000 00060fff 4 KB Platform Control */
 
 /* i.MX6 SATA PSECTION Offsets */