1c517771aSPrabhakar Kushwaha /* 2c517771aSPrabhakar Kushwaha * Copyright (C) 2014 Freescale Semiconductor 3c517771aSPrabhakar Kushwaha * 4c517771aSPrabhakar Kushwaha * SPDX-License-Identifier: GPL-2.0+ 5c517771aSPrabhakar Kushwaha */ 6c517771aSPrabhakar Kushwaha 7c517771aSPrabhakar Kushwaha #include <common.h> 8c517771aSPrabhakar Kushwaha #include <asm/io.h> 9c517771aSPrabhakar Kushwaha #include <asm/types.h> 10c517771aSPrabhakar Kushwaha #include <malloc.h> 11c517771aSPrabhakar Kushwaha #include <net.h> 12c517771aSPrabhakar Kushwaha #include <hwconfig.h> 13c517771aSPrabhakar Kushwaha #include <phy.h> 14c517771aSPrabhakar Kushwaha #include <linux/compat.h> 15c919ab9eSPrabhakar Kushwaha #include <fsl-mc/fsl_dpmac.h> 16c517771aSPrabhakar Kushwaha 17c517771aSPrabhakar Kushwaha #include "ldpaa_eth.h" 18c517771aSPrabhakar Kushwaha 195753b0f1SPrabhakar Kushwaha #undef CONFIG_PHYLIB 20c517771aSPrabhakar Kushwaha static int init_phy(struct eth_device *dev) 21c517771aSPrabhakar Kushwaha { 22c517771aSPrabhakar Kushwaha /*TODO for external PHY */ 23c517771aSPrabhakar Kushwaha 24c517771aSPrabhakar Kushwaha return 0; 25c517771aSPrabhakar Kushwaha } 26c517771aSPrabhakar Kushwaha 275038d3e5SPrabhakar Kushwaha #ifdef DEBUG 285038d3e5SPrabhakar Kushwaha static void ldpaa_eth_get_dpni_counter(void) 295038d3e5SPrabhakar Kushwaha { 305038d3e5SPrabhakar Kushwaha int err = 0; 315038d3e5SPrabhakar Kushwaha u64 value; 325038d3e5SPrabhakar Kushwaha 335038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 345038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 355038d3e5SPrabhakar Kushwaha DPNI_CNT_ING_FRAME, 365038d3e5SPrabhakar Kushwaha &value); 375038d3e5SPrabhakar Kushwaha if (err < 0) { 385038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n"); 395038d3e5SPrabhakar Kushwaha return; 405038d3e5SPrabhakar Kushwaha } 415038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_ING_FRAME=%lld\n", value); 425038d3e5SPrabhakar Kushwaha 435038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 445038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 455038d3e5SPrabhakar Kushwaha DPNI_CNT_ING_BYTE, 465038d3e5SPrabhakar Kushwaha &value); 475038d3e5SPrabhakar Kushwaha if (err < 0) { 485038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n"); 495038d3e5SPrabhakar Kushwaha return; 505038d3e5SPrabhakar Kushwaha } 515038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_ING_BYTE=%lld\n", value); 525038d3e5SPrabhakar Kushwaha 535038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 545038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 555038d3e5SPrabhakar Kushwaha DPNI_CNT_ING_FRAME_DROP , 565038d3e5SPrabhakar Kushwaha &value); 575038d3e5SPrabhakar Kushwaha if (err < 0) { 585038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n"); 595038d3e5SPrabhakar Kushwaha return; 605038d3e5SPrabhakar Kushwaha } 615038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value); 625038d3e5SPrabhakar Kushwaha 635038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 645038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 655038d3e5SPrabhakar Kushwaha DPNI_CNT_ING_FRAME_DISCARD, 665038d3e5SPrabhakar Kushwaha &value); 675038d3e5SPrabhakar Kushwaha if (err < 0) { 685038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n"); 695038d3e5SPrabhakar Kushwaha return; 705038d3e5SPrabhakar Kushwaha } 715038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value); 725038d3e5SPrabhakar Kushwaha 735038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 745038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 755038d3e5SPrabhakar Kushwaha DPNI_CNT_EGR_FRAME, 765038d3e5SPrabhakar Kushwaha &value); 775038d3e5SPrabhakar Kushwaha if (err < 0) { 785038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n"); 795038d3e5SPrabhakar Kushwaha return; 805038d3e5SPrabhakar Kushwaha } 815038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_EGR_FRAME=%lld\n", value); 825038d3e5SPrabhakar Kushwaha 835038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 845038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 855038d3e5SPrabhakar Kushwaha DPNI_CNT_EGR_BYTE , 865038d3e5SPrabhakar Kushwaha &value); 875038d3e5SPrabhakar Kushwaha if (err < 0) { 885038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n"); 895038d3e5SPrabhakar Kushwaha return; 905038d3e5SPrabhakar Kushwaha } 915038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_EGR_BYTE =%lld\n", value); 925038d3e5SPrabhakar Kushwaha 935038d3e5SPrabhakar Kushwaha err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, 945038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, 955038d3e5SPrabhakar Kushwaha DPNI_CNT_EGR_FRAME_DISCARD , 965038d3e5SPrabhakar Kushwaha &value); 975038d3e5SPrabhakar Kushwaha if (err < 0) { 985038d3e5SPrabhakar Kushwaha printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n"); 995038d3e5SPrabhakar Kushwaha return; 1005038d3e5SPrabhakar Kushwaha } 1015038d3e5SPrabhakar Kushwaha printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value); 1025038d3e5SPrabhakar Kushwaha } 1035038d3e5SPrabhakar Kushwaha #endif 1045038d3e5SPrabhakar Kushwaha 105c517771aSPrabhakar Kushwaha static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, 106c517771aSPrabhakar Kushwaha const struct dpaa_fd *fd) 107c517771aSPrabhakar Kushwaha { 108c517771aSPrabhakar Kushwaha u64 fd_addr; 109c517771aSPrabhakar Kushwaha uint16_t fd_offset; 110c517771aSPrabhakar Kushwaha uint32_t fd_length; 111c517771aSPrabhakar Kushwaha struct ldpaa_fas *fas; 112c517771aSPrabhakar Kushwaha uint32_t status, err; 11356c57cf7SPrabhakar Kushwaha u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; 11456c57cf7SPrabhakar Kushwaha u32 time_start; 115c517771aSPrabhakar Kushwaha struct qbman_release_desc releasedesc; 116c517771aSPrabhakar Kushwaha struct qbman_swp *swp = dflt_dpio->sw_portal; 117c517771aSPrabhakar Kushwaha 118c517771aSPrabhakar Kushwaha fd_addr = ldpaa_fd_get_addr(fd); 119c517771aSPrabhakar Kushwaha fd_offset = ldpaa_fd_get_offset(fd); 120c517771aSPrabhakar Kushwaha fd_length = ldpaa_fd_get_len(fd); 121c517771aSPrabhakar Kushwaha 122c517771aSPrabhakar Kushwaha debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length); 123c517771aSPrabhakar Kushwaha 124c517771aSPrabhakar Kushwaha if (fd->simple.frc & LDPAA_FD_FRC_FASV) { 125c517771aSPrabhakar Kushwaha /* Read the frame annotation status word and check for errors */ 126c517771aSPrabhakar Kushwaha fas = (struct ldpaa_fas *) 127c517771aSPrabhakar Kushwaha ((uint8_t *)(fd_addr) + 128c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.private_data_size); 129c517771aSPrabhakar Kushwaha status = le32_to_cpu(fas->status); 130c517771aSPrabhakar Kushwaha if (status & LDPAA_ETH_RX_ERR_MASK) { 131c517771aSPrabhakar Kushwaha printf("Rx frame error(s): 0x%08x\n", 132c517771aSPrabhakar Kushwaha status & LDPAA_ETH_RX_ERR_MASK); 133c517771aSPrabhakar Kushwaha goto error; 134c517771aSPrabhakar Kushwaha } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) { 135c517771aSPrabhakar Kushwaha printf("Unsupported feature in bitmask: 0x%08x\n", 136c517771aSPrabhakar Kushwaha status & LDPAA_ETH_RX_UNSUPP_MASK); 137c517771aSPrabhakar Kushwaha goto error; 138c517771aSPrabhakar Kushwaha } 139c517771aSPrabhakar Kushwaha } 140c517771aSPrabhakar Kushwaha 141c517771aSPrabhakar Kushwaha debug("Rx frame: To Upper layer\n"); 142c517771aSPrabhakar Kushwaha net_process_received_packet((uint8_t *)(fd_addr) + fd_offset, 143c517771aSPrabhakar Kushwaha fd_length); 144c517771aSPrabhakar Kushwaha 145c517771aSPrabhakar Kushwaha error: 1465753b0f1SPrabhakar Kushwaha flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); 147c517771aSPrabhakar Kushwaha qbman_release_desc_clear(&releasedesc); 148c517771aSPrabhakar Kushwaha qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 14956c57cf7SPrabhakar Kushwaha time_start = get_timer(0); 150c517771aSPrabhakar Kushwaha do { 151c517771aSPrabhakar Kushwaha /* Release buffer into the QBMAN */ 152c517771aSPrabhakar Kushwaha err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); 15356c57cf7SPrabhakar Kushwaha } while (get_timer(time_start) < timeo && err == -EBUSY); 15456c57cf7SPrabhakar Kushwaha 15556c57cf7SPrabhakar Kushwaha if (err == -EBUSY) 15656c57cf7SPrabhakar Kushwaha printf("Rx frame: QBMAN buffer release fails\n"); 15756c57cf7SPrabhakar Kushwaha 158c517771aSPrabhakar Kushwaha return; 159c517771aSPrabhakar Kushwaha } 160c517771aSPrabhakar Kushwaha 161c517771aSPrabhakar Kushwaha static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) 162c517771aSPrabhakar Kushwaha { 163c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; 164c517771aSPrabhakar Kushwaha const struct ldpaa_dq *dq; 165c517771aSPrabhakar Kushwaha const struct dpaa_fd *fd; 166b4c3a35dSPrabhakar Kushwaha int i = 5, err = 0, status; 167b4c3a35dSPrabhakar Kushwaha u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; 168b4c3a35dSPrabhakar Kushwaha u32 time_start; 169c517771aSPrabhakar Kushwaha static struct qbman_pull_desc pulldesc; 170c517771aSPrabhakar Kushwaha struct qbman_swp *swp = dflt_dpio->sw_portal; 171c517771aSPrabhakar Kushwaha 1725753b0f1SPrabhakar Kushwaha while (--i) { 173c517771aSPrabhakar Kushwaha qbman_pull_desc_clear(&pulldesc); 174c517771aSPrabhakar Kushwaha qbman_pull_desc_set_numframes(&pulldesc, 1); 175c517771aSPrabhakar Kushwaha qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid); 176c517771aSPrabhakar Kushwaha 177c517771aSPrabhakar Kushwaha err = qbman_swp_pull(swp, &pulldesc); 178c517771aSPrabhakar Kushwaha if (err < 0) { 179c517771aSPrabhakar Kushwaha printf("Dequeue frames error:0x%08x\n", err); 180c517771aSPrabhakar Kushwaha continue; 181c517771aSPrabhakar Kushwaha } 182c517771aSPrabhakar Kushwaha 183b4c3a35dSPrabhakar Kushwaha time_start = get_timer(0); 1845753b0f1SPrabhakar Kushwaha 185b4c3a35dSPrabhakar Kushwaha do { 186b4c3a35dSPrabhakar Kushwaha dq = qbman_swp_dqrr_next(swp); 187b4c3a35dSPrabhakar Kushwaha } while (get_timer(time_start) < timeo && !dq); 1885753b0f1SPrabhakar Kushwaha 189c517771aSPrabhakar Kushwaha if (dq) { 190c517771aSPrabhakar Kushwaha /* Check for valid frame. If not sent a consume 191c517771aSPrabhakar Kushwaha * confirmation to QBMAN otherwise give it to NADK 192c517771aSPrabhakar Kushwaha * application and then send consume confirmation to 193c517771aSPrabhakar Kushwaha * QBMAN. 194c517771aSPrabhakar Kushwaha */ 195c517771aSPrabhakar Kushwaha status = (uint8_t)ldpaa_dq_flags(dq); 196c517771aSPrabhakar Kushwaha if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { 197c517771aSPrabhakar Kushwaha debug("Dequeue RX frames:"); 198c517771aSPrabhakar Kushwaha debug("No frame delivered\n"); 199c517771aSPrabhakar Kushwaha 200c517771aSPrabhakar Kushwaha qbman_swp_dqrr_consume(swp, dq); 2010c7c87a4SPrabhakar Kushwaha continue; 202c517771aSPrabhakar Kushwaha } 203c517771aSPrabhakar Kushwaha 204c517771aSPrabhakar Kushwaha fd = ldpaa_dq_fd(dq); 205c517771aSPrabhakar Kushwaha 206c517771aSPrabhakar Kushwaha /* Obtain FD and process it */ 207c517771aSPrabhakar Kushwaha ldpaa_eth_rx(priv, fd); 208c517771aSPrabhakar Kushwaha qbman_swp_dqrr_consume(swp, dq); 209c517771aSPrabhakar Kushwaha break; 210b4c3a35dSPrabhakar Kushwaha } else { 211b4c3a35dSPrabhakar Kushwaha err = -ENODATA; 212b4c3a35dSPrabhakar Kushwaha debug("No DQRR entries\n"); 213b4c3a35dSPrabhakar Kushwaha break; 214c517771aSPrabhakar Kushwaha } 215c517771aSPrabhakar Kushwaha } 216c517771aSPrabhakar Kushwaha 217c517771aSPrabhakar Kushwaha return err; 218c517771aSPrabhakar Kushwaha } 219c517771aSPrabhakar Kushwaha 220c517771aSPrabhakar Kushwaha static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) 221c517771aSPrabhakar Kushwaha { 222c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 223c517771aSPrabhakar Kushwaha struct dpaa_fd fd; 224c517771aSPrabhakar Kushwaha u64 buffer_start; 225c517771aSPrabhakar Kushwaha int data_offset, err; 226e48df52bSPrabhakar Kushwaha u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; 227e48df52bSPrabhakar Kushwaha u32 time_start; 228c517771aSPrabhakar Kushwaha struct qbman_swp *swp = dflt_dpio->sw_portal; 229c517771aSPrabhakar Kushwaha struct qbman_eq_desc ed; 230e48df52bSPrabhakar Kushwaha struct qbman_release_desc releasedesc; 231c517771aSPrabhakar Kushwaha 232c517771aSPrabhakar Kushwaha /* Setup the FD fields */ 233c517771aSPrabhakar Kushwaha memset(&fd, 0, sizeof(fd)); 234c517771aSPrabhakar Kushwaha 235c517771aSPrabhakar Kushwaha data_offset = priv->tx_data_offset; 236c517771aSPrabhakar Kushwaha 237c517771aSPrabhakar Kushwaha do { 238c517771aSPrabhakar Kushwaha err = qbman_swp_acquire(dflt_dpio->sw_portal, 239c517771aSPrabhakar Kushwaha dflt_dpbp->dpbp_attr.bpid, 240c517771aSPrabhakar Kushwaha &buffer_start, 1); 241c517771aSPrabhakar Kushwaha } while (err == -EBUSY); 242c517771aSPrabhakar Kushwaha 243c517771aSPrabhakar Kushwaha if (err < 0) { 244c517771aSPrabhakar Kushwaha printf("qbman_swp_acquire() failed\n"); 245c517771aSPrabhakar Kushwaha return -ENOMEM; 246c517771aSPrabhakar Kushwaha } 247c517771aSPrabhakar Kushwaha 248c517771aSPrabhakar Kushwaha debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start); 249c517771aSPrabhakar Kushwaha 250c517771aSPrabhakar Kushwaha memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len); 251c517771aSPrabhakar Kushwaha 2525753b0f1SPrabhakar Kushwaha flush_dcache_range(buffer_start, buffer_start + 2535753b0f1SPrabhakar Kushwaha LDPAA_ETH_RX_BUFFER_SIZE); 254c517771aSPrabhakar Kushwaha 255c517771aSPrabhakar Kushwaha ldpaa_fd_set_addr(&fd, (u64)buffer_start); 256c517771aSPrabhakar Kushwaha ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset)); 257c517771aSPrabhakar Kushwaha ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid); 258c517771aSPrabhakar Kushwaha ldpaa_fd_set_len(&fd, len); 259c517771aSPrabhakar Kushwaha 260c517771aSPrabhakar Kushwaha fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA | 261c517771aSPrabhakar Kushwaha LDPAA_FD_CTRL_PTV1; 262c517771aSPrabhakar Kushwaha 263c517771aSPrabhakar Kushwaha qbman_eq_desc_clear(&ed); 264c517771aSPrabhakar Kushwaha qbman_eq_desc_set_no_orp(&ed, 0); 265c517771aSPrabhakar Kushwaha qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); 266e48df52bSPrabhakar Kushwaha 267e48df52bSPrabhakar Kushwaha time_start = get_timer(0); 268e48df52bSPrabhakar Kushwaha 269e48df52bSPrabhakar Kushwaha while (get_timer(time_start) < timeo) { 270e48df52bSPrabhakar Kushwaha err = qbman_swp_enqueue(swp, &ed, 271e48df52bSPrabhakar Kushwaha (const struct qbman_fd *)(&fd)); 272e48df52bSPrabhakar Kushwaha if (err != -EBUSY) 273e48df52bSPrabhakar Kushwaha break; 274e48df52bSPrabhakar Kushwaha } 275e48df52bSPrabhakar Kushwaha 276e48df52bSPrabhakar Kushwaha if (err < 0) { 277c517771aSPrabhakar Kushwaha printf("error enqueueing Tx frame\n"); 278e48df52bSPrabhakar Kushwaha goto error; 279e48df52bSPrabhakar Kushwaha } 280c517771aSPrabhakar Kushwaha 281c517771aSPrabhakar Kushwaha return err; 282e48df52bSPrabhakar Kushwaha 283e48df52bSPrabhakar Kushwaha error: 284e48df52bSPrabhakar Kushwaha qbman_release_desc_clear(&releasedesc); 285e48df52bSPrabhakar Kushwaha qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); 286e48df52bSPrabhakar Kushwaha time_start = get_timer(0); 287e48df52bSPrabhakar Kushwaha do { 288e48df52bSPrabhakar Kushwaha /* Release buffer into the QBMAN */ 289e48df52bSPrabhakar Kushwaha err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1); 290e48df52bSPrabhakar Kushwaha } while (get_timer(time_start) < timeo && err == -EBUSY); 291e48df52bSPrabhakar Kushwaha 292e48df52bSPrabhakar Kushwaha if (err == -EBUSY) 293e48df52bSPrabhakar Kushwaha printf("TX data: QBMAN buffer release fails\n"); 294e48df52bSPrabhakar Kushwaha 295e48df52bSPrabhakar Kushwaha return err; 296c517771aSPrabhakar Kushwaha } 297c517771aSPrabhakar Kushwaha 298c517771aSPrabhakar Kushwaha static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) 299c517771aSPrabhakar Kushwaha { 300c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 301c517771aSPrabhakar Kushwaha struct dpni_queue_attr rx_queue_attr; 302c919ab9eSPrabhakar Kushwaha struct dpmac_link_state dpmac_link_state = { 0 }; 3035038d3e5SPrabhakar Kushwaha #ifdef DEBUG 3045038d3e5SPrabhakar Kushwaha struct dpni_link_state link_state; 3055038d3e5SPrabhakar Kushwaha #endif 306c517771aSPrabhakar Kushwaha int err; 307c517771aSPrabhakar Kushwaha 308c517771aSPrabhakar Kushwaha if (net_dev->state == ETH_STATE_ACTIVE) 309c517771aSPrabhakar Kushwaha return 0; 310c517771aSPrabhakar Kushwaha 311c919ab9eSPrabhakar Kushwaha if (get_mc_boot_status() != 0) { 312c919ab9eSPrabhakar Kushwaha printf("ERROR (MC is not booted)\n"); 313c919ab9eSPrabhakar Kushwaha return -ENODEV; 314c919ab9eSPrabhakar Kushwaha } 315c919ab9eSPrabhakar Kushwaha 316c919ab9eSPrabhakar Kushwaha if (get_dpl_apply_status() == 0) { 317c919ab9eSPrabhakar Kushwaha printf("ERROR (DPL is deployed. No device available)\n"); 318c919ab9eSPrabhakar Kushwaha return -ENODEV; 319c919ab9eSPrabhakar Kushwaha } 320c919ab9eSPrabhakar Kushwaha /* DPMAC initialization */ 321c919ab9eSPrabhakar Kushwaha err = ldpaa_dpmac_setup(priv); 322c919ab9eSPrabhakar Kushwaha if (err < 0) 323c919ab9eSPrabhakar Kushwaha goto err_dpmac_setup; 324c919ab9eSPrabhakar Kushwaha 325c919ab9eSPrabhakar Kushwaha /* DPMAC binding DPNI */ 326c919ab9eSPrabhakar Kushwaha err = ldpaa_dpmac_bind(priv); 327c919ab9eSPrabhakar Kushwaha if (err) 328c919ab9eSPrabhakar Kushwaha goto err_dpamc_bind; 329c919ab9eSPrabhakar Kushwaha 330c517771aSPrabhakar Kushwaha /* DPNI initialization */ 331c517771aSPrabhakar Kushwaha err = ldpaa_dpni_setup(priv); 332c517771aSPrabhakar Kushwaha if (err < 0) 333c517771aSPrabhakar Kushwaha goto err_dpni_setup; 334c517771aSPrabhakar Kushwaha 335c517771aSPrabhakar Kushwaha err = ldpaa_dpbp_setup(); 336c517771aSPrabhakar Kushwaha if (err < 0) 337c517771aSPrabhakar Kushwaha goto err_dpbp_setup; 338c517771aSPrabhakar Kushwaha 339c517771aSPrabhakar Kushwaha /* DPNI binding DPBP */ 340c517771aSPrabhakar Kushwaha err = ldpaa_dpni_bind(priv); 341c517771aSPrabhakar Kushwaha if (err) 342c919ab9eSPrabhakar Kushwaha goto err_dpni_bind; 343c517771aSPrabhakar Kushwaha 3447b2edb8bSPrabhakar Kushwaha err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, 345c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, net_dev->enetaddr); 346c517771aSPrabhakar Kushwaha if (err) { 3477b2edb8bSPrabhakar Kushwaha printf("dpni_add_mac_addr() failed\n"); 348c517771aSPrabhakar Kushwaha return err; 349c517771aSPrabhakar Kushwaha } 350c517771aSPrabhakar Kushwaha 351c517771aSPrabhakar Kushwaha #ifdef CONFIG_PHYLIB 352c517771aSPrabhakar Kushwaha /* TODO Check this path */ 3535753b0f1SPrabhakar Kushwaha err = phy_startup(priv->phydev); 3545753b0f1SPrabhakar Kushwaha if (err) { 355c517771aSPrabhakar Kushwaha printf("%s: Could not initialize\n", priv->phydev->dev->name); 3565753b0f1SPrabhakar Kushwaha return err; 357c517771aSPrabhakar Kushwaha } 358c517771aSPrabhakar Kushwaha #else 359c517771aSPrabhakar Kushwaha priv->phydev->speed = SPEED_1000; 360c517771aSPrabhakar Kushwaha priv->phydev->link = 1; 361c517771aSPrabhakar Kushwaha priv->phydev->duplex = DUPLEX_FULL; 362c517771aSPrabhakar Kushwaha #endif 363c517771aSPrabhakar Kushwaha 364c919ab9eSPrabhakar Kushwaha err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 365c517771aSPrabhakar Kushwaha if (err < 0) { 366c517771aSPrabhakar Kushwaha printf("dpni_enable() failed\n"); 367c517771aSPrabhakar Kushwaha return err; 368c517771aSPrabhakar Kushwaha } 369c517771aSPrabhakar Kushwaha 370c919ab9eSPrabhakar Kushwaha dpmac_link_state.rate = SPEED_1000; 371c919ab9eSPrabhakar Kushwaha dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG; 372c919ab9eSPrabhakar Kushwaha dpmac_link_state.up = 1; 373c919ab9eSPrabhakar Kushwaha err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, 374c919ab9eSPrabhakar Kushwaha priv->dpmac_handle, &dpmac_link_state); 375c919ab9eSPrabhakar Kushwaha if (err < 0) { 376c919ab9eSPrabhakar Kushwaha printf("dpmac_set_link_state() failed\n"); 377c919ab9eSPrabhakar Kushwaha return err; 378c919ab9eSPrabhakar Kushwaha } 3795038d3e5SPrabhakar Kushwaha 3805038d3e5SPrabhakar Kushwaha #ifdef DEBUG 3815038d3e5SPrabhakar Kushwaha err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, 3825038d3e5SPrabhakar Kushwaha dflt_dpni->dpni_handle, &link_state); 3835038d3e5SPrabhakar Kushwaha if (err < 0) { 3845038d3e5SPrabhakar Kushwaha printf("dpni_get_link_state() failed\n"); 3855038d3e5SPrabhakar Kushwaha return err; 3865038d3e5SPrabhakar Kushwaha } 3875038d3e5SPrabhakar Kushwaha 3885038d3e5SPrabhakar Kushwaha printf("link status: %d - ", link_state.up); 3895038d3e5SPrabhakar Kushwaha link_state.up == 0 ? printf("down\n") : 3905038d3e5SPrabhakar Kushwaha link_state.up == 1 ? printf("up\n") : printf("error state\n"); 3915038d3e5SPrabhakar Kushwaha #endif 3925038d3e5SPrabhakar Kushwaha 393c517771aSPrabhakar Kushwaha /* TODO: support multiple Rx flows */ 394c919ab9eSPrabhakar Kushwaha err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, 395c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr); 396c517771aSPrabhakar Kushwaha if (err) { 397c517771aSPrabhakar Kushwaha printf("dpni_get_rx_flow() failed\n"); 398c517771aSPrabhakar Kushwaha goto err_rx_flow; 399c517771aSPrabhakar Kushwaha } 400c517771aSPrabhakar Kushwaha 401c517771aSPrabhakar Kushwaha priv->rx_dflt_fqid = rx_queue_attr.fqid; 402c517771aSPrabhakar Kushwaha 403c919ab9eSPrabhakar Kushwaha err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, 40487457d11SPrabhakar Kushwaha &priv->tx_qdid); 405c517771aSPrabhakar Kushwaha if (err) { 406c517771aSPrabhakar Kushwaha printf("dpni_get_qdid() failed\n"); 407c517771aSPrabhakar Kushwaha goto err_qdid; 408c517771aSPrabhakar Kushwaha } 409c517771aSPrabhakar Kushwaha 410c517771aSPrabhakar Kushwaha if (!priv->phydev->link) 411c517771aSPrabhakar Kushwaha printf("%s: No link.\n", priv->phydev->dev->name); 412c517771aSPrabhakar Kushwaha 413c517771aSPrabhakar Kushwaha return priv->phydev->link ? 0 : -1; 414c517771aSPrabhakar Kushwaha 415c517771aSPrabhakar Kushwaha err_qdid: 416c517771aSPrabhakar Kushwaha err_rx_flow: 417c919ab9eSPrabhakar Kushwaha dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 418c919ab9eSPrabhakar Kushwaha err_dpni_bind: 419c517771aSPrabhakar Kushwaha ldpaa_dpbp_free(); 420c517771aSPrabhakar Kushwaha err_dpbp_setup: 421c919ab9eSPrabhakar Kushwaha err_dpamc_bind: 422c919ab9eSPrabhakar Kushwaha dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 423c517771aSPrabhakar Kushwaha err_dpni_setup: 424c919ab9eSPrabhakar Kushwaha err_dpmac_setup: 425c517771aSPrabhakar Kushwaha return err; 426c517771aSPrabhakar Kushwaha } 427c517771aSPrabhakar Kushwaha 428c517771aSPrabhakar Kushwaha static void ldpaa_eth_stop(struct eth_device *net_dev) 429c517771aSPrabhakar Kushwaha { 430c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 431c517771aSPrabhakar Kushwaha int err = 0; 432c517771aSPrabhakar Kushwaha 4335753b0f1SPrabhakar Kushwaha if ((net_dev->state == ETH_STATE_PASSIVE) || 4345753b0f1SPrabhakar Kushwaha (net_dev->state == ETH_STATE_INIT)) 435c517771aSPrabhakar Kushwaha return; 436c919ab9eSPrabhakar Kushwaha 4375038d3e5SPrabhakar Kushwaha #ifdef DEBUG 4385038d3e5SPrabhakar Kushwaha ldpaa_eth_get_dpni_counter(); 4395038d3e5SPrabhakar Kushwaha #endif 4405038d3e5SPrabhakar Kushwaha 441c919ab9eSPrabhakar Kushwaha err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS, 442c919ab9eSPrabhakar Kushwaha dflt_dprc_handle, &dpmac_endpoint); 443c919ab9eSPrabhakar Kushwaha if (err < 0) 444c919ab9eSPrabhakar Kushwaha printf("dprc_disconnect() failed dpmac_endpoint\n"); 445c919ab9eSPrabhakar Kushwaha 446c919ab9eSPrabhakar Kushwaha err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); 447c919ab9eSPrabhakar Kushwaha if (err < 0) 448c919ab9eSPrabhakar Kushwaha printf("dpmac_destroy() failed\n"); 449c919ab9eSPrabhakar Kushwaha 450c517771aSPrabhakar Kushwaha /* Stop Tx and Rx traffic */ 451c919ab9eSPrabhakar Kushwaha err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 452c517771aSPrabhakar Kushwaha if (err < 0) 453c517771aSPrabhakar Kushwaha printf("dpni_disable() failed\n"); 454c517771aSPrabhakar Kushwaha 455c517771aSPrabhakar Kushwaha #ifdef CONFIG_PHYLIB 456c517771aSPrabhakar Kushwaha phy_shutdown(priv->phydev); 457c517771aSPrabhakar Kushwaha #endif 458c517771aSPrabhakar Kushwaha 459c517771aSPrabhakar Kushwaha ldpaa_dpbp_free(); 460c919ab9eSPrabhakar Kushwaha dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 461c919ab9eSPrabhakar Kushwaha dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 462c517771aSPrabhakar Kushwaha } 463c517771aSPrabhakar Kushwaha 464c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_drain_cnt(int count) 465c517771aSPrabhakar Kushwaha { 466c517771aSPrabhakar Kushwaha uint64_t buf_array[7]; 467c517771aSPrabhakar Kushwaha void *addr; 468c517771aSPrabhakar Kushwaha int ret, i; 469c517771aSPrabhakar Kushwaha 470c517771aSPrabhakar Kushwaha BUG_ON(count > 7); 471c517771aSPrabhakar Kushwaha 472c517771aSPrabhakar Kushwaha do { 473c517771aSPrabhakar Kushwaha ret = qbman_swp_acquire(dflt_dpio->sw_portal, 474c517771aSPrabhakar Kushwaha dflt_dpbp->dpbp_attr.bpid, 475c517771aSPrabhakar Kushwaha buf_array, count); 476c517771aSPrabhakar Kushwaha if (ret < 0) { 477c517771aSPrabhakar Kushwaha printf("qbman_swp_acquire() failed\n"); 478c517771aSPrabhakar Kushwaha return; 479c517771aSPrabhakar Kushwaha } 480c517771aSPrabhakar Kushwaha for (i = 0; i < ret; i++) { 481c517771aSPrabhakar Kushwaha addr = (void *)buf_array[i]; 482c517771aSPrabhakar Kushwaha debug("Free: buffer addr =0x%p\n", addr); 483c517771aSPrabhakar Kushwaha free(addr); 484c517771aSPrabhakar Kushwaha } 485c517771aSPrabhakar Kushwaha } while (ret); 486c517771aSPrabhakar Kushwaha } 487c517771aSPrabhakar Kushwaha 488c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_drain(void) 489c517771aSPrabhakar Kushwaha { 490c517771aSPrabhakar Kushwaha int i; 491c517771aSPrabhakar Kushwaha for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) 492c517771aSPrabhakar Kushwaha ldpaa_dpbp_drain_cnt(7); 493c517771aSPrabhakar Kushwaha } 494c517771aSPrabhakar Kushwaha 495c517771aSPrabhakar Kushwaha static int ldpaa_bp_add_7(uint16_t bpid) 496c517771aSPrabhakar Kushwaha { 497c517771aSPrabhakar Kushwaha uint64_t buf_array[7]; 498c517771aSPrabhakar Kushwaha u8 *addr; 499c517771aSPrabhakar Kushwaha int i; 500c517771aSPrabhakar Kushwaha struct qbman_release_desc rd; 501c517771aSPrabhakar Kushwaha 502c517771aSPrabhakar Kushwaha for (i = 0; i < 7; i++) { 503*14480454SPrabhakar Kushwaha addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE); 504c517771aSPrabhakar Kushwaha if (!addr) { 505c517771aSPrabhakar Kushwaha printf("addr allocation failed\n"); 506c517771aSPrabhakar Kushwaha goto err_alloc; 507c517771aSPrabhakar Kushwaha } 508c517771aSPrabhakar Kushwaha memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE); 5095753b0f1SPrabhakar Kushwaha flush_dcache_range((u64)addr, 5105753b0f1SPrabhakar Kushwaha (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE)); 511c517771aSPrabhakar Kushwaha 512c517771aSPrabhakar Kushwaha buf_array[i] = (uint64_t)addr; 513c517771aSPrabhakar Kushwaha debug("Release: buffer addr =0x%p\n", addr); 514c517771aSPrabhakar Kushwaha } 515c517771aSPrabhakar Kushwaha 516c517771aSPrabhakar Kushwaha release_bufs: 517c517771aSPrabhakar Kushwaha /* In case the portal is busy, retry until successful. 518c517771aSPrabhakar Kushwaha * This function is guaranteed to succeed in a reasonable amount 519c517771aSPrabhakar Kushwaha * of time. 520c517771aSPrabhakar Kushwaha */ 521c517771aSPrabhakar Kushwaha 522c517771aSPrabhakar Kushwaha do { 523c517771aSPrabhakar Kushwaha mdelay(1); 524c517771aSPrabhakar Kushwaha qbman_release_desc_clear(&rd); 525c517771aSPrabhakar Kushwaha qbman_release_desc_set_bpid(&rd, bpid); 526c517771aSPrabhakar Kushwaha } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i)); 527c517771aSPrabhakar Kushwaha 528c517771aSPrabhakar Kushwaha return i; 529c517771aSPrabhakar Kushwaha 530c517771aSPrabhakar Kushwaha err_alloc: 531c517771aSPrabhakar Kushwaha if (i) 532c517771aSPrabhakar Kushwaha goto release_bufs; 533c517771aSPrabhakar Kushwaha 534c517771aSPrabhakar Kushwaha return 0; 535c517771aSPrabhakar Kushwaha } 536c517771aSPrabhakar Kushwaha 537c517771aSPrabhakar Kushwaha static int ldpaa_dpbp_seed(uint16_t bpid) 538c517771aSPrabhakar Kushwaha { 539c517771aSPrabhakar Kushwaha int i; 540c517771aSPrabhakar Kushwaha int count; 541c517771aSPrabhakar Kushwaha 542c517771aSPrabhakar Kushwaha for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) { 543c517771aSPrabhakar Kushwaha count = ldpaa_bp_add_7(bpid); 544c517771aSPrabhakar Kushwaha if (count < 7) 545c517771aSPrabhakar Kushwaha printf("Buffer Seed= %d\n", count); 546c517771aSPrabhakar Kushwaha } 547c517771aSPrabhakar Kushwaha 548c517771aSPrabhakar Kushwaha return 0; 549c517771aSPrabhakar Kushwaha } 550c517771aSPrabhakar Kushwaha 551c517771aSPrabhakar Kushwaha static int ldpaa_dpbp_setup(void) 552c517771aSPrabhakar Kushwaha { 553c517771aSPrabhakar Kushwaha int err; 554c517771aSPrabhakar Kushwaha 55587457d11SPrabhakar Kushwaha err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id, 556c517771aSPrabhakar Kushwaha &dflt_dpbp->dpbp_handle); 557c517771aSPrabhakar Kushwaha if (err) { 558c517771aSPrabhakar Kushwaha printf("dpbp_open() failed\n"); 559c517771aSPrabhakar Kushwaha goto err_open; 560c517771aSPrabhakar Kushwaha } 561c517771aSPrabhakar Kushwaha 56287457d11SPrabhakar Kushwaha err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 563c517771aSPrabhakar Kushwaha if (err) { 564c517771aSPrabhakar Kushwaha printf("dpbp_enable() failed\n"); 565c517771aSPrabhakar Kushwaha goto err_enable; 566c517771aSPrabhakar Kushwaha } 567c517771aSPrabhakar Kushwaha 56887457d11SPrabhakar Kushwaha err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 56987457d11SPrabhakar Kushwaha dflt_dpbp->dpbp_handle, 570c517771aSPrabhakar Kushwaha &dflt_dpbp->dpbp_attr); 571c517771aSPrabhakar Kushwaha if (err) { 572c517771aSPrabhakar Kushwaha printf("dpbp_get_attributes() failed\n"); 573c517771aSPrabhakar Kushwaha goto err_get_attr; 574c517771aSPrabhakar Kushwaha } 575c517771aSPrabhakar Kushwaha 576c517771aSPrabhakar Kushwaha err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); 577c517771aSPrabhakar Kushwaha if (err) { 578c517771aSPrabhakar Kushwaha printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", 579c517771aSPrabhakar Kushwaha dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); 580c517771aSPrabhakar Kushwaha goto err_seed; 581c517771aSPrabhakar Kushwaha } 582c517771aSPrabhakar Kushwaha 583c517771aSPrabhakar Kushwaha return 0; 584c517771aSPrabhakar Kushwaha 585c517771aSPrabhakar Kushwaha err_seed: 586c517771aSPrabhakar Kushwaha err_get_attr: 58787457d11SPrabhakar Kushwaha dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 588c517771aSPrabhakar Kushwaha err_enable: 58987457d11SPrabhakar Kushwaha dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 590c517771aSPrabhakar Kushwaha err_open: 591c517771aSPrabhakar Kushwaha return err; 592c517771aSPrabhakar Kushwaha } 593c517771aSPrabhakar Kushwaha 594c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_free(void) 595c517771aSPrabhakar Kushwaha { 596c517771aSPrabhakar Kushwaha ldpaa_dpbp_drain(); 59787457d11SPrabhakar Kushwaha dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 59887457d11SPrabhakar Kushwaha dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 59987457d11SPrabhakar Kushwaha dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); 600c517771aSPrabhakar Kushwaha } 601c517771aSPrabhakar Kushwaha 602c919ab9eSPrabhakar Kushwaha static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv) 603c919ab9eSPrabhakar Kushwaha { 604c919ab9eSPrabhakar Kushwaha int err = 0; 605c919ab9eSPrabhakar Kushwaha struct dpmac_cfg dpmac_cfg; 606c919ab9eSPrabhakar Kushwaha 607c919ab9eSPrabhakar Kushwaha dpmac_cfg.mac_id = priv->dpmac_id; 608c919ab9eSPrabhakar Kushwaha err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg, 609c919ab9eSPrabhakar Kushwaha &priv->dpmac_handle); 610c919ab9eSPrabhakar Kushwaha if (err) 611c919ab9eSPrabhakar Kushwaha printf("dpmac_create() failed\n"); 612c919ab9eSPrabhakar Kushwaha return err; 613c919ab9eSPrabhakar Kushwaha } 614c919ab9eSPrabhakar Kushwaha 615c919ab9eSPrabhakar Kushwaha static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv) 616c919ab9eSPrabhakar Kushwaha { 617c919ab9eSPrabhakar Kushwaha int err = 0; 618c919ab9eSPrabhakar Kushwaha struct dprc_connection_cfg dprc_connection_cfg = { 619c919ab9eSPrabhakar Kushwaha /* If both rates are zero the connection */ 620c919ab9eSPrabhakar Kushwaha /* will be configured in "best effort" mode. */ 621c919ab9eSPrabhakar Kushwaha .committed_rate = 0, 622c919ab9eSPrabhakar Kushwaha .max_rate = 0 623c919ab9eSPrabhakar Kushwaha }; 624c919ab9eSPrabhakar Kushwaha 6255038d3e5SPrabhakar Kushwaha #ifdef DEBUG 6265038d3e5SPrabhakar Kushwaha struct dprc_endpoint dbg_endpoint; 6275038d3e5SPrabhakar Kushwaha int state = 0; 6285038d3e5SPrabhakar Kushwaha #endif 6295038d3e5SPrabhakar Kushwaha 630c919ab9eSPrabhakar Kushwaha memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint)); 631c919ab9eSPrabhakar Kushwaha sprintf(dpmac_endpoint.type, "dpmac"); 632c919ab9eSPrabhakar Kushwaha dpmac_endpoint.id = priv->dpmac_id; 633c919ab9eSPrabhakar Kushwaha 634c919ab9eSPrabhakar Kushwaha memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint)); 635c919ab9eSPrabhakar Kushwaha sprintf(dpni_endpoint.type, "dpni"); 636c919ab9eSPrabhakar Kushwaha dpni_endpoint.id = dflt_dpni->dpni_id; 637c919ab9eSPrabhakar Kushwaha 638c919ab9eSPrabhakar Kushwaha err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS, 639c919ab9eSPrabhakar Kushwaha dflt_dprc_handle, 640c919ab9eSPrabhakar Kushwaha &dpmac_endpoint, 641c919ab9eSPrabhakar Kushwaha &dpni_endpoint, 642c919ab9eSPrabhakar Kushwaha &dprc_connection_cfg); 6435038d3e5SPrabhakar Kushwaha if (err) 6445038d3e5SPrabhakar Kushwaha printf("dprc_connect() failed\n"); 6455038d3e5SPrabhakar Kushwaha 6465038d3e5SPrabhakar Kushwaha #ifdef DEBUG 6475038d3e5SPrabhakar Kushwaha err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS, 6485038d3e5SPrabhakar Kushwaha dflt_dprc_handle, &dpni_endpoint, 6495038d3e5SPrabhakar Kushwaha &dbg_endpoint, &state); 6505038d3e5SPrabhakar Kushwaha printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type); 6515038d3e5SPrabhakar Kushwaha printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id); 6525038d3e5SPrabhakar Kushwaha printf("%s, DPMAC State= %d\n", __func__, state); 6535038d3e5SPrabhakar Kushwaha 6545038d3e5SPrabhakar Kushwaha memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint)); 6555038d3e5SPrabhakar Kushwaha err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS, 6565038d3e5SPrabhakar Kushwaha dflt_dprc_handle, &dpmac_endpoint, 6575038d3e5SPrabhakar Kushwaha &dbg_endpoint, &state); 6585038d3e5SPrabhakar Kushwaha printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type); 6595038d3e5SPrabhakar Kushwaha printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id); 6605038d3e5SPrabhakar Kushwaha printf("%s, DPNI State= %d\n", __func__, state); 6615038d3e5SPrabhakar Kushwaha #endif 662c919ab9eSPrabhakar Kushwaha return err; 663c919ab9eSPrabhakar Kushwaha } 664c919ab9eSPrabhakar Kushwaha 665c517771aSPrabhakar Kushwaha static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) 666c517771aSPrabhakar Kushwaha { 667c517771aSPrabhakar Kushwaha int err; 668c517771aSPrabhakar Kushwaha 669c517771aSPrabhakar Kushwaha /* and get a handle for the DPNI this interface is associate with */ 670c919ab9eSPrabhakar Kushwaha err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id, 671c919ab9eSPrabhakar Kushwaha &dflt_dpni->dpni_handle); 672c517771aSPrabhakar Kushwaha if (err) { 673c517771aSPrabhakar Kushwaha printf("dpni_open() failed\n"); 674c517771aSPrabhakar Kushwaha goto err_open; 675c517771aSPrabhakar Kushwaha } 676c517771aSPrabhakar Kushwaha 67787457d11SPrabhakar Kushwaha err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, 678c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 679c919ab9eSPrabhakar Kushwaha &dflt_dpni->dpni_attrs); 680c517771aSPrabhakar Kushwaha if (err) { 681c517771aSPrabhakar Kushwaha printf("dpni_get_attributes() failed (err=%d)\n", err); 682c517771aSPrabhakar Kushwaha goto err_get_attr; 683c517771aSPrabhakar Kushwaha } 684c517771aSPrabhakar Kushwaha 685c517771aSPrabhakar Kushwaha /* Configure our buffers' layout */ 686c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | 687c517771aSPrabhakar Kushwaha DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | 688*14480454SPrabhakar Kushwaha DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE | 689*14480454SPrabhakar Kushwaha DPNI_BUF_LAYOUT_OPT_DATA_ALIGN; 690c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.pass_parser_result = true; 691c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.pass_frame_status = true; 692c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; 693*14480454SPrabhakar Kushwaha /* HW erratum mandates data alignment in multiples of 256 */ 694*14480454SPrabhakar Kushwaha dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN; 695c517771aSPrabhakar Kushwaha /* ...rx, ... */ 69687457d11SPrabhakar Kushwaha err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 697c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 698c919ab9eSPrabhakar Kushwaha &dflt_dpni->buf_layout); 699c517771aSPrabhakar Kushwaha if (err) { 700c517771aSPrabhakar Kushwaha printf("dpni_set_rx_buffer_layout() failed"); 701c517771aSPrabhakar Kushwaha goto err_buf_layout; 702c517771aSPrabhakar Kushwaha } 703c517771aSPrabhakar Kushwaha 704c517771aSPrabhakar Kushwaha /* ... tx, ... */ 705*14480454SPrabhakar Kushwaha /* remove Rx-only options */ 706*14480454SPrabhakar Kushwaha dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | 707*14480454SPrabhakar Kushwaha DPNI_BUF_LAYOUT_OPT_PARSER_RESULT); 70887457d11SPrabhakar Kushwaha err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 709c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 710c919ab9eSPrabhakar Kushwaha &dflt_dpni->buf_layout); 711c517771aSPrabhakar Kushwaha if (err) { 712c517771aSPrabhakar Kushwaha printf("dpni_set_tx_buffer_layout() failed"); 713c517771aSPrabhakar Kushwaha goto err_buf_layout; 714c517771aSPrabhakar Kushwaha } 715c517771aSPrabhakar Kushwaha 716c517771aSPrabhakar Kushwaha /* ... tx-confirm. */ 717c919ab9eSPrabhakar Kushwaha dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; 71887457d11SPrabhakar Kushwaha err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, 719c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 720c919ab9eSPrabhakar Kushwaha &dflt_dpni->buf_layout); 721c517771aSPrabhakar Kushwaha if (err) { 722c517771aSPrabhakar Kushwaha printf("dpni_set_tx_conf_buffer_layout() failed"); 723c517771aSPrabhakar Kushwaha goto err_buf_layout; 724c517771aSPrabhakar Kushwaha } 725c517771aSPrabhakar Kushwaha 726c517771aSPrabhakar Kushwaha /* Now that we've set our tx buffer layout, retrieve the minimum 727c517771aSPrabhakar Kushwaha * required tx data offset. 728c517771aSPrabhakar Kushwaha */ 72987457d11SPrabhakar Kushwaha err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS, 730c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, 731c919ab9eSPrabhakar Kushwaha &priv->tx_data_offset); 732c517771aSPrabhakar Kushwaha if (err) { 733c517771aSPrabhakar Kushwaha printf("dpni_get_tx_data_offset() failed\n"); 734c517771aSPrabhakar Kushwaha goto err_data_offset; 735c517771aSPrabhakar Kushwaha } 736c517771aSPrabhakar Kushwaha 737c517771aSPrabhakar Kushwaha /* Warn in case TX data offset is not multiple of 64 bytes. */ 738c517771aSPrabhakar Kushwaha WARN_ON(priv->tx_data_offset % 64); 739c517771aSPrabhakar Kushwaha 740c517771aSPrabhakar Kushwaha /* Accomodate SWA space. */ 741c517771aSPrabhakar Kushwaha priv->tx_data_offset += LDPAA_ETH_SWA_SIZE; 742c517771aSPrabhakar Kushwaha debug("priv->tx_data_offset=%d\n", priv->tx_data_offset); 743c517771aSPrabhakar Kushwaha 744c517771aSPrabhakar Kushwaha return 0; 745c517771aSPrabhakar Kushwaha 746c517771aSPrabhakar Kushwaha err_data_offset: 747c517771aSPrabhakar Kushwaha err_buf_layout: 748c517771aSPrabhakar Kushwaha err_get_attr: 749c919ab9eSPrabhakar Kushwaha dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); 750c517771aSPrabhakar Kushwaha err_open: 751c517771aSPrabhakar Kushwaha return err; 752c517771aSPrabhakar Kushwaha } 753c517771aSPrabhakar Kushwaha 754c517771aSPrabhakar Kushwaha static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) 755c517771aSPrabhakar Kushwaha { 756c517771aSPrabhakar Kushwaha struct dpni_pools_cfg pools_params; 757c517771aSPrabhakar Kushwaha struct dpni_tx_flow_cfg dflt_tx_flow; 758c517771aSPrabhakar Kushwaha int err = 0; 759c517771aSPrabhakar Kushwaha 760c517771aSPrabhakar Kushwaha pools_params.num_dpbp = 1; 761c517771aSPrabhakar Kushwaha pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id; 762c517771aSPrabhakar Kushwaha pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE; 763c919ab9eSPrabhakar Kushwaha err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS, 764c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, &pools_params); 765c517771aSPrabhakar Kushwaha if (err) { 766c517771aSPrabhakar Kushwaha printf("dpni_set_pools() failed\n"); 767c517771aSPrabhakar Kushwaha return err; 768c517771aSPrabhakar Kushwaha } 769c517771aSPrabhakar Kushwaha 770c517771aSPrabhakar Kushwaha priv->tx_flow_id = DPNI_NEW_FLOW_ID; 771c517771aSPrabhakar Kushwaha memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); 772c517771aSPrabhakar Kushwaha 7730c7c87a4SPrabhakar Kushwaha dflt_tx_flow.options = DPNI_TX_FLOW_OPT_ONLY_TX_ERROR; 7740c7c87a4SPrabhakar Kushwaha dflt_tx_flow.conf_err_cfg.use_default_queue = 0; 7750c7c87a4SPrabhakar Kushwaha dflt_tx_flow.conf_err_cfg.errors_only = 1; 776c919ab9eSPrabhakar Kushwaha err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, 777c919ab9eSPrabhakar Kushwaha dflt_dpni->dpni_handle, &priv->tx_flow_id, 778c919ab9eSPrabhakar Kushwaha &dflt_tx_flow); 779c517771aSPrabhakar Kushwaha if (err) { 780c517771aSPrabhakar Kushwaha printf("dpni_set_tx_flow() failed\n"); 781c517771aSPrabhakar Kushwaha return err; 782c517771aSPrabhakar Kushwaha } 783c517771aSPrabhakar Kushwaha 784c517771aSPrabhakar Kushwaha return 0; 785c517771aSPrabhakar Kushwaha } 786c517771aSPrabhakar Kushwaha 787c919ab9eSPrabhakar Kushwaha static int ldpaa_eth_netdev_init(struct eth_device *net_dev, 788c919ab9eSPrabhakar Kushwaha phy_interface_t enet_if) 789c517771aSPrabhakar Kushwaha { 790c517771aSPrabhakar Kushwaha int err; 791c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; 792c517771aSPrabhakar Kushwaha 793c919ab9eSPrabhakar Kushwaha sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id, 794c919ab9eSPrabhakar Kushwaha phy_interface_strings[enet_if]); 795c517771aSPrabhakar Kushwaha 796c517771aSPrabhakar Kushwaha net_dev->iobase = 0; 797c517771aSPrabhakar Kushwaha net_dev->init = ldpaa_eth_open; 798c517771aSPrabhakar Kushwaha net_dev->halt = ldpaa_eth_stop; 799c517771aSPrabhakar Kushwaha net_dev->send = ldpaa_eth_tx; 800c517771aSPrabhakar Kushwaha net_dev->recv = ldpaa_eth_pull_dequeue_rx; 801c517771aSPrabhakar Kushwaha /* 802c517771aSPrabhakar Kushwaha TODO: PHY MDIO information 803c517771aSPrabhakar Kushwaha priv->bus = info->bus; 804c517771aSPrabhakar Kushwaha priv->phyaddr = info->phy_addr; 805c517771aSPrabhakar Kushwaha priv->enet_if = info->enet_if; 806c517771aSPrabhakar Kushwaha */ 807c517771aSPrabhakar Kushwaha 808c517771aSPrabhakar Kushwaha if (init_phy(net_dev)) 809c517771aSPrabhakar Kushwaha return 0; 810c517771aSPrabhakar Kushwaha 811c517771aSPrabhakar Kushwaha err = eth_register(net_dev); 812c517771aSPrabhakar Kushwaha if (err < 0) { 813c517771aSPrabhakar Kushwaha printf("eth_register() = %d\n", err); 814c517771aSPrabhakar Kushwaha return err; 815c517771aSPrabhakar Kushwaha } 816c517771aSPrabhakar Kushwaha 817c517771aSPrabhakar Kushwaha return 0; 818c517771aSPrabhakar Kushwaha } 819c517771aSPrabhakar Kushwaha 820c919ab9eSPrabhakar Kushwaha int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if) 821c517771aSPrabhakar Kushwaha { 822c517771aSPrabhakar Kushwaha struct eth_device *net_dev = NULL; 823c517771aSPrabhakar Kushwaha struct ldpaa_eth_priv *priv = NULL; 824c517771aSPrabhakar Kushwaha int err = 0; 825c517771aSPrabhakar Kushwaha 826c517771aSPrabhakar Kushwaha 827c517771aSPrabhakar Kushwaha /* Net device */ 828c517771aSPrabhakar Kushwaha net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); 829c517771aSPrabhakar Kushwaha if (!net_dev) { 830c517771aSPrabhakar Kushwaha printf("eth_device malloc() failed\n"); 831c517771aSPrabhakar Kushwaha return -ENOMEM; 832c517771aSPrabhakar Kushwaha } 833c517771aSPrabhakar Kushwaha memset(net_dev, 0, sizeof(struct eth_device)); 834c517771aSPrabhakar Kushwaha 835c517771aSPrabhakar Kushwaha /* alloc the ldpaa ethernet private struct */ 836c517771aSPrabhakar Kushwaha priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv)); 837c517771aSPrabhakar Kushwaha if (!priv) { 838c517771aSPrabhakar Kushwaha printf("ldpaa_eth_priv malloc() failed\n"); 839c517771aSPrabhakar Kushwaha return -ENOMEM; 840c517771aSPrabhakar Kushwaha } 841c517771aSPrabhakar Kushwaha memset(priv, 0, sizeof(struct ldpaa_eth_priv)); 842c517771aSPrabhakar Kushwaha 843c517771aSPrabhakar Kushwaha net_dev->priv = (void *)priv; 844c517771aSPrabhakar Kushwaha priv->net_dev = (struct eth_device *)net_dev; 845c919ab9eSPrabhakar Kushwaha priv->dpmac_id = dpmac_id; 846c919ab9eSPrabhakar Kushwaha debug("%s dpmac_id=%d\n", __func__, dpmac_id); 847c517771aSPrabhakar Kushwaha 848c919ab9eSPrabhakar Kushwaha err = ldpaa_eth_netdev_init(net_dev, enet_if); 849c517771aSPrabhakar Kushwaha if (err) 850c517771aSPrabhakar Kushwaha goto err_netdev_init; 851c517771aSPrabhakar Kushwaha 852c517771aSPrabhakar Kushwaha debug("ldpaa ethernet: Probed interface %s\n", net_dev->name); 853c517771aSPrabhakar Kushwaha return 0; 854c517771aSPrabhakar Kushwaha 855c517771aSPrabhakar Kushwaha err_netdev_init: 856c517771aSPrabhakar Kushwaha free(priv); 857c517771aSPrabhakar Kushwaha net_dev->priv = NULL; 858c517771aSPrabhakar Kushwaha free(net_dev); 859c517771aSPrabhakar Kushwaha 860c517771aSPrabhakar Kushwaha return err; 861c517771aSPrabhakar Kushwaha } 862