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 #include <fsl-mc/fsl_dpmac.h> 16 17 #include "ldpaa_eth.h" 18 19 #undef CONFIG_PHYLIB 20 static int init_phy(struct eth_device *dev) 21 { 22 /*TODO for external PHY */ 23 24 return 0; 25 } 26 27 #ifdef DEBUG 28 static void ldpaa_eth_get_dpni_counter(void) 29 { 30 int err = 0; 31 u64 value; 32 33 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 34 dflt_dpni->dpni_handle, 35 DPNI_CNT_ING_FRAME, 36 &value); 37 if (err < 0) { 38 printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n"); 39 return; 40 } 41 printf("DPNI_CNT_ING_FRAME=%lld\n", value); 42 43 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 44 dflt_dpni->dpni_handle, 45 DPNI_CNT_ING_BYTE, 46 &value); 47 if (err < 0) { 48 printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n"); 49 return; 50 } 51 printf("DPNI_CNT_ING_BYTE=%lld\n", value); 52 53 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 54 dflt_dpni->dpni_handle, 55 DPNI_CNT_ING_FRAME_DROP , 56 &value); 57 if (err < 0) { 58 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n"); 59 return; 60 } 61 printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value); 62 63 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 64 dflt_dpni->dpni_handle, 65 DPNI_CNT_ING_FRAME_DISCARD, 66 &value); 67 if (err < 0) { 68 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n"); 69 return; 70 } 71 printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value); 72 73 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 74 dflt_dpni->dpni_handle, 75 DPNI_CNT_EGR_FRAME, 76 &value); 77 if (err < 0) { 78 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n"); 79 return; 80 } 81 printf("DPNI_CNT_EGR_FRAME=%lld\n", value); 82 83 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 84 dflt_dpni->dpni_handle, 85 DPNI_CNT_EGR_BYTE , 86 &value); 87 if (err < 0) { 88 printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n"); 89 return; 90 } 91 printf("DPNI_CNT_EGR_BYTE =%lld\n", value); 92 93 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 94 dflt_dpni->dpni_handle, 95 DPNI_CNT_EGR_FRAME_DISCARD , 96 &value); 97 if (err < 0) { 98 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n"); 99 return; 100 } 101 printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value); 102 } 103 #endif 104 105 static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, 106 const struct dpaa_fd *fd) 107 { 108 u64 fd_addr; 109 uint16_t fd_offset; 110 uint32_t fd_length; 111 struct ldpaa_fas *fas; 112 uint32_t status, err; 113 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; 114 u32 time_start; 115 struct qbman_release_desc releasedesc; 116 struct qbman_swp *swp = dflt_dpio->sw_portal; 117 118 fd_addr = ldpaa_fd_get_addr(fd); 119 fd_offset = ldpaa_fd_get_offset(fd); 120 fd_length = ldpaa_fd_get_len(fd); 121 122 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length); 123 124 if (fd->simple.frc & LDPAA_FD_FRC_FASV) { 125 /* Read the frame annotation status word and check for errors */ 126 fas = (struct ldpaa_fas *) 127 ((uint8_t *)(fd_addr) + 128 dflt_dpni->buf_layout.private_data_size); 129 status = le32_to_cpu(fas->status); 130 if (status & LDPAA_ETH_RX_ERR_MASK) { 131 printf("Rx frame error(s): 0x%08x\n", 132 status & LDPAA_ETH_RX_ERR_MASK); 133 goto error; 134 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) { 135 printf("Unsupported feature in bitmask: 0x%08x\n", 136 status & LDPAA_ETH_RX_UNSUPP_MASK); 137 goto error; 138 } 139 } 140 141 debug("Rx frame: To Upper layer\n"); 142 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset, 143 fd_length); 144 145 error: 146 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); 147 qbman_release_desc_clear(&releasedesc); 148 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 149 time_start = get_timer(0); 150 do { 151 /* Release buffer into the QBMAN */ 152 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); 153 } while (get_timer(time_start) < timeo && err == -EBUSY); 154 155 if (err == -EBUSY) 156 printf("Rx frame: QBMAN buffer release fails\n"); 157 158 return; 159 } 160 161 static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) 162 { 163 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; 164 const struct ldpaa_dq *dq; 165 const struct dpaa_fd *fd; 166 int i = 5, err = 0, status; 167 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; 168 u32 time_start; 169 static struct qbman_pull_desc pulldesc; 170 struct qbman_swp *swp = dflt_dpio->sw_portal; 171 172 while (--i) { 173 qbman_pull_desc_clear(&pulldesc); 174 qbman_pull_desc_set_numframes(&pulldesc, 1); 175 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid); 176 177 err = qbman_swp_pull(swp, &pulldesc); 178 if (err < 0) { 179 printf("Dequeue frames error:0x%08x\n", err); 180 continue; 181 } 182 183 time_start = get_timer(0); 184 185 do { 186 dq = qbman_swp_dqrr_next(swp); 187 } while (get_timer(time_start) < timeo && !dq); 188 189 if (dq) { 190 /* Check for valid frame. If not sent a consume 191 * confirmation to QBMAN otherwise give it to NADK 192 * application and then send consume confirmation to 193 * QBMAN. 194 */ 195 status = (uint8_t)ldpaa_dq_flags(dq); 196 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { 197 debug("Dequeue RX frames:"); 198 debug("No frame delivered\n"); 199 200 qbman_swp_dqrr_consume(swp, dq); 201 continue; 202 } 203 204 fd = ldpaa_dq_fd(dq); 205 206 /* Obtain FD and process it */ 207 ldpaa_eth_rx(priv, fd); 208 qbman_swp_dqrr_consume(swp, dq); 209 break; 210 } else { 211 err = -ENODATA; 212 debug("No DQRR entries\n"); 213 break; 214 } 215 } 216 217 return err; 218 } 219 220 static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) 221 { 222 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 223 struct dpaa_fd fd; 224 u64 buffer_start; 225 int data_offset, err; 226 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; 227 u32 time_start; 228 struct qbman_swp *swp = dflt_dpio->sw_portal; 229 struct qbman_eq_desc ed; 230 struct qbman_release_desc releasedesc; 231 232 /* Setup the FD fields */ 233 memset(&fd, 0, sizeof(fd)); 234 235 data_offset = priv->tx_data_offset; 236 237 do { 238 err = qbman_swp_acquire(dflt_dpio->sw_portal, 239 dflt_dpbp->dpbp_attr.bpid, 240 &buffer_start, 1); 241 } while (err == -EBUSY); 242 243 if (err < 0) { 244 printf("qbman_swp_acquire() failed\n"); 245 return -ENOMEM; 246 } 247 248 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start); 249 250 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len); 251 252 flush_dcache_range(buffer_start, buffer_start + 253 LDPAA_ETH_RX_BUFFER_SIZE); 254 255 ldpaa_fd_set_addr(&fd, (u64)buffer_start); 256 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset)); 257 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid); 258 ldpaa_fd_set_len(&fd, len); 259 260 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA | 261 LDPAA_FD_CTRL_PTV1; 262 263 qbman_eq_desc_clear(&ed); 264 qbman_eq_desc_set_no_orp(&ed, 0); 265 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); 266 267 time_start = get_timer(0); 268 269 while (get_timer(time_start) < timeo) { 270 err = qbman_swp_enqueue(swp, &ed, 271 (const struct qbman_fd *)(&fd)); 272 if (err != -EBUSY) 273 break; 274 } 275 276 if (err < 0) { 277 printf("error enqueueing Tx frame\n"); 278 goto error; 279 } 280 281 return err; 282 283 error: 284 qbman_release_desc_clear(&releasedesc); 285 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 286 time_start = get_timer(0); 287 do { 288 /* Release buffer into the QBMAN */ 289 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1); 290 } while (get_timer(time_start) < timeo && err == -EBUSY); 291 292 if (err == -EBUSY) 293 printf("TX data: QBMAN buffer release fails\n"); 294 295 return err; 296 } 297 298 static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) 299 { 300 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 301 struct dpni_queue_attr rx_queue_attr; 302 struct dpmac_link_state dpmac_link_state = { 0 }; 303 #ifdef DEBUG 304 struct dpni_link_state link_state; 305 #endif 306 int err; 307 308 if (net_dev->state == ETH_STATE_ACTIVE) 309 return 0; 310 311 if (get_mc_boot_status() != 0) { 312 printf("ERROR (MC is not booted)\n"); 313 return -ENODEV; 314 } 315 316 if (get_dpl_apply_status() == 0) { 317 printf("ERROR (DPL is deployed. No device available)\n"); 318 return -ENODEV; 319 } 320 /* DPMAC initialization */ 321 err = ldpaa_dpmac_setup(priv); 322 if (err < 0) 323 goto err_dpmac_setup; 324 325 /* DPMAC binding DPNI */ 326 err = ldpaa_dpmac_bind(priv); 327 if (err) 328 goto err_dpamc_bind; 329 330 /* DPNI initialization */ 331 err = ldpaa_dpni_setup(priv); 332 if (err < 0) 333 goto err_dpni_setup; 334 335 err = ldpaa_dpbp_setup(); 336 if (err < 0) 337 goto err_dpbp_setup; 338 339 /* DPNI binding DPBP */ 340 err = ldpaa_dpni_bind(priv); 341 if (err) 342 goto err_dpni_bind; 343 344 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, 345 dflt_dpni->dpni_handle, net_dev->enetaddr); 346 if (err) { 347 printf("dpni_add_mac_addr() failed\n"); 348 return err; 349 } 350 351 #ifdef CONFIG_PHYLIB 352 /* TODO Check this path */ 353 err = phy_startup(priv->phydev); 354 if (err) { 355 printf("%s: Could not initialize\n", priv->phydev->dev->name); 356 return err; 357 } 358 #else 359 priv->phydev->speed = SPEED_1000; 360 priv->phydev->link = 1; 361 priv->phydev->duplex = DUPLEX_FULL; 362 #endif 363 364 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 365 if (err < 0) { 366 printf("dpni_enable() failed\n"); 367 return err; 368 } 369 370 dpmac_link_state.rate = SPEED_1000; 371 dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG; 372 dpmac_link_state.up = 1; 373 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, 374 priv->dpmac_handle, &dpmac_link_state); 375 if (err < 0) { 376 printf("dpmac_set_link_state() failed\n"); 377 return err; 378 } 379 380 #ifdef DEBUG 381 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, 382 dflt_dpni->dpni_handle, &link_state); 383 if (err < 0) { 384 printf("dpni_get_link_state() failed\n"); 385 return err; 386 } 387 388 printf("link status: %d - ", link_state.up); 389 link_state.up == 0 ? printf("down\n") : 390 link_state.up == 1 ? printf("up\n") : printf("error state\n"); 391 #endif 392 393 /* TODO: support multiple Rx flows */ 394 err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, 395 dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr); 396 if (err) { 397 printf("dpni_get_rx_flow() failed\n"); 398 goto err_rx_flow; 399 } 400 401 priv->rx_dflt_fqid = rx_queue_attr.fqid; 402 403 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, 404 &priv->tx_qdid); 405 if (err) { 406 printf("dpni_get_qdid() failed\n"); 407 goto err_qdid; 408 } 409 410 if (!priv->phydev->link) 411 printf("%s: No link.\n", priv->phydev->dev->name); 412 413 return priv->phydev->link ? 0 : -1; 414 415 err_qdid: 416 err_rx_flow: 417 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 418 err_dpni_bind: 419 ldpaa_dpbp_free(); 420 err_dpbp_setup: 421 err_dpamc_bind: 422 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 423 err_dpni_setup: 424 err_dpmac_setup: 425 return err; 426 } 427 428 static void ldpaa_eth_stop(struct eth_device *net_dev) 429 { 430 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 431 int err = 0; 432 433 if ((net_dev->state == ETH_STATE_PASSIVE) || 434 (net_dev->state == ETH_STATE_INIT)) 435 return; 436 437 #ifdef DEBUG 438 ldpaa_eth_get_dpni_counter(); 439 #endif 440 441 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS, 442 dflt_dprc_handle, &dpmac_endpoint); 443 if (err < 0) 444 printf("dprc_disconnect() failed dpmac_endpoint\n"); 445 446 err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); 447 if (err < 0) 448 printf("dpmac_destroy() failed\n"); 449 450 /* Stop Tx and Rx traffic */ 451 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 452 if (err < 0) 453 printf("dpni_disable() failed\n"); 454 455 #ifdef CONFIG_PHYLIB 456 phy_shutdown(priv->phydev); 457 #endif 458 459 ldpaa_dpbp_free(); 460 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 461 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 462 } 463 464 static void ldpaa_dpbp_drain_cnt(int count) 465 { 466 uint64_t buf_array[7]; 467 void *addr; 468 int ret, i; 469 470 BUG_ON(count > 7); 471 472 do { 473 ret = qbman_swp_acquire(dflt_dpio->sw_portal, 474 dflt_dpbp->dpbp_attr.bpid, 475 buf_array, count); 476 if (ret < 0) { 477 printf("qbman_swp_acquire() failed\n"); 478 return; 479 } 480 for (i = 0; i < ret; i++) { 481 addr = (void *)buf_array[i]; 482 debug("Free: buffer addr =0x%p\n", addr); 483 free(addr); 484 } 485 } while (ret); 486 } 487 488 static void ldpaa_dpbp_drain(void) 489 { 490 int i; 491 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) 492 ldpaa_dpbp_drain_cnt(7); 493 } 494 495 static int ldpaa_bp_add_7(uint16_t bpid) 496 { 497 uint64_t buf_array[7]; 498 u8 *addr; 499 int i; 500 struct qbman_release_desc rd; 501 502 for (i = 0; i < 7; i++) { 503 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE); 504 if (!addr) { 505 printf("addr allocation failed\n"); 506 goto err_alloc; 507 } 508 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE); 509 flush_dcache_range((u64)addr, 510 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE)); 511 512 buf_array[i] = (uint64_t)addr; 513 debug("Release: buffer addr =0x%p\n", addr); 514 } 515 516 release_bufs: 517 /* In case the portal is busy, retry until successful. 518 * This function is guaranteed to succeed in a reasonable amount 519 * of time. 520 */ 521 522 do { 523 mdelay(1); 524 qbman_release_desc_clear(&rd); 525 qbman_release_desc_set_bpid(&rd, bpid); 526 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i)); 527 528 return i; 529 530 err_alloc: 531 if (i) 532 goto release_bufs; 533 534 return 0; 535 } 536 537 static int ldpaa_dpbp_seed(uint16_t bpid) 538 { 539 int i; 540 int count; 541 542 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) { 543 count = ldpaa_bp_add_7(bpid); 544 if (count < 7) 545 printf("Buffer Seed= %d\n", count); 546 } 547 548 return 0; 549 } 550 551 static int ldpaa_dpbp_setup(void) 552 { 553 int err; 554 555 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id, 556 &dflt_dpbp->dpbp_handle); 557 if (err) { 558 printf("dpbp_open() failed\n"); 559 goto err_open; 560 } 561 562 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 563 if (err) { 564 printf("dpbp_enable() failed\n"); 565 goto err_enable; 566 } 567 568 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 569 dflt_dpbp->dpbp_handle, 570 &dflt_dpbp->dpbp_attr); 571 if (err) { 572 printf("dpbp_get_attributes() failed\n"); 573 goto err_get_attr; 574 } 575 576 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); 577 if (err) { 578 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", 579 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); 580 goto err_seed; 581 } 582 583 return 0; 584 585 err_seed: 586 err_get_attr: 587 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 588 err_enable: 589 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 590 err_open: 591 return err; 592 } 593 594 static void ldpaa_dpbp_free(void) 595 { 596 ldpaa_dpbp_drain(); 597 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 598 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 599 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 600 } 601 602 static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io, 603 struct ldpaa_eth_priv *priv) 604 { 605 struct dpmac_attr attr; 606 int error; 607 608 memset(&attr, 0, sizeof(struct dpmac_attr)); 609 error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS, 610 priv->dpmac_handle, 611 &attr); 612 if (error == 0) { 613 if ((attr.version.major != DPMAC_VER_MAJOR) || 614 (attr.version.minor != DPMAC_VER_MINOR)) { 615 printf("DPMAC version mismatch found %u.%u,", 616 attr.version.major, attr.version.minor); 617 printf("supported version is %u.%u\n", 618 DPMAC_VER_MAJOR, DPMAC_VER_MINOR); 619 } 620 } 621 622 return error; 623 } 624 625 static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv) 626 { 627 int err = 0; 628 struct dpmac_cfg dpmac_cfg; 629 630 dpmac_cfg.mac_id = priv->dpmac_id; 631 err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg, 632 &priv->dpmac_handle); 633 if (err) 634 printf("dpmac_create() failed\n"); 635 636 err = ldpaa_dpmac_version_check(dflt_mc_io, priv); 637 if (err < 0) 638 printf("ldpaa_dpmac_version_check() failed: %d\n", err); 639 640 return err; 641 } 642 643 static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv) 644 { 645 int err = 0; 646 struct dprc_connection_cfg dprc_connection_cfg = { 647 /* If both rates are zero the connection */ 648 /* will be configured in "best effort" mode. */ 649 .committed_rate = 0, 650 .max_rate = 0 651 }; 652 653 #ifdef DEBUG 654 struct dprc_endpoint dbg_endpoint; 655 int state = 0; 656 #endif 657 658 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint)); 659 strcpy(dpmac_endpoint.type, "dpmac"); 660 dpmac_endpoint.id = priv->dpmac_id; 661 662 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint)); 663 strcpy(dpni_endpoint.type, "dpni"); 664 dpni_endpoint.id = dflt_dpni->dpni_id; 665 666 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS, 667 dflt_dprc_handle, 668 &dpmac_endpoint, 669 &dpni_endpoint, 670 &dprc_connection_cfg); 671 if (err) 672 printf("dprc_connect() failed\n"); 673 674 #ifdef DEBUG 675 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS, 676 dflt_dprc_handle, &dpni_endpoint, 677 &dbg_endpoint, &state); 678 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type); 679 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id); 680 printf("%s, DPMAC State= %d\n", __func__, state); 681 682 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint)); 683 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS, 684 dflt_dprc_handle, &dpmac_endpoint, 685 &dbg_endpoint, &state); 686 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type); 687 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id); 688 printf("%s, DPNI State= %d\n", __func__, state); 689 #endif 690 return err; 691 } 692 693 static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) 694 { 695 int err; 696 697 /* and get a handle for the DPNI this interface is associate with */ 698 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id, 699 &dflt_dpni->dpni_handle); 700 if (err) { 701 printf("dpni_open() failed\n"); 702 goto err_open; 703 } 704 705 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 706 dflt_dpni->dpni_handle, 707 &dflt_dpni->dpni_attrs); 708 if (err) { 709 printf("dpni_get_attributes() failed (err=%d)\n", err); 710 goto err_get_attr; 711 } 712 713 /* Configure our buffers' layout */ 714 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | 715 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | 716 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE | 717 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN; 718 dflt_dpni->buf_layout.pass_parser_result = true; 719 dflt_dpni->buf_layout.pass_frame_status = true; 720 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; 721 /* HW erratum mandates data alignment in multiples of 256 */ 722 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN; 723 /* ...rx, ... */ 724 err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 725 dflt_dpni->dpni_handle, 726 &dflt_dpni->buf_layout); 727 if (err) { 728 printf("dpni_set_rx_buffer_layout() failed"); 729 goto err_buf_layout; 730 } 731 732 /* ... tx, ... */ 733 /* remove Rx-only options */ 734 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | 735 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT); 736 err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 737 dflt_dpni->dpni_handle, 738 &dflt_dpni->buf_layout); 739 if (err) { 740 printf("dpni_set_tx_buffer_layout() failed"); 741 goto err_buf_layout; 742 } 743 744 /* ... tx-confirm. */ 745 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; 746 err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 747 dflt_dpni->dpni_handle, 748 &dflt_dpni->buf_layout); 749 if (err) { 750 printf("dpni_set_tx_conf_buffer_layout() failed"); 751 goto err_buf_layout; 752 } 753 754 /* Now that we've set our tx buffer layout, retrieve the minimum 755 * required tx data offset. 756 */ 757 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS, 758 dflt_dpni->dpni_handle, 759 &priv->tx_data_offset); 760 if (err) { 761 printf("dpni_get_tx_data_offset() failed\n"); 762 goto err_data_offset; 763 } 764 765 /* Warn in case TX data offset is not multiple of 64 bytes. */ 766 WARN_ON(priv->tx_data_offset % 64); 767 768 /* Accomodate SWA space. */ 769 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE; 770 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset); 771 772 return 0; 773 774 err_data_offset: 775 err_buf_layout: 776 err_get_attr: 777 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 778 err_open: 779 return err; 780 } 781 782 static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) 783 { 784 struct dpni_pools_cfg pools_params; 785 struct dpni_tx_flow_cfg dflt_tx_flow; 786 int err = 0; 787 788 pools_params.num_dpbp = 1; 789 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id; 790 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE; 791 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS, 792 dflt_dpni->dpni_handle, &pools_params); 793 if (err) { 794 printf("dpni_set_pools() failed\n"); 795 return err; 796 } 797 798 priv->tx_flow_id = DPNI_NEW_FLOW_ID; 799 memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); 800 801 dflt_tx_flow.options = DPNI_TX_FLOW_OPT_ONLY_TX_ERROR; 802 dflt_tx_flow.conf_err_cfg.use_default_queue = 0; 803 dflt_tx_flow.conf_err_cfg.errors_only = 1; 804 err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, 805 dflt_dpni->dpni_handle, &priv->tx_flow_id, 806 &dflt_tx_flow); 807 if (err) { 808 printf("dpni_set_tx_flow() failed\n"); 809 return err; 810 } 811 812 return 0; 813 } 814 815 static int ldpaa_eth_netdev_init(struct eth_device *net_dev, 816 phy_interface_t enet_if) 817 { 818 int err; 819 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 820 821 sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id, 822 phy_interface_strings[enet_if]); 823 824 net_dev->iobase = 0; 825 net_dev->init = ldpaa_eth_open; 826 net_dev->halt = ldpaa_eth_stop; 827 net_dev->send = ldpaa_eth_tx; 828 net_dev->recv = ldpaa_eth_pull_dequeue_rx; 829 /* 830 TODO: PHY MDIO information 831 priv->bus = info->bus; 832 priv->phyaddr = info->phy_addr; 833 priv->enet_if = info->enet_if; 834 */ 835 836 if (init_phy(net_dev)) 837 return 0; 838 839 err = eth_register(net_dev); 840 if (err < 0) { 841 printf("eth_register() = %d\n", err); 842 return err; 843 } 844 845 return 0; 846 } 847 848 int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if) 849 { 850 struct eth_device *net_dev = NULL; 851 struct ldpaa_eth_priv *priv = NULL; 852 int err = 0; 853 854 855 /* Net device */ 856 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 857 if (!net_dev) { 858 printf("eth_device malloc() failed\n"); 859 return -ENOMEM; 860 } 861 memset(net_dev, 0, sizeof(struct eth_device)); 862 863 /* alloc the ldpaa ethernet private struct */ 864 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv)); 865 if (!priv) { 866 printf("ldpaa_eth_priv malloc() failed\n"); 867 return -ENOMEM; 868 } 869 memset(priv, 0, sizeof(struct ldpaa_eth_priv)); 870 871 net_dev->priv = (void *)priv; 872 priv->net_dev = (struct eth_device *)net_dev; 873 priv->dpmac_id = dpmac_id; 874 debug("%s dpmac_id=%d\n", __func__, dpmac_id); 875 876 err = ldpaa_eth_netdev_init(net_dev, enet_if); 877 if (err) 878 goto err_netdev_init; 879 880 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name); 881 return 0; 882 883 err_netdev_init: 884 free(priv); 885 net_dev->priv = NULL; 886 free(net_dev); 887 888 return err; 889 } 890