]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/net/bcm570x_autoneg.c
9023796aa05967f89891a9140998c746613e190a
[people/ms/u-boot.git] / drivers / net / bcm570x_autoneg.c
1 /******************************************************************************/
2 /* */
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */
4 /* Corporation. */
5 /* All rights reserved. */
6 /* */
7 /* This program is free software; you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation, located in the file LICENSE. */
10 /* */
11 /* History: */
12 /******************************************************************************/
13 #if !defined(CONFIG_NET_MULTI)
14 #if INCLUDE_TBI_SUPPORT
15 #include "bcm570x_autoneg.h"
16 #include "bcm570x_mm.h"
17
18
19 /******************************************************************************/
20 /* Description: */
21 /* */
22 /* Return: */
23 /******************************************************************************/
24 void
25 MM_AnTxConfig(
26 PAN_STATE_INFO pAnInfo)
27 {
28 PLM_DEVICE_BLOCK pDevice;
29
30 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
31
32 REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT);
33
34 pDevice->MacMode |= MAC_MODE_SEND_CONFIGS;
35 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
36 }
37
38
39 /******************************************************************************/
40 /* Description: */
41 /* */
42 /* Return: */
43 /******************************************************************************/
44 void
45 MM_AnTxIdle(
46 PAN_STATE_INFO pAnInfo)
47 {
48 PLM_DEVICE_BLOCK pDevice;
49
50 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
51
52 pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS;
53 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
54 }
55
56
57 /******************************************************************************/
58 /* Description: */
59 /* */
60 /* Return: */
61 /******************************************************************************/
62 char
63 MM_AnRxConfig(
64 PAN_STATE_INFO pAnInfo,
65 unsigned short *pRxConfig)
66 {
67 PLM_DEVICE_BLOCK pDevice;
68 LM_UINT32 Value32;
69 char Retcode;
70
71 Retcode = AN_FALSE;
72
73 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
74
75 Value32 = REG_RD(pDevice, MacCtrl.Status);
76 if(Value32 & MAC_STATUS_RECEIVING_CFG)
77 {
78 Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg);
79 *pRxConfig = (unsigned short) Value32;
80
81 Retcode = AN_TRUE;
82 }
83
84 return Retcode;
85 }
86
87
88 /******************************************************************************/
89 /* Description: */
90 /* */
91 /* Return: */
92 /******************************************************************************/
93 void
94 AutonegInit(
95 PAN_STATE_INFO pAnInfo)
96 {
97 unsigned long j;
98
99 for(j = 0; j < sizeof(AN_STATE_INFO); j++)
100 {
101 ((unsigned char *) pAnInfo)[j] = 0;
102 }
103
104 /* Initialize the default advertisement register. */
105 pAnInfo->mr_adv_full_duplex = 1;
106 pAnInfo->mr_adv_sym_pause = 1;
107 pAnInfo->mr_adv_asym_pause = 1;
108 pAnInfo->mr_an_enable = 1;
109 }
110
111
112 /******************************************************************************/
113 /* Description: */
114 /* */
115 /* Return: */
116 /******************************************************************************/
117 AUTONEG_STATUS
118 Autoneg8023z(
119 PAN_STATE_INFO pAnInfo)
120 {
121 unsigned short RxConfig;
122 unsigned long Delta_us;
123 AUTONEG_STATUS AnRet;
124
125 /* Get the current time. */
126 if(pAnInfo->State == AN_STATE_UNKNOWN)
127 {
128 pAnInfo->RxConfig.AsUSHORT = 0;
129 pAnInfo->CurrentTime_us = 0;
130 pAnInfo->LinkTime_us = 0;
131 pAnInfo->AbilityMatchCfg = 0;
132 pAnInfo->AbilityMatchCnt = 0;
133 pAnInfo->AbilityMatch = AN_FALSE;
134 pAnInfo->IdleMatch = AN_FALSE;
135 pAnInfo->AckMatch = AN_FALSE;
136 }
137
138 /* Increment the timer tick. This function is called every microsecon. */
139 /* pAnInfo->CurrentTime_us++; */
140
141 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
142 /* corresponding conditions are satisfied. */
143 if(MM_AnRxConfig(pAnInfo, &RxConfig))
144 {
145 if(RxConfig != pAnInfo->AbilityMatchCfg)
146 {
147 pAnInfo->AbilityMatchCfg = RxConfig;
148 pAnInfo->AbilityMatch = AN_FALSE;
149 pAnInfo->AbilityMatchCnt = 0;
150 }
151 else
152 {
153 pAnInfo->AbilityMatchCnt++;
154 if(pAnInfo->AbilityMatchCnt > 1)
155 {
156 pAnInfo->AbilityMatch = AN_TRUE;
157 pAnInfo->AbilityMatchCfg = RxConfig;
158 }
159 }
160
161 if(RxConfig & AN_CONFIG_ACK)
162 {
163 pAnInfo->AckMatch = AN_TRUE;
164 }
165 else
166 {
167 pAnInfo->AckMatch = AN_FALSE;
168 }
169
170 pAnInfo->IdleMatch = AN_FALSE;
171 }
172 else
173 {
174 pAnInfo->IdleMatch = AN_TRUE;
175
176 pAnInfo->AbilityMatchCfg = 0;
177 pAnInfo->AbilityMatchCnt = 0;
178 pAnInfo->AbilityMatch = AN_FALSE;
179 pAnInfo->AckMatch = AN_FALSE;
180
181 RxConfig = 0;
182 }
183
184 /* Save the last Config. */
185 pAnInfo->RxConfig.AsUSHORT = RxConfig;
186
187 /* Default return code. */
188 AnRet = AUTONEG_STATUS_OK;
189
190 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
191 switch(pAnInfo->State)
192 {
193 case AN_STATE_UNKNOWN:
194 if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an)
195 {
196 pAnInfo->CurrentTime_us = 0;
197 pAnInfo->State = AN_STATE_AN_ENABLE;
198 }
199
200 /* Fall through.*/
201
202 case AN_STATE_AN_ENABLE:
203 pAnInfo->mr_an_complete = AN_FALSE;
204 pAnInfo->mr_page_rx = AN_FALSE;
205
206 if(pAnInfo->mr_an_enable)
207 {
208 pAnInfo->LinkTime_us = 0;
209 pAnInfo->AbilityMatchCfg = 0;
210 pAnInfo->AbilityMatchCnt = 0;
211 pAnInfo->AbilityMatch = AN_FALSE;
212 pAnInfo->IdleMatch = AN_FALSE;
213 pAnInfo->AckMatch = AN_FALSE;
214
215 pAnInfo->State = AN_STATE_AN_RESTART_INIT;
216 }
217 else
218 {
219 pAnInfo->State = AN_STATE_DISABLE_LINK_OK;
220 }
221 break;
222
223 case AN_STATE_AN_RESTART_INIT:
224 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
225 pAnInfo->mr_np_loaded = AN_FALSE;
226
227 pAnInfo->TxConfig.AsUSHORT = 0;
228 MM_AnTxConfig(pAnInfo);
229
230 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
231
232 pAnInfo->State = AN_STATE_AN_RESTART;
233
234 /* Fall through.*/
235
236 case AN_STATE_AN_RESTART:
237 /* Get the current time and compute the delta with the saved */
238 /* link timer. */
239 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
240 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
241 {
242 pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT;
243 }
244 else
245 {
246 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
247 }
248 break;
249
250 case AN_STATE_DISABLE_LINK_OK:
251 AnRet = AUTONEG_STATUS_DONE;
252 break;
253
254 case AN_STATE_ABILITY_DETECT_INIT:
255 /* Note: in the state diagram, this variable is set to */
256 /* mr_adv_ability<12>. Is this right?. */
257 pAnInfo->mr_toggle_tx = AN_FALSE;
258
259 /* Send the config as advertised in the advertisement register. */
260 pAnInfo->TxConfig.AsUSHORT = 0;
261 pAnInfo->TxConfig.D5_FD = pAnInfo->mr_adv_full_duplex;
262 pAnInfo->TxConfig.D6_HD = pAnInfo->mr_adv_half_duplex;
263 pAnInfo->TxConfig.D7_PS1 = pAnInfo->mr_adv_sym_pause;
264 pAnInfo->TxConfig.D8_PS2 = pAnInfo->mr_adv_asym_pause;
265 pAnInfo->TxConfig.D12_RF1 = pAnInfo->mr_adv_remote_fault1;
266 pAnInfo->TxConfig.D13_RF2 = pAnInfo->mr_adv_remote_fault2;
267 pAnInfo->TxConfig.D15_NP = pAnInfo->mr_adv_next_page;
268
269 MM_AnTxConfig(pAnInfo);
270
271 pAnInfo->State = AN_STATE_ABILITY_DETECT;
272
273 break;
274
275 case AN_STATE_ABILITY_DETECT:
276 if(pAnInfo->AbilityMatch == AN_TRUE &&
277 pAnInfo->RxConfig.AsUSHORT != 0)
278 {
279 pAnInfo->State = AN_STATE_ACK_DETECT_INIT;
280 }
281
282 break;
283
284 case AN_STATE_ACK_DETECT_INIT:
285 pAnInfo->TxConfig.D14_ACK = 1;
286 MM_AnTxConfig(pAnInfo);
287
288 pAnInfo->State = AN_STATE_ACK_DETECT;
289
290 /* Fall through. */
291
292 case AN_STATE_ACK_DETECT:
293 if(pAnInfo->AckMatch == AN_TRUE)
294 {
295 if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) ==
296 (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK))
297 {
298 pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT;
299 }
300 else
301 {
302 pAnInfo->State = AN_STATE_AN_ENABLE;
303 }
304 }
305 else if(pAnInfo->AbilityMatch == AN_TRUE &&
306 pAnInfo->RxConfig.AsUSHORT == 0)
307 {
308 pAnInfo->State = AN_STATE_AN_ENABLE;
309 }
310
311 break;
312
313 case AN_STATE_COMPLETE_ACK_INIT:
314 /* Make sure invalid bits are not set. */
315 if(pAnInfo->RxConfig.bits.D0 || pAnInfo->RxConfig.bits.D1 ||
316 pAnInfo->RxConfig.bits.D2 || pAnInfo->RxConfig.bits.D3 ||
317 pAnInfo->RxConfig.bits.D4 || pAnInfo->RxConfig.bits.D9 ||
318 pAnInfo->RxConfig.bits.D10 || pAnInfo->RxConfig.bits.D11)
319 {
320 AnRet = AUTONEG_STATUS_FAILED;
321 break;
322 }
323
324 /* Set up the link partner advertisement register. */
325 pAnInfo->mr_lp_adv_full_duplex = pAnInfo->RxConfig.D5_FD;
326 pAnInfo->mr_lp_adv_half_duplex = pAnInfo->RxConfig.D6_HD;
327 pAnInfo->mr_lp_adv_sym_pause = pAnInfo->RxConfig.D7_PS1;
328 pAnInfo->mr_lp_adv_asym_pause = pAnInfo->RxConfig.D8_PS2;
329 pAnInfo->mr_lp_adv_remote_fault1 = pAnInfo->RxConfig.D12_RF1;
330 pAnInfo->mr_lp_adv_remote_fault2 = pAnInfo->RxConfig.D13_RF2;
331 pAnInfo->mr_lp_adv_next_page = pAnInfo->RxConfig.D15_NP;
332
333 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
334
335 pAnInfo->mr_toggle_tx = !pAnInfo->mr_toggle_tx;
336 pAnInfo->mr_toggle_rx = pAnInfo->RxConfig.bits.D11;
337 pAnInfo->mr_np_rx = pAnInfo->RxConfig.D15_NP;
338 pAnInfo->mr_page_rx = AN_TRUE;
339
340 pAnInfo->State = AN_STATE_COMPLETE_ACK;
341 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
342
343 break;
344
345 case AN_STATE_COMPLETE_ACK:
346 if(pAnInfo->AbilityMatch == AN_TRUE &&
347 pAnInfo->RxConfig.AsUSHORT == 0)
348 {
349 pAnInfo->State = AN_STATE_AN_ENABLE;
350 break;
351 }
352
353 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
354
355 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
356 {
357 if(pAnInfo->mr_adv_next_page == 0 ||
358 pAnInfo->mr_lp_adv_next_page == 0)
359 {
360 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
361 }
362 else
363 {
364 if(pAnInfo->TxConfig.bits.D15 == 0 &&
365 pAnInfo->mr_np_rx == 0)
366 {
367 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
368 }
369 else
370 {
371 AnRet = AUTONEG_STATUS_FAILED;
372 }
373 }
374 }
375
376 break;
377
378 case AN_STATE_IDLE_DETECT_INIT:
379 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
380
381 MM_AnTxIdle(pAnInfo);
382
383 pAnInfo->State = AN_STATE_IDLE_DETECT;
384
385 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
386
387 break;
388
389 case AN_STATE_IDLE_DETECT:
390 if(pAnInfo->AbilityMatch == AN_TRUE &&
391 pAnInfo->RxConfig.AsUSHORT == 0)
392 {
393 pAnInfo->State = AN_STATE_AN_ENABLE;
394 break;
395 }
396
397 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
398 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
399 {
400 #if 0
401 /* if(pAnInfo->IdleMatch == AN_TRUE) */
402 /* { */
403 #endif
404 pAnInfo->State = AN_STATE_LINK_OK;
405 #if 0
406 /* } */
407 /* else */
408 /* { */
409 /* AnRet = AUTONEG_STATUS_FAILED; */
410 /* break; */
411 /* } */
412 #endif
413 }
414
415 break;
416
417 case AN_STATE_LINK_OK:
418 pAnInfo->mr_an_complete = AN_TRUE;
419 pAnInfo->mr_link_ok = AN_TRUE;
420 AnRet = AUTONEG_STATUS_DONE;
421
422 break;
423
424 case AN_STATE_NEXT_PAGE_WAIT_INIT:
425 break;
426
427 case AN_STATE_NEXT_PAGE_WAIT:
428 break;
429
430 default:
431 AnRet = AUTONEG_STATUS_FAILED;
432 break;
433 }
434
435 return AnRet;
436 }
437 #endif /* INCLUDE_TBI_SUPPORT */
438
439 #endif /* !defined(CONFIG_NET_MULTI) */