From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mingkai Hu Date: Thu, 27 Jan 2011 12:52:52 +0800 Subject: [U-Boot] [PATCH 14/14] PHY: add some misc phy code support In-Reply-To: <1296103972-2696-14-git-send-email-Mingkai.hu@freescale.com> References: <1296103972-2696-1-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-2-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-3-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-4-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-5-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-6-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-7-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-8-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-9-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-10-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-11-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-12-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-13-git-send-email-Mingkai.hu@freescale.com> <1296103972-2696-14-git-send-email-Mingkai.hu@freescale.com> Message-ID: <1296103972-2696-15-git-send-email-Mingkai.hu@freescale.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Port from tsec.c file to add support for cis8201, cis8204, dm9161, dp83865, ksz804, lxt971, rtl8211b. Signed-off-by: Mingkai Hu --- 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(®base->miimadd, (phyid << 8) | MIIM_CIS8204_SLED_CON); + out_be32(®base->miimcon, MIIM_CIS8204_SLEDCON_INIT); + asm("sync"); + + timeout = 1000000; + while ((in_be32(®base->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