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
dp83848_is_phy_connected(int phy_addr)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
dp83848_get_link_speed(int phy_addr)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
dp83848_init_phy(int phy_addr)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
dp83848_auto_negotiate(int phy_addr)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