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