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