X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fnet%2Fldpaa_eth%2Fldpaa_eth.c;h=725173f6273789323ba097c5a1661c0ba1ce1468;hb=401d1c4f5d2d29c4bc4beaec95402ca23eb63295;hp=7f96883d347de6a1a44c0f4f07d666b515dc7164;hpb=cd85bec36d0e0d16fedb00e0c434ed070a9c6b37;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 7f96883..725173f 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -1,109 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2014 Freescale Semiconductor - * - * SPDX-License-Identifier: GPL-2.0+ + * Copyright 2014-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP */ #include -#include -#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include #include +#include +#include +#include #include -#include - +#include +#include #include "ldpaa_eth.h" -#undef CONFIG_PHYLIB -static int init_phy(struct eth_device *dev) +#ifdef CONFIG_PHYLIB +#ifdef CONFIG_DM_ETH +static void init_phy(struct udevice *dev) { - /*TODO for external PHY */ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); - return 0; -} + priv->phy = dm_eth_phy_connect(dev); -#ifdef DEBUG -static void ldpaa_eth_get_dpni_counter(void) + if (!priv->phy) + return; + + phy_config(priv->phy); +} +#else +static int init_phy(struct eth_device *dev) { - int err = 0; - u64 value; + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; + struct phy_device *phydev = NULL; + struct mii_dev *bus; + int phy_addr, phy_num; + int ret = 0; - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n"); - return; - } - printf("DPNI_CNT_ING_FRAME=%lld\n", value); + bus = wriop_get_mdio(priv->dpmac_id); + if (bus == NULL) + return 0; - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_BYTE, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n"); - return; - } - printf("DPNI_CNT_ING_BYTE=%lld\n", value); + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num); + if (phy_addr < 0) + continue; - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME_DROP , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n"); - return; + phydev = phy_connect(bus, phy_addr, dev, + wriop_get_enet_if(priv->dpmac_id)); + if (!phydev) { + printf("Failed to connect\n"); + ret = -ENODEV; + break; + } + wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev); + ret = phy_config(phydev); + if (ret) + break; } - printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value); - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME_DISCARD, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n"); - return; - } - printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value); + if (ret) { + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (!phydev) + continue; - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_FRAME, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n"); - return; + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL); + } } - printf("DPNI_CNT_EGR_FRAME=%lld\n", value); - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_BYTE , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n"); - return; + return ret; +} +#endif +#endif + +#ifdef DEBUG + +#define DPNI_STATS_PER_PAGE 6 + +static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = { + { + "DPNI_CNT_ING_ALL_FRAMES", + "DPNI_CNT_ING_ALL_BYTES", + "DPNI_CNT_ING_MCAST_FRAMES", + "DPNI_CNT_ING_MCAST_BYTES", + "DPNI_CNT_ING_BCAST_FRAMES", + "DPNI_CNT_ING_BCAST_BYTES", + }, { + "DPNI_CNT_EGR_ALL_FRAMES", + "DPNI_CNT_EGR_ALL_BYTES", + "DPNI_CNT_EGR_MCAST_FRAMES", + "DPNI_CNT_EGR_MCAST_BYTES", + "DPNI_CNT_EGR_BCAST_FRAMES", + "DPNI_CNT_EGR_BCAST_BYTES", + }, { + "DPNI_CNT_ING_FILTERED_FRAMES", + "DPNI_CNT_ING_DISCARDED_FRAMES", + "DPNI_CNT_ING_NOBUFFER_DISCARDS", + "DPNI_CNT_EGR_DISCARDED_FRAMES", + "DPNI_CNT_EGR_CNF_FRAMES", + "" + }, +}; + +static void print_dpni_stats(const char *strings[], + struct dpni_statistics dpni_stats) +{ + uint64_t *stat; + int i; + + stat = (uint64_t *)&dpni_stats; + for (i = 0; i < DPNI_STATS_PER_PAGE; i++) { + if (strcmp(strings[i], "\0") == 0) + break; + printf("%s= %llu\n", strings[i], *stat); + stat++; } - printf("DPNI_CNT_EGR_BYTE =%lld\n", value); +} - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_FRAME_DISCARD , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n"); - return; +static void ldpaa_eth_get_dpni_counter(void) +{ + int err = 0; + unsigned int page = 0; + struct dpni_statistics dpni_stats; + + printf("DPNI counters ..\n"); + for (page = 0; page < 3; page++) { + err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, page, + &dpni_stats); + if (err < 0) { + printf("dpni_get_statistics: failed:"); + printf("%d for page[%d]\n", err, page); + return; + } + print_dpni_stats(dpni_statistics[page], dpni_stats); } - printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value); } +#ifdef CONFIG_DM_ETH +static void ldpaa_eth_get_dpmac_counter(struct udevice *dev) +{ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); +#else static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; +#endif int err = 0; u64 value; @@ -115,6 +167,7 @@ static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev) printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n"); return; } + printf("\nDPMAC counters ..\n"); printf("DPMAC_CNT_ING_BYTE=%lld\n", value); err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, @@ -235,9 +288,16 @@ error: return; } +#ifdef CONFIG_DM_ETH +static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev, + int flags, uchar **packetp) +{ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); +#else static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; +#endif const struct ldpaa_dq *dq; const struct dpaa_fd *fd; int i = 5, err = 0, status; @@ -294,9 +354,15 @@ static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) return err; } +#ifdef CONFIG_DM_ETH +static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len) +{ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); +#else static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; +#endif struct dpaa_fd fd; u64 buffer_start; int data_offset, err; @@ -317,7 +383,7 @@ static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) &buffer_start, 1); } while (err == -EBUSY); - if (err < 0) { + if (err <= 0) { printf("qbman_swp_acquire() failed\n"); return -ENOMEM; } @@ -372,18 +438,101 @@ error: return err; } -static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) +static struct phy_device *ldpaa_get_phydev(struct ldpaa_eth_priv *priv) +{ +#ifdef CONFIG_DM_ETH + return priv->phy; +#else +#ifdef CONFIG_PHYLIB + struct phy_device *phydev = NULL; + int phy_num; + + /* start the phy devices one by one and update the dpmac state */ + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (phydev) + return phydev; + } + return NULL; +#endif + return NULL; +#endif +} + +static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, + struct dpmac_link_state *state) +{ + phy_interface_t enet_if; + struct phy_device *phydev = NULL; + int err; + + /* let's start off with maximum capabilities */ + enet_if = wriop_get_enet_if(priv->dpmac_id); + switch (enet_if) { + case PHY_INTERFACE_MODE_XGMII: + state->rate = SPEED_10000; + break; + default: + state->rate = SPEED_1000; + break; + } + + state->up = 1; + state->options |= DPMAC_LINK_OPT_AUTONEG; + phydev = ldpaa_get_phydev(priv); + + if (phydev) { + err = phy_startup(phydev); + if (err) { + printf("%s: Could not initialize\n", phydev->dev->name); + state->up = 0; + } else if (phydev->link) { + state->rate = min(state->rate, (uint32_t)phydev->speed); + if (!phydev->duplex) + state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; + if (!phydev->autoneg) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + } else { + state->up = 0; + } + } + + if (!phydev) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + + if (!state->up) { + state->rate = 0; + state->options = 0; + return -ENOLINK; + } + + return 0; +} + +#ifdef CONFIG_DM_ETH +static int ldpaa_eth_open(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_plat(dev); + struct ldpaa_eth_priv *priv = dev_get_priv(dev); +#else +static int ldpaa_eth_open(struct eth_device *net_dev, struct bd_info *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; - struct dpni_queue_attr rx_queue_attr; +#endif struct dpmac_link_state dpmac_link_state = { 0 }; #ifdef DEBUG struct dpni_link_state link_state; #endif - int err; + int err = 0; + struct dpni_queue d_queue; +#ifdef CONFIG_DM_ETH + if (eth_is_active(dev)) + return 0; +#else if (net_dev->state == ETH_STATE_ACTIVE) return 0; +#endif if (get_mc_boot_status() != 0) { printf("ERROR (MC is not booted)\n"); @@ -394,15 +543,20 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) printf("ERROR (DPL is deployed. No device available)\n"); return -ENODEV; } + /* DPMAC initialization */ err = ldpaa_dpmac_setup(priv); if (err < 0) goto err_dpmac_setup; + err = ldpaa_get_dpmac_state(priv, &dpmac_link_state); + if (err < 0) + goto err_dpmac_bind; + /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err) - goto err_dpamc_bind; + goto err_dpmac_bind; /* DPNI initialization */ err = ldpaa_dpni_setup(priv); @@ -418,35 +572,24 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err) goto err_dpni_bind; +#ifdef CONFIG_DM_ETH + err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, plat->enetaddr); +#else err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, net_dev->enetaddr); +#endif if (err) { printf("dpni_add_mac_addr() failed\n"); return err; } -#ifdef CONFIG_PHYLIB - /* TODO Check this path */ - err = phy_startup(priv->phydev); - if (err) { - printf("%s: Could not initialize\n", priv->phydev->dev->name); - return err; - } -#else - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; -#endif - err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); if (err < 0) { printf("dpni_enable() failed\n"); return err; } - dpmac_link_state.rate = SPEED_1000; - dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG; - dpmac_link_state.up = 1; err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -455,6 +598,10 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) } #ifdef DEBUG + printf("DPMAC link status: %d - ", dpmac_link_state.up); + dpmac_link_state.up == 0 ? printf("down\n") : + dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n"); + err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &link_state); if (err < 0) { @@ -462,20 +609,21 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - printf("link status: %d - ", link_state.up); + printf("DPNI link status: %d - ", link_state.up); link_state.up == 0 ? printf("down\n") : link_state.up == 1 ? printf("up\n") : printf("error state\n"); #endif - /* TODO: support multiple Rx flows */ - err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr); + memset(&d_queue, 0, sizeof(struct dpni_queue)); + err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, DPNI_QUEUE_RX, + 0, 0, &d_queue); if (err) { - printf("dpni_get_rx_flow() failed\n"); - goto err_rx_flow; + printf("dpni_get_queue failed\n"); + goto err_get_queue; } - priv->rx_dflt_fqid = rx_queue_attr.fqid; + priv->rx_dflt_fqid = d_queue.fqid; err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &priv->tx_qdid); @@ -484,44 +632,68 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - if (!priv->phydev->link) - printf("%s: No link.\n", priv->phydev->dev->name); - - return priv->phydev->link ? 0 : -1; + return dpmac_link_state.up; err_qdid: -err_rx_flow: +err_get_queue: dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_bind: ldpaa_dpbp_free(); err_dpbp_setup: -err_dpamc_bind: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: +err_dpmac_bind: + dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, priv->dpmac_id); err_dpmac_setup: return err; } +#ifdef CONFIG_DM_ETH +static void ldpaa_eth_stop(struct udevice *dev) +{ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); +#else static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; +#endif + struct phy_device *phydev = NULL; int err = 0; +#ifdef CONFIG_DM_ETH + if (!eth_is_active(dev)) + return; +#else if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) return; +#endif #ifdef DEBUG ldpaa_eth_get_dpni_counter(); +#ifdef CONFIG_DM_ETH + ldpaa_eth_get_dpmac_counter(dev); +#else ldpaa_eth_get_dpmac_counter(net_dev); #endif +#endif err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle, &dpmac_endpoint); if (err < 0) printf("dprc_disconnect() failed dpmac_endpoint\n"); - err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + if (err < 0) + printf("dpmac_close() failed\n"); + + err = dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + priv->dpmac_id); if (err < 0) printf("dpmac_destroy() failed\n"); @@ -530,13 +702,20 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) if (err < 0) printf("dpni_disable() failed\n"); -#ifdef CONFIG_PHYLIB - phy_shutdown(priv->phydev); -#endif + phydev = ldpaa_get_phydev(priv); + if (phydev) + phy_shutdown(phydev); + /* Free DPBP handle and reset. */ ldpaa_dpbp_free(); + dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); + if (err < 0) + printf("dpni_reset() failed\n"); + dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); + if (err < 0) + printf("dpni_close() failed\n"); } static void ldpaa_dpbp_drain_cnt(int count) @@ -652,6 +831,7 @@ static int ldpaa_dpbp_setup(void) } err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); + if (err) { printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); @@ -680,21 +860,19 @@ static void ldpaa_dpbp_free(void) static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io, struct ldpaa_eth_priv *priv) { - struct dpmac_attr attr; int error; - - memset(&attr, 0, sizeof(struct dpmac_attr)); - error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS, - priv->dpmac_handle, - &attr); - if (error == 0) { - if ((attr.version.major != DPMAC_VER_MAJOR) || - (attr.version.minor != DPMAC_VER_MINOR)) { - printf("DPMAC version mismatch found %u.%u,", - attr.version.major, attr.version.minor); - printf("supported version is %u.%u\n", - DPMAC_VER_MAJOR, DPMAC_VER_MINOR); - } + uint16_t major_ver, minor_ver; + + error = dpmac_get_api_version(dflt_mc_io, 0, + &major_ver, + &minor_ver); + if ((major_ver < DPMAC_VER_MAJOR) || + (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) { + printf("DPMAC version mismatch found %u.%u,", + major_ver, minor_ver); + printf("supported version is %u.%u\n", + DPMAC_VER_MAJOR, DPMAC_VER_MINOR); + return error; } return error; @@ -706,14 +884,36 @@ static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv) struct dpmac_cfg dpmac_cfg; dpmac_cfg.mac_id = priv->dpmac_id; - err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg, - &priv->dpmac_handle); + + err = dpmac_create(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, &dpmac_cfg, + &priv->dpmac_id); if (err) printf("dpmac_create() failed\n"); err = ldpaa_dpmac_version_check(dflt_mc_io, priv); - if (err < 0) + if (err < 0) { printf("ldpaa_dpmac_version_check() failed: %d\n", err); + goto err_version_check; + } + + err = dpmac_open(dflt_mc_io, + MC_CMD_NO_FLAGS, + priv->dpmac_id, + &priv->dpmac_handle); + if (err < 0) { + printf("dpmac_open() failed: %d\n", err); + goto err_open; + } + + return err; + +err_open: +err_version_check: + dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, priv->dpmac_id); return err; } @@ -779,7 +979,6 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) printf("dpni_open() failed\n"); goto err_open; } - err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &dflt_dpni->dpni_attrs); @@ -798,12 +997,13 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; /* HW erratum mandates data alignment in multiples of 256 */ dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN; + /* ...rx, ... */ - err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, DPNI_QUEUE_RX); if (err) { - printf("dpni_set_rx_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } @@ -811,21 +1011,22 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) /* remove Rx-only options */ dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | DPNI_BUF_LAYOUT_OPT_PARSER_RESULT); - err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, DPNI_QUEUE_TX); if (err) { - printf("dpni_set_tx_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } /* ... tx-confirm. */ dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; - err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, + DPNI_QUEUE_TX_CONFIRM); if (err) { - printf("dpni_set_tx_conf_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } @@ -860,10 +1061,10 @@ err_open: static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) { struct dpni_pools_cfg pools_params; - struct dpni_tx_flow_cfg dflt_tx_flow; - struct dpni_tx_conf_cfg tx_conf_cfg; + struct dpni_queue tx_queue; int err = 0; + memset(&pools_params, 0, sizeof(pools_params)); pools_params.num_dpbp = 1; pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id; pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE; @@ -874,55 +1075,149 @@ static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) return err; } - priv->tx_flow_id = DPNI_NEW_FLOW_ID; - memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); + memset(&tx_queue, 0, sizeof(struct dpni_queue)); + + err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + DPNI_QUEUE_TX, 0, 0, &tx_queue); - dflt_tx_flow.use_common_tx_conf_queue = 0; - err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, &priv->tx_flow_id, - &dflt_tx_flow); if (err) { - printf("dpni_set_tx_flow() failed\n"); + printf("dpni_set_queue() failed\n"); return err; } - memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg)); - tx_conf_cfg.errors_only = true; - /*Set tx-conf and error configuration*/ - err = dpni_set_tx_conf(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - priv->tx_flow_id, &tx_conf_cfg); + err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + DPNI_CONF_DISABLE); if (err) { - printf("dpni_set_tx_conf() failed\n"); + printf("dpni_set_tx_confirmation_mode() failed\n"); return err; } return 0; } +#ifdef CONFIG_DM_ETH +static int ldpaa_eth_probe(struct udevice *dev) +{ + struct ofnode_phandle_args phandle; + + /* Nothing to do if there is no "phy-handle" in the DTS node */ + if (dev_read_phandle_with_args(dev, "phy-handle", NULL, + 0, 0, &phandle)) { + return 0; + } + + init_phy(dev); + + return 0; +} + +static uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev) +{ + int port_node = dev_of_offset(dev); + + return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1); +} + +static const char *ldpaa_eth_get_phy_mode_str(struct udevice *dev) +{ + int port_node = dev_of_offset(dev); + const char *phy_mode_str; + + phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, + "phy-connection-type", NULL); + if (phy_mode_str) + return phy_mode_str; + + phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL); + return phy_mode_str; +} + +static int ldpaa_eth_bind(struct udevice *dev) +{ + const char *phy_mode_str = NULL; + uint32_t dpmac_id; + char eth_name[16]; + int phy_mode = -1; + + phy_mode_str = ldpaa_eth_get_phy_mode_str(dev); + if (phy_mode_str) + phy_mode = phy_get_interface_by_name(phy_mode_str); + if (phy_mode == -1) { + dev_err(dev, "incorrect phy mode\n"); + return -EINVAL; + } + + dpmac_id = ldpaa_eth_get_dpmac_id(dev); + if (dpmac_id == -1) { + dev_err(dev, "missing reg field from the dpmac node\n"); + return -EINVAL; + } + + sprintf(eth_name, "DPMAC%d@%s", dpmac_id, phy_mode_str); + device_set_name(dev, eth_name); + + return 0; +} + +static int ldpaa_eth_of_to_plat(struct udevice *dev) +{ + struct ldpaa_eth_priv *priv = dev_get_priv(dev); + const char *phy_mode_str; + + priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev); + phy_mode_str = ldpaa_eth_get_phy_mode_str(dev); + priv->phy_mode = phy_get_interface_by_name(phy_mode_str); + + return 0; +} + +static const struct eth_ops ldpaa_eth_ops = { + .start = ldpaa_eth_open, + .send = ldpaa_eth_tx, + .recv = ldpaa_eth_pull_dequeue_rx, + .stop = ldpaa_eth_stop, +}; + +static const struct udevice_id ldpaa_eth_of_ids[] = { + { .compatible = "fsl,qoriq-mc-dpmac" }, +}; + +U_BOOT_DRIVER(ldpaa_eth) = { + .name = "ldpaa_eth", + .id = UCLASS_ETH, + .of_match = ldpaa_eth_of_ids, + .of_to_plat = ldpaa_eth_of_to_plat, + .bind = ldpaa_eth_bind, + .probe = ldpaa_eth_probe, + .ops = &ldpaa_eth_ops, + .priv_auto = sizeof(struct ldpaa_eth_priv), + .plat_auto = sizeof(struct eth_pdata), +}; + +#else + static int ldpaa_eth_netdev_init(struct eth_device *net_dev, phy_interface_t enet_if) { int err; struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; - sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id, - phy_interface_strings[enet_if]); + snprintf(net_dev->name, ETH_NAME_LEN, "DPMAC%d@%s", priv->dpmac_id, + phy_interface_strings[enet_if]); net_dev->iobase = 0; net_dev->init = ldpaa_eth_open; net_dev->halt = ldpaa_eth_stop; net_dev->send = ldpaa_eth_tx; net_dev->recv = ldpaa_eth_pull_dequeue_rx; -/* - TODO: PHY MDIO information - priv->bus = info->bus; - priv->phyaddr = info->phy_addr; - priv->enet_if = info->enet_if; -*/ - if (init_phy(net_dev)) - return 0; +#ifdef CONFIG_PHYLIB + err = init_phy(net_dev); + if (err < 0) + return err; +#endif err = eth_register(net_dev); if (err < 0) { @@ -939,7 +1234,6 @@ int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if) struct ldpaa_eth_priv *priv = NULL; int err = 0; - /* Net device */ net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!net_dev) { @@ -952,6 +1246,7 @@ int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if) priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv)); if (!priv) { printf("ldpaa_eth_priv malloc() failed\n"); + free(net_dev); return -ENOMEM; } memset(priv, 0, sizeof(struct ldpaa_eth_priv)); @@ -975,3 +1270,4 @@ err_netdev_init: return err; } +#endif