Home | History | Annotate | Download | only in mach-davinci
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * National Semiconductor DP83848 PHY Driver for TI DaVinci
      4  * (TMS320DM644x) based boards.
      5  *
      6  * Copyright (C) 2007 Sergey Kubushyn <ksi (at) koi8.net>
      7  *
      8  * --------------------------------------------------------
      9  */
     10 
     11 #include <common.h>
     12 #include <net.h>
     13 #include <dp83848.h>
     14 #include <asm/arch/emac_defs.h>
     15 #include "../../../drivers/net/davinci_emac.h"
     16 
     17 #ifdef CONFIG_DRIVER_TI_EMAC
     18 
     19 #ifdef CONFIG_CMD_NET
     20 
     21 int dp83848_is_phy_connected(int phy_addr)
     22 {
     23 	u_int16_t	id1, id2;
     24 
     25 	if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
     26 		return(0);
     27 	if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
     28 		return(0);
     29 
     30 	if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
     31 		return(1);
     32 
     33 	return(0);
     34 }
     35 
     36 int dp83848_get_link_speed(int phy_addr)
     37 {
     38 	u_int16_t		tmp;
     39 	volatile emac_regs*	emac = (emac_regs *)EMAC_BASE_ADDR;
     40 
     41 	if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
     42 		return(0);
     43 
     44 	if (!(tmp & DP83848_LINK_STATUS))	/* link up? */
     45 		return(0);
     46 
     47 	if (!davinci_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
     48 		return(0);
     49 
     50 	/* Speed doesn't matter, there is no setting for it in EMAC... */
     51 	if (tmp & DP83848_DUPLEX) {
     52 		/* set DM644x EMAC for Full Duplex  */
     53 		emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE |
     54 			EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
     55 	} else {
     56 		/*set DM644x EMAC for Half Duplex  */
     57 		emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
     58 	}
     59 
     60 	return(1);
     61 }
     62 
     63 
     64 int dp83848_init_phy(int phy_addr)
     65 {
     66 	int	ret = 1;
     67 
     68 	if (!dp83848_get_link_speed(phy_addr)) {
     69 		/* Try another time */
     70 		udelay(100000);
     71 		ret = dp83848_get_link_speed(phy_addr);
     72 	}
     73 
     74 	/* Disable PHY Interrupts */
     75 	davinci_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
     76 
     77 	return(ret);
     78 }
     79 
     80 
     81 int dp83848_auto_negotiate(int phy_addr)
     82 {
     83 	u_int16_t	tmp;
     84 
     85 
     86 	if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
     87 		return(0);
     88 
     89 	/* Restart Auto_negotiation  */
     90 	tmp &= ~DP83848_AUTONEG;	/* remove autonegotiation enable */
     91 	tmp |= DP83848_ISOLATE;		/* Electrically isolate PHY */
     92 	davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
     93 
     94 	/* Set the Auto_negotiation Advertisement Register
     95 	 * MII advertising for Next page, 100BaseTxFD and HD,
     96 	 * 10BaseTFD and HD, IEEE 802.3
     97 	 */
     98 	tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
     99 		DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
    100 	davinci_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
    101 
    102 
    103 	/* Read Control Register */
    104 	if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
    105 		return(0);
    106 
    107 	tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
    108 	davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
    109 
    110 	/* Restart Auto_negotiation  */
    111 	tmp |= DP83848_RESTART_AUTONEG;
    112 	davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
    113 
    114 	/*check AutoNegotiate complete */
    115 	udelay(10000);
    116 	if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
    117 		return(0);
    118 
    119 	if (!(tmp & DP83848_AUTONEG_COMP))
    120 		return(0);
    121 
    122 	return (dp83848_get_link_speed(phy_addr));
    123 }
    124 
    125 #endif	/* CONFIG_CMD_NET */
    126 
    127 #endif	/* CONFIG_DRIVER_ETHER */
    128