]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/davinci/dp83848.c
powerpc/83xx: fix sdram initialization for keymile boards
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / davinci / dp83848.c
1 /*
2  * National Semiconductor DP83848 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 <dp83848.h>
31 #include <asm/arch/emac_defs.h>
32
33 #ifdef CONFIG_DRIVER_TI_EMAC
34
35 #ifdef CONFIG_CMD_NET
36
37 int dp83848_is_phy_connected(int phy_addr)
38 {
39         u_int16_t       id1, id2;
40
41         if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
42                 return(0);
43         if (!davinci_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
44                 return(0);
45
46         if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
47                 return(1);
48
49         return(0);
50 }
51
52 int dp83848_get_link_speed(int phy_addr)
53 {
54         u_int16_t               tmp;
55         volatile emac_regs*     emac = (emac_regs *)EMAC_BASE_ADDR;
56
57         if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
58                 return(0);
59
60         if (!(tmp & DP83848_LINK_STATUS))       /* link up? */
61                 return(0);
62
63         if (!davinci_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
64                 return(0);
65
66         /* Speed doesn't matter, there is no setting for it in EMAC... */
67         if (tmp & DP83848_DUPLEX) {
68                 /* set DM644x EMAC for Full Duplex  */
69                 emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE |
70                         EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
71         } else {
72                 /*set DM644x EMAC for Half Duplex  */
73                 emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
74         }
75
76         return(1);
77 }
78
79
80 int dp83848_init_phy(int phy_addr)
81 {
82         int     ret = 1;
83
84         if (!dp83848_get_link_speed(phy_addr)) {
85                 /* Try another time */
86                 udelay(100000);
87                 ret = dp83848_get_link_speed(phy_addr);
88         }
89
90         /* Disable PHY Interrupts */
91         davinci_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
92
93         return(ret);
94 }
95
96
97 int dp83848_auto_negotiate(int phy_addr)
98 {
99         u_int16_t       tmp;
100
101
102         if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
103                 return(0);
104
105         /* Restart Auto_negotiation  */
106         tmp &= ~DP83848_AUTONEG;        /* remove autonegotiation enable */
107         tmp |= DP83848_ISOLATE;         /* Electrically isolate PHY */
108         davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
109
110         /* Set the Auto_negotiation Advertisement Register
111          * MII advertising for Next page, 100BaseTxFD and HD,
112          * 10BaseTFD and HD, IEEE 802.3
113          */
114         tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
115                 DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
116         davinci_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
117
118
119         /* Read Control Register */
120         if (!davinci_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
121                 return(0);
122
123         tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
124         davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
125
126         /* Restart Auto_negotiation  */
127         tmp |= DP83848_RESTART_AUTONEG;
128         davinci_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
129
130         /*check AutoNegotiate complete */
131         udelay(10000);
132         if (!davinci_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
133                 return(0);
134
135         if (!(tmp & DP83848_AUTONEG_COMP))
136                 return(0);
137
138         return (dp83848_get_link_speed(phy_addr));
139 }
140
141 #endif  /* CONFIG_CMD_NET */
142
143 #endif  /* CONFIG_DRIVER_ETHER */