[U-Boot] [PATCH 14/14] PHY: add some misc phy code support

Mingkai Hu Mingkai.hu at freescale.com
Thu Jan 27 05:52:52 CET 2011


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

Signed-off-by: Mingkai Hu <Mingkai.hu at 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




More information about the U-Boot mailing list