1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Texas Instruments K3 AM65 PRU Ethernet Driver 4 * 5 * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ 6 * 7 */ 8 9#include <asm/io.h> 10#include <asm/processor.h> 11#include <clk.h> 12#include <dm/lists.h> 13#include <dm/device.h> 14#include <dma-uclass.h> 15#include <dm/of_access.h> 16#include <dm/pinctrl.h> 17#include <fs_loader.h> 18#include <miiphy.h> 19#include <net.h> 20#include <phy.h> 21#include <power-domain.h> 22#include <linux/soc/ti/ti-udma.h> 23#include <regmap.h> 24#include <remoteproc.h> 25#include <syscon.h> 26#include <soc.h> 27#include <linux/pruss_driver.h> 28#include <dm/device_compat.h> 29 30#include "icssg_prueth.h" 31#include "icss_mii_rt.h" 32 33#define ICSS_SLICE0 0 34#define ICSS_SLICE1 1 35 36#ifdef PKTSIZE_ALIGN 37#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN 38#else 39#define UDMA_RX_BUF_SIZE ALIGN(PKTSIZE, ARCH_DMA_MINALIGN) 40#endif 41 42#ifdef PKTBUFSRX 43#define UDMA_RX_DESC_NUM PKTBUFSRX 44#else 45#define UDMA_RX_DESC_NUM 4 46#endif 47 48/* Config region lies in shared RAM */ 49#define ICSS_CONFIG_OFFSET_SLICE0 0 50#define ICSS_CONFIG_OFFSET_SLICE1 0x8000 51 52/* Firmware flags */ 53#define ICSS_SET_RUN_FLAG_VLAN_ENABLE BIT(0) /* switch only */ 54#define ICSS_SET_RUN_FLAG_FLOOD_UNICAST BIT(1) /* switch only */ 55#define ICSS_SET_RUN_FLAG_PROMISC BIT(2) /* MAC only */ 56#define ICSS_SET_RUN_FLAG_MULTICAST_PROMISC BIT(3) /* MAC only */ 57 58/* CTRLMMR_ICSSG_RGMII_CTRL register bits */ 59#define ICSSG_CTRL_RGMII_ID_MODE BIT(24) 60 61/* Management packet type */ 62#define PRUETH_PKT_TYPE_CMD 0x10 63 64/* Number of PRU Cores per Slice */ 65#define ICSSG_NUM_PRU_CORES 3 66 67static int icssg_gmii_select(struct prueth_priv *priv) 68{ 69 struct phy_device *phydev = priv->phydev; 70 71 if (phydev->interface != PHY_INTERFACE_MODE_MII && 72 phydev->interface < PHY_INTERFACE_MODE_RGMII && 73 phydev->interface > PHY_INTERFACE_MODE_RGMII_TXID) { 74 dev_err(priv->dev, "PHY mode unsupported %s\n", 75 phy_string_for_interface(phydev->interface)); 76 return -EINVAL; 77 } 78 79 /* AM65 SR2.0 has TX Internal delay always enabled by hardware 80 * and it is not possible to disable TX Internal delay. The below 81 * switch case block describes how we handle different phy modes 82 * based on hardware restriction. 83 */ 84 switch (phydev->interface) { 85 case PHY_INTERFACE_MODE_RGMII_ID: 86 phydev->interface = PHY_INTERFACE_MODE_RGMII_RXID; 87 break; 88 case PHY_INTERFACE_MODE_RGMII_TXID: 89 phydev->interface = PHY_INTERFACE_MODE_RGMII; 90 break; 91 case PHY_INTERFACE_MODE_RGMII: 92 case PHY_INTERFACE_MODE_RGMII_RXID: 93 dev_err(priv->dev, "RGMII mode without TX delay is not supported"); 94 return -EINVAL; 95 default: 96 break; 97 } 98 99 return 0; 100} 101 102static int icssg_phy_init(struct udevice *dev) 103{ 104 struct prueth_priv *priv = dev_get_priv(dev); 105 struct phy_device *phydev; 106 u32 supported = PHY_GBIT_FEATURES; 107 int ret; 108 109 phydev = dm_eth_phy_connect(dev); 110 if (!phydev) { 111 dev_err(dev, "phy_connect() failed\n"); 112 return -ENODEV; 113 } 114 115 /* disable unsupported features */ 116 supported &= ~(PHY_10BT_FEATURES | 117 SUPPORTED_100baseT_Half | 118 SUPPORTED_1000baseT_Half | 119 SUPPORTED_Pause | 120 SUPPORTED_Asym_Pause); 121 122 phydev->supported &= supported; 123 phydev->advertising = phydev->supported; 124 priv->phydev = phydev; 125 126 ret = icssg_gmii_select(priv); 127 if (ret) 128 goto out; 129 130 ret = phy_config(phydev); 131 if (ret < 0) 132 dev_err(dev, "phy_config() failed: %d", ret); 133out: 134 return ret; 135} 136 137static void icssg_config_set_speed(struct prueth_priv *priv, int speed) 138{ 139 struct prueth *prueth = priv->prueth; 140 u8 fw_speed; 141 142 switch (speed) { 143 case SPEED_1000: 144 fw_speed = FW_LINK_SPEED_1G; 145 break; 146 case SPEED_100: 147 fw_speed = FW_LINK_SPEED_100M; 148 break; 149 case SPEED_10: 150 fw_speed = FW_LINK_SPEED_10M; 151 break; 152 default: 153 /* Other links speeds not supported */ 154 dev_err(priv->dev, "Unsupported link speed\n"); 155 return; 156 } 157 158 writeb(fw_speed, prueth->dram[priv->port_id].pa + PORT_LINK_SPEED_OFFSET); 159} 160 161static int icssg_update_link(struct prueth_priv *priv) 162{ 163 struct phy_device *phy = priv->phydev; 164 struct prueth *prueth = priv->prueth; 165 bool gig_en = false, full_duplex = false; 166 167 if (phy->link) { /* link up */ 168 if (phy->speed == SPEED_1000) 169 gig_en = true; 170 if (phy->duplex == DUPLEX_FULL) 171 full_duplex = true; 172 /* Set the RGMII cfg for gig en and full duplex */ 173 icssg_update_rgmii_cfg(prueth->miig_rt, phy->speed, full_duplex, 174 priv->port_id, priv); 175 /* update the Tx IPG based on 100M/1G speed */ 176 icssg_config_ipg(priv, phy->speed, priv->port_id); 177 178 /* Send command to firmware to update Speed setting */ 179 icssg_config_set_speed(priv, phy->speed); 180 181 /* Enable PORT FORWARDING */ 182 emac_set_port_state(priv, ICSSG_EMAC_PORT_FORWARD); 183 184 printf("link up on port %d, speed %d, %s duplex\n", 185 priv->port_id, phy->speed, 186 (phy->duplex == DUPLEX_FULL) ? "full" : "half"); 187 } else { 188 emac_set_port_state(priv, ICSSG_EMAC_PORT_DISABLE); 189 printf("link down on port %d\n", priv->port_id); 190 } 191 192 return phy->link; 193} 194 195struct icssg_firmwares { 196 char *pru; 197 char *rtu; 198 char *txpru; 199}; 200 201static struct icssg_firmwares icssg_emac_firmwares[] = { 202 { 203 .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru0-prueth-fw.elf", 204 .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", 205 .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", 206 }, 207 { 208 .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru1-prueth-fw.elf", 209 .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", 210 .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", 211 } 212}; 213 214static int icssg_start_pru_cores(struct udevice *dev) 215{ 216 struct prueth_priv *priv = dev_get_priv(dev); 217 struct prueth *prueth = priv->prueth; 218 struct icssg_firmwares *firmwares; 219 struct udevice *rproc_dev = NULL; 220 int ret, slice; 221 u32 phandle; 222 u8 index; 223 224 slice = priv->port_id; 225 index = slice * ICSSG_NUM_PRU_CORES; 226 firmwares = icssg_emac_firmwares; 227 228 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index, &phandle); 229 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); 230 if (ret) { 231 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", 232 phandle, ret); 233 return ret; 234 } 235 236 prueth->pru_core_id = dev_seq(rproc_dev); 237 ret = rproc_set_firmware(rproc_dev, firmwares[slice].pru); 238 if (ret) 239 return ret; 240 241 ret = rproc_boot(rproc_dev); 242 if (ret) { 243 dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret); 244 return -EINVAL; 245 } 246 247 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 1, &phandle); 248 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); 249 if (ret) { 250 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", 251 phandle, ret); 252 goto halt_pru; 253 } 254 255 prueth->rtu_core_id = dev_seq(rproc_dev); 256 ret = rproc_set_firmware(rproc_dev, firmwares[slice].rtu); 257 if (ret) 258 goto halt_pru; 259 260 ret = rproc_boot(rproc_dev); 261 if (ret) { 262 dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret); 263 goto halt_pru; 264 } 265 266 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 2, &phandle); 267 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); 268 if (ret) { 269 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", 270 phandle, ret); 271 goto halt_rtu; 272 } 273 274 prueth->txpru_core_id = dev_seq(rproc_dev); 275 ret = rproc_set_firmware(rproc_dev, firmwares[slice].txpru); 276 if (ret) 277 goto halt_rtu; 278 279 ret = rproc_boot(rproc_dev); 280 if (ret) { 281 dev_err(dev, "failed to boot TXPRU%d: %d\n", slice, ret); 282 goto halt_rtu; 283 } 284 285 return 0; 286 287halt_rtu: 288 rproc_stop(prueth->rtu_core_id); 289 290halt_pru: 291 rproc_stop(prueth->pru_core_id); 292 return ret; 293} 294 295static int icssg_stop_pru_cores(struct udevice *dev) 296{ 297 struct prueth_priv *priv = dev_get_priv(dev); 298 struct prueth *prueth = priv->prueth; 299 300 rproc_stop(prueth->pru_core_id); 301 rproc_stop(prueth->rtu_core_id); 302 rproc_stop(prueth->txpru_core_id); 303 304 return 0; 305} 306 307static int prueth_start(struct udevice *dev) 308{ 309 struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data; 310 struct eth_pdata *pdata = dev_get_plat(dev); 311 struct prueth_priv *priv = dev_get_priv(dev); 312 struct prueth *prueth = priv->prueth; 313 struct icssg_flow_cfg *flow_cfg; 314 u8 *hwaddr = pdata->enetaddr; 315 char chn_name[16]; 316 void *config; 317 int ret, i; 318 319 icssg_class_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr); 320 icssg_ft1_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr); 321 icssg_class_default(prueth->miig_rt, priv->port_id, 0); 322 323 /* Set Load time configuration */ 324 icssg_config(priv); 325 326 ret = icssg_start_pru_cores(dev); 327 if (ret) 328 return ret; 329 330 /* To differentiate channels for SLICE0 vs SLICE1 */ 331 snprintf(chn_name, sizeof(chn_name), "tx%d-0", priv->port_id); 332 333 ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_tx); 334 if (ret) 335 dev_err(dev, "TX dma get failed %d\n", ret); 336 337 snprintf(chn_name, sizeof(chn_name), "rx%d", priv->port_id); 338 ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_rx); 339 if (ret) 340 dev_err(dev, "RX dma get failed %d\n", ret); 341 342 for (i = 0; i < UDMA_RX_DESC_NUM; i++) { 343 ret = dma_prepare_rcv_buf(&prueth->dma_rx, 344 net_rx_packets[i], 345 UDMA_RX_BUF_SIZE); 346 if (ret) 347 dev_err(dev, "RX dma add buf failed %d\n", ret); 348 } 349 350 ret = dma_enable(&prueth->dma_tx); 351 if (ret) { 352 dev_err(dev, "TX dma_enable failed %d\n", ret); 353 goto tx_fail; 354 } 355 356 ret = dma_enable(&prueth->dma_rx); 357 if (ret) { 358 dev_err(dev, "RX dma_enable failed %d\n", ret); 359 goto rx_fail; 360 } 361 362 /* check if the rx_flow_id of dma_rx is as expected since 363 * driver hardcode that value in config struct to firmware 364 * in probe. Just add this sanity check to catch any change 365 * to rx channel assignment in the future. 366 */ 367 dma_get_cfg(&prueth->dma_rx, 0, (void **)&dma_rx_cfg_data); 368 config = (void *)(prueth->dram[priv->port_id].pa + ICSSG_CONFIG_OFFSET); 369 370 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; 371 writew(dma_rx_cfg_data->flow_id_base, &flow_cfg->rx_base_flow); 372 writew(0, &flow_cfg->mgm_base_flow); 373 374 dev_info(dev, "K3 ICSSG: rflow_id_base: %u, chn_name = %s\n", 375 dma_rx_cfg_data->flow_id_base, chn_name); 376 377 ret = emac_fdb_flow_id_updated(priv); 378 if (ret) { 379 dev_err(dev, "Failed to update Rx Flow ID %d", ret); 380 goto phy_fail; 381 } 382 383 ret = phy_startup(priv->phydev); 384 if (ret) { 385 dev_err(dev, "phy_startup failed\n"); 386 goto phy_fail; 387 } 388 389 ret = icssg_update_link(priv); 390 if (!ret) { 391 ret = -ENODEV; 392 goto phy_shut; 393 } 394 395 return 0; 396 397phy_shut: 398 phy_shutdown(priv->phydev); 399phy_fail: 400 dma_disable(&prueth->dma_rx); 401 dma_free(&prueth->dma_rx); 402rx_fail: 403 dma_disable(&prueth->dma_tx); 404 dma_free(&prueth->dma_tx); 405 406tx_fail: 407 icssg_class_disable(prueth->miig_rt, priv->port_id); 408 409 return ret; 410} 411 412static int prueth_send(struct udevice *dev, void *packet, int length) 413{ 414 struct prueth_priv *priv = dev_get_priv(dev); 415 struct prueth *prueth = priv->prueth; 416 int ret; 417 418 ret = dma_send(&prueth->dma_tx, packet, length, NULL); 419 420 return ret; 421} 422 423static int prueth_recv(struct udevice *dev, int flags, uchar **packetp) 424{ 425 struct prueth_priv *priv = dev_get_priv(dev); 426 struct prueth *prueth = priv->prueth; 427 int ret; 428 429 /* try to receive a new packet */ 430 ret = dma_receive(&prueth->dma_rx, (void **)packetp, NULL); 431 432 return ret; 433} 434 435static int prueth_free_pkt(struct udevice *dev, uchar *packet, int length) 436{ 437 struct prueth_priv *priv = dev_get_priv(dev); 438 struct prueth *prueth = priv->prueth; 439 int ret = 0; 440 441 if (length > 0) { 442 u32 pkt = prueth->rx_next % UDMA_RX_DESC_NUM; 443 444 dev_dbg(dev, "%s length:%d pkt:%u\n", __func__, length, pkt); 445 446 ret = dma_prepare_rcv_buf(&prueth->dma_rx, 447 net_rx_packets[pkt], 448 UDMA_RX_BUF_SIZE); 449 prueth->rx_next++; 450 } 451 452 return ret; 453} 454 455static void prueth_stop(struct udevice *dev) 456{ 457 struct prueth_priv *priv = dev_get_priv(dev); 458 struct prueth *prueth = priv->prueth; 459 460 phy_shutdown(priv->phydev); 461 462 dma_disable(&prueth->dma_tx); 463 dma_disable(&prueth->dma_rx); 464 465 icssg_stop_pru_cores(dev); 466 467 dma_free(&prueth->dma_tx); 468 dma_free(&prueth->dma_rx); 469} 470 471static const struct eth_ops prueth_ops = { 472 .start = prueth_start, 473 .send = prueth_send, 474 .recv = prueth_recv, 475 .free_pkt = prueth_free_pkt, 476 .stop = prueth_stop, 477}; 478 479static int icssg_ofdata_parse_phy(struct udevice *dev) 480{ 481 struct prueth_priv *priv = dev_get_priv(dev); 482 483 dev_read_u32(dev, "reg", &priv->port_id); 484 priv->phy_interface = dev_read_phy_mode(dev); 485 if (priv->phy_interface == PHY_INTERFACE_MODE_NA) { 486 dev_err(dev, "Invalid PHY mode '%s', port %u\n", 487 phy_string_for_interface(priv->phy_interface), 488 priv->port_id); 489 return -EINVAL; 490 } 491 492 return 0; 493} 494 495static int prueth_port_probe(struct udevice *dev) 496{ 497 struct prueth_priv *priv = dev_get_priv(dev); 498 struct prueth *prueth; 499 char portname[15]; 500 int ret; 501 502 priv->dev = dev; 503 prueth = dev_get_priv(dev->parent); 504 priv->prueth = prueth; 505 506 sprintf(portname, "%s-%s", dev->parent->name, dev->name); 507 508 device_set_name(dev, portname); 509 510 ret = icssg_ofdata_parse_phy(dev); 511 if (ret) 512 goto out; 513 514 ret = icssg_phy_init(dev); 515 if (ret) 516 goto out; 517 518 ret = pruss_request_mem_region(prueth->pruss, 519 priv->port_id ? PRUSS_MEM_DRAM1 : PRUSS_MEM_DRAM0, 520 &prueth->dram[priv->port_id]); 521 if (ret) { 522 dev_err(dev, "could not request DRAM%d region\n", priv->port_id); 523 return ret; 524 } 525out: 526 return ret; 527} 528 529static int prueth_probe(struct udevice *dev) 530{ 531 ofnode node, pruss_node, mdio_node, sram_node, curr_sram_node; 532 struct prueth *prueth = dev_get_priv(dev); 533 u32 phandle, err, sp, prev_end_addr; 534 struct udevice **prussdev = NULL; 535 ofnode eth_ports_node, eth_node; 536 struct udevice *port_dev; 537 int ret = 0; 538 539 prueth->dev = dev; 540 541 err = ofnode_read_u32(dev_ofnode(dev), "ti,prus", &phandle); 542 if (err) 543 return err; 544 545 node = ofnode_get_by_phandle(phandle); 546 if (!ofnode_valid(node)) 547 return -EINVAL; 548 549 pruss_node = ofnode_get_parent(node); 550 ret = device_get_global_by_ofnode(pruss_node, prussdev); 551 if (ret) 552 dev_err(dev, "error getting the pruss dev\n"); 553 prueth->pruss = *prussdev; 554 555 ret = pruss_request_mem_region(*prussdev, PRUSS_MEM_SHRD_RAM2, 556 &prueth->shram); 557 if (ret) 558 return ret; 559 560 ret = pruss_request_tm_region(*prussdev, &prueth->tmaddr); 561 if (ret) 562 return ret; 563 564 prueth->miig_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-g-rt"); 565 if (!prueth->miig_rt) { 566 dev_err(dev, "couldn't get mii-g-rt syscon regmap\n"); 567 return -ENODEV; 568 } 569 570 prueth->mii_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-rt"); 571 if (!prueth->mii_rt) { 572 dev_err(dev, "couldn't get mii-rt syscon regmap\n"); 573 return -ENODEV; 574 } 575 576 ret = ofnode_read_u32(dev_ofnode(dev), "sram", &sp); 577 if (ret) { 578 dev_err(dev, "sram node fetch failed %d\n", ret); 579 return ret; 580 } 581 582 sram_node = ofnode_get_by_phandle(sp); 583 if (!ofnode_valid(sram_node)) 584 return -EINVAL; 585 586 prev_end_addr = ofnode_get_addr(sram_node); 587 588 ofnode_for_each_subnode(curr_sram_node, sram_node) { 589 u32 start_addr, size, end_addr, avail; 590 const char *name; 591 592 name = ofnode_get_name(curr_sram_node); 593 start_addr = ofnode_get_addr(curr_sram_node); 594 size = ofnode_get_size(curr_sram_node); 595 end_addr = start_addr + size; 596 avail = start_addr - prev_end_addr; 597 598 if (avail > MSMC_RAM_SIZE) 599 break; 600 601 prev_end_addr = end_addr; 602 } 603 604 prueth->sram_pa = prev_end_addr; 605 if (prueth->sram_pa % SZ_64K != 0) { 606 /* This is constraint for SR2.0 firmware */ 607 dev_err(dev, "sram address needs to be 64KB aligned\n"); 608 return -EINVAL; 609 } 610 dev_dbg(dev, "sram: addr %x size %x\n", prueth->sram_pa, MSMC_RAM_SIZE); 611 612 mdio_node = ofnode_find_subnode(pruss_node, "mdio"); 613 prueth->mdio_base = ofnode_get_addr(mdio_node); 614 ofnode_read_u32(mdio_node, "bus_freq", &prueth->mdio_freq); 615 616 ret = clk_get_by_name_nodev(mdio_node, "fck", &prueth->mdiofck); 617 if (ret) { 618 dev_err(dev, "failed to get clock %d\n", ret); 619 return ret; 620 } 621 622 ret = clk_enable(&prueth->mdiofck); 623 if (ret) { 624 dev_err(dev, "clk_enable failed %d\n", ret); 625 return ret; 626 } 627 628 eth_ports_node = dev_read_subnode(dev, "ethernet-ports"); 629 if (!ofnode_valid(eth_ports_node)) 630 return -ENOENT; 631 632 ofnode_for_each_subnode(eth_node, eth_ports_node) { 633 const char *node_name; 634 u32 port_id; 635 bool disabled; 636 637 node_name = ofnode_get_name(eth_node); 638 disabled = !ofnode_is_enabled(eth_node); 639 ret = ofnode_read_u32(eth_node, "reg", &port_id); 640 if (ret) 641 dev_err(dev, "%s: error reading port_id (%d)\n", node_name, ret); 642 643 if (port_id >= PRUETH_NUM_MACS) { 644 dev_err(dev, "%s: invalid port_id (%d)\n", node_name, port_id); 645 return -EINVAL; 646 } 647 648 if (port_id < 0) 649 continue; 650 if (disabled) 651 continue; 652 653 ret = device_bind_driver_to_node(dev, "prueth_port", 654 ofnode_get_name(eth_node), 655 eth_node, &port_dev); 656 if (ret) { 657 dev_err(dev, "Failed to bind to %s node\n", ofnode_get_name(eth_node)); 658 goto out; 659 } 660 } 661 662 return 0; 663out: 664 clk_disable(&prueth->mdiofck); 665 666 return ret; 667} 668 669static const struct udevice_id prueth_ids[] = { 670 { .compatible = "ti,am654-icssg-prueth" }, 671 { .compatible = "ti,am642-icssg-prueth" }, 672 { } 673}; 674 675U_BOOT_DRIVER(prueth) = { 676 .name = "prueth", 677 .id = UCLASS_MISC, 678 .of_match = prueth_ids, 679 .probe = prueth_probe, 680 .priv_auto = sizeof(struct prueth), 681}; 682 683U_BOOT_DRIVER(prueth_port) = { 684 .name = "prueth_port", 685 .id = UCLASS_ETH, 686 .probe = prueth_port_probe, 687 .ops = &prueth_ops, 688 .priv_auto = sizeof(struct prueth_priv), 689 .plat_auto = sizeof(struct eth_pdata), 690 .flags = DM_FLAG_ALLOC_PRIV_DMA, 691}; 692