diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/dc2114x.c | 1 | ||||
-rw-r--r-- | drivers/net/eepro100.c | 2 | ||||
-rw-r--r-- | drivers/net/fsl-mc/mc.c | 6 | ||||
-rw-r--r-- | drivers/net/ldpaa_eth/ldpaa_eth.c | 171 | ||||
-rw-r--r-- | drivers/net/ldpaa_eth/ldpaa_eth.h | 1 | ||||
-rw-r--r-- | drivers/net/ldpaa_eth/ldpaa_wriop.c | 69 | ||||
-rw-r--r-- | drivers/net/mvneta.c | 8 | ||||
-rw-r--r-- | drivers/net/mvpp2.c | 13 | ||||
-rw-r--r-- | drivers/net/natsemi.c | 1 | ||||
-rw-r--r-- | drivers/net/ns8382x.c | 1 | ||||
-rw-r--r-- | drivers/net/pch_gbe.c | 4 | ||||
-rw-r--r-- | drivers/net/phy/ti.c | 93 | ||||
-rw-r--r-- | drivers/net/rtl8139.c | 4 | ||||
-rw-r--r-- | drivers/net/rtl8169.c | 4 | ||||
-rw-r--r-- | drivers/net/sandbox.c | 417 | ||||
-rw-r--r-- | drivers/net/zynq_gem.c | 4 |
17 files changed, 571 insertions, 230 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5441da47d1..f1f0e2d94e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -344,7 +344,7 @@ config XILINX_EMACLITE This MAC is present in Xilinx Microblaze, Zynq and ZynqMP SoCs. config ZYNQ_GEM - depends on DM_ETH && (ARCH_ZYNQ || ARCH_ZYNQMP) + depends on DM_ETH && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL) select PHYLIB bool "Xilinx Ethernet GEM" help diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 8d7c271038..e3c403c13f 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -123,7 +123,6 @@ #define TOUT_LOOP 1000000 #define SETUP_FRAME_LEN 192 -#define ETH_ALEN 6 struct de4x5_desc { volatile s32 status; diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index ae65b649bf..2fe0ba6e20 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -193,8 +193,6 @@ struct descriptor { /* A generic descriptor. */ #define TOUT_LOOP 1000000 -#define ETH_ALEN 6 - static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ static int rx_next; /* RX descriptor ring pointer */ diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index d9a897dc86..b245fbc681 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -363,8 +363,7 @@ static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type) for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { /* port not enabled */ - if ((wriop_is_enabled_dpmac(i) != 1) || - (wriop_get_phy_address(i) == -1)) + if (wriop_is_enabled_dpmac(i) != 1) continue; snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i, @@ -886,8 +885,7 @@ int fsl_mc_ldpaa_init(bd_t *bis) int i; for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) - if ((wriop_is_enabled_dpmac(i) == 1) && - (wriop_get_phy_address(i) != -1)) + if (wriop_is_enabled_dpmac(i) == 1) ldpaa_eth_init(i, wriop_get_enet_if(i)); return 0; } diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index a25b7cd906..73b7ba29df 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -23,21 +23,43 @@ static int init_phy(struct eth_device *dev) 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; bus = wriop_get_mdio(priv->dpmac_id); if (bus == NULL) return 0; - phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id), - dev, wriop_get_enet_if(priv->dpmac_id)); - if (!phydev) { - printf("Failed to connect\n"); - return -1; + 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; + + 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; } - priv->phydev = phydev; + 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; + + free(phydev); + wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL); + } + } - return phy_config(phydev); + return ret; } #endif @@ -377,6 +399,70 @@ error: return err; } +static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv, + struct dpmac_link_state *state) +{ + phy_interface_t enet_if; + int phys_detected; +#ifdef CONFIG_PHYLIB + struct phy_device *phydev = NULL; + int err, phy_num; +#endif + + /* 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; + + phys_detected = 0; +#ifdef CONFIG_PHYLIB + state->options |= DPMAC_LINK_OPT_AUTONEG; + + /* 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) + continue; + + phys_detected++; + err = phy_startup(phydev); + if (err) { + printf("%s: Could not initialize\n", phydev->dev->name); + state->up = 0; + break; + } + 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 { + /* break out of loop even if one phy is down */ + state->up = 0; + break; + } + } +#endif + if (!phys_detected) + state->options &= ~DPMAC_LINK_OPT_AUTONEG; + + if (!state->up) { + state->rate = 0; + state->options = 0; + return -ENOLINK; + } + + return 0; +} + static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; @@ -385,8 +471,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) struct dpni_link_state link_state; #endif int err = 0; - struct mii_dev *bus; - phy_interface_t enet_if; struct dpni_queue d_queue; if (net_dev->state == ETH_STATE_ACTIVE) @@ -407,47 +491,14 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err < 0) goto err_dpmac_setup; -#ifdef CONFIG_PHYLIB - if (priv->phydev) { - err = phy_startup(priv->phydev); - if (err) { - printf("%s: Could not initialize\n", - priv->phydev->dev->name); - goto err_dpamc_bind; - } - } -#else - priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); - - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; -#endif - - bus = wriop_get_mdio(priv->dpmac_id); - enet_if = wriop_get_enet_if(priv->dpmac_id); - if ((bus == NULL) && - (enet_if == PHY_INTERFACE_MODE_XGMII)) { - priv->phydev = (struct phy_device *) - malloc(sizeof(struct phy_device)); - memset(priv->phydev, 0, sizeof(struct phy_device)); - - priv->phydev->speed = SPEED_10000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; - } - - if (!priv->phydev->link) { - printf("%s: No link.\n", priv->phydev->dev->name); - err = -1; - goto err_dpamc_bind; - } + 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); @@ -476,18 +527,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - dpmac_link_state.rate = priv->phydev->speed; - - if (priv->phydev->autoneg == AUTONEG_DISABLE) - dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; - else - dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; - - if (priv->phydev->duplex == DUPLEX_HALF) - dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; - - dpmac_link_state.up = priv->phydev->link; - err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -530,7 +569,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; } - return priv->phydev->link; + return dpmac_link_state.up; err_qdid: err_get_queue: @@ -540,7 +579,7 @@ err_dpni_bind: err_dpbp_setup: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: -err_dpamc_bind: +err_dpmac_bind: dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); dpmac_destroy(dflt_mc_io, dflt_dprc_handle, @@ -554,7 +593,8 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; #ifdef CONFIG_PHYLIB - struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); + struct phy_device *phydev = NULL; + int phy_num; #endif if ((net_dev->state == ETH_STATE_PASSIVE) || @@ -588,11 +628,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n"); #ifdef CONFIG_PHYLIB - if (priv->phydev && bus != NULL) - phy_shutdown(priv->phydev); - else { - free(priv->phydev); - priv->phydev = NULL; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num); + if (phydev) + phy_shutdown(phydev); } #endif diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h index ee784a55ee..3f9154b5bb 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.h +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -127,7 +127,6 @@ struct ldpaa_eth_priv { uint16_t tx_flow_id; enum ldpaa_eth_type type; /* 1G or 10G ethernet */ - struct phy_device *phydev; }; struct dprc_endpoint dpmac_endpoint; diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c index 0731a795c8..06a284ad68 100644 --- a/drivers/net/ldpaa_eth/ldpaa_wriop.c +++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c @@ -22,10 +22,10 @@ __weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc) void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) { phy_interface_t enet_if; + int phy_num; dpmac_info[dpmac_id].enabled = 0; dpmac_info[dpmac_id].id = 0; - dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = PHY_INTERFACE_MODE_NONE; enet_if = wriop_dpmac_enet_if(dpmac_id, lane_prtcl); @@ -34,14 +34,23 @@ void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) dpmac_info[dpmac_id].id = dpmac_id; dpmac_info[dpmac_id].enet_if = enet_if; } + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if) { + int phy_num; + dpmac_info[dpmac_id].enabled = 1; dpmac_info[dpmac_id].id = dpmac_id; - dpmac_info[dpmac_id].phy_addr = -1; dpmac_info[dpmac_id].enet_if = enet_if; + for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) { + dpmac_info[dpmac_id].phydev[phy_num] = NULL; + dpmac_info[dpmac_id].phy_addr[phy_num] = -1; + } } @@ -58,47 +67,53 @@ static int wriop_dpmac_to_index(int dpmac_id) return -1; } -void wriop_disable_dpmac(int dpmac_id) +int wriop_disable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 0; wriop_dpmac_disable(dpmac_id); + + return 0; } -void wriop_enable_dpmac(int dpmac_id) +int wriop_enable_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].enabled = 1; wriop_dpmac_enable(dpmac_id); + + return 0; } -u8 wriop_is_enabled_dpmac(int dpmac_id) +int wriop_is_enabled_dpmac(int dpmac_id) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; return dpmac_info[i].enabled; } -void wriop_set_mdio(int dpmac_id, struct mii_dev *bus) +int wriop_set_mdio(int dpmac_id, struct mii_dev *bus) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; dpmac_info[i].bus = bus; + + return 0; } struct mii_dev *wriop_get_mdio(int dpmac_id) @@ -111,44 +126,56 @@ struct mii_dev *wriop_get_mdio(int dpmac_id) return dpmac_info[i].bus; } -void wriop_set_phy_address(int dpmac_id, int address) +int wriop_set_phy_address(int dpmac_id, int phy_num, int address) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; + + dpmac_info[i].phy_addr[phy_num] = address; - dpmac_info[i].phy_addr = address; + return 0; } -int wriop_get_phy_address(int dpmac_id) +int wriop_get_phy_address(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return -1; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - return dpmac_info[i].phy_addr; + return dpmac_info[i].phy_addr[phy_num]; } -void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev) +int wriop_set_phy_dev(int dpmac_id, int phy_num, struct phy_device *phydev) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) - return; + return -ENODEV; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return -EINVAL; - dpmac_info[i].phydev = phydev; + dpmac_info[i].phydev[phy_num] = phydev; + + return 0; } -struct phy_device *wriop_get_phy_dev(int dpmac_id) +struct phy_device *wriop_get_phy_dev(int dpmac_id, int phy_num) { int i = wriop_dpmac_to_index(dpmac_id); if (i == -1) return NULL; + if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM) + return NULL; - return dpmac_info[i].phydev; + return dpmac_info[i].phydev[phy_num]; } phy_interface_t wriop_get_enet_if(int dpmac_id) diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index ab697b9bc7..8cb04b52d7 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -34,14 +34,6 @@ DECLARE_GLOBAL_DATA_PTR; # error Marvell mvneta requires PHYLIB #endif -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) - #define CONFIG_NR_CPUS 1 #define ETH_HLEN 14 /* Total octets in header */ diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 62c0c2be06..f34245ba77 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -35,18 +35,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_dbg(dev, fmt, args...) \ - printf(fmt, ##args) - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - #define __verify_pcpu_ptr(ptr) \ do { \ const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \ @@ -68,7 +56,6 @@ do { \ #define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE) #define CONFIG_NR_CPUS 1 -#define ETH_HLEN ETHER_HDR_SIZE /* Total octets in header */ /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ #define WRAP (2 + ETH_HLEN + 4 + 32) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 0ed9bb5765..86f689802e 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -61,7 +61,6 @@ #define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/ns8382x.c b/drivers/net/ns8382x.c index f941c15b27..ea7ece54b6 100644 --- a/drivers/net/ns8382x.c +++ b/drivers/net/ns8382x.c @@ -59,7 +59,6 @@ /* defines */ #define DSIZE 0x00000FFF -#define ETH_ALEN 6 #define CRC_SIZE 4 #define TOUT_LOOP 500000 #define TX_BUF_SIZE 1536 diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index d31c45f3b6..2286dd07e9 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -429,7 +429,7 @@ static int pch_gbe_phy_init(struct udevice *dev) return 0; } -int pch_gbe_probe(struct udevice *dev) +static int pch_gbe_probe(struct udevice *dev) { struct pch_gbe_priv *priv; struct eth_pdata *plat = dev_get_platdata(dev); @@ -464,7 +464,7 @@ int pch_gbe_probe(struct udevice *dev) return pch_gbe_phy_init(dev); } -int pch_gbe_remove(struct udevice *dev) +static int pch_gbe_remove(struct udevice *dev) { struct pch_gbe_priv *priv = dev_get_priv(dev); diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index f870e6d662..6db6edd0d0 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -24,6 +24,7 @@ /* Extended Registers */ #define DP83867_CFG4 0x0031 #define DP83867_RGMIICTL 0x0032 +#define DP83867_STRAP_STS1 0x006E #define DP83867_RGMIIDCTL 0x0086 #define DP83867_IO_MUX_CFG 0x0170 @@ -48,8 +49,12 @@ #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) +/* STRAP_STS1 bits */ +#define DP83867_STRAP_STS1_RESERVED BIT(11) + /* PHY CTRL bits */ #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 +#define DP83867_PHYCR_RESERVED_MASK BIT(11) #define DP83867_MDI_CROSSOVER 5 #define DP83867_MDI_CROSSOVER_AUTO 2 #define DP83867_MDI_CROSSOVER_MDIX 2 @@ -88,6 +93,18 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 +#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \ + GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT) + +/* CFG4 bits */ +#define DP83867_CFG4_PORT_MIRROR_EN BIT(0) + +enum { + DP83867_PORT_MIRRORING_KEEP, + DP83867_PORT_MIRRORING_EN, + DP83867_PORT_MIRRORING_DIS, +}; struct dp83867_private { int rx_id_delay; @@ -95,6 +112,8 @@ struct dp83867_private { int fifo_depth; int io_impedance; bool rxctrl_strap_quirk; + int port_mirroring; + int clk_output_sel; }; /** @@ -163,6 +182,26 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, phy_write(phydev, addr, MII_MMD_DATA, data); } +static int dp83867_config_port_mirroring(struct phy_device *phydev) +{ + struct dp83867_private *dp83867 = + (struct dp83867_private *)phydev->priv; + u16 val; + + val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr); + + if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN) + val |= DP83867_CFG4_PORT_MIRROR_EN; + else + val &= ~DP83867_CFG4_PORT_MIRROR_EN; + + phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr, val); + + return 0; +} + #if defined(CONFIG_DM_ETH) /** * dp83867_data_init - Convenience function for setting PHY specific data @@ -173,6 +212,18 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; ofnode node; + u16 val; + + /* Optional configuration */ + + /* + * Keep the default value if ti,clk-output-sel is not set + * or to high + */ + + dp83867->clk_output_sel = + ofnode_read_u32_default(node, "ti,clk-output-sel", + DP83867_CLK_O_SEL_REF_CLK); node = phy_get_ofnode(phydev); if (!ofnode_valid(node)) @@ -197,6 +248,23 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth", -1); + if (ofnode_read_bool(node, "enet-phy-lane-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN; + + if (ofnode_read_bool(node, "enet-phy-lane-no-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; + + + /* Clock output selection if muxing property is set */ + if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr); + val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val |= (dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr, val); + } return 0; } @@ -218,7 +286,7 @@ static int dp83867_config(struct phy_device *phydev) { struct dp83867_private *dp83867; unsigned int val, delay, cfg2; - int ret; + int ret, bs; if (!phydev->priv) { dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); @@ -253,6 +321,26 @@ static int dp83867_config(struct phy_device *phydev) (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); if (ret) goto err_out; + + /* The code below checks if "port mirroring" N/A MODE4 has been + * enabled during power on bootstrap. + * + * Such N/A mode enabled by mistake can put PHY IC in some + * internal testing mode and disable RGMII transmission. + * + * In this particular case one needs to check STRAP_STS1 + * register's bit 11 (marked as RESERVED). + */ + + bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1, + DP83867_DEVADDR, phydev->addr); + val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL); + if (bs & DP83867_STRAP_STS1_RESERVED) { + val &= ~DP83867_PHYCR_RESERVED_MASK; + phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, + val); + } + } else if (phy_interface_is_sgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000)); @@ -315,6 +403,9 @@ static int dp83867_config(struct phy_device *phydev) } } + if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP) + dp83867_config_port_mirroring(phydev); + genphy_config_aneg(phydev); return 0; diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ea523435f0..590f8ce154 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -80,10 +80,6 @@ #define RTL_TIMEOUT 100000 -#define ETH_FRAME_LEN 1514 -#define ETH_ALEN 6 -#define ETH_ZLEN 60 - /* PCI Tuning Parameters Threshold is bytes transferred to chip before transmission starts. */ #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index e0e3a6d570..a78f3d233f 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -102,10 +102,6 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #define RTL_R16(reg) readw(ioaddr + (reg)) #define RTL_R32(reg) readl(ioaddr + (reg)) -#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE -#define ETH_ALEN MAC_ADDR_LEN -#define ETH_ZLEN 60 - #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \ (pci_addr_t)(unsigned long)a) #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)(unsigned long)dev->priv, \ diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index b71c8f88d9..decce2fa59 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -10,26 +10,11 @@ #include <dm.h> #include <malloc.h> #include <net.h> +#include <asm/eth.h> #include <asm/test.h> DECLARE_GLOBAL_DATA_PTR; -/** - * struct eth_sandbox_priv - memory for sandbox mock driver - * - * fake_host_hwaddr: MAC address of mocked machine - * fake_host_ipaddr: IP address of mocked machine - * recv_packet_buffer: buffer of the packet returned as received - * recv_packet_length: length of the packet returned as received - */ -struct eth_sandbox_priv { - uchar fake_host_hwaddr[ARP_HLEN]; - struct in_addr fake_host_ipaddr; - uchar *recv_packet_buffer; - int recv_packet_length; -}; - -static bool disabled[8] = {false}; static bool skip_timeout; /* @@ -40,7 +25,16 @@ static bool skip_timeout; */ void sandbox_eth_disable_response(int index, bool disable) { - disabled[index] = disable; + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + priv->disabled = disable; } /* @@ -53,103 +47,304 @@ void sandbox_eth_skip_timeout(void) skip_timeout = true; } -static int sb_eth_start(struct udevice *dev) +/* + * sandbox_eth_arp_req_to_reply() + * + * Check for an arp request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) { struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct arp_hdr *arp; + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; - debug("eth_sandbox: Start\n"); + if (ntohs(eth->et_protlen) != PROT_ARP) + return -EAGAIN; - priv->recv_packet_buffer = net_rx_packets[0]; + arp = packet + ETHER_HDR_SIZE; + + if (ntohs(arp->ar_op) != ARPOP_REQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* store this as the assumed IP of the fake host */ + priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); + + /* Formulate a fake response */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REPLY); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); + net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; return 0; } -static int sb_eth_send(struct udevice *dev, void *packet, int length) +/* + * sandbox_eth_ping_req_to_reply() + * + * Check for a ping request to be sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) { struct eth_sandbox_priv *priv = dev_get_priv(dev); struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct icmp_hdr *icmp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; - debug("eth_sandbox: Send packet %d\n", length); + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + + if (ip->ip_p != IPPROTO_ICMP) + return -EAGAIN; + + icmp = (struct icmp_hdr *)&ip->udp_src; + + if (icmp->type != ICMP_ECHO_REQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the ping */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv, packet, len); + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + icmpr = (struct icmp_hdr *)&ipr->udp_src; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + ipr->ip_sum = 0; + ipr->ip_off = 0; + net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); + net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr->type = ICMP_ECHO_REPLY; + icmpr->checksum = 0; + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length[priv->recv_packets] = len; + ++priv->recv_packets; + + return 0; +} + +/* + * sandbox_eth_recv_arp_req() + * + * Inject an ARP request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_arp_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct arp_hdr *arp_recv; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_ARP); + + arp_recv = (void *)eth_recv + ETHER_HDR_SIZE; + arp_recv->ar_hrd = htons(ARP_ETHER); + arp_recv->ar_pro = htons(PROT_IP); + arp_recv->ar_hln = ARP_HLEN; + arp_recv->ar_pln = ARP_PLEN; + arp_recv->ar_op = htons(ARPOP_REQUEST); + memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); + memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN); + net_write_ip(&arp_recv->ar_tpa, net_ip); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + ARP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} + +/* + * sandbox_eth_recv_ping_req() + * + * Inject a ping request for this target + * + * returns 0 if injected, -EOVERFLOW if not + */ +int sandbox_eth_recv_ping_req(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct icmp_hdr *icmpr; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return -EOVERFLOW; + + /* Formulate a fake ping */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + + memcpy(eth_recv->et_dest, net_ethaddr, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_IP); + + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + ipr->ip_hl_v = 0x45; + ipr->ip_len = htons(IP_ICMP_HDR_SIZE); + ipr->ip_off = htons(IP_FLAGS_DFRAG); + ipr->ip_p = IPPROTO_ICMP; + ipr->ip_sum = 0; + net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr); + net_write_ip(&ipr->ip_dst, net_ip); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + icmpr = (struct icmp_hdr *)&ipr->udp_src; + + icmpr->type = ICMP_ECHO_REQUEST; + icmpr->code = 0; + icmpr->checksum = 0; + icmpr->un.echo.id = 0; + icmpr->un.echo.sequence = htons(1); + icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + IP_ICMP_HDR_SIZE; + ++priv->recv_packets; + + return 0; +} - if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) && - disabled[dev->seq]) +/* + * sb_default_handler() + * + * perform typical responses to simple ping + * + * dev - device pointer + * pkt - "sent" packet buffer + * len - length of packet + */ +static int sb_default_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + if (!sandbox_eth_arp_req_to_reply(dev, packet, len)) + return 0; + if (!sandbox_eth_ping_req_to_reply(dev, packet, len)) return 0; - if (ntohs(eth->et_protlen) == PROT_ARP) { - struct arp_hdr *arp = packet + ETHER_HDR_SIZE; - - if (ntohs(arp->ar_op) == ARPOP_REQUEST) { - struct ethernet_hdr *eth_recv; - struct arp_hdr *arp_recv; - - /* store this as the assumed IP of the fake host */ - priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa); - /* Formulate a fake response */ - eth_recv = (void *)priv->recv_packet_buffer; - memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - eth_recv->et_protlen = htons(PROT_ARP); - - arp_recv = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - arp_recv->ar_hrd = htons(ARP_ETHER); - arp_recv->ar_pro = htons(PROT_IP); - arp_recv->ar_hln = ARP_HLEN; - arp_recv->ar_pln = ARP_PLEN; - arp_recv->ar_op = htons(ARPOP_REPLY); - memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, - ARP_HLEN); - net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr); - memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN); - net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa); - - priv->recv_packet_length = ETHER_HDR_SIZE + - ARP_HDR_SIZE; - } - } else if (ntohs(eth->et_protlen) == PROT_IP) { - struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE; - - if (ip->ip_p == IPPROTO_ICMP) { - struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src; - - if (icmp->type == ICMP_ECHO_REQUEST) { - struct ethernet_hdr *eth_recv; - struct ip_udp_hdr *ipr; - struct icmp_hdr *icmpr; - - /* reply to the ping */ - memcpy(priv->recv_packet_buffer, packet, - length); - eth_recv = (void *)priv->recv_packet_buffer; - ipr = (void *)priv->recv_packet_buffer + - ETHER_HDR_SIZE; - icmpr = (struct icmp_hdr *)&ipr->udp_src; - memcpy(eth_recv->et_dest, eth->et_src, - ARP_HLEN); - memcpy(eth_recv->et_src, priv->fake_host_hwaddr, - ARP_HLEN); - ipr->ip_sum = 0; - ipr->ip_off = 0; - net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src); - net_write_ip((void *)&ipr->ip_src, - priv->fake_host_ipaddr); - ipr->ip_sum = compute_ip_checksum(ipr, - IP_HDR_SIZE); - - icmpr->type = ICMP_ECHO_REPLY; - icmpr->checksum = 0; - icmpr->checksum = compute_ip_checksum(icmpr, - ICMP_HDR_SIZE); - - priv->recv_packet_length = length; - } - } + return 0; +} + +/* + * sandbox_eth_set_tx_handler() + * + * Set a custom response to a packet being sent through the sandbox eth test + * driver + * + * index - interface to set the handler for + * handler - The func ptr to call on send. If NULL, set to default handler + */ +void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler) +{ + struct udevice *dev; + struct eth_sandbox_priv *priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + priv = dev_get_priv(dev); + if (handler) + priv->tx_handler = handler; + else + priv->tx_handler = sb_default_handler; +} + +/* + * Set priv ptr + * + * priv - priv void ptr to store in the device + */ +void sandbox_eth_set_priv(int index, void *priv) +{ + struct udevice *dev; + struct eth_sandbox_priv *dev_priv; + int ret; + + ret = uclass_get_device(UCLASS_ETH, index, &dev); + if (ret) + return; + + dev_priv = dev_get_priv(dev); + + dev_priv->priv = priv; +} + +static int sb_eth_start(struct udevice *dev) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + + debug("eth_sandbox: Start\n"); + + priv->recv_packets = 0; + for (int i = 0; i < PKTBUFSRX; i++) { + priv->recv_packet_buffer[i] = net_rx_packets[i]; + priv->recv_packet_length[i] = 0; } return 0; } +static int sb_eth_send(struct udevice *dev, void *packet, int length) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + + debug("eth_sandbox: Send packet %d\n", length); + + if (priv->disabled) + return 0; + + return priv->tx_handler(dev, packet, length); +} + static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) { struct eth_sandbox_priv *priv = dev_get_priv(dev); @@ -159,18 +354,37 @@ static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp) skip_timeout = false; } - if (priv->recv_packet_length) { - int lcl_recv_packet_length = priv->recv_packet_length; + if (priv->recv_packets) { + int lcl_recv_packet_length = priv->recv_packet_length[0]; - debug("eth_sandbox: received packet %d\n", - priv->recv_packet_length); - priv->recv_packet_length = 0; - *packetp = priv->recv_packet_buffer; + debug("eth_sandbox: received packet[%d], %d waiting\n", + lcl_recv_packet_length, priv->recv_packets - 1); + *packetp = priv->recv_packet_buffer[0]; return lcl_recv_packet_length; } return 0; } +static int sb_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + int i; + + if (!priv->recv_packets) + return 0; + + --priv->recv_packets; + for (i = 0; i < priv->recv_packets; i++) { + priv->recv_packet_length[i] = priv->recv_packet_length[i + 1]; + memcpy(priv->recv_packet_buffer[i], + priv->recv_packet_buffer[i + 1], + priv->recv_packet_length[i + 1]); + } + priv->recv_packet_length[priv->recv_packets] = 0; + + return 0; +} + static void sb_eth_stop(struct udevice *dev) { debug("eth_sandbox: Stop\n"); @@ -189,6 +403,7 @@ static const struct eth_ops sb_eth_ops = { .start = sb_eth_start, .send = sb_eth_send, .recv = sb_eth_recv, + .free_pkt = sb_eth_free_pkt, .stop = sb_eth_stop, .write_hwaddr = sb_eth_write_hwaddr, }; @@ -212,6 +427,8 @@ static int sb_eth_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN); + priv->disabled = false; + priv->tx_handler = sb_default_handler; return 0; } diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index e22d048e8f..bc33126536 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -461,6 +461,7 @@ static int zynq_gem_init(struct udevice *dev) break; } +#if !defined(CONFIG_ARCH_VERSAL) ret = clk_set_rate(&priv->clk, clk_rate); if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) { dev_err(dev, "failed to set tx clock rate\n"); @@ -472,6 +473,9 @@ static int zynq_gem_init(struct udevice *dev) dev_err(dev, "failed to enable tx clock\n"); return ret; } +#else + debug("requested clk_rate %ld\n", clk_rate); +#endif setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); |