diff options
Diffstat (limited to 'arch/arm/mach-davinci/lxt972.c')
-rw-r--r-- | arch/arm/mach-davinci/lxt972.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/lxt972.c b/arch/arm/mach-davinci/lxt972.c new file mode 100644 index 0000000..a7356f9 --- /dev/null +++ b/arch/arm/mach-davinci/lxt972.c @@ -0,0 +1,113 @@ +/* + * Intel LXT971/LXT972 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <net.h> +#include <miiphy.h> +#include <lxt971a.h> +#include <asm/arch/emac_defs.h> +#include "../../../drivers/net/davinci_emac.h" + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +int lxt972_is_phy_connected(int phy_addr) +{ + u_int16_t id1, id2; + + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID1, &id1)) + return(0); + if (!davinci_eth_phy_read(phy_addr, MII_PHYSID2, &id2)) + return(0); + + if ((id1 == (0x0013)) && ((id2 & 0xfff0) == 0x78e0)) + return(1); + + return(0); +} + +int lxt972_get_link_speed(int phy_addr) +{ + u_int16_t stat1, tmp; + volatile emac_regs *emac = (emac_regs *)EMAC_BASE_ADDR; + + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1)) + return(0); + + if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link up? */ + return(0); + + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) + return(0); + + tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE; + + davinci_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp); + /* Read back */ + if (!davinci_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) + return(0); + + /* Speed doesn't matter, there is no setting for it in EMAC... */ + if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { + /* set DM644x EMAC for Full Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | + EMAC_MACCONTROL_FULLDUPLEX_ENABLE; + } else { + /*set DM644x EMAC for Half Duplex */ + emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; + } + + return(1); +} + + +int lxt972_init_phy(int phy_addr) +{ + int ret = 1; + + if (!lxt972_get_link_speed(phy_addr)) { + /* Try another time */ + ret = lxt972_get_link_speed(phy_addr); + } + + /* Disable PHY Interrupts */ + davinci_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0); + + return(ret); +} + + +int lxt972_auto_negotiate(int phy_addr) +{ + u_int16_t tmp; + + if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp)) + return(0); + + /* Restart Auto_negotiation */ + tmp |= BMCR_ANRESTART; + davinci_eth_phy_write(phy_addr, MII_BMCR, tmp); + + /*check AutoNegotiate complete */ + udelay (10000); + if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp)) + return(0); + + if (!(tmp & BMSR_ANEGCOMPLETE)) + return(0); + + return (lxt972_get_link_speed(phy_addr)); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_ETHER */ |