uboot/drivers/net/xilinx_emaclite.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2007-2009 Michal Simek
   4 * (C) Copyright 2003 Xilinx Inc.
   5 *
   6 * Michal SIMEK <monstr@monstr.eu>
   7 */
   8
   9#include <common.h>
  10#include <net.h>
  11#include <config.h>
  12#include <dm.h>
  13#include <console.h>
  14#include <malloc.h>
  15#include <asm/io.h>
  16#include <phy.h>
  17#include <miiphy.h>
  18#include <fdtdec.h>
  19#include <linux/errno.h>
  20#include <linux/kernel.h>
  21#include <asm/io.h>
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25#define ENET_ADDR_LENGTH        6
  26#define ETH_FCS_LEN             4 /* Octets in the FCS */
  27
  28/* Xmit complete */
  29#define XEL_TSR_XMIT_BUSY_MASK          0x00000001UL
  30/* Xmit interrupt enable bit */
  31#define XEL_TSR_XMIT_IE_MASK            0x00000008UL
  32/* Program the MAC address */
  33#define XEL_TSR_PROGRAM_MASK            0x00000002UL
  34/* define for programming the MAC address into the EMAC Lite */
  35#define XEL_TSR_PROG_MAC_ADDR   (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
  36
  37/* Transmit packet length upper byte */
  38#define XEL_TPLR_LENGTH_MASK_HI         0x0000FF00UL
  39/* Transmit packet length lower byte */
  40#define XEL_TPLR_LENGTH_MASK_LO         0x000000FFUL
  41
  42/* Recv complete */
  43#define XEL_RSR_RECV_DONE_MASK          0x00000001UL
  44/* Recv interrupt enable bit */
  45#define XEL_RSR_RECV_IE_MASK            0x00000008UL
  46
  47/* MDIO Address Register Bit Masks */
  48#define XEL_MDIOADDR_REGADR_MASK  0x0000001F    /* Register Address */
  49#define XEL_MDIOADDR_PHYADR_MASK  0x000003E0    /* PHY Address */
  50#define XEL_MDIOADDR_PHYADR_SHIFT 5
  51#define XEL_MDIOADDR_OP_MASK      0x00000400    /* RD/WR Operation */
  52
  53/* MDIO Write Data Register Bit Masks */
  54#define XEL_MDIOWR_WRDATA_MASK    0x0000FFFF    /* Data to be Written */
  55
  56/* MDIO Read Data Register Bit Masks */
  57#define XEL_MDIORD_RDDATA_MASK    0x0000FFFF    /* Data to be Read */
  58
  59/* MDIO Control Register Bit Masks */
  60#define XEL_MDIOCTRL_MDIOSTS_MASK 0x00000001    /* MDIO Status Mask */
  61#define XEL_MDIOCTRL_MDIOEN_MASK  0x00000008    /* MDIO Enable */
  62
  63struct emaclite_regs {
  64        u32 tx_ping; /* 0x0 - TX Ping buffer */
  65        u32 reserved1[504];
  66        u32 mdioaddr; /* 0x7e4 - MDIO Address Register */
  67        u32 mdiowr; /* 0x7e8 - MDIO Write Data Register */
  68        u32 mdiord;/* 0x7ec - MDIO Read Data Register */
  69        u32 mdioctrl; /* 0x7f0 - MDIO Control Register */
  70        u32 tx_ping_tplr; /* 0x7f4 - Tx packet length */
  71        u32 global_interrupt; /* 0x7f8 - Global interrupt enable */
  72        u32 tx_ping_tsr; /* 0x7fc - Tx status */
  73        u32 tx_pong; /* 0x800 - TX Pong buffer */
  74        u32 reserved2[508];
  75        u32 tx_pong_tplr; /* 0xff4 - Tx packet length */
  76        u32 reserved3; /* 0xff8 */
  77        u32 tx_pong_tsr; /* 0xffc - Tx status */
  78        u32 rx_ping; /* 0x1000 - Receive Buffer */
  79        u32 reserved4[510];
  80        u32 rx_ping_rsr; /* 0x17fc - Rx status */
  81        u32 rx_pong; /* 0x1800 - Receive Buffer */
  82        u32 reserved5[510];
  83        u32 rx_pong_rsr; /* 0x1ffc - Rx status */
  84};
  85
  86struct xemaclite {
  87        bool use_rx_pong_buffer_next;   /* Next RX buffer to read from */
  88        u32 txpp;               /* TX ping pong buffer */
  89        u32 rxpp;               /* RX ping pong buffer */
  90        int phyaddr;
  91        struct emaclite_regs *regs;
  92        struct phy_device *phydev;
  93        struct mii_dev *bus;
  94};
  95
  96static uchar etherrxbuff[PKTSIZE_ALIGN]; /* Receive buffer */
  97
  98static void xemaclite_alignedread(u32 *srcptr, void *destptr, u32 bytecount)
  99{
 100        u32 i;
 101        u32 alignbuffer;
 102        u32 *to32ptr;
 103        u32 *from32ptr;
 104        u8 *to8ptr;
 105        u8 *from8ptr;
 106
 107        from32ptr = (u32 *) srcptr;
 108
 109        /* Word aligned buffer, no correction needed. */
 110        to32ptr = (u32 *) destptr;
 111        while (bytecount > 3) {
 112                *to32ptr++ = *from32ptr++;
 113                bytecount -= 4;
 114        }
 115        to8ptr = (u8 *) to32ptr;
 116
 117        alignbuffer = *from32ptr++;
 118        from8ptr = (u8 *) &alignbuffer;
 119
 120        for (i = 0; i < bytecount; i++)
 121                *to8ptr++ = *from8ptr++;
 122}
 123
 124static void xemaclite_alignedwrite(void *srcptr, u32 *destptr, u32 bytecount)
 125{
 126        u32 i;
 127        u32 alignbuffer;
 128        u32 *to32ptr = (u32 *) destptr;
 129        u32 *from32ptr;
 130        u8 *to8ptr;
 131        u8 *from8ptr;
 132
 133        from32ptr = (u32 *) srcptr;
 134        while (bytecount > 3) {
 135
 136                *to32ptr++ = *from32ptr++;
 137                bytecount -= 4;
 138        }
 139
 140        alignbuffer = 0;
 141        to8ptr = (u8 *) &alignbuffer;
 142        from8ptr = (u8 *) from32ptr;
 143
 144        for (i = 0; i < bytecount; i++)
 145                *to8ptr++ = *from8ptr++;
 146
 147        *to32ptr++ = alignbuffer;
 148}
 149
 150static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
 151                        bool set, unsigned int timeout)
 152{
 153        u32 val;
 154        unsigned long start = get_timer(0);
 155
 156        while (1) {
 157                val = __raw_readl(reg);
 158
 159                if (!set)
 160                        val = ~val;
 161
 162                if ((val & mask) == mask)
 163                        return 0;
 164
 165                if (get_timer(start) > timeout)
 166                        break;
 167
 168                if (ctrlc()) {
 169                        puts("Abort\n");
 170                        return -EINTR;
 171                }
 172
 173                udelay(1);
 174        }
 175
 176        debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n",
 177              func, reg, mask, set);
 178
 179        return -ETIMEDOUT;
 180}
 181
 182static int mdio_wait(struct emaclite_regs *regs)
 183{
 184        return wait_for_bit(__func__, &regs->mdioctrl,
 185                            XEL_MDIOCTRL_MDIOSTS_MASK, false, 2000);
 186}
 187
 188static u32 phyread(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
 189                   u16 *data)
 190{
 191        struct emaclite_regs *regs = emaclite->regs;
 192
 193        if (mdio_wait(regs))
 194                return 1;
 195
 196        u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
 197        __raw_writel(XEL_MDIOADDR_OP_MASK
 198                | ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
 199                | registernum), &regs->mdioaddr);
 200        __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
 201
 202        if (mdio_wait(regs))
 203                return 1;
 204
 205        /* Read data */
 206        *data = __raw_readl(&regs->mdiord);
 207        return 0;
 208}
 209
 210static u32 phywrite(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
 211                    u16 data)
 212{
 213        struct emaclite_regs *regs = emaclite->regs;
 214
 215        if (mdio_wait(regs))
 216                return 1;
 217
 218        /*
 219         * Write the PHY address, register number and clear the OP bit in the
 220         * MDIO Address register and then write the value into the MDIO Write
 221         * Data register. Finally, set the Status bit in the MDIO Control
 222         * register to start a MDIO write transaction.
 223         */
 224        u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
 225        __raw_writel(~XEL_MDIOADDR_OP_MASK
 226                & ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
 227                | registernum), &regs->mdioaddr);
 228        __raw_writel(data, &regs->mdiowr);
 229        __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
 230
 231        if (mdio_wait(regs))
 232                return 1;
 233
 234        return 0;
 235}
 236
 237static void emaclite_stop(struct udevice *dev)
 238{
 239        debug("eth_stop\n");
 240}
 241
 242/* Use MII register 1 (MII status register) to detect PHY */
 243#define PHY_DETECT_REG  1
 244
 245/* Mask used to verify certain PHY features (or register contents)
 246 * in the register above:
 247 *  0x1000: 10Mbps full duplex support
 248 *  0x0800: 10Mbps half duplex support
 249 *  0x0008: Auto-negotiation support
 250 */
 251#define PHY_DETECT_MASK 0x1808
 252
 253static int setup_phy(struct udevice *dev)
 254{
 255        int i, ret;
 256        u16 phyreg;
 257        struct xemaclite *emaclite = dev_get_priv(dev);
 258        struct phy_device *phydev;
 259
 260        u32 supported = SUPPORTED_10baseT_Half |
 261                        SUPPORTED_10baseT_Full |
 262                        SUPPORTED_100baseT_Half |
 263                        SUPPORTED_100baseT_Full;
 264
 265        if (emaclite->phyaddr != -1) {
 266                phyread(emaclite, emaclite->phyaddr, PHY_DETECT_REG, &phyreg);
 267                if ((phyreg != 0xFFFF) &&
 268                    ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
 269                        /* Found a valid PHY address */
 270                        debug("Default phy address %d is valid\n",
 271                              emaclite->phyaddr);
 272                } else {
 273                        debug("PHY address is not setup correctly %d\n",
 274                              emaclite->phyaddr);
 275                        emaclite->phyaddr = -1;
 276                }
 277        }
 278
 279        if (emaclite->phyaddr == -1) {
 280                /* detect the PHY address */
 281                for (i = 31; i >= 0; i--) {
 282                        phyread(emaclite, i, PHY_DETECT_REG, &phyreg);
 283                        if ((phyreg != 0xFFFF) &&
 284                            ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
 285                                /* Found a valid PHY address */
 286                                emaclite->phyaddr = i;
 287                                debug("emaclite: Found valid phy address, %d\n",
 288                                      i);
 289                                break;
 290                        }
 291                }
 292        }
 293
 294        /* interface - look at tsec */
 295        phydev = phy_connect(emaclite->bus, emaclite->phyaddr, dev,
 296                             PHY_INTERFACE_MODE_MII);
 297        /*
 298         * Phy can support 1000baseT but device NOT that's why phydev->supported
 299         * must be setup for 1000baseT. phydev->advertising setups what speeds
 300         * will be used for autonegotiation where 1000baseT must be disabled.
 301         */
 302        phydev->supported = supported | SUPPORTED_1000baseT_Half |
 303                                                SUPPORTED_1000baseT_Full;
 304        phydev->advertising = supported;
 305        emaclite->phydev = phydev;
 306        phy_config(phydev);
 307        ret = phy_startup(phydev);
 308        if (ret)
 309                return ret;
 310
 311        if (!phydev->link) {
 312                printf("%s: No link.\n", phydev->dev->name);
 313                return 0;
 314        }
 315
 316        /* Do not setup anything */
 317        return 1;
 318}
 319
 320static int emaclite_start(struct udevice *dev)
 321{
 322        struct xemaclite *emaclite = dev_get_priv(dev);
 323        struct eth_pdata *pdata = dev_get_platdata(dev);
 324        struct emaclite_regs *regs = emaclite->regs;
 325
 326        debug("EmacLite Initialization Started\n");
 327
 328/*
 329 * TX - TX_PING & TX_PONG initialization
 330 */
 331        /* Restart PING TX */
 332        __raw_writel(0, &regs->tx_ping_tsr);
 333        /* Copy MAC address */
 334        xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_ping,
 335                               ENET_ADDR_LENGTH);
 336        /* Set the length */
 337        __raw_writel(ENET_ADDR_LENGTH, &regs->tx_ping_tplr);
 338        /* Update the MAC address in the EMAC Lite */
 339        __raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_ping_tsr);
 340        /* Wait for EMAC Lite to finish with the MAC address update */
 341        while ((__raw_readl(&regs->tx_ping_tsr) &
 342                XEL_TSR_PROG_MAC_ADDR) != 0)
 343                ;
 344
 345        if (emaclite->txpp) {
 346                /* The same operation with PONG TX */
 347                __raw_writel(0, &regs->tx_pong_tsr);
 348                xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_pong,
 349                                       ENET_ADDR_LENGTH);
 350                __raw_writel(ENET_ADDR_LENGTH, &regs->tx_pong_tplr);
 351                __raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_pong_tsr);
 352                while ((__raw_readl(&regs->tx_pong_tsr) &
 353                       XEL_TSR_PROG_MAC_ADDR) != 0)
 354                        ;
 355        }
 356
 357/*
 358 * RX - RX_PING & RX_PONG initialization
 359 */
 360        /* Write out the value to flush the RX buffer */
 361        __raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_ping_rsr);
 362
 363        if (emaclite->rxpp)
 364                __raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_pong_rsr);
 365
 366        __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, &regs->mdioctrl);
 367        if (__raw_readl(&regs->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
 368                if (!setup_phy(dev))
 369                        return -1;
 370
 371        debug("EmacLite Initialization complete\n");
 372        return 0;
 373}
 374
 375static int xemaclite_txbufferavailable(struct xemaclite *emaclite)
 376{
 377        u32 tmp;
 378        struct emaclite_regs *regs = emaclite->regs;
 379
 380        /*
 381         * Read the other buffer register
 382         * and determine if the other buffer is available
 383         */
 384        tmp = ~__raw_readl(&regs->tx_ping_tsr);
 385        if (emaclite->txpp)
 386                tmp |= ~__raw_readl(&regs->tx_pong_tsr);
 387
 388        return !(tmp & XEL_TSR_XMIT_BUSY_MASK);
 389}
 390
 391static int emaclite_send(struct udevice *dev, void *ptr, int len)
 392{
 393        u32 reg;
 394        struct xemaclite *emaclite = dev_get_priv(dev);
 395        struct emaclite_regs *regs = emaclite->regs;
 396
 397        u32 maxtry = 1000;
 398
 399        if (len > PKTSIZE)
 400                len = PKTSIZE;
 401
 402        while (xemaclite_txbufferavailable(emaclite) && maxtry) {
 403                udelay(10);
 404                maxtry--;
 405        }
 406
 407        if (!maxtry) {
 408                printf("Error: Timeout waiting for ethernet TX buffer\n");
 409                /* Restart PING TX */
 410                __raw_writel(0, &regs->tx_ping_tsr);
 411                if (emaclite->txpp) {
 412                        __raw_writel(0, &regs->tx_pong_tsr);
 413                }
 414                return -1;
 415        }
 416
 417        /* Determine if the expected buffer address is empty */
 418        reg = __raw_readl(&regs->tx_ping_tsr);
 419        if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
 420                debug("Send packet from tx_ping buffer\n");
 421                /* Write the frame to the buffer */
 422                xemaclite_alignedwrite(ptr, &regs->tx_ping, len);
 423                __raw_writel(len
 424                        & (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO),
 425                       &regs->tx_ping_tplr);
 426                reg = __raw_readl(&regs->tx_ping_tsr);
 427                reg |= XEL_TSR_XMIT_BUSY_MASK;
 428                __raw_writel(reg, &regs->tx_ping_tsr);
 429                return 0;
 430        }
 431
 432        if (emaclite->txpp) {
 433                /* Determine if the expected buffer address is empty */
 434                reg = __raw_readl(&regs->tx_pong_tsr);
 435                if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
 436                        debug("Send packet from tx_pong buffer\n");
 437                        /* Write the frame to the buffer */
 438                        xemaclite_alignedwrite(ptr, &regs->tx_pong, len);
 439                        __raw_writel(len &
 440                                 (XEL_TPLR_LENGTH_MASK_HI |
 441                                  XEL_TPLR_LENGTH_MASK_LO),
 442                                  &regs->tx_pong_tplr);
 443                        reg = __raw_readl(&regs->tx_pong_tsr);
 444                        reg |= XEL_TSR_XMIT_BUSY_MASK;
 445                        __raw_writel(reg, &regs->tx_pong_tsr);
 446                        return 0;
 447                }
 448        }
 449
 450        puts("Error while sending frame\n");
 451        return -1;
 452}
 453
 454static int emaclite_recv(struct udevice *dev, int flags, uchar **packetp)
 455{
 456        u32 length, first_read, reg, attempt = 0;
 457        void *addr, *ack;
 458        struct xemaclite *emaclite = dev->priv;
 459        struct emaclite_regs *regs = emaclite->regs;
 460        struct ethernet_hdr *eth;
 461        struct ip_udp_hdr *ip;
 462
 463try_again:
 464        if (!emaclite->use_rx_pong_buffer_next) {
 465                reg = __raw_readl(&regs->rx_ping_rsr);
 466                debug("Testing data at rx_ping\n");
 467                if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
 468                        debug("Data found in rx_ping buffer\n");
 469                        addr = &regs->rx_ping;
 470                        ack = &regs->rx_ping_rsr;
 471                } else {
 472                        debug("Data not found in rx_ping buffer\n");
 473                        /* Pong buffer is not available - return immediately */
 474                        if (!emaclite->rxpp)
 475                                return -1;
 476
 477                        /* Try pong buffer if this is first attempt */
 478                        if (attempt++)
 479                                return -1;
 480                        emaclite->use_rx_pong_buffer_next =
 481                                        !emaclite->use_rx_pong_buffer_next;
 482                        goto try_again;
 483                }
 484        } else {
 485                reg = __raw_readl(&regs->rx_pong_rsr);
 486                debug("Testing data at rx_pong\n");
 487                if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
 488                        debug("Data found in rx_pong buffer\n");
 489                        addr = &regs->rx_pong;
 490                        ack = &regs->rx_pong_rsr;
 491                } else {
 492                        debug("Data not found in rx_pong buffer\n");
 493                        /* Try ping buffer if this is first attempt */
 494                        if (attempt++)
 495                                return -1;
 496                        emaclite->use_rx_pong_buffer_next =
 497                                        !emaclite->use_rx_pong_buffer_next;
 498                        goto try_again;
 499                }
 500        }
 501
 502        /* Read all bytes for ARP packet with 32bit alignment - 48bytes  */
 503        first_read = ALIGN(ETHER_HDR_SIZE + ARP_HDR_SIZE + ETH_FCS_LEN, 4);
 504        xemaclite_alignedread(addr, etherrxbuff, first_read);
 505
 506        /* Detect real packet size */
 507        eth = (struct ethernet_hdr *)etherrxbuff;
 508        switch (ntohs(eth->et_protlen)) {
 509        case PROT_ARP:
 510                length = first_read;
 511                debug("ARP Packet %x\n", length);
 512                break;
 513        case PROT_IP:
 514                ip = (struct ip_udp_hdr *)(etherrxbuff + ETHER_HDR_SIZE);
 515                length = ntohs(ip->ip_len);
 516                length += ETHER_HDR_SIZE + ETH_FCS_LEN;
 517                debug("IP Packet %x\n", length);
 518                break;
 519        default:
 520                debug("Other Packet\n");
 521                length = PKTSIZE;
 522                break;
 523        }
 524
 525        /* Read the rest of the packet which is longer then first read */
 526        if (length != first_read)
 527                xemaclite_alignedread(addr + first_read,
 528                                      etherrxbuff + first_read,
 529                                      length - first_read);
 530
 531        /* Acknowledge the frame */
 532        reg = __raw_readl(ack);
 533        reg &= ~XEL_RSR_RECV_DONE_MASK;
 534        __raw_writel(reg, ack);
 535
 536        debug("Packet receive from 0x%p, length %dB\n", addr, length);
 537        *packetp = etherrxbuff;
 538        return length;
 539}
 540
 541static int emaclite_miiphy_read(struct mii_dev *bus, int addr,
 542                                int devad, int reg)
 543{
 544        u32 ret;
 545        u16 val = 0;
 546
 547        ret = phyread(bus->priv, addr, reg, &val);
 548        debug("emaclite: Read MII 0x%x, 0x%x, 0x%x, %d\n", addr, reg, val, ret);
 549        return val;
 550}
 551
 552static int emaclite_miiphy_write(struct mii_dev *bus, int addr, int devad,
 553                                 int reg, u16 value)
 554{
 555        debug("emaclite: Write MII 0x%x, 0x%x, 0x%x\n", addr, reg, value);
 556        return phywrite(bus->priv, addr, reg, value);
 557}
 558
 559static int emaclite_probe(struct udevice *dev)
 560{
 561        struct xemaclite *emaclite = dev_get_priv(dev);
 562        int ret;
 563
 564        emaclite->bus = mdio_alloc();
 565        emaclite->bus->read = emaclite_miiphy_read;
 566        emaclite->bus->write = emaclite_miiphy_write;
 567        emaclite->bus->priv = emaclite;
 568
 569        ret = mdio_register_seq(emaclite->bus, dev->seq);
 570        if (ret)
 571                return ret;
 572
 573        return 0;
 574}
 575
 576static int emaclite_remove(struct udevice *dev)
 577{
 578        struct xemaclite *emaclite = dev_get_priv(dev);
 579
 580        free(emaclite->phydev);
 581        mdio_unregister(emaclite->bus);
 582        mdio_free(emaclite->bus);
 583
 584        return 0;
 585}
 586
 587static const struct eth_ops emaclite_ops = {
 588        .start = emaclite_start,
 589        .send = emaclite_send,
 590        .recv = emaclite_recv,
 591        .stop = emaclite_stop,
 592};
 593
 594static int emaclite_ofdata_to_platdata(struct udevice *dev)
 595{
 596        struct eth_pdata *pdata = dev_get_platdata(dev);
 597        struct xemaclite *emaclite = dev_get_priv(dev);
 598        int offset = 0;
 599
 600        pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 601        emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
 602                                                                 0x10000);
 603
 604        emaclite->phyaddr = -1;
 605
 606        offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
 607                                      "phy-handle");
 608        if (offset > 0)
 609                emaclite->phyaddr = fdtdec_get_int(gd->fdt_blob, offset,
 610                                                   "reg", -1);
 611
 612        emaclite->txpp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 613                                        "xlnx,tx-ping-pong", 0);
 614        emaclite->rxpp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 615                                        "xlnx,rx-ping-pong", 0);
 616
 617        printf("EMACLITE: %lx, phyaddr %d, %d/%d\n", (ulong)emaclite->regs,
 618               emaclite->phyaddr, emaclite->txpp, emaclite->rxpp);
 619
 620        return 0;
 621}
 622
 623static const struct udevice_id emaclite_ids[] = {
 624        { .compatible = "xlnx,xps-ethernetlite-1.00.a" },
 625        { }
 626};
 627
 628U_BOOT_DRIVER(emaclite) = {
 629        .name   = "emaclite",
 630        .id     = UCLASS_ETH,
 631        .of_match = emaclite_ids,
 632        .ofdata_to_platdata = emaclite_ofdata_to_platdata,
 633        .probe  = emaclite_probe,
 634        .remove = emaclite_remove,
 635        .ops    = &emaclite_ops,
 636        .priv_auto_alloc_size = sizeof(struct xemaclite),
 637        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
 638};
 639