1 /******************************************************************************/
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */
5 /* All rights reserved. */
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. */
12 /******************************************************************************/
13 #if !defined(CONFIG_NET_MULTI)
14 #if INCLUDE_TBI_SUPPORT
15 #include "bcm570x_autoneg.h"
16 #include "bcm570x_mm.h"
19 /******************************************************************************/
23 /******************************************************************************/
26 PAN_STATE_INFO pAnInfo)
28 PLM_DEVICE_BLOCK pDevice;
30 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
32 REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT);
34 pDevice->MacMode |= MAC_MODE_SEND_CONFIGS;
35 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
39 /******************************************************************************/
43 /******************************************************************************/
46 PAN_STATE_INFO pAnInfo)
48 PLM_DEVICE_BLOCK pDevice;
50 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
52 pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS;
53 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
57 /******************************************************************************/
61 /******************************************************************************/
64 PAN_STATE_INFO pAnInfo,
65 unsigned short *pRxConfig)
67 PLM_DEVICE_BLOCK pDevice;
73 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
75 Value32 = REG_RD(pDevice, MacCtrl.Status);
76 if(Value32 & MAC_STATUS_RECEIVING_CFG)
78 Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg);
79 *pRxConfig = (unsigned short) Value32;
88 /******************************************************************************/
92 /******************************************************************************/
95 PAN_STATE_INFO pAnInfo)
99 for(j = 0; j < sizeof(AN_STATE_INFO); j++)
101 ((unsigned char *) pAnInfo)[j] = 0;
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;
112 /******************************************************************************/
116 /******************************************************************************/
119 PAN_STATE_INFO pAnInfo)
121 unsigned short RxConfig;
122 unsigned long Delta_us;
123 AUTONEG_STATUS AnRet;
125 /* Get the current time. */
126 if(pAnInfo->State == AN_STATE_UNKNOWN)
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;
138 /* Increment the timer tick. This function is called every microsecon. */
139 /* pAnInfo->CurrentTime_us++; */
141 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
142 /* corresponding conditions are satisfied. */
143 if(MM_AnRxConfig(pAnInfo, &RxConfig))
145 if(RxConfig != pAnInfo->AbilityMatchCfg)
147 pAnInfo->AbilityMatchCfg = RxConfig;
148 pAnInfo->AbilityMatch = AN_FALSE;
149 pAnInfo->AbilityMatchCnt = 0;
153 pAnInfo->AbilityMatchCnt++;
154 if(pAnInfo->AbilityMatchCnt > 1)
156 pAnInfo->AbilityMatch = AN_TRUE;
157 pAnInfo->AbilityMatchCfg = RxConfig;
161 if(RxConfig & AN_CONFIG_ACK)
163 pAnInfo->AckMatch = AN_TRUE;
167 pAnInfo->AckMatch = AN_FALSE;
170 pAnInfo->IdleMatch = AN_FALSE;
174 pAnInfo->IdleMatch = AN_TRUE;
176 pAnInfo->AbilityMatchCfg = 0;
177 pAnInfo->AbilityMatchCnt = 0;
178 pAnInfo->AbilityMatch = AN_FALSE;
179 pAnInfo->AckMatch = AN_FALSE;
184 /* Save the last Config. */
185 pAnInfo->RxConfig.AsUSHORT = RxConfig;
187 /* Default return code. */
188 AnRet = AUTONEG_STATUS_OK;
190 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
191 switch(pAnInfo->State)
193 case AN_STATE_UNKNOWN:
194 if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an)
196 pAnInfo->CurrentTime_us = 0;
197 pAnInfo->State = AN_STATE_AN_ENABLE;
202 case AN_STATE_AN_ENABLE:
203 pAnInfo->mr_an_complete = AN_FALSE;
204 pAnInfo->mr_page_rx = AN_FALSE;
206 if(pAnInfo->mr_an_enable)
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;
215 pAnInfo->State = AN_STATE_AN_RESTART_INIT;
219 pAnInfo->State = AN_STATE_DISABLE_LINK_OK;
223 case AN_STATE_AN_RESTART_INIT:
224 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
225 pAnInfo->mr_np_loaded = AN_FALSE;
227 pAnInfo->TxConfig.AsUSHORT = 0;
228 MM_AnTxConfig(pAnInfo);
230 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
232 pAnInfo->State = AN_STATE_AN_RESTART;
236 case AN_STATE_AN_RESTART:
237 /* Get the current time and compute the delta with the saved */
239 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
240 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
242 pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT;
246 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
250 case AN_STATE_DISABLE_LINK_OK:
251 AnRet = AUTONEG_STATUS_DONE;
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;
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;
269 MM_AnTxConfig(pAnInfo);
271 pAnInfo->State = AN_STATE_ABILITY_DETECT;
275 case AN_STATE_ABILITY_DETECT:
276 if(pAnInfo->AbilityMatch == AN_TRUE &&
277 pAnInfo->RxConfig.AsUSHORT != 0)
279 pAnInfo->State = AN_STATE_ACK_DETECT_INIT;
284 case AN_STATE_ACK_DETECT_INIT:
285 pAnInfo->TxConfig.D14_ACK = 1;
286 MM_AnTxConfig(pAnInfo);
288 pAnInfo->State = AN_STATE_ACK_DETECT;
292 case AN_STATE_ACK_DETECT:
293 if(pAnInfo->AckMatch == AN_TRUE)
295 if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) ==
296 (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK))
298 pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT;
302 pAnInfo->State = AN_STATE_AN_ENABLE;
305 else if(pAnInfo->AbilityMatch == AN_TRUE &&
306 pAnInfo->RxConfig.AsUSHORT == 0)
308 pAnInfo->State = AN_STATE_AN_ENABLE;
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)
320 AnRet = AUTONEG_STATUS_FAILED;
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;
333 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
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;
340 pAnInfo->State = AN_STATE_COMPLETE_ACK;
341 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
345 case AN_STATE_COMPLETE_ACK:
346 if(pAnInfo->AbilityMatch == AN_TRUE &&
347 pAnInfo->RxConfig.AsUSHORT == 0)
349 pAnInfo->State = AN_STATE_AN_ENABLE;
353 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
355 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
357 if(pAnInfo->mr_adv_next_page == 0 ||
358 pAnInfo->mr_lp_adv_next_page == 0)
360 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
364 if(pAnInfo->TxConfig.bits.D15 == 0 &&
365 pAnInfo->mr_np_rx == 0)
367 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
371 AnRet = AUTONEG_STATUS_FAILED;
378 case AN_STATE_IDLE_DETECT_INIT:
379 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
381 MM_AnTxIdle(pAnInfo);
383 pAnInfo->State = AN_STATE_IDLE_DETECT;
385 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
389 case AN_STATE_IDLE_DETECT:
390 if(pAnInfo->AbilityMatch == AN_TRUE &&
391 pAnInfo->RxConfig.AsUSHORT == 0)
393 pAnInfo->State = AN_STATE_AN_ENABLE;
397 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
398 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
401 /* if(pAnInfo->IdleMatch == AN_TRUE) */
404 pAnInfo->State = AN_STATE_LINK_OK;
409 /* AnRet = AUTONEG_STATUS_FAILED; */
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;
424 case AN_STATE_NEXT_PAGE_WAIT_INIT:
427 case AN_STATE_NEXT_PAGE_WAIT:
431 AnRet = AUTONEG_STATUS_FAILED;
437 #endif /* INCLUDE_TBI_SUPPORT */
439 #endif /* !defined(CONFIG_NET_MULTI) */