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