uboot/drivers/net/bcm570x_autoneg.c
<<
>>
Prefs
   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/******************************************************************************/
  24void
  25MM_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/******************************************************************************/
  44void
  45MM_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/******************************************************************************/
  62char
  63MM_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/******************************************************************************/
  93void
  94AutonegInit(
  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/******************************************************************************/
 117AUTONEG_STATUS
 118Autoneg8023z(
 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) */
 440