xref: /openbmc/u-boot/arch/arm/mach-davinci/dp83848.c (revision 1a68faac)
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@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/ti/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