]>
Commit | Line | Data |
---|---|---|
645da510 WD |
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> | |
645da510 WD |
31 | #ifdef CONFIG_DRIVER_ETHER |
32 | ||
c041e9d2 JS |
33 | #include <bcm5221.h> |
34 | ||
3a1ed1e1 | 35 | #if defined(CONFIG_CMD_NET) |
645da510 WD |
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 | ||
3a1ed1e1 | 230 | #endif |
645da510 WD |
231 | |
232 | #endif /* CONFIG_DRIVER_ETHER */ |