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