1 /* 2 * Copyright (C) 2014 Freescale Semiconductor 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <asm/types.h> 10 #include <malloc.h> 11 #include <net.h> 12 #include <hwconfig.h> 13 #include <phy.h> 14 #include <linux/compat.h> 15 16 #include "ldpaa_eth.h" 17 18 #undef CONFIG_PHYLIB 19 static int init_phy(struct eth_device *dev) 20 { 21 /*TODO for external PHY */ 22 23 return 0; 24 } 25 26 static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, 27 const struct dpaa_fd *fd) 28 { 29 u64 fd_addr; 30 uint16_t fd_offset; 31 uint32_t fd_length; 32 struct ldpaa_fas *fas; 33 uint32_t status, err; 34 struct qbman_release_desc releasedesc; 35 struct qbman_swp *swp = dflt_dpio->sw_portal; 36 37 fd_addr = ldpaa_fd_get_addr(fd); 38 fd_offset = ldpaa_fd_get_offset(fd); 39 fd_length = ldpaa_fd_get_len(fd); 40 41 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length); 42 43 if (fd->simple.frc & LDPAA_FD_FRC_FASV) { 44 /* Read the frame annotation status word and check for errors */ 45 fas = (struct ldpaa_fas *) 46 ((uint8_t *)(fd_addr) + 47 priv->buf_layout.private_data_size); 48 status = le32_to_cpu(fas->status); 49 if (status & LDPAA_ETH_RX_ERR_MASK) { 50 printf("Rx frame error(s): 0x%08x\n", 51 status & LDPAA_ETH_RX_ERR_MASK); 52 goto error; 53 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) { 54 printf("Unsupported feature in bitmask: 0x%08x\n", 55 status & LDPAA_ETH_RX_UNSUPP_MASK); 56 goto error; 57 } 58 } 59 60 debug("Rx frame: To Upper layer\n"); 61 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset, 62 fd_length); 63 64 error: 65 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); 66 qbman_release_desc_clear(&releasedesc); 67 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 68 do { 69 /* Release buffer into the QBMAN */ 70 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); 71 } while (err == -EBUSY); 72 return; 73 } 74 75 static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) 76 { 77 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; 78 const struct ldpaa_dq *dq; 79 const struct dpaa_fd *fd; 80 int i = 5, err = 0, status, loop = 20; 81 static struct qbman_pull_desc pulldesc; 82 struct qbman_swp *swp = dflt_dpio->sw_portal; 83 84 while (--i) { 85 qbman_pull_desc_clear(&pulldesc); 86 qbman_pull_desc_set_numframes(&pulldesc, 1); 87 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid); 88 89 err = qbman_swp_pull(swp, &pulldesc); 90 if (err < 0) { 91 printf("Dequeue frames error:0x%08x\n", err); 92 continue; 93 } 94 95 do { 96 loop--; 97 dq = qbman_swp_dqrr_next(swp); 98 99 if (!loop) 100 break; 101 } while (!dq); 102 103 if (dq) { 104 /* Check for valid frame. If not sent a consume 105 * confirmation to QBMAN otherwise give it to NADK 106 * application and then send consume confirmation to 107 * QBMAN. 108 */ 109 status = (uint8_t)ldpaa_dq_flags(dq); 110 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { 111 debug("Dequeue RX frames:"); 112 debug("No frame delivered\n"); 113 114 qbman_swp_dqrr_consume(swp, dq); 115 break; 116 } 117 118 fd = ldpaa_dq_fd(dq); 119 120 /* Obtain FD and process it */ 121 ldpaa_eth_rx(priv, fd); 122 qbman_swp_dqrr_consume(swp, dq); 123 break; 124 } 125 } 126 127 return err; 128 } 129 130 static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv, 131 const struct dpaa_fd *fd) 132 { 133 uint64_t fd_addr; 134 struct ldpaa_fas *fas; 135 uint32_t status, err; 136 struct qbman_release_desc releasedesc; 137 struct qbman_swp *swp = dflt_dpio->sw_portal; 138 139 fd_addr = ldpaa_fd_get_addr(fd); 140 141 142 debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr); 143 144 /* Check the status from the Frame Annotation */ 145 if (fd->simple.frc & LDPAA_FD_FRC_FASV) { 146 fas = (struct ldpaa_fas *) 147 ((uint8_t *)(fd_addr) + 148 priv->buf_layout.private_data_size); 149 status = le32_to_cpu(fas->status); 150 if (status & LDPAA_ETH_TXCONF_ERR_MASK) { 151 printf("TxConf frame error(s): 0x%08x\n", 152 status & LDPAA_ETH_TXCONF_ERR_MASK); 153 } 154 } 155 156 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); 157 qbman_release_desc_clear(&releasedesc); 158 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 159 do { 160 /* Release buffer into the QBMAN */ 161 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); 162 } while (err == -EBUSY); 163 } 164 165 static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) 166 { 167 const struct ldpaa_dq *dq; 168 const struct dpaa_fd *fd; 169 int err = 0; 170 int i = 5, status, loop = 20; 171 static struct qbman_pull_desc pulldesc; 172 struct qbman_swp *swp = dflt_dpio->sw_portal; 173 174 while (--i) { 175 qbman_pull_desc_clear(&pulldesc); 176 qbman_pull_desc_set_numframes(&pulldesc, 1); 177 qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid); 178 179 err = qbman_swp_pull(swp, &pulldesc); 180 if (err < 0) { 181 printf("Dequeue TX conf frames error:0x%08x\n", err); 182 continue; 183 } 184 185 do { 186 loop--; 187 dq = qbman_swp_dqrr_next(swp); 188 189 if (!loop) 190 break; 191 } while (!dq); 192 193 if (dq) { 194 /* Check for valid frame. If not sent a consume 195 * confirmation to QBMAN otherwise give it to NADK 196 * application and then send consume confirmation to 197 * QBMAN. 198 */ 199 status = (uint8_t)ldpaa_dq_flags(dq); 200 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { 201 debug("Dequeue TX conf frames:"); 202 debug("No frame is delivered\n"); 203 204 qbman_swp_dqrr_consume(swp, dq); 205 break; 206 } 207 fd = ldpaa_dq_fd(dq); 208 209 ldpaa_eth_tx_conf(priv, fd); 210 qbman_swp_dqrr_consume(swp, dq); 211 break; 212 } 213 } 214 215 return err; 216 } 217 218 static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) 219 { 220 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 221 struct dpaa_fd fd; 222 u64 buffer_start; 223 int data_offset, err; 224 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; 225 u32 time_start; 226 struct qbman_swp *swp = dflt_dpio->sw_portal; 227 struct qbman_eq_desc ed; 228 struct qbman_release_desc releasedesc; 229 230 /* Setup the FD fields */ 231 memset(&fd, 0, sizeof(fd)); 232 233 data_offset = priv->tx_data_offset; 234 235 do { 236 err = qbman_swp_acquire(dflt_dpio->sw_portal, 237 dflt_dpbp->dpbp_attr.bpid, 238 &buffer_start, 1); 239 } while (err == -EBUSY); 240 241 if (err < 0) { 242 printf("qbman_swp_acquire() failed\n"); 243 return -ENOMEM; 244 } 245 246 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start); 247 248 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len); 249 250 flush_dcache_range(buffer_start, buffer_start + 251 LDPAA_ETH_RX_BUFFER_SIZE); 252 253 ldpaa_fd_set_addr(&fd, (u64)buffer_start); 254 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset)); 255 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid); 256 ldpaa_fd_set_len(&fd, len); 257 258 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA | 259 LDPAA_FD_CTRL_PTV1; 260 261 qbman_eq_desc_clear(&ed); 262 qbman_eq_desc_set_no_orp(&ed, 0); 263 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); 264 265 time_start = get_timer(0); 266 267 while (get_timer(time_start) < timeo) { 268 err = qbman_swp_enqueue(swp, &ed, 269 (const struct qbman_fd *)(&fd)); 270 if (err != -EBUSY) 271 break; 272 } 273 274 if (err < 0) { 275 printf("error enqueueing Tx frame\n"); 276 goto error; 277 } 278 279 mdelay(1); 280 281 err = ldpaa_eth_pull_dequeue_tx_conf(priv); 282 if (err < 0) 283 printf("error Tx Conf frame\n"); 284 285 return err; 286 287 error: 288 qbman_release_desc_clear(&releasedesc); 289 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 290 time_start = get_timer(0); 291 do { 292 /* Release buffer into the QBMAN */ 293 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1); 294 } while (get_timer(time_start) < timeo && err == -EBUSY); 295 296 if (err == -EBUSY) 297 printf("TX data: QBMAN buffer release fails\n"); 298 299 return err; 300 } 301 302 static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) 303 { 304 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 305 struct dpni_queue_attr rx_queue_attr; 306 struct dpni_tx_flow_attr tx_flow_attr; 307 uint8_t mac_addr[6]; 308 int err; 309 310 if (net_dev->state == ETH_STATE_ACTIVE) 311 return 0; 312 313 /* DPNI initialization */ 314 err = ldpaa_dpni_setup(priv); 315 if (err < 0) 316 goto err_dpni_setup; 317 318 err = ldpaa_dpbp_setup(); 319 if (err < 0) 320 goto err_dpbp_setup; 321 322 /* DPNI binding DPBP */ 323 err = ldpaa_dpni_bind(priv); 324 if (err) 325 goto err_bind; 326 327 err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle, 328 mac_addr); 329 if (err) { 330 printf("dpni_get_primary_mac_addr() failed\n"); 331 return err; 332 } 333 334 memcpy(net_dev->enetaddr, mac_addr, 0x6); 335 336 /* setup the MAC address */ 337 if (net_dev->enetaddr[0] & 0x01) { 338 printf("%s: MacAddress is multcast address\n", __func__); 339 return 1; 340 } 341 342 #ifdef CONFIG_PHYLIB 343 /* TODO Check this path */ 344 err = phy_startup(priv->phydev); 345 if (err) { 346 printf("%s: Could not initialize\n", priv->phydev->dev->name); 347 return err; 348 } 349 #else 350 priv->phydev->speed = SPEED_1000; 351 priv->phydev->link = 1; 352 priv->phydev->duplex = DUPLEX_FULL; 353 #endif 354 355 err = dpni_enable(dflt_mc_io, priv->dpni_handle); 356 if (err < 0) { 357 printf("dpni_enable() failed\n"); 358 return err; 359 } 360 361 /* TODO: support multiple Rx flows */ 362 err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0, 363 &rx_queue_attr); 364 if (err) { 365 printf("dpni_get_rx_flow() failed\n"); 366 goto err_rx_flow; 367 } 368 369 priv->rx_dflt_fqid = rx_queue_attr.fqid; 370 371 err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid); 372 if (err) { 373 printf("dpni_get_qdid() failed\n"); 374 goto err_qdid; 375 } 376 377 err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id, 378 &tx_flow_attr); 379 if (err) { 380 printf("dpni_get_tx_flow() failed\n"); 381 goto err_tx_flow; 382 } 383 384 priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid; 385 386 if (!priv->phydev->link) 387 printf("%s: No link.\n", priv->phydev->dev->name); 388 389 return priv->phydev->link ? 0 : -1; 390 391 err_tx_flow: 392 err_qdid: 393 err_rx_flow: 394 dpni_disable(dflt_mc_io, priv->dpni_handle); 395 err_bind: 396 ldpaa_dpbp_free(); 397 err_dpbp_setup: 398 dpni_close(dflt_mc_io, priv->dpni_handle); 399 err_dpni_setup: 400 return err; 401 } 402 403 static void ldpaa_eth_stop(struct eth_device *net_dev) 404 { 405 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 406 int err = 0; 407 408 if ((net_dev->state == ETH_STATE_PASSIVE) || 409 (net_dev->state == ETH_STATE_INIT)) 410 return; 411 /* Stop Tx and Rx traffic */ 412 err = dpni_disable(dflt_mc_io, priv->dpni_handle); 413 if (err < 0) 414 printf("dpni_disable() failed\n"); 415 416 #ifdef CONFIG_PHYLIB 417 phy_shutdown(priv->phydev); 418 #endif 419 420 ldpaa_dpbp_free(); 421 dpni_reset(dflt_mc_io, priv->dpni_handle); 422 dpni_close(dflt_mc_io, priv->dpni_handle); 423 } 424 425 static void ldpaa_dpbp_drain_cnt(int count) 426 { 427 uint64_t buf_array[7]; 428 void *addr; 429 int ret, i; 430 431 BUG_ON(count > 7); 432 433 do { 434 ret = qbman_swp_acquire(dflt_dpio->sw_portal, 435 dflt_dpbp->dpbp_attr.bpid, 436 buf_array, count); 437 if (ret < 0) { 438 printf("qbman_swp_acquire() failed\n"); 439 return; 440 } 441 for (i = 0; i < ret; i++) { 442 addr = (void *)buf_array[i]; 443 debug("Free: buffer addr =0x%p\n", addr); 444 free(addr); 445 } 446 } while (ret); 447 } 448 449 static void ldpaa_dpbp_drain(void) 450 { 451 int i; 452 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) 453 ldpaa_dpbp_drain_cnt(7); 454 } 455 456 static int ldpaa_bp_add_7(uint16_t bpid) 457 { 458 uint64_t buf_array[7]; 459 u8 *addr; 460 int i; 461 struct qbman_release_desc rd; 462 463 for (i = 0; i < 7; i++) { 464 addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE); 465 if (!addr) { 466 printf("addr allocation failed\n"); 467 goto err_alloc; 468 } 469 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE); 470 flush_dcache_range((u64)addr, 471 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE)); 472 473 buf_array[i] = (uint64_t)addr; 474 debug("Release: buffer addr =0x%p\n", addr); 475 } 476 477 release_bufs: 478 /* In case the portal is busy, retry until successful. 479 * This function is guaranteed to succeed in a reasonable amount 480 * of time. 481 */ 482 483 do { 484 mdelay(1); 485 qbman_release_desc_clear(&rd); 486 qbman_release_desc_set_bpid(&rd, bpid); 487 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i)); 488 489 return i; 490 491 err_alloc: 492 if (i) 493 goto release_bufs; 494 495 return 0; 496 } 497 498 static int ldpaa_dpbp_seed(uint16_t bpid) 499 { 500 int i; 501 int count; 502 503 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) { 504 count = ldpaa_bp_add_7(bpid); 505 if (count < 7) 506 printf("Buffer Seed= %d\n", count); 507 } 508 509 return 0; 510 } 511 512 static int ldpaa_dpbp_setup(void) 513 { 514 int err; 515 516 err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id, 517 &dflt_dpbp->dpbp_handle); 518 if (err) { 519 printf("dpbp_open() failed\n"); 520 goto err_open; 521 } 522 523 err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle); 524 if (err) { 525 printf("dpbp_enable() failed\n"); 526 goto err_enable; 527 } 528 529 err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle, 530 &dflt_dpbp->dpbp_attr); 531 if (err) { 532 printf("dpbp_get_attributes() failed\n"); 533 goto err_get_attr; 534 } 535 536 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); 537 if (err) { 538 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", 539 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); 540 goto err_seed; 541 } 542 543 return 0; 544 545 err_seed: 546 err_get_attr: 547 dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle); 548 err_enable: 549 dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle); 550 err_open: 551 return err; 552 } 553 554 static void ldpaa_dpbp_free(void) 555 { 556 ldpaa_dpbp_drain(); 557 dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle); 558 dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle); 559 dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle); 560 } 561 562 static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) 563 { 564 int err; 565 566 /* and get a handle for the DPNI this interface is associate with */ 567 err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle); 568 if (err) { 569 printf("dpni_open() failed\n"); 570 goto err_open; 571 } 572 573 err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle, 574 &priv->dpni_attrs); 575 if (err) { 576 printf("dpni_get_attributes() failed (err=%d)\n", err); 577 goto err_get_attr; 578 } 579 580 /* Configure our buffers' layout */ 581 priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | 582 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | 583 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; 584 priv->buf_layout.pass_parser_result = true; 585 priv->buf_layout.pass_frame_status = true; 586 priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; 587 /* ...rx, ... */ 588 err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle, 589 &priv->buf_layout); 590 if (err) { 591 printf("dpni_set_rx_buffer_layout() failed"); 592 goto err_buf_layout; 593 } 594 595 /* ... tx, ... */ 596 priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT; 597 err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle, 598 &priv->buf_layout); 599 if (err) { 600 printf("dpni_set_tx_buffer_layout() failed"); 601 goto err_buf_layout; 602 } 603 604 /* ... tx-confirm. */ 605 priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; 606 err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle, 607 &priv->buf_layout); 608 if (err) { 609 printf("dpni_set_tx_conf_buffer_layout() failed"); 610 goto err_buf_layout; 611 } 612 613 /* Now that we've set our tx buffer layout, retrieve the minimum 614 * required tx data offset. 615 */ 616 err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle, 617 &priv->tx_data_offset); 618 if (err) { 619 printf("dpni_get_tx_data_offset() failed\n"); 620 goto err_data_offset; 621 } 622 623 /* Warn in case TX data offset is not multiple of 64 bytes. */ 624 WARN_ON(priv->tx_data_offset % 64); 625 626 /* Accomodate SWA space. */ 627 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE; 628 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset); 629 630 return 0; 631 632 err_data_offset: 633 err_buf_layout: 634 err_get_attr: 635 dpni_close(dflt_mc_io, priv->dpni_handle); 636 err_open: 637 return err; 638 } 639 640 static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) 641 { 642 struct dpni_pools_cfg pools_params; 643 struct dpni_tx_flow_cfg dflt_tx_flow; 644 int err = 0; 645 646 pools_params.num_dpbp = 1; 647 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id; 648 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE; 649 err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params); 650 if (err) { 651 printf("dpni_set_pools() failed\n"); 652 return err; 653 } 654 655 priv->tx_flow_id = DPNI_NEW_FLOW_ID; 656 memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); 657 658 err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle, 659 &priv->tx_flow_id, &dflt_tx_flow); 660 if (err) { 661 printf("dpni_set_tx_flow() failed\n"); 662 return err; 663 } 664 665 return 0; 666 } 667 668 static int ldpaa_eth_netdev_init(struct eth_device *net_dev) 669 { 670 int err; 671 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 672 673 sprintf(net_dev->name, "DPNI%d", priv->dpni_id); 674 675 net_dev->iobase = 0; 676 net_dev->init = ldpaa_eth_open; 677 net_dev->halt = ldpaa_eth_stop; 678 net_dev->send = ldpaa_eth_tx; 679 net_dev->recv = ldpaa_eth_pull_dequeue_rx; 680 /* 681 TODO: PHY MDIO information 682 priv->bus = info->bus; 683 priv->phyaddr = info->phy_addr; 684 priv->enet_if = info->enet_if; 685 */ 686 687 if (init_phy(net_dev)) 688 return 0; 689 690 err = eth_register(net_dev); 691 if (err < 0) { 692 printf("eth_register() = %d\n", err); 693 return err; 694 } 695 696 return 0; 697 } 698 699 int ldpaa_eth_init(struct dprc_obj_desc obj_desc) 700 { 701 struct eth_device *net_dev = NULL; 702 struct ldpaa_eth_priv *priv = NULL; 703 int err = 0; 704 705 706 /* Net device */ 707 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 708 if (!net_dev) { 709 printf("eth_device malloc() failed\n"); 710 return -ENOMEM; 711 } 712 memset(net_dev, 0, sizeof(struct eth_device)); 713 714 /* alloc the ldpaa ethernet private struct */ 715 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv)); 716 if (!priv) { 717 printf("ldpaa_eth_priv malloc() failed\n"); 718 return -ENOMEM; 719 } 720 memset(priv, 0, sizeof(struct ldpaa_eth_priv)); 721 722 net_dev->priv = (void *)priv; 723 priv->net_dev = (struct eth_device *)net_dev; 724 priv->dpni_id = obj_desc.id; 725 726 err = ldpaa_eth_netdev_init(net_dev); 727 if (err) 728 goto err_netdev_init; 729 730 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name); 731 return 0; 732 733 err_netdev_init: 734 free(priv); 735 net_dev->priv = NULL; 736 free(net_dev); 737 738 return err; 739 } 740