All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode
@ 2011-01-27  4:52 Mingkai Hu
  2011-01-27  4:52 ` [U-Boot] [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl Mingkai Hu
  2011-01-27  6:04 ` [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Kumar Gala
  0 siblings, 2 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

This patchset add support for the P4080's datapath accelation architecture
in independent mode, and do some code refactor of the file tsec.c.

1. Add the releated MAC controller support, includeing dTSEC and 10GEC
2. Add support for FMan ethernet in Independent mode
3. Add PHY support (VSC8244 and VSC8234) to a new file fsl_phy.c which
   can be reused by other code, such tsec and uec code.
4. tsec code cleanup
5. Move all the PHY code in tsec.c to fsl_phy.c to make it reuseable.

Based on the latest WD's U-Boot tree. Tested on P4080DS and MPC8536DS
board with SGMII card.

[PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl
[PATCH 02/14] powerpc/fman: add PHY support for dTSEC
[PATCH 03/14] powerpc/fman: add dTSEC controller support
[PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support
[PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode
[PATCH 06/14] powerpc/corenet_ds: Add fman support
[PATCH 07/14] tsec: use IO accessories to access the register
[PATCH 08/14] tsec: arrange the code to avoid useless function declaration
[PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t)
[PATCH 10/14] tsec: refactor the PHY code to make it reuseable
[PATCH 11/14] PHY: add some Vitesse phy support
[PATCH 12/14] PHY: add some Broadcom phy support
[PATCH 13/14] PHY: add some Marvell phy support
[PATCH 14/14] PHY: add some misc phy code support

Thanks,
Mingkai

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

* [U-Boot] [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl
  2011-01-27  4:52 [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Mingkai Hu
@ 2011-01-27  4:52 ` Mingkai Hu
  2011-01-27  4:52   ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Mingkai Hu
  2011-01-27  6:04 ` [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Kumar Gala
  1 sibling, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Kumar Gala <galak@kernel.crashing.org>

Also rename serdes_get_bank() to serdes_get_bank_by_lane().

Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c |   33 +++++++++++++++++++++++-
 arch/powerpc/include/asm/fsl_serdes.h         |    4 +++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
index 7fc00d8..c4c595e 100644
--- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
@@ -29,6 +29,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/fsl_law.h>
+#include <asm/errno.h>
 #include "fsl_corenet_serdes.h"
 
 static u32 serdes_prtcl_map;
@@ -91,7 +92,7 @@ int serdes_get_lane_idx(int lane)
 	return lanes[lane].idx;
 }
 
-int serdes_get_bank(int lane)
+int serdes_get_bank_by_lane(int lane)
 {
 	return lanes[lane].bank;
 }
@@ -263,6 +264,34 @@ static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur,
 }
 #endif
 
+static int __serdes_get_first_lane(uint32_t prtcl, enum srds_prtcl device)
+{
+	int i;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (serdes_get_prtcl(prtcl, i) == device)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+int serdes_get_first_lane(enum srds_prtcl device)
+{
+	u32 prtcl;
+	const ccsr_gur_t *gur;
+
+	gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* Is serdes enabled@all? */
+	if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0))
+		return -ENODEV;
+
+	prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
+
+	return __serdes_get_first_lane(prtcl, device);
+}
+
 void fsl_serdes_init(void)
 {
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
@@ -318,7 +347,7 @@ void fsl_serdes_init(void)
 	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
 		enum srds_prtcl lane_prtcl = serdes_get_prtcl(cfg, lane);
 		if (serdes_lane_enabled(lane)) {
-			have_bank[serdes_get_bank(lane)] = 1;
+			have_bank[serdes_get_bank_by_lane(lane)] = 1;
 			serdes_prtcl_map |= (1 << lane_prtcl);
 		}
 	}
diff --git a/arch/powerpc/include/asm/fsl_serdes.h b/arch/powerpc/include/asm/fsl_serdes.h
index 85518eb..9d9f2e4 100644
--- a/arch/powerpc/include/asm/fsl_serdes.h
+++ b/arch/powerpc/include/asm/fsl_serdes.h
@@ -53,4 +53,8 @@ enum srds_prtcl {
 int is_serdes_configured(enum srds_prtcl device);
 void fsl_serdes_init(void);
 
+#ifdef CONFIG_FSL_CORENET
+int serdes_get_first_lane(enum srds_prtcl device);
+#endif
+
 #endif /* __FSL_SERDES_H */
-- 
1.6.4

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

* [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC
  2011-01-27  4:52 ` [U-Boot] [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl Mingkai Hu
@ 2011-01-27  4:52   ` Mingkai Hu
  2011-01-27  4:52     ` [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support Mingkai Hu
                       ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Kumar Gala <galak@kernel.crashing.org>

Add VSC8244 and VSC8234 phy support, this will be reused
by etsec code.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 arch/powerpc/include/asm/fsl_enet.h |   10 +
 drivers/net/fsl_phy.c               |  353 +++++++++++++++++++++++++++++++++++
 drivers/net/fsl_phy.h               |  176 +++++++++++++++++
 3 files changed, 539 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fsl_phy.c
 create mode 100644 drivers/net/fsl_phy.h

diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h
index 4fb2857..9475249 100644
--- a/arch/powerpc/include/asm/fsl_enet.h
+++ b/arch/powerpc/include/asm/fsl_enet.h
@@ -28,6 +28,16 @@ enum fsl_phy_enet_if {
 	FSL_ETH_IF_NONE,
 };
 
+typedef struct tsec_mii_mng {
+	u32 miimcfg;		/* MII management configuration reg */
+	u32 miimcom;		/* MII management command reg */
+	u32 miimadd;		/* MII management address reg */
+	u32 miimcon;		/* MII management control reg */
+	u32 miimstat;		/* MII management status reg  */
+	u32 miimind;		/* MII management indication reg */
+	u32 ifstat;		/* Interface Status Register */
+} __attribute__ ((packed))tsec_mii_t;
+
 int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc);
 
 #endif /* __ASM_PPC_FSL_ENET_H */
diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
new file mode 100644
index 0000000..1ba0ce1
--- /dev/null
+++ b/drivers/net/fsl_phy.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@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 <asm/errno.h>
+
+#include "fsl_phy.h"
+
+void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr,
+		int dev_addr, int regnum, int value)
+{
+	int timeout = 1000000;
+
+	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
+	out_be32(&phyregs->miimcon, value);
+	asm("sync");
+
+	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--);
+}
+
+int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr,
+		int dev_addr, int regnum)
+{
+	int value;
+	int timeout = 1000000;
+
+	/* Put the address of the phy, and the register
+	 * number into MIIMADD */
+	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
+
+	/* Clear the command register, and wait */
+	out_be32(&phyregs->miimcom, 0);
+	asm("sync");
+
+	/* Initiate a read command, and wait */
+	out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE);
+	asm("sync");
+
+	/* Wait for the the indication that the read is done */
+	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+			&& timeout--);
+
+	/* Grab the value read from the PHY */
+	value = in_be32(&phyregs->miimstat);
+
+	return value;
+}
+
+int tsec_phy_read(struct mii_info *mii_info, int dev_addr, int regnum)
+{
+	tsec_mii_t *phyregs = mii_info->phyregs;
+
+	return tsec_local_mdio_read(phyregs, mii_info->mii_id, dev_addr,
+			regnum);
+}
+
+int tsec_phy_write(struct mii_info *mii_info, int dev_addr, int regnum,
+			int value)
+{
+	tsec_mii_t *phyregs = mii_info->phyregs;
+
+	tsec_local_mdio_write(phyregs, mii_info->mii_id, dev_addr, regnum,
+		value);
+
+	return 0;
+}
+
+static int genphy_config(struct mii_info *mii_info)
+{
+	return tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+}
+
+/**
+ * genphy_update_link - update link status in @phydev
+ * @phydev: target phy_device struct
+ *
+ * Description: Update the value in phydev->link to reflect the
+ *   current link value.  In order to do this, we need to read
+ *   the status register twice, keeping the second value.
+ */
+static int genphy_update_link(struct mii_info *phydev)
+{
+	unsigned int mii_reg;
+
+	/*
+	 * Wait if the link is up, and autonegotiation is in progress
+	 * (ie - we're capable and it's not done)
+	 */
+	mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
+
+	/*
+	 * If we already saw the link up, and it hasn't gone down, then
+	 * we don't need to wait for autoneg again
+	 */
+	if (phydev->link && mii_reg & BMSR_LSTATUS)
+		return 0;
+
+	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
+		int i = 0;
+
+		printf("%s Waiting for PHY auto negotiation to complete",
+			phydev->dev->name);
+		while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
+			/*
+			 * Timeout reached ?
+			 */
+			if (i > 5000) {
+				printf(" TIMEOUT !\n");
+				phydev->link = 0;
+				return 0;
+			}
+
+			if (ctrlc()) {
+				puts("user interrupt!\n");
+				phydev->link = 0;
+				return -EINTR;
+			}
+
+			if ((i++ % 500) == 0)
+				printf(".");
+
+			udelay(1000);	/* 1 ms */
+			mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
+		}
+		printf(" done\n");
+		phydev->link = 1;
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		/* Read the link a second time to clear the latched state */
+		mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
+
+		if (mii_reg & BMSR_LSTATUS)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Generic function which updates the speed and duplex.  If
+ * autonegotiation is enabled, it uses the AND of the link
+ * partner's advertised capabilities and our advertised
+ * capabilities.  If autonegotiation is disabled, we use the
+ * appropriate bits in the control register.
+ *
+ * Stolen from Linux's mii.c and phy_device.c
+ */
+static int genphy_parse_link(struct mii_info *phydev)
+{
+	int mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
+
+	/* We're using autonegotiation */
+	if (mii_reg & BMSR_ANEGCAPABLE) {
+		u32 lpa = 0;
+		u32 gblpa = 0;
+
+		/* Check for gigabit capability */
+		if (mii_reg & BMSR_ERCAP) {
+			/* We want a list of states supported by
+			 * both PHYs in the link
+			 */
+			gblpa = tsec_phy_read(phydev, 0, MII_STAT1000);
+			gblpa &= tsec_phy_read(phydev, 0, MII_CTRL1000) << 2;
+		}
+
+		/* Set the baseline so we only have to set them
+		 * if they're different
+		 */
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+
+		/* Check the gigabit fields */
+		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
+			phydev->speed = SPEED_1000;
+
+			if (gblpa & PHY_1000BTSR_1000FD)
+				phydev->duplex = DUPLEX_FULL;
+
+			/* We're done! */
+			return 0;
+		}
+
+		lpa = tsec_phy_read(phydev, 0, MII_ADVERTISE);
+		lpa &= tsec_phy_read(phydev, 0, MII_LPA);
+
+		if (lpa & (LPA_100FULL | LPA_100HALF)) {
+			phydev->speed = SPEED_100;
+
+			if (lpa & LPA_100FULL)
+				phydev->duplex = DUPLEX_FULL;
+
+		} else if (lpa & LPA_10FULL)
+			phydev->duplex = DUPLEX_FULL;
+	} else {
+		u32 bmcr = tsec_phy_read(phydev, 0, MII_BMCR);
+
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+
+		if (bmcr & BMCR_FULLDPLX)
+			phydev->duplex = DUPLEX_FULL;
+
+		if (bmcr & BMCR_SPEED1000)
+			phydev->speed = SPEED_1000;
+		else if (bmcr & BMCR_SPEED100)
+			phydev->speed = SPEED_100;
+	}
+
+	return 0;
+}
+
+static int genphy_startup(struct mii_info *phydev)
+{
+	genphy_update_link(phydev);
+	genphy_parse_link(phydev);
+
+	return 0;
+}
+
+static int genphy_shutdown(struct mii_info *phydev)
+{
+	return 0;
+}
+
+/* Vitesse VSC8244 */
+static int vsc8244_parse_status(struct mii_info *mii_info)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_VSC8244_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_VSC8244_AUXCONSTAT_GBIT:
+		mii_info->speed = SPEED_1000;
+		break;
+	case MIIM_VSC8244_AUXCONSTAT_100:
+		mii_info->speed = SPEED_100;
+		break;
+	default:
+		mii_info->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vsc8244_startup(struct mii_info *mii_info)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(mii_info);
+	vsc8244_parse_status(mii_info);
+
+	return 0;
+}
+
+static struct phy_info phy_info_VSC8244 = {
+	"Vitesse VSC8244",
+	0xfc6c0,
+	0xffff0,
+	&genphy_config,
+	&vsc8244_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_VSC8234 = {
+	"Vitesse VSC8234",
+	0xfc620,
+	0xffff0,
+	&genphy_config,
+	&vsc8244_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_generic = {
+	"Unknown/Generic PHY",
+	0x0,
+	0x0,
+	&genphy_config,
+	&genphy_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info *phy_info[] = {
+	&phy_info_VSC8244,
+	&phy_info_VSC8234,
+	&phy_info_generic
+};
+
+/*
+ * Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev.  return a struct phy_info structure describing that PHY
+ */
+struct phy_info *tsec_get_phy_info(struct mii_info *mii_info)
+{
+	u16 phy_reg;
+	u32 phy_ID;
+	int i;
+	struct phy_info *theInfo = NULL;
+
+	/* Grab the bits from PHYIR1, and put them in the upper half */
+	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID1);
+	phy_ID = (phy_reg & 0xffff) << 16;
+
+	/* Grab the bits from PHYIR2, and put them in the lower half */
+	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID2);
+	phy_ID |= (phy_reg & 0xffff);
+
+	/* loop through all the known PHY types, and find one that */
+	/* matches the ID we read from the PHY. */
+	for (i = 0; i < ARRAY_SIZE(phy_info); i++)
+		if ((phy_info[i]->uid & phy_info[i]->mask) ==
+				(phy_ID & phy_info[i]->mask)) {
+			theInfo = phy_info[i];
+			break;
+		}
+
+	if (theInfo == &phy_info_generic) {
+		printf("%s: No support for PHY id %x; assuming generic\n",
+				mii_info->dev->name, phy_ID);
+	} else {
+		printf("%s: PHY is %s (%x)\n", mii_info->dev->name,
+				theInfo->name, phy_ID);
+	}
+
+	return theInfo;
+}
diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
new file mode 100644
index 0000000..8a8b6e8
--- /dev/null
+++ b/drivers/net/fsl_phy.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@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 __FSL_PHY_H__
+#define __FSL_PHY_H__
+
+#include <net.h>
+#include <miiphy.h>
+#include <asm/fsl_enet.h>
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF		0x00
+#define DUPLEX_FULL		0x01
+
+#define PORT_TP		0x00
+#define PORT_AUI	0x01
+#define PORT_MII	0x02
+#define PORT_FIBRE	0x03
+
+#define MII_BMCR_INIT           0x00001140
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT          0x80000000
+#define MIIMCFG_MGMT_CLOCK_SELECT   0x00000007
+#define MIIMCFG_INIT_VALUE	    0x00000003
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_CYCLE	0x00000001
+#define MIIMCOM_SCAN_CYCLE	0x00000002
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT	8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY		0x00000001
+#define MIIMIND_NOTVALID	0x00000004
+
+#define AUTONEG_DISABLE		0x00
+#define AUTONEG_ENABLE		0x01
+#define SPEED_10		10
+#define SPEED_100		100
+#define SPEED_1000		1000
+#define SPEED_2500		2500
+#define SPEED_10000		10000
+#define SUPPORTED_10baseT_Half		(1 << 0)
+#define SUPPORTED_10baseT_Full		(1 << 1)
+#define SUPPORTED_100baseT_Half		(1 << 2)
+#define SUPPORTED_100baseT_Full		(1 << 3)
+#define SUPPORTED_1000baseT_Half	(1 << 4)
+#define SUPPORTED_1000baseT_Full	(1 << 5)
+#define SUPPORTED_Autoneg		(1 << 6)
+#define SUPPORTED_TP			(1 << 7)
+#define SUPPORTED_AUI			(1 << 8)
+#define SUPPORTED_MII			(1 << 9)
+#define SUPPORTED_FIBRE			(1 << 10)
+#define SUPPORTED_BNC			(1 << 11)
+#define SUPPORTED_10000baseT_Full	(1 << 12)
+#define SUPPORTED_Pause			(1 << 13)
+#define SUPPORTED_Asym_Pause		(1 << 14)
+#define SUPPORTED_2500baseX_Full	(1 << 15)
+
+/* Indicates what features are advertised by the interface. */
+#define ADVERTISED_10baseT_Half		(1 << 0)
+#define ADVERTISED_10baseT_Full		(1 << 1)
+#define ADVERTISED_100baseT_Half	(1 << 2)
+#define ADVERTISED_100baseT_Full	(1 << 3)
+#define ADVERTISED_1000baseT_Half	(1 << 4)
+#define ADVERTISED_1000baseT_Full	(1 << 5)
+#define ADVERTISED_Autoneg		(1 << 6)
+#define ADVERTISED_TP			(1 << 7)
+#define ADVERTISED_AUI			(1 << 8)
+#define ADVERTISED_MII			(1 << 9)
+#define ADVERTISED_FIBRE		(1 << 10)
+#define ADVERTISED_BNC			(1 << 11)
+#define ADVERTISED_10000baseT_Full	(1 << 12)
+#define ADVERTISED_Pause		(1 << 13)
+#define ADVERTISED_Asym_Pause		(1 << 14)
+#define ADVERTISED_2500baseX_Full	(1 << 15)
+
+#define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
+
+/* Entry for Vitesse VSC8244 regs starts here */
+/* Vitesse VSC8244 Auxiliary Control/Status Register */
+#define MIIM_VSC8244_AUX_CONSTAT	0x1c
+#define MIIM_VSC8244_AUXCONSTAT_INIT	0x0000
+#define MIIM_VSC8244_AUXCONSTAT_DUPLEX	0x0020
+#define MIIM_VSC8244_AUXCONSTAT_SPEED	0x0018
+#define MIIM_VSC8244_AUXCONSTAT_GBIT	0x0010
+#define MIIM_VSC8244_AUXCONSTAT_100	0x0008
+#define MIIM_CONTROL_INIT_LOOPBACK	0x4000
+
+struct mii_info {
+	/* Information about the PHY type */
+	/* And management functions */
+	struct phy_info *phyinfo;
+	void *phyregs;
+
+	struct eth_device *dev;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int speed;
+	int duplex;
+
+	/* The most recently read link state */
+	int link;
+	int port;
+
+	u32 advertising;
+	int autoneg;
+	int mii_id;
+	u32 flags;
+
+	/* private data pointer */
+	/* For use by PHYs to maintain extra state */
+	void *priv;
+
+	/* Provided by ethernet driver */
+	int (*mdio_read)(struct eth_device *dev, int mii_id, int reg);
+	void (*mdio_write)(struct eth_device *dev, int mii_id, int reg,
+			    int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be masked to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ */
+struct phy_info {
+	char *name;
+	unsigned int uid;
+	unsigned int mask;
+	/* Called to configure the PHY, and modify the controller
+	 * based on the results */
+	int (*config)(struct mii_info *mii_info);
+
+	/* Called when starting up the controller */
+	int (*startup)(struct mii_info *mii_info);
+
+	/* Called when bringing down the controller */
+	int (*shutdown)(struct mii_info *mii_info);
+};
+
+struct phy_info *tsec_get_phy_info(struct mii_info *mii_info);
+void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr, int dev_addr,
+		int reg, int value);
+int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr, int dev_addr,
+		int regnum);
+int tsec_phy_read(struct mii_info *mii_info, int dev_addr, int regnum);
+int tsec_phy_write(struct mii_info *mii_info, int dev_addr, int regnum,
+		int value);
+#endif /* __FSL_PHY_H__ */
+
-- 
1.6.4

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

* [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support
  2011-01-27  4:52   ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Mingkai Hu
@ 2011-01-27  4:52     ` Mingkai Hu
  2011-01-27  4:52       ` [U-Boot] [PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support Mingkai Hu
  2011-01-27  6:15     ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Kumar Gala
  2011-01-27 16:10     ` Timur Tabi
  2 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Kumar Gala <galak@kernel.crashing.org>

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 arch/powerpc/include/asm/fsl_enet.h |   12 ++
 drivers/net/fm/dtsec.c              |  168 +++++++++++++++++++++++
 drivers/net/fm/dtsec.h              |  251 +++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fm/dtsec.c
 create mode 100644 drivers/net/fm/dtsec.h

diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h
index 9475249..f94482d 100644
--- a/arch/powerpc/include/asm/fsl_enet.h
+++ b/arch/powerpc/include/asm/fsl_enet.h
@@ -38,6 +38,18 @@ typedef struct tsec_mii_mng {
 	u32 ifstat;		/* Interface Status Register */
 } __attribute__ ((packed))tsec_mii_t;
 
+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, enum fsl_phy_enet_if type,
+				int speed);
+};
+
 int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc);
 
 #endif /* __ASM_PPC_FSL_ENET_H */
diff --git a/drivers/net/fm/dtsec.c b/drivers/net/fm/dtsec.c
new file mode 100644
index 0000000..7c28217
--- /dev/null
+++ b/drivers/net/fm/dtsec.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+
+#include "dtsec.h"
+#include "../fsl_phy.h"
+
+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);
+
+	/* 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, enum fsl_phy_enet_if 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 GMII:
+		ecntrl |= ECNTRL_GMIIM;
+		break;
+	case RGMII:
+		ecntrl |= (ECNTRL_GMIIM | ECNTRL_RPM);
+		if (speed == SPEED_100)
+			ecntrl |= ECNTRL_R100M;
+		break;
+	case RMII:
+		if (speed == SPEED_100)
+			ecntrl |= ECNTRL_R100M;
+		break;
+	case 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 = phyregs;
+	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/dtsec.h b/drivers/net/fm/dtsec.h
new file mode 100644
index 0000000..64339e0
--- /dev/null
+++ b/drivers/net/fm/dtsec.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 __DTSEC_H__
+#define __DTSEC_H__
+
+#include <asm/types.h>
+#include <asm/fsl_enet.h>
+
+/* 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 read-only */
+#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_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	0x0000002a
+
+/* 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 */
+
+#define TCTRL_INIT	TCTRL_GTS
+
+/* 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 */
+
+#define RCTRL_INIT	(RCTRL_GRS | RCTRL_UPROM)
+
+/* 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)
+#define MACCFG1_INIT		MACCFG1_SOFT_RST
+
+/* MACCFG2 - MAC configuration 2 register */
+#define MACCFG2_PRE_LEN		0x0000f000 /* preamble length */
+#define MACCFG2_IF_MODE_MASK	0x00000300 /* 01 - Nibble mode, MII, 10/100 Mbps MII/RMII
+					      10 - Byte mode, GMII/TBI, 1000 GMII/TBI */
+#define MACCFG2_IF_MODE_NIBBLE	0x00000100
+#define MACCFG2_IF_MODE_BYTE	0x00000200
+#define MACCFG2_PRE_RX_EN	0x00000080 /* receive preamble enable */
+#define MACCFG2_PRE_TX_EN	0x00000040 /* enable user defined preamble for Tx */
+#define MACCFG2_HUGE_FRAME	0x00000020 /* huge frame enable (eq/gt maximum frame length) */
+#define MACCFG2_LEN_CHECK	0x00000010 /* MAC check frame's length field on Rx */
+#define MACCFG2_MAG_EN		0x00000008 /* magic packet enable */
+#define MACCFG2_PAD_CRC		0x00000004 /* pad and append CRC for transmitted short frame */
+#define MACCFG2_CRC_EN		0x00000002 /* MAC appends a CRC on all frames */
+#define MACCFG2_FULL_DUPLEX	0x00000001 /* The MAC operates in full deplex mode */
+
+#define MACCFG2_DEFAULT		0x00007000
+#define MACCFG2_INIT		(MACCFG2_DEFAULT | MACCFG2_LEN_CHECK | MACCFG2_PAD_CRC \
+				| MACCFG2_FULL_DUPLEX | MACCFG2_IF_MODE_NIBBLE)
+
+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];
+} __attribute__ ((packed));
+
+void init_dtsec(struct fsl_enet_mac *mac, void *base, void *phyregs, int max_rx_len);
+
+#endif
-- 
1.6.4

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

* [U-Boot] [PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support
  2011-01-27  4:52     ` [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support Mingkai Hu
@ 2011-01-27  4:52       ` Mingkai Hu
  2011-01-27  4:52         ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Mingkai Hu
  0 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Kumar Gala <galak@kernel.crashing.org>

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/fm/tgec.c     |  104 ++++++++++++++++++++
 drivers/net/fm/tgec.h     |  230 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fm/tgec_phy.c |  155 ++++++++++++++++++++++++++++++
 3 files changed, 489 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fm/tgec.c
 create mode 100644 drivers/net/fm/tgec.h
 create mode 100644 drivers/net/fm/tgec_phy.c

diff --git a/drivers/net/fm/tgec.c b/drivers/net/fm/tgec.c
new file mode 100644
index 0000000..02a2476
--- /dev/null
+++ b/drivers/net/fm/tgec.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+
+#include "tgec.h"
+
+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);
+
+	/* 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,
+					enum fsl_phy_enet_if 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.h b/drivers/net/fm/tgec.h
new file mode 100644
index 0000000..8d64db2
--- /dev/null
+++ b/drivers/net/fm/tgec.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 "../fsl_phy.h"
+
+/* 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 address with second */
+#define TGEC_CMD_CFG_NO_LEN_CHK		0x00020000 /* payload length check disable */
+#define TGEC_CMD_CFG_SEND_IDLE		0x00010000 /* send XGMII idle sequences */
+#define TGEC_CMD_CFG_RX_ER_DISC		0x00004000 /* enable receive error frame discard */
+#define TGEC_CMD_CFG_CMD_FRM_EN		0x00002000 /* all command frames are accepted */
+#define TGEC_CMD_CFG_STAT_CLR		0x00001000 /* all statistics counters are cleared */
+#define TGEC_CMD_CFG_TX_ADDR_INS	0x00000200 /* overwrite the souce MAC address */
+#define TGEC_CMD_CFG_PAUSE_IGNORE	0x00000100 /* ignores received pause frames */
+#define TGEC_CMD_CFG_PAUSE_FWD		0x00000080 /* forwards pause frames to the user app */
+#define TGEC_CMD_CFG_CRC_FWD		0x00000040 /* MAC forward Rx CRC to user */
+#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 receive path enable */
+#define TGEC_CMD_CFG_TX_EN		0x00000001 /* MAC transmit path enable */
+
+#define TGEC_CMD_CFG_RXTX_EN		(TGEC_CMD_CFG_RX_EN | TGEC_CMD_CFG_TX_EN)
+
+#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)
+/* 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 {
+	/* 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 second 48-bit MAC address */
+	u32	mac_addr_3;	/* Upper 16 bits of the second 48-bit MAC address */
+	u32	res3[4];
+	u32	imask;		/* Interrupt mask register */
+	u32	ievent;		/* Interrupt event register */
+	u32	res4[6];
+	/* 10GEC statistics counter registers */
+	u32	tx_frame_u;	/* Transmit frame counter upper */
+	u32	tx_frame_l;	/* Transmit frame counter lower */
+	u32	rx_frame_u;	/* Receive frame counter upper */
+	u32	rx_frame_l;	/* Receive frame counter lower */
+	u32	rx_frame_crc_err_u;	/* Receive frame check sequence error upper */
+	u32	rx_frame_crc_err_l;	/* Receive frame check sequence error lower */
+	u32	rx_align_err_u;	/* Receive alignment error upper */
+	u32	rx_align_err_l;	/* Receive alignment error lower */
+	u32	tx_pause_frame_u;	/* Transmit valid pause frame upper */
+	u32	tx_pause_frame_l;	/* Transmit valid pause frame lower */
+	u32	rx_pause_frame_u;	/* Receive valid pause frame upper */
+	u32	rx_pause_frame_l;	/* Receive valid pause frame upper */
+	u32	rx_long_err_u;	/* Receive too long frame error upper */
+	u32	rx_long_err_l;	/* Receive too long frame error lower */
+	u32	rx_frame_err_u;	/* Receive frame length error upper */
+	u32	rx_frame_err_l;	/* Receive frame length error lower */
+	u32	tx_vlan_u;	/* Transmit VLAN frame upper */
+	u32	tx_vlan_l;	/* Transmit VLAN frame lower */
+	u32	rx_vlan_u;	/* Receive VLAN frame upper */
+	u32	rx_vlan_l;	/* Receive VLAN frame lower */
+	u32	tx_oct_u;	/* Transmit octets upper */
+	u32	tx_oct_l;	/* Transmit octets lower */
+	u32	rx_oct_u;	/* Receive octets upper */
+	u32	rx_oct_l;	/* Receive octets lower */
+	u32	rx_uni_u;	/* Receive unicast frame upper */
+	u32	rx_uni_l;	/* Receive unicast frame lower */
+	u32	rx_multi_u;	/* Receive multicast frame upper */
+	u32	rx_multi_l;	/* Receive multicast frame lower */
+	u32	rx_brd_u;	/* Receive broadcast frame upper */
+	u32	rx_brd_l;	/* Receive broadcast frame lower */
+	u32	tx_frame_err_u;	/* Transmit frame error upper */
+	u32	tx_frame_err_l;	/* Transmit frame error lower */
+	u32	tx_uni_u;	/* Transmit unicast frame upper */
+	u32	tx_uni_l;	/* Transmit unicast frame lower */
+	u32	tx_multi_u;	/* Transmit multicast frame upper */
+	u32	tx_multi_l;	/* Transmit multicast frame lower */
+	u32	tx_brd_u;	/* Transmit broadcast frame upper */
+	u32	tx_brd_l;	/* Transmit broadcast frame lower */
+	u32	rx_drop_u;	/* Receive dropped packets upper */
+	u32	rx_drop_l;	/* Receive dropped packets lower */
+	u32	rx_eoct_u;	/* Receive ethernet octets upper */
+	u32	rx_eoct_l;	/* Receive ethernet octets lower */
+	u32	rx_pkt_u;	/* Receive packets upper */
+	u32	rx_pkt_l;	/* Receive packets lower */
+	u32	tx_undsz_u;	/* Undersized packet upper */
+	u32	tx_undsz_l;	/* Undersized packet lower */
+	u32	rx_64_u;	/* Receive 64 oct packet upper */
+	u32	rx_64_l;	/* Receive 64 oct packet lower */
+	u32	rx_127_u;	/* Receive 65 to 127 oct packet upper */
+	u32	rx_127_l;	/* Receive 65 to 127 oct packet lower */
+	u32	rx_255_u;	/* Receive 128 to 255 oct packet upper */
+	u32	rx_255_l;	/* Receive 128 to 255 oct packet lower */
+	u32	rx_511_u;	/* Receive 256 to 511 oct packet upper */
+	u32	rx_511_l;	/* Receive 256 to 511 oct packet lower */
+	u32	rx_1023_u;	/* Receive 512 to 1023 oct packet upper */
+	u32	rx_1023_l;	/* Receive 512 to 1023 oct packet lower */
+	u32	rx_1518_u;	/* Receive 1024 to 1518 oct packet upper */
+	u32	rx_1518_l;	/* Receive 1024 to 1518 oct packet lower */
+	u32	rx_1519_u;	/* Receive 1519 to max oct packet upper */
+	u32	rx_1519_l;	/* Receive 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;	/* Receive frame error upper */
+	u32	rx_err_l;	/* Receive frame error lower */
+	u32	res5[0x39a];
+} __attribute__ ((packed));
+
+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 */
+} __attribute__ ((packed));
+
+#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)
+
+void init_tgec(struct fsl_enet_mac *mac, void *base, void *phyregs, int max_rx_len);
+struct phy_info *tgec_get_phy_info(struct mii_info *mii_info);
+
+#endif
diff --git a/drivers/net/fm/tgec_phy.c b/drivers/net/fm/tgec_phy.c
new file mode 100644
index 0000000..cf95e02
--- /dev/null
+++ b/drivers/net/fm/tgec_phy.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Andy Fleming <afleming@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 <asm/io.h>
+
+#include "../fsl_phy.h"
+#include "tgec.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_write_phy_reg(struct tgec_mdio_controller *regs, int port_addr,
+			int dev_addr, int regnum, int value)
+{
+	u32 mdio_ctl;
+	u32 stat_val;
+
+	/* 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_read_phy_reg(struct tgec_mdio_controller *regs, int port_addr,
+	int dev_addr, int regnum)
+{
+	u32 mdio_ctl;
+	u32 stat_val;
+
+	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 in_be32(&regs->mdio_data) & 0xffff;
+}
+
+int tgec_phy_write(struct mii_info *mii_info, int dev_addr, int regnum,
+		int value)
+{
+	struct tgec_mdio_controller *regs = mii_info->phyregs;
+
+	return tgec_write_phy_reg(regs, mii_info->mii_id, dev_addr, regnum,
+			value);
+}
+
+int tgec_phy_read(struct mii_info *mii_info, int dev_addr, int regnum)
+{
+	struct tgec_mdio_controller *regs = mii_info->phyregs;
+
+	return tgec_read_phy_reg(regs, mii_info->mii_id, dev_addr, regnum);
+}
+
+/* For now, just assume 10G, and use AN as basis for link state */
+int tgec_shutdown_phy(struct mii_info *mii_info)
+{
+	return 0;
+}
+int tgec_startup_phy(struct mii_info *mii_info)
+{
+	mii_info->link = 1;
+	mii_info->speed = 1000;
+	mii_info->duplex = 1;
+	return 0;
+}
+
+int tgec_config_phy(struct mii_info *mii_info)
+{
+	return 0;
+}
+
+int tn2020_config_phy(struct mii_info *mii_info)
+{
+	if (mii_info->port == PORT_FIBRE) {
+		tgec_phy_write(mii_info, 30, 93, 2);
+		tgec_phy_write(mii_info, 7, 0, 0x3200);
+	}
+
+	return 0;
+}
+
+/* Giant hack. */
+struct phy_info phy_info_tgec = {
+	"Teranetics TN2020",
+	0xf00,
+	0xf00,
+	&tn2020_config_phy,
+	&tgec_startup_phy,
+	&tgec_shutdown_phy,
+};
+
+struct phy_info *tgec_phy_info[] = {
+	&phy_info_tgec,
+};
+
+struct phy_info *tgec_get_phy_info(struct mii_info *mii_info)
+{
+	return &phy_info_tgec;
+}
-- 
1.6.4

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

* [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode
  2011-01-27  4:52       ` [U-Boot] [PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support Mingkai Hu
@ 2011-01-27  4:52         ` Mingkai Hu
  2011-01-27  4:52           ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Mingkai Hu
  2011-01-27 17:40           ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Timur Tabi
  0 siblings, 2 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Dave Liu <daveliu@freescale.com>

Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Signed-off-by: Dai Haruki <dai.haruki@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 Makefile                            |    1 +
 arch/powerpc/cpu/mpc85xx/cpu_init.c |    5 +
 arch/powerpc/cpu/mpc8xxx/cpu.c      |    4 +
 drivers/net/Makefile                |    1 +
 drivers/net/fm/Makefile             |   45 ++
 drivers/net/fm/fm.c                 |  519 +++++++++++++++
 drivers/net/fm/fm.h                 |  312 +++++++++
 drivers/net/fm/fm_eth.c             | 1234 +++++++++++++++++++++++++++++++++++
 include/fm_eth.h                    |  348 ++++++++++
 9 files changed, 2469 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fm/Makefile
 create mode 100644 drivers/net/fm/fm.c
 create mode 100644 drivers/net/fm/fm.h
 create mode 100644 drivers/net/fm/fm_eth.c
 create mode 100644 include/fm_eth.h

diff --git a/Makefile b/Makefile
index 5f93646..a0532e0 100644
--- a/Makefile
+++ b/Makefile
@@ -225,6 +225,7 @@ LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
 endif
 ifeq ($(CPU),mpc85xx)
 LIBS += drivers/qe/libqe.o
+LIBS += drivers/net/fm/libfm.a
 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 8ece970..0ceec19 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>
@@ -419,6 +420,10 @@ int cpu_init_r(void)
 	isync();
 #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 4335fb4..97e4fa4 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>
@@ -160,5 +161,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/drivers/net/Makefile b/drivers/net/Makefile
index fd9d0b4..3810665 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
+COBJS-$(CONFIG_FMAN_ENET) += fsl_phy.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..0dc99ca
--- /dev/null
+++ b/drivers/net/fm/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright 2009-2010 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.a
+
+COBJS-$(CONFIG_FMAN_ENET) += dtsec.o fm.o fm_eth.o tgec.o tgec_phy.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+CFLAGS	:= $(CFLAGS) -D__GCC__
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
new file mode 100644
index 0000000..ecc4ffc
--- /dev/null
+++ b/drivers/net/fm/fm.c
@@ -0,0 +1,519 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 */
+
+struct fm_global *fman[MAX_NUM_FM];
+
+u32 fm_get_base_addr(int fm, enum fm_block block, int port)
+{
+	u32 addr = 0;
+
+	if (fm == 0)
+		addr = CONFIG_SYS_FSL_FM1_ADDR;
+	else if (fm == 1)
+		addr = CONFIG_SYS_FSL_FM2_ADDR;
+
+	switch (block) {
+	case fm_muram_e: /* muram */
+		addr += 0;
+		break;
+	case fm_bmi_e:
+		addr += 0x80000 + port * 0x1000;
+		break;
+	case fm_qmi_e:
+		addr += 0x80400 + port * 0x1000;
+		break;
+	case fm_parser_e:
+		addr += 0x80800 + port * 0x1000;
+		break;
+	case fm_policer_e:
+		addr += 0xc0000;
+		break;
+	case fm_keygen_e:
+		addr += 0xc1000;
+		break;
+	case fm_dma_e:
+		addr += 0xc2000;
+		break;
+	case fm_fpm_e:
+		addr += 0xc3000;
+		break;
+	case fm_imem_e:
+		addr += 0xc4000;
+		break;
+	case fm_soft_paser_e:
+		addr += 0xc7000;
+		break;
+	case fm_mac_e:
+		addr += port < MAX_NUM_1G_MAC ? (0xe0000 + port * 0x2000)
+			: 0xf0000;
+		break;
+	case fm_mdio_e:
+		addr += port < MAX_NUM_1G_MAC ? (0xe1120 + port * 0x2000)
+			: 0xf1000;
+		break;
+	case fm_1588_tmr_e:
+		addr += 0xfe000;
+		break;
+	}
+	return addr;
+}
+
+int fm_get_port_id(enum fm_port_type type, int num)
+{
+	int port_id, base;
+
+	switch (type) {
+	case fm_port_type_oh_e:
+		base = OH_PORT_ID_BASE;
+		break;
+	case fm_port_type_rx_e:
+		base = RX_PORT_1G_BASE;
+		break;
+	case fm_port_type_rx_10g_e:
+		base = RX_PORT_10G_BASE;
+		break;
+	case fm_port_type_tx_e:
+		base = TX_PORT_1G_BASE;
+		break;
+	case fm_port_type_tx_10g_e:
+		base = TX_PORT_10G_BASE;
+		break;
+	default:
+		base = 0;
+		break;
+	}
+
+	port_id = base + num;
+	return port_id;
+}
+
+/** 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, u32 *ucode, unsigned int size)
+{
+	struct fm_iram *iram;
+	unsigned int i;
+	unsigned int timeout = 1000000;
+
+	iram = (struct fm_iram *)fm_get_base_addr(fm, fm_imem_e, 0);
+	/* enable address auto increase */
+	out_be32(&iram->iadd, IRAM_IADD_AIE);
+	/* write microcode to IRAM */
+	for (i = 0; i < size / 4; i++)
+		out_be32(&iram->idata, ucode[i]);
+
+	/* verify if the writing is over */
+	out_be32(&iram->iadd, 0);
+	while ((in_be32(&iram->idata) != ucode[0]) && --timeout);
+
+	/* enable microcode from IRAM */
+	out_be32(&iram->iready, IRAM_READY);
+}
+
+static void fm_init_axi_dma(int fm)
+{
+	struct fm_dma *axi_dma;
+	u32 val;
+
+	axi_dma = (struct fm_dma *)fm_get_base_addr(fm, fm_dma_e, 0);
+	/* clear DMA status */
+	val = in_be32(&axi_dma->fmdmsr);
+	out_be32(&axi_dma->fmdmsr, val | FMDMSR_CLEAR_ALL);
+	/* set DMA mode */
+	val = in_be32(&axi_dma->fmdmmr);
+	out_be32(&axi_dma->fmdmmr, val | FMDMMR_INIT);
+	/* set thresholds - high */
+	out_be32(&axi_dma->fmdmtr, FMDMTR_DEFAULT);
+	/* set hysteresis - low */
+	out_be32(&axi_dma->fmdmhy, FMDMHY_DEFAULT);
+	/* set emergency threshold */
+	out_be32(&axi_dma->fmdmsetr, FMDMSETR_DEFAULT);
+}
+
+u32 fm_muram_alloc(struct fm_muram *mem, u32 size, u32 align)
+{
+	u32 ret;
+	u32 align_mask, off;
+	u32 save;
+
+	align_mask = align - 1;
+	save = mem->alloc;
+
+	if ((off = (save & align_mask)) != 0)
+		mem->alloc += (align - off);
+	if ((off = size & align_mask) != 0)
+		size += (align - off);
+	if ((mem->alloc + size) >= mem->top) {
+		mem->alloc = save;
+		printf("%s: run out of ram.\n", __func__);
+	}
+
+	ret = mem->alloc;
+	mem->alloc += size;
+	memset((void *)ret, 0, size);
+
+	return ret;
+}
+
+static void fm_init_muram(int fm, struct fm_muram *mem)
+{
+	u32 base;
+
+	base = fm_get_base_addr(fm, fm_muram_e, 0);
+	mem->fm = fm;
+	mem->base = base;
+	mem->res_size = FM_MURAM_RES_SIZE;
+	mem->size = FM_MURAM_SIZE;
+	mem->alloc = base + FM_MURAM_RES_SIZE;
+	mem->top = base + FM_MURAM_SIZE;
+}
+
+static void fm_reset(int) __attribute__((__unused__));
+static void fm_reset(int fm)
+{
+	struct fm_fpm *fpm;
+	fpm = (struct fm_fpm *)fm_get_base_addr(fm, fm_fpm_e, 0);
+
+	/* reset entire FMAN and MACs */
+	out_be32(&fpm->fmrstc, FMRSTC_RESET_FMAN);
+	udelay(10);
+}
+
+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(int fm)
+{
+	struct fm_fpm *fpm;
+	int i, port_id;
+	u32 val;
+
+	fpm = (struct fm_fpm *)fm_get_base_addr(fm, fm_fpm_e, 0);
+
+	val = in_be32(&fpm->fmnee);
+	out_be32(&fpm->fmnee, val | 0x0000000f);
+
+	/* 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 = fm_get_port_id(fm_port_type_oh_e, 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 = fm_get_port_id(fm_port_type_rx_e, 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 = fm_get_port_id(fm_port_type_tx_e, i);
+		val = fm_assign_risc(port_id);
+		out_be32(&fpm->fpmprc, val);
+	}
+	/* Rx 10G port */
+	port_id = fm_get_port_id(fm_port_type_rx_10g_e, 0);
+	val = fm_assign_risc(port_id);
+	out_be32(&fpm->fpmprc, val);
+	/* Tx 10G port */
+	port_id = fm_get_port_id(fm_port_type_tx_10g_e, 0);
+	val = fm_assign_risc(port_id);
+	out_be32(&fpm->fpmprc, val);
+
+	/* disable the dispatch limit in IM case */
+	out_be32(&fpm->fpmflc, FMFPFLC_DEFAULT);
+	/* set the dispatch thresholds */
+	out_be32(&fpm->fpmdis1, FMFPDIST1_DEFAULT);
+	out_be32(&fpm->fpmdis2, FMFPDIST2_DEFAULT);
+	/* clear events */
+	out_be32(&fpm->fmnee, FMFPEE_CLEAR_EVENT);
+
+	/* clear risc events */
+	for (i = 0; i < 4; i++)
+		out_be32(&fpm->fpmcev[i], 0xffffffff);
+
+	/* clear error */
+	out_be32(&fpm->fpmrcr, 0x0000c000);
+}
+
+static void fm_init_bmi(int fm, u32 offset, u32 pool_size)
+{
+	struct fm_bmi_common *bmi;
+	int blk, i, port_id;
+	u32 val;
+
+	bmi = (struct fm_bmi_common *)fm_get_base_addr(fm, fm_bmi_e, 0);
+
+	/* Need 128KB total free buffer pool size */
+	val = offset / 256;
+	blk = 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);
+
+	/* max outstanding tasks/dma transfer = 96/24 */
+	out_be32(&bmi->fmbm_cfg2, FMBM_CFG2_INIT);
+
+	/* 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 = fm_get_port_id(fm_port_type_oh_e, i);
+		/* max tasks=1, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id - 1], 0);
+		/* port FIFO size - 256 bytes, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id - 1], 0);
+	}
+	/* Rx 1G port */
+	for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) {
+		port_id = fm_get_port_id(fm_port_type_rx_e, i);
+		/* max tasks=4, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id - 1], 0x03000000);
+		/* FIFO size - 4KB, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id - 1], 0x0000000f);
+	}
+	/* Tx 1G port FIFO size - 4KB, no extra */
+	for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) {
+		port_id = fm_get_port_id(fm_port_type_tx_e, i);
+		/* max tasks=4, max dma=1, no extra */
+		out_be32(&bmi->fmbm_pp[port_id - 1], 0x03000000);
+		/* FIFO size - 4KB, no extra */
+		out_be32(&bmi->fmbm_pfs[port_id - 1], 0x0000000f);
+	}
+	/* Rx 10G port */
+	port_id = fm_get_port_id(fm_port_type_rx_10g_e, 0);
+	/* max tasks=12, max dma=3, no extra */
+	out_be32(&bmi->fmbm_pp[port_id - 1], 0x0b000200);
+	/* FIFO size - 4KB, no extra */
+	out_be32(&bmi->fmbm_pfs[port_id - 1], 0x0000000f);
+
+	/* Tx 10G port */
+	port_id = fm_get_port_id(fm_port_type_tx_10g_e, 0);
+	/* max tasks=12, max dma=3, no extra */
+	out_be32(&bmi->fmbm_pp[port_id - 1], 0x0b000200);
+	/* FIFO size - 4KB, no extra */
+	out_be32(&bmi->fmbm_pfs[port_id - 1], 0x0000000f);
+
+	/* initialize internal buffers data base (linked list) */
+	out_be32(&bmi->fmbm_init, FMBM_INIT_START);
+}
+
+static void fm_init_qmi(int fm)
+{
+	struct fm_qmi_common *qmi;
+
+	qmi = (struct fm_qmi_common *)fm_get_base_addr(fm, fm_qmi_e, 0);
+
+	/* disable enqueue and dequeue of QMI */
+	out_be32(&qmi->fmqm_gc, FMQM_GC_INIT);
+
+	/* 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);
+}
+
+struct fm_global *fm_get_global(int index)
+{
+	return fman[index];
+}
+
+/*
+ * 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(struct fm_global *fm,
+				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:  Invalid address for firmware\n");
+		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: Data at %p is not a firmware\n", firmware);
+		return -EPERM;
+	}
+
+	/* Check the version */
+	if (hdr->version != 1) {
+		printf("Fman: Unsupported firmware version %u\n", hdr->version);
+		return -EPERM;
+	}
+
+	/* Validate some of the fields */
+	if ((firmware->count != 1)) {
+		printf("Fman: Invalid data in firmware header\n");
+		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:  Invalid length in firmware header\n");
+		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 Firmware CRC is invalid\n");
+		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) {
+			printf("Fman: Uploading microcode version %u.%u.%u.\n",
+			       ucode->major, ucode->minor, ucode->revision);
+			fm->ucode = (void *) CONFIG_SYS_FMAN_FW_ADDR +
+				ucode->code_offset;
+			fm->ucode_size = sizeof(u32) * ucode->count;
+			fm->ucode_ver = (ucode->major << 16) |
+				(ucode->major << 8) | ucode->revision;
+			fm_upload_ucode(fm->fm, fm->ucode, fm->ucode_size);
+		}
+	}
+
+	return 0;
+}
+
+/* Init common part of FM, index is fm num# like fm as above */
+int fm_init_common(int index)
+{
+	struct fm_global *fm;
+	struct fm_muram *muram;
+	u32 free_pool_offset;
+	int rc;
+
+	fm = (struct fm_global *)malloc(sizeof(struct fm_global));
+	if (!fm) {
+		printf("%s: no memory\n", __func__);
+		return -ENOMEM;
+	}
+	/* set it to global */
+	fman[index] = fm;
+	/* zero the fm_global */
+	memset(fm, 0, sizeof(struct fm_global));
+
+	/* init muram */
+	muram = &fm->muram;
+	fm_init_muram(index, muram);
+
+	/* save these information */
+	fm->fm = index;
+
+	/* Upload the Fman microcode if it's present */
+#ifdef CONFIG_SYS_FMAN_FW_ADDR
+	rc = fman_upload_firmware(fm, (void *) CONFIG_SYS_FMAN_FW_ADDR);
+	if (rc)
+		return rc;
+#endif
+
+	/* alloc free buffer pool in MURAM */
+	fm->free_pool_base = fm_muram_alloc(muram, FM_FREE_POOL_SIZE,
+				FM_FREE_POOL_ALIGN);
+	if (!fm->free_pool_base) {
+		printf("%s: no muram for free buffer pool\n", __func__);
+		return -ENOMEM;
+	}
+	free_pool_offset = fm->free_pool_base - muram->base;
+	fm->free_pool_size = FM_FREE_POOL_SIZE;
+
+	/* init qmi */
+	fm_init_qmi(index);
+	/* init fpm */
+	fm_init_fpm(index);
+	/* int axi dma */
+	fm_init_axi_dma(index);
+	/* init bmi common */
+	fm_init_bmi(index, free_pool_offset, fm->free_pool_size);
+
+	return 0;
+}
+
diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h
new file mode 100644
index 0000000..5d68a9c
--- /dev/null
+++ b/drivers/net/fm/fm.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 __FM_H__
+#define __FM_H__
+
+#include <common.h>
+#include <fm_eth.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_fman.h>
+
+#define MAX_NUM_FM		2
+#define MAX_NUM_1G_MAC		5 /* max number of 1G MAC per FM */
+
+/* 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	4
+#define RX_PORT_10G_BASE	0x10
+#define TX_PORT_1G_BASE		0x28
+#define MAX_NUM_TX_PORT_1G	4
+#define TX_PORT_10G_BASE	0x30
+
+enum fm_port_type {
+	fm_port_type_oh_e,
+	fm_port_type_rx_e,
+	fm_port_type_rx_10g_e,
+	fm_port_type_tx_e,
+	fm_port_type_tx_10g_e
+};
+
+/* 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
+
+enum fm_block {
+	fm_muram_e,
+	fm_bmi_e,
+	fm_qmi_e,
+	fm_parser_e,
+	fm_policer_e,
+	fm_keygen_e,
+	fm_dma_e,
+	fm_fpm_e,
+	fm_imem_e,
+	fm_soft_paser_e,
+	fm_mac_e, /* 1gmac(1-4), 10gmac */
+	fm_mdio_e, /* 5 mdio, the 5th match to 10gmac */
+	fm_1588_tmr_e
+};
+
+/* FM MURAM
+ */
+struct fm_muram {
+	u32 base;
+	u32 top;
+	u32 size;
+	u32 res_size;
+	u32 fm;
+	u32 alloc;
+};
+#define FM_MURAM_SIZE		0x28000
+#define FM_MURAM_RES_SIZE	0x01000
+
+/* FM IRAM registers
+ */
+struct fm_iram {
+	u32 iadd; /* instruction address register */
+	u32 idata; /* instruction data register */
+	u32 itcfg; /* timing config register */
+	u32 iready; /* ready register */
+	u32 res[0x1FFFC];
+} __attribute__ ((packed));
+
+#define IRAM_IADD_AIE		0x80000000 /* address auto increase enable */
+#define IRAM_READY		0x80000000 /* ready to use */
+
+
+/* FMDMSR - Fman DMA status register */
+#define FMDMSR_CMDQNE		0x10000000 /* command queue not empty */
+#define FMDMSR_BER		0x08000000 /* bus error event occurred on bus */
+#define FMDMSR_RDB_ECC		0x04000000 /* read buffer ECC error */
+#define FMDMSR_WRB_SECC		0x02000000 /* write buffer ECC error on system side */
+#define FMDMSR_WRB_FECC		0x01000000 /* write buffer ECC error on Fman side */
+#define FMDMSR_DPEXT_SECC	0x00800000 /* dual port external ECC error on system side */
+#define FMDMSR_DPEXT_FECC	0x00400000 /* dual port external ECC error on Fman side */
+#define FMDMSR_DPDAT_SECC	0x00200000 /* dual port data ECC error on system side */
+#define FMDMSR_DPDAT_FECC	0x00100000 /* dual port data ECC error on Fman side */
+#define FMDMSR_SPDAT_FECC	0x00080000 /* single port data ECC error on 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_CACHE_OVRD_MASK	0xc0000000 /* override cache field one the command bus */
+#define FMDMMR_CACHE_NO_CACHING	0x00000000 /* 00 - no override, no caching */
+#define FMDMMR_CACHE_NO_STASH	0x40000000 /* 01 - data should not be stashed in cache */
+#define FMDMMR_CACHE_MAY_STASH	0x80000000 /* 10 - data may be stashed in cache */
+#define FMDMMR_CACHE_STASH	0xc0000000 /* 11 - data should be stashed in cache */
+#define FMDMMR_AID_OVRD		0x20000000 /* AID override, AID='0000' */
+#define FMDMMR_SBER		0x10000000 /* stop the DMA transaction if a bus error */
+#define FMDMMR_AXI_DBG_MASK	0x0f000000 /* number of beates to be written to external mem */
+#define FMDMMR_AXI_DBG_SHIFT	24
+#define FMDMMR_ERRD_EN		0x00800000 /* enable read port emergency */
+#define FMDMMR_ERWR_EN		0x00400000 /* enable write port emergency */
+#define FMDMMR_BER_EN		0x00200000 /* enable external bus error event */
+#define FMDMMR_EB_EN		0x00100000 /* enable emergency towards external bus */
+#define FMDMMR_ERRD_EME		0x00080000 /* set manual emergency on read port */
+#define FMDMMR_ERWR_EME		0x00040000 /* set manual emergency on write port */
+#define FMDMMR_EB_EME_MASK	0x00030000 /* priority on external bus */
+#define FMDMMR_EB_EME_NORMAL	0x00000000 /* 00 - normal */
+#define FMDMMR_EB_EME_EBS	0x00010000 /* 01 - extended bus service */
+#define FMDMMR_EB_EME_SOS	0x00020000 /* 10 - SOS priority */
+#define FMDMMR_EB_EME_EBSSOS	0x00030000 /* 11 - EBS + SOS priority */
+#define FMDMMR_PROT0		0x00001000 /* bus protection - privilege */
+#define FMDMMR_PROT2		0x00000400 /* bus protection - instruction */
+#define FMDMMR_BMI_EMR		0x00000040 /* SOS emergency is set by BMI */
+#define FMDMMR_ECC_MASK		0x00000020 /* enable ECC error events */
+#define FMDMMR_AID_TNUM		0x00000010 /* choose the 4 LSB bits of TNUM output on AID */
+
+#define FMDMMR_INIT		(FMDMMR_SBER)
+
+/* FMDMTR - FMan DMA threshold register
+ */
+#define FMDMTR_DEFAULT		0x18600060 /* high- cmd=24, read/write internal buf=96 */
+
+/* FMDMHY - FMan DMA hysteresis register
+ */
+#define FMDMHY_DEFAULT		0x10400040 /* low- cmd=16, read/write internal buf=64 */
+
+/* FMDMSETR - FMan DMA SOS emergency threshold register
+ */
+#define FMDMSETR_DEFAULT	0x00000000
+
+#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)
+
+#define FMFPFLC_DEFAULT		0x00000000 /* no dispatch limitation */
+#define FMFPDIST1_DEFAULT	0x10101010
+#define FMFPDIST2_DEFAULT	0x10101010
+
+#define FMRSTC_RESET_FMAN	0x80000000 /* reset entire FMAN and MACs */
+
+/* FMFP_EE - FPM event and enable register
+ */
+#define FMFPEE_DECC		0x80000000 /* double ECC erorr on FPM ram access */
+#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 error 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)
+
+/* FMBM_INIT - BMI initialization register
+ */
+#define FMBM_INIT_START		0x80000000 /* start to init the internal buf linked list */
+
+/* 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 */
+#define FMBM_CFG1_FBPO_INIT	0x00000010
+
+/* FMBM_CFG2 - BMI configuration 2
+ */
+#define FMBM_CFG2_TNTSKS_MASK	0x007f0000 /* Total number of task */
+#define FMBM_CFG2_TNTSKS_SHIFT	16
+#define FMBM_CFG2_TDMA_MASK	0x0000003f /* Total DMA */
+
+#define FMBM_CFG2_INIT		0x00600018 /* max outstanding tasks/dma transfer = 96/24 */
+
+/* FMBM_IEVR - interrupt event
+ */
+#define FMBM_IEVR_PEC		0x80000000 /* pipeline table ECC error 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
+
+/* 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 statistic counters */
+#define FMQM_GC_ENQ_THR_MASK	0x00003f00 /* max number of enqueue Tnum */
+#define FMQM_GC_ENQ_THR_SHIFT	8
+#define FMQM_GC_DEQ_THR_MASK	0x0000003f /* max number of dequeue Tnum */
+
+#define FMQM_GC_INIT		0x00003030 /* enqueue/dequeue disable */
+
+/* FMQM_EIE - error interrupt event register
+ */
+#define FMQM_EIE_DEE		0x80000000 /* double-bit ECC detected */
+#define FMQM_EIE_DFUPE		0x40000000 /* dequeue from unkown PortID error */
+#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 interrupt enable */
+#define FMQM_EIEN_DFUPEN	0x40000000 /* dequeue from unkown PortID int enable */
+#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 error interrupt enable */
+#define FMQM_IEN_DISABLE_ALL	0x00000000
+
+struct fm_global {
+	int fm;			/* 0-FM1, 1-FM2 */
+	u32 ucode_ver;		/* microcode version */
+	u32 *ucode;		/* microcode */
+	u32 ucode_size;
+	struct fm_muram muram;	/* muram info structure */
+	u32 free_pool_base;	/* Free buffer pool base - FIFO */
+	u32 free_pool_size;
+};
+
+#define FM_FREE_POOL_SIZE	0x20000 /* 128K bytes */
+#define FM_FREE_POOL_ALIGN	256
+
+u32 fm_get_base_addr(int fm, enum fm_block block, int port);
+int fm_get_port_id(enum fm_port_type type, int num);
+u32 fm_muram_alloc(struct fm_muram *mem, u32 size, u32 align);
+int fm_init_common(int index);
+struct fm_global *fm_get_global(int index);
+
+/* Fman ethernet private struct */
+typedef struct fm_eth {
+	enum fm_port port;
+	int fm_index;			/* Fman index */
+	u32 num;			/* 0-3: dTSEC0-3 and 4: TGEC */
+	int rx_port;			/* Rx port for the ethernet */
+	int tx_port;			/* Tx port for the ethernet */
+	enum fm_eth_type type;		/* 1G or 10G ethernet */
+	enum fsl_phy_enet_if enet_if;
+	struct fm_global *fm;		/* Fman global information */
+	struct fsl_enet_mac *mac;	/* MAC controller */
+	struct phy_info *phyinfo;
+	struct mii_info *mii_info;
+	void *phyregs;
+	int phyaddr;
+	struct eth_device *dev;
+	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 */
+} __attribute__ ((packed)) fm_eth_t;
+
+#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/fm_eth.c b/drivers/net/fm/fm_eth.c
new file mode 100644
index 0000000..17b6807
--- /dev/null
+++ b/drivers/net/fm/fm_eth.c
@@ -0,0 +1,1234 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 <asm/fsl_serdes.h>
+
+#include "fm.h"
+#include "miiphy.h"
+#include "dtsec.h"
+#include "tgec.h"
+#include "../fsl_phy.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MAXCONTROLLERS	(10)
+static struct eth_device *devlist[MAXCONTROLLERS];
+static int num_controllers;
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+	&& !defined(BITBANGMII)
+static int cur_mdio45_dev;
+extern void tgec_write_phy_reg(struct tgec_mdio_controller *regs, int port_addr,
+		int dev_addr, int regnum, int value);
+extern int tgec_read_phy_reg(struct tgec_mdio_controller *regs, int port_addr,
+		int dev_addr, int regnum);
+extern void mux_mdio_for_fm(enum fm_port port, int fm, int num);
+#endif
+
+struct fm_eth_info fm1_dtsec_info[CONFIG_SYS_NUM_FM1_DTSEC] = {
+#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
+};
+
+struct fm_eth_info fm1_10gec_info[CONFIG_SYS_NUM_FM1_10GEC] = {
+	FM_TGEC_INFO_INITIALIZER(1, 1),
+};
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+struct fm_eth_info fm2_dtsec_info[CONFIG_SYS_NUM_FM2_DTSEC] = {
+	FM_DTSEC_INFO_INITIALIZER(2, 1),
+	FM_DTSEC_INFO_INITIALIZER(2, 2),
+	FM_DTSEC_INFO_INITIALIZER(2, 3),
+	FM_DTSEC_INFO_INITIALIZER(2, 4),
+};
+
+struct fm_eth_info fm2_10gec_info[CONFIG_SYS_NUM_FM2_10GEC] = {
+	FM_TGEC_INFO_INITIALIZER(2, 1),
+};
+#endif
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+	&& !defined(BITBANGMII)
+/*
+ * Find a device index from the devlist by name
+ *
+ * Returns:
+ *  The index where the device is located, -1 on error
+ */
+static int miiphy_find_dev_by_name(const char *devname)
+{
+	int i;
+
+	for (i = 0; i < num_controllers; i++) {
+		if (strncmp(devname, devlist[i]->name, strlen(devname)) == 0)
+			break;
+	}
+
+	/* If device cannot be found, returns -1 */
+	if (i == num_controllers) {
+		printf("%s: device %s not found in devlist\n",
+				__func__, devname);
+		i = -1;
+	}
+
+	return i;
+}
+
+static int dtsec_miiphy_read(const char *devname, unsigned char addr,
+		unsigned char reg, unsigned short *value)
+{
+	int devindex = 0;
+	struct fm_eth *fm;
+
+	if (devname == NULL || value == NULL) {
+		printf("%s: NULL pointer given\n", __func__);
+	} else {
+		devindex = miiphy_find_dev_by_name(devname);
+		if (devindex >= 0) {
+			tsec_mii_t *phyregs;
+
+			fm = devlist[devindex]->priv;
+			phyregs = fm->phyregs;
+			mux_mdio_for_fm(fm->port, fm->fm_index, fm->num);
+			*value = tsec_local_mdio_read(phyregs, addr, 0, reg);
+		}
+	}
+
+	return 0;
+}
+
+static int dtsec_miiphy_write(const char *devname, unsigned char addr,
+		unsigned char reg, unsigned short value)
+{
+	int devindex = 0;
+	struct fm_eth *fm;
+
+	if (devname == NULL) {
+		printf("%s: NULL pointer given\n", __func__);
+	} else {
+		devindex = miiphy_find_dev_by_name(devname);
+		if (devindex >= 0) {
+			tsec_mii_t *phyregs;
+
+			fm = devlist[devindex]->priv;
+			phyregs = fm->phyregs;
+			mux_mdio_for_fm(fm->port, fm->fm_index, fm->num);
+			tsec_local_mdio_write(phyregs, addr, 0, reg, value);
+		}
+	}
+
+	return 0;
+}
+
+int do_mdio45(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int port;
+	int dev;
+	int reg;
+	struct tgec_mdio_controller *regs;
+	struct fm_eth *fm_eth;
+	int result;
+
+	if (argc < 3) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	if (argc == 3) {
+		int dev;
+
+		if (strcmp(argv[1], "device")) {
+			cmd_usage(cmdtp);
+			return 1;
+		}
+		dev = miiphy_find_dev_by_name(argv[2]);
+
+		if (dev >= 0)
+			cur_mdio45_dev = dev;
+
+		return 0;
+	}
+
+	port = (int)simple_strtoul(argv[2], NULL, 10);
+	dev = (int)simple_strtoul(argv[3], NULL, 10);
+	reg = (int)simple_strtoul(argv[4], NULL, 10);
+
+	fm_eth = devlist[cur_mdio45_dev]->priv;
+	regs = fm_eth->phyregs;
+
+	mux_mdio_for_fm(fm_eth->port, fm_eth->fm_index, fm_eth->num);
+
+	if (strcmp(argv[1], "read") == 0) {
+		result = tgec_read_phy_reg(regs, port, dev, reg);
+		printf("Read %d %d %d: %x\n", port, dev, reg, result);
+	} else if (strcmp(argv[1], "write") == 0 && argc > 5)
+		tgec_write_phy_reg(regs, port, dev, reg,
+				(int)simple_strtoul(argv[5], NULL, 16));
+
+	return 0;
+}
+U_BOOT_CMD(
+	mdio45,	6,	1,	do_mdio45,
+	"MDIO Clause 45 utility commands",
+	"mdio45 device <devname> - Set controller to <devname>\n"
+	"mdio45 read   <portaddr> <devaddr> <reg> - read <reg> [0-65535] of device <devaddr> [1-31] on PHY <portaddr> [0-31]\n"
+	"mdio45 write  <portaddr> <devaddr> <reg> <data> - write reg <reg> [0-65535] of device <devaddr> [1-31] on PHY <portaddr> [0-31]\n"
+);
+
+#define TBIANA_SETTINGS ( \
+		TBIANA_ASYMMETRIC_PAUSE \
+		| TBIANA_SYMMETRIC_PAUSE \
+		| TBIANA_FULL_DUPLEX \
+		)
+
+#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;
+	tsec_mii_t *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, regs->tbipa, 0, TBI_TBICON,
+			TBICON_CLK_SELECT);
+	tsec_local_mdio_write(phyregs, regs->tbipa, 0, TBI_ANA,
+			TBIANA_SETTINGS);
+	tsec_local_mdio_write(phyregs, regs->tbipa, 0, TBI_CR, TBICR_SETTINGS);
+}
+
+static struct phy_info *dtsec_init_phy(struct eth_device *dev,
+					struct mii_info *mii_info)
+{
+	struct fm_eth *fm_eth;
+	struct dtsec *regs;
+	tsec_mii_t *miiregs;
+	struct phy_info *curphy;
+	int timeout = 1000000;
+
+	mii_info->advertising = (ADVERTISED_10baseT_Half |
+				ADVERTISED_10baseT_Full |
+				ADVERTISED_100baseT_Half |
+				ADVERTISED_100baseT_Full |
+				ADVERTISED_1000baseT_Full);
+
+	fm_eth = dev->priv;
+	regs = (struct dtsec *)fm_eth->mac->base;
+	miiregs = (tsec_mii_t *)fm_eth->mac->phyregs;
+
+	/* Assign a Physical address to the TBI */
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+
+	out_be32(&miiregs->miimcfg, MIIMCFG_RESET_MGMT);
+	out_be32(&miiregs->miimcfg, 0);
+	out_be32(&miiregs->miimcfg, MIIMCFG_INIT_VALUE);
+	asm("sync");
+	while (in_be32(&miiregs->miimind)&MIIMIND_BUSY && timeout--);
+
+	if (fm_eth->enet_if == SGMII)
+		dtsec_configure_serdes(fm_eth);
+
+	/* Get the cmd structure corresponding to the attached PHY */
+	curphy = tsec_get_phy_info(mii_info);
+	if (curphy == NULL) {
+		printf("%s: No PHY found\n", dev->name);
+		return NULL;
+	}
+
+	return curphy;
+}
+
+static struct phy_info *tgec_init_phy(struct eth_device *dev,
+					struct mii_info *mii_info)
+{
+	struct phy_info *curphy;
+	struct fm_eth *fm;
+	char phyopt[20];
+
+	fm = dev->priv;
+
+	mii_info->advertising = (ADVERTISED_100baseT_Full |
+				ADVERTISED_1000baseT_Full |
+				ADVERTISED_10000baseT_Full);
+
+	/* Get the cmd structure corresponding to the attached PHY */
+	curphy = tgec_get_phy_info(mii_info);
+	if (curphy == NULL)
+		printf("%s: No PHY found\n", dev->name);
+
+	cur_mdio45_dev = miiphy_find_dev_by_name(dev->name);
+
+	sprintf(phyopt, "fsl_fm%d_xaui_phy", fm->fm_index + 1);
+
+	if (hwconfig_arg_cmp(phyopt, "xfi"))
+		mii_info->port = PORT_FIBRE;
+
+	return curphy;
+}
+#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_enable(int fm, int port)
+{
+	struct fm_bmi_rx_port *rx_port;
+	u32 val;
+
+	rx_port = (struct fm_bmi_rx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+	val = in_be32(&rx_port->fmbm_rcfg);
+	val |= FMBM_RCFG_EN;
+	out_be32(&rx_port->fmbm_rcfg, val);
+}
+
+static void bmi_rx_port_disable(int fm, int port)
+{
+	struct fm_bmi_rx_port *rx_port;
+	u32 val;
+	int timeout = 1000000;
+
+	rx_port = (struct fm_bmi_rx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+	val = in_be32(&rx_port->fmbm_rcfg);
+	val &= ~FMBM_RCFG_EN;
+	out_be32(&rx_port->fmbm_rcfg, val);
+
+	/* 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(int fm, int port)
+{
+	struct fm_bmi_rx_port *rx_port;
+	rx_port = (struct fm_bmi_rx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+
+	/* set BMI to independent mode, Rx port disable */
+	out_be32(&rx_port->fmbm_rcfg, FMBM_RCFG_IM);
+	/* set Rx DMA attributes - no swap, no stash/no optimization */
+	out_be32(&rx_port->fmbm_rda, FMBM_RDA_INIT);
+	/* set Rx FIFO parameters */
+	out_be32(&rx_port->fmbm_rfp, FMBM_RFP_DEFAULT);
+	/* set Rx frame end parameters */
+	out_be32(&rx_port->fmbm_rfed, FMBM_RFED_DEFAULT);
+	/* set Rx IC parameters */
+	out_be32(&rx_port->fmbm_ricp, FMBM_RICP_DEFAULT);
+	/* 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 */
+	out_be32(&rx_port->fmbm_rfca, FMBM_RFCA_DEFAULT);
+	/* 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_enable(int fm, int port)
+{
+	struct fm_bmi_tx_port *tx_port;
+	u32 val;
+
+	tx_port = (struct fm_bmi_tx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+	val = in_be32(&tx_port->fmbm_tcfg);
+	val |= FMBM_TCFG_EN;
+	out_be32(&tx_port->fmbm_tcfg, val);
+}
+
+static void bmi_tx_port_disable(int fm, int port)
+{
+	struct fm_bmi_tx_port *tx_port;
+	u32 val;
+	int timeout = 1000000;
+
+	tx_port = (struct fm_bmi_tx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+	val = in_be32(&tx_port->fmbm_tcfg);
+	val &= ~FMBM_TCFG_EN;
+	out_be32(&tx_port->fmbm_tcfg, val);
+
+	/* 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(int fm, int port)
+{
+	struct fm_bmi_tx_port *tx_port;
+
+	tx_port = (struct fm_bmi_tx_port *)fm_get_base_addr(fm,
+					fm_bmi_e, port);
+
+	/* set BMI to independent mode, Tx port disable */
+	out_be32(&tx_port->fmbm_tcfg, FMBM_TCFG_IM);
+	/* set Tx DMA attributes - no stash/no swap */
+	out_be32(&tx_port->fmbm_tda, FMBM_TDA_INIT);
+	/* set Tx FIFO parameters - pipeline depth=1, low comfort 20*256B */
+	out_be32(&tx_port->fmbm_tfp, FMBM_TFP_INIT);
+	/* set Tx frame margins parameters */
+	out_be32(&tx_port->fmbm_tfed, FMBM_TFED_DEFAULT);
+	/* set Tx IC parameters */
+	out_be32(&tx_port->fmbm_ticp, FMBM_TICP_DEFAULT);
+	/* 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 */
+	out_be32(&tx_port->fmbm_tfca, FMBM_TFCA_DEFAULT);
+	/* 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 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;
+	__asm__ __volatile__ ("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;
+	__asm__ __volatile__ ("sync");
+}
+
+static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth)
+{
+	struct fm_global *fm;
+	struct fm_muram *muram;
+	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;
+	int i;
+
+	fm = fm_eth->fm;
+	muram = &fm->muram;
+
+	/* alloc global parameter ram at MURAM */
+	pram = (struct fm_port_global_pram *)fm_muram_alloc(muram,
+		FM_PRAM_SIZE, FM_PRAM_ALIGN);
+	fm_eth->rx_pram = pram;
+
+	/* parameter page offset to MURAM */
+	pram_page_offset = (u32)pram - muram->base;
+
+	/* 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 */
+	bmi_rx_port = (struct fm_bmi_rx_port *)fm_get_base_addr(fm->fm,
+					fm_bmi_e, fm_eth->rx_port);
+	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_global *fm;
+	struct fm_muram *muram;
+	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;
+	int i;
+
+	fm = fm_eth->fm;
+	muram = &fm->muram;
+
+	/* alloc global parameter ram at MURAM */
+	pram = (struct fm_port_global_pram *)fm_muram_alloc(muram,
+		FM_PRAM_SIZE, FM_PRAM_ALIGN);
+	fm_eth->tx_pram = pram;
+
+	/* parameter page offset to MURAM */
+	pram_page_offset = (u32)pram - muram->base;
+
+	/* 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 */
+	bmi_tx_port = (struct fm_bmi_tx_port *)fm_get_base_addr(fm->fm,
+					fm_bmi_e, fm_eth->tx_port);
+	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 */
+	if (mac->init_mac)
+		mac->init_mac(mac);
+
+	/* For some reason we need to set SPEED_100 */
+	if ((fm_eth->enet_if == 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->fm_index, fm_eth->rx_port);
+	/* init bmi tx port, IM mode and disable */
+	bmi_tx_port_init(fm_eth->fm_index, fm_eth->tx_port);
+
+	return 1;
+}
+
+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;
+	}
+	if (mac->set_mac_addr)
+		mac->set_mac_addr(mac, dev->enetaddr);
+
+	/* enable bmi Rx port */
+	bmi_rx_port_enable(fm_eth->fm_index, fm_eth->rx_port);
+	/* enable MAC rx/tx port */
+	if (mac->enable_mac)
+		mac->enable_mac(mac);
+	/* enable bmi Tx port */
+	bmi_tx_port_enable(fm_eth->fm_index, fm_eth->tx_port);
+	/* re-enable transmission of frame */
+	fmc_tx_port_graceful_stop_disable(fm_eth);
+
+#ifdef CONFIG_MII
+	mux_mdio_for_fm(fm_eth->port, fm_eth->fm_index, fm_eth->num);
+
+	if (fm_eth->phyinfo && fm_eth->phyinfo->startup)
+		fm_eth->phyinfo->startup(fm_eth->mii_info);
+#else
+	fm_eth->mii_info->speed = SPEED_1000;
+	fm_eth->mii_info->link = 1;
+	fm_eth->mii_info->duplex = DUPLEX_FULL;
+#endif
+
+	/* set the MAC-PHY mode */
+	if (mac->set_if_mode)
+		mac->set_if_mode(mac, fm_eth->enet_if, fm_eth->mii_info->speed);
+
+	return fm_eth->mii_info->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->fm_index, fm_eth->tx_port);
+	/* disable MAC rx/tx port */
+	if (mac->disable_mac)
+		mac->disable_mac(mac);
+	/* disable bmi Rx port */
+	bmi_rx_port_disable(fm_eth->fm_index, fm_eth->rx_port);
+
+#ifdef CONFIG_MII
+	mux_mdio_for_fm(fm_eth->port, fm_eth->fm_index, fm_eth->num);
+
+	if (fm_eth->phyinfo && fm_eth->phyinfo->shutdown)
+		fm_eth->phyinfo->shutdown(fm_eth->mii_info);
+#endif
+}
+
+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(1000);
+		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;
+	__asm__ __volatile__ ("sync");
+	txbd->status = TxBD_READY | TxBD_LAST;
+	__asm__ __volatile__ ("sync");
+
+	/* update TxQD, let RISC to send the packet */
+	offset_in = muram_readw(&pram->txqd.offset_in);
+	offset_in += SIZEOFBD;
+	if (offset_in >= muram_readw(&pram->txqd.bd_ring_size))
+		offset_in = 0;
+	muram_writew(&pram->txqd.offset_in, offset_in);
+	__asm__ __volatile__ ("sync");
+
+	/* wait for buffer to be transmitted */
+	for (i = 0; txbd->status & TxBD_READY; i++) {
+		udelay(1000);
+		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;
+		__asm__ __volatile__ ("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 += SIZEOFBD;
+		if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size))
+			offset_out = 0;
+		muram_writew(&pram->rxqd.offset_out, offset_out);
+		__asm__ __volatile__ ("sync");
+	}
+	fm_eth->cur_rxbd = (void *)rxbd;
+
+	return 1;
+}
+
+static int fm_eth_init_mac(struct fm_eth *fm_eth)
+{
+	struct fsl_enet_mac *mac;
+	int fm, num;
+	void *base, *phyregs = NULL;
+
+	mac = fm_eth->mac;
+	fm = fm_eth->fm_index;
+	num = fm_eth->num;
+
+	/* Get the mac registers base address */
+	base = (void *)fm_get_base_addr(fm, fm_mac_e, num);
+	phyregs = (void *)fm_get_base_addr(fm, fm_mdio_e, num);
+
+	/* 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, phyregs, 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 mii_info	*mii_info;
+#ifdef CONFIG_MII
+	struct phy_info *curphy;
+#endif
+
+	mii_info = malloc(sizeof(*mii_info));
+	if (!mii_info) {
+		printf("%s: Could not allocate mii_info", dev->name);
+		return -1;
+	}
+	memset(mii_info, 0, sizeof(*mii_info));
+
+	mii_info->duplex = DUPLEX_FULL;
+	mii_info->link = 0;
+
+	mii_info->autoneg = 1;
+	mii_info->mii_id = fm_eth->phyaddr;
+
+	mii_info->priv = fm_eth;
+	mii_info->dev = dev;
+	fm_eth->mii_info = mii_info;
+
+	mii_info->phyregs = fm_eth->phyregs;
+
+#ifdef CONFIG_MII
+	mux_mdio_for_fm(fm_eth->port, fm_eth->fm_index, fm_eth->num);
+
+	if (fm_eth->type == fm_eth_1g_e)
+		curphy = dtsec_init_phy(dev, mii_info);
+	else
+		curphy = tgec_init_phy(dev, mii_info);
+
+	fm_eth->phyinfo = curphy;
+
+	if (!curphy)
+		return -1;
+
+	if (curphy->config)
+		curphy->config(fm_eth->mii_info);
+#endif
+
+	return 0;
+}
+
+static int fm_eth_initialize(struct fm_global *fm, struct fm_eth_info *info)
+{
+	struct eth_device *dev;
+	struct fm_eth *fm_eth;
+	int rx_port, tx_port;
+	int i, 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 the fm global to Fman ethernet struct */
+	fm_eth->fm = fm;
+	/* save the fm num# to Fman ethernet struct */
+	fm_eth->fm_index = fm->fm;
+	/* save num to Fman ethenet (0-3: dTSEC, 4: TGEC) */
+	num = info->num;
+	fm_eth->num = num;
+	fm_eth->port = info->port;
+	fm_eth->type = info->type;
+
+	/* Rx port and Tx port for the Fman ethernet */
+	if (fm_eth->type == fm_eth_1g_e) {
+		rx_port = fm_get_port_id(fm_port_type_rx_e, num);
+		tx_port = fm_get_port_id(fm_port_type_tx_e, num);
+	} else {
+		rx_port = fm_get_port_id(fm_port_type_rx_10g_e, 0);
+		tx_port = fm_get_port_id(fm_port_type_tx_10g_e, 0);
+	}
+	fm_eth->rx_port = rx_port;
+	fm_eth->tx_port = tx_port;
+
+	/* init global mac structure */
+	if (!fm_eth_init_mac(fm_eth))
+		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", fm->fm + 1, num + 1);
+	else
+		sprintf(dev->name, "FM%d at TGEC%d", fm->fm + 1, 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;
+
+	/* clear the ethernet address */
+	for (i = 0; i < 6; i++)
+		dev->enetaddr[i] = 0;
+	eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+	&& !defined(BITBANGMII)
+	miiphy_register(dev->name, dtsec_miiphy_read, dtsec_miiphy_write);
+#endif
+
+	fm_eth->phyaddr = info->phy_addr;
+	fm_eth->phyregs = info->phy_regs;
+	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;
+
+	return 1;
+}
+
+int fm_standard_init(bd_t *bis)
+{
+	int i;
+	struct fm_global *fm;
+
+	if (fm_init_common(0))
+		return 0;
+
+	fm = fm_get_global(0);
+
+	for (i = 0; i < CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+		if (fm1_dtsec_info[i].enabled) {
+			if (!fm_eth_initialize(fm, &fm1_dtsec_info[i]))
+				return 0;
+		}
+	}
+	for (i = 0; i < CONFIG_SYS_NUM_FM1_10GEC; i++) {
+		if (fm1_10gec_info[i].enabled) {
+			if (!fm_eth_initialize(fm, &fm1_10gec_info[i]))
+				return 0;
+		}
+	}
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	if (fm_init_common(1))
+		return 0;
+
+	fm = fm_get_global(1);
+
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_DTSEC; i++) {
+		if (fm2_dtsec_info[i].enabled) {
+			if (!fm_eth_initialize(fm, &fm2_dtsec_info[i]))
+				return 0;
+		}
+	}
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_10GEC; i++) {
+		if (fm2_10gec_info[i].enabled) {
+			if (!fm_eth_initialize(fm, &fm2_10gec_info[i]))
+				return 0;
+		}
+	}
+#endif
+
+	return 1;
+}
+
+static int is_device_enabled(u32 devdisr_mask)
+{
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 devdisr2 = in_be32(&gur->devdisr2);
+
+	return !(devdisr_mask & devdisr2);
+}
+
+/* Init data structures based on HW cfg */
+void fman_enet_init(void)
+{
+	int i;
+	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	u32 rcwsr11 = in_be32(&gur->rcwsr[11]);
+
+	for (i = 0; i < CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+		if (is_device_enabled(fm1_dtsec_info[i].devdisr_mask)) {
+			fm1_dtsec_info[i].enabled = 1;
+			fm1_dtsec_info[i].enet_if = SGMII;
+		} else {
+			fm1_dtsec_info[i].enabled = 0;
+		}
+	}
+	for (i = 0; i < CONFIG_SYS_NUM_FM1_10GEC; i++) {
+		if (is_device_enabled(fm1_10gec_info[i].devdisr_mask)) {
+			fm1_10gec_info[i].enabled = 1;
+			fm1_10gec_info[i].enet_if = XAUI;
+		} else {
+			fm1_10gec_info[i].enabled = 0;
+		}
+		if (!is_serdes_configured(XAUI_FM1))
+			fm1_10gec_info[i].enabled = 0;
+	}
+
+	if (!is_serdes_configured(SGMII_FM1_DTSEC1))
+		fm1_dtsec_info[0].enabled = 0;
+
+	if ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+		FSL_CORENET_RCWSR11_EC1_FM1_DTSEC1) {
+		fm1_dtsec_info[0].enabled = 1;
+		fm1_dtsec_info[0].enet_if = RGMII;
+	}
+
+	if ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2) {
+		fm1_dtsec_info[1].enabled = 1;
+		fm1_dtsec_info[1].enet_if = RGMII;
+	}
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_DTSEC; i++) {
+		if (is_device_enabled(fm2_dtsec_info[i].devdisr_mask)) {
+			fm2_dtsec_info[i].enabled = 1;
+			fm2_dtsec_info[i].enet_if = SGMII;
+		} else {
+			fm2_dtsec_info[i].enabled = 0;
+		}
+	}
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_10GEC; i++) {
+		if (is_device_enabled(fm2_10gec_info[i].devdisr_mask)) {
+			fm2_10gec_info[i].enabled = 1;
+			fm2_10gec_info[i].enet_if = XAUI;
+		} else {
+			fm2_10gec_info[i].enabled = 0;
+		}
+		if (!is_serdes_configured(XAUI_FM2))
+			fm2_10gec_info[i].enabled = 0;
+	}
+
+	if ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+		FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1) {
+		fm2_dtsec_info[0].enabled = 1;
+		fm2_dtsec_info[0].enet_if = RGMII;
+	}
+#endif
+
+	return ;
+}
+
+void fm_info_set_phy_address(enum fm_port port, int address)
+{
+	switch (port) {
+	case FM1_DTSEC1:
+	case FM1_DTSEC2:
+	case FM1_DTSEC3:
+	case FM1_DTSEC4:
+	case FM1_DTSEC5:
+		fm1_dtsec_info[port - FM1_DTSEC1].phy_addr = address;
+		break;
+	case FM1_10GEC1:
+		fm1_10gec_info[port - FM1_10GEC1].phy_addr = address;
+		break;
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	case FM2_DTSEC1:
+	case FM2_DTSEC2:
+	case FM2_DTSEC3:
+	case FM2_DTSEC4:
+		fm2_dtsec_info[port - FM2_DTSEC1].phy_addr = address;
+		break;
+	case FM2_10GEC1:
+		fm2_10gec_info[port - FM2_10GEC1].phy_addr = address;
+		break;
+#endif
+	default:
+		break;
+	};
+}
+
+enum fsl_phy_enet_if fm_info_get_enet_if(enum fm_port port)
+{
+	switch (port) {
+	case FM1_DTSEC1:
+	case FM1_DTSEC2:
+	case FM1_DTSEC3:
+	case FM1_DTSEC4:
+	case FM1_DTSEC5:
+		if (fm1_dtsec_info[port - FM1_DTSEC1].enabled)
+			return fm1_dtsec_info[port - FM1_DTSEC1].enet_if;
+		break;
+	case FM1_10GEC1:
+		if (fm1_10gec_info[port - FM1_10GEC1].enabled)
+			return fm1_10gec_info[port - FM1_10GEC1].enet_if;
+		break;
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	case FM2_DTSEC1:
+	case FM2_DTSEC2:
+	case FM2_DTSEC3:
+	case FM2_DTSEC4:
+		if (fm2_dtsec_info[port - FM2_DTSEC1].enabled)
+			return fm2_dtsec_info[port - FM2_DTSEC1].enet_if;
+		break;
+	case FM2_10GEC1:
+		if (fm2_10gec_info[port - FM2_10GEC1].enabled)
+			return fm2_10gec_info[port - FM2_10GEC1].enet_if;
+		break;
+#endif
+	default:
+		break;
+	};
+
+	return FSL_ETH_IF_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_fman_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 < CONFIG_SYS_NUM_FM1_DTSEC; i++)
+		ft_fman_fixup_port(blob, &fm1_dtsec_info[i], "fsl,fman-1g-mac");
+	for (i = 0; i < CONFIG_SYS_NUM_FM1_10GEC; i++)
+		ft_fman_fixup_port(blob, &fm1_10gec_info[i], "fsl,fman-10g-mac");
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_DTSEC; i++)
+		ft_fman_fixup_port(blob, &fm2_dtsec_info[i], "fsl,fman-1g-mac");
+	for (i = 0; i < CONFIG_SYS_NUM_FM2_10GEC; i++)
+		ft_fman_fixup_port(blob, &fm2_10gec_info[i], "fsl,fman-10g-mac");
+#endif
+}
diff --git a/include/fm_eth.h b/include/fm_eth.h
new file mode 100644
index 0000000..199bcd9
--- /dev/null
+++ b/include/fm_eth.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@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 __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,
+};
+
+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 */
+} __attribute__ ((packed));
+
+/* 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_RDA - Rx DMA attributes
+ */
+#define FMBM_RDA_SWAP_MASK	0xc0000000
+#define FMBM_RDA_SWAP_SHIFT	30
+#define FMBM_RDA_NO_SWAP	0x00000000
+#define FMBM_RDA_SWAP_LE	0x40000000 /* swapped in powerpc little endian mode */
+#define FMBM_RDA_SWAP_BE	0x80000000 /* swapped in big endian mode */
+#define FMBM_RDA_ICC_MASK	0x30000000
+#define FMBM_RDA_ICC_NOSTASH	0x00000000 /* IC write cacheable, no allocate */
+#define FMBM_RDA_ICC_STASH	0x10000000 /* IC write cacheable and allocate */
+#define FMBM_RDA_FHC_MASK	0x0c000000
+#define FMBM_RDA_FHC_NOSTASH	0x00000000 /* frame header write cacheable, no allocate */
+#define FMBM_RDA_FHC_STASH	0x04000000 /* frame header write cacheable and allocate */
+#define FMBM_RDA_SGC_MASK	0x03000000
+#define FMBM_RDA_SGC_NOSTASH	0x00000000 /* scatter gather write cacheable, no alloc */
+#define FMBM_RDA_SGC_STASH	0x01000000 /* scatter gather write cacheable and alloc */
+#define FMBM_RDA_WOPT_MASK	0x00300000
+#define FMBM_RDA_NO_OPT		0x00000000
+#define FMBM_RDA_WRITE_OPT	0x00100000 /* allow to write more bytes than the actual */
+
+#define FMBM_RDA_MASK_ALL	(FMBM_RDA_SWAP_MASK | FMBM_RDA_ICC_MASK \
+				| FMBM_RDA_FHC_MASK | FMBM_RDA_SGC_MASK \
+				| FMBM_RDA_WOPT_MASK)
+
+#define FMBM_RDA_INIT		0x00000000
+
+/* FMBM_RFP - Rx FIFO parameters
+ */
+#define FMBM_RFP_DEFAULT	0x03ff03ff
+
+/* FMBM_RFED - Rx Frame end data
+ */
+#define FMBM_RFED_DEFAULT	0x00000000
+
+/* FMBM_RICP - Rx internal context
+ */
+#define FMBM_RICP_DEFAULT	0x00000002
+
+/* FMBM_RFCA - Rx frame command attributes
+ */
+#define FMBM_RFCA_ORDER		0x80000000
+#define FMBM_RFCA_SYNC		0x02000000
+#define FMBM_RFCA_DEFAULT	0x003c0000
+
+/* 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 */
+} __attribute__ ((packed));
+
+/* 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_TDA - Tx DMA attributes
+ */
+#define FMBM_TDA_INIT		0x00000000 /* No swap, no stashing */
+
+/* FMBM_TFP - Tx FIFO parameters
+ */
+#define FMBM_TFP_INIT		0x00000013 /* pipeline=1, low comfort=5KB */
+
+/* FMBM_TFED - Tx frame end data
+ */
+#define FMBM_TFED_DEFAULT	0x00000000
+
+/* FMBM_TICP - Tx internal context parameters
+ */
+#define FMBM_TICP_DEFAULT	0x00000000
+
+/* FMBM_TFCA - Tx frame command attributes
+ */
+#define FMBM_TFCA_DEFAULT	0x00040000
+
+/* FMBM_TSTC - Tx statistics counters
+ */
+#define FMBM_TSTC_EN		0x80000000
+
+/* Rx/Tx buffer descriptor
+ */
+struct fm_port_bd {
+	u16 status;
+	u16 len;
+	u32 res0;
+	u16 res1;
+	u16 buf_ptr_hi;
+	u32 buf_ptr_lo;
+} __attribute__ ((packed));
+
+#define SIZEOFBD		sizeof(struct fm_port_bd)
+
+/* 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];
+} __attribute__ ((packed));
+
+#define QD_RXF_INT_MASK		0x0010 /* 1=set interrupt for receive frame */
+#define QD_BSY_INT_MASK		0x0008 /* 1=set interrupt for receive busy event */
+#define QD_FPMEVT_SEL_MASK	0x0003
+
+/* IM global parameter RAM
+ */
+struct fm_port_global_pram {
+	u32 mode;	/* independent mode register */
+	u32 rxqd_ptr;	/* Rx queue descriptor pointer, RxQD size=32 bytes
+			   8 bytes aligned, independent mode page address + 0x20 */
+	u32 txqd_ptr;	/* Tx queue descriptor pointer, TxQD size=32 bytes
+			   8 bytes aligned, independent mode page address + 0x40 */
+	u16 mrblr;	/* max Rx buffer length, set its value to the power of 2 */
+	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];
+} __attribute__ ((packed));
+
+#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
+
+/****************************
+ * Fman ethernet
+ ****************************/
+enum fm_eth_type {
+	fm_eth_1g_e,
+	fm_eth_10g_e,
+};
+
+/* Fman MAC controller
+ */
+#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)
+
+/* Fman ethernet info struct */
+#define FM_ETH_INFO_INITIALIZER(idx, pregs) \
+	.fm		= idx,						\
+	.phy_regs	= (void *)pregs,				\
+	.enet_if	= FSL_ETH_IF_NONE,				\
+
+#define FM_DTSEC_INFO_INITIALIZER(idx, n) \
+{									\
+	FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR)	\
+	.num		= n - 1,					\
+	.type		= fm_eth_1g_e,					\
+	.port		= FM##idx##_DTSEC##n,				\
+	.devdisr_mask	= FSL_CORENET_DEVDISR2_DTSEC##idx##_##n,	\
+	.compat_offset	= CONFIG_SYS_FSL_FM##idx##_OFFSET +		\
+				offsetof(struct ccsr_fman, mac[n-1]),	\
+}
+
+#define FM_TGEC_INFO_INITIALIZER(idx, n) \
+{									\
+	FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR)	\
+	.num		= n + 3,					\
+	.type		= fm_eth_10g_e,					\
+	.port		= FM##idx##_10GEC##n,				\
+	.devdisr_mask	= FSL_CORENET_DEVDISR2_10GEC##idx,		\
+	.compat_offset	= CONFIG_SYS_FSL_FM##idx##_OFFSET +		\
+				offsetof(struct ccsr_fman, fm_10gec),	\
+}
+
+struct fm_eth_info {
+	int enabled;
+	u32 devdisr_mask;
+	int fm;
+	int num;
+	enum fm_port port;
+	enum fm_eth_type type;
+	u8 phy_addr;
+	void *phy_regs;
+	enum fsl_phy_enet_if enet_if;
+	u32 compat_offset;
+};
+
+int fm_standard_init(bd_t *bis);
+int fm_initialize(int index, struct fm_eth_info *fm_info, int num);
+void fman_enet_init(void);
+void fdt_fixup_fman_ethernet(void *fdt);
+enum fsl_phy_enet_if fm_info_get_enet_if(enum fm_port port);
+void fm_info_set_phy_address(enum fm_port port, int address);
+
+#endif
-- 
1.6.4

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

* [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support
  2011-01-27  4:52         ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Mingkai Hu
@ 2011-01-27  4:52           ` Mingkai Hu
  2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
  2011-01-27 17:42             ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Timur Tabi
  2011-01-27 17:40           ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Timur Tabi
  1 sibling, 2 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

From: Kumar Gala <galak@kernel.crashing.org>

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 board/freescale/corenet_ds/Makefile     |    1 +
 board/freescale/corenet_ds/corenet_ds.c |   11 +-
 board/freescale/corenet_ds/eth_p4080.c  |  352 +++++++++++++++++++++++++++++++
 3 files changed, 359 insertions(+), 5 deletions(-)
 create mode 100644 board/freescale/corenet_ds/eth_p4080.c

diff --git a/board/freescale/corenet_ds/Makefile b/board/freescale/corenet_ds/Makefile
index 1047d78..a6872ac 100644
--- a/board/freescale/corenet_ds/Makefile
+++ b/board/freescale/corenet_ds/Makefile
@@ -28,6 +28,7 @@ LIB	= $(obj)lib$(BOARD).o
 
 COBJS-y	+= $(BOARD).o
 COBJS-y	+= ddr.o
+COBJS-$(CONFIG_P4080DS)	+= eth_p4080.o
 COBJS-$(CONFIG_P4080DS)	+= p4080ds_ddr.o
 COBJS-$(CONFIG_PCI)	+= pci.o
 COBJS-y	+= law.o
diff --git a/board/freescale/corenet_ds/corenet_ds.c b/board/freescale/corenet_ds/corenet_ds.c
index 232dc72..2eadf99 100644
--- a/board/freescale/corenet_ds/corenet_ds.c
+++ b/board/freescale/corenet_ds/corenet_ds.c
@@ -32,10 +32,12 @@
 #include <asm/fsl_serdes.h>
 #include <asm/fsl_portals.h>
 #include <asm/fsl_liodn.h>
+#include <fm_eth.h>
 
 extern void pci_of_setup(void *blob, bd_t *bd);
 
 #include "../common/ngpixis.h"
+#include "../../../drivers/net/fm/dtsec.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -193,6 +195,8 @@ void board_lmb_reserve(struct lmb *lmb)
 }
 #endif
 
+extern void fdt_fixup_p4080ds_enet(void * blob);
+
 void ft_board_setup(void *blob, bd_t *bd)
 {
 	phys_addr_t base;
@@ -210,9 +214,6 @@ void ft_board_setup(void *blob, bd_t *bd)
 #endif
 
 	fdt_fixup_liodn(blob);
-}
-
-int board_eth_init(bd_t *bis)
-{
-	return pci_eth_init(bis);
+	fdt_fixup_fman_ethernet(blob);
+	fdt_fixup_p4080ds_enet(blob);
 }
diff --git a/board/freescale/corenet_ds/eth_p4080.c b/board/freescale/corenet_ds/eth_p4080.c
new file mode 100644
index 0000000..465b07c
--- /dev/null
+++ b/board/freescale/corenet_ds/eth_p4080.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2009-2010 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 <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_serdes.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+#include <fm_eth.h>
+
+#include "../common/ngpixis.h"
+#include "../../../drivers/net/fm/dtsec.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define EMI_NONE	0xffffffff
+#define EMI_MASK	0xf0000000
+#define EMI1_RGMII	0x0
+#define EMI1_SLOT3	0x80000000	/* bank1 EFGH */
+#define EMI1_SLOT4	0x40000000	/* bank2 ABCD */
+#define EMI1_SLOT5	0xc0000000	/* bank3 ABCD */
+#define EMI2_SLOT4	0x10000000	/* bank2 ABCD */
+#define EMI2_SLOT5	0x30000000	/* bank3 ABCD */
+#define EMI1_MASK	0xc0000000
+#define EMI2_MASK	0x30000000
+
+static int mdio_mux[NUM_FM_PORTS];
+
+void mux_mdio_for_fm(enum fm_port port, int fm, int num)
+{
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR);
+	uint gpioval = in_be32(&pgpio->gpdat) & ~(EMI_MASK);
+	gpioval |= mdio_mux[port];
+
+	out_be32(&pgpio->gpdat, gpioval);
+}
+
+static u32 find_or_alloc_phandle(void * blob, const char * path, u32 phandle)
+{
+	int off;
+	u32 ph = 0;
+
+	path = fdt_get_alias(blob, path);
+	if (path) {
+		off = fdt_path_offset(blob, path);
+		if (off) {
+			ph = fdt_get_phandle(blob, off);
+			if ((ph == 0) || (ph == -1)) {
+				ph = phandle++;
+				fdt_setprop_cell(blob, off, "linux,phandle", ph);
+			}
+		}
+	}
+
+	return ph;
+}
+
+static void fdt_set_phy_handle(void *fdt, char * prop, phys_addr_t pa,
+				const char *alias)
+{
+	int offset;
+	u32 ph = find_or_alloc_phandle(fdt, alias, fdt_alloc_phandle(fdt));
+
+	offset = fdt_node_offset_by_compat_reg(fdt, prop, pa);
+	fdt_setprop(fdt, offset, "phy-handle", &ph, sizeof(ph));
+}
+
+/*
+ * Sets the specified node's status to the value contained in "status"
+ * If the first character of the specified path is "/" then we use
+ * alias as a path.  Otherwise, we look for an alias of that name
+ */
+static void fdt_set_node_status(void *fdt, const char *alias,
+			const char *status)
+{
+	const char *path = fdt_get_alias(fdt, alias);
+
+	if (!path)
+		path = alias;
+
+	do_fixup_by_path(fdt, path, "status", status, strlen(status) + 1, 1);
+}
+
+void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
+				enum fm_port port, int offset)
+{
+
+	if (mdio_mux[port] == EMI1_RGMII) {
+		fdt_set_phy_handle(blob, prop, pa, "phy_rgmii");
+	}
+
+	if (mdio_mux[port] == EMI1_SLOT3) {
+		int idx = port - FM2_DTSEC1 + 5;
+		char phy[16];
+
+		sprintf(phy, "phy%d_slot3", idx);
+
+		fdt_set_phy_handle(blob, prop, pa, phy);
+	}
+}
+
+void fdt_fixup_p4080ds_enet(void *fdt)
+{
+	int i;
+
+	/*
+	 * P4080DS can be configured in many different ways, supporting a number
+	 * of combinations of ethernet devices and phy types.  In order to
+	 * have just one device tree for all of those configurations, we fix up
+	 * the tree here.  By default, the device tree configures FM1 and FM2
+	 * for SGMII, and configures XAUI on both 10G interfaces.  So we have
+	 * a number of different variables to track:
+	 *
+	 * 1) Whether the device is configured at all.  Whichever devices are
+	 *    not enabled should be disabled by setting the "status" property
+	 *    to "disabled".
+	 * 2) What the PHY interface is.  If this is an RGMII connection,
+	 *    we should change the "phy-connection-type" property to
+	 *    "rgmii"
+	 * 3) Which PHY is being used.  Because the MDIO buses are muxed,
+	 *    we need to redirect the "phy-handle" property to point at the
+	 *    PHY on the right slot/bus.
+	 */
+
+	/* We've got six MDIO nodes that may or may not need to exist */
+	fdt_set_node_status(fdt, "emi1_slot3", "disabled");
+	fdt_set_node_status(fdt, "emi1_slot4", "disabled");
+	fdt_set_node_status(fdt, "emi1_slot5", "disabled");
+	fdt_set_node_status(fdt, "emi2_slot4", "disabled");
+	fdt_set_node_status(fdt, "emi2_slot5", "disabled");
+
+	for (i = 0; i < NUM_FM_PORTS; i++) {
+		switch(mdio_mux[i]) {
+		case EMI1_SLOT3:
+			fdt_set_node_status(fdt, "emi1_slot3", "okay");
+			break;
+		case EMI1_SLOT4:
+			fdt_set_node_status(fdt, "emi1_slot4", "okay");
+			break;
+		case EMI1_SLOT5:
+			fdt_set_node_status(fdt, "emi1_slot5", "okay");
+			break;
+		case EMI2_SLOT4:
+			fdt_set_node_status(fdt, "emi2_slot4", "okay");
+			break;
+		case EMI2_SLOT5:
+			fdt_set_node_status(fdt, "emi2_slot5", "okay");
+			break;
+		}
+	}
+}
+
+enum board_slots {
+	SLOT1 = 1,
+	SLOT2,
+	SLOT3,
+	SLOT4,
+	SLOT5,
+	SLOT6,
+};
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_FMAN_ENET
+	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR);
+	struct dtsec *tsec = (void *)CONFIG_SYS_FSL_FM1_DTSEC1_ADDR;
+	int i;
+
+	u8 lane_to_slot[] = {
+		SLOT1, /* 0 - Bank 1:A */
+		SLOT1, /* 1 - Bank 1:B */
+		SLOT2, /* 2 - Bank 1:C */
+		SLOT2, /* 3 - Bank 1:D */
+		SLOT3, /* 4 - Bank 1:E */
+		SLOT3, /* 5 - Bank 1:F */
+		SLOT3, /* 6 - Bank 1:G */
+		SLOT3, /* 7 - Bank 1:H */
+		SLOT6, /* 8 - Bank 1:I */
+		SLOT6, /* 9 - Bank 1:J */
+		SLOT4, /* 10 - Bank 2:A */
+		SLOT4, /* 11 - Bank 2:B */
+		SLOT4, /* 12 - Bank 2:C */
+		SLOT4, /* 13 - Bank 2:D */
+		SLOT5, /* 14 - Bank 3:A */
+		SLOT5, /* 15 - Bank 3:B */
+		SLOT5, /* 16 - Bank 3:C */
+		SLOT5, /* 17 - Bank 3:D */
+	};
+
+	/*
+	 * Set TBIPA on FM1 at DTSEC1.  This is needed for configurations
+	 * where FM1@DTSEC1 isn't used directly, since it provides
+	 * MDIO for other ports.
+	 */
+	out_be32(&tsec->tbipa, CONFIG_SYS_TBIPA_VALUE);
+
+	/* Initialize the mdio_mux array so we can recognize empty elements */
+	for (i = 0; i < NUM_FM_PORTS; i++)
+		mdio_mux[i] = EMI_NONE;
+
+	/* The first 4 GPIOs are outputs to control MDIO bus muxing */
+	out_be32(&pgpio->gpdir, EMI_MASK);
+
+	fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
+	fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
+	fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR);
+	fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
+	fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR);
+	fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR);
+	fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC3_PHY_ADDR);
+	fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC4_PHY_ADDR);
+	fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR);
+#endif
+
+	for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+		int idx = i - FM1_DTSEC1, lane, slot;
+		switch(fm_info_get_enet_if(i)) {
+		case SGMII:
+			lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
+			if (lane < 0)
+				break;
+			slot = lane_to_slot[lane];
+			switch (slot) {
+			case SLOT3:
+				mdio_mux[i] = EMI1_SLOT3;
+				break;
+			case SLOT4:
+				mdio_mux[i] = EMI1_SLOT4;
+				break;
+			case SLOT5:
+				mdio_mux[i] = EMI1_SLOT5;
+				break;
+			};
+			break;
+		case RGMII:
+			fm_info_set_phy_address(i, 0);
+			mdio_mux[i] = EMI1_RGMII;
+			break;
+		default:
+			break;
+		}
+	}
+
+	for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) {
+		int idx = i - FM1_10GEC1, lane, slot;
+		switch(fm_info_get_enet_if(i)) {
+		case XAUI:
+			lane = serdes_get_first_lane(XAUI_FM1 + idx);
+			if (lane < 0)
+				break;
+			slot = lane_to_slot[lane];
+			switch (slot) {
+			case SLOT4:
+				mdio_mux[i] = EMI2_SLOT4;
+				break;
+			case SLOT5:
+				mdio_mux[i] = EMI2_SLOT5;
+				break;
+			};
+			break;
+		default:
+			break;
+		}
+	}
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
+		int idx = i - FM2_DTSEC1, lane, slot;
+		switch(fm_info_get_enet_if(i)) {
+		case SGMII:
+			lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx);
+			if (lane < 0)
+				break;
+			slot = lane_to_slot[lane];
+			switch (slot) {
+			case SLOT3:
+				mdio_mux[i] = EMI1_SLOT3;
+				break;
+			case SLOT4:
+				mdio_mux[i] = EMI1_SLOT4;
+				break;
+			case SLOT5:
+				mdio_mux[i] = EMI1_SLOT5;
+				break;
+			};
+			break;
+		case RGMII:
+			fm_info_set_phy_address(i, 0);
+			mdio_mux[i] = EMI1_RGMII;
+			break;
+		default:
+			break;
+		}
+	}
+
+	for (i = FM2_10GEC1; i < FM2_10GEC1 + CONFIG_SYS_NUM_FM2_10GEC; i++) {
+		int idx = i - FM2_10GEC1, lane, slot;
+		switch(fm_info_get_enet_if(i)) {
+		case XAUI:
+			lane = serdes_get_first_lane(XAUI_FM2 + idx);
+			if (lane < 0)
+				break;
+			slot = lane_to_slot[lane];
+			switch (slot) {
+			case SLOT4:
+				mdio_mux[i] = EMI2_SLOT4;
+				break;
+			case SLOT5:
+				mdio_mux[i] = EMI2_SLOT5;
+				break;
+			};
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+
+	cpu_eth_init(bis);
+#endif /* CONFIG_FMAN_ENET */
+
+	return pci_eth_init(bis);
+}
-- 
1.6.4

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

* [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register
  2011-01-27  4:52           ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Mingkai Hu
@ 2011-01-27  4:52             ` Mingkai Hu
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
                                 ` (2 more replies)
  2011-01-27 17:42             ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Timur Tabi
  1 sibling, 3 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/tsec.c |  232 ++++++++++++++++++++++++++-------------------------
 include/tsec.h     |    6 +-
 2 files changed, 121 insertions(+), 117 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 9c8fe62..910cf9e 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -50,7 +50,7 @@ static int tsec_recv(struct eth_device *dev);
 static int tsec_init(struct eth_device *dev, bd_t * bd);
 static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info);
 static void tsec_halt(struct eth_device *dev);
-static void init_registers(volatile tsec_t * regs);
+static void init_registers(tsec_t * regs);
 static void startup_tsec(struct eth_device *dev);
 static int init_phy(struct eth_device *dev);
 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
@@ -166,9 +166,9 @@ static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
 	eth_register(dev);
 
 	/* Reset the MAC */
-	priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
+	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
-	priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
 	&& !defined(BITBANGMII)
@@ -190,16 +190,16 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 	char tmpbuf[MAC_ADDR_LEN];
 	int i;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Make sure the controller is stopped */
 	tsec_halt(dev);
 
 	/* Init MACCFG2.  Defaults to GMII */
-	regs->maccfg2 = MACCFG2_INIT_SETTINGS;
+	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
 
 	/* Init ECNTRL */
-	regs->ecntrl = ECNTRL_INIT_SETTINGS;
+	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
 
 	/* Copy the station address into the address registers.
 	 * Backwards, because little endian MACS are dumb */
@@ -209,11 +209,11 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
 		  tmpbuf[3];
 
-	regs->macstnaddr1 = tempval;
+	out_be32(&regs->macstnaddr1, tempval);
 
 	tempval = *((uint *) (tmpbuf + 4));
 
-	regs->macstnaddr2 = tempval;
+	out_be32(&regs->macstnaddr2, tempval);
 
 	/* reset the indices to zero */
 	rxIdx = 0;
@@ -230,17 +230,17 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 }
 
 /* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
+static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 		uint reg, uint value)
 {
 	int timeout = 1000000;
 
-	phyregs->miimadd = (addr << 8) | reg;
-	phyregs->miimcon = value;
+	out_be32(&phyregs->miimadd, (addr << 8) | reg);
+	out_be32(&phyregs->miimcon, value);
 	asm("sync");
 
 	timeout = 1000000;
-	while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ;
+	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--) ;
 }
 
 
@@ -254,28 +254,27 @@ static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
  */
-static uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs,
-				uint phyid, uint regnum)
+static uint tsec_local_mdio_read(tsec_mdio_t *phyregs, uint phyid, uint regnum)
 {
 	uint value;
 
 	/* Put the address of the phy, and the register
 	 * number into MIIMADD */
-	phyregs->miimadd = (phyid << 8) | regnum;
+	out_be32(&phyregs->miimadd, (phyid << 8) | regnum);
 
 	/* Clear the command register, and wait */
-	phyregs->miimcom = 0;
+	out_be32(&phyregs->miimcom, 0);
 	asm("sync");
 
 	/* Initiate a read command, and wait */
-	phyregs->miimcom = MIIM_READ_COMMAND;
+	out_be32(&phyregs->miimcom, MIIM_READ_COMMAND);
 	asm("sync");
 
 	/* Wait for the the indication that the read is done */
-	while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
+	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
 
 	/* Grab the value read from the PHY */
-	value = phyregs->miimstat;
+	value = in_be32(&phyregs->miimstat);
 
 	return value;
 }
@@ -321,18 +320,18 @@ static int init_phy(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	struct phy_info *curphy;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Assign a Physical address to the TBI */
-	regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
 	asm("sync");
 
 	/* Reset MII (due to new addresses) */
-	priv->phyregs->miimcfg = MIIMCFG_RESET;
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
 	asm("sync");
-	priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
 	asm("sync");
-	while (priv->phyregs->miimind & MIIMIND_BUSY) ;
+	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY) ;
 
 	/* Get the cmd structure corresponding to the attached
 	 * PHY */
@@ -345,7 +344,7 @@ static int init_phy(struct eth_device *dev)
 		return 0;
 	}
 
-	if (regs->ecntrl & ECNTRL_SGMII_MODE)
+	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
 		tsec_configure_serdes(priv);
 
 	priv->phyinfo = curphy;
@@ -838,16 +837,16 @@ static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
 static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
 {
 	uint phyid;
-	volatile tsec_mdio_t *regbase = priv->phyregs;
+	tsec_mdio_t *regbase = priv->phyregs;
 	int timeout = 1000000;
 
 	for (phyid = 0; phyid < 4; phyid++) {
-		regbase->miimadd = (phyid << 8) | mii_reg;
-		regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
+		out_be32(&regbase->miimadd, (phyid << 8) | mii_reg);
+		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
 		asm("sync");
 
 		timeout = 1000000;
-		while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
+		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--) ;
 	}
 
 	return MIIM_CIS8204_SLEDCON_INIT;
@@ -874,45 +873,45 @@ static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
  * those we don't care about (unless zero is bad, in which case,
  * choose a more appropriate value)
  */
-static void init_registers(volatile tsec_t * regs)
+static void init_registers(tsec_t * regs)
 {
 	/* Clear IEVENT */
-	regs->ievent = IEVENT_INIT_CLEAR;
-
-	regs->imask = IMASK_INIT_CLEAR;
-
-	regs->hash.iaddr0 = 0;
-	regs->hash.iaddr1 = 0;
-	regs->hash.iaddr2 = 0;
-	regs->hash.iaddr3 = 0;
-	regs->hash.iaddr4 = 0;
-	regs->hash.iaddr5 = 0;
-	regs->hash.iaddr6 = 0;
-	regs->hash.iaddr7 = 0;
-
-	regs->hash.gaddr0 = 0;
-	regs->hash.gaddr1 = 0;
-	regs->hash.gaddr2 = 0;
-	regs->hash.gaddr3 = 0;
-	regs->hash.gaddr4 = 0;
-	regs->hash.gaddr5 = 0;
-	regs->hash.gaddr6 = 0;
-	regs->hash.gaddr7 = 0;
-
-	regs->rctrl = 0x00000000;
+	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
+
+	out_be32(&regs->imask, IMASK_INIT_CLEAR);
+
+	out_be32(&regs->hash.iaddr0, 0);
+	out_be32(&regs->hash.iaddr1, 0);
+	out_be32(&regs->hash.iaddr2, 0);
+	out_be32(&regs->hash.iaddr3, 0);
+	out_be32(&regs->hash.iaddr4, 0);
+	out_be32(&regs->hash.iaddr5, 0);
+	out_be32(&regs->hash.iaddr6, 0);
+	out_be32(&regs->hash.iaddr7, 0);
+
+	out_be32(&regs->hash.gaddr0, 0);
+	out_be32(&regs->hash.gaddr1, 0);
+	out_be32(&regs->hash.gaddr2, 0);
+	out_be32(&regs->hash.gaddr3, 0);
+	out_be32(&regs->hash.gaddr4, 0);
+	out_be32(&regs->hash.gaddr5, 0);
+	out_be32(&regs->hash.gaddr6, 0);
+	out_be32(&regs->hash.gaddr7, 0);
+
+	out_be32(&regs->rctrl, 0x00000000);
 
 	/* Init RMON mib registers */
 	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
 
-	regs->rmon.cam1 = 0xffffffff;
-	regs->rmon.cam2 = 0xffffffff;
+	out_be32(&regs->rmon.cam1, 0xffffffff);
+	out_be32(&regs->rmon.cam2, 0xffffffff);
 
-	regs->mrblr = MRBLR_INIT_SETTINGS;
+	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
 
-	regs->minflr = MINFLR_INIT_SETTINGS;
+	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
 
-	regs->attr = ATTR_INIT_SETTINGS;
-	regs->attreli = ATTRELI_INIT_SETTINGS;
+	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
+	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
 
 }
 
@@ -922,44 +921,49 @@ static void init_registers(volatile tsec_t * regs)
 static void adjust_link(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
+	u32 ecntrl, maccfg2;
 
-	if (priv->link) {
-		if (priv->duplexity != 0)
-			regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
-		else
-			regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
+	if (!priv->link) {
+		printf("%s: No link.\n", dev->name);
+		return;
+	}
 
-		switch (priv->speed) {
-		case 1000:
-			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
-					 | MACCFG2_GMII);
-			break;
-		case 100:
-		case 10:
-			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
-					 | MACCFG2_MII);
+	/* clear all bits relative with interface mode */
+	ecntrl = in_be32(&regs->ecntrl);
+	ecntrl &= ~ECNTRL_R100;
 
-			/* Set R100 bit in all modes although
-			 * it is only used in RGMII mode
-			 */
-			if (priv->speed == 100)
-				regs->ecntrl |= ECNTRL_R100;
-			else
-				regs->ecntrl &= ~(ECNTRL_R100);
-			break;
-		default:
-			printf("%s: Speed was bad\n", dev->name);
-			break;
-		}
+	maccfg2 = in_be32(&regs->maccfg2);
+	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
 
-		printf("Speed: %d, %s duplex%s\n", priv->speed,
-		       (priv->duplexity) ? "full" : "half",
-		       (priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+	if (priv->duplexity)
+		maccfg2 |= MACCFG2_FULL_DUPLEX;
 
-	} else {
-		printf("%s: No link.\n", dev->name);
+	switch (priv->speed) {
+	case 1000:
+		maccfg2 |= MACCFG2_GMII;
+		break;
+	case 100:
+	case 10:
+		maccfg2 |= MACCFG2_MII;
+
+		/* Set R100 bit in all modes although
+		 * it is only used in RGMII mode
+		 */
+		if (priv->speed == 100)
+			ecntrl |= ECNTRL_R100;
+		break;
+	default:
+		printf("%s: Speed was bad\n", dev->name);
+		break;
 	}
+
+	out_be32(&regs->ecntrl, ecntrl);
+	out_be32(&regs->maccfg2, maccfg2);
+
+	printf("Speed: %d, %s duplex%s\n", priv->speed,
+			(priv->duplexity) ? "full" : "half",
+			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
 }
 
 /* Set up the buffers and their descriptors, and bring up the
@@ -969,11 +973,11 @@ static void startup_tsec(struct eth_device *dev)
 {
 	int i;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Point to the buffer descriptors */
-	regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
-	regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
+	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
 
 	/* Initialize the Rx Buffer descriptors */
 	for (i = 0; i < PKTBUFSRX; i++) {
@@ -998,13 +1002,13 @@ static void startup_tsec(struct eth_device *dev)
 	adjust_link(dev);
 
 	/* Enable Transmit and Receive */
-	regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
 
 	/* Tell the DMA it is clear to go */
-	regs->dmactrl |= DMACTRL_INIT_SETTINGS;
-	regs->tstat = TSTAT_CLEAR_THALT;
-	regs->rstat = RSTAT_CLEAR_RHALT;
-	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
 }
 
 /* This returns the status bits of the device.	The return value
@@ -1017,7 +1021,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
 	int i;
 	int result = 0;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Find an empty buffer descriptor */
 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
@@ -1033,7 +1037,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
 	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
 
 	/* Tell the DMA to go */
-	regs->tstat = TSTAT_CLEAR_THALT;
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
 
 	/* Wait for buffer to be transmitted */
 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
@@ -1053,7 +1057,7 @@ static int tsec_recv(struct eth_device *dev)
 {
 	int length;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
 
@@ -1076,9 +1080,9 @@ static int tsec_recv(struct eth_device *dev)
 		rxIdx = (rxIdx + 1) % PKTBUFSRX;
 	}
 
-	if (regs->ievent & IEVENT_BSY) {
-		regs->ievent = IEVENT_BSY;
-		regs->rstat = RSTAT_CLEAR_RHALT;
+	if (in_be32(&regs->ievent) & IEVENT_BSY) {
+		out_be32(&regs->ievent, IEVENT_BSY);
+		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
 	}
 
 	return -1;
@@ -1089,15 +1093,15 @@ static int tsec_recv(struct eth_device *dev)
 static void tsec_halt(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
-	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
-	regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
 
-	while ((regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))
+	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
 		!= (IEVENT_GRSC | IEVENT_GTSC)) ;
 
-	regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
+	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
 
 	/* Shut down the PHY, as needed */
 	if(priv->phyinfo)
@@ -1881,13 +1885,13 @@ static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
 {
 	int i;
 	uint result;
-	volatile tsec_mdio_t *phyregs = priv->phyregs;
+	tsec_mdio_t *phyregs = priv->phyregs;
 
-	phyregs->miimcfg = MIIMCFG_RESET;
+	out_be32(&phyregs->miimcfg, MIIMCFG_RESET);
 
-	phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+	out_be32(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
 
-	while (phyregs->miimind & MIIMIND_BUSY) ;
+	while (in_be32(&phyregs->miimind) & MIIMIND_BUSY) ;
 
 	for (i = 0; cmd->mii_reg != miim_end; i++) {
 		if (cmd->mii_data == miim_read) {
diff --git a/include/tsec.h b/include/tsec.h
index d56ec2c..6971b47 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -587,9 +587,9 @@ typedef struct tsec
 #define TSEC_FIBER	(1 << 3)	/* PHY uses fiber, eg 1000 Base-X */
 
 struct tsec_private {
-	volatile tsec_t *regs;
-	volatile tsec_mdio_t *phyregs;
-	volatile tsec_mdio_t *phyregs_sgmii;
+	tsec_t *regs;
+	tsec_mdio_t *phyregs;
+	tsec_mdio_t *phyregs_sgmii;
 	struct phy_info *phyinfo;
 	uint phyaddr;
 	u32 flags;
-- 
1.6.4

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

* [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration
  2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
@ 2011-01-27  4:52               ` Mingkai Hu
  2011-01-27  4:52                 ` [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t) Mingkai Hu
                                   ` (2 more replies)
  2011-02-02 22:47               ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Andy Fleming
  2011-02-05 20:26               ` Kumar Gala
  2 siblings, 3 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/tsec.c |  857 +++++++++++++++++++++++++---------------------------
 1 files changed, 416 insertions(+), 441 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 910cf9e..40f1c76 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -44,31 +44,6 @@ static RTXBD rtx __attribute__ ((aligned(8)));
 #error "rtx must be 64-bit aligned"
 #endif
 
-static int tsec_send(struct eth_device *dev,
-		     volatile void *packet, int length);
-static int tsec_recv(struct eth_device *dev);
-static int tsec_init(struct eth_device *dev, bd_t * bd);
-static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info);
-static void tsec_halt(struct eth_device *dev);
-static void init_registers(tsec_t * regs);
-static void startup_tsec(struct eth_device *dev);
-static int init_phy(struct eth_device *dev);
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
-uint read_phy_reg(struct tsec_private *priv, uint regnum);
-static struct phy_info *get_phy_info(struct eth_device *dev);
-static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
-static void adjust_link(struct eth_device *dev);
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-	&& !defined(BITBANGMII)
-static int tsec_miiphy_write(const char *devname, unsigned char addr,
-			     unsigned char reg, unsigned short value);
-static int tsec_miiphy_read(const char *devname, unsigned char addr,
-			    unsigned char reg, unsigned short *value);
-#endif
-#ifdef CONFIG_MCAST_TFTP
-static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
-#endif
-
 /* Default initializations for TSEC controllers. */
 
 static struct tsec_info_struct tsec_info[] = {
@@ -95,140 +70,6 @@ static struct tsec_info_struct tsec_info[] = {
 #endif
 };
 
-/*
- * Initialize all the TSEC devices
- *
- * Returns the number of TSEC devices that were initialized
- */
-int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
-{
-	int i;
-	int ret, count = 0;
-
-	for (i = 0; i < num; i++) {
-		ret = tsec_initialize(bis, &tsecs[i]);
-		if (ret > 0)
-			count += ret;
-	}
-
-	return count;
-}
-
-int tsec_standard_init(bd_t *bis)
-{
-	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
-}
-
-/* Initialize device structure. Returns success if PHY
- * initialization succeeded (i.e. if it recognizes the PHY)
- */
-static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
-{
-	struct eth_device *dev;
-	int i;
-	struct tsec_private *priv;
-
-	dev = (struct eth_device *)malloc(sizeof *dev);
-
-	if (NULL == dev)
-		return 0;
-
-	memset(dev, 0, sizeof *dev);
-
-	priv = (struct tsec_private *)malloc(sizeof(*priv));
-
-	if (NULL == priv)
-		return 0;
-
-	privlist[num_tsecs++] = priv;
-	priv->regs = tsec_info->regs;
-	priv->phyregs = tsec_info->miiregs;
-	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
-
-	priv->phyaddr = tsec_info->phyaddr;
-	priv->flags = tsec_info->flags;
-
-	sprintf(dev->name, tsec_info->devname);
-	dev->iobase = 0;
-	dev->priv = priv;
-	dev->init = tsec_init;
-	dev->halt = tsec_halt;
-	dev->send = tsec_send;
-	dev->recv = tsec_recv;
-#ifdef CONFIG_MCAST_TFTP
-	dev->mcast = tsec_mcast_addr;
-#endif
-
-	/* Tell u-boot to get the addr from the env */
-	for (i = 0; i < 6; i++)
-		dev->enetaddr[i] = 0;
-
-	eth_register(dev);
-
-	/* Reset the MAC */
-	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
-	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
-	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
-
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-	&& !defined(BITBANGMII)
-	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
-#endif
-
-	/* Try to initialize PHY here, and return */
-	return init_phy(dev);
-}
-
-/* Initializes data structures and registers for the controller,
- * and brings the interface up.	 Returns the link status, meaning
- * that it returns success if the link is up, failure otherwise.
- * This allows u-boot to find the first active controller.
- */
-static int tsec_init(struct eth_device *dev, bd_t * bd)
-{
-	uint tempval;
-	char tmpbuf[MAC_ADDR_LEN];
-	int i;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Make sure the controller is stopped */
-	tsec_halt(dev);
-
-	/* Init MACCFG2.  Defaults to GMII */
-	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
-
-	/* Init ECNTRL */
-	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
-
-	/* Copy the station address into the address registers.
-	 * Backwards, because little endian MACS are dumb */
-	for (i = 0; i < MAC_ADDR_LEN; i++) {
-		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
-	}
-	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
-		  tmpbuf[3];
-
-	out_be32(&regs->macstnaddr1, tempval);
-
-	tempval = *((uint *) (tmpbuf + 4));
-
-	out_be32(&regs->macstnaddr2, tempval);
-
-	/* reset the indices to zero */
-	rxIdx = 0;
-	txIdx = 0;
-
-	/* Clear out (for the most part) the other registers */
-	init_registers(regs);
-
-	/* Ready the device for tx/rx */
-	startup_tsec(dev);
-
-	/* If there's no link, fail */
-	return (priv->link ? 0 : -1);
-}
-
 /* Writes the given phy's reg with value, using the specified MDIO regs */
 static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 		uint reg, uint value)
@@ -243,7 +84,6 @@ static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--) ;
 }
 
-
 /* Provide the default behavior of writing the PHY of this ethernet device */
 #define write_phy_reg(priv, regnum, value) \
 	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
@@ -312,48 +152,6 @@ static void tsec_configure_serdes(struct tsec_private *priv)
 			CONFIG_TSEC_TBICR_SETTINGS);
 }
 
-/* Discover which PHY is attached to the device, and configure it
- * properly.  If the PHY is not recognized, then return 0
- * (failure).  Otherwise, return 1
- */
-static int init_phy(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	struct phy_info *curphy;
-	tsec_t *regs = priv->regs;
-
-	/* Assign a Physical address to the TBI */
-	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
-	asm("sync");
-
-	/* Reset MII (due to new addresses) */
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
-	asm("sync");
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-	asm("sync");
-	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY) ;
-
-	/* Get the cmd structure corresponding to the attached
-	 * PHY */
-	curphy = get_phy_info(dev);
-
-	if (curphy == NULL) {
-		priv->phyinfo = NULL;
-		printf("%s: No PHY found\n", dev->name);
-
-		return 0;
-	}
-
-	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
-		tsec_configure_serdes(priv);
-
-	priv->phyinfo = curphy;
-
-	phy_run_commands(priv, priv->phyinfo->config);
-
-	return 1;
-}
-
 /*
  * Returns which value to write to the control register.
  * For 10/100, the value is slightly different
@@ -869,245 +667,6 @@ static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
 	return mii_data;
 }
 
-/* Initialized required registers to appropriate values, zeroing
- * those we don't care about (unless zero is bad, in which case,
- * choose a more appropriate value)
- */
-static void init_registers(tsec_t * regs)
-{
-	/* Clear IEVENT */
-	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
-
-	out_be32(&regs->imask, IMASK_INIT_CLEAR);
-
-	out_be32(&regs->hash.iaddr0, 0);
-	out_be32(&regs->hash.iaddr1, 0);
-	out_be32(&regs->hash.iaddr2, 0);
-	out_be32(&regs->hash.iaddr3, 0);
-	out_be32(&regs->hash.iaddr4, 0);
-	out_be32(&regs->hash.iaddr5, 0);
-	out_be32(&regs->hash.iaddr6, 0);
-	out_be32(&regs->hash.iaddr7, 0);
-
-	out_be32(&regs->hash.gaddr0, 0);
-	out_be32(&regs->hash.gaddr1, 0);
-	out_be32(&regs->hash.gaddr2, 0);
-	out_be32(&regs->hash.gaddr3, 0);
-	out_be32(&regs->hash.gaddr4, 0);
-	out_be32(&regs->hash.gaddr5, 0);
-	out_be32(&regs->hash.gaddr6, 0);
-	out_be32(&regs->hash.gaddr7, 0);
-
-	out_be32(&regs->rctrl, 0x00000000);
-
-	/* Init RMON mib registers */
-	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
-
-	out_be32(&regs->rmon.cam1, 0xffffffff);
-	out_be32(&regs->rmon.cam2, 0xffffffff);
-
-	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
-
-	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
-
-	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
-	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
-
-}
-
-/* Configure maccfg2 based on negotiated speed and duplex
- * reported by PHY handling code
- */
-static void adjust_link(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-	u32 ecntrl, maccfg2;
-
-	if (!priv->link) {
-		printf("%s: No link.\n", dev->name);
-		return;
-	}
-
-	/* clear all bits relative with interface mode */
-	ecntrl = in_be32(&regs->ecntrl);
-	ecntrl &= ~ECNTRL_R100;
-
-	maccfg2 = in_be32(&regs->maccfg2);
-	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
-
-	if (priv->duplexity)
-		maccfg2 |= MACCFG2_FULL_DUPLEX;
-
-	switch (priv->speed) {
-	case 1000:
-		maccfg2 |= MACCFG2_GMII;
-		break;
-	case 100:
-	case 10:
-		maccfg2 |= MACCFG2_MII;
-
-		/* Set R100 bit in all modes although
-		 * it is only used in RGMII mode
-		 */
-		if (priv->speed == 100)
-			ecntrl |= ECNTRL_R100;
-		break;
-	default:
-		printf("%s: Speed was bad\n", dev->name);
-		break;
-	}
-
-	out_be32(&regs->ecntrl, ecntrl);
-	out_be32(&regs->maccfg2, maccfg2);
-
-	printf("Speed: %d, %s duplex%s\n", priv->speed,
-			(priv->duplexity) ? "full" : "half",
-			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
-}
-
-/* Set up the buffers and their descriptors, and bring up the
- * interface
- */
-static void startup_tsec(struct eth_device *dev)
-{
-	int i;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Point to the buffer descriptors */
-	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
-	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
-
-	/* Initialize the Rx Buffer descriptors */
-	for (i = 0; i < PKTBUFSRX; i++) {
-		rtx.rxbd[i].status = RXBD_EMPTY;
-		rtx.rxbd[i].length = 0;
-		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
-	}
-	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
-
-	/* Initialize the TX Buffer Descriptors */
-	for (i = 0; i < TX_BUF_CNT; i++) {
-		rtx.txbd[i].status = 0;
-		rtx.txbd[i].length = 0;
-		rtx.txbd[i].bufPtr = 0;
-	}
-	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
-
-	/* Start up the PHY */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->startup);
-
-	adjust_link(dev);
-
-	/* Enable Transmit and Receive */
-	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
-
-	/* Tell the DMA it is clear to go */
-	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
-	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
-	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
-	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-}
-
-/* This returns the status bits of the device.	The return value
- * is never checked, and this is what the 8260 driver did, so we
- * do the same.	 Presumably, this would be zero if there were no
- * errors
- */
-static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
-{
-	int i;
-	int result = 0;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Find an empty buffer descriptor */
-	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-		if (i >= TOUT_LOOP) {
-			debug("%s: tsec: tx buffers full\n", dev->name);
-			return result;
-		}
-	}
-
-	rtx.txbd[txIdx].bufPtr = (uint) packet;
-	rtx.txbd[txIdx].length = length;
-	rtx.txbd[txIdx].status |=
-	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
-
-	/* Tell the DMA to go */
-	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
-
-	/* Wait for buffer to be transmitted */
-	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-		if (i >= TOUT_LOOP) {
-			debug("%s: tsec: tx error\n", dev->name);
-			return result;
-		}
-	}
-
-	txIdx = (txIdx + 1) % TX_BUF_CNT;
-	result = rtx.txbd[txIdx].status & TXBD_STATS;
-
-	return result;
-}
-
-static int tsec_recv(struct eth_device *dev)
-{
-	int length;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
-
-		length = rtx.rxbd[rxIdx].length;
-
-		/* Send the packet up if there were no errors */
-		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
-			NetReceive(NetRxPackets[rxIdx], length - 4);
-		} else {
-			printf("Got error %x\n",
-			       (rtx.rxbd[rxIdx].status & RXBD_STATS));
-		}
-
-		rtx.rxbd[rxIdx].length = 0;
-
-		/* Set the wrap bit if this is the last element in the list */
-		rtx.rxbd[rxIdx].status =
-		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
-
-		rxIdx = (rxIdx + 1) % PKTBUFSRX;
-	}
-
-	if (in_be32(&regs->ievent) & IEVENT_BSY) {
-		out_be32(&regs->ievent, IEVENT_BSY);
-		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
-	}
-
-	return -1;
-
-}
-
-/* Stop the interface */
-static void tsec_halt(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-
-	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
-		!= (IEVENT_GRSC | IEVENT_GTSC)) ;
-
-	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
-
-	/* Shut down the PHY, as needed */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->shutdown);
-}
-
 static struct phy_info phy_info_M88E1149S = {
 	0x1410ca,
 	"Marvell 88E1149S",
@@ -2003,3 +1562,419 @@ tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
 	return 0;
 }
 #endif /* Multicast TFTP ? */
+
+/* Initialized required registers to appropriate values, zeroing
+ * those we don't care about (unless zero is bad, in which case,
+ * choose a more appropriate value)
+ */
+static void init_registers(tsec_t * regs)
+{
+	/* Clear IEVENT */
+	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
+
+	out_be32(&regs->imask, IMASK_INIT_CLEAR);
+
+	out_be32(&regs->hash.iaddr0, 0);
+	out_be32(&regs->hash.iaddr1, 0);
+	out_be32(&regs->hash.iaddr2, 0);
+	out_be32(&regs->hash.iaddr3, 0);
+	out_be32(&regs->hash.iaddr4, 0);
+	out_be32(&regs->hash.iaddr5, 0);
+	out_be32(&regs->hash.iaddr6, 0);
+	out_be32(&regs->hash.iaddr7, 0);
+
+	out_be32(&regs->hash.gaddr0, 0);
+	out_be32(&regs->hash.gaddr1, 0);
+	out_be32(&regs->hash.gaddr2, 0);
+	out_be32(&regs->hash.gaddr3, 0);
+	out_be32(&regs->hash.gaddr4, 0);
+	out_be32(&regs->hash.gaddr5, 0);
+	out_be32(&regs->hash.gaddr6, 0);
+	out_be32(&regs->hash.gaddr7, 0);
+
+	out_be32(&regs->rctrl, 0x00000000);
+
+	/* Init RMON mib registers */
+	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
+
+	out_be32(&regs->rmon.cam1, 0xffffffff);
+	out_be32(&regs->rmon.cam2, 0xffffffff);
+
+	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
+
+	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
+
+	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
+	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
+
+}
+
+/* Configure maccfg2 based on negotiated speed and duplex
+ * reported by PHY handling code
+ */
+static void adjust_link(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+	u32 ecntrl, maccfg2;
+
+	if (!priv->link) {
+		printf("%s: No link.\n", dev->name);
+		return;
+	}
+
+	/* clear all bits relative with interface mode */
+	ecntrl = in_be32(&regs->ecntrl);
+	ecntrl &= ~ECNTRL_R100;
+
+	maccfg2 = in_be32(&regs->maccfg2);
+	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
+
+	if (priv->duplexity)
+		maccfg2 |= MACCFG2_FULL_DUPLEX;
+
+	switch (priv->speed) {
+	case 1000:
+		maccfg2 |= MACCFG2_GMII;
+		break;
+	case 100:
+	case 10:
+		maccfg2 |= MACCFG2_MII;
+
+		/* Set R100 bit in all modes although
+		 * it is only used in RGMII mode
+		 */
+		if (priv->speed == 100)
+			ecntrl |= ECNTRL_R100;
+		break;
+	default:
+		printf("%s: Speed was bad\n", dev->name);
+		break;
+	}
+
+	out_be32(&regs->ecntrl, ecntrl);
+	out_be32(&regs->maccfg2, maccfg2);
+
+	printf("Speed: %d, %s duplex%s\n", priv->speed,
+			(priv->duplexity) ? "full" : "half",
+			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+}
+
+/* Set up the buffers and their descriptors, and bring up the
+ * interface
+ */
+static void startup_tsec(struct eth_device *dev)
+{
+	int i;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Point to the buffer descriptors */
+	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
+	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
+
+	/* Initialize the Rx Buffer descriptors */
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rtx.rxbd[i].status = RXBD_EMPTY;
+		rtx.rxbd[i].length = 0;
+		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
+	}
+	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
+
+	/* Initialize the TX Buffer Descriptors */
+	for (i = 0; i < TX_BUF_CNT; i++) {
+		rtx.txbd[i].status = 0;
+		rtx.txbd[i].length = 0;
+		rtx.txbd[i].bufPtr = 0;
+	}
+	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
+
+	/* Start up the PHY */
+	if(priv->phyinfo)
+		phy_run_commands(priv, priv->phyinfo->startup);
+
+	adjust_link(dev);
+
+	/* Enable Transmit and Receive */
+	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
+
+	/* Tell the DMA it is clear to go */
+	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+}
+
+/* This returns the status bits of the device.	The return value
+ * is never checked, and this is what the 8260 driver did, so we
+ * do the same.	 Presumably, this would be zero if there were no
+ * errors
+ */
+static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
+{
+	int i;
+	int result = 0;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Find an empty buffer descriptor */
+	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+		if (i >= TOUT_LOOP) {
+			debug("%s: tsec: tx buffers full\n", dev->name);
+			return result;
+		}
+	}
+
+	rtx.txbd[txIdx].bufPtr = (uint) packet;
+	rtx.txbd[txIdx].length = length;
+	rtx.txbd[txIdx].status |=
+	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+
+	/* Tell the DMA to go */
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+
+	/* Wait for buffer to be transmitted */
+	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+		if (i >= TOUT_LOOP) {
+			debug("%s: tsec: tx error\n", dev->name);
+			return result;
+		}
+	}
+
+	txIdx = (txIdx + 1) % TX_BUF_CNT;
+	result = rtx.txbd[txIdx].status & TXBD_STATS;
+
+	return result;
+}
+
+static int tsec_recv(struct eth_device *dev)
+{
+	int length;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
+
+		length = rtx.rxbd[rxIdx].length;
+
+		/* Send the packet up if there were no errors */
+		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
+			NetReceive(NetRxPackets[rxIdx], length - 4);
+		} else {
+			printf("Got error %x\n",
+			       (rtx.rxbd[rxIdx].status & RXBD_STATS));
+		}
+
+		rtx.rxbd[rxIdx].length = 0;
+
+		/* Set the wrap bit if this is the last element in the list */
+		rtx.rxbd[rxIdx].status =
+		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+
+		rxIdx = (rxIdx + 1) % PKTBUFSRX;
+	}
+
+	if (in_be32(&regs->ievent) & IEVENT_BSY) {
+		out_be32(&regs->ievent, IEVENT_BSY);
+		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	}
+
+	return -1;
+
+}
+
+/* Stop the interface */
+static void tsec_halt(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+
+	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
+		!= (IEVENT_GRSC | IEVENT_GTSC)) ;
+
+	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
+
+	/* Shut down the PHY, as needed */
+	if(priv->phyinfo)
+		phy_run_commands(priv, priv->phyinfo->shutdown);
+}
+
+/* Initializes data structures and registers for the controller,
+ * and brings the interface up.	 Returns the link status, meaning
+ * that it returns success if the link is up, failure otherwise.
+ * This allows u-boot to find the first active controller.
+ */
+static int tsec_init(struct eth_device *dev, bd_t * bd)
+{
+	uint tempval;
+	char tmpbuf[MAC_ADDR_LEN];
+	int i;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Make sure the controller is stopped */
+	tsec_halt(dev);
+
+	/* Init MACCFG2.  Defaults to GMII */
+	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
+
+	/* Init ECNTRL */
+	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
+
+	/* Copy the station address into the address registers.
+	 * Backwards, because little endian MACS are dumb */
+	for (i = 0; i < MAC_ADDR_LEN; i++) {
+		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
+	}
+	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
+		  tmpbuf[3];
+
+	out_be32(&regs->macstnaddr1, tempval);
+
+	tempval = *((uint *) (tmpbuf + 4));
+
+	out_be32(&regs->macstnaddr2, tempval);
+
+	/* reset the indices to zero */
+	rxIdx = 0;
+	txIdx = 0;
+
+	/* Clear out (for the most part) the other registers */
+	init_registers(regs);
+
+	/* Ready the device for tx/rx */
+	startup_tsec(dev);
+
+	/* If there's no link, fail */
+	return (priv->link ? 0 : -1);
+}
+
+/* Discover which PHY is attached to the device, and configure it
+ * properly.  If the PHY is not recognized, then return 0
+ * (failure).  Otherwise, return 1
+ */
+static int init_phy(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	struct phy_info *curphy;
+	tsec_t *regs = priv->regs;
+
+	/* Assign a Physical address to the TBI */
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+	asm("sync");
+
+	/* Reset MII (due to new addresses) */
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
+	asm("sync");
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
+	asm("sync");
+	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY) ;
+
+	/* Get the cmd structure corresponding to the attached
+	 * PHY */
+	curphy = get_phy_info(dev);
+
+	if (curphy == NULL) {
+		priv->phyinfo = NULL;
+		printf("%s: No PHY found\n", dev->name);
+
+		return 0;
+	}
+
+	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
+		tsec_configure_serdes(priv);
+
+	priv->phyinfo = curphy;
+
+	phy_run_commands(priv, priv->phyinfo->config);
+
+	return 1;
+}
+
+/* Initialize device structure. Returns success if PHY
+ * initialization succeeded (i.e. if it recognizes the PHY)
+ */
+static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
+{
+	struct eth_device *dev;
+	int i;
+	struct tsec_private *priv;
+
+	dev = (struct eth_device *)malloc(sizeof *dev);
+
+	if (NULL == dev)
+		return 0;
+
+	memset(dev, 0, sizeof *dev);
+
+	priv = (struct tsec_private *)malloc(sizeof(*priv));
+
+	if (NULL == priv)
+		return 0;
+
+	privlist[num_tsecs++] = priv;
+	priv->regs = tsec_info->regs;
+	priv->phyregs = tsec_info->miiregs;
+	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
+
+	priv->phyaddr = tsec_info->phyaddr;
+	priv->flags = tsec_info->flags;
+
+	sprintf(dev->name, tsec_info->devname);
+	dev->iobase = 0;
+	dev->priv = priv;
+	dev->init = tsec_init;
+	dev->halt = tsec_halt;
+	dev->send = tsec_send;
+	dev->recv = tsec_recv;
+#ifdef CONFIG_MCAST_TFTP
+	dev->mcast = tsec_mcast_addr;
+#endif
+
+	/* Tell u-boot to get the addr from the env */
+	for (i = 0; i < 6; i++)
+		dev->enetaddr[i] = 0;
+
+	eth_register(dev);
+
+	/* Reset the MAC */
+	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
+	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+	&& !defined(BITBANGMII)
+	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
+#endif
+
+	/* Try to initialize PHY here, and return */
+	return init_phy(dev);
+}
+
+/*
+ * Initialize all the TSEC devices
+ *
+ * Returns the number of TSEC devices that were initialized
+ */
+int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
+{
+	int i;
+	int ret, count = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = tsec_initialize(bis, &tsecs[i]);
+		if (ret > 0)
+			count += ret;
+	}
+
+	return count;
+}
+
+int tsec_standard_init(bd_t *bis)
+{
+	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
+}
+
-- 
1.6.4

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

* [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t)
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
@ 2011-01-27  4:52                 ` Mingkai Hu
  2011-01-27  4:52                   ` [U-Boot] [PATCH 10/14] tsec: refactor the PHY code to make it reuseable Mingkai Hu
  2011-02-02 22:48                 ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Andy Fleming
  2011-02-05 20:26                 ` Kumar Gala
  2 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

This will pave the way to move the PHY code to fsl_phy.c which
will be reused by all other code.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/tsec.c |   10 +++++-----
 include/tsec.h     |   35 +++++++++++------------------------
 2 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 40f1c76..ac65c43 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -56,7 +56,7 @@ static struct tsec_info_struct tsec_info[] = {
 #ifdef CONFIG_MPC85XX_FEC
 	{
 		.regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
-		.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR),
+		.miiregs = (tsec_mii_t *)(MDIO_BASE_ADDR + 0x520),
 		.devname = CONFIG_MPC85XX_FEC_NAME,
 		.phyaddr = FEC_PHY_ADDR,
 		.flags = FEC_FLAGS
@@ -71,7 +71,7 @@ static struct tsec_info_struct tsec_info[] = {
 };
 
 /* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
+static void tsec_local_mdio_write(tsec_mii_t *phyregs, uint addr,
 		uint reg, uint value)
 {
 	int timeout = 1000000;
@@ -94,7 +94,7 @@ static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
  */
-static uint tsec_local_mdio_read(tsec_mdio_t *phyregs, uint phyid, uint regnum)
+static uint tsec_local_mdio_read(tsec_mii_t *phyregs, uint phyid, uint regnum)
 {
 	uint value;
 
@@ -635,7 +635,7 @@ static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
 static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
 {
 	uint phyid;
-	tsec_mdio_t *regbase = priv->phyregs;
+	tsec_mii_t *regbase = priv->phyregs;
 	int timeout = 1000000;
 
 	for (phyid = 0; phyid < 4; phyid++) {
@@ -1444,7 +1444,7 @@ static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
 {
 	int i;
 	uint result;
-	tsec_mdio_t *phyregs = priv->phyregs;
+	tsec_mii_t *phyregs = priv->phyregs;
 
 	out_be32(&phyregs->miimcfg, MIIMCFG_RESET);
 
diff --git a/include/tsec.h b/include/tsec.h
index 6971b47..054e5cf 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -19,15 +19,18 @@
 
 #include <net.h>
 #include <config.h>
+#include <asm/fsl_enet.h>
 
 #define TSEC_SIZE 		0x01000
 #define TSEC_MDIO_OFFSET	0x01000
 
+#define CONFIG_SYS_MDIO_BASE_ADDR (TSEC_BASE_ADDR + 0x520)
+
 #define STD_TSEC_INFO(num) \
 {			\
 	.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)), \
-	.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR), \
-	.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
+	.miiregs = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR), \
+	.miiregs_sgmii = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR \
 					 + (num - 1) * TSEC_MDIO_OFFSET), \
 	.devname = CONFIG_TSEC##num##_NAME, \
 	.phyaddr = TSEC##num##_PHY_ADDR, \
@@ -37,8 +40,8 @@
 #define SET_STD_TSEC_INFO(x, num) \
 {			\
 	x.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)); \
-	x.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR); \
-	x.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
+	x.miiregs = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR); \
+	x.miiregs_sgmii = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR \
 					  + (num - 1) * TSEC_MDIO_OFFSET); \
 	x.devname = CONFIG_TSEC##num##_NAME; \
 	x.phyaddr = TSEC##num##_PHY_ADDR; \
@@ -467,22 +470,6 @@ typedef struct tsec_hash_regs
 	uint	res2[24];
 } tsec_hash_t;
 
-typedef struct tsec_mdio {
-	uint	res1[4];
-	uint	ieventm;
-	uint	imaskm;
-	uint	res2;
-	uint	emapm;
-	uint	res3[320];
-	uint	miimcfg;	/* MII Management: Configuration */
-	uint	miimcom;	/* MII Management: Command */
-	uint	miimadd;	/* MII Management: Address */
-	uint	miimcon;	/* MII Management: Control */
-	uint	miimstat;	/* MII Management: Status */
-	uint	miimind;	/* MII Management: Indicators */
-	uint	res4[690];
-} tsec_mdio_t;
-
 typedef struct tsec
 {
 	/* General Control and Status Registers (0x2_n000) */
@@ -588,8 +575,8 @@ typedef struct tsec
 
 struct tsec_private {
 	tsec_t *regs;
-	tsec_mdio_t *phyregs;
-	tsec_mdio_t *phyregs_sgmii;
+	tsec_mii_t *phyregs;
+	tsec_mii_t *phyregs_sgmii;
 	struct phy_info *phyinfo;
 	uint phyaddr;
 	u32 flags;
@@ -648,8 +635,8 @@ struct phy_info {
 
 struct tsec_info_struct {
 	tsec_t *regs;
-	tsec_mdio_t *miiregs;
-	tsec_mdio_t *miiregs_sgmii;
+	tsec_mii_t *miiregs;
+	tsec_mii_t *miiregs_sgmii;
 	char *devname;
 	unsigned int phyaddr;
 	u32 flags;
-- 
1.6.4

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

* [U-Boot] [PATCH 10/14] tsec: refactor the PHY code to make it reuseable
  2011-01-27  4:52                 ` [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t) Mingkai Hu
@ 2011-01-27  4:52                   ` Mingkai Hu
  2011-01-27  4:52                     ` [U-Boot] [PATCH 11/14] PHY: add some Vitesse phy support Mingkai Hu
  0 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Also remove the PHY code which will be added by the
following patches.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/Makefile |    2 +-
 drivers/net/tsec.c   | 1483 +++-----------------------------------------------
 include/tsec.h       |  246 +---------
 3 files changed, 70 insertions(+), 1661 deletions(-)

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3810665..42fa327 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -79,7 +79,7 @@ COBJS-$(CONFIG_TIGON3) += tigon3.o
 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
+COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_phy.o
 COBJS-$(CONFIG_FMAN_ENET) += fsl_phy.o
 COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 COBJS-$(CONFIG_ULI526X) += uli526x.o
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index ac65c43..6ed3e09 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -20,6 +20,7 @@
 #include <asm/errno.h>
 
 #include "miiphy.h"
+#include "fsl_phy.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -70,59 +71,6 @@ static struct tsec_info_struct tsec_info[] = {
 #endif
 };
 
-/* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(tsec_mii_t *phyregs, uint addr,
-		uint reg, uint value)
-{
-	int timeout = 1000000;
-
-	out_be32(&phyregs->miimadd, (addr << 8) | reg);
-	out_be32(&phyregs->miimcon, value);
-	asm("sync");
-
-	timeout = 1000000;
-	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--) ;
-}
-
-/* Provide the default behavior of writing the PHY of this ethernet device */
-#define write_phy_reg(priv, regnum, value) \
-	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
-
-/* Reads register regnum on the device's PHY through the
- * specified registers.	 It lowers and raises the read
- * command, and waits for the data to become valid (miimind
- * notvalid bit cleared), and the bus to cease activity (miimind
- * busy bit cleared), and then returns the value
- */
-static uint tsec_local_mdio_read(tsec_mii_t *phyregs, uint phyid, uint regnum)
-{
-	uint value;
-
-	/* Put the address of the phy, and the register
-	 * number into MIIMADD */
-	out_be32(&phyregs->miimadd, (phyid << 8) | regnum);
-
-	/* Clear the command register, and wait */
-	out_be32(&phyregs->miimcom, 0);
-	asm("sync");
-
-	/* Initiate a read command, and wait */
-	out_be32(&phyregs->miimcom, MIIM_READ_COMMAND);
-	asm("sync");
-
-	/* Wait for the the indication that the read is done */
-	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
-
-	/* Grab the value read from the PHY */
-	value = in_be32(&phyregs->miimstat);
-
-	return value;
-}
-
-/* #define to provide old read_phy_reg functionality without duplicating code */
-#define read_phy_reg(priv,regnum) \
-	tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum)
-
 #define TBIANA_SETTINGS ( \
 		TBIANA_ASYMMETRIC_PAUSE \
 		| TBIANA_SYMMETRIC_PAUSE \
@@ -144,1332 +92,12 @@ static void tsec_configure_serdes(struct tsec_private *priv)
 {
 	/* Access TBI PHY registers at given TSEC register offset as opposed
 	 * to the register offset used for external PHY accesses */
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_ANA,
-			TBIANA_SETTINGS);
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_TBICON,
-			TBICON_CLK_SELECT);
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_CR,
-			CONFIG_TSEC_TBICR_SETTINGS);
-}
-
-/*
- * Returns which value to write to the control register.
- * For 10/100, the value is slightly different
- */
-static uint mii_cr_init(uint mii_reg, struct tsec_private * priv)
-{
-	if (priv->flags & TSEC_GIGABIT)
-		return MIIM_CONTROL_INIT;
-	else
-		return MIIM_CR_INIT;
-}
-
-/*
- * Wait for auto-negotiation to complete, then determine link
- */
-static uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
-{
-	/*
-	 * Wait if the link is up, and autonegotiation is in progress
-	 * (ie - we're capable and it's not done)
-	 */
-	mii_reg = read_phy_reg(priv, MIIM_STATUS);
-	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
-		int i = 0;
-
-		puts("Waiting for PHY auto negotiation to complete");
-		while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
-			/*
-			 * Timeout reached ?
-			 */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				return 0;
-			}
-
-			if (ctrlc()) {
-				puts("user interrupt!\n");
-				priv->link = 0;
-				return -EINTR;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_STATUS);
-		}
-		puts(" done\n");
-
-		/* Link status bit is latched low, read it again */
-		mii_reg = read_phy_reg(priv, MIIM_STATUS);
-
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	}
-
-	priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0;
-
-	return 0;
-}
-
-/* Generic function which updates the speed and duplex.  If
- * autonegotiation is enabled, it uses the AND of the link
- * partner's advertised capabilities and our advertised
- * capabilities.  If autonegotiation is disabled, we use the
- * appropriate bits in the control register.
- *
- * Stolen from Linux's mii.c and phy_device.c
- */
-static uint mii_parse_link(uint mii_reg, struct tsec_private *priv)
-{
-	/* We're using autonegotiation */
-	if (mii_reg & BMSR_ANEGCAPABLE) {
-		uint lpa = 0;
-		uint gblpa = 0;
-
-		/* Check for gigabit capability */
-		if (mii_reg & BMSR_ERCAP) {
-			/* We want a list of states supported by
-			 * both PHYs in the link
-			 */
-			gblpa = read_phy_reg(priv, MII_STAT1000);
-			gblpa &= read_phy_reg(priv, MII_CTRL1000) << 2;
-		}
-
-		/* Set the baseline so we only have to set them
-		 * if they're different
-		 */
-		priv->speed = 10;
-		priv->duplexity = 0;
-
-		/* Check the gigabit fields */
-		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
-			priv->speed = 1000;
-
-			if (gblpa & PHY_1000BTSR_1000FD)
-				priv->duplexity = 1;
-
-			/* We're done! */
-			return 0;
-		}
-
-		lpa = read_phy_reg(priv, MII_ADVERTISE);
-		lpa &= read_phy_reg(priv, MII_LPA);
-
-		if (lpa & (LPA_100FULL | LPA_100HALF)) {
-			priv->speed = 100;
-
-			if (lpa & LPA_100FULL)
-				priv->duplexity = 1;
-
-		} else if (lpa & LPA_10FULL)
-			priv->duplexity = 1;
-	} else {
-		uint bmcr = read_phy_reg(priv, MII_BMCR);
-
-		priv->speed = 10;
-		priv->duplexity = 0;
-
-		if (bmcr & BMCR_FULLDPLX)
-			priv->duplexity = 1;
-
-		if (bmcr & BMCR_SPEED1000)
-			priv->speed = 1000;
-		else if (bmcr & BMCR_SPEED100)
-			priv->speed = 100;
-	}
-
-	return 0;
-}
-
-/*
- * "Ethernet at Wirespeed" needs to be enabled to achieve link in certain
- * circumstances.  eg a gigabit TSEC connected to a gigabit switch with
- * a 4-wire ethernet cable.  Both ends advertise gigabit, but can't
- * link.  "Ethernet at Wirespeed" reduces advertised speed until link
- * can be achieved.
- */
-static uint mii_BCM54xx_wirespeed(uint mii_reg, struct tsec_private *priv)
-{
-	return (read_phy_reg(priv, mii_reg) & 0x8FFF) | 0x8010;
-}
-
-/*
- * Parse the BCM54xx status register for speed and duplex information.
- * The linux sungem_phy has this information, but in a table format.
- */
-static uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv)
-{
-	/* If there is no link, speed and duplex don't matter */
-	if (!priv->link)
-		return 0;
-
-	switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
-		MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
-	case 1:
-		priv->duplexity = 0;
-		priv->speed = 10;
-		break;
-	case 2:
-		priv->duplexity = 1;
-		priv->speed = 10;
-		break;
-	case 3:
-		priv->duplexity = 0;
-		priv->speed = 100;
-		break;
-	case 5:
-		priv->duplexity = 1;
-		priv->speed = 100;
-		break;
-	case 6:
-		priv->duplexity = 0;
-		priv->speed = 1000;
-		break;
-	case 7:
-		priv->duplexity = 1;
-		priv->speed = 1000;
-		break;
-	default:
-		printf("Auto-neg error, defaulting to 10BT/HD\n");
-		priv->duplexity = 0;
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/*
- * Find out if PHY is in copper or serdes mode by looking at Expansion Reg
- * 0x42 - "Operating Mode Status Register"
- */
-static int BCM8482_is_serdes(struct tsec_private *priv)
-{
-	u16 val;
-	int serdes = 0;
-
-	write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_ER | 0x42);
-	val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA);
-
-	switch (val & 0x1f) {
-	case 0x0d:	/* RGMII-to-100Base-FX */
-	case 0x0e:	/* RGMII-to-SGMII */
-	case 0x0f:	/* RGMII-to-SerDes */
-	case 0x12:	/* SGMII-to-SerDes */
-	case 0x13:	/* SGMII-to-100Base-FX */
-	case 0x16:	/* SerDes-to-Serdes */
-		serdes = 1;
-		break;
-	case 0x6:	/* RGMII-to-Copper */
-	case 0x14:	/* SGMII-to-Copper */
-	case 0x17:	/* SerDes-to-Copper */
-		break;
-	default:
-		printf("ERROR, invalid PHY mode (0x%x\n)", val);
-		break;
-	}
-
-	return serdes;
-}
-
-/*
- * Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating
- * Mode Status Register"
- */
-uint mii_parse_BCM5482_serdes_sr(struct tsec_private *priv)
-{
-	u16 val;
-	int i = 0;
-
-	/* Wait 1s for link - Clause 37 autonegotiation happens very fast */
-	while (1) {
-		write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL,
-				MIIM_BCM54XX_EXP_SEL_ER | 0x42);
-		val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA);
-
-		if (val & 0x8000)
-			break;
-
-		if (i++ > 1000) {
-			priv->link = 0;
-			return 1;
-		}
-
-		udelay(1000);	/* 1 ms */
-	}
-
-	priv->link = 1;
-	switch ((val >> 13) & 0x3) {
-	case (0x00):
-		priv->speed = 10;
-		break;
-	case (0x01):
-		priv->speed = 100;
-		break;
-	case (0x02):
-		priv->speed = 1000;
-		break;
-	}
-
-	priv->duplexity = (val & 0x1000) == 0x1000;
-
-	return 0;
-}
-
-/*
- * Figure out if BCM5482 is in serdes or copper mode and determine link
- * configuration accordingly
- */
-static uint mii_parse_BCM5482_sr(uint mii_reg, struct tsec_private *priv)
-{
-	if (BCM8482_is_serdes(priv)) {
-		mii_parse_BCM5482_serdes_sr(priv);
-		priv->flags |= TSEC_FIBER;
-	} else {
-		/* Wait for auto-negotiation to complete or fail */
-		mii_parse_sr(mii_reg, priv);
-
-		/* Parse BCM54xx copper aux status register */
-		mii_reg = read_phy_reg(priv, MIIM_BCM54xx_AUXSTATUS);
-		mii_parse_BCM54xx_sr(mii_reg, priv);
-	}
-
-	return 0;
-}
-
-/* Parse the 88E1011's status register for speed and duplex
- * information
- */
-static uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
-
-	if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) &&
-		!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
-		int i = 0;
-
-		puts("Waiting for PHY realtime link");
-		while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
-			/* Timeout reached ? */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				break;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
-		}
-		puts(" done\n");
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	} else {
-		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
-			priv->link = 1;
-		else
-			priv->link = 0;
-	}
-
-	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED);
-
-	switch (speed) {
-	case MIIM_88E1011_PHYSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_88E1011_PHYSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-	}
-
-	return 0;
-}
-
-/* Parse the RTL8211B's status register for speed and duplex
- * information
- */
-static uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
-	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
-		int i = 0;
-
-		/* in case of timeout ->link is cleared */
-		priv->link = 1;
-		puts("Waiting for PHY realtime link");
-		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
-			/* Timeout reached ? */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				break;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
-		}
-		puts(" done\n");
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	} else {
-		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
-			priv->link = 1;
-		else
-			priv->link = 0;
-	}
-
-	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
-
-	switch (speed) {
-	case MIIM_RTL8211B_PHYSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_RTL8211B_PHYSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-	}
-
-	return 0;
-}
-
-/* Parse the cis8201's status register for speed and duplex
- * information
- */
-static uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
-	switch (speed) {
-	case MIIM_CIS8201_AUXCONSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_CIS8201_AUXCONSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/* Parse the vsc8244's status register for speed and duplex
- * information
- */
-static uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
-	switch (speed) {
-	case MIIM_VSC8244_AUXCONSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_VSC8244_AUXCONSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/* Parse the DM9161's status register for speed and duplex
- * information
- */
-static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
-{
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
-		priv->speed = 100;
-	else
-		priv->speed = 10;
-
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	return 0;
-}
-
-/*
- * Hack to write all 4 PHYs with the LED values
- */
-static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
-{
-	uint phyid;
-	tsec_mii_t *regbase = priv->phyregs;
-	int timeout = 1000000;
-
-	for (phyid = 0; phyid < 4; phyid++) {
-		out_be32(&regbase->miimadd, (phyid << 8) | mii_reg);
-		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
-		asm("sync");
-
-		timeout = 1000000;
-		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--) ;
-	}
-
-	return MIIM_CIS8204_SLEDCON_INIT;
-}
-
-static uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv)
-{
-	if (priv->flags & TSEC_REDUCED)
-		return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
-	else
-		return MIIM_CIS8204_EPHYCON_INIT;
-}
-
-static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
-{
-	uint mii_data = read_phy_reg(priv, mii_reg);
-
-	if (priv->flags & TSEC_REDUCED)
-		mii_data = (mii_data & 0xfff0) | 0x000b;
-	return mii_data;
-}
-
-static struct phy_info phy_info_M88E1149S = {
-	0x1410ca,
-	"Marvell 88E1149S",
-	4,
-	(struct phy_cmd[]) {     /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1d, 0x1f, NULL},
-		{0x1e, 0x200c, NULL},
-		{0x1d, 0x5, NULL},
-		{0x1e, 0x0, NULL},
-		{0x1e, 0x100, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* shutdown */
-		{miim_end,}
-	},
-};
-
-/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
-static struct phy_info phy_info_BCM5461S = {
-	0x02060c1,	/* 5461 ID */
-	"Broadcom BCM5461S",
-	0, /* not clear to me what minor revisions we can shift away */
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_BCM5464S = {
-	0x02060b1,	/* 5464 ID */
-	"Broadcom BCM5464S",
-	0, /* not clear to me what minor revisions we can shift away */
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_BCM5482S =  {
-	0x0143bcb,
-	"Broadcom BCM5482S",
-	4,
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		/* Setup read from auxilary control shadow register 7 */
-		{MIIM_BCM54xx_AUXCNTL, MIIM_BCM54xx_AUXCNTL_ENCODE(7), NULL},
-		/* Read Misc Control register and or in Ethernet at Wirespeed */
-		{MIIM_BCM54xx_AUXCNTL, 0, &mii_BCM54xx_wirespeed},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		/* Initial config/enable of secondary SerDes interface */
-		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf), NULL},
-		/* Write intial value to secondary SerDes Contol */
-		{MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_SSD | 0, NULL},
-		{MIIM_BCM54XX_EXP_DATA, MIIM_CONTROL_RESTART, NULL},
-		/* Enable copper/fiber auto-detect */
-		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201)},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Determine copper/fiber, auto-negotiate, and read the result */
-		{MIIM_STATUS, miim_read, &mii_parse_BCM5482_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1011S = {
-	0x01410c6,
-	"Marvell 88E1011S",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1d, 0x1f, NULL},
-		{0x1e, 0x200c, NULL},
-		{0x1d, 0x5, NULL},
-		{0x1e, 0x0, NULL},
-		{0x1e, 0x100, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1111S = {
-	0x01410cc,
-	"Marvell 88E1111S",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1b, 0x848f, &mii_m88e1111s_setmode},
-		{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1118 = {
-	0x01410e1,
-	"Marvell 88E1118",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x16, 0x0002, NULL}, /* Change Page Number */
-		{0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */
-		{0x16, 0x0003, NULL}, /* Change Page Number */
-		{0x10, 0x021e, NULL}, /* Adjust LED control */
-		{0x16, 0x0000, NULL}, /* Change Page Number */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		{0x16, 0x0000, NULL}, /* Change Page Number */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read,
-		 &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/*
- *  Since to access LED register we need do switch the page, we
- * do LED configuring in the miim_read-like function as follows
- */
-static uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv)
-{
-	uint pg;
-
-	/* Switch the page to access the led register */
-	pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE);
-	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE);
-
-	/* Configure leds */
-	write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL,
-		      MIIM_88E1121_PHY_LED_DEF);
-
-	/* Restore the page pointer */
-	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg);
-	return 0;
-}
-
-static struct phy_info phy_info_M88E1121R = {
-	0x01410cb,
-	"Marvell 88E1121R",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		/* Configure leds */
-		{MIIM_88E1121_PHY_LED_CTRL, miim_read, &mii_88E1121_set_led},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		/* Disable IRQs and de-assert interrupt */
-		{MIIM_88E1121_PHY_IRQ_EN, 0, NULL},
-		{MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_STATUS, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv)
-{
-	uint mii_data = read_phy_reg(priv, mii_reg);
-
-	/* Setting MIIM_88E1145_PHY_EXT_CR */
-	if (priv->flags & TSEC_REDUCED)
-		return mii_data |
-		    MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY;
-	else
-		return mii_data;
-}
-
-static struct phy_info phy_info_M88E1145 = {
-	0x01410cd,
-	"Marvell 88E1145",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-
-		/* Errata E0, E1 */
-		{29, 0x001b, NULL},
-		{30, 0x418f, NULL},
-		{29, 0x0016, NULL},
-		{30, 0xa2da, NULL},
-
-		/* Configure the PHY */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, NULL},
-		{MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_88E1111_PHY_LED_CONTROL, MIIM_88E1111_PHY_LED_DIRECT, NULL},
-		/* Read the Status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_cis8204 = {
-	0x3f11,
-	"Cicada Cis8204",
-	6,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT,
-		 &mii_cis8204_fixled},
-		{MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT,
-		 &mii_cis8204_setmode},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/* Cicada 8201 */
-static struct phy_info phy_info_cis8201 = {
-	0xfc41,
-	"CIS8201",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8211 = {
-	0xfc4b,
-	"Vitesse VSC8211",
-	4,
-	(struct phy_cmd[]) { /* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8244 = {
-	0x3f1b,
-	"Vitesse VSC8244",
-	6,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8641 = {
-	0x7043,
-	"Vitesse VSC8641",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8221 = {
-	0xfc55,
-	"Vitesse VSC8221",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8601 = {
-	0x00007042,
-	"Vitesse VSC8601",
-	4,
-	(struct phy_cmd[]) {     /* config */
-		/* Override PHY config settings */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-#ifdef CONFIG_SYS_VSC8601_SKEWFIX
-		{MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL},
-#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
-		{MIIM_EXT_PAGE_ACCESS,1,NULL},
-#define VSC8101_SKEW \
-	(CONFIG_SYS_VSC8601_SKEW_TX << 14) | (CONFIG_SYS_VSC8601_SKEW_RX << 12)
-		{MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL},
-		{MIIM_EXT_PAGE_ACCESS,0,NULL},
-#endif
-#endif
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESTART, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_dm9161 = {
-	0x0181b88,
-	"Davicom DM9161E",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
-		/* Do not bypass the scrambler/descrambler */
-		{MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
-		/* Clear 10BTCSR to default */
-		{MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CR_INIT, NULL},
-		/* Restart Auto Negotiation */
-		{MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/* micrel KSZ804  */
-static struct phy_info phy_info_ksz804 =  {
-	0x0022151,
-	"Micrel KSZ804 PHY",
-	4,
-	(struct phy_cmd[]) { /* config */
-		{MII_BMCR, BMCR_RESET, NULL},
-		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		{MII_BMSR, miim_read, NULL},
-		{MII_BMSR, miim_read, &mii_parse_sr},
-		{MII_BMSR, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	}
-};
-
-/* a generic flavor.  */
-static struct phy_info phy_info_generic =  {
-	0,
-	"Unknown/Generic PHY",
-	32,
-	(struct phy_cmd[]) { /* config */
-		{MII_BMCR, BMCR_RESET, NULL},
-		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		{MII_BMSR, miim_read, NULL},
-		{MII_BMSR, miim_read, &mii_parse_sr},
-		{MII_BMSR, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	}
-};
-
-static uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
-{
-	unsigned int speed;
-	if (priv->link) {
-		speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
-
-		switch (speed) {
-		case MIIM_LXT971_SR2_10HDX:
-			priv->speed = 10;
-			priv->duplexity = 0;
-			break;
-		case MIIM_LXT971_SR2_10FDX:
-			priv->speed = 10;
-			priv->duplexity = 1;
-			break;
-		case MIIM_LXT971_SR2_100HDX:
-			priv->speed = 100;
-			priv->duplexity = 0;
-			break;
-		default:
-			priv->speed = 100;
-			priv->duplexity = 1;
-		}
-	} else {
-		priv->speed = 0;
-		priv->duplexity = 0;
-	}
-
-	return 0;
-}
-
-static struct phy_info phy_info_lxt971 = {
-	0x0001378e,
-	"LXT971",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CR, MIIM_CR_INIT, mii_cr_init},	/* autonegotiate */
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup - enable interrupts */
-		/* { 0x12, 0x00f2, NULL }, */
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown - disable interrupts */
-		{miim_end,}
-	},
-};
-
-/* Parse the DP83865's link and auto-neg status register for speed and duplex
- * information
- */
-static uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
-{
-	switch (mii_reg & MIIM_DP83865_SPD_MASK) {
-
-	case MIIM_DP83865_SPD_1000:
-		priv->speed = 1000;
-		break;
-
-	case MIIM_DP83865_SPD_100:
-		priv->speed = 100;
-		break;
-
-	default:
-		priv->speed = 10;
-		break;
-
-	}
-
-	if (mii_reg & MIIM_DP83865_DPX_FULL)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	return 0;
-}
-
-static struct phy_info phy_info_dp83865 = {
-	0x20005c7,
-	"NatSemi DP83865",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the link and auto-neg status */
-		{MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_rtl8211b = {
-	0x001cc91,
-	"RealTek RTL8211B",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info *phy_info[] = {
-	&phy_info_cis8204,
-	&phy_info_cis8201,
-	&phy_info_BCM5461S,
-	&phy_info_BCM5464S,
-	&phy_info_BCM5482S,
-	&phy_info_M88E1011S,
-	&phy_info_M88E1111S,
-	&phy_info_M88E1118,
-	&phy_info_M88E1121R,
-	&phy_info_M88E1145,
-	&phy_info_M88E1149S,
-	&phy_info_dm9161,
-	&phy_info_ksz804,
-	&phy_info_lxt971,
-	&phy_info_VSC8211,
-	&phy_info_VSC8244,
-	&phy_info_VSC8601,
-	&phy_info_VSC8641,
-	&phy_info_VSC8221,
-	&phy_info_dp83865,
-	&phy_info_rtl8211b,
-	&phy_info_generic,	/* must be last; has ID 0 and 32 bit mask */
-	NULL
-};
-
-/* Grab the identifier of the device's PHY, and search through
- * all of the known PHYs to see if one matches.	 If so, return
- * it, if not, return NULL
- */
-static struct phy_info *get_phy_info(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	uint phy_reg, phy_ID;
-	int i;
-	struct phy_info *theInfo = NULL;
-
-	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
-	phy_ID = (phy_reg & 0xffff) << 16;
-
-	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
-	phy_ID |= (phy_reg & 0xffff);
-
-	/* loop through all the known PHY types, and find one that */
-	/* matches the ID we read from the PHY. */
-	for (i = 0; phy_info[i]; i++) {
-		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {
-			theInfo = phy_info[i];
-			break;
-		}
-	}
-
-	if (theInfo == &phy_info_generic) {
-		printf("%s: No support for PHY id %x; assuming generic\n",
-			dev->name, phy_ID);
-	} else {
-		debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
-	}
-
-	return theInfo;
-}
-
-/* Execute the given series of commands on the given device's
- * PHY, running functions as necessary
- */
-static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
-{
-	int i;
-	uint result;
-	tsec_mii_t *phyregs = priv->phyregs;
-
-	out_be32(&phyregs->miimcfg, MIIMCFG_RESET);
-
-	out_be32(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
-	while (in_be32(&phyregs->miimind) & MIIMIND_BUSY) ;
-
-	for (i = 0; cmd->mii_reg != miim_end; i++) {
-		if (cmd->mii_data == miim_read) {
-			result = read_phy_reg(priv, cmd->mii_reg);
-
-			if (cmd->funct != NULL)
-				(*(cmd->funct)) (result, priv);
-
-		} else {
-			if (cmd->funct != NULL)
-				result = (*(cmd->funct)) (cmd->mii_reg, priv);
-			else
-				result = cmd->mii_data;
-
-			write_phy_reg(priv, cmd->mii_reg, result);
-
-		}
-		cmd++;
-	}
+	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, 0,
+			TBI_ANA, TBIANA_SETTINGS);
+	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, 0,
+			TBI_TBICON, TBICON_CLK_SELECT);
+	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, 0,
+			TBI_CR,	CONFIG_TSEC_TBICR_SETTINGS);
 }
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
@@ -1487,12 +115,12 @@ static int tsec_miiphy_read(const char *devname, unsigned char addr,
 	unsigned short ret;
 	struct tsec_private *priv = privlist[0];
 
-	if (NULL == priv) {
+	if (!priv) {
 		printf("Can't read PHY at address %d\n", addr);
 		return -1;
 	}
 
-	ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg);
+	ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, 0, reg);
 	*value = ret;
 
 	return 0;
@@ -1509,16 +137,15 @@ static int tsec_miiphy_write(const char *devname, unsigned char addr,
 {
 	struct tsec_private *priv = privlist[0];
 
-	if (NULL == priv) {
+	if (!priv) {
 		printf("Can't write PHY at address %d\n", addr);
 		return -1;
 	}
 
-	tsec_local_mdio_write(priv->phyregs, addr, reg, value);
+	tsec_local_mdio_write(priv->phyregs, addr, 0, reg, value);
 
 	return 0;
 }
-
 #endif
 
 #ifdef CONFIG_MCAST_TFTP
@@ -1612,14 +239,14 @@ static void init_registers(tsec_t * regs)
 /* Configure maccfg2 based on negotiated speed and duplex
  * reported by PHY handling code
  */
-static void adjust_link(struct eth_device *dev)
+static void adjust_link(struct mii_info *mii_info)
 {
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	struct tsec_private *priv = (struct tsec_private *)mii_info->dev->priv;
 	tsec_t *regs = priv->regs;
 	u32 ecntrl, maccfg2;
 
-	if (!priv->link) {
-		printf("%s: No link.\n", dev->name);
+	if (!mii_info->link) {
+		printf("%s: No link.\n", mii_info->dev->name);
 		return;
 	}
 
@@ -1630,10 +257,10 @@ static void adjust_link(struct eth_device *dev)
 	maccfg2 = in_be32(&regs->maccfg2);
 	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
 
-	if (priv->duplexity)
+	if (mii_info->duplex)
 		maccfg2 |= MACCFG2_FULL_DUPLEX;
 
-	switch (priv->speed) {
+	switch (mii_info->speed) {
 	case 1000:
 		maccfg2 |= MACCFG2_GMII;
 		break;
@@ -1644,20 +271,20 @@ static void adjust_link(struct eth_device *dev)
 		/* Set R100 bit in all modes although
 		 * it is only used in RGMII mode
 		 */
-		if (priv->speed == 100)
+		if (mii_info->speed == 100)
 			ecntrl |= ECNTRL_R100;
 		break;
 	default:
-		printf("%s: Speed was bad\n", dev->name);
+		printf("%s: Speed was bad\n", mii_info->dev->name);
 		break;
 	}
 
 	out_be32(&regs->ecntrl, ecntrl);
 	out_be32(&regs->maccfg2, maccfg2);
 
-	printf("Speed: %d, %s duplex%s\n", priv->speed,
-			(priv->duplexity) ? "full" : "half",
-			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+	printf("Speed: %d, %s duplex%s\n", mii_info->speed,
+			(mii_info->duplex) ? "full" : "half",
+			(mii_info->flags & TSEC_FIBER) ? ", fiber mode" : "");
 }
 
 /* Set up the buffers and their descriptors, and bring up the
@@ -1669,6 +296,10 @@ static void startup_tsec(struct eth_device *dev)
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	tsec_t *regs = priv->regs;
 
+	/* reset the indices to zero */
+	rxIdx = 0;
+	txIdx = 0;
+
 	/* Point to the buffer descriptors */
 	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
 	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
@@ -1689,12 +320,6 @@ static void startup_tsec(struct eth_device *dev)
 	}
 	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
 
-	/* Start up the PHY */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->startup);
-
-	adjust_link(dev);
-
 	/* Enable Transmit and Receive */
 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
 
@@ -1798,8 +423,8 @@ static void tsec_halt(struct eth_device *dev)
 	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
 
 	/* Shut down the PHY, as needed */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->shutdown);
+	if (priv->phyinfo && priv->phyinfo->shutdown)
+		priv->phyinfo->shutdown(priv->mii_info);
 }
 
 /* Initializes data structures and registers for the controller,
@@ -1838,18 +463,20 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 
 	out_be32(&regs->macstnaddr2, tempval);
 
-	/* reset the indices to zero */
-	rxIdx = 0;
-	txIdx = 0;
-
 	/* Clear out (for the most part) the other registers */
 	init_registers(regs);
 
 	/* Ready the device for tx/rx */
 	startup_tsec(dev);
 
+	/* Start up the PHY */
+	if (priv->phyinfo && priv->phyinfo->startup)
+		priv->phyinfo->startup(priv->mii_info);
+
+	adjust_link(priv->mii_info);
+
 	/* If there's no link, fail */
-	return (priv->link ? 0 : -1);
+	return (priv->mii_info->link ? 0 : -1);
 }
 
 /* Discover which PHY is attached to the device, and configure it
@@ -1860,14 +487,41 @@ static int init_phy(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	struct phy_info *curphy;
+	struct mii_info	*mii_info;
 	tsec_t *regs = priv->regs;
 
+	mii_info = malloc(sizeof(*mii_info));
+	if (!mii_info) {
+		printf("%s: Could not allocate mii_info", dev->name);
+		return -1;
+	}
+	memset(mii_info, 0, sizeof(*mii_info));
+
+	mii_info->duplex = DUPLEX_FULL;
+	mii_info->link = 0;
+
+	mii_info->autoneg = 1;
+	mii_info->mii_id = priv->phyaddr;
+
+	mii_info->advertising = (ADVERTISED_10baseT_Half |
+				ADVERTISED_10baseT_Full |
+				ADVERTISED_100baseT_Half |
+				ADVERTISED_100baseT_Full |
+				ADVERTISED_1000baseT_Full);
+
+	mii_info->phyregs = (void *)priv->phyregs;
+
+	mii_info->priv = priv;
+	mii_info->dev = dev;
+	mii_info->flags = priv->flags;
+	priv->mii_info = mii_info;
+
 	/* Assign a Physical address to the TBI */
 	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
 	asm("sync");
 
 	/* Reset MII (due to new addresses) */
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET_MGMT);
 	asm("sync");
 	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
 	asm("sync");
@@ -1875,21 +529,20 @@ static int init_phy(struct eth_device *dev)
 
 	/* Get the cmd structure corresponding to the attached
 	 * PHY */
-	curphy = get_phy_info(dev);
-
-	if (curphy == NULL) {
+	curphy = tsec_get_phy_info(mii_info);
+	if (!curphy) {
 		priv->phyinfo = NULL;
 		printf("%s: No PHY found\n", dev->name);
 
 		return 0;
 	}
+	priv->phyinfo = curphy;
 
 	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
 		tsec_configure_serdes(priv);
 
-	priv->phyinfo = curphy;
-
-	phy_run_commands(priv, priv->phyinfo->config);
+	if (curphy->config)
+		curphy->config(priv->mii_info);
 
 	return 1;
 }
diff --git a/include/tsec.h b/include/tsec.h
index 054e5cf..2a2af32 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -54,8 +54,6 @@
 #define TSEC_TIMEOUT 1000
 #define TOUT_LOOP	1000000
 
-#define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
-
 /* TBI register addresses */
 #define TBI_CR			0x00
 #define TBI_SR			0x01
@@ -102,201 +100,9 @@
 #define ECNTRL_R100		0x00000008
 #define ECNTRL_SGMII_MODE	0x00000002
 
-#define miim_end -2
-#define miim_read -1
-
 #ifndef CONFIG_SYS_TBIPA_VALUE
     #define CONFIG_SYS_TBIPA_VALUE	0x1f
 #endif
-#define MIIMCFG_INIT_VALUE	0x00000003
-#define MIIMCFG_RESET		0x80000000
-
-#define MIIMIND_BUSY		0x00000001
-#define MIIMIND_NOTVALID	0x00000004
-
-#define MIIM_CONTROL		0x00
-#define MIIM_CONTROL_RESET	0x00009140
-#define MIIM_CONTROL_INIT	0x00001140
-#define MIIM_CONTROL_RESTART	0x00001340
-#define MIIM_ANEN		0x00001000
-
-#define MIIM_CR			0x00
-#define MIIM_CR_RST		0x00008000
-#define MIIM_CR_INIT		0x00001000
-
-#define MIIM_STATUS		0x1
-#define MIIM_STATUS_AN_DONE	0x00000020
-#define MIIM_STATUS_LINK	0x0004
-
-#define MIIM_PHYIR1		0x2
-#define MIIM_PHYIR2		0x3
-
-#define MIIM_ANAR		0x4
-#define MIIM_ANAR_INIT		0x1e1
-
-#define MIIM_TBI_ANLPBPA	0x5
-#define MIIM_TBI_ANLPBPA_HALF	0x00000040
-#define MIIM_TBI_ANLPBPA_FULL	0x00000020
-
-#define MIIM_TBI_ANEX		0x6
-#define MIIM_TBI_ANEX_NP	0x00000004
-#define MIIM_TBI_ANEX_PRX	0x00000002
-
-#define MIIM_GBIT_CONTROL	0x9
-#define MIIM_GBIT_CONTROL_INIT	0xe00
-
-#define MIIM_EXT_PAGE_ACCESS	0x1f
-
-/* Broadcom BCM54xx -- taken from linux sungem_phy */
-#define MIIM_BCM54xx_AUXCNTL			0x18
-#define MIIM_BCM54xx_AUXCNTL_ENCODE(val)	((val & 0x7) << 12)|(val & 0x7)
-#define MIIM_BCM54xx_AUXSTATUS			0x19
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK	0x0700
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT	8
-
-#define MIIM_BCM54XX_SHD	0x1c	/* 0x1c shadow registers */
-#define MIIM_BCM54XX_SHD_WRITE	0x8000
-#define MIIM_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
-#define MIIM_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
-#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data)	\
-	(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
-	 MIIM_BCM54XX_SHD_DATA(data))
-
-#define MIIM_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
-#define MIIM_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
-#define MIIM_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
-#define MIIM_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
-
-/* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT	0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT	0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED	0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT	0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100	0x0008
-
-/* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1		0x17
-#define MIIM_CIS8201_EXTCON1_INIT	0x0000
-
-/* Cicada 8204 Extended PHY Control Register 1 */
-#define MIIM_CIS8204_EPHY_CON		0x17
-#define MIIM_CIS8204_EPHYCON_INIT	0x0006
-#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
-
-/* Cicada 8204 Serial LED Control Register */
-#define MIIM_CIS8204_SLED_CON		0x1b
-#define MIIM_CIS8204_SLEDCON_INIT	0x1115
-
-#define MIIM_GBIT_CON		0x09
-#define MIIM_GBIT_CON_ADVERT	0x0e00
-
-/* Entry for Vitesse VSC8244 regs starts here */
-/* Vitesse VSC8244 Auxiliary Control/Status Register */
-#define MIIM_VSC8244_AUX_CONSTAT	0x1c
-#define MIIM_VSC8244_AUXCONSTAT_INIT	0x0000
-#define MIIM_VSC8244_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_VSC8244_AUXCONSTAT_SPEED	0x0018
-#define MIIM_VSC8244_AUXCONSTAT_GBIT	0x0010
-#define MIIM_VSC8244_AUXCONSTAT_100	0x0008
-#define MIIM_CONTROL_INIT_LOOPBACK	0x4000
-
-/* Vitesse VSC8244 Extended PHY Control Register 1 */
-#define MIIM_VSC8244_EPHY_CON		0x17
-#define MIIM_VSC8244_EPHYCON_INIT	0x0006
-
-/* Vitesse VSC8244 Serial LED Control Register */
-#define MIIM_VSC8244_LED_CON		0x1b
-#define MIIM_VSC8244_LEDCON_INIT	0xF011
-
-/* Entry for Vitesse VSC8601 regs starts here (Not complete) */
-/* Vitesse VSC8601 Extended PHY Control Register 1 */
-#define MIIM_VSC8601_EPHY_CON		0x17
-#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
-#define MIIM_VSC8601_SKEW_CTRL		0x1c
-
-/* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS		0x11
-#define MIIM_88E1011_PHYSTAT_SPEED	0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT	0x8000
-#define MIIM_88E1011_PHYSTAT_100	0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX	0x2000
-#define MIIM_88E1011_PHYSTAT_SPDDONE	0x0800
-#define MIIM_88E1011_PHYSTAT_LINK	0x0400
-
-#define MIIM_88E1011_PHY_SCR		0x10
-#define MIIM_88E1011_PHY_MDI_X_AUTO	0x0060
-
-/* 88E1111 PHY LED Control Register */
-#define MIIM_88E1111_PHY_LED_CONTROL	24
-#define MIIM_88E1111_PHY_LED_DIRECT	0x4100
-#define MIIM_88E1111_PHY_LED_COMBINE	0x411C
-
-/* 88E1121 PHY LED Control Register */
-#define MIIM_88E1121_PHY_LED_CTRL	16
-#define MIIM_88E1121_PHY_LED_PAGE	3
-#define MIIM_88E1121_PHY_LED_DEF	0x0030
-
-/* 88E1121 PHY IRQ Enable/Status Register */
-#define MIIM_88E1121_PHY_IRQ_EN		18
-#define MIIM_88E1121_PHY_IRQ_STATUS	19
-
-#define MIIM_88E1121_PHY_PAGE		22
-
-/* 88E1145 Extended PHY Specific Control Register */
-#define MIIM_88E1145_PHY_EXT_CR 20
-#define MIIM_M88E1145_RGMII_RX_DELAY	0x0080
-#define MIIM_M88E1145_RGMII_TX_DELAY	0x0002
-
-#define MIIM_88E1145_PHY_PAGE	29
-#define MIIM_88E1145_PHY_CAL_OV 30
-
-/* RTL8211B PHY Status Register */
-#define MIIM_RTL8211B_PHY_STATUS	0x11
-#define MIIM_RTL8211B_PHYSTAT_SPEED	0xc000
-#define MIIM_RTL8211B_PHYSTAT_GBIT	0x8000
-#define MIIM_RTL8211B_PHYSTAT_100	0x4000
-#define MIIM_RTL8211B_PHYSTAT_DUPLEX	0x2000
-#define MIIM_RTL8211B_PHYSTAT_SPDDONE	0x0800
-#define MIIM_RTL8211B_PHYSTAT_LINK	0x0400
-
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP	0x0400
-#define MIIM_DM9161_CR_RSTAN	0x1200
-
-#define MIIM_DM9161_SCR		0x10
-#define MIIM_DM9161_SCR_INIT	0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR	0x11
-#define MIIM_DM9161_SCSR_100F	0x8000
-#define MIIM_DM9161_SCSR_100H	0x4000
-#define MIIM_DM9161_SCSR_10F	0x2000
-#define MIIM_DM9161_SCSR_10H	0x1000
-
-/* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR	0x12
-#define MIIM_DM9161_10BTCSR_INIT	0x7800
-
-/* LXT971 Status 2 registers */
-#define MIIM_LXT971_SR2		     0x11  /* Status Register 2  */
-#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
-#define MIIM_LXT971_SR2_10HDX	   0x0000  /*  10 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_10FDX	   0x0200  /*  10 Mbit full duplex selected */
-#define MIIM_LXT971_SR2_100HDX	   0x4000  /* 100 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_100FDX	   0x4200  /* 100 Mbit full duplex selected */
-
-/* DP83865 Control register values */
-#define MIIM_DP83865_CR_INIT	0x9200
-
-/* DP83865 Link and Auto-Neg Status Register */
-#define MIIM_DP83865_LANR	0x11
-#define MIIM_DP83865_SPD_MASK	0x0018
-#define MIIM_DP83865_SPD_1000	0x0010
-#define MIIM_DP83865_SPD_100	0x0008
-#define MIIM_DP83865_DPX_FULL	0x0002
-
-#define MIIM_READ_COMMAND	0x00000001
 
 #define MRBLR_INIT_SETTINGS	PKTSIZE_ALIGN
 
@@ -577,60 +383,10 @@ struct tsec_private {
 	tsec_t *regs;
 	tsec_mii_t *phyregs;
 	tsec_mii_t *phyregs_sgmii;
+	struct mii_info *mii_info;
 	struct phy_info *phyinfo;
 	uint phyaddr;
 	u32 flags;
-	uint link;
-	uint duplexity;
-	uint speed;
-};
-
-
-/*
- * struct phy_cmd:  A command for reading or writing a PHY register
- *
- * mii_reg:  The register to read or write
- *
- * mii_data:  For writes, the value to put in the register.
- *	A value of -1 indicates this is a read.
- *
- * funct: A function pointer which is invoked for each command.
- *	For reads, this function will be passed the value read
- *	from the PHY, and process it.
- *	For writes, the result of this function will be written
- *	to the PHY register
- */
-struct phy_cmd {
-	uint mii_reg;
-	uint mii_data;
-	uint (*funct) (uint mii_reg, struct tsec_private * priv);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be shifted right by "shift" bits to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * The struct phy_cmd entries represent pointers to an arrays of
- * commands which tell the driver what to do to the PHY.
- */
-struct phy_info {
-	uint id;
-	char *name;
-	uint shift;
-	/* Called to configure the PHY, and modify the controller
-	 * based on the results */
-	struct phy_cmd *config;
-
-	/* Called when starting up the controller */
-	struct phy_cmd *startup;
-
-	/* Called when bringing down the controller */
-	struct phy_cmd *shutdown;
 };
 
 struct tsec_info_struct {
-- 
1.6.4

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

* [U-Boot] [PATCH 11/14] PHY: add some Vitesse phy support
  2011-01-27  4:52                   ` [U-Boot] [PATCH 10/14] tsec: refactor the PHY code to make it reuseable Mingkai Hu
@ 2011-01-27  4:52                     ` Mingkai Hu
  2011-01-27  4:52                       ` [U-Boot] [PATCH 12/14] PHY: add some Broadcom " Mingkai Hu
  0 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Port from tsec.c file to add support for vsc8221, vsc8211, vsc8601, vsc8641.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/fsl_phy.c |  119 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fsl_phy.h |   21 +++++++++
 2 files changed, 140 insertions(+), 0 deletions(-)

diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
index 1ba0ce1..a6ec614 100644
--- a/drivers/net/fsl_phy.c
+++ b/drivers/net/fsl_phy.c
@@ -242,6 +242,58 @@ static int genphy_shutdown(struct mii_info *phydev)
 	return 0;
 }
 
+/* Vitesse VSC8211 */
+static int vsc8211_config(struct mii_info *mii_info)
+{
+	/* Override PHY config settings */
+	tsec_phy_write(mii_info, 0, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	tsec_phy_write(mii_info, 0, MIIM_CIS8201_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+	/* Configure some basic stuff */
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int vsc8211_parse_status(struct mii_info *mii_info)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_CIS8201_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS8201_AUXCONSTAT_GBIT:
+		mii_info->speed = SPEED_1000;
+		break;
+	case MIIM_CIS8201_AUXCONSTAT_100:
+		mii_info->speed = SPEED_100;
+		break;
+	default:
+		mii_info->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vsc8211_startup(struct mii_info *mii_info)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(mii_info);
+	vsc8211_parse_status(mii_info);
+
+	return 0;
+}
+ 
 /* Vitesse VSC8244 */
 static int vsc8244_parse_status(struct mii_info *mii_info)
 {
@@ -280,6 +332,51 @@ static int vsc8244_startup(struct mii_info *mii_info)
 	return 0;
 }
 
+/* Vitesse VSC8601 */
+int vsc8601_config(struct mii_info *mii_info)
+{
+	unsigned int reg;
+
+	/* Configure some basic stuff */
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+#ifdef CONFIG_SYS_VSC8601_SKEWFIX
+	tsec_phy_write(mii_info, 0, MIIM_VSC8601_EPHY_CON,
+			MIIM_VSC8601_EPHY_CON_INIT_SKEW);
+#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
+	tsec_phy_write(mii_info, 0, PHY_EXT_PAGE_ACCESS, 1);
+#define VSC8101_SKEW \
+	(CONFIG_SYS_VSC8601_SKEW_TX << 14) | (CONFIG_SYS_VSC8601_SKEW_RX << 12)
+	tsec_phy_write(mii_info, 0, MIIM_VSC8601_SKEW_CTRL, VSC8101_SKEW);
+	tsec_phy_write(mii_info, 0, PHY_EXT_PAGE_ACCESS, 0);
+#endif
+#endif
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+
+	reg = tsec_phy_read(mii_info, 0, MII_BMCR);
+	reg |= BMCR_ANRESTART;
+	tsec_phy_write(mii_info, 0, MII_BMCR, reg);
+
+	return 0;
+}
+
+static struct phy_info phy_info_VSC8211 = {
+	"Vitesse VSC8211",
+	0xfc4b0,
+	0xffff0,
+	&vsc8211_config,
+	&vsc8211_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_VSC8221 = {
+	"Vitesse VSC8221",
+	0xfc550,
+	0xffff0,
+	&genphy_config,
+	&vsc8244_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_VSC8244 = {
 	"Vitesse VSC8244",
 	0xfc6c0,
@@ -298,6 +395,24 @@ static struct phy_info phy_info_VSC8234 = {
 	&genphy_shutdown,
 };
 
+static struct phy_info phy_info_VSC8601 = {
+	"Vitesse VSC8601",
+	0x70420,
+	0xffff0,
+	&vsc8601_config,
+	&vsc8244_startup,
+	&genphy_shutdown,
+};
+
+struct phy_info phy_info_VSC8641 = {
+	"Vitesse VSC8641",
+	0x70430,
+	0xffff0,
+	&genphy_config,
+	&vsc8244_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_generic = {
 	"Unknown/Generic PHY",
 	0x0,
@@ -308,8 +423,12 @@ static struct phy_info phy_info_generic = {
 };
 
 static struct phy_info *phy_info[] = {
+	&phy_info_VSC8211,
+	&phy_info_VSC8221,
 	&phy_info_VSC8244,
 	&phy_info_VSC8234,
+	&phy_info_VSC8601,
+	&phy_info_VSC8641,
 	&phy_info_generic
 };
 
diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
index 8a8b6e8..d18cc58 100644
--- a/drivers/net/fsl_phy.h
+++ b/drivers/net/fsl_phy.h
@@ -34,7 +34,11 @@
 #define PORT_MII	0x02
 #define PORT_FIBRE	0x03
 
+/* PHY register offsets */
+#define PHY_EXT_PAGE_ACCESS	0x1f
+
 #define MII_BMCR_INIT           0x00001140
+#define MII_ADVERTISE_INIT	0x1e1
 
 /* MII Management Configuration Register */
 #define MIIMCFG_RESET_MGMT          0x80000000
@@ -96,6 +100,18 @@
 
 #define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
 
+/* Cicada Auxiliary Control/Status Register */
+#define MIIM_CIS8201_AUX_CONSTAT	0x1c
+#define MIIM_CIS8201_AUXCONSTAT_INIT	0x0004
+#define MIIM_CIS8201_AUXCONSTAT_DUPLEX	0x0020
+#define MIIM_CIS8201_AUXCONSTAT_SPEED	0x0018
+#define MIIM_CIS8201_AUXCONSTAT_GBIT	0x0010
+#define MIIM_CIS8201_AUXCONSTAT_100	0x0008
+
+/* Cicada Extended Control Register 1 */
+#define MIIM_CIS8201_EXT_CON1		0x17
+#define MIIM_CIS8201_EXTCON1_INIT	0x0000
+
 /* Entry for Vitesse VSC8244 regs starts here */
 /* Vitesse VSC8244 Auxiliary Control/Status Register */
 #define MIIM_VSC8244_AUX_CONSTAT	0x1c
@@ -106,6 +122,11 @@
 #define MIIM_VSC8244_AUXCONSTAT_100	0x0008
 #define MIIM_CONTROL_INIT_LOOPBACK	0x4000
 
+/* Vitesse VSC8601 Extended PHY Control Register 1 */
+#define MIIM_VSC8601_EPHY_CON		0x17
+#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
+#define MIIM_VSC8601_SKEW_CTRL		0x1c
+
 struct mii_info {
 	/* Information about the PHY type */
 	/* And management functions */
-- 
1.6.4

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

* [U-Boot] [PATCH 12/14] PHY: add some Broadcom phy support
  2011-01-27  4:52                     ` [U-Boot] [PATCH 11/14] PHY: add some Vitesse phy support Mingkai Hu
@ 2011-01-27  4:52                       ` Mingkai Hu
  2011-01-27  4:52                         ` [U-Boot] [PATCH 13/14] PHY: add some Marvell " Mingkai Hu
  0 siblings, 1 reply; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Port from tsec.c file to add support for bcm5461, bcm5464, bcm5482s.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/fsl_phy.c |  245 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fsl_phy.h |   22 +++++
 2 files changed, 267 insertions(+), 0 deletions(-)

diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
index a6ec614..7c22666 100644
--- a/drivers/net/fsl_phy.c
+++ b/drivers/net/fsl_phy.c
@@ -21,6 +21,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/errno.h>
+#include <tsec.h>
 
 #include "fsl_phy.h"
 
@@ -242,6 +243,220 @@ static int genphy_shutdown(struct mii_info *phydev)
 	return 0;
 }
 
+/* Broadcom BCM5461S */
+static int bcm5461_config(struct mii_info *mii_info)
+{
+	unsigned int reg;
+
+	/* reset the PHY */
+	reg = tsec_phy_read(mii_info, 0, MII_BMCR);
+	reg |= BMCR_RESET;
+	tsec_phy_write(mii_info, 0, MII_BMCR, reg);
+
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+
+	/* reset the PHY */
+	reg = tsec_phy_read(mii_info, 0, MII_BMCR);
+	reg |= BMCR_RESET;
+	tsec_phy_write(mii_info, 0, MII_BMCR, reg);
+
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int bcm54xx_parse_status(struct mii_info *mii_info)
+{
+	unsigned int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_BCM54xx_AUXSTATUS);
+
+	switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
+			MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
+		case 1:
+		mii_info->duplex = DUPLEX_HALF;
+		mii_info->speed = SPEED_10;
+		break;
+		case 2:
+		mii_info->duplex = DUPLEX_FULL;
+		mii_info->speed = SPEED_10;
+		break;
+		case 3:
+		mii_info->duplex = DUPLEX_HALF;
+		mii_info->speed = SPEED_100;
+		break;
+		case 5:
+		mii_info->duplex = DUPLEX_FULL;
+		mii_info->speed = SPEED_100;
+		break;
+		case 6:
+		mii_info->duplex = DUPLEX_HALF;
+		mii_info->speed = SPEED_1000;
+		break;
+		case 7:
+		mii_info->duplex = DUPLEX_FULL;
+		mii_info->speed = SPEED_1000;
+		break;
+		default:
+		printf("Auto-neg error, defaulting to 10BT/HD\n");
+		mii_info->duplex = DUPLEX_HALF;
+		mii_info->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int bcm54xx_startup(struct mii_info *mii_info)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(mii_info);
+	bcm54xx_parse_status(mii_info);
+
+	return 0;
+}
+
+/* Broadcom BCM5482S */
+/*
+ * "Ethernet at Wirespeed" needs to be enabled to achieve link in certain
+ * circumstances.  eg a gigabit TSEC connected to a gigabit switch with
+ * a 4-wire ethernet cable.  Both ends advertise gigabit, but can't
+ * link.  "Ethernet at Wirespeed" reduces advertised speed until link
+ * can be achieved.
+ */
+static u32 bcm5482_read_wirespeed(struct mii_info *mii_info, u32 reg)
+{
+	return (tsec_phy_read(mii_info, 0, reg) & 0x8FFF) | 0x8010;
+}
+
+static int bcm5482_config(struct mii_info *mii_info)
+{
+	unsigned int reg;
+
+	/* reset the PHY */
+	reg = tsec_phy_read(mii_info, 0, MII_BMCR);
+	reg |= BMCR_RESET;
+	tsec_phy_write(mii_info, 0, MII_BMCR, reg);
+
+	/* Setup read from auxilary control shadow register 7 */
+	tsec_phy_write(mii_info, 0, MIIM_BCM54xx_AUXCNTL,
+			MIIM_BCM54xx_AUXCNTL_ENCODE(7));
+	/* Read Misc Control register and or in Ethernet at Wirespeed */
+	reg = bcm5482_read_wirespeed(mii_info, MIIM_BCM54xx_AUXCNTL);
+	tsec_phy_write(mii_info, 0, MIIM_BCM54xx_AUXCNTL, reg);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+	/* Initial config/enable of secondary SerDes interface */
+	tsec_phy_write(mii_info, 0, MIIM_BCM54XX_SHD,
+			MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf));
+	/* Write intial value to secondary SerDes Contol */
+	tsec_phy_write(mii_info, 0, MIIM_BCM54XX_EXP_SEL,
+			MIIM_BCM54XX_EXP_SEL_SSD | 0);
+	tsec_phy_write(mii_info, 0, MIIM_BCM54XX_EXP_DATA, MII_BMCR_RESTART);
+	/* Enable copper/fiber auto-detect */
+	tsec_phy_write(mii_info, 0, MIIM_BCM54XX_SHD,
+			MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201));
+
+	return 0;
+}
+
+/*
+ * Find out if PHY is in copper or serdes mode by looking at Expansion Reg
+ * 0x42 - "Operating Mode Status Register"
+ */
+static int bcm5482_is_serdes(struct mii_info *mii_info)
+{
+	u16 val;
+	int serdes = 0;
+
+	tsec_phy_write(mii_info, 0, MIIM_BCM54XX_EXP_SEL,
+			MIIM_BCM54XX_EXP_SEL_ER | 0x42);
+	val = tsec_phy_read(mii_info, 0, MIIM_BCM54XX_EXP_DATA);
+
+	switch (val & 0x1f) {
+	case 0x0d:	/* RGMII-to-100Base-FX */
+	case 0x0e:	/* RGMII-to-SGMII */
+	case 0x0f:	/* RGMII-to-SerDes */
+	case 0x12:	/* SGMII-to-SerDes */
+	case 0x13:	/* SGMII-to-100Base-FX */
+	case 0x16:	/* SerDes-to-Serdes */
+		serdes = 1;
+		break;
+	case 0x6:	/* RGMII-to-Copper */
+	case 0x14:	/* SGMII-to-Copper */
+	case 0x17:	/* SerDes-to-Copper */
+		break;
+	default:
+		printf("ERROR, invalid PHY mode (0x%x\n)", val);
+		break;
+	}
+
+	return serdes;
+}
+
+/*
+ * Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating
+ * Mode Status Register"
+ */
+static u32 bcm5482_parse_serdes_sr(struct mii_info *mii_info)
+{
+	u16 val;
+	int i = 0;
+
+	/* Wait 1s for link - Clause 37 autonegotiation happens very fast */
+	while (1) {
+		tsec_phy_write(mii_info, 0, MIIM_BCM54XX_EXP_SEL,
+				MIIM_BCM54XX_EXP_SEL_ER | 0x42);
+		val = tsec_phy_read(mii_info, 0, MIIM_BCM54XX_EXP_DATA);
+
+		if (val & 0x8000)
+			break;
+
+		if (i++ > 1000) {
+			mii_info->link = 0;
+			return 1;
+		}
+
+		udelay(1000);	/* 1 ms */
+	}
+
+	mii_info->link = 1;
+	switch ((val >> 13) & 0x3) {
+	case (0x00):
+		mii_info->speed = 10;
+		break;
+	case (0x01):
+		mii_info->speed = 100;
+		break;
+	case (0x02):
+		mii_info->speed = 1000;
+		break;
+	}
+
+	mii_info->duplex = (val & 0x1000) == 0x1000;
+
+	return 0;
+}
+
+/*
+ * Figure out if BCM5482 is in serdes or copper mode and determine link
+ * configuration accordingly
+ */
+static int bcm5482_startup(struct mii_info *mii_info)
+{
+	if (bcm5482_is_serdes(mii_info)) {
+		bcm5482_parse_serdes_sr(mii_info);
+		mii_info->flags |= TSEC_FIBER;
+	} else {
+		/* Wait for auto-negotiation to complete or fail */
+		genphy_update_link(mii_info);
+		/* Parse BCM54xx copper aux status register */
+		bcm54xx_parse_status(mii_info);
+	}
+
+	return 0;
+}
+
 /* Vitesse VSC8211 */
 static int vsc8211_config(struct mii_info *mii_info)
 {
@@ -359,6 +574,33 @@ int vsc8601_config(struct mii_info *mii_info)
 	return 0;
 }
 
+static struct phy_info phy_info_BCM5461S = {
+	"Broadcom BCM5461S",
+	0x2060c0,
+	0xfffff0,
+	&bcm5461_config,
+	&bcm54xx_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_BCM5464S = {
+	"Broadcom BCM5464S",
+	0x2060b0,
+	0xfffff0,
+	&bcm5461_config,
+	&bcm54xx_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_BCM5482S = {
+	"Broadcom BCM5482S",
+	0x143bcb0,
+	0xffffff0,
+	&bcm5482_config,
+	&bcm5482_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_VSC8211 = {
 	"Vitesse VSC8211",
 	0xfc4b0,
@@ -423,6 +665,9 @@ static struct phy_info phy_info_generic = {
 };
 
 static struct phy_info *phy_info[] = {
+	&phy_info_BCM5461S,
+	&phy_info_BCM5464S,
+	&phy_info_BCM5482S,
 	&phy_info_VSC8211,
 	&phy_info_VSC8221,
 	&phy_info_VSC8244,
diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
index d18cc58..340527c 100644
--- a/drivers/net/fsl_phy.h
+++ b/drivers/net/fsl_phy.h
@@ -38,7 +38,9 @@
 #define PHY_EXT_PAGE_ACCESS	0x1f
 
 #define MII_BMCR_INIT           0x00001140
+#define MII_BMCR_RESTART	0x00001340
 #define MII_ADVERTISE_INIT	0x1e1
+#define MII_CTRL1000_INIT	0xe00
 
 /* MII Management Configuration Register */
 #define MIIMCFG_RESET_MGMT          0x80000000
@@ -100,6 +102,26 @@
 
 #define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
 
+/* Broadcom BCM54xx -- taken from linux sungem_phy */
+#define MIIM_BCM54xx_AUXCNTL			0x18
+#define MIIM_BCM54xx_AUXCNTL_ENCODE(val)	((val & 0x7) << 12)|(val & 0x7)
+#define MIIM_BCM54xx_AUXSTATUS			0x19
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK	0x0700
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT	8
+
+#define MIIM_BCM54XX_SHD			0x1c
+#define MIIM_BCM54XX_SHD_WRITE			0x8000
+#define MIIM_BCM54XX_SHD_VAL(x)			((x & 0x1f) << 10)
+#define MIIM_BCM54XX_SHD_DATA(x)		((x & 0x3ff) << 0)
+#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data)	\
+	(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
+	 MIIM_BCM54XX_SHD_DATA(data))
+
+#define MIIM_BCM54XX_EXP_DATA		0x15	/* Expansion register data */
+#define MIIM_BCM54XX_EXP_SEL		0x17	/* Expansion register select */
+#define MIIM_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
+#define MIIM_BCM54XX_EXP_SEL_ER		0x0f00	/* Expansion register select */
+
 /* Cicada Auxiliary Control/Status Register */
 #define MIIM_CIS8201_AUX_CONSTAT	0x1c
 #define MIIM_CIS8201_AUXCONSTAT_INIT	0x0004
-- 
1.6.4

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

* [U-Boot] [PATCH 13/14] PHY: add some Marvell phy support
  2011-01-27  4:52                       ` [U-Boot] [PATCH 12/14] PHY: add some Broadcom " Mingkai Hu
@ 2011-01-27  4:52                         ` Mingkai Hu
  2011-01-27  4:52                           ` [U-Boot] [PATCH 14/14] PHY: add some misc phy code support Mingkai Hu
  2011-01-27  5:44                           ` [U-Boot] [PATCH 13/14] PHY: add some Marvell phy support Macpaul Lin
  0 siblings, 2 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Port from tsec.c file to add support for m88e1011s, m88e1111s, m88e1118,
m88e1121r, m88e1145, m88e1149s.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/fsl_phy.c |  299 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fsl_phy.h |   36 ++++++
 2 files changed, 335 insertions(+), 0 deletions(-)

diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
index 7c22666..ad9d65e 100644
--- a/drivers/net/fsl_phy.c
+++ b/drivers/net/fsl_phy.c
@@ -457,6 +457,245 @@ static int bcm5482_startup(struct mii_info *mii_info)
 	return 0;
 }
 
+/* Marvell 88E1011S */
+static int m88e1011s_config(struct mii_info *mii_info)
+{
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+
+	tsec_phy_write(mii_info, 0, 0x1d, 0x1f);
+	tsec_phy_write(mii_info, 0, 0x1e, 0x200c);
+	tsec_phy_write(mii_info, 0, 0x1d, 0x5);
+	tsec_phy_write(mii_info, 0, 0x1e, 0);
+	tsec_phy_write(mii_info, 0, 0x1e, 0x100);
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+/* Parse the 88E1011's status register for speed and duplex
+ * information
+ */
+static uint m88e1011s_parse_status(struct mii_info *mii_info)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_88E1011_PHY_STATUS);
+
+	if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) &&
+		!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
+		int i = 0;
+
+		puts("Waiting for PHY realtime link");
+		while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
+			/* Timeout reached ? */
+			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts(" TIMEOUT !\n");
+				mii_info->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0) {
+				putc('.');
+			}
+			udelay(1000);
+			mii_reg = tsec_phy_read(mii_info, 0,
+					MIIM_88E1011_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
+			mii_info->link = 1;
+		else
+			mii_info->link = 0;
+	}
+
+	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_88E1011_PHYSTAT_SPEED;
+
+	switch (speed) {
+	case MIIM_88E1011_PHYSTAT_GBIT:
+		mii_info->speed = SPEED_1000;
+		break;
+	case MIIM_88E1011_PHYSTAT_100:
+		mii_info->speed = SPEED_100;
+		break;
+	default:
+		mii_info->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int m88e1011s_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	m88e1011s_parse_status(mii_info);
+
+	return 0;
+}
+
+/* Marvell 88E1111S */
+static int m88e1111s_config(struct mii_info *mii_info)
+{
+	int reg;
+
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+
+	if (mii_info->flags & TSEC_REDUCED) {
+		reg = tsec_phy_read(mii_info, 0, 0x1b);
+		reg = (reg & 0xfff0) | 0xb;
+		tsec_phy_write(mii_info, 0, 0x1b, reg);
+	} else {
+		tsec_phy_write(mii_info, 0, 0x1b, 0x1f);
+	}
+
+	tsec_phy_write(mii_info, 0, 0x14, 0x0cd2);
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+/* Marvell 88E1118 */
+static int m88e1118_config(struct mii_info *mii_info)
+{
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	/* Change Page Number */
+	tsec_phy_write(mii_info, 0, 0x16, 0x0002);
+	/* Delay RGMII TX and RX */
+	tsec_phy_write(mii_info, 0, 0x15, 0x1070);
+	/* Change Page Number */
+	tsec_phy_write(mii_info, 0, 0x16, 0x0003);
+	/* Adjust LED control */
+	tsec_phy_write(mii_info, 0, 0x10, 0x021e);
+	/* Change Page Number */
+	tsec_phy_write(mii_info, 0, 0x16, 0x0000);
+
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int m88e1118_startup(struct mii_info *mii_info)
+{
+	/* Change Page Number */
+	tsec_phy_write(mii_info, 0, 0x16, 0x0000);
+
+	genphy_update_link(mii_info);
+	m88e1011s_parse_status(mii_info);
+
+	return 0;
+}
+
+/* Marvell 88E1121R */
+static int m88e1121_config(struct mii_info *mii_info)
+{
+	int pg;
+
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+
+	/* Switch the page to access the led register */
+	pg = tsec_phy_read(mii_info, 0, MIIM_88E1121_PHY_PAGE);
+	tsec_phy_write(mii_info, 0, MIIM_88E1121_PHY_PAGE,
+			MIIM_88E1121_PHY_LED_PAGE);
+	/* Configure leds */
+	tsec_phy_write(mii_info, 0, MIIM_88E1121_PHY_LED_CTRL,
+			MIIM_88E1121_PHY_LED_DEF);
+	/* Restore the page pointer */
+	tsec_phy_write(mii_info, 0, MIIM_88E1121_PHY_PAGE, pg);
+
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+	/* Disable IRQs and de-assert interrupt */
+	tsec_phy_write(mii_info, 0, MIIM_88E1121_PHY_IRQ_EN, 0);
+	tsec_phy_read(mii_info, 0, MIIM_88E1121_PHY_IRQ_STATUS);
+
+	return 0;
+}
+
+/* Marvell 88E1145 */
+static int m88e1145_config(struct mii_info *mii_info)
+{
+	int reg;
+
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+
+	/* Errata E0, E1 */
+	tsec_phy_write(mii_info, 0, 29, 0x001b);
+	tsec_phy_write(mii_info, 0, 30, 0x418f);
+	tsec_phy_write(mii_info, 0, 29, 0x0016);
+	tsec_phy_write(mii_info, 0, 30, 0xa2da);
+
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+
+	tsec_phy_write(mii_info, 0, MIIM_88E1011_PHY_SCR,
+			MIIM_88E1011_PHY_MDI_X_AUTO);
+
+	reg = tsec_phy_read(mii_info, 0, MIIM_88E1145_PHY_EXT_CR);
+	if (mii_info->flags & TSEC_REDUCED)
+		reg |= MIIM_M88E1145_RGMII_RX_DELAY |
+			MIIM_M88E1145_RGMII_TX_DELAY;
+	tsec_phy_write(mii_info, 0, MIIM_88E1145_PHY_EXT_CR, reg);
+
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int m88e1145_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	tsec_phy_write(mii_info, 0, MIIM_88E1111_PHY_LED_CONTROL,
+			MIIM_88E1111_PHY_LED_DIRECT);
+	m88e1011s_parse_status(mii_info);
+
+	return 0;
+}
+
+/* Marvell 88E1149S */
+static int m88e1149_config(struct mii_info *mii_info)
+{
+	/* Reset and configure the PHY */
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+
+	tsec_phy_write(mii_info, 0, 0x1d, 0x1f);
+	tsec_phy_write(mii_info, 0, 0x1e, 0x200c);
+	tsec_phy_write(mii_info, 0, 0x1d, 0x5);
+	tsec_phy_write(mii_info, 0, 0x1e, 0x0);
+	tsec_phy_write(mii_info, 0, 0x1e, 0x100);
+
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
 /* Vitesse VSC8211 */
 static int vsc8211_config(struct mii_info *mii_info)
 {
@@ -601,6 +840,60 @@ static struct phy_info phy_info_BCM5482S = {
 	&genphy_shutdown,
 };
 
+static struct phy_info phy_info_M88E1011S = {
+	"Marvell 88E1011S",
+	0x1410c60,
+	0xffffff0,
+	&m88e1011s_config,
+	&m88e1011s_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_M88E1111S = {
+	"Marvell 88E1111S",
+	0x1410cc0,
+	0xffffff0,
+	&m88e1111s_config,
+	&m88e1011s_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_M88E1118 = {
+	"Marvell 88E1118",
+	0x1410e10,
+	0xffffff0,
+	&m88e1118_config,
+	&m88e1118_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_M88E1121R = {
+	"Marvell 88E1121R",
+	0x1410cb0,
+	0xffffff0,
+	&m88e1121_config,
+	&genphy_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_M88E1145 = {
+	"Marvell 88E1145",
+	0x1410cd0,
+	0xffffff0,
+	&m88e1145_config,
+	&m88e1145_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_M88E1149S = {
+	"Marvell 88E1149S",
+	0x1410ca0,
+	0xffffff0,
+	&m88e1149_config,
+	&m88e1011s_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_VSC8211 = {
 	"Vitesse VSC8211",
 	0xfc4b0,
@@ -668,6 +961,12 @@ static struct phy_info *phy_info[] = {
 	&phy_info_BCM5461S,
 	&phy_info_BCM5464S,
 	&phy_info_BCM5482S,
+	&phy_info_M88E1011S,
+	&phy_info_M88E1111S,
+	&phy_info_M88E1118,
+	&phy_info_M88E1121R,
+	&phy_info_M88E1145,
+	&phy_info_M88E1149S,
 	&phy_info_VSC8211,
 	&phy_info_VSC8221,
 	&phy_info_VSC8244,
diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
index 340527c..5e6d236 100644
--- a/drivers/net/fsl_phy.h
+++ b/drivers/net/fsl_phy.h
@@ -134,6 +134,42 @@
 #define MIIM_CIS8201_EXT_CON1		0x17
 #define MIIM_CIS8201_EXTCON1_INIT	0x0000
 
+/* 88E1011 PHY Status Register */
+#define MIIM_88E1011_PHY_STATUS		0x11
+#define MIIM_88E1011_PHYSTAT_SPEED	0xc000
+#define MIIM_88E1011_PHYSTAT_GBIT	0x8000
+#define MIIM_88E1011_PHYSTAT_100	0x4000
+#define MIIM_88E1011_PHYSTAT_DUPLEX	0x2000
+#define MIIM_88E1011_PHYSTAT_SPDDONE	0x0800
+#define MIIM_88E1011_PHYSTAT_LINK	0x0400
+
+#define MIIM_88E1011_PHY_SCR		0x10
+#define MIIM_88E1011_PHY_MDI_X_AUTO	0x0060
+
+/* 88E1111 PHY LED Control Register */
+#define MIIM_88E1111_PHY_LED_CONTROL	24
+#define MIIM_88E1111_PHY_LED_DIRECT	0x4100
+#define MIIM_88E1111_PHY_LED_COMBINE	0x411C
+
+/* 88E1121 PHY LED Control Register */
+#define MIIM_88E1121_PHY_LED_CTRL	16
+#define MIIM_88E1121_PHY_LED_PAGE	3
+#define MIIM_88E1121_PHY_LED_DEF	0x0030
+
+/* 88E1121 PHY IRQ Enable/Status Register */
+#define MIIM_88E1121_PHY_IRQ_EN		18
+#define MIIM_88E1121_PHY_IRQ_STATUS	19
+
+#define MIIM_88E1121_PHY_PAGE		22
+
+/* 88E1145 Extended PHY Specific Control Register */
+#define MIIM_88E1145_PHY_EXT_CR 20
+#define MIIM_M88E1145_RGMII_RX_DELAY	0x0080
+#define MIIM_M88E1145_RGMII_TX_DELAY	0x0002
+
+#define MIIM_88E1145_PHY_PAGE	29
+#define MIIM_88E1145_PHY_CAL_OV 30
+
 /* Entry for Vitesse VSC8244 regs starts here */
 /* Vitesse VSC8244 Auxiliary Control/Status Register */
 #define MIIM_VSC8244_AUX_CONSTAT	0x1c
-- 
1.6.4

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

* [U-Boot] [PATCH 14/14] PHY: add some misc phy code support
  2011-01-27  4:52                         ` [U-Boot] [PATCH 13/14] PHY: add some Marvell " Mingkai Hu
@ 2011-01-27  4:52                           ` Mingkai Hu
  2011-01-27  5:44                           ` [U-Boot] [PATCH 13/14] PHY: add some Marvell phy support Macpaul Lin
  1 sibling, 0 replies; 26+ messages in thread
From: Mingkai Hu @ 2011-01-27  4:52 UTC (permalink / raw)
  To: u-boot

Port from tsec.c file to add support for cis8201, cis8204, dm9161,
dp83865, ksz804, lxt971, rtl8211b.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
---
 drivers/net/fsl_phy.c |  356 ++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/fsl_phy.h |   57 ++++++++
 drivers/net/tsec.c    |   24 ++++
 3 files changed, 436 insertions(+), 1 deletions(-)

diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
index ad9d65e..3a8ebbc 100644
--- a/drivers/net/fsl_phy.c
+++ b/drivers/net/fsl_phy.c
@@ -457,6 +457,211 @@ static int bcm5482_startup(struct mii_info *mii_info)
 	return 0;
 }
 
+/* CIS8201 */
+static int cis8201_config(struct mii_info *mii_info)
+{
+	/* Override PHY config settings */
+	tsec_phy_write(mii_info, 0, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	tsec_phy_write(mii_info, 0, MIIM_CIS8201_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int cis8201_parse_status(struct mii_info *mii_info)
+{
+	int speed;
+	int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_CIS8201_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS8201_AUXCONSTAT_GBIT:
+		mii_info->speed = SPEED_1000;
+		break;
+	case MIIM_CIS8201_AUXCONSTAT_100:
+		mii_info->speed = SPEED_100;
+		break;
+	default:
+		mii_info->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int cis8201_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	cis8201_parse_status(mii_info);
+
+	return 0;
+}
+
+/* CIS8204 */
+static int __cis8204_fixled(struct mii_info *mii_info)
+{
+	return 0;
+}
+
+int cis8204_fixled(struct mii_info *mii_info)
+	__attribute__((weak, alias("__cis8204_fixled")));
+
+static int cis8204_config(struct mii_info *mii_info)
+{
+	/* Override PHY config settings */
+	tsec_phy_write(mii_info, 0, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_AUXCONSTAT_INIT);
+	/* Configure some basic stuff */
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	cis8204_fixled(mii_info);
+
+	if (mii_info->flags & TSEC_REDUCED)
+		tsec_phy_write(mii_info, 0, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT |
+				MIIM_CIS8204_EPHYCON_RGMII);
+	else
+		tsec_phy_write(mii_info, 0, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT);
+
+	return 0;
+}
+
+/* Davicom DM9161E */
+static int dm9161_config(struct mii_info *mii_info)
+{
+	tsec_phy_write(mii_info, 0, MII_BMCR, MIIM_DM9161_CR_STOP);
+	/* Do not bypass the scrambler/descrambler */
+	tsec_phy_write(mii_info, 0, MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT);
+	/* Clear 10BTCSR to default */
+	tsec_phy_write(mii_info, 0, MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT);
+
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+	/* Restart Auto Negotiation */
+	tsec_phy_write(mii_info, 0, MII_BMCR, MIIM_DM9161_CR_RSTAN);
+
+	return 0;
+}
+
+static int dm9161_parse_status(struct mii_info *mii_info)
+{
+	int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_DM9161_SCSR);
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
+		mii_info->speed = SPEED_100;
+	else
+		mii_info->speed = SPEED_10;
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dm9161_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	dm9161_parse_status(mii_info);
+
+	return 0;
+}
+
+/* NatSemi DP83865 */
+static int dp83865_config(struct mii_info *mii_info)
+{
+	return tsec_phy_write(mii_info, 0, MII_BMCR, MIIM_DP83865_CR_INIT);
+}
+
+static int dp83865_parse_status(struct mii_info *mii_info)
+{
+	int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_DP83865_LANR);
+
+	switch (mii_reg & MIIM_DP83865_SPD_MASK) {
+
+	case MIIM_DP83865_SPD_1000:
+		mii_info->speed = SPEED_1000;
+		break;
+
+	case MIIM_DP83865_SPD_100:
+		mii_info->speed = SPEED_100;
+		break;
+
+	default:
+		mii_info->speed = SPEED_10;
+		break;
+
+	}
+
+	if (mii_reg & MIIM_DP83865_DPX_FULL)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dp83865_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	dp83865_parse_status(mii_info);
+
+	return 0;
+}
+
+/* LXT971 */
+static int lxt971_parse_status(struct mii_info *mii_info)
+{
+	int mii_reg;
+	int speed;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_LXT971_SR2);
+	speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
+
+	switch (speed) {
+	case MIIM_LXT971_SR2_10HDX:
+		mii_info->speed = SPEED_10;
+		mii_info->duplex = DUPLEX_HALF;
+		break;
+	case MIIM_LXT971_SR2_10FDX:
+		mii_info->speed = SPEED_10;
+		mii_info->duplex = DUPLEX_FULL;
+		break;
+	case MIIM_LXT971_SR2_100HDX:
+		mii_info->speed = SPEED_100;
+		mii_info->duplex = DUPLEX_HALF;
+		break;
+	default:
+		mii_info->speed = SPEED_100;
+		mii_info->duplex = DUPLEX_FULL;
+	}
+
+	return 0;
+}
+
+static int lxt971_startup(struct mii_info *mii_info)
+{
+	genphy_update_link(mii_info);
+	lxt971_parse_status(mii_info);
+
+	return 0;
+}
+
 /* Marvell 88E1011S */
 static int m88e1011s_config(struct mii_info *mii_info)
 {
@@ -747,7 +952,86 @@ static int vsc8211_startup(struct mii_info *mii_info)
 
 	return 0;
 }
- 
+
+/* RealTek RTL8211B */
+static int rtl8211b_config(struct mii_info *mii_info)
+{
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
+	tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
+	tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
+	tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
+
+	return 0;
+}
+
+static int rtl8211b_parse_status(struct mii_info *mii_info)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = tsec_phy_read(mii_info, 0, MIIM_RTL8211B_PHY_STATUS);
+
+	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+		int i = 0;
+
+		/* in case of timeout ->link is cleared */
+		mii_info->link = 1;
+		puts("Waiting for PHY realtime link");
+		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+			/* Timeout reached ? */
+			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts(" TIMEOUT !\n");
+				mii_info->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0) {
+				putc('.');
+			}
+			udelay(1000);	/* 1 ms */
+			mii_reg = tsec_phy_read(mii_info, 0,
+					MIIM_RTL8211B_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
+			mii_info->link = 1;
+		else
+			mii_info->link = 0;
+	}
+
+	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
+		mii_info->duplex = DUPLEX_FULL;
+	else
+		mii_info->duplex = DUPLEX_HALF;
+
+	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
+
+	switch (speed) {
+	case MIIM_RTL8211B_PHYSTAT_GBIT:
+		mii_info->speed = SPEED_1000;
+		break;
+	case MIIM_RTL8211B_PHYSTAT_100:
+		mii_info->speed = SPEED_100;
+		break;
+	default:
+		mii_info->speed = SPEED_10;
+	}
+
+	return 0;
+}
+
+static int rtl8211b_startup(struct mii_info *mii_info)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(mii_info);
+	rtl8211b_parse_status(mii_info);
+
+	return 0;
+}
+
 /* Vitesse VSC8244 */
 static int vsc8244_parse_status(struct mii_info *mii_info)
 {
@@ -840,6 +1124,60 @@ static struct phy_info phy_info_BCM5482S = {
 	&genphy_shutdown,
 };
 
+static struct phy_info phy_info_CIS8201 = {
+	"CIS8201",
+	0xfc410,
+	0xffff0,
+	&cis8201_config,
+	&cis8201_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_CIS8204 = {
+	"Cicada Cis8204",
+	0xfc440,
+	0xffff0,
+	&cis8204_config,
+	&cis8201_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_DM9161 = {
+	"Davicom DM9161E",
+	0x181b880,
+	0xffffff0,
+	&dm9161_config,
+	&dm9161_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_DP83865 = {
+	"NatSemi DP83865",
+	0x20005c70,
+	0xfffffff0,
+	&dp83865_config,
+	&dp83865_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_KSZ804 = {
+	"Micrel KSZ804",
+	0x221510,
+	0xfffff0,
+	&genphy_config,
+	&genphy_startup,
+	&genphy_shutdown,
+};
+
+static struct phy_info phy_info_LXT971 = {
+	"LXT971",
+	0x1378e0,
+	0xfffff0,
+	&genphy_config,
+	&lxt971_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_M88E1011S = {
 	"Marvell 88E1011S",
 	0x1410c60,
@@ -894,6 +1232,15 @@ static struct phy_info phy_info_M88E1149S = {
 	&genphy_shutdown,
 };
 
+static struct phy_info phy_info_RTL8211B = {
+	"RealTek RTL8211B",
+	0x1cc910,
+	0xfffff0,
+	&rtl8211b_config,
+	&rtl8211b_startup,
+	&genphy_shutdown,
+};
+
 static struct phy_info phy_info_VSC8211 = {
 	"Vitesse VSC8211",
 	0xfc4b0,
@@ -961,12 +1308,19 @@ static struct phy_info *phy_info[] = {
 	&phy_info_BCM5461S,
 	&phy_info_BCM5464S,
 	&phy_info_BCM5482S,
+	&phy_info_CIS8201,
+	&phy_info_CIS8204,
+	&phy_info_DM9161,
+	&phy_info_DP83865,
+	&phy_info_KSZ804,
+	&phy_info_LXT971,
 	&phy_info_M88E1011S,
 	&phy_info_M88E1111S,
 	&phy_info_M88E1118,
 	&phy_info_M88E1121R,
 	&phy_info_M88E1145,
 	&phy_info_M88E1149S,
+	&phy_info_RTL8211B,
 	&phy_info_VSC8211,
 	&phy_info_VSC8221,
 	&phy_info_VSC8244,
diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
index 5e6d236..ba284e6 100644
--- a/drivers/net/fsl_phy.h
+++ b/drivers/net/fsl_phy.h
@@ -134,6 +134,54 @@
 #define MIIM_CIS8201_EXT_CON1		0x17
 #define MIIM_CIS8201_EXTCON1_INIT	0x0000
 
+/* Cicada 8204 Extended PHY Control Register 1 */
+#define MIIM_CIS8204_EPHY_CON		0x17
+#define MIIM_CIS8204_EPHYCON_INIT	0x0006
+#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
+
+/* Cicada 8204 Serial LED Control Register */
+#define MIIM_CIS8204_SLED_CON		0x1b
+#define MIIM_CIS8204_SLEDCON_INIT	0x1115
+
+#define MIIM_GBIT_CON		0x09
+#define MIIM_GBIT_CON_ADVERT	0x0e00
+
+/* DM9161 Control register values */
+#define MIIM_DM9161_CR_STOP	0x0400
+#define MIIM_DM9161_CR_RSTAN	0x1200
+
+#define MIIM_DM9161_SCR		0x10
+#define MIIM_DM9161_SCR_INIT	0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR	0x11
+#define MIIM_DM9161_SCSR_100F	0x8000
+#define MIIM_DM9161_SCSR_100H	0x4000
+#define MIIM_DM9161_SCSR_10F	0x2000
+#define MIIM_DM9161_SCSR_10H	0x1000
+
+/* DM9161 10BT Configuration/Status */
+#define MIIM_DM9161_10BTCSR	0x12
+#define MIIM_DM9161_10BTCSR_INIT	0x7800
+
+/* DP83865 Control register values */
+#define MIIM_DP83865_CR_INIT	0x9200
+
+/* DP83865 Link and Auto-Neg Status Register */
+#define MIIM_DP83865_LANR	0x11
+#define MIIM_DP83865_SPD_MASK	0x0018
+#define MIIM_DP83865_SPD_1000	0x0010
+#define MIIM_DP83865_SPD_100	0x0008
+#define MIIM_DP83865_DPX_FULL	0x0002
+
+/* LXT971 Status 2 registers */
+#define MIIM_LXT971_SR2		     0x11  /* Status Register 2  */
+#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
+#define MIIM_LXT971_SR2_10HDX	   0x0000  /*  10 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_10FDX	   0x0200  /*  10 Mbit full duplex selected */
+#define MIIM_LXT971_SR2_100HDX	   0x4000  /* 100 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_100FDX	   0x4200  /* 100 Mbit full duplex selected */
+
 /* 88E1011 PHY Status Register */
 #define MIIM_88E1011_PHY_STATUS		0x11
 #define MIIM_88E1011_PHYSTAT_SPEED	0xc000
@@ -170,6 +218,15 @@
 #define MIIM_88E1145_PHY_PAGE	29
 #define MIIM_88E1145_PHY_CAL_OV 30
 
+/* RTL8211B PHY Status Register */
+#define MIIM_RTL8211B_PHY_STATUS	0x11
+#define MIIM_RTL8211B_PHYSTAT_SPEED	0xc000
+#define MIIM_RTL8211B_PHYSTAT_GBIT	0x8000
+#define MIIM_RTL8211B_PHYSTAT_100	0x4000
+#define MIIM_RTL8211B_PHYSTAT_DUPLEX	0x2000
+#define MIIM_RTL8211B_PHYSTAT_SPDDONE	0x0800
+#define MIIM_RTL8211B_PHYSTAT_LINK	0x0400
+
 /* Entry for Vitesse VSC8244 regs starts here */
 /* Vitesse VSC8244 Auxiliary Control/Status Register */
 #define MIIM_VSC8244_AUX_CONSTAT	0x1c
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 6ed3e09..fd8829d 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -190,6 +190,30 @@ tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
 }
 #endif /* Multicast TFTP ? */
 
+/*
+ * Hack to write all 4 PHYs with the LED values
+ */
+int cis8204_fixled(struct mii_info *mii_info)
+{
+	uint phyid;
+	tsec_mii_t *regbase = mii_info->phyregs;
+	int timeout = 1000000;
+
+	for (phyid = 0; phyid < 4; phyid++) {
+		out_be32(&regbase->miimadd, (phyid << 8) | MIIM_CIS8204_SLED_CON);
+		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
+		asm("sync");
+
+		timeout = 1000000;
+		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--) ;
+	}
+
+	tsec_phy_write(mii_info, 0, MIIM_CIS8204_SLED_CON,
+			MIIM_CIS8204_SLEDCON_INIT);
+
+	return 0;
+}
+
 /* Initialized required registers to appropriate values, zeroing
  * those we don't care about (unless zero is bad, in which case,
  * choose a more appropriate value)
-- 
1.6.4

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

* [U-Boot] [PATCH 13/14] PHY: add some Marvell phy support
  2011-01-27  4:52                         ` [U-Boot] [PATCH 13/14] PHY: add some Marvell " Mingkai Hu
  2011-01-27  4:52                           ` [U-Boot] [PATCH 14/14] PHY: add some misc phy code support Mingkai Hu
@ 2011-01-27  5:44                           ` Macpaul Lin
  1 sibling, 0 replies; 26+ messages in thread
From: Macpaul Lin @ 2011-01-27  5:44 UTC (permalink / raw)
  To: u-boot

Hi Mingkai,

2011/1/27 Mingkai Hu <Mingkai.hu@freescale.com>

> Port from tsec.c file to add support for m88e1011s, m88e1111s, m88e1118,
> m88e1121r, m88e1145, m88e1149s.
>
> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> ---
>  drivers/net/fsl_phy.c |  299
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fsl_phy.h |   36 ++++++
>  2 files changed, 335 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
> index 7c22666..ad9d65e 100644
> --- a/drivers/net/fsl_phy.c
> +++ b/drivers/net/fsl_phy.c
> @@ -457,6 +457,245 @@ static int bcm5482_startup(struct mii_info *mii_info)
>        return 0;
>  }
>
> +/* Marvell 88E1011S */
> +static int m88e1011s_config(struct mii_info *mii_info)
> +{
> +       /* Reset and configure the PHY */
> +       tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
> +
> +       tsec_phy_write(mii_info, 0, 0x1d, 0x1f);
> +       tsec_phy_write(mii_info, 0, 0x1e, 0x200c);
> +       tsec_phy_write(mii_info, 0, 0x1d, 0x5);
> +       tsec_phy_write(mii_info, 0, 0x1e, 0);
> +       tsec_phy_write(mii_info, 0, 0x1e, 0x100);
> +       tsec_phy_write(mii_info, 0, MII_CTRL1000, MII_CTRL1000_INIT);
> +       tsec_phy_write(mii_info, 0, MII_ADVERTISE, MII_ADVERTISE_INIT);
> +
> +       tsec_phy_write(mii_info, 0, MII_BMCR, BMCR_RESET);
> +       tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
> +
> +       return 0;
> +}
>

Is this possible to assign the clear definition about bit fields with phy
registers
rather than hard-code hex value?
I think clear definitions will help both other vendor and your customers,
whom are the ODM/OEM vendors is easier to debug with these phy chips.

Hope you can agree with this suggestions.

-- 
Best regards,
Macpaul Lin

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

* [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode
  2011-01-27  4:52 [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Mingkai Hu
  2011-01-27  4:52 ` [U-Boot] [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl Mingkai Hu
@ 2011-01-27  6:04 ` Kumar Gala
  2011-01-27  6:09   ` Hu Mingkai-B21284
  1 sibling, 1 reply; 26+ messages in thread
From: Kumar Gala @ 2011-01-27  6:04 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> This patchset add support for the P4080's datapath accelation architecture
> in independent mode, and do some code refactor of the file tsec.c.
> 
> 1. Add the releated MAC controller support, includeing dTSEC and 10GEC
> 2. Add support for FMan ethernet in Independent mode
> 3. Add PHY support (VSC8244 and VSC8234) to a new file fsl_phy.c which
>  can be reused by other code, such tsec and uec code.
> 4. tsec code cleanup
> 5. Move all the PHY code in tsec.c to fsl_phy.c to make it reuseable.
> 
> Based on the latest WD's U-Boot tree. Tested on P4080DS and MPC8536DS
> board with SGMII card.
> 
> [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl
> [PATCH 02/14] powerpc/fman: add PHY support for dTSEC
> [PATCH 03/14] powerpc/fman: add dTSEC controller support
> [PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support
> [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode
> [PATCH 06/14] powerpc/corenet_ds: Add fman support
> [PATCH 07/14] tsec: use IO accessories to access the register
> [PATCH 08/14] tsec: arrange the code to avoid useless function declaration
> [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t)
> [PATCH 10/14] tsec: refactor the PHY code to make it reuseable
> [PATCH 11/14] PHY: add some Vitesse phy support
> [PATCH 12/14] PHY: add some Broadcom phy support
> [PATCH 13/14] PHY: add some Marvell phy support
> [PATCH 14/14] PHY: add some misc phy code support
> 
> Thanks,
> Mingkai

I suggest we re-order these patches to first deal with tsec changes and refactor of the phy code.  After which we should introduce fman driver code that shares fsl_phy.c

These patches also break some fundamental rules about patches:
1. some patches aren't used by anything
2. some patches break functionality

- k

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

* [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode
  2011-01-27  6:04 ` [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Kumar Gala
@ 2011-01-27  6:09   ` Hu Mingkai-B21284
  0 siblings, 0 replies; 26+ messages in thread
From: Hu Mingkai-B21284 @ 2011-01-27  6:09 UTC (permalink / raw)
  To: u-boot



> -----Original Message-----
> From: Kumar Gala [mailto:galak at kernel.crashing.org]
> Sent: Thursday, January 27, 2011 2:05 PM
> To: Hu Mingkai-B21284
> Cc: u-boot at lists.denx.de; Fleming Andy-AFLEMING; Zang Roy-R61911; Liu Dave-
> R63238; Medve Emilian-EMMEDVE1; Tabi Timur-B04825; Phillips Kim-R1AAHA; Haruki
> Dai-R35557; Radulescu Ruxandra Ioana-B05472
> Subject: Re: [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in
> Independent mode
> 
> 
> On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:
> 
> > This patchset add support for the P4080's datapath accelation
> > architecture in independent mode, and do some code refactor of the file tsec.c.
> >
> > 1. Add the releated MAC controller support, includeing dTSEC and 10GEC
> > 2. Add support for FMan ethernet in Independent mode 3. Add PHY
> > support (VSC8244 and VSC8234) to a new file fsl_phy.c which  can be
> > reused by other code, such tsec and uec code.
> > 4. tsec code cleanup
> > 5. Move all the PHY code in tsec.c to fsl_phy.c to make it reuseable.
> >
> > Based on the latest WD's U-Boot tree. Tested on P4080DS and MPC8536DS
> > board with SGMII card.
> >
> > [PATCH 01/14] powerpc/p4080: Add function to report which lane is used
> > for a prtcl [PATCH 02/14] powerpc/fman: add PHY support for dTSEC
> > [PATCH 03/14] powerpc/fman: add dTSEC controller support [PATCH 04/14]
> > powerpc/fman: add 10GEC controller and PHY support [PATCH 05/14]
> > powerpc/qoirq: Add support for FMan ethernet in Independent mode
> > [PATCH 06/14] powerpc/corenet_ds: Add fman support [PATCH 07/14] tsec:
> > use IO accessories to access the register [PATCH 08/14] tsec: arrange
> > the code to avoid useless function declaration [PATCH 09/14] tsec: use
> > general ethernet MII register struct(tsec_mii_t) [PATCH 10/14] tsec:
> > refactor the PHY code to make it reuseable [PATCH 11/14] PHY: add some
> > Vitesse phy support [PATCH 12/14] PHY: add some Broadcom phy support
> > [PATCH 13/14] PHY: add some Marvell phy support [PATCH 14/14] PHY: add
> > some misc phy code support
> >
> > Thanks,
> > Mingkai
> 
> I suggest we re-order these patches to first deal with tsec changes and refactor
> of the phy code.  After which we should introduce fman driver code that shares
> fsl_phy.c
> 
> These patches also break some fundamental rules about patches:
> 1. some patches aren't used by anything
> 2. some patches break functionality
> 

OK, I'll reorder the patchset and take care of the above rules in the next version.
Thanks for your comments.

Thanks,
Mingkai

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

* [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC
  2011-01-27  4:52   ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Mingkai Hu
  2011-01-27  4:52     ` [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support Mingkai Hu
@ 2011-01-27  6:15     ` Kumar Gala
  2011-01-27 16:10     ` Timur Tabi
  2 siblings, 0 replies; 26+ messages in thread
From: Kumar Gala @ 2011-01-27  6:15 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> From: Kumar Gala <galak@kernel.crashing.org>
> 
> Add VSC8244 and VSC8234 phy support, this will be reused
> by etsec code.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> ---
> arch/powerpc/include/asm/fsl_enet.h |   10 +
> drivers/net/fsl_phy.c               |  353 +++++++++++++++++++++++++++++++++++
> drivers/net/fsl_phy.h               |  176 +++++++++++++++++
> 3 files changed, 539 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/fsl_phy.c
> create mode 100644 drivers/net/fsl_phy.h
> 

General question should we use DTSEC name to match p4080 manual for this ?

> diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h
> index 4fb2857..9475249 100644
> --- a/arch/powerpc/include/asm/fsl_enet.h
> +++ b/arch/powerpc/include/asm/fsl_enet.h
> @@ -28,6 +28,16 @@ enum fsl_phy_enet_if {
> 	FSL_ETH_IF_NONE,
> };
> 
> +typedef struct tsec_mii_mng {

Wondering if we should use dtsec_ here since that matches P4080 Manual and possible removes some confusion with tsec enet controller.

> +	u32 miimcfg;		/* MII management configuration reg */
> +	u32 miimcom;		/* MII management command reg */
> +	u32 miimadd;		/* MII management address reg */
> +	u32 miimcon;		/* MII management control reg */
> +	u32 miimstat;		/* MII management status reg  */
> +	u32 miimind;		/* MII management indication reg */
> +	u32 ifstat;		/* Interface Status Register */
> +} __attribute__ ((packed))tsec_mii_t;
> +
> int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc);
> 
> #endif /* __ASM_PPC_FSL_ENET_H */
> diff --git a/drivers/net/fsl_phy.c b/drivers/net/fsl_phy.c
> new file mode 100644
> index 0000000..1ba0ce1
> --- /dev/null
> +++ b/drivers/net/fsl_phy.c
> @@ -0,0 +1,353 @@
> +/*
> + * Copyright 2009-2010 Freescale Semiconductor, Inc.
> + *	Jun-jie Zhang <b18070@freescale.com>
> + *	Mingkai Hu <Mingkai.hu@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 <asm/errno.h>
> +
> +#include "fsl_phy.h"
> +
> +void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr,
> +		int dev_addr, int regnum, int value)
> +{
> +	int timeout = 1000000;
> +
> +	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
> +	out_be32(&phyregs->miimcon, value);
> +	asm("sync");
> +
> +	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--);
> +}
> +
> +int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr,
> +		int dev_addr, int regnum)
> +{
> +	int value;
> +	int timeout = 1000000;
> +
> +	/* Put the address of the phy, and the register
> +	 * number into MIIMADD */
> +	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
> +
> +	/* Clear the command register, and wait */
> +	out_be32(&phyregs->miimcom, 0);
> +	asm("sync");
> +
> +	/* Initiate a read command, and wait */
> +	out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE);
> +	asm("sync");
> +
> +	/* Wait for the the indication that the read is done */
> +	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
> +			&& timeout--);
> +
> +	/* Grab the value read from the PHY */
> +	value = in_be32(&phyregs->miimstat);
> +
> +	return value;
> +}
> +
> +int tsec_phy_read(struct mii_info *mii_info, int dev_addr, int regnum)
> +{
> +	tsec_mii_t *phyregs = mii_info->phyregs;
> +
> +	return tsec_local_mdio_read(phyregs, mii_info->mii_id, dev_addr,
> +			regnum);
> +}
> +
> +int tsec_phy_write(struct mii_info *mii_info, int dev_addr, int regnum,
> +			int value)
> +{
> +	tsec_mii_t *phyregs = mii_info->phyregs;
> +
> +	tsec_local_mdio_write(phyregs, mii_info->mii_id, dev_addr, regnum,
> +		value);
> +
> +	return 0;
> +}
> +
> +static int genphy_config(struct mii_info *mii_info)
> +{
> +	return tsec_phy_write(mii_info, 0, MII_BMCR, MII_BMCR_INIT);
> +}
> +
> +/**
> + * genphy_update_link - update link status in @phydev
> + * @phydev: target phy_device struct
> + *
> + * Description: Update the value in phydev->link to reflect the
> + *   current link value.  In order to do this, we need to read
> + *   the status register twice, keeping the second value.
> + */
> +static int genphy_update_link(struct mii_info *phydev)
> +{
> +	unsigned int mii_reg;
> +
> +	/*
> +	 * Wait if the link is up, and autonegotiation is in progress
> +	 * (ie - we're capable and it's not done)
> +	 */
> +	mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
> +
> +	/*
> +	 * If we already saw the link up, and it hasn't gone down, then
> +	 * we don't need to wait for autoneg again
> +	 */
> +	if (phydev->link && mii_reg & BMSR_LSTATUS)
> +		return 0;
> +
> +	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
> +		int i = 0;
> +
> +		printf("%s Waiting for PHY auto negotiation to complete",
> +			phydev->dev->name);
> +		while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
> +			/*
> +			 * Timeout reached ?
> +			 */
> +			if (i > 5000) {
> +				printf(" TIMEOUT !\n");
> +				phydev->link = 0;
> +				return 0;
> +			}
> +
> +			if (ctrlc()) {
> +				puts("user interrupt!\n");
> +				phydev->link = 0;
> +				return -EINTR;
> +			}
> +
> +			if ((i++ % 500) == 0)
> +				printf(".");
> +
> +			udelay(1000);	/* 1 ms */
> +			mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
> +		}
> +		printf(" done\n");
> +		phydev->link = 1;
> +		udelay(500000);	/* another 500 ms (results in faster booting) */
> +	} else {
> +		/* Read the link a second time to clear the latched state */
> +		mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
> +
> +		if (mii_reg & BMSR_LSTATUS)
> +			phydev->link = 1;
> +		else
> +			phydev->link = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Generic function which updates the speed and duplex.  If
> + * autonegotiation is enabled, it uses the AND of the link
> + * partner's advertised capabilities and our advertised
> + * capabilities.  If autonegotiation is disabled, we use the
> + * appropriate bits in the control register.
> + *
> + * Stolen from Linux's mii.c and phy_device.c
> + */
> +static int genphy_parse_link(struct mii_info *phydev)
> +{
> +	int mii_reg = tsec_phy_read(phydev, 0, MII_BMSR);
> +
> +	/* We're using autonegotiation */
> +	if (mii_reg & BMSR_ANEGCAPABLE) {
> +		u32 lpa = 0;
> +		u32 gblpa = 0;
> +
> +		/* Check for gigabit capability */
> +		if (mii_reg & BMSR_ERCAP) {
> +			/* We want a list of states supported by
> +			 * both PHYs in the link
> +			 */
> +			gblpa = tsec_phy_read(phydev, 0, MII_STAT1000);
> +			gblpa &= tsec_phy_read(phydev, 0, MII_CTRL1000) << 2;
> +		}
> +
> +		/* Set the baseline so we only have to set them
> +		 * if they're different
> +		 */
> +		phydev->speed = SPEED_10;
> +		phydev->duplex = DUPLEX_HALF;
> +
> +		/* Check the gigabit fields */
> +		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
> +			phydev->speed = SPEED_1000;
> +
> +			if (gblpa & PHY_1000BTSR_1000FD)
> +				phydev->duplex = DUPLEX_FULL;
> +
> +			/* We're done! */
> +			return 0;
> +		}
> +
> +		lpa = tsec_phy_read(phydev, 0, MII_ADVERTISE);
> +		lpa &= tsec_phy_read(phydev, 0, MII_LPA);
> +
> +		if (lpa & (LPA_100FULL | LPA_100HALF)) {
> +			phydev->speed = SPEED_100;
> +
> +			if (lpa & LPA_100FULL)
> +				phydev->duplex = DUPLEX_FULL;
> +
> +		} else if (lpa & LPA_10FULL)
> +			phydev->duplex = DUPLEX_FULL;
> +	} else {
> +		u32 bmcr = tsec_phy_read(phydev, 0, MII_BMCR);
> +
> +		phydev->speed = SPEED_10;
> +		phydev->duplex = DUPLEX_HALF;
> +
> +		if (bmcr & BMCR_FULLDPLX)
> +			phydev->duplex = DUPLEX_FULL;
> +
> +		if (bmcr & BMCR_SPEED1000)
> +			phydev->speed = SPEED_1000;
> +		else if (bmcr & BMCR_SPEED100)
> +			phydev->speed = SPEED_100;
> +	}
> +
> +	return 0;
> +}
> +
> +static int genphy_startup(struct mii_info *phydev)
> +{
> +	genphy_update_link(phydev);
> +	genphy_parse_link(phydev);
> +
> +	return 0;
> +}
> +
> +static int genphy_shutdown(struct mii_info *phydev)
> +{
> +	return 0;
> +}
> +
> +/* Vitesse VSC8244 */
> +static int vsc8244_parse_status(struct mii_info *mii_info)
> +{
> +	unsigned int speed;
> +	unsigned int mii_reg;
> +
> +	mii_reg = tsec_phy_read(mii_info, 0, MIIM_VSC8244_AUX_CONSTAT);
> +
> +	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
> +		mii_info->duplex = DUPLEX_FULL;
> +	else
> +		mii_info->duplex = DUPLEX_HALF;
> +
> +	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
> +	switch (speed) {
> +	case MIIM_VSC8244_AUXCONSTAT_GBIT:
> +		mii_info->speed = SPEED_1000;
> +		break;
> +	case MIIM_VSC8244_AUXCONSTAT_100:
> +		mii_info->speed = SPEED_100;
> +		break;
> +	default:
> +		mii_info->speed = SPEED_10;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int vsc8244_startup(struct mii_info *mii_info)
> +{
> +	/* Read the Status (2x to make sure link is right) */
> +	genphy_update_link(mii_info);
> +	vsc8244_parse_status(mii_info);
> +
> +	return 0;
> +}
> +
> +static struct phy_info phy_info_VSC8244 = {
> +	"Vitesse VSC8244",
> +	0xfc6c0,
> +	0xffff0,
> +	&genphy_config,
> +	&vsc8244_startup,
> +	&genphy_shutdown,
> +};
> +
> +static struct phy_info phy_info_VSC8234 = {
> +	"Vitesse VSC8234",
> +	0xfc620,
> +	0xffff0,
> +	&genphy_config,
> +	&vsc8244_startup,
> +	&genphy_shutdown,
> +};
> +
> +static struct phy_info phy_info_generic = {
> +	"Unknown/Generic PHY",
> +	0x0,
> +	0x0,
> +	&genphy_config,
> +	&genphy_startup,
> +	&genphy_shutdown,
> +};
> +
> +static struct phy_info *phy_info[] = {
> +	&phy_info_VSC8244,
> +	&phy_info_VSC8234,
> +	&phy_info_generic
> +};
> +
> +/*
> + * Use the PHY ID registers to determine what type of PHY is attached
> + * to device dev.  return a struct phy_info structure describing that PHY
> + */
> +struct phy_info *tsec_get_phy_info(struct mii_info *mii_info)
> +{
> +	u16 phy_reg;
> +	u32 phy_ID;
> +	int i;
> +	struct phy_info *theInfo = NULL;
> +
> +	/* Grab the bits from PHYIR1, and put them in the upper half */
> +	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID1);
> +	phy_ID = (phy_reg & 0xffff) << 16;
> +
> +	/* Grab the bits from PHYIR2, and put them in the lower half */
> +	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID2);
> +	phy_ID |= (phy_reg & 0xffff);
> +
> +	/* loop through all the known PHY types, and find one that */
> +	/* matches the ID we read from the PHY. */
> +	for (i = 0; i < ARRAY_SIZE(phy_info); i++)
> +		if ((phy_info[i]->uid & phy_info[i]->mask) ==
> +				(phy_ID & phy_info[i]->mask)) {
> +			theInfo = phy_info[i];
> +			break;
> +		}
> +
> +	if (theInfo == &phy_info_generic) {
> +		printf("%s: No support for PHY id %x; assuming generic\n",
> +				mii_info->dev->name, phy_ID);
> +	} else {
> +		printf("%s: PHY is %s (%x)\n", mii_info->dev->name,
> +				theInfo->name, phy_ID);
> +	}
> +
> +	return theInfo;
> +}
> diff --git a/drivers/net/fsl_phy.h b/drivers/net/fsl_phy.h
> new file mode 100644
> index 0000000..8a8b6e8
> --- /dev/null
> +++ b/drivers/net/fsl_phy.h
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright 2009-2010 Freescale Semiconductor, Inc.
> + *	Jun-jie Zhang <b18070@freescale.com>
> + *	Mingkai Hu <Mingkai.hu@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 __FSL_PHY_H__
> +#define __FSL_PHY_H__
> +
> +#include <net.h>
> +#include <miiphy.h>
> +#include <asm/fsl_enet.h>


We need to utilize <linux/mii.h>

> +
> +/* Duplex, half or full. */
> +#define DUPLEX_HALF		0x00
> +#define DUPLEX_FULL		0x01
> +
> +#define PORT_TP		0x00
> +#define PORT_AUI	0x01
> +#define PORT_MII	0x02
> +#define PORT_FIBRE	0x03
> +
> +#define MII_BMCR_INIT           0x00001140
> +
> +/* MII Management Configuration Register */
> +#define MIIMCFG_RESET_MGMT          0x80000000
> +#define MIIMCFG_MGMT_CLOCK_SELECT   0x00000007
> +#define MIIMCFG_INIT_VALUE	    0x00000003
> +
> +/* MII Management Command Register */
> +#define MIIMCOM_READ_CYCLE	0x00000001
> +#define MIIMCOM_SCAN_CYCLE	0x00000002
> +
> +/* MII Management Address Register */
> +#define MIIMADD_PHY_ADDR_SHIFT	8
> +
> +/* MII Management Indicator Register */
> +#define MIIMIND_BUSY		0x00000001
> +#define MIIMIND_NOTVALID	0x00000004
> +
> +#define AUTONEG_DISABLE		0x00
> +#define AUTONEG_ENABLE		0x01
> +#define SPEED_10		10
> +#define SPEED_100		100
> +#define SPEED_1000		1000
> +#define SPEED_2500		2500
> +#define SPEED_10000		10000
> +#define SUPPORTED_10baseT_Half		(1 << 0)
> +#define SUPPORTED_10baseT_Full		(1 << 1)
> +#define SUPPORTED_100baseT_Half		(1 << 2)
> +#define SUPPORTED_100baseT_Full		(1 << 3)
> +#define SUPPORTED_1000baseT_Half	(1 << 4)
> +#define SUPPORTED_1000baseT_Full	(1 << 5)
> +#define SUPPORTED_Autoneg		(1 << 6)
> +#define SUPPORTED_TP			(1 << 7)
> +#define SUPPORTED_AUI			(1 << 8)
> +#define SUPPORTED_MII			(1 << 9)
> +#define SUPPORTED_FIBRE			(1 << 10)
> +#define SUPPORTED_BNC			(1 << 11)
> +#define SUPPORTED_10000baseT_Full	(1 << 12)
> +#define SUPPORTED_Pause			(1 << 13)
> +#define SUPPORTED_Asym_Pause		(1 << 14)
> +#define SUPPORTED_2500baseX_Full	(1 << 15)
> +
> +/* Indicates what features are advertised by the interface. */
> +#define ADVERTISED_10baseT_Half		(1 << 0)
> +#define ADVERTISED_10baseT_Full		(1 << 1)
> +#define ADVERTISED_100baseT_Half	(1 << 2)
> +#define ADVERTISED_100baseT_Full	(1 << 3)
> +#define ADVERTISED_1000baseT_Half	(1 << 4)
> +#define ADVERTISED_1000baseT_Full	(1 << 5)
> +#define ADVERTISED_Autoneg		(1 << 6)
> +#define ADVERTISED_TP			(1 << 7)
> +#define ADVERTISED_AUI			(1 << 8)
> +#define ADVERTISED_MII			(1 << 9)
> +#define ADVERTISED_FIBRE		(1 << 10)
> +#define ADVERTISED_BNC			(1 << 11)
> +#define ADVERTISED_10000baseT_Full	(1 << 12)
> +#define ADVERTISED_Pause		(1 << 13)
> +#define ADVERTISED_Asym_Pause		(1 << 14)
> +#define ADVERTISED_2500baseX_Full	(1 << 15)
> +
> +#define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
> +
> +/* Entry for Vitesse VSC8244 regs starts here */
> +/* Vitesse VSC8244 Auxiliary Control/Status Register */
> +#define MIIM_VSC8244_AUX_CONSTAT	0x1c
> +#define MIIM_VSC8244_AUXCONSTAT_INIT	0x0000
> +#define MIIM_VSC8244_AUXCONSTAT_DUPLEX	0x0020
> +#define MIIM_VSC8244_AUXCONSTAT_SPEED	0x0018
> +#define MIIM_VSC8244_AUXCONSTAT_GBIT	0x0010
> +#define MIIM_VSC8244_AUXCONSTAT_100	0x0008
> +#define MIIM_CONTROL_INIT_LOOPBACK	0x4000
> +
> +struct mii_info {
> +	/* Information about the PHY type */
> +	/* And management functions */
> +	struct phy_info *phyinfo;
> +	void *phyregs;
> +
> +	struct eth_device *dev;
> +
> +	/* forced speed & duplex (no autoneg)
> +	 * partner speed & duplex & pause (autoneg)
> +	 */
> +	int speed;
> +	int duplex;
> +
> +	/* The most recently read link state */
> +	int link;
> +	int port;
> +
> +	u32 advertising;
> +	int autoneg;
> +	int mii_id;
> +	u32 flags;
> +
> +	/* private data pointer */
> +	/* For use by PHYs to maintain extra state */
> +	void *priv;
> +
> +	/* Provided by ethernet driver */
> +	int (*mdio_read)(struct eth_device *dev, int mii_id, int reg);
> +	void (*mdio_write)(struct eth_device *dev, int mii_id, int reg,
> +			    int val);
> +};
> +
> +/* struct phy_info: a structure which defines attributes for a PHY
> + *
> + * id will contain a number which represents the PHY.  During
> + * startup, the driver will poll the PHY to find out what its
> + * UID--as defined by registers 2 and 3--is.  The 32-bit result
> + * gotten from the PHY will be masked to
> + * discard any bits which may change based on revision numbers
> + * unimportant to functionality
> + *
> + */
> +struct phy_info {
> +	char *name;
> +	unsigned int uid;
> +	unsigned int mask;
> +	/* Called to configure the PHY, and modify the controller
> +	 * based on the results */
> +	int (*config)(struct mii_info *mii_info);
> +
> +	/* Called when starting up the controller */
> +	int (*startup)(struct mii_info *mii_info);
> +
> +	/* Called when bringing down the controller */
> +	int (*shutdown)(struct mii_info *mii_info);
> +};
> +
> +struct phy_info *tsec_get_phy_info(struct mii_info *mii_info);
> +void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr, int dev_addr,
> +		int reg, int value);
> +int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr, int dev_addr,
> +		int regnum);
> +int tsec_phy_read(struct mii_info *mii_info, int dev_addr, int regnum);
> +int tsec_phy_write(struct mii_info *mii_info, int dev_addr, int regnum,
> +		int value);
> +#endif /* __FSL_PHY_H__ */
> +
> -- 
> 1.6.4
> 

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

* [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC
  2011-01-27  4:52   ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Mingkai Hu
  2011-01-27  4:52     ` [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support Mingkai Hu
  2011-01-27  6:15     ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Kumar Gala
@ 2011-01-27 16:10     ` Timur Tabi
  2 siblings, 0 replies; 26+ messages in thread
From: Timur Tabi @ 2011-01-27 16:10 UTC (permalink / raw)
  To: u-boot

Mingkai Hu wrote:
> +	u16 phy_reg;
> +	u32 phy_ID;
> +	int i;
> +	struct phy_info *theInfo = NULL;
> +
> +	/* Grab the bits from PHYIR1, and put them in the upper half */
> +	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID1);
> +	phy_ID = (phy_reg & 0xffff) << 16;
> +
> +	/* Grab the bits from PHYIR2, and put them in the lower half */
> +	phy_reg = tsec_phy_read(mii_info, 0, MII_PHYSID2);
> +	phy_ID |= (phy_reg & 0xffff);

The "& 0xffff" is unnecessary since phy_reg is a u16, so it can never be larger
than 0xffff.

> +			theInfo = phy_info[i];

CamelCase variables?

> + * Copyright 2009-2010 Freescale Semiconductor, Inc.

Should any of these be 2011?

-- 
Timur Tabi
Linux kernel developer at Freescale

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

* [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode
  2011-01-27  4:52         ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Mingkai Hu
  2011-01-27  4:52           ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Mingkai Hu
@ 2011-01-27 17:40           ` Timur Tabi
  1 sibling, 0 replies; 26+ messages in thread
From: Timur Tabi @ 2011-01-27 17:40 UTC (permalink / raw)
  To: u-boot

Mingkai Hu wrote:
> +LIB	:= $(obj)libfm.a

Libraries are now .o files, not .a files.  Take a look at the other Makefiles to
see how they've recently changed.

> +u32 fm_muram_alloc(struct fm_muram *mem, u32 size, u32 align)
> +{
> +	u32 ret;
> +	u32 align_mask, off;
> +	u32 save;
> +
> +	align_mask = align - 1;
> +	save = mem->alloc;
> +
> +	if ((off = (save & align_mask)) != 0)
> +		mem->alloc += (align - off);
> +	if ((off = size & align_mask) != 0)
> +		size += (align - off);
> +	if ((mem->alloc + size) >= mem->top) {
> +		mem->alloc = save;
> +		printf("%s: run out of ram.\n", __func__);
> +	}

What exactly happens here?  If you run out of memory, you return a pointer
anyway?  Shouldn't you return NULL here or something?

> +	/* 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) {
> +			printf("Fman: Uploading microcode version %u.%u.%u.\n",
> +			       ucode->major, ucode->minor, ucode->revision);
> +			fm->ucode = (void *) CONFIG_SYS_FMAN_FW_ADDR +
> +				ucode->code_offset;

Just FYI, this code will only work on systems that have NOR flash mapped to I/O
space.  If the customer boots from NAND and doesn't have any NOR flash on his
board, then CONFIG_SYS_FMAN_FW_ADDR will be invalid.  In addition, I don't see
any code that passes the value of CONFIG_SYS_FMAN_FW_ADDR to the kernel via
"fman_ucode".

> +	/* setup TxBD */
> +	txbd->buf_ptr_hi = 0;
> +	txbd->buf_ptr_lo = (u32)buf;
> +	txbd->len = len;
> +	__asm__ __volatile__ ("sync");

Why do we sometimes do "asm("sync");" and sometimes we do "__asm__ __volatile__
("sync");"?  And why do we have hard-coded asm anyway?  There is a sync()
function that does this already.


> +	txbd->status = TxBD_READY | TxBD_LAST;
> +	__asm__ __volatile__ ("sync");
> +
> +	/* update TxQD, let RISC to send the packet */
> +	offset_in = muram_readw(&pram->txqd.offset_in);
> +	offset_in += SIZEOFBD;
> +	if (offset_in >= muram_readw(&pram->txqd.bd_ring_size))
> +		offset_in = 0;
> +	muram_writew(&pram->txqd.offset_in, offset_in);
> +	__asm__ __volatile__ ("sync");
> +
> +	/* wait for buffer to be transmitted */
> +	for (i = 0; txbd->status & TxBD_READY; i++) {
> +		udelay(1000);
> +		if (i > 0x10000) {
> +			printf("%s: Tx error\n", dev->name);
> +			return 0;
> +		}
> +	}

If you're going to do a timeout, do it the same way everyone else does.  Start
with the timeout value, and decrement the variable.  Something like this:

	timeout = 0x10000; (why a hex number anyway?)
	while (!(txbd->status & TxBD_READY) && --timeout)
		udelay(1000);

> +static void
> +__def_board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
> +				enum fm_port port, int offset)
> +{
> +	return ;

Delete this "return ;".  It doesn't do anything.

-- 
Timur Tabi
Linux kernel developer at Freescale

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

* [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support
  2011-01-27  4:52           ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Mingkai Hu
  2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
@ 2011-01-27 17:42             ` Timur Tabi
  1 sibling, 0 replies; 26+ messages in thread
From: Timur Tabi @ 2011-01-27 17:42 UTC (permalink / raw)
  To: u-boot

Mingkai Hu wrote:
> +enum board_slots {
> +	SLOT1 = 1,
> +	SLOT2,
> +	SLOT3,
> +	SLOT4,
> +	SLOT5,
> +	SLOT6,
> +};

This is silly.  SLOT1 == 1, SLOT2 == 2, etc.  Just delete this enum and use numbers.

-- 
Timur Tabi
Linux kernel developer at Freescale

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

* [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register
  2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
@ 2011-02-02 22:47               ` Andy Fleming
  2011-02-05 20:26               ` Kumar Gala
  2 siblings, 0 replies; 26+ messages in thread
From: Andy Fleming @ 2011-02-02 22:47 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>

Acked-by: Andy Fleming <afleming@freescale.com>

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

* [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
  2011-01-27  4:52                 ` [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t) Mingkai Hu
@ 2011-02-02 22:48                 ` Andy Fleming
  2011-02-05 20:26                 ` Kumar Gala
  2 siblings, 0 replies; 26+ messages in thread
From: Andy Fleming @ 2011-02-02 22:48 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>

Acked-by: Andy Fleming <afleming@freescale.com>

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

* [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register
  2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
  2011-02-02 22:47               ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Andy Fleming
@ 2011-02-05 20:26               ` Kumar Gala
  2 siblings, 0 replies; 26+ messages in thread
From: Kumar Gala @ 2011-02-05 20:26 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> ---
> drivers/net/tsec.c |  232 ++++++++++++++++++++++++++-------------------------
> include/tsec.h     |    6 +-
> 2 files changed, 121 insertions(+), 117 deletions(-)

applied to 85xx next

- k

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

* [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration
  2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
  2011-01-27  4:52                 ` [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t) Mingkai Hu
  2011-02-02 22:48                 ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Andy Fleming
@ 2011-02-05 20:26                 ` Kumar Gala
  2 siblings, 0 replies; 26+ messages in thread
From: Kumar Gala @ 2011-02-05 20:26 UTC (permalink / raw)
  To: u-boot


On Jan 26, 2011, at 10:52 PM, Mingkai Hu wrote:

> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> ---
> drivers/net/tsec.c |  857 +++++++++++++++++++++++++---------------------------
> 1 files changed, 416 insertions(+), 441 deletions(-)

applied to 85xx next

- k

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

end of thread, other threads:[~2011-02-05 20:26 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-27  4:52 [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Mingkai Hu
2011-01-27  4:52 ` [U-Boot] [PATCH 01/14] powerpc/p4080: Add function to report which lane is used for a prtcl Mingkai Hu
2011-01-27  4:52   ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Mingkai Hu
2011-01-27  4:52     ` [U-Boot] [PATCH 03/14] powerpc/fman: add dTSEC controller support Mingkai Hu
2011-01-27  4:52       ` [U-Boot] [PATCH 04/14] powerpc/fman: add 10GEC controller and PHY support Mingkai Hu
2011-01-27  4:52         ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Mingkai Hu
2011-01-27  4:52           ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Mingkai Hu
2011-01-27  4:52             ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Mingkai Hu
2011-01-27  4:52               ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Mingkai Hu
2011-01-27  4:52                 ` [U-Boot] [PATCH 09/14] tsec: use general ethernet MII register struct(tsec_mii_t) Mingkai Hu
2011-01-27  4:52                   ` [U-Boot] [PATCH 10/14] tsec: refactor the PHY code to make it reuseable Mingkai Hu
2011-01-27  4:52                     ` [U-Boot] [PATCH 11/14] PHY: add some Vitesse phy support Mingkai Hu
2011-01-27  4:52                       ` [U-Boot] [PATCH 12/14] PHY: add some Broadcom " Mingkai Hu
2011-01-27  4:52                         ` [U-Boot] [PATCH 13/14] PHY: add some Marvell " Mingkai Hu
2011-01-27  4:52                           ` [U-Boot] [PATCH 14/14] PHY: add some misc phy code support Mingkai Hu
2011-01-27  5:44                           ` [U-Boot] [PATCH 13/14] PHY: add some Marvell phy support Macpaul Lin
2011-02-02 22:48                 ` [U-Boot] [PATCH 08/14] tsec: arrange the code to avoid useless function declaration Andy Fleming
2011-02-05 20:26                 ` Kumar Gala
2011-02-02 22:47               ` [U-Boot] [PATCH 07/14] tsec: use IO accessories to access the register Andy Fleming
2011-02-05 20:26               ` Kumar Gala
2011-01-27 17:42             ` [U-Boot] [PATCH 06/14] powerpc/corenet_ds: Add fman support Timur Tabi
2011-01-27 17:40           ` [U-Boot] [PATCH 05/14] powerpc/qoirq: Add support for FMan ethernet in Independent mode Timur Tabi
2011-01-27  6:15     ` [U-Boot] [PATCH 02/14] powerpc/fman: add PHY support for dTSEC Kumar Gala
2011-01-27 16:10     ` Timur Tabi
2011-01-27  6:04 ` [U-Boot] [PATCH 00/14] powerpc/p4080: add support for FMan ethernet in Independent mode Kumar Gala
2011-01-27  6:09   ` Hu Mingkai-B21284

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