]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm920t/at91rm9200/bcm5221.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / cpu / arm920t / at91rm9200 / bcm5221.c
1 /*
2  * Broadcom BCM5221 Ethernet PHY
3  *
4  * (C) Copyright 2005 REA Elektronik GmbH <www.rea.de>
5  * Anders Larsen <alarsen@rea.de>
6  *
7  * (C) Copyright 2003
8  * Author : Hamid Ikdoumi (Atmel)
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28
29 #include <at91rm9200_net.h>
30 #include <net.h>
31 #include <bcm5221.h>
32
33 #ifdef CONFIG_DRIVER_ETHER
34
35 #if defined(CONFIG_CMD_NET)
36
37 /*
38  * Name:
39  *      bcm5221_IsPhyConnected
40  * Description:
41  *      Reads the 2 PHY ID registers
42  * Arguments:
43  *      p_mac - pointer to AT91S_EMAC struct
44  * Return value:
45  *      TRUE - if id read successfully
46  *      FALSE- if error
47  */
48 unsigned int bcm5221_IsPhyConnected (AT91PS_EMAC p_mac)
49 {
50         unsigned short Id1, Id2;
51
52         at91rm9200_EmacEnableMDIO (p_mac);
53         at91rm9200_EmacReadPhy (p_mac, BCM5221_PHYID1, &Id1);
54         at91rm9200_EmacReadPhy (p_mac, BCM5221_PHYID2, &Id2);
55         at91rm9200_EmacDisableMDIO (p_mac);
56
57         if ((Id1 == (BCM5221_PHYID1_OUI >> 6)) &&
58                 ((Id2 >> 10) == (BCM5221_PHYID1_OUI & BCM5221_LSB_MASK)))
59                 return TRUE;
60
61         return FALSE;
62 }
63
64 /*
65  * Name:
66  *      bcm5221_GetLinkSpeed
67  * Description:
68  *      Link parallel detection status of MAC is checked and set in the
69  *      MAC configuration registers
70  * Arguments:
71  *      p_mac - pointer to MAC
72  * Return value:
73  *      TRUE - if link status set succesfully
74  *      FALSE - if link status not set
75  */
76 unsigned char bcm5221_GetLinkSpeed (AT91PS_EMAC p_mac)
77 {
78         unsigned short stat1, stat2;
79
80         if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMSR, &stat1))
81                 return FALSE;
82
83         if (!(stat1 & BCM5221_LINK_STATUS))     /* link status up? */
84                 return FALSE;
85
86         if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_ACSR, &stat2))
87                 return FALSE;
88
89         if ((stat1 & BCM5221_100BASE_TX_FD) && (stat2 & BCM5221_100) && (stat2 & BCM5221_FDX)) {
90                 /*set Emac for 100BaseTX and Full Duplex  */
91                 p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
92                 return TRUE;
93         }
94
95         if ((stat1 & BCM5221_10BASE_T_FD) && !(stat2 & BCM5221_100) && (stat2 & BCM5221_FDX)) {
96                 /*set MII for 10BaseT and Full Duplex  */
97                 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
98                                 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
99                                 | AT91C_EMAC_FD;
100                 return TRUE;
101         }
102
103         if ((stat1 & BCM5221_100BASE_TX_HD) && (stat2 & BCM5221_100) && !(stat2 & BCM5221_FDX)) {
104                 /*set MII for 100BaseTX and Half Duplex  */
105                 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
106                                 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
107                                 | AT91C_EMAC_SPD;
108                 return TRUE;
109         }
110
111         if ((stat1 & BCM5221_10BASE_T_HD) && !(stat2 & BCM5221_100) && !(stat2 & BCM5221_FDX)) {
112                 /*set MII for 10BaseT and Half Duplex  */
113                 p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
114                 return TRUE;
115         }
116         return FALSE;
117 }
118
119
120 /*
121  * Name:
122  *      bcm5221_InitPhy
123  * Description:
124  *      MAC starts checking its link by using parallel detection and
125  *      Autonegotiation and the same is set in the MAC configuration registers
126  * Arguments:
127  *      p_mac - pointer to struct AT91S_EMAC
128  * Return value:
129  *      TRUE - if link status set succesfully
130  *      FALSE - if link status not set
131  */
132 unsigned char bcm5221_InitPhy (AT91PS_EMAC p_mac)
133 {
134         unsigned char ret = TRUE;
135         unsigned short IntValue;
136
137         at91rm9200_EmacEnableMDIO (p_mac);
138
139         if (!bcm5221_GetLinkSpeed (p_mac)) {
140                 /* Try another time */
141                 ret = bcm5221_GetLinkSpeed (p_mac);
142         }
143
144         /* Disable PHY Interrupts */
145         at91rm9200_EmacReadPhy (p_mac, BCM5221_INTR, &IntValue);
146         /* clear FDX LED and INTR Enable */
147         IntValue &= ~(BCM5221_FDX_LED | BCM5221_INTR_ENABLE);
148         /* set FDX, SPD, Link, INTR masks */
149         IntValue |= (BCM5221_FDX_MASK  | BCM5221_SPD_MASK |
150                      BCM5221_LINK_MASK | BCM5221_INTR_MASK);
151         at91rm9200_EmacWritePhy (p_mac, BCM5221_INTR, &IntValue);
152         at91rm9200_EmacDisableMDIO (p_mac);
153
154         return (ret);
155 }
156
157
158 /*
159  * Name:
160  *      bcm5221_AutoNegotiate
161  * Description:
162  *      MAC Autonegotiates with the partner status of same is set in the
163  *      MAC configuration registers
164  * Arguments:
165  *      dev - pointer to struct net_device
166  * Return value:
167  *      TRUE - if link status set successfully
168  *      FALSE - if link status not set
169  */
170 unsigned char bcm5221_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
171 {
172         unsigned short value;
173         unsigned short PhyAnar;
174         unsigned short PhyAnalpar;
175
176         /* Set bcm5221 control register */
177         if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMCR, &value))
178                 return FALSE;
179         value &= ~BCM5221_AUTONEG;      /* remove autonegotiation enable */
180         value |=  BCM5221_ISOLATE;      /* Electrically isolate PHY */
181         if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value))
182                 return FALSE;
183
184         /* Set the Auto_negotiation Advertisement Register */
185         /* MII advertising for 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
186         PhyAnar = BCM5221_TX_FDX | BCM5221_TX_HDX |
187                   BCM5221_10_FDX | BCM5221_10_HDX | BCM5221_AN_IEEE_802_3;
188         if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_ANAR, &PhyAnar))
189                 return FALSE;
190
191         /* Read the Control Register     */
192         if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_BMCR, &value))
193                 return FALSE;
194
195         value |= BCM5221_SPEED_SELECT | BCM5221_AUTONEG | BCM5221_DUPLEX_MODE;
196         if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value))
197                 return FALSE;
198         /* Restart Auto_negotiation  */
199         value |= BCM5221_RESTART_AUTONEG;
200         value &= ~BCM5221_ISOLATE;
201         if (!at91rm9200_EmacWritePhy (p_mac, BCM5221_BMCR, &value))
202                 return FALSE;
203
204         /*check AutoNegotiate complete */
205         udelay (10000);
206         at91rm9200_EmacReadPhy (p_mac, BCM5221_BMSR, &value);
207         if (!(value & BCM5221_AUTONEG_COMP))
208                 return FALSE;
209
210         /* Get the AutoNeg Link partner base page */
211         if (!at91rm9200_EmacReadPhy (p_mac, BCM5221_ANLPAR, &PhyAnalpar))
212                 return FALSE;
213
214         if ((PhyAnar & BCM5221_TX_FDX) && (PhyAnalpar & BCM5221_TX_FDX)) {
215                 /*set MII for 100BaseTX and Full Duplex  */
216                 p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
217                 return TRUE;
218         }
219
220         if ((PhyAnar & BCM5221_10_FDX) && (PhyAnalpar & BCM5221_10_FDX)) {
221                 /*set MII for 10BaseT and Full Duplex  */
222                 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
223                                 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
224                                 | AT91C_EMAC_FD;
225                 return TRUE;
226         }
227         return FALSE;
228 }
229
230 #endif
231
232 #endif  /* CONFIG_DRIVER_ETHER */