Merge with git://www.denx.de/git/u-boot.git
[platform/kernel/u-boot.git] / cpu / arm926ejs / davinci / lxt972.c
1 /*
2  * Intel LXT971/LXT972 PHY Driver for TI DaVinci
3  * (TMS320DM644x) based boards.
4  *
5  * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
6  *
7  * --------------------------------------------------------
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <common.h>
29 #include <net.h>
30 #include <lxt971a.h>
31 #include <asm/arch/emac_defs.h>
32
33 #ifdef CONFIG_DRIVER_TI_EMAC
34
35 #ifdef CONFIG_CMD_NET
36
37 int lxt972_is_phy_connected(int phy_addr)
38 {
39         u_int16_t       id1, id2;
40
41         if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1))
42                 return(0);
43         if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2))
44                 return(0);
45
46         if ((id1 == (0x0013)) && ((id2  & 0xfff0) == 0x78e0))
47                 return(1);
48
49         return(0);
50 }
51
52 int lxt972_get_link_speed(int phy_addr)
53 {
54         u_int16_t               stat1, tmp;
55         volatile emac_regs*     emac = (emac_regs *)EMAC_BASE_ADDR;
56
57         if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1))
58                 return(0);
59
60         if (!(stat1 & PHY_LXT971_STAT2_LINK))   /* link up? */
61                 return(0);
62
63         if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
64                 return(0);
65
66         tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE;
67
68         dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp);
69         /* Read back */
70         if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
71                 return(0);
72
73
74         /* Speed doesn't matter, there is no setting for it in EMAC... */
75         if (stat1 & PHY_LXT971_STAT2_100BTX) {
76                 if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
77                         /* set DM644x EMAC for Full Duplex  */
78                         emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
79                 } else {
80                         /*set DM644x EMAC for Half Duplex  */
81                         emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
82                 }
83
84                 return(1);
85         } else {
86                 if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
87                         /* set DM644x EMAC for Full Duplex  */
88                         emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
89                 } else {
90                         /*set DM644x EMAC for Half Duplex  */
91                         emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
92                 }
93
94                 return(1);
95         }
96
97         return(0);
98 }
99
100
101 int lxt972_init_phy(int phy_addr)
102 {
103         int     ret = 1;
104
105         if (!lxt972_get_link_speed(phy_addr)) {
106                 /* Try another time */
107                 ret = lxt972_get_link_speed(phy_addr);
108         }
109
110         /* Disable PHY Interrupts */
111         dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0);
112
113         return(ret);
114 }
115
116
117 int lxt972_auto_negotiate(int phy_addr)
118 {
119         u_int16_t       tmp;
120
121
122         if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp))
123                 return(0);
124
125         /* Restart Auto_negotiation  */
126         tmp |= PHY_COMMON_CTRL_RES_AUTO;
127         dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp);
128
129         /*check AutoNegotiate complete */
130         udelay (10000);
131         if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp))
132                 return(0);
133
134         if (!(tmp & PHY_COMMON_STAT_AN_COMP))
135                 return(0);
136
137         return (lxt972_get_link_speed(phy_addr));
138 }
139
140 #endif  /* CONFIG_CMD_NET */
141
142 #endif  /* CONFIG_DRIVER_ETHER */