Commit c517771ae745dbba59112b8d311e41d37c0fc032

Authored by Prabhakar Kushwaha
Committed by York Sun
1 parent a2a55e518f

driver/ldpaa_eth: Add LDPAA Ethernet driver

LDPAA Ethernet driver is a freescale's new ethernet driver based on
Layerscape architecture.

Every ethernet driver controls on DPNI object. Where all DPNIs share
one common DPBP and DPIO object to support  Rx and Tx flows.

Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
CC: Cristian Sovaiala <cristian.sovaiala@freescale.com>
CC: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
CC: J. German Rivera <German.Rivera@freescale.com>
[York Sun: s/NetReceive/net_process_received_packet]
Reviewed-by: York Sun <yorksun@freescale.com>

Showing 7 changed files with 879 additions and 3 deletions Side-by-side Diff

arch/arm/include/asm/arch-fsl-lsch3/config.h
... ... @@ -10,6 +10,12 @@
10 10 #include <fsl_ddrc_version.h>
11 11  
12 12 #define CONFIG_SYS_PAGE_SIZE 0x10000
  13 +
  14 +#ifndef L1_CACHE_BYTES
  15 +#define L1_CACHE_SHIFT 6
  16 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
  17 +#endif
  18 +
13 19 #define CONFIG_MP
14 20 #define CONFIG_SYS_FSL_OCRAM_BASE 0x18000000 /* initial RAM */
15 21 /* Link Definitions */
drivers/net/Makefile
... ... @@ -69,5 +69,6 @@
69 69 xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
70 70 obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
71 71 obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
  72 +obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
72 73 obj-$(CONFIG_VSC9953) += vsc9953.o
drivers/net/fsl-mc/mc.c
... ... @@ -397,9 +397,10 @@
397 397 return 0;
398 398 }
399 399  
400   -int dprc_init_container_obj(struct dprc_obj_desc obj_desc)
  400 +int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle)
401 401 {
402   - int error = 0;
  402 + int error = 0, state = 0;
  403 + struct dprc_endpoint dpni_endpoint, dpmac_endpoint;
403 404 if (!strcmp(obj_desc.type, "dpbp")) {
404 405 if (!dflt_dpbp) {
405 406 error = dpbp_init(obj_desc);
... ... @@ -412,6 +413,15 @@
412 413 if (error < 0)
413 414 printf("dpio_init failed\n");
414 415 }
  416 + } else if (!strcmp(obj_desc.type, "dpni")) {
  417 + strcpy(dpni_endpoint.type, obj_desc.type);
  418 + dpni_endpoint.id = obj_desc.id;
  419 + error = dprc_get_connection(dflt_mc_io, dprc_handle,
  420 + &dpni_endpoint, &dpmac_endpoint, &state);
  421 + if (!strcmp(dpmac_endpoint.type, "dpmac"))
  422 + error = ldpaa_eth_init(obj_desc);
  423 + if (error < 0)
  424 + printf("ldpaa_eth_init failed\n");
415 425 }
416 426  
417 427 return error;
... ... @@ -436,7 +446,7 @@
436 446 debug("Discovered object: type %s, id %d, req %s\n",
437 447 obj_desc.type, obj_desc.id, obj_type);
438 448  
439   - error = dprc_init_container_obj(obj_desc);
  449 + error = dprc_init_container_obj(obj_desc, dprc_handle);
440 450 if (error < 0) {
441 451 printf("dprc_init_container_obj(i=%d) failed: %d\n",
442 452 i, error);
drivers/net/ldpaa_eth/Makefile
  1 +#
  2 +# Copyright 2014 Freescale Semiconductor, Inc.
  3 +#
  4 +# SPDX-License-Identifier: GPL-2.0+
  5 +#
  6 +
  7 +# Layerscape LDPAA driver
  8 +obj-y += ldpaa_eth.o
drivers/net/ldpaa_eth/ldpaa_eth.c
  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 +static int init_phy(struct eth_device *dev)
  19 +{
  20 + /*TODO for external PHY */
  21 +
  22 + return 0;
  23 +}
  24 +
  25 +static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
  26 + const struct dpaa_fd *fd)
  27 +{
  28 + u64 fd_addr;
  29 + uint16_t fd_offset;
  30 + uint32_t fd_length;
  31 + struct ldpaa_fas *fas;
  32 + uint32_t status, err;
  33 + struct qbman_release_desc releasedesc;
  34 + struct qbman_swp *swp = dflt_dpio->sw_portal;
  35 +
  36 + invalidate_dcache_all();
  37 +
  38 + fd_addr = ldpaa_fd_get_addr(fd);
  39 + fd_offset = ldpaa_fd_get_offset(fd);
  40 + fd_length = ldpaa_fd_get_len(fd);
  41 +
  42 + debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
  43 +
  44 + if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
  45 + /* Read the frame annotation status word and check for errors */
  46 + fas = (struct ldpaa_fas *)
  47 + ((uint8_t *)(fd_addr) +
  48 + priv->buf_layout.private_data_size);
  49 + status = le32_to_cpu(fas->status);
  50 + if (status & LDPAA_ETH_RX_ERR_MASK) {
  51 + printf("Rx frame error(s): 0x%08x\n",
  52 + status & LDPAA_ETH_RX_ERR_MASK);
  53 + goto error;
  54 + } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
  55 + printf("Unsupported feature in bitmask: 0x%08x\n",
  56 + status & LDPAA_ETH_RX_UNSUPP_MASK);
  57 + goto error;
  58 + }
  59 + }
  60 +
  61 + debug("Rx frame: To Upper layer\n");
  62 + net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
  63 + fd_length);
  64 +
  65 +error:
  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;
  81 + static struct qbman_pull_desc pulldesc;
  82 + struct qbman_swp *swp = dflt_dpio->sw_portal;
  83 +
  84 + qbman_pull_desc_clear(&pulldesc);
  85 + qbman_pull_desc_set_numframes(&pulldesc, 1);
  86 + qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
  87 +
  88 + while (--i) {
  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 + dq = qbman_swp_dqrr_next(swp);
  96 + if (dq) {
  97 + /* Check for valid frame. If not sent a consume
  98 + * confirmation to QBMAN otherwise give it to NADK
  99 + * application and then send consume confirmation to
  100 + * QBMAN.
  101 + */
  102 + status = (uint8_t)ldpaa_dq_flags(dq);
  103 + if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
  104 + debug("Dequeue RX frames:");
  105 + debug("No frame delivered\n");
  106 +
  107 + qbman_swp_dqrr_consume(swp, dq);
  108 + break;
  109 + }
  110 +
  111 + fd = ldpaa_dq_fd(dq);
  112 +
  113 + /* Obtain FD and process it */
  114 + ldpaa_eth_rx(priv, fd);
  115 + qbman_swp_dqrr_consume(swp, dq);
  116 + break;
  117 + }
  118 + }
  119 +
  120 + return err;
  121 +}
  122 +
  123 +static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv,
  124 + const struct dpaa_fd *fd)
  125 +{
  126 + uint64_t fd_addr;
  127 + struct ldpaa_fas *fas;
  128 + uint32_t status, err;
  129 + struct qbman_release_desc releasedesc;
  130 + struct qbman_swp *swp = dflt_dpio->sw_portal;
  131 +
  132 + invalidate_dcache_all();
  133 + fd_addr = ldpaa_fd_get_addr(fd);
  134 +
  135 +
  136 + debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr);
  137 +
  138 + /* Check the status from the Frame Annotation */
  139 + if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
  140 + fas = (struct ldpaa_fas *)
  141 + ((uint8_t *)(fd_addr) +
  142 + priv->buf_layout.private_data_size);
  143 + status = le32_to_cpu(fas->status);
  144 + if (status & LDPAA_ETH_TXCONF_ERR_MASK) {
  145 + printf("TxConf frame error(s): 0x%08x\n",
  146 + status & LDPAA_ETH_TXCONF_ERR_MASK);
  147 + }
  148 + }
  149 +
  150 + qbman_release_desc_clear(&releasedesc);
  151 + qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
  152 + do {
  153 + /* Release buffer into the QBMAN */
  154 + err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
  155 + } while (err == -EBUSY);
  156 +}
  157 +
  158 +static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv)
  159 +{
  160 + const struct ldpaa_dq *dq;
  161 + const struct dpaa_fd *fd;
  162 + int err = 0;
  163 + int i = 5, status;
  164 + static struct qbman_pull_desc pulldesc;
  165 + struct qbman_swp *swp = dflt_dpio->sw_portal;
  166 +
  167 + qbman_pull_desc_clear(&pulldesc);
  168 + qbman_pull_desc_set_numframes(&pulldesc, 1);
  169 + qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid);
  170 +
  171 + while (--i) {
  172 + err = qbman_swp_pull(swp, &pulldesc);
  173 + if (err < 0) {
  174 + printf("Dequeue TX conf frames error:0x%08x\n", err);
  175 + continue;
  176 + }
  177 +
  178 + dq = qbman_swp_dqrr_next(swp);
  179 + if (dq) {
  180 + /* Check for valid frame. If not sent a consume
  181 + * confirmation to QBMAN otherwise give it to NADK
  182 + * application and then send consume confirmation to
  183 + * QBMAN.
  184 + */
  185 + status = (uint8_t)ldpaa_dq_flags(dq);
  186 + if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
  187 + debug("Dequeue TX conf frames:");
  188 + debug("No frame is delivered\n");
  189 +
  190 + qbman_swp_dqrr_consume(swp, dq);
  191 + break;
  192 + }
  193 + fd = ldpaa_dq_fd(dq);
  194 +
  195 + ldpaa_eth_tx_conf(priv, fd);
  196 + qbman_swp_dqrr_consume(swp, dq);
  197 + break;
  198 + }
  199 + }
  200 +
  201 + return err;
  202 +}
  203 +
  204 +static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
  205 +{
  206 + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  207 + struct dpaa_fd fd;
  208 + u64 buffer_start;
  209 + int data_offset, err;
  210 + struct qbman_swp *swp = dflt_dpio->sw_portal;
  211 + struct qbman_eq_desc ed;
  212 +
  213 + /* Setup the FD fields */
  214 + memset(&fd, 0, sizeof(fd));
  215 +
  216 + data_offset = priv->tx_data_offset;
  217 +
  218 + do {
  219 + err = qbman_swp_acquire(dflt_dpio->sw_portal,
  220 + dflt_dpbp->dpbp_attr.bpid,
  221 + &buffer_start, 1);
  222 + } while (err == -EBUSY);
  223 +
  224 + if (err < 0) {
  225 + printf("qbman_swp_acquire() failed\n");
  226 + return -ENOMEM;
  227 + }
  228 +
  229 + debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
  230 +
  231 + memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
  232 +
  233 + flush_dcache_range(buffer_start, LDPAA_ETH_RX_BUFFER_SIZE);
  234 +
  235 + ldpaa_fd_set_addr(&fd, (u64)buffer_start);
  236 + ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
  237 + ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
  238 + ldpaa_fd_set_len(&fd, len);
  239 +
  240 + fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
  241 + LDPAA_FD_CTRL_PTV1;
  242 +
  243 + qbman_eq_desc_clear(&ed);
  244 + qbman_eq_desc_set_no_orp(&ed, 0);
  245 + qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
  246 + err = qbman_swp_enqueue(swp, &ed, (const struct qbman_fd *)(&fd));
  247 + if (err < 0)
  248 + printf("error enqueueing Tx frame\n");
  249 +
  250 + mdelay(1);
  251 +
  252 + err = ldpaa_eth_pull_dequeue_tx_conf(priv);
  253 + if (err < 0)
  254 + printf("error Tx Conf frame\n");
  255 +
  256 + return err;
  257 +}
  258 +
  259 +static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
  260 +{
  261 + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  262 + struct dpni_queue_attr rx_queue_attr;
  263 + struct dpni_tx_flow_attr tx_flow_attr;
  264 + uint8_t mac_addr[6];
  265 + int err;
  266 +
  267 + if (net_dev->state == ETH_STATE_ACTIVE)
  268 + return 0;
  269 +
  270 + /* DPNI initialization */
  271 + err = ldpaa_dpni_setup(priv);
  272 + if (err < 0)
  273 + goto err_dpni_setup;
  274 +
  275 + err = ldpaa_dpbp_setup();
  276 + if (err < 0)
  277 + goto err_dpbp_setup;
  278 +
  279 + /* DPNI binding DPBP */
  280 + err = ldpaa_dpni_bind(priv);
  281 + if (err)
  282 + goto err_bind;
  283 +
  284 + err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle,
  285 + mac_addr);
  286 + if (err) {
  287 + printf("dpni_get_primary_mac_addr() failed\n");
  288 + return err;
  289 + }
  290 +
  291 + memcpy(net_dev->enetaddr, mac_addr, 0x6);
  292 +
  293 + /* setup the MAC address */
  294 + if (net_dev->enetaddr[0] & 0x01) {
  295 + printf("%s: MacAddress is multcast address\n", __func__);
  296 + return 1;
  297 + }
  298 +
  299 +#ifdef CONFIG_PHYLIB
  300 + /* TODO Check this path */
  301 + ret = phy_startup(priv->phydev);
  302 + if (ret) {
  303 + printf("%s: Could not initialize\n", priv->phydev->dev->name);
  304 + return ret;
  305 + }
  306 +#else
  307 + priv->phydev->speed = SPEED_1000;
  308 + priv->phydev->link = 1;
  309 + priv->phydev->duplex = DUPLEX_FULL;
  310 +#endif
  311 +
  312 + err = dpni_enable(dflt_mc_io, priv->dpni_handle);
  313 + if (err < 0) {
  314 + printf("dpni_enable() failed\n");
  315 + return err;
  316 + }
  317 +
  318 + /* TODO: support multiple Rx flows */
  319 + err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0,
  320 + &rx_queue_attr);
  321 + if (err) {
  322 + printf("dpni_get_rx_flow() failed\n");
  323 + goto err_rx_flow;
  324 + }
  325 +
  326 + priv->rx_dflt_fqid = rx_queue_attr.fqid;
  327 +
  328 + err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid);
  329 + if (err) {
  330 + printf("dpni_get_qdid() failed\n");
  331 + goto err_qdid;
  332 + }
  333 +
  334 + err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id,
  335 + &tx_flow_attr);
  336 + if (err) {
  337 + printf("dpni_get_tx_flow() failed\n");
  338 + goto err_tx_flow;
  339 + }
  340 +
  341 + priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid;
  342 +
  343 + if (!priv->phydev->link)
  344 + printf("%s: No link.\n", priv->phydev->dev->name);
  345 +
  346 + return priv->phydev->link ? 0 : -1;
  347 +
  348 +err_tx_flow:
  349 +err_qdid:
  350 +err_rx_flow:
  351 + dpni_disable(dflt_mc_io, priv->dpni_handle);
  352 +err_bind:
  353 + ldpaa_dpbp_free();
  354 +err_dpbp_setup:
  355 + dpni_close(dflt_mc_io, priv->dpni_handle);
  356 +err_dpni_setup:
  357 + return err;
  358 +}
  359 +
  360 +static void ldpaa_eth_stop(struct eth_device *net_dev)
  361 +{
  362 + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  363 + int err = 0;
  364 +
  365 + if (net_dev->state == ETH_STATE_PASSIVE)
  366 + return;
  367 + /* Stop Tx and Rx traffic */
  368 + err = dpni_disable(dflt_mc_io, priv->dpni_handle);
  369 + if (err < 0)
  370 + printf("dpni_disable() failed\n");
  371 +
  372 +#ifdef CONFIG_PHYLIB
  373 + phy_shutdown(priv->phydev);
  374 +#endif
  375 +
  376 + ldpaa_dpbp_free();
  377 + dpni_reset(dflt_mc_io, priv->dpni_handle);
  378 + dpni_close(dflt_mc_io, priv->dpni_handle);
  379 +}
  380 +
  381 +static void ldpaa_dpbp_drain_cnt(int count)
  382 +{
  383 + uint64_t buf_array[7];
  384 + void *addr;
  385 + int ret, i;
  386 +
  387 + BUG_ON(count > 7);
  388 +
  389 + do {
  390 + ret = qbman_swp_acquire(dflt_dpio->sw_portal,
  391 + dflt_dpbp->dpbp_attr.bpid,
  392 + buf_array, count);
  393 + if (ret < 0) {
  394 + printf("qbman_swp_acquire() failed\n");
  395 + return;
  396 + }
  397 + for (i = 0; i < ret; i++) {
  398 + addr = (void *)buf_array[i];
  399 + debug("Free: buffer addr =0x%p\n", addr);
  400 + free(addr);
  401 + }
  402 + } while (ret);
  403 +}
  404 +
  405 +static void ldpaa_dpbp_drain(void)
  406 +{
  407 + int i;
  408 + for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
  409 + ldpaa_dpbp_drain_cnt(7);
  410 +}
  411 +
  412 +static int ldpaa_bp_add_7(uint16_t bpid)
  413 +{
  414 + uint64_t buf_array[7];
  415 + u8 *addr;
  416 + int i;
  417 + struct qbman_release_desc rd;
  418 +
  419 + for (i = 0; i < 7; i++) {
  420 + addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
  421 + if (!addr) {
  422 + printf("addr allocation failed\n");
  423 + goto err_alloc;
  424 + }
  425 + memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
  426 +
  427 + buf_array[i] = (uint64_t)addr;
  428 + debug("Release: buffer addr =0x%p\n", addr);
  429 + }
  430 +
  431 +release_bufs:
  432 + /* In case the portal is busy, retry until successful.
  433 + * This function is guaranteed to succeed in a reasonable amount
  434 + * of time.
  435 + */
  436 +
  437 + do {
  438 + mdelay(1);
  439 + qbman_release_desc_clear(&rd);
  440 + qbman_release_desc_set_bpid(&rd, bpid);
  441 + } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
  442 +
  443 + return i;
  444 +
  445 +err_alloc:
  446 + if (i)
  447 + goto release_bufs;
  448 +
  449 + return 0;
  450 +}
  451 +
  452 +static int ldpaa_dpbp_seed(uint16_t bpid)
  453 +{
  454 + int i;
  455 + int count;
  456 +
  457 + for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
  458 + count = ldpaa_bp_add_7(bpid);
  459 + if (count < 7)
  460 + printf("Buffer Seed= %d\n", count);
  461 + }
  462 +
  463 + return 0;
  464 +}
  465 +
  466 +static int ldpaa_dpbp_setup(void)
  467 +{
  468 + int err;
  469 +
  470 + err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id,
  471 + &dflt_dpbp->dpbp_handle);
  472 + if (err) {
  473 + printf("dpbp_open() failed\n");
  474 + goto err_open;
  475 + }
  476 +
  477 + err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle);
  478 + if (err) {
  479 + printf("dpbp_enable() failed\n");
  480 + goto err_enable;
  481 + }
  482 +
  483 + err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle,
  484 + &dflt_dpbp->dpbp_attr);
  485 + if (err) {
  486 + printf("dpbp_get_attributes() failed\n");
  487 + goto err_get_attr;
  488 + }
  489 +
  490 + err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
  491 + if (err) {
  492 + printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
  493 + dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
  494 + goto err_seed;
  495 + }
  496 +
  497 + return 0;
  498 +
  499 +err_seed:
  500 +err_get_attr:
  501 + dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
  502 +err_enable:
  503 + dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
  504 +err_open:
  505 + return err;
  506 +}
  507 +
  508 +static void ldpaa_dpbp_free(void)
  509 +{
  510 + ldpaa_dpbp_drain();
  511 + dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
  512 + dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle);
  513 + dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
  514 +}
  515 +
  516 +static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
  517 +{
  518 + int err;
  519 +
  520 + /* and get a handle for the DPNI this interface is associate with */
  521 + err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle);
  522 + if (err) {
  523 + printf("dpni_open() failed\n");
  524 + goto err_open;
  525 + }
  526 +
  527 + err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle,
  528 + &priv->dpni_attrs);
  529 + if (err) {
  530 + printf("dpni_get_attributes() failed (err=%d)\n", err);
  531 + goto err_get_attr;
  532 + }
  533 +
  534 + /* Configure our buffers' layout */
  535 + priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
  536 + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  537 + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  538 + priv->buf_layout.pass_parser_result = true;
  539 + priv->buf_layout.pass_frame_status = true;
  540 + priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
  541 + /* ...rx, ... */
  542 + err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle,
  543 + &priv->buf_layout);
  544 + if (err) {
  545 + printf("dpni_set_rx_buffer_layout() failed");
  546 + goto err_buf_layout;
  547 + }
  548 +
  549 + /* ... tx, ... */
  550 + priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
  551 + err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle,
  552 + &priv->buf_layout);
  553 + if (err) {
  554 + printf("dpni_set_tx_buffer_layout() failed");
  555 + goto err_buf_layout;
  556 + }
  557 +
  558 + /* ... tx-confirm. */
  559 + priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  560 + err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle,
  561 + &priv->buf_layout);
  562 + if (err) {
  563 + printf("dpni_set_tx_conf_buffer_layout() failed");
  564 + goto err_buf_layout;
  565 + }
  566 +
  567 + /* Now that we've set our tx buffer layout, retrieve the minimum
  568 + * required tx data offset.
  569 + */
  570 + err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle,
  571 + &priv->tx_data_offset);
  572 + if (err) {
  573 + printf("dpni_get_tx_data_offset() failed\n");
  574 + goto err_data_offset;
  575 + }
  576 +
  577 + /* Warn in case TX data offset is not multiple of 64 bytes. */
  578 + WARN_ON(priv->tx_data_offset % 64);
  579 +
  580 + /* Accomodate SWA space. */
  581 + priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
  582 + debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
  583 +
  584 + return 0;
  585 +
  586 +err_data_offset:
  587 +err_buf_layout:
  588 +err_get_attr:
  589 + dpni_close(dflt_mc_io, priv->dpni_handle);
  590 +err_open:
  591 + return err;
  592 +}
  593 +
  594 +static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
  595 +{
  596 + struct dpni_pools_cfg pools_params;
  597 + struct dpni_tx_flow_cfg dflt_tx_flow;
  598 + int err = 0;
  599 +
  600 + pools_params.num_dpbp = 1;
  601 + pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
  602 + pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
  603 + err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params);
  604 + if (err) {
  605 + printf("dpni_set_pools() failed\n");
  606 + return err;
  607 + }
  608 +
  609 + priv->tx_flow_id = DPNI_NEW_FLOW_ID;
  610 + memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
  611 +
  612 + err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle,
  613 + &priv->tx_flow_id, &dflt_tx_flow);
  614 + if (err) {
  615 + printf("dpni_set_tx_flow() failed\n");
  616 + return err;
  617 + }
  618 +
  619 + return 0;
  620 +}
  621 +
  622 +static int ldpaa_eth_netdev_init(struct eth_device *net_dev)
  623 +{
  624 + int err;
  625 + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  626 +
  627 + if (priv->type == LDPAA_ETH_1G_E)
  628 + sprintf(net_dev->name, "DTSEC%d", priv->dpni_id);
  629 + else
  630 + sprintf(net_dev->name, "TGEC%d", priv->dpni_id);
  631 +
  632 + net_dev->iobase = 0;
  633 + net_dev->init = ldpaa_eth_open;
  634 + net_dev->halt = ldpaa_eth_stop;
  635 + net_dev->send = ldpaa_eth_tx;
  636 + net_dev->recv = ldpaa_eth_pull_dequeue_rx;
  637 +/*
  638 + TODO: PHY MDIO information
  639 + priv->bus = info->bus;
  640 + priv->phyaddr = info->phy_addr;
  641 + priv->enet_if = info->enet_if;
  642 +*/
  643 +
  644 + if (init_phy(net_dev))
  645 + return 0;
  646 +
  647 + err = eth_register(net_dev);
  648 + if (err < 0) {
  649 + printf("eth_register() = %d\n", err);
  650 + return err;
  651 + }
  652 +
  653 + return 0;
  654 +}
  655 +
  656 +int ldpaa_eth_init(struct dprc_obj_desc obj_desc)
  657 +{
  658 + struct eth_device *net_dev = NULL;
  659 + struct ldpaa_eth_priv *priv = NULL;
  660 + int err = 0;
  661 +
  662 +
  663 + /* Net device */
  664 + net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  665 + if (!net_dev) {
  666 + printf("eth_device malloc() failed\n");
  667 + return -ENOMEM;
  668 + }
  669 + memset(net_dev, 0, sizeof(struct eth_device));
  670 +
  671 + /* alloc the ldpaa ethernet private struct */
  672 + priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
  673 + if (!priv) {
  674 + printf("ldpaa_eth_priv malloc() failed\n");
  675 + return -ENOMEM;
  676 + }
  677 + memset(priv, 0, sizeof(struct ldpaa_eth_priv));
  678 +
  679 + net_dev->priv = (void *)priv;
  680 + priv->net_dev = (struct eth_device *)net_dev;
  681 + priv->dpni_id = obj_desc.id;
  682 +
  683 + err = ldpaa_eth_netdev_init(net_dev);
  684 + if (err)
  685 + goto err_netdev_init;
  686 +
  687 + debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
  688 + return 0;
  689 +
  690 +err_netdev_init:
  691 + free(priv);
  692 + net_dev->priv = NULL;
  693 + free(net_dev);
  694 +
  695 + return err;
  696 +}
drivers/net/ldpaa_eth/ldpaa_eth.h
  1 +/*
  2 + * Copyright (C) 2014 Freescale Semiconductor
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef __LDPAA_ETH_H
  8 +#define __LDPAA_ETH_H
  9 +
  10 +#include <linux/netdevice.h>
  11 +#include <fsl-mc/fsl_mc.h>
  12 +#include <fsl-mc/fsl_dpaa_fd.h>
  13 +#include <fsl-mc/fsl_dprc.h>
  14 +#include <fsl-mc/fsl_dpni.h>
  15 +#include <fsl-mc/fsl_dpbp.h>
  16 +#include <fsl-mc/fsl_dpio.h>
  17 +#include <fsl-mc/fsl_qbman_portal.h>
  18 +#include <fsl-mc/fsl_mc_private.h>
  19 +
  20 +
  21 +enum ldpaa_eth_type {
  22 + LDPAA_ETH_1G_E,
  23 + LDPAA_ETH_10G_E,
  24 +};
  25 +
  26 +/* Arbitrary values for now, but we'll need to tune */
  27 +#define LDPAA_ETH_NUM_BUFS (2 * 7)
  28 +#define LDPAA_ETH_REFILL_THRESH (LDPAA_ETH_NUM_BUFS/2)
  29 +#define LDPAA_ETH_RX_BUFFER_SIZE 2048
  30 +
  31 +/* Hardware requires alignment for ingress/egress buffer addresses
  32 + * and ingress buffer lengths.
  33 + */
  34 +#define LDPAA_ETH_BUF_ALIGN 64
  35 +
  36 +/* So far we're only accomodating a skb backpointer in the frame's
  37 + * software annotation, but the hardware options are either 0 or 64.
  38 + */
  39 +#define LDPAA_ETH_SWA_SIZE 64
  40 +
  41 +/* Annotation valid bits in FD FRC */
  42 +#define LDPAA_FD_FRC_FASV 0x8000
  43 +#define LDPAA_FD_FRC_FAEADV 0x4000
  44 +#define LDPAA_FD_FRC_FAPRV 0x2000
  45 +#define LDPAA_FD_FRC_FAIADV 0x1000
  46 +#define LDPAA_FD_FRC_FASWOV 0x0800
  47 +#define LDPAA_FD_FRC_FAICFDV 0x0400
  48 +
  49 +/* Annotation bits in FD CTRL */
  50 +#define LDPAA_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */
  51 +#define LDPAA_FD_CTRL_PTA 0x00800000
  52 +#define LDPAA_FD_CTRL_PTV1 0x00400000
  53 +
  54 +/* TODO: we may want to move this and other WRIOP related defines
  55 + * to a separate header
  56 + */
  57 +/* Frame annotation status */
  58 +struct ldpaa_fas {
  59 + u8 reserved;
  60 + u8 ppid;
  61 + __le16 ifpid;
  62 + __le32 status;
  63 +} __packed;
  64 +
  65 +/* Debug frame, otherwise supposed to be discarded */
  66 +#define LDPAA_ETH_FAS_DISC 0x80000000
  67 +/* MACSEC frame */
  68 +#define LDPAA_ETH_FAS_MS 0x40000000
  69 +#define LDPAA_ETH_FAS_PTP 0x08000000
  70 +/* Ethernet multicast frame */
  71 +#define LDPAA_ETH_FAS_MC 0x04000000
  72 +/* Ethernet broadcast frame */
  73 +#define LDPAA_ETH_FAS_BC 0x02000000
  74 +#define LDPAA_ETH_FAS_KSE 0x00040000
  75 +#define LDPAA_ETH_FAS_EOFHE 0x00020000
  76 +#define LDPAA_ETH_FAS_MNLE 0x00010000
  77 +#define LDPAA_ETH_FAS_TIDE 0x00008000
  78 +#define LDPAA_ETH_FAS_PIEE 0x00004000
  79 +/* Frame length error */
  80 +#define LDPAA_ETH_FAS_FLE 0x00002000
  81 +/* Frame physical error; our favourite pastime */
  82 +#define LDPAA_ETH_FAS_FPE 0x00001000
  83 +#define LDPAA_ETH_FAS_PTE 0x00000080
  84 +#define LDPAA_ETH_FAS_ISP 0x00000040
  85 +#define LDPAA_ETH_FAS_PHE 0x00000020
  86 +#define LDPAA_ETH_FAS_BLE 0x00000010
  87 +/* L3 csum validation performed */
  88 +#define LDPAA_ETH_FAS_L3CV 0x00000008
  89 +/* L3 csum error */
  90 +#define LDPAA_ETH_FAS_L3CE 0x00000004
  91 +/* L4 csum validation performed */
  92 +#define LDPAA_ETH_FAS_L4CV 0x00000002
  93 +/* L4 csum error */
  94 +#define LDPAA_ETH_FAS_L4CE 0x00000001
  95 +/* These bits always signal errors */
  96 +#define LDPAA_ETH_RX_ERR_MASK (LDPAA_ETH_FAS_DISC | \
  97 + LDPAA_ETH_FAS_KSE | \
  98 + LDPAA_ETH_FAS_EOFHE | \
  99 + LDPAA_ETH_FAS_MNLE | \
  100 + LDPAA_ETH_FAS_TIDE | \
  101 + LDPAA_ETH_FAS_PIEE | \
  102 + LDPAA_ETH_FAS_FLE | \
  103 + LDPAA_ETH_FAS_FPE | \
  104 + LDPAA_ETH_FAS_PTE | \
  105 + LDPAA_ETH_FAS_ISP | \
  106 + LDPAA_ETH_FAS_PHE | \
  107 + LDPAA_ETH_FAS_BLE | \
  108 + LDPAA_ETH_FAS_L3CE | \
  109 + LDPAA_ETH_FAS_L4CE)
  110 +/* Unsupported features in the ingress */
  111 +#define LDPAA_ETH_RX_UNSUPP_MASK LDPAA_ETH_FAS_MS
  112 +/* TODO trim down the bitmask; not all of them apply to Tx-confirm */
  113 +#define LDPAA_ETH_TXCONF_ERR_MASK (LDPAA_ETH_FAS_KSE | \
  114 + LDPAA_ETH_FAS_EOFHE | \
  115 + LDPAA_ETH_FAS_MNLE | \
  116 + LDPAA_ETH_FAS_TIDE)
  117 +
  118 +struct ldpaa_eth_priv {
  119 + struct eth_device *net_dev;
  120 + int dpni_id;
  121 + uint16_t dpni_handle;
  122 + struct dpni_attr dpni_attrs;
  123 + /* Insofar as the MC is concerned, we're using one layout on all 3 types
  124 + * of buffers (Rx, Tx, Tx-Conf).
  125 + */
  126 + struct dpni_buffer_layout buf_layout;
  127 + uint16_t tx_data_offset;
  128 +
  129 + uint32_t rx_dflt_fqid;
  130 + uint16_t tx_qdid;
  131 + uint32_t tx_conf_fqid;
  132 + uint16_t tx_flow_id;
  133 +
  134 + enum ldpaa_eth_type type; /* 1G or 10G ethernet */
  135 + phy_interface_t enet_if;
  136 + struct mii_dev *bus;
  137 + struct phy_device *phydev;
  138 + int phyaddr;
  139 +
  140 +};
  141 +
  142 +extern struct fsl_mc_io *dflt_mc_io;
  143 +extern struct fsl_dpbp_obj *dflt_dpbp;
  144 +extern struct fsl_dpio_obj *dflt_dpio;
  145 +
  146 +static void ldpaa_dpbp_drain_cnt(int count);
  147 +static void ldpaa_dpbp_drain(void);
  148 +static int ldpaa_dpbp_seed(uint16_t bpid);
  149 +static void ldpaa_dpbp_free(void);
  150 +static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv);
  151 +static int ldpaa_dpbp_setup(void);
  152 +static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv);
  153 +#endif /* __LDPAA_H */
include/fsl-mc/fsl_mc_private.h
... ... @@ -16,6 +16,7 @@
16 16  
17 17 #include <fsl-mc/fsl_mc_sys.h>
18 18 #include <fsl-mc/fsl_mc_cmd.h>
  19 +#include <fsl-mc/fsl_dprc.h>
19 20 #include <fsl-mc/fsl_dpbp.h>
20 21  
21 22 extern struct fsl_mc_io *dflt_mc_io;
... ... @@ -45,5 +46,6 @@
45 46 extern struct fsl_dpio_obj *dflt_dpio;
46 47  
47 48 int mc_init(void);
  49 +int ldpaa_eth_init(struct dprc_obj_desc obj_desc);
48 50 #endif /* _FSL_MC_PRIVATE_H_ */