[U-Boot] [PATCH 1/5] powerpc/85xx: Add support for FMan ethernet in Independent mode

Kumar Gala galak at kernel.crashing.org
Mon Aug 1 08:23:41 CEST 2011


The Frame Manager (FMan) on QorIQ SoCs with DPAA (datapath acceleration
architecture) is the ethernet contoller block.  Normally it is utilized
via Queue Manager (Qman) and Buffer Manager (Bman).  However for boot
usage the FMan supports a mode similar to QE or CPM ethernet collers
called Independent mode.

Additionally the FMan block supports multiple 1g and 10g interfaces as a
single entity in the system rather than each controller being managed
uniquely.  This means we have to initialize all of Fman regardless of
the number of interfaces we utilize.

Different SoCs support different combinations of the number of FMan as
well as the number of 1g & 10g interfaces support per Fman.

We add support for the following SoCs:
 * P1023 - 1 Fman, 2x1g
 * P4080 - 2 Fman, each Fman has 4x1g and 1x10g
 * P204x/P3041/P5020 - 1 Fman, 5x1g, 1x10g

Signed-off-by: Dave Liu <daveliu at freescale.com>
Signed-off-by: Andy Fleming <afleming at freescale.com>
Signed-off-by: Timur Tabi <timur at freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
Signed-off-by: Dai Haruki <dai.haruki at freescale.com>
Signed-off-by: Kim Phillips <kim.phillips at freescale.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu at freescale.com>
Signed-off-by: Lei Xu <B33228 at freescale.com>
Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
Signed-off-by: Scott Wood <scottwood at freescale.com>
Signed-off-by: Shaohui Xie <b21989 at freescale.com>
Signed-off-by: Kumar Gala <galak at kernel.crashing.org>
---
 Makefile                              |    1 +
 arch/powerpc/cpu/mpc85xx/cpu_init.c   |    5 +
 arch/powerpc/cpu/mpc8xxx/cpu.c        |    4 +
 arch/powerpc/include/asm/config.h     |    5 +
 arch/powerpc/include/asm/fsl_dtsec.h  |  244 ++++++++++++
 arch/powerpc/include/asm/fsl_fman.h   |  257 ++++++++++++-
 arch/powerpc/include/asm/fsl_tgec.h   |  215 +++++++++++
 arch/powerpc/include/asm/immap_85xx.h |   23 +-
 drivers/net/Makefile                  |    1 +
 drivers/net/fm/Makefile               |   61 +++
 drivers/net/fm/dtsec.c                |  181 +++++++++
 drivers/net/fm/eth.c                  |  670 +++++++++++++++++++++++++++++++++
 drivers/net/fm/fm.c                   |  432 +++++++++++++++++++++
 drivers/net/fm/fm.h                   |  154 ++++++++
 drivers/net/fm/init.c                 |  208 ++++++++++
 drivers/net/fm/p1023.c                |   68 ++++
 drivers/net/fm/p4080.c                |   94 +++++
 drivers/net/fm/p5020.c                |   85 +++++
 drivers/net/fm/tgec.c                 |  119 ++++++
 drivers/net/fm/tgec_phy.c             |  139 +++++++
 include/fm_eth.h                      |  114 ++++++
 21 files changed, 3068 insertions(+), 12 deletions(-)
 create mode 100644 arch/powerpc/include/asm/fsl_dtsec.h
 create mode 100644 arch/powerpc/include/asm/fsl_tgec.h
 create mode 100644 drivers/net/fm/Makefile
 create mode 100644 drivers/net/fm/dtsec.c
 create mode 100644 drivers/net/fm/eth.c
 create mode 100644 drivers/net/fm/fm.c
 create mode 100644 drivers/net/fm/fm.h
 create mode 100644 drivers/net/fm/init.c
 create mode 100644 drivers/net/fm/p1023.c
 create mode 100644 drivers/net/fm/p4080.c
 create mode 100644 drivers/net/fm/p5020.c
 create mode 100644 drivers/net/fm/tgec.c
 create mode 100644 drivers/net/fm/tgec_phy.c
 create mode 100644 include/fm_eth.h

diff --git a/Makefile b/Makefile
index ac757e6..b176464 100644
--- a/Makefile
+++ b/Makefile
@@ -257,6 +257,7 @@ LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
 endif
 ifeq ($(CPU),mpc85xx)
 LIBS += drivers/qe/libqe.o
+LIBS += drivers/net/fm/libfm.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
 LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
 endif
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index 6aca166..27f836c 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -31,6 +31,7 @@
 #include <asm/processor.h>
 #include <ioports.h>
 #include <sata.h>
+#include <fm_eth.h>
 #include <asm/io.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
@@ -472,6 +473,10 @@ skip_l2:
 	}
 #endif
 
+#ifdef CONFIG_FMAN_ENET
+	fman_enet_init();
+#endif
+
 	return 0;
 }
 
diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c
index 767bc52..861952d 100644
--- a/arch/powerpc/cpu/mpc8xxx/cpu.c
+++ b/arch/powerpc/cpu/mpc8xxx/cpu.c
@@ -27,6 +27,7 @@
 #include <common.h>
 #include <command.h>
 #include <tsec.h>
+#include <fm_eth.h>
 #include <netdev.h>
 #include <asm/cache.h>
 #include <asm/io.h>
@@ -174,5 +175,8 @@ int cpu_eth_init(bd_t *bis)
 	tsec_standard_init(bis);
 #endif
 
+#ifdef CONFIG_FMAN_ENET
+	fm_standard_init(bis);
+#endif
 	return 0;
 }
diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
index 9aad9be..c5e5c9c 100644
--- a/arch/powerpc/include/asm/config.h
+++ b/arch/powerpc/include/asm/config.h
@@ -96,6 +96,11 @@
 #endif /* TSEC_ENET */
 #endif /* !CONFIG_PHYLIB */
 
+/* The FMAN driver uses the PHYLIB infrastructure */
+#if defined(CONFIG_FMAN_ENET)
+#define CONFIG_PHYLIB
+#endif
+
 /* All PPC boards must swap IDE bytes */
 #define CONFIG_IDE_SWAP_IO
 
diff --git a/arch/powerpc/include/asm/fsl_dtsec.h b/arch/powerpc/include/asm/fsl_dtsec.h
new file mode 100644
index 0000000..d1d993c
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_dtsec.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __DTSEC_H__
+#define __DTSEC_H__
+
+#include <asm/types.h>
+
+struct dtsec {
+	u32	tsec_id;	/* controller ID and version */
+	u32	tsec_id2;	/* controller ID and configuration */
+	u32	ievent;		/* interrupt event */
+	u32	imask;		/* interrupt mask */
+	u32	res0;
+	u32	ecntrl;		/* ethernet control and configuration */
+	u32	ptv;		/* pause time value */
+	u32	tbipa;		/* TBI PHY address */
+	u32	res1[8];
+	u32	tctrl;		/* Transmit control register */
+	u32	res2[3];
+	u32	rctrl;		/* Receive control register */
+	u32	res3[11];
+	u32	igaddr[8];	/* Individual group address */
+	u32	gaddr[8];	/* group address */
+	u32	res4[16];
+	u32	maccfg1;	/* MAC configuration register 1 */
+	u32	maccfg2;	/* MAC configuration register 2 */
+	u32	ipgifg;		/* inter-packet/inter-frame gap */
+	u32	hafdup;		/* half-duplex control */
+	u32	maxfrm;		/* Maximum frame size */
+	u32	res5[3];
+	u32	miimcfg;	/* MII management configuration */
+	u32	miimcom;	/* MII management command */
+	u32	miimadd;	/* MII management address */
+	u32	miimcon;	/* MII management control */
+	u32	miimstat;	/* MII management status */
+	u32	miimind;	/* MII management indicator */
+	u32	res6;
+	u32	ifstat;		/* Interface status */
+	u32	macstnaddr1;	/* MAC station address 1 */
+	u32	macstnaddr2;	/* MAC station address 2 */
+	u32	res7[46];
+	/* transmit and receive counter */
+	u32	tr64;		/* Tx and Rx 64 bytes frame */
+	u32	tr127;		/* Tx and Rx 65 to 127 bytes frame */
+	u32	tr255;		/* Tx and Rx 128 to 255 bytes frame */
+	u32	tr511;		/* Tx and Rx 256 to 511 bytes frame */
+	u32	tr1k;		/* Tx and Rx 512 to 1023 bytes frame */
+	u32	trmax;		/* Tx and Rx 1024 to 1518 bytes frame */
+	u32	trmgv;		/* Tx and Rx 1519 to 1522 good VLAN frame */
+	/* receive counters */
+	u32	rbyt;		/* Receive byte counter */
+	u32	rpkt;		/* Receive packet counter */
+	u32	rfcs;		/* Receive FCS error */
+	u32	rmca;		/* Receive multicast packet */
+	u32	rbca;		/* Receive broadcast packet */
+	u32	rxcf;		/* Receive control frame */
+	u32	rxpf;		/* Receive pause frame */
+	u32	rxuo;		/* Receive unknown OP code */
+	u32	raln;		/* Receive alignment error */
+	u32	rflr;		/* Receive frame length error */
+	u32	rcde;		/* Receive code error */
+	u32	rcse;		/* Receive carrier sense error */
+	u32	rund;		/* Receive undersize packet */
+	u32	rovr;		/* Receive oversize packet */
+	u32	rfrg;		/* Receive fragments counter */
+	u32	rjbr;		/* Receive jabber counter */
+	u32	rdrp;		/* Receive drop counter */
+	/* transmit counters */
+	u32	tbyt;		/* Transmit byte counter */
+	u32	tpkt;		/* Transmit packet */
+	u32	tmca;		/* Transmit multicast packet */
+	u32	tbca;		/* Transmit broadcast packet */
+	u32	txpf;		/* Transmit pause control frame */
+	u32	tdfr;		/* Transmit deferral packet */
+	u32	tedf;		/* Transmit excessive deferral pkt */
+	u32	tscl;		/* Transmit single collision pkt */
+	u32	tmcl;		/* Transmit multiple collision pkt */
+	u32	tlcl;		/* Transmit late collision pkt */
+	u32	txcl;		/* Transmit excessive collision */
+	u32	tncl;		/* Transmit total collision */
+	u32	res8;
+	u32	tdrp;		/* Transmit drop frame */
+	u32	tjbr;		/* Transmit jabber frame */
+	u32	tfcs;		/* Transmit FCS error */
+	u32	txcf;		/* Transmit control frame */
+	u32	tovr;		/* Transmit oversize frame */
+	u32	tund;		/* Transmit undersize frame */
+	u32	tfrg;		/* Transmit fragments frame */
+	/* counter controls */
+	u32	car1;		/* carry register 1 */
+	u32	car2;		/* carry register 2 */
+	u32	cam1;		/* carry register 1 mask */
+	u32	cam2;		/* carry register 2 mask */
+	u32	res9[80];
+};
+
+
+/* TBI register addresses */
+#define TBI_CR			0x00
+#define TBI_SR			0x01
+#define TBI_ANA			0x04
+#define TBI_ANLPBPA		0x05
+#define TBI_ANEX		0x06
+#define TBI_TBICON		0x11
+
+/* TBI MDIO register bit fields*/
+#define TBICON_CLK_SELECT	0x0020
+#define TBIANA_ASYMMETRIC_PAUSE 0x0100
+#define TBIANA_SYMMETRIC_PAUSE  0x0080
+#define TBIANA_HALF_DUPLEX	0x0040
+#define TBIANA_FULL_DUPLEX	0x0020
+#define TBICR_PHY_RESET		0x8000
+#define TBICR_ANEG_ENABLE	0x1000
+#define TBICR_RESTART_ANEG	0x0200
+#define TBICR_FULL_DUPLEX	0x0100
+#define TBICR_SPEED1_SET	0x0040
+
+/* IEVENT - interrupt events register */
+#define IEVENT_BABR	0x80000000 /* Babbling receive error */
+#define IEVENT_RXC	0x40000000 /* pause control frame received */
+#define IEVENT_MSRO	0x04000000 /* MIB counter overflow */
+#define IEVENT_GTSC	0x02000000 /* Graceful transmit stop complete */
+#define IEVENT_BABT	0x01000000 /* Babbling transmit error */
+#define IEVENT_TXC	0x00800000 /* control frame transmitted */
+#define IEVENT_TXE	0x00400000 /* Transmit channel error */
+#define IEVENT_LC	0x00040000 /* Late collision occurred */
+#define IEVENT_CRL	0x00020000 /* Collision retry exceed limit */
+#define IEVENT_XFUN	0x00010000 /* Transmit FIFO underrun */
+#define IEVENT_ABRT	0x00008000 /* Transmit packet abort */
+#define IEVENT_MMRD	0x00000400 /* MII management read complete */
+#define IEVENT_MMWR	0x00000200 /* MII management write complete */
+#define IEVENT_GRSC	0x00000100 /* Graceful stop complete */
+#define IEVENT_TDPE	0x00000002 /* Internal data parity error on Tx */
+#define IEVENT_RDPE	0x00000001 /* Internal data parity error on Rx */
+
+#define IEVENT_CLEAR_ALL	0xffffffff
+
+/* IMASK - interrupt mask register */
+#define IMASK_BREN	0x80000000 /* Babbling receive enable */
+#define IMASK_RXCEN	0x40000000 /* receive control enable */
+#define IMASK_MSROEN	0x04000000 /* MIB counter overflow enable */
+#define IMASK_GTSCEN	0x02000000 /* Graceful Tx stop complete enable */
+#define IMASK_BTEN	0x01000000 /* Babbling transmit error enable */
+#define IMASK_TXCEN	0x00800000 /* control frame transmitted enable */
+#define IMASK_TXEEN	0x00400000 /* Transmit channel error enable */
+#define IMASK_LCEN	0x00040000 /* Late collision interrupt enable */
+#define IMASK_CRLEN	0x00020000 /* Collision retry exceed limit */
+#define IMASK_XFUNEN	0x00010000 /* Transmit FIFO underrun enable */
+#define IMASK_ABRTEN	0x00008000 /* Transmit packet abort enable */
+#define IMASK_MMRDEN	0x00000400 /* MII management read complete enable */
+#define IMASK_MMWREN	0x00000200 /* MII management write complete enable */
+#define IMASK_GRSCEN	0x00000100 /* Graceful stop complete interrupt enable */
+#define IMASK_TDPEEN	0x00000002 /* Internal data parity error on Tx enable */
+#define IMASK_RDPEEN	0x00000001 /* Internal data parity error on Rx enable */
+
+#define IMASK_MASK_ALL	0x00000000
+
+/* ECNTRL - ethernet control register */
+#define ECNTRL_CFG_RO	0x80000000 /* GMIIM, RPM, R100M, SGMIIM bits are RO */
+#define ECNTRL_CLRCNT	0x00004000 /* clear all statistics */
+#define ECNTRL_AUTOZ	0x00002000 /* auto zero MIB counter */
+#define ECNTRL_STEN	0x00001000 /* enable internal counters to update */
+#define ECNTRL_GMIIM	0x00000040 /* 1- GMII or RGMII interface mode */
+#define ECNTRL_TBIM	0x00000020 /* 1- Ten-bit interface mode */
+#define ECNTRL_RPM	0x00000010 /* 1- RGMII reduced-pin mode */
+#define ECNTRL_R100M	0x00000008 /* 1- RGMII 100 Mbps, SGMII 100 Mbps
+				      0- RGMII 10 Mbps, SGMII 10 Mbps */
+#define ECNTRL_SGMIIM	0x00000002 /* 1- SGMII interface mode */
+#define ECNTRL_TBIM	0x00000020 /* 1- TBI Interface mode (for SGMII) */
+
+#define ECNTRL_DEFAULT	(ECNTRL_TBIM | ECNTRL_R100M | ECNTRL_SGMIIM)
+
+/* TCTRL - Transmit control register */
+#define TCTRL_THDF	0x00000800 /* Transmit half-duplex flow control */
+#define TCTRL_TTSE	0x00000040 /* Transmit time-stamp enable */
+#define TCTRL_GTS	0x00000020 /* Graceful transmit stop */
+#define TCTRL_RFC_PAUSE	0x00000010 /* Receive flow control pause frame */
+
+/* RCTRL - Receive control register */
+#define RCTRL_PAL_MASK	0x001f0000 /* packet alignment padding length */
+#define RCTRL_PAL_SHIFT	16
+#define RCTRL_CFA	0x00008000 /* control frame accept enable */
+#define RCTRL_GHTX	0x00000800 /* group address hash table extend */
+#define RCTRL_RTSE	0x00000040 /* receive 1588 time-stamp enable */
+#define RCTRL_GRS	0x00000020 /* graceful receive stop */
+#define RCTRL_BC_REJ	0x00000010 /* broadcast frame reject */
+#define RCTRL_BC_MPROM	0x00000008 /* all multicast/broadcast frames received */
+#define RCTRL_RSF	0x00000004 /* receive short frame(17~63 bytes) enable */
+#define RCTRL_EMEN	0x00000002 /* Exact match MAC address enable */
+#define RCTRL_UPROM	0x00000001 /* all unicast frame received */
+
+/* MACCFG1 - MAC configuration 1 register */
+#define MACCFG1_SOFT_RST	0x80000000 /* place the MAC in reset */
+#define MACCFG1_RST_RXMAC	0x00080000 /* reset receive MAC control block */
+#define MACCFG1_RST_TXMAC	0x00040000 /* reet transmit MAC control block */
+#define MACCFG1_RST_RXFUN	0x00020000 /* reset receive function block */
+#define MACCFG1_RST_TXFUN	0x00010000 /* reset transmit function block */
+#define MACCFG1_LOOPBACK	0x00000100 /* MAC loopback */
+#define MACCFG1_RX_FLOW		0x00000020 /* Receive flow */
+#define MACCFG1_TX_FLOW		0x00000010 /* Transmit flow */
+#define MACCFG1_SYNC_RXEN	0x00000008 /* Frame reception enabled */
+#define MACCFG1_RX_EN		0x00000004 /* Rx enable */
+#define MACCFG1_SYNC_TXEN	0x00000002 /* Frame transmission is enabled */
+#define MACCFG1_TX_EN		0x00000001 /* Tx enable */
+#define MACCFG1_RXTX_EN		(MACCFG1_RX_EN | MACCFG1_TX_EN)
+
+/* MACCFG2 - MAC configuration 2 register */
+#define MACCFG2_PRE_LEN_MASK	0x0000f000 /* preamble length */
+#define MACCFG2_PRE_LEN(x)	((x << 12) & MACCFG2_PRE_LEN_MASK)
+#define MACCFG2_IF_MODE_MASK	0x00000300
+#define MACCFG2_IF_MODE_NIBBLE	0x00000100 /* MII, 10/100 Mbps MII/RMII */
+#define MACCFG2_IF_MODE_BYTE	0x00000200 /* GMII/TBI, 1000 GMII/TBI */
+#define MACCFG2_PRE_RX_EN	0x00000080 /* receive preamble enable */
+#define MACCFG2_PRE_TX_EN	0x00000040 /* tx preable enable */
+#define MACCFG2_HUGE_FRAME	0x00000020 /* >= max frame len enable */
+#define MACCFG2_LEN_CHECK	0x00000010 /* MAC check frame's length Rx */
+#define MACCFG2_MAG_EN		0x00000008 /* magic packet enable */
+#define MACCFG2_PAD_CRC		0x00000004 /* pad and append CRC */
+#define MACCFG2_CRC_EN		0x00000002 /* MAC appends a CRC on all frames */
+#define MACCFG2_FULL_DUPLEX	0x00000001 /* Full deplex mode */
+
+struct fsl_enet_mac;
+
+void init_dtsec(struct fsl_enet_mac *mac, void *base, void *phyregs,
+		int max_rx_len);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_fman.h b/arch/powerpc/include/asm/fsl_fman.h
index 6c01ffc..fddc0cc 100644
--- a/arch/powerpc/include/asm/fsl_fman.h
+++ b/arch/powerpc/include/asm/fsl_fman.h
@@ -1,7 +1,7 @@
 /*
  * MPC85xx Internal Memory Map
  *
- * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -82,6 +82,189 @@ typedef struct fm_qmi {
 	u8	res[1024];
 } fm_qmi_t;
 
+struct fm_bmi_rx_port {
+	u32 fmbm_rcfg;	/* Rx configuration */
+	u32 fmbm_rst;	/* Rx status */
+	u32 fmbm_rda;	/* Rx DMA attributes */
+	u32 fmbm_rfp;	/* Rx FIFO parameters */
+	u32 fmbm_rfed;	/* Rx frame end data */
+	u32 fmbm_ricp;	/* Rx internal context parameters */
+	u32 fmbm_rim;	/* Rx internal margins */
+	u32 fmbm_rebm;	/* Rx external buffer margins */
+	u32 fmbm_rfne;	/* Rx frame next engine */
+	u32 fmbm_rfca;	/* Rx frame command attributes */
+	u32 fmbm_rfpne;	/* Rx frame parser next engine */
+	u32 fmbm_rpso;	/* Rx parse start offset */
+	u32 fmbm_rpp;	/* Rx policer profile */
+	u32 fmbm_rccb;	/* Rx coarse classification base */
+	u32 res1[0x2];
+	u32 fmbm_rprai[0x8];	/* Rx parse results array Initialization */
+	u32 fmbm_rfqid;		/* Rx frame queue ID */
+	u32 fmbm_refqid;	/* Rx error frame queue ID */
+	u32 fmbm_rfsdm;		/* Rx frame status discard mask */
+	u32 fmbm_rfsem;		/* Rx frame status error mask */
+	u32 fmbm_rfene;		/* Rx frame enqueue next engine */
+	u32 res2[0x23];
+	u32 fmbm_ebmpi[0x8];	/* buffer manager pool information */
+	u32 fmbm_acnt[0x8];	/* allocate counter */
+	u32 res3[0x8];
+	u32 fmbm_cgm[0x8];	/* congestion group map */
+	u32 fmbm_mpd;		/* BMan pool depletion */
+	u32 res4[0x1F];
+	u32 fmbm_rstc;		/* Rx statistics counters */
+	u32 fmbm_rfrc;		/* Rx frame counters */
+	u32 fmbm_rfbc;		/* Rx bad frames counter */
+	u32 fmbm_rlfc;		/* Rx large frames counter */
+	u32 fmbm_rffc;		/* Rx filter frames counter */
+	u32 fmbm_rfdc;		/* Rx frame discard counter */
+	u32 fmbm_rfldec;	/* Rx frames list DMA error counter */
+	u32 fmbm_rodc;		/* Rx out of buffers discard counter */
+	u32 fmbm_rbdc;		/* Rx buffers deallocate counter */
+	u32 res5[0x17];
+	u32 fmbm_rpc;		/* Rx performance counters */
+	u32 fmbm_rpcp;		/* Rx performance count parameters */
+	u32 fmbm_rccn;		/* Rx cycle counter */
+	u32 fmbm_rtuc;		/* Rx tasks utilization counter */
+	u32 fmbm_rrquc;		/* Rx receive queue utilization counter */
+	u32 fmbm_rduc;		/* Rx DMA utilization counter */
+	u32 fmbm_rfuc;		/* Rx FIFO utilization counter */
+	u32 fmbm_rpac;		/* Rx pause activation counter */
+	u32 res6[0x18];
+	u32 fmbm_rdbg;		/* Rx debug configuration */
+};
+
+/* FMBM_RCFG - Rx configuration */
+#define FMBM_RCFG_EN		0x80000000 /* port is enabled to receive data */
+#define FMBM_RCFG_FDOVR		0x02000000 /* frame discard override */
+#define FMBM_RCFG_IM		0x01000000 /* independent mode */
+
+/* FMBM_RST - Rx status */
+#define FMBM_RST_BSY		0x80000000 /* Rx port is busy */
+
+/* FMBM_RFCA - Rx frame command attributes */
+#define FMBM_RFCA_ORDER		0x80000000
+#define FMBM_RFCA_MR_MASK	0x003f0000
+#define FMBM_RFCA_MR(x)		((x << 16) & FMBM_RFCA_MR_MASK)
+
+/* FMBM_RSTC - Rx statistics */
+#define FMBM_RSTC_EN		0x80000000 /* statistics counters enable */
+
+struct fm_bmi_tx_port {
+	u32 fmbm_tcfg;	/* Tx configuration */
+	u32 fmbm_tst;	/* Tx status */
+	u32 fmbm_tda;	/* Tx DMA attributes */
+	u32 fmbm_tfp;	/* Tx FIFO parameters */
+	u32 fmbm_tfed;	/* Tx frame end data */
+	u32 fmbm_ticp;	/* Tx internal context parameters */
+	u32 fmbm_tfne;	/* Tx frame next engine */
+	u32 fmbm_tfca;	/* Tx frame command attributes */
+	u32 fmbm_tcfqid;/* Tx confirmation frame queue ID */
+	u32 fmbm_tfeqid;/* Tx error frame queue ID */
+	u32 fmbm_tfene;	/* Tx frame enqueue next engine */
+	u32 fmbm_trlmts;/* Tx rate limiter scale */
+	u32 fmbm_trlmt;	/* Tx rate limiter */
+	u32 res0[0x73];
+	u32 fmbm_tstc;	/* Tx statistics counters */
+	u32 fmbm_tfrc;	/* Tx frame counter */
+	u32 fmbm_tfdc;	/* Tx frames discard counter */
+	u32 fmbm_tfledc;/* Tx frame length error discard counter */
+	u32 fmbm_tfufdc;/* Tx frame unsupported format discard counter */
+	u32 fmbm_tbdc;	/* Tx buffers deallocate counter */
+	u32 res1[0x1a];
+	u32 fmbm_tpc;	/* Tx performance counters */
+	u32 fmbm_tpcp;	/* Tx performance count parameters */
+	u32 fmbm_tccn;	/* Tx cycle counter */
+	u32 fmbm_ttuc;	/* Tx tasks utilization counter */
+	u32 fmbm_ttcquc;/* Tx transmit confirm queue utilization counter */
+	u32 fmbm_tduc;	/* Tx DMA utilization counter */
+	u32 fmbm_tfuc;	/* Tx FIFO utilization counter */
+	u32 res2[0x19];
+	u32 fmbm_tdcfg;	/* Tx debug configuration */
+};
+
+/* FMBM_TCFG - Tx configuration */
+#define FMBM_TCFG_EN	0x80000000 /* port is enabled to transmit data */
+#define FMBM_TCFG_IM	0x01000000 /* independent mode enable */
+
+/* FMBM_TST - Tx status */
+#define FMBM_TST_BSY		0x80000000 /* Tx port is busy */
+
+/* FMBM_TFCA - Tx frame command attributes */
+#define FMBM_TFCA_ORDER		0x80000000
+#define FMBM_TFCA_MR_MASK	0x003f0000
+#define FMBM_TFCA_MR(x)		((x << 16) & FMBM_TFCA_MR_MASK)
+
+/* FMBM_TSTC - Tx statistics counters */
+#define FMBM_TSTC_EN		0x80000000
+
+/* FMBM_INIT - BMI initialization register */
+#define FMBM_INIT_START		0x80000000 /* init internal buffers */
+
+/* FMBM_CFG1 - BMI configuration 1 */
+#define FMBM_CFG1_FBPS_MASK	0x03ff0000 /* Free buffer pool size */
+#define FMBM_CFG1_FBPS_SHIFT	16
+#define FMBM_CFG1_FBPO_MASK	0x000003ff /* Free buffer pool offset */
+
+/* FMBM_IEVR - interrupt event */
+#define FMBM_IEVR_PEC		0x80000000 /* pipeline table ECC err detected */
+#define FMBM_IEVR_LEC		0x40000000 /* linked list RAM ECC error */
+#define FMBM_IEVR_SEC		0x20000000 /* statistics count RAM ECC error */
+#define FMBM_IEVR_CLEAR_ALL	(FMBM_IEVR_PEC | FMBM_IEVR_LEC | FMBM_IEVR_SEC)
+
+/* FMBM_IER - interrupt enable */
+#define FMBM_IER_PECE		0x80000000 /* PEC interrupt enable */
+#define FMBM_IER_LECE		0x40000000 /* LEC interrupt enable */
+#define FMBM_IER_SECE		0x20000000 /* SEC interrupt enable */
+
+#define FMBM_IER_DISABLE_ALL	0x00000000
+
+/* FMBM_PP - BMI Port Parameters */
+#define FMBM_PP_MXT_MASK	0x3f000000 /* Max # tasks */
+#define FMBM_PP_MXT(x)		(((x-1) << 24) & FMBM_PP_MXT_MASK)
+#define FMBM_PP_MXD_MASK	0x00000f00 /* Max DMA */
+#define FMBM_PP_MXD(x)		(((x-1) << 8) & FMBM_PP_MXD_MASK)
+
+/* FMBM_PFS - BMI Port FIFO Size */
+#define FMBM_PFS_IFSZ_MASK	0x000003ff /* Internal Fifo Size */
+#define FMBM_PFS_IFSZ(x)	(x & FMBM_PFS_IFSZ_MASK)
+
+/* FMQM_GC - global configuration */
+#define FMQM_GC_ENQ_EN		0x80000000 /* enqueue enable */
+#define FMQM_GC_DEQ_EN		0x40000000 /* dequeue enable */
+#define FMQM_GC_STEN		0x10000000 /* enable global stat counters */
+#define FMQM_GC_ENQ_THR_MASK	0x00003f00 /* max number of enqueue Tnum */
+#define FMQM_GC_ENQ(x)		((x << 8) &  FMQM_GC_ENQ_THR_MAS)
+#define FMQM_GC_DEQ_THR_MASK	0x0000003f /* max number of dequeue Tnum */
+#define FMQM_GC_DEQ(x)		(x & FMQM_GC_DEQ_THR_MASK)
+
+/* FMQM_EIE - error interrupt event register */
+#define FMQM_EIE_DEE		0x80000000 /* double-bit ECC error */
+#define FMQM_EIE_DFUPE		0x40000000 /* dequeue from unknown PortID */
+#define FMQM_EIE_CLEAR_ALL	(FMQM_EIE_DEE | FMQM_EIE_DFUPE)
+
+/* FMQM_EIEN - error interrupt enable register */
+#define FMQM_EIEN_DEEN		0x80000000 /* double-bit ECC error */
+#define FMQM_EIEN_DFUPEN	0x40000000 /* dequeue from unknown PortID */
+#define FMQM_EIEN_DISABLE_ALL	0x00000000
+
+/* FMQM_IE - interrupt event register */
+#define FMQM_IE_SEE		0x80000000 /* single-bit ECC error detected */
+#define FMQM_IE_CLEAR_ALL	FMQM_IE_SEE
+
+/* FMQM_IEN - interrupt enable register */
+#define FMQM_IEN_SEE		0x80000000 /* single-bit ECC err IRQ enable */
+#define FMQM_IEN_DISABLE_ALL	0x00000000
+
+/* NIA - next invoked action */
+#define NIA_ENG_RISC		0x00000000
+#define NIA_ENG_MASK		0x007c0000
+
+/* action code */
+#define NIA_RISC_AC_CC		0x00000006
+#define NIA_RISC_AC_IM_TX	0x00000008 /* independent mode Tx */
+#define NIA_RISC_AC_IM_RX	0x0000000a /* independent mode Rx */
+#define NIA_RISC_AC_HC		0x0000000c
+
 typedef struct fm_parser {
 	u8	res[1024];
 } fm_parser_t;
@@ -113,6 +296,27 @@ typedef struct fm_dma {
 	u32	res[0x3c8];
 } fm_dma_t;
 
+/* FMDMSR - Fman DMA status register */
+#define FMDMSR_CMDQNE		0x10000000 /* command queue not empty */
+#define FMDMSR_BER		0x08000000 /* bus err event occurred on bus */
+#define FMDMSR_RDB_ECC		0x04000000 /* read buffer ECC error */
+#define FMDMSR_WRB_SECC		0x02000000 /* write buf ECC err sys side */
+#define FMDMSR_WRB_FECC		0x01000000 /* write buf ECC err Fman side */
+#define FMDMSR_DPEXT_SECC	0x00800000 /* DP external ECC err sys side */
+#define FMDMSR_DPEXT_FECC	0x00400000 /* DP external ECC err Fman side */
+#define FMDMSR_DPDAT_SECC	0x00200000 /* DP data ECC err on sys side */
+#define FMDMSR_DPDAT_FECC	0x00100000 /* DP data ECC err on Fman side */
+#define FMDMSR_SPDAT_FECC	0x00080000 /* SP data ECC error Fman side */
+
+#define FMDMSR_CLEAR_ALL	(FMDMSR_BER | FMDMSR_RDB_ECC \
+				| FMDMSR_WRB_SECC | FMDMSR_WRB_FECC \
+				| FMDMSR_DPEXT_SECC | FMDMSR_DPEXT_FECC \
+				| FMDMSR_DPDAT_SECC | FMDMSR_DPDAT_FECC \
+				| FMDMSR_SPDAT_FECC)
+
+/* FMDMMR - FMan DMA mode register */
+#define FMDMMR_SBER		0x10000000 /* stop the DMA if a bus error */
+
 typedef struct fm_fpm {
 	u32	fpmtnc;		/* TNUM control */
 	u32	fpmprc;		/* Port_ID control */
@@ -141,7 +345,7 @@ typedef struct fm_fpm {
 	u32	fmcld;		/* classifier debug control */
 	u32	fmnpi;		/* normal pending interrupts */
 	u32	res5;
-	u32	fmnee;		/* event and enable */
+	u32	fmfpee;		/* event and enable */
 	u32	fpmcev[0x4];	/* CPU event 0-3 */
 	u32	res6[0x4];
 	u32	fmfp_ps[0x40];	/* port status */
@@ -150,9 +354,47 @@ typedef struct fm_fpm {
 	u32	res8[0xa0];
 } fm_fpm_t;
 
+/* FMFP_PRC - FPM Port_ID Control Register */
+#define FMFPPRC_PORTID_MASK	0x3f000000
+#define FMFPPRC_PORTID_SHIFT	24
+#define FMFPPRC_ORA_SHIFT	16
+#define FMFPPRC_RISC1		0x00000001
+#define FMFPPRC_RISC2		0x00000002
+#define FMFPPRC_RISC_ALL	(FMFPPRC_RISC1 | FMFPPRC_RSIC2)
+
+/* FPM Flush Control Register */
+#define FMFP_FLC_DISP_LIM_NONE	0x00000000 /* no dispatch limitation */
+
+/* FMFP_EE - FPM event and enable register */
+#define FMFPEE_DECC		0x80000000 /* double ECC err on FPM ram */
+#define FMFPEE_STL		0x40000000 /* stall of task ... */
+#define FMFPEE_SECC		0x20000000 /* single ECC error */
+#define FMFPEE_RFM		0x00010000 /* release FMan */
+#define FMFPEE_DECC_EN		0x00008000 /* double ECC interrupt enable */
+#define FMFPEE_STL_EN		0x00004000 /* stall of task interrupt enable */
+#define FMFPEE_SECC_EN		0x00002000 /* single ECC err interrupt enable */
+#define FMFPEE_EHM		0x00000008 /* external halt enable */
+#define FMFPEE_UEC		0x00000004 /* FMan is not halted */
+#define FMFPEE_CER		0x00000002 /* only errornous task stalled */
+#define FMFPEE_DER		0x00000001 /* DMA error is just reported */
+
+#define FMFPEE_CLEAR_EVENT	(FMFPEE_DECC | FMFPEE_STL | FMFPEE_SECC | \
+				 FMFPEE_EHM | FMFPEE_UEC | FMFPEE_CER | \
+				 FMFPEE_DER | FMFPEE_RFM)
+
+/* FMFP_RCR - FMan Rams Control and Event */
+#define FMFP_RCR_MDEC		0x00008000 /* double ECC error in muram */
+#define FMFP_RCR_IDEC		0x00004000 /* double ECC error in iram */
+
 typedef struct fm_imem {
-	u8	res[4*1024];
+	u32	iadd;		/* instruction address register */
+	u32	idata;		/* instruction data register */
+	u32	itcfg;		/* timing config register */
+	u32	iready;		/* ready register */
+	u8	res[0xff0];
 } fm_imem_t;
+#define IRAM_IADD_AIE		0x80000000 /* address auto increase enable */
+#define IRAM_READY		0x80000000 /* ready to use */
 
 typedef struct fm_soft_parser {
 	u8	res[4*1024];
@@ -200,10 +442,11 @@ typedef struct ccsr_fman {
 	struct {
 		fm_dtsec_t	fm_dtesc;
 		fm_mdio_t	fm_mdio;
-	} mac[4];
-	u8			res3[32*1024];
-	fm_10gec_t		fm_10gec;
-	fm_10gec_mdio_t		fm_10gec_mdio;
+	} mac_1g[8];		/* support up to 8 1g controllers */
+	struct {
+		fm_10gec_t		fm_10gec;
+		fm_10gec_mdio_t		fm_10gec_mdio;
+	} mac_10g[1];
 	u8			res4[48*1024];
 	fm_1588_t		fm_1588;
 	u8			res5[4*1024];
diff --git a/arch/powerpc/include/asm/fsl_tgec.h b/arch/powerpc/include/asm/fsl_tgec.h
new file mode 100644
index 0000000..8de37c9
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_tgec.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __TGEC_H__
+#define __TGEC_H__
+
+#include <phy.h>
+
+struct tgec {
+	/* 10GEC general control and status registers */
+	u32	tgec_id;	/* Controller ID register */
+	u32	res0;
+	u32	command_config;	/* Control and configuration register */
+	u32	mac_addr_0;	/* Lower 32 bits of 48-bit MAC address */
+	u32	mac_addr_1;	/* Upper 16 bits of 48-bit MAC address */
+	u32	maxfrm;		/* Maximum frame length register */
+	u32	pause_quant;	/* Pause quanta register */
+	u32	res1[4];
+	u32	hashtable_ctrl;	/* Hash table control register */
+	u32	res2[4];
+	u32	status;		/* MAC status register */
+	u32	tx_ipg_length;	/* Transmitter inter-packet-gap register */
+	u32	mac_addr_2;	/* Lower 32 bits of the 2nd 48-bit MAC addr */
+	u32	mac_addr_3;	/* Upper 16 bits of the 2nd 48-bit MAC addr */
+	u32	res3[4];
+	u32	imask;		/* Interrupt mask register */
+	u32	ievent;		/* Interrupt event register */
+	u32	res4[6];
+	/* 10GEC statistics counter registers */
+	u32	tx_frame_u;	/* Tx frame counter upper */
+	u32	tx_frame_l;	/* Tx frame counter lower */
+	u32	rx_frame_u;	/* Rx frame counter upper */
+	u32	rx_frame_l;	/* Rx frame counter lower */
+	u32	rx_frame_crc_err_u; /* Rx frame check sequence error upper */
+	u32	rx_frame_crc_err_l; /* Rx frame check sequence error lower */
+	u32	rx_align_err_u;	/* Rx alignment error upper */
+	u32	rx_align_err_l;	/* Rx alignment error lower */
+	u32	tx_pause_frame_u; /* Tx valid pause frame upper */
+	u32	tx_pause_frame_l; /* Tx valid pause frame lower */
+	u32	rx_pause_frame_u; /* Rx valid pause frame upper */
+	u32	rx_pause_frame_l; /* Rx valid pause frame upper */
+	u32	rx_long_err_u;	/* Rx too long frame error upper */
+	u32	rx_long_err_l;	/* Rx too long frame error lower */
+	u32	rx_frame_err_u;	/* Rx frame length error upper */
+	u32	rx_frame_err_l;	/* Rx frame length error lower */
+	u32	tx_vlan_u;	/* Tx VLAN frame upper */
+	u32	tx_vlan_l;	/* Tx VLAN frame lower */
+	u32	rx_vlan_u;	/* Rx VLAN frame upper */
+	u32	rx_vlan_l;	/* Rx VLAN frame lower */
+	u32	tx_oct_u;	/* Tx octets upper */
+	u32	tx_oct_l;	/* Tx octets lower */
+	u32	rx_oct_u;	/* Rx octets upper */
+	u32	rx_oct_l;	/* Rx octets lower */
+	u32	rx_uni_u;	/* Rx unicast frame upper */
+	u32	rx_uni_l;	/* Rx unicast frame lower */
+	u32	rx_multi_u;	/* Rx multicast frame upper */
+	u32	rx_multi_l;	/* Rx multicast frame lower */
+	u32	rx_brd_u;	/* Rx broadcast frame upper */
+	u32	rx_brd_l;	/* Rx broadcast frame lower */
+	u32	tx_frame_err_u;	/* Tx frame error upper */
+	u32	tx_frame_err_l;	/* Tx frame error lower */
+	u32	tx_uni_u;	/* Tx unicast frame upper */
+	u32	tx_uni_l;	/* Tx unicast frame lower */
+	u32	tx_multi_u;	/* Tx multicast frame upper */
+	u32	tx_multi_l;	/* Tx multicast frame lower */
+	u32	tx_brd_u;	/* Tx broadcast frame upper */
+	u32	tx_brd_l;	/* Tx broadcast frame lower */
+	u32	rx_drop_u;	/* Rx dropped packets upper */
+	u32	rx_drop_l;	/* Rx dropped packets lower */
+	u32	rx_eoct_u;	/* Rx ethernet octets upper */
+	u32	rx_eoct_l;	/* Rx ethernet octets lower */
+	u32	rx_pkt_u;	/* Rx packets upper */
+	u32	rx_pkt_l;	/* Rx packets lower */
+	u32	tx_undsz_u;	/* Undersized packet upper */
+	u32	tx_undsz_l;	/* Undersized packet lower */
+	u32	rx_64_u;	/* Rx 64 oct packet upper */
+	u32	rx_64_l;	/* Rx 64 oct packet lower */
+	u32	rx_127_u;	/* Rx 65 to 127 oct packet upper */
+	u32	rx_127_l;	/* Rx 65 to 127 oct packet lower */
+	u32	rx_255_u;	/* Rx 128 to 255 oct packet upper */
+	u32	rx_255_l;	/* Rx 128 to 255 oct packet lower */
+	u32	rx_511_u;	/* Rx 256 to 511 oct packet upper */
+	u32	rx_511_l;	/* Rx 256 to 511 oct packet lower */
+	u32	rx_1023_u;	/* Rx 512 to 1023 oct packet upper */
+	u32	rx_1023_l;	/* Rx 512 to 1023 oct packet lower */
+	u32	rx_1518_u;	/* Rx 1024 to 1518 oct packet upper */
+	u32	rx_1518_l;	/* Rx 1024 to 1518 oct packet lower */
+	u32	rx_1519_u;	/* Rx 1519 to max oct packet upper */
+	u32	rx_1519_l;	/* Rx 1519 to max oct packet lower */
+	u32	tx_oversz_u;	/* oversized packet upper */
+	u32	tx_oversz_l;	/* oversized packet lower */
+	u32	tx_jabber_u;	/* Jabber packet upper */
+	u32	tx_jabber_l;	/* Jabber packet lower */
+	u32	tx_frag_u;	/* Fragment packet upper */
+	u32	tx_frag_l;	/* Fragment packet lower */
+	u32	rx_err_u;	/* Rx frame error upper */
+	u32	rx_err_l;	/* Rx frame error lower */
+	u32	res5[0x39a];
+};
+
+/* EC10G_ID - 10-gigabit ethernet MAC controller ID */
+#define EC10G_ID_VER_MASK	0x0000ff00
+#define EC10G_ID_VER_SHIFT	8
+#define EC10G_ID_REV_MASK	0x000000ff
+
+/* COMMAND_CONFIG - command and configuration register */
+#define TGEC_CMD_CFG_EN_TIMESTAMP	0x00100000 /* enable IEEE1588 */
+#define TGEC_CMD_CFG_TX_ADDR_INS_SEL	0x00080000 /* Tx mac addr w/ second */
+#define TGEC_CMD_CFG_NO_LEN_CHK		0x00020000 /* payload len chk disable */
+#define TGEC_CMD_CFG_SEND_IDLE		0x00010000 /* send XGMII idle seqs */
+#define TGEC_CMD_CFG_RX_ER_DISC		0x00004000 /* Rx err frm discard enb */
+#define TGEC_CMD_CFG_CMD_FRM_EN		0x00002000 /* CMD frame RX enable */
+#define TGEC_CMD_CFG_STAT_CLR		0x00001000 /* clear stats */
+#define TGEC_CMD_CFG_TX_ADDR_INS	0x00000200 /* overwrite src MAC addr */
+#define TGEC_CMD_CFG_PAUSE_IGNORE	0x00000100 /* ignore pause frames */
+#define TGEC_CMD_CFG_PAUSE_FWD		0x00000080 /* fwd pause frames */
+#define TGEC_CMD_CFG_CRC_FWD		0x00000040 /* fwd Rx CRC frames */
+#define TGEC_CMD_CFG_PAD_EN		0x00000020 /* MAC remove Rx padding */
+#define TGEC_CMD_CFG_PROM_EN		0x00000010 /* promiscuous mode enable */
+#define TGEC_CMD_CFG_WAN_MODE		0x00000008 /* WAN mode enable */
+#define TGEC_CMD_CFG_RX_EN		0x00000002 /* MAC Rx path enable */
+#define TGEC_CMD_CFG_TX_EN		0x00000001 /* MAC Tx path enable */
+#define TGEC_CMD_CFG_RXTX_EN	(TGEC_CMD_CFG_RX_EN | TGEC_CMD_CFG_TX_EN)
+
+/* HASHTABLE_CTRL - Hashtable control register */
+#define HASHTABLE_CTRL_MCAST_EN	0x00000200 /* enable mulitcast Rx hash */
+#define HASHTABLE_CTRL_ADDR_MASK	0x000001ff
+
+/* TX_IPG_LENGTH - Transmit inter-packet gap length register */
+#define TX_IPG_LENGTH_IPG_LEN_MASK	0x000003ff
+
+/* IMASK - interrupt mask register */
+#define IMASK_MDIO_SCAN_EVENT	0x00010000 /* MDIO scan event mask */
+#define IMASK_MDIO_CMD_CMPL	0x00008000 /* MDIO cmd completion mask */
+#define IMASK_REM_FAULT		0x00004000 /* remote fault mask */
+#define IMASK_LOC_FAULT		0x00002000 /* local fault mask */
+#define IMASK_TX_ECC_ER		0x00001000 /* Tx frame ECC error mask */
+#define IMASK_TX_FIFO_UNFL	0x00000800 /* Tx FIFO underflow mask */
+#define IMASK_TX_ER		0x00000200 /* Tx frame error mask */
+#define IMASK_RX_FIFO_OVFL	0x00000100 /* Rx FIFO overflow mask */
+#define IMASK_RX_ECC_ER		0x00000080 /* Rx frame ECC error mask */
+#define IMASK_RX_JAB_FRM	0x00000040 /* Rx jabber frame mask */
+#define IMASK_RX_OVRSZ_FRM	0x00000020 /* Rx oversized frame mask */
+#define IMASK_RX_RUNT_FRM	0x00000010 /* Rx runt frame mask */
+#define IMASK_RX_FRAG_FRM	0x00000008 /* Rx fragment frame mask */
+#define IMASK_RX_LEN_ER		0x00000004 /* Rx payload length error mask */
+#define IMASK_RX_CRC_ER		0x00000002 /* Rx CRC error mask */
+#define IMASK_RX_ALIGN_ER	0x00000001 /* Rx alignment error mask */
+
+#define IMASK_MASK_ALL		0x00000000
+
+/* IEVENT - interrupt event register */
+#define IEVENT_MDIO_SCAN_EVENT	0x00010000 /* MDIO scan event */
+#define IEVENT_MDIO_CMD_CMPL	0x00008000 /* MDIO cmd completion */
+#define IEVENT_REM_FAULT	0x00004000 /* remote fault */
+#define IEVENT_LOC_FAULT	0x00002000 /* local fault */
+#define IEVENT_TX_ECC_ER	0x00001000 /* Tx frame ECC error */
+#define IEVENT_TX_FIFO_UNFL	0x00000800 /* Tx FIFO underflow */
+#define IEVENT_TX_ER		0x00000200 /* Tx frame error */
+#define IEVENT_RX_FIFO_OVFL	0x00000100 /* Rx FIFO overflow */
+#define IEVENT_RX_ECC_ER	0x00000080 /* Rx frame ECC error */
+#define IEVENT_RX_JAB_FRM	0x00000040 /* Rx jabber frame */
+#define IEVENT_RX_OVRSZ_FRM	0x00000020 /* Rx oversized frame */
+#define IEVENT_RX_RUNT_FRM	0x00000010 /* Rx runt frame */
+#define IEVENT_RX_FRAG_FRM	0x00000008 /* Rx fragment frame */
+#define IEVENT_RX_LEN_ER	0x00000004 /* Rx payload length error */
+#define IEVENT_RX_CRC_ER	0x00000002 /* Rx CRC error */
+#define IEVENT_RX_ALIGN_ER	0x00000001 /* Rx alignment error */
+
+#define IEVENT_CLEAR_ALL	0xffffffff
+
+struct tgec_mdio_controller {
+	u32	res0[0xc];
+	u32	mdio_stat;	/* MDIO configuration and status */
+	u32	mdio_ctl;	/* MDIO control */
+	u32	mdio_data;	/* MDIO data */
+	u32	mdio_addr;	/* MDIO address */
+};
+
+#define MDIO_STAT_CLKDIV(x)	(((x>>1) & 0xff) << 8)
+#define MDIO_STAT_BSY		(1 << 0)
+#define MDIO_STAT_RD_ER		(1 << 1)
+#define MDIO_CTL_DEV_ADDR(x)	(x & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x)	((x & 0x1f) << 5)
+#define MDIO_CTL_PRE_DIS	(1 << 10)
+#define MDIO_CTL_SCAN_EN	(1 << 11)
+#define MDIO_CTL_POST_INC	(1 << 14)
+#define MDIO_CTL_READ		(1 << 15)
+
+#define MDIO_DATA(x)		(x & 0xffff)
+#define MDIO_DATA_BSY		(1 << 31)
+
+struct fsl_enet_mac;
+
+void init_tgec(struct fsl_enet_mac *mac, void *base, void *phyregs,
+		int max_rx_len);
+
+#endif
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index 6aaade0..50569fb 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -1700,12 +1700,24 @@ typedef struct ccsr_gur {
 #define FSL_CORENET_RCWSR8_HOST_AGT_B1		0x00e00000
 #define FSL_CORENET_RCWSR8_HOST_AGT_B2		0x00100000
 #define FSL_CORENET_RCWSR11_EC1			0x00c00000 /* bits 360..361 */
-#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC1	0x00000000
-#define FSL_CORENET_RCWSR11_EC1_FM1_USB1	0x00800000
+#if defined(CONFIG_PPC_P4080)
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC1		0x00000000
+#define FSL_CORENET_RCWSR11_EC1_FM1_USB1		0x00800000
 #define FSL_CORENET_RCWSR11_EC2			0x001c0000 /* bits 363..365 */
-#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1	0x00000000
-#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2	0x00080000
-#define FSL_CORENET_RCWSR11_EC2_USB2		0x00100000
+#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1		0x00000000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2		0x00080000
+#define FSL_CORENET_RCWSR11_EC2_USB2			0x00100000
+#endif
+#if defined(CONFIG_PPC_P2040) || defined(CONFIG_PPC_P2041) \
+	|| defined(CONFIG_PPC_P3041) || defined(CONFIG_PPC_P5020)
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_RGMII	0x00000000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_MII		0x00800000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_NONE		0x00c00000
+#define FSL_CORENET_RCWSR11_EC2			0x00180000 /* bits 363..364 */
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_RGMII	0x00000000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_MII		0x00100000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_NONE		0x00180000
+#endif
 	u8	res18[192];
 	u32	scratchrw[4];	/* Scratch Read/Write */
 	u8	res19[240];
@@ -1873,6 +1885,7 @@ typedef struct ccsr_gur {
 #if defined(CONFIG_P1017) || defined(CONFIG_P1023)
 #define MPC85xx_PORDEVSR_SGMII1_DIS	0x10000000
 #define MPC85xx_PORDEVSR_SGMII2_DIS	0x08000000
+#define MPC85xx_PORDEVSR_TSEC1_PRTC	0x02000000
 #else
 #define MPC85xx_PORDEVSR_SGMII1_DIS	0x20000000
 #define MPC85xx_PORDEVSR_SGMII2_DIS	0x10000000
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 819b197..39f036e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -80,6 +80,7 @@ COBJS-$(CONFIG_TIGON3) += bcm570x_autoneg.o
 COBJS-$(CONFIG_TIGON3) += 5701rls.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
+COBJS-$(CONFIG_FMAN_ENET) += fsl_mdio.o
 COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile
new file mode 100644
index 0000000..9692575
--- /dev/null
+++ b/drivers/net/fm/Makefile
@@ -0,0 +1,61 @@
+#
+# Copyright 2009-2011 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libfm.o
+
+ifdef CONFIG_FMAN_ENET
+COBJS-y += dtsec.o
+COBJS-y += eth.o
+COBJS-y += fm.o
+COBJS-y += init.o
+COBJS-y += tgec.o
+COBJS-y += tgec_phy.o
+
+# SoC specific SERDES support
+COBJS-$(CONFIG_P1017)	+= p1023.o
+COBJS-$(CONFIG_P1023)	+= p1023.o
+# The P204x, P304x, and P5020 are the same
+COBJS-$(CONFIG_PPC_P2040) += p5020.o
+COBJS-$(CONFIG_PPC_P2041) += p5020.o
+COBJS-$(CONFIG_PPC_P3041) += p5020.o
+COBJS-$(CONFIG_PPC_P4080) += p4080.o
+COBJS-$(CONFIG_PPC_P5020) += p5020.o
+endif
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/net/fm/dtsec.c b/drivers/net/fm/dtsec.c
new file mode 100644
index 0000000..a77ee20
--- /dev/null
+++ b/drivers/net/fm/dtsec.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_dtsec.h>
+#include <fsl_mdio.h>
+#include <phy.h>
+
+#include "fm.h"
+
+#define RCTRL_INIT	(RCTRL_GRS | RCTRL_UPROM)
+#define TCTRL_INIT	TCTRL_GTS
+#define MACCFG1_INIT	MACCFG1_SOFT_RST
+
+#define MACCFG2_INIT	(MACCFG2_PRE_LEN(0x7) | MACCFG2_LEN_CHECK | \
+			 MACCFG2_PAD_CRC | MACCFG2_FULL_DUPLEX | \
+			 MACCFG2_IF_MODE_NIBBLE)
+
+/* MAXFRM - maximum frame length register */
+#define MAXFRM_MASK		0x00003fff
+
+static void dtsec_init_mac(struct fsl_enet_mac *mac)
+{
+	struct dtsec *regs = mac->base;
+
+	/* soft reset */
+	out_be32(&regs->maccfg1, MACCFG1_SOFT_RST);
+	udelay(1000);
+
+	/* clear soft reset, Rx/Tx MAC disable */
+	out_be32(&regs->maccfg1, 0);
+
+	/* graceful stop rx */
+	out_be32(&regs->rctrl, RCTRL_INIT);
+	udelay(1000);
+
+	/* graceful stop tx */
+	out_be32(&regs->tctrl, TCTRL_INIT);
+	udelay(1000);
+
+	/* disable all interrupts */
+	out_be32(&regs->imask, IMASK_MASK_ALL);
+
+	/* clear all events */
+	out_be32(&regs->ievent, IEVENT_CLEAR_ALL);
+
+	/* set the max Rx length */
+	out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);
+
+	/* set the ecntrl to reset value */
+	out_be32(&regs->ecntrl, ECNTRL_DEFAULT);
+
+	/*
+	 * Rx length check, no strip CRC for Rx, pad and append CRC for Tx,
+	 * full duplex
+	 */
+	out_be32(&regs->maccfg2, MACCFG2_INIT);
+}
+
+static void dtsec_enable_mac(struct fsl_enet_mac *mac)
+{
+	struct dtsec *regs = mac->base;
+
+	/* enable Rx/Tx MAC */
+	setbits_be32(&regs->maccfg1, MACCFG1_RXTX_EN);
+
+	/* clear the graceful Rx stop */
+	clrbits_be32(&regs->rctrl, RCTRL_GRS);
+
+	/* clear the graceful Tx stop */
+	clrbits_be32(&regs->tctrl, TCTRL_GTS);
+}
+
+static void dtsec_disable_mac(struct fsl_enet_mac *mac)
+{
+	struct dtsec *regs = mac->base;
+
+	/* graceful Rx stop */
+	setbits_be32(&regs->rctrl, RCTRL_GRS);
+
+	/* graceful Tx stop */
+	setbits_be32(&regs->tctrl, TCTRL_GTS);
+
+	/* disable Rx/Tx MAC */
+	clrbits_be32(&regs->maccfg1, MACCFG1_RXTX_EN);
+}
+
+static void dtsec_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr)
+{
+	struct dtsec *regs = mac->base;
+	u32 mac_addr1, mac_addr2;
+
+	/*
+	 * if a station address of 0x12345678ABCD, perform a write to
+	 * MACSTNADDR1 of 0xCDAB7856, MACSTNADDR2 of 0x34120000
+	 */
+	mac_addr1 = (mac_addr[5] << 24) | (mac_addr[4] << 16) | \
+			(mac_addr[3] << 8)  | (mac_addr[2]);
+	out_be32(&regs->macstnaddr1, mac_addr1);
+
+	mac_addr2 = ((mac_addr[1] << 24) | (mac_addr[0] << 16)) & 0xffff0000;
+	out_be32(&regs->macstnaddr2, mac_addr2);
+}
+
+static void dtsec_set_interface_mode(struct fsl_enet_mac *mac,
+		phy_interface_t type, int speed)
+{
+	struct dtsec *regs = mac->base;
+	u32 ecntrl, maccfg2;
+
+	/* clear all bits relative with interface mode */
+	ecntrl = in_be32(&regs->ecntrl);
+	ecntrl &= ~(ECNTRL_TBIM | ECNTRL_GMIIM | ECNTRL_RPM |
+				  ECNTRL_R100M | ECNTRL_SGMIIM);
+
+	maccfg2 = in_be32(&regs->maccfg2);
+	maccfg2 &= ~MACCFG2_IF_MODE_MASK;
+
+	if (speed == SPEED_1000)
+		maccfg2 |= MACCFG2_IF_MODE_BYTE;
+	else
+		maccfg2 |= MACCFG2_IF_MODE_NIBBLE;
+
+	/* set interface mode */
+	switch (type) {
+	case PHY_INTERFACE_MODE_GMII:
+		ecntrl |= ECNTRL_GMIIM;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+		ecntrl |= (ECNTRL_GMIIM | ECNTRL_RPM);
+		if (speed == SPEED_100)
+			ecntrl |= ECNTRL_R100M;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		if (speed == SPEED_100)
+			ecntrl |= ECNTRL_R100M;
+		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		ecntrl |= (ECNTRL_SGMIIM | ECNTRL_TBIM);
+		if (speed == SPEED_100)
+			ecntrl |= ECNTRL_R100M;
+		break;
+	default:
+		break;
+	}
+
+	out_be32(&regs->ecntrl, ecntrl);
+	out_be32(&regs->maccfg2, maccfg2);
+}
+
+void init_dtsec(struct fsl_enet_mac *mac, void *base,
+		void *phyregs, int max_rx_len)
+{
+	mac->base = base;
+	mac->phyregs = NULL;
+	mac->max_rx_len = max_rx_len;
+	mac->init_mac = dtsec_init_mac;
+	mac->enable_mac = dtsec_enable_mac;
+	mac->disable_mac = dtsec_disable_mac;
+	mac->set_mac_addr = dtsec_set_mac_addr;
+	mac->set_if_mode = dtsec_set_interface_mode;
+}
diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c
new file mode 100644
index 0000000..0ae26e2
--- /dev/null
+++ b/drivers/net/fm/eth.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <net.h>
+#include <hwconfig.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/fsl_dtsec.h>
+#include <asm/fsl_tgec.h>
+
+#include "fm.h"
+
+static struct eth_device *devlist[NUM_FM_PORTS];
+static int num_controllers = 0;
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) && !defined(BITBANGMII)
+
+#define TBIANA_SETTINGS (TBIANA_ASYMMETRIC_PAUSE | TBIANA_SYMMETRIC_PAUSE | \
+			 TBIANA_FULL_DUPLEX)
+
+#define TBIANA_SGMII_ACK 0x4001
+
+#define TBICR_SETTINGS (TBICR_ANEG_ENABLE | TBICR_RESTART_ANEG | \
+			TBICR_FULL_DUPLEX | TBICR_SPEED1_SET)
+
+/* Configure the TBI for SGMII operation */
+void dtsec_configure_serdes(struct fm_eth *priv)
+{
+	struct dtsec *regs = priv->mac->base;
+	struct tsec_mii_mng *phyregs = priv->mac->phyregs;
+
+	/*
+	 * Access TBI PHY registers at given TSEC register offset as
+	 * opposed to the register offset used for external PHY accesses
+	 */
+	tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0, TBI_TBICON,
+			TBICON_CLK_SELECT);
+	tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0, TBI_ANA,
+			TBIANA_SGMII_ACK);
+	tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0,
+			TBI_CR, TBICR_SETTINGS);
+}
+
+static void dtsec_init_phy(struct eth_device *dev)
+{
+	struct fm_eth *fm_eth = dev->priv;
+	struct dtsec *regs = (struct dtsec *)fm_eth->mac->base;
+
+	/* Assign a Physical address to the TBI */
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+
+	if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII)
+		dtsec_configure_serdes(fm_eth);
+}
+
+static int tgec_is_fibre(struct eth_device *dev)
+{
+	struct fm_eth *fm = dev->priv;
+	char phyopt[20];
+
+	sprintf(phyopt, "fsl_fm%d_xaui_phy", fm->fm_index + 1);
+
+	return hwconfig_arg_cmp(phyopt, "xfi");
+}
+#endif
+
+static u16 muram_readw(u16 *addr)
+{
+	u32 base = (u32)addr & ~0x3;
+	u32 val32 = *(u32 *)base;
+	int byte_pos;
+	u16 ret;
+
+	byte_pos = (u32)addr & 0x3;
+	if (byte_pos)
+		ret = (u16)(val32 & 0x0000ffff);
+	else
+		ret = (u16)((val32 & 0xffff0000) >> 16);
+
+	return ret;
+}
+
+static void muram_writew(u16 *addr, u16 val)
+{
+	u32 base = (u32)addr & ~0x3;
+	u32 org32 = *(u32 *)base;
+	u32 val32;
+	int byte_pos;
+
+	byte_pos = (u32)addr & 0x3;
+	if (byte_pos)
+		val32 = (org32 & 0xffff0000) | val;
+	else
+		val32 = (org32 & 0x0000ffff) | ((u32)val << 16);
+
+	*(u32 *)base = val32;
+}
+
+static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port)
+{
+	int timeout = 1000000;
+
+	clrbits_be32(&rx_port->fmbm_rcfg, FMBM_RCFG_EN);
+
+	/* wait until the rx port is not busy */
+	while ((in_be32(&rx_port->fmbm_rst) & FMBM_RST_BSY) && timeout--)
+		;
+}
+
+static void bmi_rx_port_init(struct fm_bmi_rx_port *rx_port)
+{
+	/* set BMI to independent mode, Rx port disable */
+	out_be32(&rx_port->fmbm_rcfg, FMBM_RCFG_IM);
+	/* clear FOF in IM case */
+	out_be32(&rx_port->fmbm_rim, 0);
+	/* Rx frame next engine -RISC */
+	out_be32(&rx_port->fmbm_rfne, NIA_ENG_RISC | NIA_RISC_AC_IM_RX);
+	/* Rx command attribute - no order, MR[3] = 1 */
+	clrbits_be32(&rx_port->fmbm_rfca, FMBM_RFCA_ORDER | FMBM_RFCA_MR_MASK);
+	setbits_be32(&rx_port->fmbm_rfca, FMBM_RFCA_MR(4));
+	/* enable Rx statistic counters */
+	out_be32(&rx_port->fmbm_rstc, FMBM_RSTC_EN);
+	/* disable Rx performance counters */
+	out_be32(&rx_port->fmbm_rpc, 0);
+}
+
+static void bmi_tx_port_disable(struct fm_bmi_tx_port *tx_port)
+{
+	int timeout = 1000000;
+
+	clrbits_be32(&tx_port->fmbm_tcfg, FMBM_TCFG_EN);
+
+	/* wait until the tx port is not busy */
+	while ((in_be32(&tx_port->fmbm_tst) & FMBM_TST_BSY) && timeout--)
+		;
+}
+
+static void bmi_tx_port_init(struct fm_bmi_tx_port *tx_port)
+{
+	/* set BMI to independent mode, Tx port disable */
+	out_be32(&tx_port->fmbm_tcfg, FMBM_TCFG_IM);
+	/* Tx frame next engine -RISC */
+	out_be32(&tx_port->fmbm_tfne, NIA_ENG_RISC | NIA_RISC_AC_IM_TX);
+	out_be32(&tx_port->fmbm_tfene, NIA_ENG_RISC | NIA_RISC_AC_IM_TX);
+	/* Tx command attribute - no order, MR[3] = 1 */
+	clrbits_be32(&tx_port->fmbm_tfca, FMBM_TFCA_ORDER | FMBM_TFCA_MR_MASK);
+	setbits_be32(&tx_port->fmbm_tfca, FMBM_TFCA_MR(4));
+	/* enable Tx statistic counters */
+	out_be32(&tx_port->fmbm_tstc, FMBM_TSTC_EN);
+	/* disable Tx performance counters */
+	out_be32(&tx_port->fmbm_tpc, 0);
+}
+
+static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth)
+{
+	struct fm_port_global_pram *pram;
+	u32 pram_page_offset;
+	void *rx_bd_ring_base;
+	void *rx_buf_pool;
+	struct fm_port_bd *rxbd;
+	struct fm_port_qd *rxqd;
+	struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port;
+	int i;
+
+	/* alloc global parameter ram at MURAM */
+	pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index,
+		FM_PRAM_SIZE, FM_PRAM_ALIGN);
+	fm_eth->rx_pram = pram;
+
+	/* parameter page offset to MURAM */
+	pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index);
+
+	/* enable global mode- snooping data buffers and BDs */
+	pram->mode = PRAM_MODE_GLOBAL;
+
+	/* init the Rx queue descriptor pionter */
+	pram->rxqd_ptr = pram_page_offset + 0x20;
+
+	/* set the max receive buffer length, power of 2 */
+	muram_writew(&pram->mrblr, MAX_RXBUF_LOG2);
+
+	/* alloc Rx buffer descriptors from main memory */
+	rx_bd_ring_base = malloc(sizeof(struct fm_port_bd)
+			* RX_BD_RING_SIZE);
+	if (!rx_bd_ring_base)
+		return 0;
+	memset(rx_bd_ring_base, 0, sizeof(struct fm_port_bd)
+			* RX_BD_RING_SIZE);
+
+	/* alloc Rx buffer from main memory */
+	rx_buf_pool = malloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE);
+	if (!rx_buf_pool)
+		return 0;
+	memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE);
+
+	/* save them to fm_eth */
+	fm_eth->rx_bd_ring = rx_bd_ring_base;
+	fm_eth->cur_rxbd = rx_bd_ring_base;
+	fm_eth->rx_buf = rx_buf_pool;
+
+	/* init Rx BDs ring */
+	rxbd = (struct fm_port_bd *)rx_bd_ring_base;
+	for (i = 0; i < RX_BD_RING_SIZE; i++) {
+		rxbd->status = RxBD_EMPTY;
+		rxbd->len = 0;
+		rxbd->buf_ptr_hi = 0;
+		rxbd->buf_ptr_lo = (u32)rx_buf_pool + i * MAX_RXBUF_LEN;
+		rxbd++;
+	}
+
+	/* set the Rx queue descriptor */
+	rxqd = &pram->rxqd;
+	muram_writew(&rxqd->gen, 0);
+	muram_writew(&rxqd->bd_ring_base_hi, 0);
+	rxqd->bd_ring_base_lo = (u32)rx_bd_ring_base;
+	muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd)
+			* RX_BD_RING_SIZE);
+	muram_writew(&rxqd->offset_in, 0);
+	muram_writew(&rxqd->offset_out, 0);
+
+	/* set IM parameter ram pointer to Rx Frame Queue ID */
+	out_be32(&bmi_rx_port->fmbm_rfqid, pram_page_offset);
+
+	return 1;
+}
+
+static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth)
+{
+	struct fm_port_global_pram *pram;
+	u32 pram_page_offset;
+	void *tx_bd_ring_base;
+	struct fm_port_bd *txbd;
+	struct fm_port_qd *txqd;
+	struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port;
+	int i;
+
+	/* alloc global parameter ram at MURAM */
+	pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index,
+		FM_PRAM_SIZE, FM_PRAM_ALIGN);
+	fm_eth->tx_pram = pram;
+
+	/* parameter page offset to MURAM */
+	pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index);
+
+	/* enable global mode- snooping data buffers and BDs */
+	pram->mode = PRAM_MODE_GLOBAL;
+
+	/* init the Tx queue descriptor pionter */
+	pram->txqd_ptr = pram_page_offset + 0x40;
+
+	/* alloc Tx buffer descriptors from main memory */
+	tx_bd_ring_base = malloc(sizeof(struct fm_port_bd)
+			* TX_BD_RING_SIZE);
+	if (!tx_bd_ring_base)
+		return 0;
+	memset(tx_bd_ring_base, 0, sizeof(struct fm_port_bd)
+			* TX_BD_RING_SIZE);
+	/* save it to fm_eth */
+	fm_eth->tx_bd_ring = tx_bd_ring_base;
+	fm_eth->cur_txbd = tx_bd_ring_base;
+
+	/* init Tx BDs ring */
+	txbd = (struct fm_port_bd *)tx_bd_ring_base;
+	for (i = 0; i < TX_BD_RING_SIZE; i++) {
+		txbd->status = TxBD_LAST;
+		txbd->len = 0;
+		txbd->buf_ptr_hi = 0;
+		txbd->buf_ptr_lo = 0;
+	}
+
+	/* set the Tx queue decriptor */
+	txqd = &pram->txqd;
+	muram_writew(&txqd->bd_ring_base_hi, 0);
+	txqd->bd_ring_base_lo = (u32)tx_bd_ring_base;
+	muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd)
+			* TX_BD_RING_SIZE);
+	muram_writew(&txqd->offset_in, 0);
+	muram_writew(&txqd->offset_out, 0);
+
+	/* set IM parameter ram pointer to Tx Confirmation Frame Queue ID */
+	out_be32(&bmi_tx_port->fmbm_tcfqid, pram_page_offset);
+
+	return 1;
+}
+
+static int fm_eth_init(struct fm_eth *fm_eth)
+{
+
+	if (!fm_eth_rx_port_parameter_init(fm_eth))
+		return 0;
+
+	if (!fm_eth_tx_port_parameter_init(fm_eth))
+		return 0;
+
+	return 1;
+}
+
+static int fm_eth_startup(struct fm_eth *fm_eth)
+{
+	struct fsl_enet_mac *mac;
+	mac = fm_eth->mac;
+
+	/* Rx/TxBDs, Rx/TxQDs, Rx buff and parameter ram init */
+	if (!fm_eth_init(fm_eth))
+		return 0;
+	/* setup the MAC controller */
+	mac->init_mac(mac);
+
+	/* For some reason we need to set SPEED_100 */
+	if ((fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII) && mac->set_if_mode)
+		mac->set_if_mode(mac, fm_eth->enet_if, SPEED_100);
+
+	/* init bmi rx port, IM mode and disable */
+	bmi_rx_port_init(fm_eth->rx_port);
+	/* init bmi tx port, IM mode and disable */
+	bmi_tx_port_init(fm_eth->tx_port);
+
+	return 1;
+}
+
+static void fmc_tx_port_graceful_stop_enable(struct fm_eth *fm_eth)
+{
+	struct fm_port_global_pram *pram;
+
+	pram = fm_eth->tx_pram;
+	/* graceful stop transmission of frames */
+	pram->mode |= PRAM_MODE_GRACEFUL_STOP;
+	sync();
+}
+
+static void fmc_tx_port_graceful_stop_disable(struct fm_eth *fm_eth)
+{
+	struct fm_port_global_pram *pram;
+
+	pram = fm_eth->tx_pram;
+	/* re-enable transmission of frames */
+	pram->mode &= ~PRAM_MODE_GRACEFUL_STOP;
+	sync();
+}
+
+static int fm_eth_open(struct eth_device *dev, bd_t *bd)
+{
+	struct fm_eth *fm_eth;
+	struct fsl_enet_mac *mac;
+
+	fm_eth = (struct fm_eth *)dev->priv;
+	mac = fm_eth->mac;
+
+	/* setup the MAC address */
+	if (dev->enetaddr[0] & 0x01) {
+		printf("%s: MacAddress is multcast address\n",	__func__);
+		return 1;
+	}
+	mac->set_mac_addr(mac, dev->enetaddr);
+
+	/* enable bmi Rx port */
+	setbits_be32(&fm_eth->rx_port->fmbm_rcfg, FMBM_RCFG_EN);
+	/* enable MAC rx/tx port */
+	mac->enable_mac(mac);
+	/* enable bmi Tx port */
+	setbits_be32(&fm_eth->tx_port->fmbm_tcfg, FMBM_TCFG_EN);
+	/* re-enable transmission of frame */
+	fmc_tx_port_graceful_stop_disable(fm_eth);
+
+#ifdef CONFIG_PHYLIB
+	phy_startup(fm_eth->phydev);
+#else
+	fm_eth->phydev->speed = SPEED_1000;
+	fm_eth->phydev->link = 1;
+	fm_eth->phydev->duplex = DUPLEX_FULL;
+#endif
+
+	/* set the MAC-PHY mode */
+	mac->set_if_mode(mac, fm_eth->enet_if, fm_eth->phydev->speed);
+
+	if (!fm_eth->phydev->link)
+		printf("%s: No link.\n", fm_eth->phydev->dev->name);
+
+	return fm_eth->phydev->link ? 0 : -1;
+}
+
+static void fm_eth_halt(struct eth_device *dev)
+{
+	struct fm_eth *fm_eth;
+	struct fsl_enet_mac *mac;
+
+	fm_eth = (struct fm_eth *)dev->priv;
+	mac = fm_eth->mac;
+
+	/* graceful stop the transmission of frames */
+	fmc_tx_port_graceful_stop_enable(fm_eth);
+	/* disable bmi Tx port */
+	bmi_tx_port_disable(fm_eth->tx_port);
+	/* disable MAC rx/tx port */
+	mac->disable_mac(mac);
+	/* disable bmi Rx port */
+	bmi_rx_port_disable(fm_eth->rx_port);
+
+	phy_shutdown(fm_eth->phydev);
+}
+
+static int fm_eth_send(struct eth_device *dev, volatile void *buf, int len)
+{
+	struct fm_eth *fm_eth;
+	struct fm_port_global_pram *pram;
+	volatile struct fm_port_bd *txbd, *txbd_base;
+	u16 offset_in;
+	int i;
+
+	fm_eth = (struct fm_eth *)dev->priv;
+	pram = fm_eth->tx_pram;
+	txbd = fm_eth->cur_txbd;
+
+	/* find one empty TxBD */
+	for (i = 0; txbd->status & TxBD_READY; i++) {
+		udelay(100);
+		if (i > 0x1000) {
+			printf("%s: Tx buffer not ready\n", dev->name);
+			return 0;
+		}
+	}
+	/* setup TxBD */
+	txbd->buf_ptr_hi = 0;
+	txbd->buf_ptr_lo = (u32)buf;
+	txbd->len = len;
+	sync();
+	txbd->status = TxBD_READY | TxBD_LAST;
+	sync();
+
+	/* update TxQD, let RISC to send the packet */
+	offset_in = muram_readw(&pram->txqd.offset_in);
+	offset_in += sizeof(struct fm_port_bd);
+	if (offset_in >= muram_readw(&pram->txqd.bd_ring_size))
+		offset_in = 0;
+	muram_writew(&pram->txqd.offset_in, offset_in);
+	sync();
+
+	/* wait for buffer to be transmitted */
+	for (i = 0; txbd->status & TxBD_READY; i++) {
+		udelay(100);
+		if (i > 0x10000) {
+			printf("%s: Tx error\n", dev->name);
+			return 0;
+		}
+	}
+
+	/* advance the TxBD */
+	txbd++;
+	txbd_base = (struct fm_port_bd *)fm_eth->tx_bd_ring;
+	if (txbd >= (txbd_base + TX_BD_RING_SIZE))
+		txbd = txbd_base;
+	/* update current txbd */
+	fm_eth->cur_txbd = (void *)txbd;
+
+	return 1;
+}
+
+static int fm_eth_recv(struct eth_device *dev)
+{
+	struct fm_eth *fm_eth;
+	struct fm_port_global_pram *pram;
+	volatile struct fm_port_bd *rxbd, *rxbd_base;
+	u16 status, len;
+	u8 *data;
+	u16 offset_out;
+
+	fm_eth = (struct fm_eth *)dev->priv;
+	pram = fm_eth->rx_pram;
+	rxbd = fm_eth->cur_rxbd;
+	status = rxbd->status;
+
+	while (!(status & RxBD_EMPTY)) {
+		if (!(status & RxBD_ERROR)) {
+			data = (u8 *)rxbd->buf_ptr_lo;
+			len = rxbd->len;
+			NetReceive(data, len);
+		} else {
+			printf("%s: Rx error\n", dev->name);
+			return 0;
+		}
+
+		/* clear the RxBDs */
+		rxbd->status = RxBD_EMPTY;
+		rxbd->len = 0;
+		sync();
+
+		/* advance RxBD */
+		rxbd++;
+		rxbd_base = (struct fm_port_bd *)fm_eth->rx_bd_ring;
+		if (rxbd >= (rxbd_base + RX_BD_RING_SIZE))
+			rxbd = rxbd_base;
+		/* read next status */
+		status = rxbd->status;
+
+		/* update RxQD */
+		offset_out = muram_readw(&pram->rxqd.offset_out);
+		offset_out += sizeof(struct fm_port_bd);
+		if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size))
+			offset_out = 0;
+		muram_writew(&pram->rxqd.offset_out, offset_out);
+		sync();
+	}
+	fm_eth->cur_rxbd = (void *)rxbd;
+
+	return 1;
+}
+
+static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
+{
+	struct fsl_enet_mac *mac;
+	int num;
+	void *base, *phyregs = NULL;
+
+	num = fm_eth->num;
+
+	/* Get the mac registers base address */
+	if (fm_eth->type == FM_ETH_1G_E) {
+		base = &reg->mac_1g[num].fm_dtesc;
+	} else {
+		base = &reg->mac_10g[num].fm_10gec;
+		phyregs = &reg->mac_10g[num].fm_10gec_mdio;
+	}
+
+	/* alloc mac controller */
+	mac = malloc(sizeof(struct fsl_enet_mac));
+	if (!mac)
+		return 0;
+	memset(mac, 0, sizeof(struct fsl_enet_mac));
+
+	/* save the mac to fm_eth struct */
+	fm_eth->mac = mac;
+
+	if (fm_eth->type == FM_ETH_1G_E)
+		init_dtsec(mac, base, NULL, MAX_RXBUF_LEN);
+	else
+		init_tgec(mac, base, phyregs, MAX_RXBUF_LEN);
+
+	return 1;
+}
+
+static int init_phy(struct eth_device *dev)
+{
+	struct fm_eth *fm_eth = dev->priv;
+	struct phy_device *phydev = NULL;
+	u32 supported;
+
+#ifdef CONFIG_PHYLIB
+	if (fm_eth->type == FM_ETH_1G_E)
+		dtsec_init_phy(dev);
+
+	if (fm_eth->bus) {
+		phydev = phy_connect(fm_eth->bus, fm_eth->phyaddr, dev,
+					fm_eth->enet_if);
+	}
+
+	if (!phydev) {
+		printf("Failed to connect\n");
+		return -1;
+	}
+
+	if (fm_eth->type == FM_ETH_1G_E) {
+		supported = (SUPPORTED_10baseT_Half |
+				SUPPORTED_10baseT_Full |
+				SUPPORTED_100baseT_Half |
+				SUPPORTED_100baseT_Full |
+				SUPPORTED_1000baseT_Full);
+	} else {
+		supported = SUPPORTED_10000baseT_Full;
+
+		if (tgec_is_fibre(dev))
+			phydev->port = PORT_FIBRE;
+	}
+
+	phydev->supported &= supported;
+	phydev->advertising = phydev->supported;
+
+	fm_eth->phydev = phydev;
+
+	phy_config(phydev);
+#endif
+
+	return 0;
+}
+
+int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info)
+{
+	struct eth_device *dev;
+	struct fm_eth *fm_eth;
+	int i, num = info->num;
+
+	/* alloc eth device */
+	dev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	if (!dev)
+		return 0;
+	memset(dev, 0, sizeof(struct eth_device));
+
+	/* alloc the FMan ethernet private struct */
+	fm_eth = (struct fm_eth *)malloc(sizeof(struct fm_eth));
+	if (!fm_eth)
+		return 0;
+	memset(fm_eth, 0, sizeof(struct fm_eth));
+
+	/* save off some things we need from the info struct */
+	fm_eth->fm_index = info->index - 1; /* keep as 0 based for muram */
+	fm_eth->num = num;
+	fm_eth->type = info->type;
+
+	fm_eth->rx_port = (void *)&reg->port[info->rx_port_id - 1].fm_bmi;
+	fm_eth->tx_port = (void *)&reg->port[info->tx_port_id - 1].fm_bmi;
+
+	/* set the ethernet max receive length */
+	fm_eth->max_rx_len = MAX_RXBUF_LEN;
+
+	/* init global mac structure */
+	if (!fm_eth_init_mac(fm_eth, reg))
+		return 0;
+
+	/* keep same as the manual, we call FMAN1, FMAN2, DTSEC1, DTSEC2, etc */
+	if (fm_eth->type == FM_ETH_1G_E)
+		sprintf(dev->name, "FM%d at DTSEC%d", info->index, num + 1);
+	else
+		sprintf(dev->name, "FM%d at TGEC%d", info->index, num + 1);
+
+	devlist[num_controllers++] = dev;
+	dev->iobase = 0;
+	dev->priv = (void *)fm_eth;
+	dev->init = fm_eth_open;
+	dev->halt = fm_eth_halt;
+	dev->send = fm_eth_send;
+	dev->recv = fm_eth_recv;
+	fm_eth->dev = dev;
+	fm_eth->bus = info->bus;
+	fm_eth->phyaddr = info->phy_addr;
+	fm_eth->enet_if = info->enet_if;
+
+	/* startup the FM im */
+	if (!fm_eth_startup(fm_eth))
+		return 0;
+
+	if (init_phy(dev))
+		return 0;
+
+	/* clear the ethernet address */
+	for (i = 0; i < 6; i++)
+		dev->enetaddr[i] = 0;
+	eth_register(dev);
+
+	return 1;
+}
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
new file mode 100644
index 0000000..23ef14b
--- /dev/null
+++ b/drivers/net/fm/fm.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#include "fm.h"
+#include "../../qe/qe.h"		/* For struct qe_firmware */
+
+#ifdef CONFIG_SYS_QE_FW_IN_NAND
+#include <nand.h>
+#elif defined(CONFIG_SYS_QE_FW_IN_SPIFLASH)
+#include <spi_flash.h>
+#elif defined(CONFIG_SYS_QE_FW_IN_MMC)
+#include <mmc.h>
+#endif
+
+struct fm_muram muram[CONFIG_SYS_NUM_FMAN];
+
+u32 fm_muram_base(int fm_idx)
+{
+	return muram[fm_idx].base;
+}
+
+u32 fm_muram_alloc(int fm_idx, u32 size, u32 align)
+{
+	u32 ret;
+	u32 align_mask, off;
+	u32 save;
+
+	align_mask = align - 1;
+	save = muram[fm_idx].alloc;
+
+	off = save & align_mask;
+	if (off != 0)
+		muram[fm_idx].alloc += (align - off);
+	off = size & align_mask;
+	if (off != 0)
+		size += (align - off);
+	if ((muram[fm_idx].alloc + size) >= muram[fm_idx].top) {
+		muram[fm_idx].alloc = save;
+		printf("%s: run out of ram.\n", __func__);
+	}
+
+	ret = muram[fm_idx].alloc;
+	muram[fm_idx].alloc += size;
+	memset((void *)ret, 0, size);
+
+	return ret;
+}
+
+static void fm_init_muram(int fm_idx, void *reg)
+{
+	u32 base = (u32)reg;
+
+	muram[fm_idx].base = base;
+	muram[fm_idx].size = CONFIG_SYS_FM_MURAM_SIZE;
+	muram[fm_idx].alloc = base + FM_MURAM_RES_SIZE;
+	muram[fm_idx].top = base + CONFIG_SYS_FM_MURAM_SIZE;
+}
+
+/*
+ * fm_upload_ucode - Fman microcode upload worker function
+ *
+ * This function does the actual uploading of an Fman microcode
+ * to an Fman.
+ */
+static void fm_upload_ucode(int fm_idx, struct fm_imem *imem,
+			    u32 *ucode, unsigned int size)
+{
+	unsigned int i;
+	unsigned int timeout = 1000000;
+
+	/* enable address auto increase */
+	out_be32(&imem->iadd, IRAM_IADD_AIE);
+	/* write microcode to IRAM */
+	for (i = 0; i < size / 4; i++)
+		out_be32(&imem->idata, ucode[i]);
+
+	/* verify if the writing is over */
+	out_be32(&imem->iadd, 0);
+	while ((in_be32(&imem->idata) != ucode[0]) && --timeout)
+		;
+	if (!timeout)
+		printf("Fman%u: microcode upload timeout\n", fm_idx + 1);
+
+	/* enable microcode from IRAM */
+	out_be32(&imem->iready, IRAM_READY);
+}
+
+/*
+ * Upload an Fman firmware
+ *
+ * This function is similar to qe_upload_firmware(), exception that it uploads
+ * a microcode to the Fman instead of the QE.
+ *
+ * Because the process for uploading a microcode to the Fman is similar for
+ * that of the QE, the QE firmware binary format is used for Fman microcode.
+ * It should be possible to unify these two functions, but for now we keep them
+ * separate.
+ */
+static int fman_upload_firmware(int fm_idx,
+				struct fm_imem *fm_imem,
+				const struct qe_firmware *firmware)
+{
+	unsigned int i;
+	u32 crc;
+	size_t calc_size = sizeof(struct qe_firmware);
+	size_t length;
+	const struct qe_header *hdr;
+
+	if (!firmware) {
+		printf("Fman%u: Invalid address for firmware\n", fm_idx + 1);
+		return -EINVAL;
+	}
+
+	hdr = &firmware->header;
+	length = be32_to_cpu(hdr->length);
+
+	/* Check the magic */
+	if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+		(hdr->magic[2] != 'F')) {
+		printf("Fman%u: Data at %p is not a firmware\n", fm_idx + 1,
+		       firmware);
+		return -EPERM;
+	}
+
+	/* Check the version */
+	if (hdr->version != 1) {
+		printf("Fman%u: Unsupported firmware version %u\n", fm_idx + 1,
+		       hdr->version);
+		return -EPERM;
+	}
+
+	/* Validate some of the fields */
+	if ((firmware->count != 1)) {
+		printf("Fman%u: Invalid data in firmware header\n", fm_idx + 1);
+		return -EINVAL;
+	}
+
+	/* Validate the length and check if there's a CRC */
+	calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
+
+	for (i = 0; i < firmware->count; i++)
+		/*
+		 * For situations where the second RISC uses the same microcode
+		 * as the first, the 'code_offset' and 'count' fields will be
+		 * zero, so it's okay to add those.
+		 */
+		calc_size += sizeof(u32) *
+			be32_to_cpu(firmware->microcode[i].count);
+
+	/* Validate the length */
+	if (length != calc_size + sizeof(u32)) {
+		printf("Fman%u: Invalid length in firmware header\n",
+		       fm_idx + 1);
+		return -EPERM;
+	}
+
+	/*
+	 * Validate the CRC.  We would normally call crc32_no_comp(), but that
+	 * function isn't available unless you turn on JFFS support.
+	 */
+	crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
+	if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
+		printf("Fman%u: Firmware CRC is invalid\n", fm_idx + 1);
+		return -EIO;
+	}
+
+	/* Loop through each microcode. */
+	for (i = 0; i < firmware->count; i++) {
+		const struct qe_microcode *ucode = &firmware->microcode[i];
+
+		/* Upload a microcode if it's present */
+		if (ucode->code_offset) {
+			u32 ucode_size;
+			u32 *code;
+			printf("Fman%u: Uploading microcode version %u.%u.%u\n",
+			       fm_idx + 1, ucode->major, ucode->minor,
+			       ucode->revision);
+			code = (void *)firmware + ucode->code_offset;
+			ucode_size = sizeof(u32) * ucode->count;
+			fm_upload_ucode(fm_idx, fm_imem, code, ucode_size);
+		}
+	}
+
+	return 0;
+}
+
+static u32 fm_assign_risc(int port_id)
+{
+	u32 risc_sel, val;
+	risc_sel = (port_id & 0x1) ? FMFPPRC_RISC2 : FMFPPRC_RISC1;
+	val = (port_id << FMFPPRC_PORTID_SHIFT) & FMFPPRC_PORTID_MASK;
+	val |= ((risc_sel << FMFPPRC_ORA_SHIFT) | risc_sel);
+
+	return val;
+}
+
+static void fm_init_fpm(struct fm_fpm *fpm)
+{
+	int i, port_id;
+	u32 val;
+
+	setbits_be32(&fpm->fmfpee, FMFPEE_EHM | FMFPEE_UEC |
+				   FMFPEE_CER | FMFPEE_DER);
+
+	/* IM mode, each even port ID to RISC#1, each odd port ID to RISC#2 */
+
+	/* offline/parser port */
+	for (i = 0; i < MAX_NUM_OH_PORT; i++) {
+		port_id = OH_PORT_ID_BASE + i;
+		val = fm_assign_risc(port_id);
+		out_be32(&fpm->fpmprc, val);
+	}
+	/* Rx 1G port */
+	for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) {
+		port_id = RX_PORT_1G_BASE + i;
+		val = fm_assign_risc(port_id);
+		out_be32(&fpm->fpmprc, val);
+	}
+	/* Tx 1G port */
+	for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) {
+		port_id = TX_PORT_1G_BASE + i;
+		val = fm_assign_risc(port_id);
+		out_be32(&fpm->fpmprc, val);
+	}
+	/* Rx 10G port */
+	port_id = RX_PORT_10G_BASE;
+	val = fm_assign_risc(port_id);
+	out_be32(&fpm->fpmprc, val);
+	/* Tx 10G port */
+	port_id = TX_PORT_10G_BASE;
+	val = fm_assign_risc(port_id);
+	out_be32(&fpm->fpmprc, val);
+
+	/* disable the dispatch limit in IM case */
+	out_be32(&fpm->fpmflc, FMFP_FLC_DISP_LIM_NONE);
+	/* clear events */
+	out_be32(&fpm->fmfpee, FMFPEE_CLEAR_EVENT);
+
+	/* clear risc events */
+	for (i = 0; i < 4; i++)
+		out_be32(&fpm->fpmcev[i], 0xffffffff);
+
+	/* clear error */
+	out_be32(&fpm->fpmrcr, FMFP_RCR_MDEC | FMFP_RCR_IDEC);
+}
+
+static int fm_init_bmi(int fm_idx, struct fm_bmi_common *bmi)
+{
+	int blk, i, port_id;
+	u32 val, offset, base;
+
+	/* alloc free buffer pool in MURAM */
+	base = fm_muram_alloc(fm_idx, FM_FREE_POOL_SIZE, FM_FREE_POOL_ALIGN);
+	if (!base) {
+		printf("%s: no muram for free buffer pool\n", __func__);
+		return -ENOMEM;
+	}
+	offset = base - fm_muram_base(fm_idx);
+
+	/* Need 128KB total free buffer pool size */
+	val = offset / 256;
+	blk = FM_FREE_POOL_SIZE / 256;
+	/* in IM, we must not begin from offset 0 in MURAM */
+	val |= ((blk - 1) << FMBM_CFG1_FBPS_SHIFT);
+	out_be32(&bmi->fmbm_cfg1, val);
+
+	/* disable all BMI interrupt */
+	out_be32(&bmi->fmbm_ier, FMBM_IER_DISABLE_ALL);
+
+	/* clear all events */
+	out_be32(&bmi->fmbm_ievr, FMBM_IEVR_CLEAR_ALL);
+
+	/*
+	 * set port parameters - FMBM_PP_x
+	 * max tasks 10G Rx/Tx=12, 1G Rx/Tx 4, others is 1
+	 * max dma 10G Rx/Tx=3, others is 1
+	 * set port FIFO size - FMBM_PFS_x
+	 * 4KB for all Rx and Tx ports
+	 */
+	/* offline/parser port */
+	for (i = 0; i < MAX_NUM_OH_PORT; i++) {
+		port_id = OH_PORT_ID_BASE + i - 1;
+		/* max tasks=1, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id], 0);
+		/* port FIFO size - 256 bytes, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id], 0);
+	}
+	/* Rx 1G port */
+	for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) {
+		port_id = RX_PORT_1G_BASE + i - 1;
+		/* max tasks=4, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4));
+		/* FIFO size - 4KB, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
+	}
+	/* Tx 1G port FIFO size - 4KB, no extra */
+	for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) {
+		port_id = TX_PORT_1G_BASE + i - 1;
+		/* max tasks=4, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4));
+		/* FIFO size - 4KB, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
+	}
+	/* Rx 10G port */
+	port_id = RX_PORT_10G_BASE - 1;
+	/* max tasks=12, max dma=3, no extra */
+	out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3));
+	/* FIFO size - 4KB, no extra */
+	out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
+
+	/* Tx 10G port */
+	port_id = TX_PORT_10G_BASE - 1;
+	/* max tasks=12, max dma=3, no extra */
+	out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3));
+	/* FIFO size - 4KB, no extra */
+	out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
+
+	/* initialize internal buffers data base (linked list) */
+	out_be32(&bmi->fmbm_init, FMBM_INIT_START);
+
+	return 0;
+}
+
+static void fm_init_qmi(struct fm_qmi_common *qmi)
+{
+	/* disable enqueue and dequeue of QMI */
+	clrbits_be32(&qmi->fmqm_gc, FMQM_GC_ENQ_EN | FMQM_GC_DEQ_EN);
+
+	/* disable all error interrupts */
+	out_be32(&qmi->fmqm_eien, FMQM_EIEN_DISABLE_ALL);
+	/* clear all error events */
+	out_be32(&qmi->fmqm_eie, FMQM_EIE_CLEAR_ALL);
+
+	/* disable all interrupts */
+	out_be32(&qmi->fmqm_ien, FMQM_IEN_DISABLE_ALL);
+	/* clear all interrupts */
+	out_be32(&qmi->fmqm_ie, FMQM_IE_CLEAR_ALL);
+}
+
+/* Init common part of FM, index is fm num# like fm as above */
+int fm_init_common(int index, struct ccsr_fman *reg)
+{
+	int rc;
+	char env_addr[32];
+#if defined(CONFIG_SYS_FMAN_FW_ADDR)
+	void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR;
+#elif defined(CONFIG_SYS_QE_FW_IN_NAND)
+	size_t fw_length = CONFIG_SYS_FMAN_FW_LENGTH;
+	void *addr = malloc(CONFIG_SYS_FMAN_FW_LENGTH);
+
+	rc = nand_read(&nand_info[0], (loff_t)CONFIG_SYS_QE_FW_IN_NAND,
+		       &fw_length, (u_char *)addr);
+	if (rc == -EUCLEAN) {
+		printf("NAND read of FMAN firmware at offset 0x%x failed %d\n",
+			CONFIG_SYS_QE_FW_IN_NAND, rc);
+	}
+#elif defined(CONFIG_SYS_QE_FW_IN_SPIFLASH)
+	struct spi_flash *ucode_flash;
+	void *addr = malloc(CONFIG_SYS_FMAN_FW_LENGTH);
+	int ret = 0;
+
+	ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
+			CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
+	if (!ucode_flash)
+		printf("SF: probe for ucode failed\n");
+	else {
+		ret = spi_flash_read(ucode_flash, CONFIG_SYS_QE_FW_IN_SPIFLASH,
+				CONFIG_SYS_FMAN_FW_LENGTH, addr);
+		if (ret)
+			printf("SF: read for ucode failed\n");
+		spi_flash_free(ucode_flash);
+	}
+#elif defined(CONFIG_SYS_QE_FW_IN_MMC)
+	int dev = CONFIG_SYS_MMC_ENV_DEV;
+	void *addr = malloc(CONFIG_SYS_FMAN_FW_LENGTH);
+	u32 cnt = CONFIG_SYS_FMAN_FW_LENGTH / 512;
+	u32 n;
+	u32 blk = CONFIG_SYS_QE_FW_IN_MMC / 512;
+	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+
+	if (!mmc)
+		printf("\nMMC cannot find device for ucode\n");
+	else {
+		printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
+				dev, blk, cnt);
+		mmc_init(mmc);
+		n = mmc->block_dev.block_read(dev, blk, cnt, addr);
+		/* flush cache after read */
+		flush_cache((ulong)addr, cnt * 512);
+	}
+#endif
+
+	/* Upload the Fman microcode if it's present */
+	rc = fman_upload_firmware(index, &reg->fm_imem, addr);
+	if (rc)
+		return rc;
+	sprintf(env_addr, "0x%lx", (long unsigned int)addr);
+	setenv("fman_ucode", env_addr);
+
+	fm_init_muram(index, &reg->muram);
+	fm_init_qmi(&reg->fm_qmi_common);
+	fm_init_fpm(&reg->fm_fpm);
+
+	/* clear DMA status */
+	setbits_be32(&reg->fm_dma.fmdmsr, FMDMSR_CLEAR_ALL);
+
+	/* set DMA mode */
+	setbits_be32(&reg->fm_dma.fmdmmr, FMDMMR_SBER);
+
+	return fm_init_bmi(index, &reg->fm_bmi_common);
+}
diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h
new file mode 100644
index 0000000..be6714f
--- /dev/null
+++ b/drivers/net/fm/fm.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FM_H__
+#define __FM_H__
+
+#include <common.h>
+#include <fm_eth.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_fman.h>
+
+/* Port ID */
+#define OH_PORT_ID_BASE		0x01
+#define MAX_NUM_OH_PORT		7
+#define RX_PORT_1G_BASE		0x08
+#define MAX_NUM_RX_PORT_1G	CONFIG_SYS_NUM_FM1_DTSEC
+#define RX_PORT_10G_BASE	0x10
+#define TX_PORT_1G_BASE		0x28
+#define MAX_NUM_TX_PORT_1G	CONFIG_SYS_NUM_FM1_DTSEC
+#define TX_PORT_10G_BASE	0x30
+
+struct fm_muram {
+	u32 base;
+	u32 top;
+	u32 size;
+	u32 alloc;
+};
+#define FM_MURAM_RES_SIZE	0x01000
+
+/* Rx/Tx buffer descriptor */
+struct fm_port_bd {
+	u16 status;
+	u16 len;
+	u32 res0;
+	u16 res1;
+	u16 buf_ptr_hi;
+	u32 buf_ptr_lo;
+};
+
+/* Common BD flags */
+#define BD_LAST			0x0800
+
+/* Rx BD status flags */
+#define RxBD_EMPTY		0x8000
+#define RxBD_LAST		BD_LAST
+#define RxBD_FIRST		0x0400
+#define RxBD_PHYS_ERR		0x0008
+#define RxBD_SIZE_ERR		0x0004
+#define RxBD_ERROR		(RxBD_PHYS_ERR | RxBD_SIZE_ERR)
+
+/* Tx BD status flags */
+#define TxBD_READY		0x8000
+#define TxBD_LAST		BD_LAST
+
+/* Rx/Tx queue descriptor */
+struct fm_port_qd {
+	u16 gen;
+	u16 bd_ring_base_hi;
+	u32 bd_ring_base_lo;
+	u16 bd_ring_size;
+	u16 offset_in;
+	u16 offset_out;
+	u16 res0;
+	u32 res1[0x4];
+};
+
+/* IM global parameter RAM */
+struct fm_port_global_pram {
+	u32 mode;	/* independent mode register */
+	u32 rxqd_ptr;	/* Rx queue descriptor pointer */
+	u32 txqd_ptr;	/* Tx queue descriptor pointer */
+	u16 mrblr;	/* max Rx buffer length */
+	u16 rxqd_bsy_cnt;	/* RxQD busy counter, should be cleared */
+	u32 res0[0x4];
+	struct fm_port_qd rxqd;	/* Rx queue descriptor */
+	struct fm_port_qd txqd;	/* Tx queue descriptor */
+	u32 res1[0x28];
+};
+
+#define FM_PRAM_SIZE		sizeof(struct fm_port_global_pram)
+#define FM_PRAM_ALIGN		256
+#define PRAM_MODE_GLOBAL	0x20000000
+#define PRAM_MODE_GRACEFUL_STOP	0x00800000
+
+#if defined(CONFIG_P1017) || defined(CONFIG_P1023)
+#define FM_FREE_POOL_SIZE	0x2000 /* 8K bytes */
+#else
+#define FM_FREE_POOL_SIZE	0x20000 /* 128K bytes */
+#endif
+#define FM_FREE_POOL_ALIGN	256
+
+u32 fm_muram_alloc(int fm_idx, u32 size, u32 align);
+u32 fm_muram_base(int fm_idx);
+int fm_init_common(int index, struct ccsr_fman *reg);
+int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info);
+phy_interface_t fman_port_enet_if(enum fm_port port);
+
+struct fsl_enet_mac {
+	void *base; /* MAC controller registers base address */
+	void *phyregs;
+	int max_rx_len;
+	void (*init_mac)(struct fsl_enet_mac *mac);
+	void (*enable_mac)(struct fsl_enet_mac *mac);
+	void (*disable_mac)(struct fsl_enet_mac *mac);
+	void (*set_mac_addr)(struct fsl_enet_mac *mac, u8 *mac_addr);
+	void (*set_if_mode)(struct fsl_enet_mac *mac, phy_interface_t type,
+				int speed);
+};
+
+/* Fman ethernet private struct */
+struct fm_eth {
+	int fm_index;			/* Fman index */
+	u32 num;			/* 0..n-1 for give type */
+	struct fm_bmi_tx_port *tx_port;
+	struct fm_bmi_rx_port *rx_port;
+	enum fm_eth_type type;		/* 1G or 10G ethernet */
+	phy_interface_t enet_if;
+	struct fsl_enet_mac *mac;	/* MAC controller */
+	struct mii_dev *bus;
+	struct phy_device *phydev;
+	int phyaddr;
+	struct eth_device *dev;
+	int max_rx_len;
+	struct fm_port_global_pram *rx_pram; /* Rx parameter table */
+	struct fm_port_global_pram *tx_pram; /* Tx parameter table */
+	void *rx_bd_ring;		/* Rx BD ring base */
+	void *cur_rxbd;			/* current Rx BD */
+	void *rx_buf;			/* Rx buffer base */
+	void *tx_bd_ring;		/* Tx BD ring base */
+	void *cur_txbd;			/* current Tx BD */
+};
+
+#define RX_BD_RING_SIZE		8
+#define TX_BD_RING_SIZE		8
+#define MAX_RXBUF_LOG2		11
+#define MAX_RXBUF_LEN		(1 << MAX_RXBUF_LOG2)
+
+#endif /* __FM_H__ */
diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c
new file mode 100644
index 0000000..5f05ab1
--- /dev/null
+++ b/drivers/net/fm/init.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_serdes.h>
+
+#include "fm.h"
+
+struct fm_eth_info fm_info[] = {
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 1)
+	FM_DTSEC_INFO_INITIALIZER(1, 1),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 2)
+	FM_DTSEC_INFO_INITIALIZER(1, 2),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 3)
+	FM_DTSEC_INFO_INITIALIZER(1, 3),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 4)
+	FM_DTSEC_INFO_INITIALIZER(1, 4),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 5)
+	FM_DTSEC_INFO_INITIALIZER(1, 5),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 1)
+	FM_DTSEC_INFO_INITIALIZER(2, 1),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 2)
+	FM_DTSEC_INFO_INITIALIZER(2, 2),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 3)
+	FM_DTSEC_INFO_INITIALIZER(2, 3),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 4)
+	FM_DTSEC_INFO_INITIALIZER(2, 4),
+#endif
+#if (CONFIG_SYS_NUM_FM1_10GEC >= 1)
+	FM_TGEC_INFO_INITIALIZER(1, 1),
+#endif
+#if (CONFIG_SYS_NUM_FM2_10GEC >= 1)
+	FM_TGEC_INFO_INITIALIZER(2, 1),
+#endif
+};
+
+int fm_standard_init(bd_t *bis)
+{
+	int i;
+	struct ccsr_fman *reg;
+
+	reg = (void *)CONFIG_SYS_FSL_FM1_ADDR;
+	if (fm_init_common(0, reg))
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
+		if ((fm_info[i].enabled) && (fm_info[i].index == 1))
+			fm_eth_initialize(reg, &fm_info[i]);
+	}
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	reg = (void *)CONFIG_SYS_FSL_FM2_ADDR;
+	if (fm_init_common(1, reg))
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
+		if ((fm_info[i].enabled) && (fm_info[i].index == 2))
+			fm_eth_initialize(reg, &fm_info[i]);
+	}
+#endif
+
+	return 1;
+}
+
+/* simple linear search to map from port to array index */
+static int fm_port_to_index(enum fm_port port)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
+		if (fm_info[i].port == port)
+			return i;
+	}
+
+	return -1;
+}
+
+/*
+ * Determine if an interface is actually active based on HW config
+ * we expect fman_port_enet_if() to report PHY_INTERFACE_MODE_NONE if
+ * the interface is not active based on HW cfg of the SoC
+ */
+void fman_enet_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
+		phy_interface_t enet_if;
+
+		enet_if = fman_port_enet_if(fm_info[i].port);
+		if (enet_if != PHY_INTERFACE_MODE_NONE) {
+			fm_info[i].enabled = 1;
+			fm_info[i].enet_if = enet_if;
+		} else {
+			fm_info[i].enabled = 0;
+		}
+	}
+
+	return ;
+}
+
+void fm_info_set_mdio(enum fm_port port, struct mii_dev *bus)
+{
+	int i = fm_port_to_index(port);
+
+	if (i == -1)
+		return;
+
+	fm_info[i].bus = bus;
+}
+
+void fm_info_set_phy_address(enum fm_port port, int address)
+{
+	int i = fm_port_to_index(port);
+
+	if (i == -1)
+		return;
+
+	fm_info[i].phy_addr = address;
+}
+
+/*
+ * Returns the type of the data interface between the given MAC and its PHY.
+ * This is typically determined by the RCW.
+ */
+phy_interface_t fm_info_get_enet_if(enum fm_port port)
+{
+	int i = fm_port_to_index(port);
+
+	if (i == -1)
+		return PHY_INTERFACE_MODE_NONE;
+
+	if (fm_info[i].enabled)
+		return fm_info[i].enet_if;
+
+	return PHY_INTERFACE_MODE_NONE;
+}
+
+static void
+__def_board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
+				enum fm_port port, int offset)
+{
+	return ;
+}
+
+void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
+				enum fm_port port, int offset)
+	 __attribute__((weak, alias("__def_board_ft_fman_fixup_port")));
+
+static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop)
+{
+	int off, ph;
+	phys_addr_t paddr = CONFIG_SYS_CCSRBAR_PHYS + info->compat_offset;
+
+	off = fdt_node_offset_by_compat_reg(blob, prop, paddr);
+
+	if (info->enabled) {
+		fdt_fixup_phy_connection(blob, off, info->enet_if);
+		board_ft_fman_fixup_port(blob, prop, paddr, info->port, off);
+		return ;
+	}
+
+	/* board code might have caused offset to change */
+	off = fdt_node_offset_by_compat_reg(blob, prop, paddr);
+
+	/* disable both the mac node and the node that has a handle to it */
+	fdt_setprop_string(blob, off, "status", "disabled");
+
+	ph = fdt_get_phandle(blob, off);
+	do_fixup_by_prop(blob, "fsl,fman-mac", &ph, sizeof(ph),
+		"status", "disabled", strlen("disabled") + 1, 1);
+}
+
+void fdt_fixup_fman_ethernet(void *blob)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(fm_info); i++) {
+		if (fm_info[i].type == FM_ETH_1G_E)
+			ft_fixup_port(blob, &fm_info[i], "fsl,fman-1g-mac");
+		else
+			ft_fixup_port(blob, &fm_info[i], "fsl,fman-10g-mac");
+	}
+}
diff --git a/drivers/net/fm/p1023.c b/drivers/net/fm/p1023.c
new file mode 100644
index 0000000..c196e79
--- /dev/null
+++ b/drivers/net/fm/p1023.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+u32 port_to_devdisr[] = {
+	[FM1_DTSEC1] = MPC85xx_DEVDISR_TSEC1,
+	[FM1_DTSEC2] = MPC85xx_DEVDISR_TSEC2,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 devdisr = in_be32(&gur->devdisr);
+
+	return port_to_devdisr[port] & devdisr;
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 pordevsr = in_be32(&gur->pordevsr);
+
+	if (is_device_disabled(port))
+		return PHY_INTERFACE_MODE_NONE;
+
+	/* DTSEC1 can be SGMII, RGMII or RMII */
+	if (port == FM1_DTSEC1) {
+		if (is_serdes_configured(SGMII_FM1_DTSEC1))
+			return PHY_INTERFACE_MODE_SGMII;
+		if (pordevsr & MPC85xx_PORDEVSR_SGMII1_DIS) {
+			if (pordevsr & MPC85xx_PORDEVSR_TSEC1_PRTC)
+				return PHY_INTERFACE_MODE_RGMII;
+			else
+				return PHY_INTERFACE_MODE_RMII;
+		}
+	}
+
+	/* DTSEC2 only supports SGMII or RGMII */
+	if (port == FM1_DTSEC2) {
+		if (is_serdes_configured(SGMII_FM1_DTSEC2))
+			return PHY_INTERFACE_MODE_SGMII;
+		if (pordevsr & MPC85xx_PORDEVSR_SGMII2_DIS)
+			return PHY_INTERFACE_MODE_RGMII;
+	}
+
+	return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/fm/p4080.c b/drivers/net/fm/p4080.c
new file mode 100644
index 0000000..6761a2f
--- /dev/null
+++ b/drivers/net/fm/p4080.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+u32 port_to_devdisr[] = {
+	[FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1,
+	[FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2,
+	[FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3,
+	[FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4,
+	[FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1,
+	[FM2_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC2_1,
+	[FM2_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC2_2,
+	[FM2_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC2_3,
+	[FM2_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC2_4,
+	[FM2_10GEC1] = FSL_CORENET_DEVDISR2_10GEC2,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 devdisr2 = in_be32(&gur->devdisr2);
+
+	return port_to_devdisr[port] & devdisr2;
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 rcwsr11 = in_be32(&gur->rcwsr[11]);
+
+	if (is_device_disabled(port))
+		return PHY_INTERFACE_MODE_NONE;
+
+	if ((port == FM1_10GEC1) && (is_serdes_configured(XAUI_FM1)))
+		return PHY_INTERFACE_MODE_XGMII;
+
+	if ((port == FM2_10GEC1) && (is_serdes_configured(XAUI_FM2)))
+		return PHY_INTERFACE_MODE_XGMII;
+
+	/* handle RGMII first */
+	if ((port == FM1_DTSEC1) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+		FSL_CORENET_RCWSR11_EC1_FM1_DTSEC1))
+		return PHY_INTERFACE_MODE_RGMII;
+
+	if ((port == FM1_DTSEC2) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2))
+		return PHY_INTERFACE_MODE_RGMII;
+
+	if ((port == FM2_DTSEC1) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1))
+		return PHY_INTERFACE_MODE_RGMII;
+
+	switch (port) {
+	case FM1_DTSEC1:
+	case FM1_DTSEC2:
+	case FM1_DTSEC3:
+	case FM1_DTSEC4:
+		if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1))
+			return PHY_INTERFACE_MODE_SGMII;
+		break;
+	case FM2_DTSEC1:
+	case FM2_DTSEC2:
+	case FM2_DTSEC3:
+	case FM2_DTSEC4:
+		if (is_serdes_configured(SGMII_FM2_DTSEC1 + port - FM2_DTSEC1))
+			return PHY_INTERFACE_MODE_SGMII;
+		break;
+	default:
+		return PHY_INTERFACE_MODE_NONE;
+	}
+
+	return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/fm/p5020.c b/drivers/net/fm/p5020.c
new file mode 100644
index 0000000..59638eb
--- /dev/null
+++ b/drivers/net/fm/p5020.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+u32 port_to_devdisr[] = {
+	[FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1,
+	[FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2,
+	[FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3,
+	[FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4,
+	[FM1_DTSEC5] = FSL_CORENET_DEVDISR2_DTSEC1_5,
+	[FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 devdisr2 = in_be32(&gur->devdisr2);
+
+	return port_to_devdisr[port] & devdisr2;
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 rcwsr11 = in_be32(&gur->rcwsr[11]);
+
+	if (is_device_disabled(port))
+		return PHY_INTERFACE_MODE_NONE;
+
+	if ((port == FM1_10GEC1) && (is_serdes_configured(XAUI_FM1)))
+		return PHY_INTERFACE_MODE_XGMII;
+
+	/* handle RGMII first */
+	if ((port == FM1_DTSEC4) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+		FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_RGMII))
+		return PHY_INTERFACE_MODE_RGMII;
+
+	if ((port == FM1_DTSEC4) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+		FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_MII))
+		return PHY_INTERFACE_MODE_MII;
+
+	if ((port == FM1_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_RGMII))
+		return PHY_INTERFACE_MODE_RGMII;
+
+	if ((port == FM1_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_MII))
+		return PHY_INTERFACE_MODE_MII;
+
+	switch (port) {
+	case FM1_DTSEC1:
+	case FM1_DTSEC2:
+	case FM1_DTSEC3:
+	case FM1_DTSEC4:
+	case FM1_DTSEC5:
+		if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1))
+			return PHY_INTERFACE_MODE_SGMII;
+		break;
+	default:
+		return PHY_INTERFACE_MODE_NONE;
+	}
+
+	return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/fm/tgec.c b/drivers/net/fm/tgec.c
new file mode 100644
index 0000000..6c1d471
--- /dev/null
+++ b/drivers/net/fm/tgec.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* MAXFRM - maximum frame length */
+#define MAXFRM_MASK	0x0000ffff
+
+#include <common.h>
+#include <phy.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_tgec.h>
+
+#include "fm.h"
+
+#define TGEC_CMD_CFG_INIT	(TGEC_CMD_CFG_NO_LEN_CHK | \
+				 TGEC_CMD_CFG_RX_ER_DISC | \
+				 TGEC_CMD_CFG_STAT_CLR | \
+				 TGEC_CMD_CFG_PAUSE_IGNORE | \
+				 TGEC_CMD_CFG_CRC_FWD)
+#define TGEC_CMD_CFG_FINAL	(TGEC_CMD_CFG_NO_LEN_CHK | \
+				 TGEC_CMD_CFG_RX_ER_DISC | \
+				 TGEC_CMD_CFG_PAUSE_IGNORE | \
+				 TGEC_CMD_CFG_CRC_FWD)
+
+static void tgec_init_mac(struct fsl_enet_mac *mac)
+{
+	struct tgec *regs = mac->base;
+
+	/* mask all interrupt */
+	out_be32(&regs->imask, IMASK_MASK_ALL);
+
+	/* clear all events */
+	out_be32(&regs->ievent, IEVENT_CLEAR_ALL);
+
+	/* set the max receive length */
+	out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);
+
+	/*
+	 * 1588 disable, insert second mac disable payload length check
+	 * disable, normal operation, any rx error frame is discarded, clear
+	 * counters, pause frame ignore, no promiscuous, LAN mode Rx CRC no
+	 * strip, Tx CRC append, Rx disable and Tx disable
+	 */
+	out_be32(&regs->command_config, TGEC_CMD_CFG_INIT);
+	udelay(1000);
+	out_be32(&regs->command_config, TGEC_CMD_CFG_FINAL);
+
+	/* multicast frame reception for the hash entry disable */
+	out_be32(&regs->hashtable_ctrl, 0);
+}
+
+static void tgec_enable_mac(struct fsl_enet_mac *mac)
+{
+	struct tgec *regs = mac->base;
+
+	setbits_be32(&regs->command_config, TGEC_CMD_CFG_RXTX_EN);
+}
+
+static void tgec_disable_mac(struct fsl_enet_mac *mac)
+{
+	struct tgec *regs = mac->base;
+
+	clrbits_be32(&regs->command_config, TGEC_CMD_CFG_RXTX_EN);
+}
+
+static void tgec_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr)
+{
+	struct tgec *regs = mac->base;
+	u32 mac_addr0, mac_addr1;
+
+	/*
+	 * if a station address of 0x12345678ABCD, perform a write to
+	 * MAC_ADDR0 of 0x78563412, MAC_ADDR1 of 0x0000CDAB
+	 */
+	mac_addr0 = (mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+			(mac_addr[1] << 8)  | (mac_addr[0]);
+	out_be32(&regs->mac_addr_0, mac_addr0);
+
+	mac_addr1 = ((mac_addr[5] << 8) | mac_addr[4]) & 0x0000ffff;
+	out_be32(&regs->mac_addr_1, mac_addr1);
+}
+
+static void tgec_set_interface_mode(struct fsl_enet_mac *mac,
+					phy_interface_t type, int speed)
+{
+	/* nothing right now */
+	return;
+}
+
+void init_tgec(struct fsl_enet_mac *mac, void *base,
+		void *phyregs, int max_rx_len)
+{
+	mac->base = base;
+	mac->phyregs = phyregs;
+	mac->max_rx_len = max_rx_len;
+	mac->init_mac = tgec_init_mac;
+	mac->enable_mac = tgec_enable_mac;
+	mac->disable_mac = tgec_disable_mac;
+	mac->set_mac_addr = tgec_set_mac_addr;
+	mac->set_if_mode = tgec_set_interface_mode;
+}
diff --git a/drivers/net/fm/tgec_phy.c b/drivers/net/fm/tgec_phy.c
new file mode 100644
index 0000000..2d349ad
--- /dev/null
+++ b/drivers/net/fm/tgec_phy.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *	Andy Fleming <afleming at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ * Some part is taken from tsec.c
+ */
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/io.h>
+#include <asm/fsl_tgec.h>
+#include <fm_eth.h>
+
+/*
+ * Write value to the PHY for this device to the register at regnum, waiting
+ * until the write is done before it returns.  All PHY configuration has to be
+ * done through the TSEC1 MIIM regs
+ */
+int tgec_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
+			int regnum, u16 value)
+{
+	u32 mdio_ctl;
+	u32 stat_val;
+	struct tgec_mdio_controller *regs = bus->priv;
+
+	if (dev_addr == MDIO_DEVAD_NONE)
+		return 0;
+
+	/* Wait till the bus is free */
+	stat_val = MDIO_STAT_CLKDIV(100);
+	out_be32(&regs->mdio_stat, stat_val);
+	while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+		;
+
+	/* Set the port and dev addr */
+	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+	out_be32(&regs->mdio_ctl, mdio_ctl);
+
+	/* Set the register address */
+	out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+	/* Wait till the bus is free */
+	while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+		;
+
+	/* Write the value to the register */
+	out_be32(&regs->mdio_data, MDIO_DATA(value));
+
+	/* Wait till the MDIO write is complete */
+	while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+		;
+
+	return 0;
+}
+
+/*
+ * Reads from register regnum in the PHY for device dev, returning the value.
+ * Clears miimcom first.  All PHY configuration has to be done through the
+ * TSEC1 MIIM regs
+ */
+int tgec_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
+			int regnum)
+{
+	u32 mdio_ctl;
+	u32 stat_val;
+	struct tgec_mdio_controller *regs = bus->priv;
+
+	if (dev_addr == MDIO_DEVAD_NONE)
+		return 0xffff;
+
+	stat_val = MDIO_STAT_CLKDIV(100);
+	out_be32(&regs->mdio_stat, stat_val);
+	/* Wait till the bus is free */
+	while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+		;
+
+	/* Set the Port and Device Addrs */
+	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+	out_be32(&regs->mdio_ctl, mdio_ctl);
+
+	/* Set the register address */
+	out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+	/* Wait till the bus is free */
+	while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+		;
+
+	/* Initiate the read */
+	mdio_ctl |= MDIO_CTL_READ;
+	out_be32(&regs->mdio_ctl, mdio_ctl);
+
+	/* Wait till the MDIO write is complete */
+	while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+		;
+
+	/* Return all Fs if nothing was there */
+	if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
+		return 0xffff;
+
+	return in_be32(&regs->mdio_data) & 0xffff;
+}
+
+int tgec_mdio_reset(struct mii_dev *bus)
+{
+	return 0;
+}
+
+int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info)
+{
+	struct mii_dev *bus = mdio_alloc();
+
+	if (!bus) {
+		printf("Failed to allocate FM TGEC MDIO bus\n");
+		return -1;
+	}
+
+	bus->read = tgec_mdio_read;
+	bus->write = tgec_mdio_write;
+	bus->reset = tgec_mdio_reset;
+	sprintf(bus->name, info->name);
+
+	bus->priv = info->regs;
+
+	return mdio_register(bus);
+}
diff --git a/include/fm_eth.h b/include/fm_eth.h
new file mode 100644
index 0000000..2ca584a
--- /dev/null
+++ b/include/fm_eth.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FM_ETH_H__
+#define __FM_ETH_H__
+
+#include <common.h>
+#include <asm/types.h>
+#include <asm/fsl_enet.h>
+
+enum fm_port {
+	FM1_DTSEC1,
+	FM1_DTSEC2,
+	FM1_DTSEC3,
+	FM1_DTSEC4,
+	FM1_DTSEC5,
+	FM1_10GEC1,
+	FM2_DTSEC1,
+	FM2_DTSEC2,
+	FM2_DTSEC3,
+	FM2_DTSEC4,
+	FM2_10GEC1,
+	NUM_FM_PORTS,
+};
+
+enum fm_eth_type {
+	FM_ETH_1G_E,
+	FM_ETH_10G_E,
+};
+
+#define CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR	(CONFIG_SYS_FSL_FM1_ADDR + 0xe1120)
+#define CONFIG_SYS_FM1_TGEC_MDIO_ADDR	(CONFIG_SYS_FSL_FM1_ADDR + 0xf1000)
+
+#define DEFAULT_FM_MDIO_NAME "FSL_MDIO0"
+#define DEFAULT_FM_TGEC_MDIO_NAME "FM_TGEC_MDIO"
+
+/* Fman ethernet info struct */
+#define FM_ETH_INFO_INITIALIZER(idx, pregs) \
+	.fm		= idx,						\
+	.phy_regs	= (void *)pregs,				\
+	.enet_if	= PHY_INTERFACE_MODE_NONE,			\
+
+#define FM_DTSEC_INFO_INITIALIZER(idx, n) \
+{									\
+	FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR)	\
+	.index		= idx,						\
+	.num		= n - 1,					\
+	.type		= FM_ETH_1G_E,					\
+	.port		= FM##idx##_DTSEC##n,				\
+	.rx_port_id	= RX_PORT_1G_BASE + n - 1,			\
+	.tx_port_id	= TX_PORT_1G_BASE + n - 1,			\
+	.compat_offset	= CONFIG_SYS_FSL_FM##idx##_OFFSET +		\
+				offsetof(struct ccsr_fman, mac_1g[n-1]),\
+}
+
+#define FM_TGEC_INFO_INITIALIZER(idx, n) \
+{									\
+	FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR)	\
+	.index		= idx,						\
+	.num		= n - 1,					\
+	.type		= FM_ETH_10G_E,					\
+	.port		= FM##idx##_10GEC##n,				\
+	.rx_port_id	= RX_PORT_10G_BASE + n - 1,			\
+	.tx_port_id	= TX_PORT_10G_BASE + n - 1,			\
+	.compat_offset	= CONFIG_SYS_FSL_FM##idx##_OFFSET +		\
+				offsetof(struct ccsr_fman, mac_10g[n-1]),\
+}
+
+struct fm_eth_info {
+	u8 enabled;
+	u8 fm;
+	u8 num;
+	u8 phy_addr;
+	int index;
+	u16 rx_port_id;
+	u16 tx_port_id;
+	enum fm_port port;
+	enum fm_eth_type type;
+	void *phy_regs;
+	phy_interface_t enet_if;
+	u32 compat_offset;
+	struct mii_dev *bus;
+};
+
+struct tgec_mdio_info {
+	struct tgec_mdio_controller *regs;
+	char *name;
+};
+
+int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info);
+int fm_standard_init(bd_t *bis);
+void fman_enet_init(void);
+void fdt_fixup_fman_ethernet(void *fdt);
+phy_interface_t fm_info_get_enet_if(enum fm_port port);
+void fm_info_set_phy_address(enum fm_port port, int address);
+void fm_info_set_mdio(enum fm_port port, struct mii_dev *bus);
+
+#endif
-- 
1.7.3.4



More information about the U-Boot mailing list