uboot/drivers/net/ax88180.c
<<
>>
Prefs
   1/*
   2 * ax88180: ASIX AX88180 Non-PCI Gigabit Ethernet u-boot driver
   3 *
   4 * This program is free software; you can distribute it and/or modify
   5 * it under the terms of the GNU General Public License (Version 2) as
   6 * published by the Free Software Foundation.
   7 * This program is distributed in the hope it will be useful, but
   8 * WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10 * See the GNU General Public License for more details.
  11 * You should have received a copy of the GNU General Public License
  12 * along with this program; if not, write to the Free Software
  13 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
  14 * USA.
  15 */
  16
  17/*
  18 * ========================================================================
  19 * ASIX AX88180 Non-PCI 16/32-bit Gigabit Ethernet Linux Driver
  20 *
  21 * The AX88180 Ethernet controller is a high performance and highly
  22 * integrated local CPU bus Ethernet controller with embedded 40K bytes
  23 * SRAM and supports both 16-bit and 32-bit SRAM-Like interfaces for any
  24 * embedded systems.
  25 * The AX88180 is a single chip 10/100/1000Mbps Gigabit Ethernet
  26 * controller that supports both MII and RGMII interfaces and is
  27 * compliant to IEEE 802.3, IEEE 802.3u and IEEE 802.3z standards.
  28 *
  29 * Please visit ASIX's web site (http://www.asix.com.tw) for more
  30 * details.
  31 *
  32 * Module Name  : ax88180.c
  33 * Date         : 2008-07-07
  34 * History
  35 * 09/06/2006   : New release for AX88180 US2 chip.
  36 * 07/07/2008   : Fix up the coding style and using inline functions
  37 *                instead of macros
  38 * ========================================================================
  39 */
  40#include <common.h>
  41#include <command.h>
  42#include <net.h>
  43#include <malloc.h>
  44#include "ax88180.h"
  45
  46/*
  47 * ===========================================================================
  48 * Local SubProgram Declaration
  49 * ===========================================================================
  50 */
  51static void ax88180_rx_handler (struct eth_device *dev);
  52static int ax88180_phy_initial (struct eth_device *dev);
  53static void ax88180_meidia_config (struct eth_device *dev);
  54static unsigned long get_CicadaPHY_meida_mode (struct eth_device *dev);
  55static unsigned long get_MarvellPHY_meida_mode (struct eth_device *dev);
  56static unsigned short ax88180_mdio_read (struct eth_device *dev,
  57                                         unsigned long regaddr);
  58static void ax88180_mdio_write (struct eth_device *dev,
  59                                unsigned long regaddr, unsigned short regdata);
  60
  61/*
  62 * ===========================================================================
  63 * Local SubProgram Bodies
  64 * ===========================================================================
  65 */
  66static int ax88180_mdio_check_complete (struct eth_device *dev)
  67{
  68        int us_cnt = 10000;
  69        unsigned short tmpval;
  70
  71        /* MDIO read/write should not take more than 10 ms */
  72        while (--us_cnt) {
  73                tmpval = INW (dev, MDIOCTRL);
  74                if (((tmpval & READ_PHY) == 0) && ((tmpval & WRITE_PHY) == 0))
  75                        break;
  76        }
  77
  78        return us_cnt;
  79}
  80
  81static unsigned short
  82ax88180_mdio_read (struct eth_device *dev, unsigned long regaddr)
  83{
  84        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
  85        unsigned long tmpval = 0;
  86
  87        OUTW (dev, (READ_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);
  88
  89        if (ax88180_mdio_check_complete (dev))
  90                tmpval = INW (dev, MDIODP);
  91        else
  92                printf ("Failed to read PHY register!\n");
  93
  94        return (unsigned short)(tmpval & 0xFFFF);
  95}
  96
  97static void
  98ax88180_mdio_write (struct eth_device *dev, unsigned long regaddr,
  99                    unsigned short regdata)
 100{
 101        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 102
 103        OUTW (dev, regdata, MDIODP);
 104
 105        OUTW (dev, (WRITE_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);
 106
 107        if (!ax88180_mdio_check_complete (dev))
 108                printf ("Failed to write PHY register!\n");
 109}
 110
 111static int ax88180_phy_reset (struct eth_device *dev)
 112{
 113        unsigned short delay_cnt = 500;
 114
 115        ax88180_mdio_write (dev, BMCR, (PHY_RESET | AUTONEG_EN));
 116
 117        /* Wait for the reset to complete, or time out (500 ms) */
 118        while (ax88180_mdio_read (dev, BMCR) & PHY_RESET) {
 119                udelay (1000);
 120                if (--delay_cnt == 0) {
 121                        printf ("Failed to reset PHY!\n");
 122                        return -1;
 123                }
 124        }
 125
 126        return 0;
 127}
 128
 129static void ax88180_mac_reset (struct eth_device *dev)
 130{
 131        unsigned long tmpval;
 132        unsigned char i;
 133
 134        struct {
 135                unsigned short offset, value;
 136        } program_seq[] = {
 137                {
 138                MISC, MISC_NORMAL}, {
 139                RXINDICATOR, DEFAULT_RXINDICATOR}, {
 140                TXCMD, DEFAULT_TXCMD}, {
 141                TXBS, DEFAULT_TXBS}, {
 142                TXDES0, DEFAULT_TXDES0}, {
 143                TXDES1, DEFAULT_TXDES1}, {
 144                TXDES2, DEFAULT_TXDES2}, {
 145                TXDES3, DEFAULT_TXDES3}, {
 146                TXCFG, DEFAULT_TXCFG}, {
 147                MACCFG2, DEFAULT_MACCFG2}, {
 148                MACCFG3, DEFAULT_MACCFG3}, {
 149                TXLEN, DEFAULT_TXLEN}, {
 150                RXBTHD0, DEFAULT_RXBTHD0}, {
 151                RXBTHD1, DEFAULT_RXBTHD1}, {
 152                RXFULTHD, DEFAULT_RXFULTHD}, {
 153                DOGTHD0, DEFAULT_DOGTHD0}, {
 154        DOGTHD1, DEFAULT_DOGTHD1},};
 155
 156        OUTW (dev, MISC_RESET_MAC, MISC);
 157        tmpval = INW (dev, MISC);
 158
 159        for (i = 0; i < (sizeof (program_seq) / sizeof (program_seq[0])); i++)
 160                OUTW (dev, program_seq[i].value, program_seq[i].offset);
 161}
 162
 163static int ax88180_poll_tx_complete (struct eth_device *dev)
 164{
 165        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 166        unsigned long tmpval, txbs_txdp;
 167        int TimeOutCnt = 10000;
 168
 169        txbs_txdp = 1 << priv->NextTxDesc;
 170
 171        while (TimeOutCnt--) {
 172
 173                tmpval = INW (dev, TXBS);
 174
 175                if ((tmpval & txbs_txdp) == 0)
 176                        break;
 177
 178                udelay (100);
 179        }
 180
 181        if (TimeOutCnt)
 182                return 0;
 183        else
 184                return -TimeOutCnt;
 185}
 186
 187static void ax88180_rx_handler (struct eth_device *dev)
 188{
 189        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 190        unsigned long data_size;
 191        unsigned short rxcurt_ptr, rxbound_ptr, next_ptr;
 192        int i;
 193#if defined (CONFIG_DRIVER_AX88180_16BIT)
 194        unsigned short *rxdata = (unsigned short *)NetRxPackets[0];
 195#else
 196        unsigned long *rxdata = (unsigned long *)NetRxPackets[0];
 197#endif
 198        unsigned short count;
 199
 200        rxcurt_ptr = INW (dev, RXCURT);
 201        rxbound_ptr = INW (dev, RXBOUND);
 202        next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;
 203
 204        debug ("ax88180: RX original RXBOUND=0x%04x,"
 205               " RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
 206
 207        while (next_ptr != rxcurt_ptr) {
 208
 209                OUTW (dev, RX_START_READ, RXINDICATOR);
 210
 211                data_size = READ_RXBUF (dev) & 0xFFFF;
 212
 213                if ((data_size == 0) || (data_size > MAX_RX_SIZE)) {
 214
 215                        OUTW (dev, RX_STOP_READ, RXINDICATOR);
 216
 217                        ax88180_mac_reset (dev);
 218                        printf ("ax88180: Invalid Rx packet length!"
 219                                " (len=0x%04lx)\n", data_size);
 220
 221                        debug ("ax88180: RX RXBOUND=0x%04x,"
 222                               "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
 223                        return;
 224                }
 225
 226                rxbound_ptr += (((data_size + 0xF) & 0xFFF0) >> 4) + 1;
 227                rxbound_ptr &= RX_PAGE_NUM_MASK;
 228
 229                /* Comput access times */
 230                count = (data_size + priv->PadSize) >> priv->BusWidth;
 231
 232                for (i = 0; i < count; i++) {
 233                        *(rxdata + i) = READ_RXBUF (dev);
 234                }
 235
 236                OUTW (dev, RX_STOP_READ, RXINDICATOR);
 237
 238                /* Pass the packet up to the protocol layers. */
 239                NetReceive (NetRxPackets[0], data_size);
 240
 241                OUTW (dev, rxbound_ptr, RXBOUND);
 242
 243                rxcurt_ptr = INW (dev, RXCURT);
 244                rxbound_ptr = INW (dev, RXBOUND);
 245                next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;
 246
 247                debug ("ax88180: RX updated RXBOUND=0x%04x,"
 248                       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
 249        }
 250
 251        return;
 252}
 253
 254static int ax88180_phy_initial (struct eth_device *dev)
 255{
 256        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 257        unsigned long tmp_regval;
 258
 259        /* Check avaliable PHY chipset  */
 260        priv->PhyAddr = MARVELL_88E1111_PHYADDR;
 261        priv->PhyID0 = ax88180_mdio_read (dev, PHYIDR0);
 262
 263        if (priv->PhyID0 == MARVELL_88E1111_PHYIDR0) {
 264
 265                debug ("ax88180: Found Marvell 88E1111 PHY."
 266                       " (PHY Addr=0x%x)\n", priv->PhyAddr);
 267
 268                tmp_regval = ax88180_mdio_read (dev, M88_EXT_SSR);
 269                if ((tmp_regval & HWCFG_MODE_MASK) == RGMII_COPPER_MODE) {
 270
 271                        ax88180_mdio_write (dev, M88_EXT_SCR, DEFAULT_EXT_SCR);
 272                        if (ax88180_phy_reset (dev) < 0)
 273                                return 0;
 274                        ax88180_mdio_write (dev, M88_IER, LINK_CHANGE_INT);
 275                }
 276        } else {
 277
 278                priv->PhyAddr = CICADA_CIS8201_PHYADDR;
 279                priv->PhyID0 = ax88180_mdio_read (dev, PHYIDR0);
 280
 281                if (priv->PhyID0 == CICADA_CIS8201_PHYIDR0) {
 282
 283                        debug ("ax88180: Found CICADA CIS8201 PHY"
 284                               " chipset. (PHY Addr=0x%x)\n", priv->PhyAddr);
 285                        ax88180_mdio_write (dev, CIS_IMR,
 286                                            (CIS_INT_ENABLE | LINK_CHANGE_INT));
 287
 288                        /* Set CIS_SMI_PRIORITY bit before force the media mode */
 289                        tmp_regval =
 290                            ax88180_mdio_read (dev, CIS_AUX_CTRL_STATUS);
 291                        tmp_regval &= ~CIS_SMI_PRIORITY;
 292                        ax88180_mdio_write (dev, CIS_AUX_CTRL_STATUS,
 293                                            tmp_regval);
 294                } else {
 295                        printf ("ax88180: Unknown PHY chipset!!\n");
 296                        return 0;
 297                }
 298        }
 299
 300        return 1;
 301}
 302
 303static void ax88180_meidia_config (struct eth_device *dev)
 304{
 305        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 306        unsigned long bmcr_val, bmsr_val;
 307        unsigned long rxcfg_val, maccfg0_val, maccfg1_val;
 308        unsigned long RealMediaMode;
 309        int i;
 310
 311        /* Waiting 2 seconds for PHY link stable */
 312        for (i = 0; i < 20000; i++) {
 313                bmsr_val = ax88180_mdio_read (dev, BMSR);
 314                if (bmsr_val & LINKOK) {
 315                        break;
 316                }
 317                udelay (100);
 318        }
 319
 320        bmsr_val = ax88180_mdio_read (dev, BMSR);
 321        debug ("ax88180: BMSR=0x%04x\n", (unsigned int)bmsr_val);
 322
 323        if (bmsr_val & LINKOK) {
 324                bmcr_val = ax88180_mdio_read (dev, BMCR);
 325
 326                if (bmcr_val & AUTONEG_EN) {
 327
 328                        /*
 329                         * Waiting for Auto-negotiation completion, this may
 330                         * take up to 5 seconds.
 331                         */
 332                        debug ("ax88180: Auto-negotiation is "
 333                               "enabled. Waiting for NWay completion..\n");
 334                        for (i = 0; i < 50000; i++) {
 335                                bmsr_val = ax88180_mdio_read (dev, BMSR);
 336                                if (bmsr_val & AUTONEG_COMPLETE) {
 337                                        break;
 338                                }
 339                                udelay (100);
 340                        }
 341                } else
 342                        debug ("ax88180: Auto-negotiation is disabled.\n");
 343
 344                debug ("ax88180: BMCR=0x%04x, BMSR=0x%04x\n",
 345                       (unsigned int)bmcr_val, (unsigned int)bmsr_val);
 346
 347                /* Get real media mode here */
 348                if (priv->PhyID0 == MARVELL_88E1111_PHYIDR0) {
 349                        RealMediaMode = get_MarvellPHY_meida_mode (dev);
 350                } else if (priv->PhyID0 == CICADA_CIS8201_PHYIDR0) {
 351                        RealMediaMode = get_CicadaPHY_meida_mode (dev);
 352                } else {
 353                        RealMediaMode = MEDIA_1000FULL;
 354                }
 355
 356                priv->LinkState = INS_LINK_UP;
 357
 358                switch (RealMediaMode) {
 359                case MEDIA_1000FULL:
 360                        debug ("ax88180: 1000Mbps Full-duplex mode.\n");
 361                        rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
 362                        maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
 363                        maccfg1_val = GIGA_MODE_EN | RXFLOW_EN |
 364                            FULLDUPLEX | DEFAULT_MACCFG1;
 365                        break;
 366
 367                case MEDIA_1000HALF:
 368                        debug ("ax88180: 1000Mbps Half-duplex mode.\n");
 369                        rxcfg_val = DEFAULT_RXCFG;
 370                        maccfg0_val = DEFAULT_MACCFG0;
 371                        maccfg1_val = GIGA_MODE_EN | DEFAULT_MACCFG1;
 372                        break;
 373
 374                case MEDIA_100FULL:
 375                        debug ("ax88180: 100Mbps Full-duplex mode.\n");
 376                        rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
 377                        maccfg0_val = SPEED100 | TXFLOW_ENABLE
 378                            | DEFAULT_MACCFG0;
 379                        maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
 380                        break;
 381
 382                case MEDIA_100HALF:
 383                        debug ("ax88180: 100Mbps Half-duplex mode.\n");
 384                        rxcfg_val = DEFAULT_RXCFG;
 385                        maccfg0_val = SPEED100 | DEFAULT_MACCFG0;
 386                        maccfg1_val = DEFAULT_MACCFG1;
 387                        break;
 388
 389                case MEDIA_10FULL:
 390                        debug ("ax88180: 10Mbps Full-duplex mode.\n");
 391                        rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
 392                        maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
 393                        maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
 394                        break;
 395
 396                case MEDIA_10HALF:
 397                        debug ("ax88180: 10Mbps Half-duplex mode.\n");
 398                        rxcfg_val = DEFAULT_RXCFG;
 399                        maccfg0_val = DEFAULT_MACCFG0;
 400                        maccfg1_val = DEFAULT_MACCFG1;
 401                        break;
 402                default:
 403                        debug ("ax88180: Unknow media mode.\n");
 404                        rxcfg_val = DEFAULT_RXCFG;
 405                        maccfg0_val = DEFAULT_MACCFG0;
 406                        maccfg1_val = DEFAULT_MACCFG1;
 407
 408                        priv->LinkState = INS_LINK_DOWN;
 409                        break;
 410                }
 411
 412        } else {
 413                rxcfg_val = DEFAULT_RXCFG;
 414                maccfg0_val = DEFAULT_MACCFG0;
 415                maccfg1_val = DEFAULT_MACCFG1;
 416
 417                priv->LinkState = INS_LINK_DOWN;
 418        }
 419
 420        OUTW (dev, rxcfg_val, RXCFG);
 421        OUTW (dev, maccfg0_val, MACCFG0);
 422        OUTW (dev, maccfg1_val, MACCFG1);
 423
 424        return;
 425}
 426
 427static unsigned long get_MarvellPHY_meida_mode (struct eth_device *dev)
 428{
 429        unsigned long m88_ssr;
 430        unsigned long MediaMode;
 431
 432        m88_ssr = ax88180_mdio_read (dev, M88_SSR);
 433        switch (m88_ssr & SSR_MEDIA_MASK) {
 434        case SSR_1000FULL:
 435                MediaMode = MEDIA_1000FULL;
 436                break;
 437        case SSR_1000HALF:
 438                MediaMode = MEDIA_1000HALF;
 439                break;
 440        case SSR_100FULL:
 441                MediaMode = MEDIA_100FULL;
 442                break;
 443        case SSR_100HALF:
 444                MediaMode = MEDIA_100HALF;
 445                break;
 446        case SSR_10FULL:
 447                MediaMode = MEDIA_10FULL;
 448                break;
 449        case SSR_10HALF:
 450                MediaMode = MEDIA_10HALF;
 451                break;
 452        default:
 453                MediaMode = MEDIA_UNKNOWN;
 454                break;
 455        }
 456
 457        return MediaMode;
 458}
 459
 460static unsigned long get_CicadaPHY_meida_mode (struct eth_device *dev)
 461{
 462        unsigned long tmp_regval;
 463        unsigned long MediaMode;
 464
 465        tmp_regval = ax88180_mdio_read (dev, CIS_AUX_CTRL_STATUS);
 466        switch (tmp_regval & CIS_MEDIA_MASK) {
 467        case CIS_1000FULL:
 468                MediaMode = MEDIA_1000FULL;
 469                break;
 470        case CIS_1000HALF:
 471                MediaMode = MEDIA_1000HALF;
 472                break;
 473        case CIS_100FULL:
 474                MediaMode = MEDIA_100FULL;
 475                break;
 476        case CIS_100HALF:
 477                MediaMode = MEDIA_100HALF;
 478                break;
 479        case CIS_10FULL:
 480                MediaMode = MEDIA_10FULL;
 481                break;
 482        case CIS_10HALF:
 483                MediaMode = MEDIA_10HALF;
 484                break;
 485        default:
 486                MediaMode = MEDIA_UNKNOWN;
 487                break;
 488        }
 489
 490        return MediaMode;
 491}
 492
 493static void ax88180_halt (struct eth_device *dev)
 494{
 495        /* Disable AX88180 TX/RX functions */
 496        OUTW (dev, WAKEMOD, CMD);
 497}
 498
 499static int ax88180_init (struct eth_device *dev, bd_t * bd)
 500{
 501        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 502        unsigned short tmp_regval;
 503
 504        ax88180_mac_reset (dev);
 505
 506        /* Disable interrupt */
 507        OUTW (dev, CLEAR_IMR, IMR);
 508
 509        /* Disable AX88180 TX/RX functions */
 510        OUTW (dev, WAKEMOD, CMD);
 511
 512        /* Fill the MAC address */
 513        tmp_regval =
 514            dev->enetaddr[0] | (((unsigned short)dev->enetaddr[1]) << 8);
 515        OUTW (dev, tmp_regval, MACID0);
 516
 517        tmp_regval =
 518            dev->enetaddr[2] | (((unsigned short)dev->enetaddr[3]) << 8);
 519        OUTW (dev, tmp_regval, MACID1);
 520
 521        tmp_regval =
 522            dev->enetaddr[4] | (((unsigned short)dev->enetaddr[5]) << 8);
 523        OUTW (dev, tmp_regval, MACID2);
 524
 525        ax88180_meidia_config (dev);
 526
 527        OUTW (dev, DEFAULT_RXFILTER, RXFILTER);
 528
 529        /* Initial variables here */
 530        priv->FirstTxDesc = TXDP0;
 531        priv->NextTxDesc = TXDP0;
 532
 533        /* Check if there is any invalid interrupt status and clear it. */
 534        OUTW (dev, INW (dev, ISR), ISR);
 535
 536        /* Start AX88180 TX/RX functions */
 537        OUTW (dev, (RXEN | TXEN | WAKEMOD), CMD);
 538
 539        return 0;
 540}
 541
 542/* Get a data block via Ethernet */
 543static int ax88180_recv (struct eth_device *dev)
 544{
 545        unsigned short ISR_Status;
 546        unsigned short tmp_regval;
 547
 548        /* Read and check interrupt status here. */
 549        ISR_Status = INW (dev, ISR);
 550
 551        while (ISR_Status) {
 552                /* Clear the interrupt status */
 553                OUTW (dev, ISR_Status, ISR);
 554
 555                debug ("\nax88180: The interrupt status = 0x%04x\n",
 556                       ISR_Status);
 557
 558                if (ISR_Status & ISR_PHY) {
 559                        /* Read ISR register once to clear PHY interrupt bit */
 560                        tmp_regval = ax88180_mdio_read (dev, M88_ISR);
 561                        ax88180_meidia_config (dev);
 562                }
 563
 564                if ((ISR_Status & ISR_RX) || (ISR_Status & ISR_RXBUFFOVR)) {
 565                        ax88180_rx_handler (dev);
 566                }
 567
 568                /* Read and check interrupt status again */
 569                ISR_Status = INW (dev, ISR);
 570        }
 571
 572        return 0;
 573}
 574
 575/* Send a data block via Ethernet. */
 576static int
 577ax88180_send (struct eth_device *dev, volatile void *packet, int length)
 578{
 579        struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
 580        unsigned short TXDES_addr;
 581        unsigned short txcmd_txdp, txbs_txdp;
 582        unsigned short tmp_data;
 583        int i;
 584#if defined (CONFIG_DRIVER_AX88180_16BIT)
 585        volatile unsigned short *txdata = (volatile unsigned short *)packet;
 586#else
 587        volatile unsigned long *txdata = (volatile unsigned long *)packet;
 588#endif
 589        unsigned short count;
 590
 591        if (priv->LinkState != INS_LINK_UP) {
 592                return 0;
 593        }
 594
 595        priv->FirstTxDesc = priv->NextTxDesc;
 596        txbs_txdp = 1 << priv->FirstTxDesc;
 597
 598        debug ("ax88180: TXDP%d is available\n", priv->FirstTxDesc);
 599
 600        txcmd_txdp = priv->FirstTxDesc << 13;
 601        TXDES_addr = TXDES0 + (priv->FirstTxDesc << 2);
 602
 603        OUTW (dev, (txcmd_txdp | length | TX_START_WRITE), TXCMD);
 604
 605        /* Comput access times */
 606        count = (length + priv->PadSize) >> priv->BusWidth;
 607
 608        for (i = 0; i < count; i++) {
 609                WRITE_TXBUF (dev, *(txdata + i));
 610        }
 611
 612        OUTW (dev, txcmd_txdp | length, TXCMD);
 613        OUTW (dev, txbs_txdp, TXBS);
 614        OUTW (dev, (TXDPx_ENABLE | length), TXDES_addr);
 615
 616        priv->NextTxDesc = (priv->NextTxDesc + 1) & TXDP_MASK;
 617
 618        /*
 619         * Check the available transmit descriptor, if we had exhausted all
 620         * transmit descriptor ,then we have to wait for at least one free
 621         * descriptor
 622         */
 623        txbs_txdp = 1 << priv->NextTxDesc;
 624        tmp_data = INW (dev, TXBS);
 625
 626        if (tmp_data & txbs_txdp) {
 627                if (ax88180_poll_tx_complete (dev) < 0) {
 628                        ax88180_mac_reset (dev);
 629                        priv->FirstTxDesc = TXDP0;
 630                        priv->NextTxDesc = TXDP0;
 631                        printf ("ax88180: Transmit time out occurred!\n");
 632                }
 633        }
 634
 635        return 0;
 636}
 637
 638static void ax88180_read_mac_addr (struct eth_device *dev)
 639{
 640        unsigned short macid0_val, macid1_val, macid2_val;
 641        unsigned short tmp_regval;
 642        unsigned short i;
 643
 644        /* Reload MAC address from EEPROM */
 645        OUTW (dev, RELOAD_EEPROM, PROMCTRL);
 646
 647        /* Waiting for reload eeprom completion */
 648        for (i = 0; i < 500; i++) {
 649                tmp_regval = INW (dev, PROMCTRL);
 650                if ((tmp_regval & RELOAD_EEPROM) == 0)
 651                        break;
 652                udelay (1000);
 653        }
 654
 655        /* Get MAC addresses */
 656        macid0_val = INW (dev, MACID0);
 657        macid1_val = INW (dev, MACID1);
 658        macid2_val = INW (dev, MACID2);
 659
 660        if (((macid0_val | macid1_val | macid2_val) != 0) &&
 661            ((macid0_val & 0x01) == 0)) {
 662                dev->enetaddr[0] = (unsigned char)macid0_val;
 663                dev->enetaddr[1] = (unsigned char)(macid0_val >> 8);
 664                dev->enetaddr[2] = (unsigned char)macid1_val;
 665                dev->enetaddr[3] = (unsigned char)(macid1_val >> 8);
 666                dev->enetaddr[4] = (unsigned char)macid2_val;
 667                dev->enetaddr[5] = (unsigned char)(macid2_val >> 8);
 668        }
 669}
 670
 671/*
 672===========================================================================
 673<<<<<<                  Exported SubProgram Bodies              >>>>>>
 674===========================================================================
 675*/
 676int ax88180_initialize (bd_t * bis)
 677{
 678        struct eth_device *dev;
 679        struct ax88180_private *priv;
 680
 681        dev = (struct eth_device *)malloc (sizeof *dev);
 682
 683        if (NULL == dev)
 684                return 0;
 685
 686        memset (dev, 0, sizeof *dev);
 687
 688        priv = (struct ax88180_private *)malloc (sizeof (*priv));
 689
 690        if (NULL == priv)
 691                return 0;
 692
 693        memset (priv, 0, sizeof *priv);
 694
 695        sprintf (dev->name, "ax88180");
 696        dev->iobase = AX88180_BASE;
 697        dev->priv = priv;
 698        dev->init = ax88180_init;
 699        dev->halt = ax88180_halt;
 700        dev->send = ax88180_send;
 701        dev->recv = ax88180_recv;
 702
 703        priv->BusWidth = BUS_WIDTH_32;
 704        priv->PadSize = 3;
 705#if defined (CONFIG_DRIVER_AX88180_16BIT)
 706        OUTW (dev, (START_BASE >> 8), BASE);
 707        OUTW (dev, DECODE_EN, DECODE);
 708
 709        priv->BusWidth = BUS_WIDTH_16;
 710        priv->PadSize = 1;
 711#endif
 712
 713        ax88180_mac_reset (dev);
 714
 715        /* Disable interrupt */
 716        OUTW (dev, CLEAR_IMR, IMR);
 717
 718        /* Disable AX88180 TX/RX functions */
 719        OUTW (dev, WAKEMOD, CMD);
 720
 721        ax88180_read_mac_addr (dev);
 722
 723        eth_register (dev);
 724
 725        return ax88180_phy_initial (dev);
 726
 727}
 728