From 22f314e01ce249ec1649623ef725552f677beb62 Mon Sep 17 00:00:00 2001 From: Jacky Chou Date: Fri, 29 Dec 2023 09:45:55 +0800 Subject: net: phy: ncsi: fixed not nullify the pointers after free The issue occurs the UAF (use-after-free) to cause double free when do the realloc function for the pointers during the reinitialization NC-SI process, and it will cause the memory management occurs error. So, nullify these pointers after free. Signed-off-by: Jacky Chou --- drivers/net/phy/ncsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c index eb3fd65bb47..96893858847 100644 --- a/drivers/net/phy/ncsi.c +++ b/drivers/net/phy/ncsi.c @@ -619,9 +619,12 @@ static void ncsi_handle_aen(struct ip_udp_hdr *ip, unsigned int len) /* Link or configuration lost - just redo the discovery process */ ncsi_priv->state = NCSI_PROBE_PACKAGE_SP; - for (i = 0; i < ncsi_priv->n_packages; i++) + for (i = 0; i < ncsi_priv->n_packages; i++) { free(ncsi_priv->packages[i].channels); + ncsi_priv->packages[i].channels = NULL; + } free(ncsi_priv->packages); + ncsi_priv->packages = NULL; ncsi_priv->n_packages = 0; ncsi_priv->current_package = NCSI_PACKAGE_MAX; -- cgit v1.3.1 From 388cb2d321dd0bc5b0dc6e7f8e96d6d0f2929736 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 1 Jan 2024 22:07:47 +0100 Subject: net: phy: broadcom: Configure LEDs on BCM54210E Configure LEDs on BCM54210E so they would blink on activity and indicate link speed. Without this the LEDs are always on if cable is plugged in. Signed-off-by: Marek Vasut --- drivers/net/phy/broadcom.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 82e3bbef7dd..ecccb7c3b54 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -42,6 +42,12 @@ #define BCM54810_SHD_CLK_CTL 0x3 #define BCM54810_SHD_CLK_CTL_GTXCLK_EN BIT(9) +#define BCM54XX_SHD_LEDS1 0x0d +#define BCM_LED_SRC_LINKSPD2 0x1 +#define BCM_LED_SRC_ACTIVITYLED 0x3 +#define BCM54XX_SHD_LEDS1_LED3(src) (((src) & 0xf) << 4) +#define BCM54XX_SHD_LEDS1_LED1(src) (((src) & 0xf) << 0) + static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum) { /* The register must be written to both the Shadow Register Select and @@ -148,7 +154,16 @@ static int bcm54210e_config(struct phy_device *phydev) if (ret < 0) return ret; - return bcm5461_config(phydev); + ret = bcm5461_config(phydev); + if (ret < 0) + return ret; + + /* Configure LEDs to blink. */ + bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, + BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | + BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); + + return 0; } static int bcm54xx_parse_status(struct phy_device *phydev) -- cgit v1.3.1 From f5dbfc82a90b2333bfee76906df883ba86a85f56 Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Thu, 4 Jan 2024 05:26:23 +0100 Subject: net: phy: Fix signed shift overflow Booting R-Car Gen3 arm64 U-Boot with CONFIG_UBSAN=y resulted in: ===================================================================== UBSAN: Undefined behaviour in drivers/net/phy/phy.c:728:19 left shift of 1 by 31 places cannot be represented in type 'int' ===================================================================== Fix it by appending the UL suffix to the numeric literal. While at it, convert the type of "addr" variable from signed to unsigned, to protect against shifting the numeric literal by a negative value (which would lead to yet another undefined behavior). Fixes: 1adb406b0141 ("phy: add phy_find_by_mask/phy_connect_dev") Signed-off-by: Eugeniu Rosca * Using U-suffix for integer is sufficient. * ffs() of non-zero value cannot be 0. But addr being unsigned is * preferable. Signed-off-by: Heinrich Schuchardt --- drivers/net/phy/phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 63b3e46f101..f39ca942f6b 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -642,12 +642,12 @@ static struct phy_device *search_for_existing_phy(struct mii_dev *bus, { /* If we have one, return the existing device, with new interface */ while (phy_mask) { - int addr = ffs(phy_mask) - 1; + unsigned int addr = ffs(phy_mask) - 1; if (bus->phymap[addr]) return bus->phymap[addr]; - phy_mask &= ~(1 << addr); + phy_mask &= ~(1U << addr); } return NULL; } -- cgit v1.3.1 From f146c446e51184a33deb798e8169aaf654c044a6 Mon Sep 17 00:00:00 2001 From: Jacky Chou Date: Mon, 15 Jan 2024 18:34:47 +0800 Subject: net: phy: the NC-SI phy device do not require mdio bus As with fixed-link phy device, the NC-SI phy devive does not require an mdio bus. So, a condition is added to check the NC-SI phy id to avoid accessing the bus pointer that is NULL. Signed-off-by: Jacky Chou --- drivers/net/phy/phy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f39ca942f6b..9cec04a0c94 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -566,7 +566,8 @@ struct phy_device *phy_device_create(struct mii_dev *bus, int addr, return NULL; } - if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID) + if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID && + phy_id != PHY_NCSI_ID) bus->phymap[addr] = dev; return dev; -- cgit v1.3.1 From 3724ec4e5ca85666d648d2082915ef272500b5e7 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Mon, 22 Jan 2024 22:33:20 +0800 Subject: net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err() The initial commit used log_msg_ret() wrongly. Fix that by moving error report to a separate dev_err() call and shrink the first argument of log_msg_ret() to no more than 4 chars. Fixes: 6b5c8d98e204 ("net: add hifemac_mdio MDIO bus driver for HiSilicon platform") Signed-off-by: Yang Xiwen --- drivers/net/hifemac_mdio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c index 343c5f3a38a..0b59d060917 100644 --- a/drivers/net/hifemac_mdio.c +++ b/drivers/net/hifemac_mdio.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev) data->membase = dev_remap_addr(dev); if (IS_ERR(data->membase)) { ret = PTR_ERR(data->membase); - return log_msg_ret("Failed to remap base addr", ret); + dev_err(dev, "Failed to remap base addr %d\n", ret); + return log_msg_ret("mdio", ret); } // clk is optional @@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev) int ret; ret = clk_prepare_enable(data->clk); - if (ret) - return log_msg_ret("Failed to enable clk", ret); + if (ret) { + dev_err(dev, "Failed to enable clock: %d\n", ret); + return log_msg_ret("clk", ret); + } return 0; } @@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = { .of_to_plat = hisi_femac_mdio_of_to_plat, .probe = hisi_femac_mdio_probe, .ops = &hisi_femac_mdio_ops, + .plat_auto = sizeof(struct mdio_perdev_priv), .priv_auto = sizeof(struct hisi_femac_mdio_data), }; -- cgit v1.3.1 From a91263c3217614311f418688d96e960263c8caef Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Mon, 22 Jan 2024 22:33:21 +0800 Subject: net: hifemac: fix log reporting shrink the first argument of log_msg_ret(), add dev_xxx() functions for error reporting. Fixes: 9d8f78a2a79f7 ("net: add hifemac Ethernet driver for HiSilicon platform") Signed-off-by: Yang Xiwen --- drivers/net/hifemac.c | 110 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 37 deletions(-) diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c index b61a29e6360..1088f3eca35 100644 --- a/drivers/net/hifemac.c +++ b/drivers/net/hifemac.c @@ -245,8 +245,10 @@ static int hisi_femac_start(struct udevice *dev) hisi_femac_rx_refill(priv); ret = phy_startup(priv->phy); - if (ret) - return log_msg_ret("Failed to startup phy", ret); + if (ret) { + dev_err(dev, "Failed to startup phy: %d\n", ret); + return log_msg_ret("phy", ret); + } if (!priv->phy->link) { debug("%s: link down\n", __func__); @@ -281,8 +283,10 @@ static int hisi_femac_send(struct udevice *dev, void *packet, int length) // wait until FIFO is empty ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, IRQ_INT_TX_PER_PACKET, true, 50, false); - if (ret == -ETIMEDOUT) - return log_msg_ret("FIFO timeout", ret); + if (ret == -ETIMEDOUT) { + dev_err(dev, "FIFO timeout\n"); + return log_msg_ret("net", ret); + } return 0; } @@ -340,35 +344,45 @@ int hisi_femac_of_to_plat(struct udevice *dev) }; priv->port_base = dev_remap_addr_name(dev, "port"); - if (IS_ERR(priv->port_base)) - return log_msg_ret("Failed to remap port address space", PTR_ERR(priv->port_base)); + if (!priv->port_base) { + dev_err(dev, "Failed to remap port address space\n"); + return log_msg_ret("net", -EINVAL); + } priv->glb_base = dev_remap_addr_name(dev, "glb"); - if (IS_ERR(priv->glb_base)) - return log_msg_ret("Failed to remap global address space", PTR_ERR(priv->glb_base)); + if (IS_ERR(priv->glb_base)) { + dev_err(dev, "Failed to remap global address space\n"); + return log_msg_ret("net", -EINVAL); + } for (i = 0; i < ARRAY_SIZE(clk_strs); i++) { priv->clks[i] = devm_clk_get(dev, clk_strs[i]); if (IS_ERR(priv->clks[i])) { dev_err(dev, "Error getting clock %s\n", clk_strs[i]); - return log_msg_ret("Failed to get clocks", PTR_ERR(priv->clks[i])); + return log_msg_ret("clk", PTR_ERR(priv->clks[i])); } } priv->mac_rst = devm_reset_control_get(dev, "mac"); - if (IS_ERR(priv->mac_rst)) - return log_msg_ret("Failed to get MAC reset", PTR_ERR(priv->mac_rst)); + if (IS_ERR(priv->mac_rst)) { + dev_err(dev, "Failed to get MAC reset %ld\n", PTR_ERR(priv->mac_rst)); + return log_msg_ret("rst", PTR_ERR(priv->mac_rst)); + } priv->phy_rst = devm_reset_control_get(dev, "phy"); - if (IS_ERR(priv->phy_rst)) - return log_msg_ret("Failed to get PHY reset", PTR_ERR(priv->phy_rst)); + if (IS_ERR(priv->phy_rst)) { + dev_err(dev, "Failed to get PHY reset %ld\n", PTR_ERR(priv->phy_rst)); + return log_msg_ret("rst", PTR_ERR(priv->phy_rst)); + } ret = dev_read_u32_array(dev, PHY_RESET_DELAYS_PROPERTY, priv->phy_reset_delays, DELAYS_NUM); - if (ret < 0) - return log_msg_ret("Failed to get PHY reset delays", ret); + if (ret < 0) { + dev_err(dev, "Failed to get PHY reset delays %d\n", ret); + return log_msg_ret("rst", ret); + } priv->mac_reset_delay = dev_read_u32_default(dev, MAC_RESET_DELAY_PROPERTY, @@ -385,32 +399,44 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv *priv) // Disable MAC clk before phy reset ret = clk_disable(priv->clks[CLK_MAC]); - if (ret < 0) - return log_msg_ret("Failed to disable MAC clock", ret); + if (ret < 0) { + pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret); + return log_msg_ret("clk", ret); + } ret = clk_disable(priv->clks[CLK_BUS]); - if (ret < 0) - return log_msg_ret("Failed to disable bus clock", ret); + if (ret < 0) { + pr_err("%s: Failed to disable bus clock %d\n", __func__, ret); + return log_msg_ret("clk", ret); + } udelay(delays[PRE_DELAY]); ret = reset_assert(rst); - if (ret < 0) - return log_msg_ret("Failed to assert reset", ret); + if (ret < 0) { + pr_err("%s: Failed to assert reset %d\n", __func__, ret); + return log_msg_ret("rst", ret); + } udelay(delays[PULSE]); ret = reset_deassert(rst); - if (ret < 0) - return log_msg_ret("Failed to deassert reset", ret); + if (ret < 0) { + pr_err("%s: Failed to deassert reset %d\n", __func__, ret); + return log_msg_ret("rst", ret); + } udelay(delays[POST_DELAY]); ret = clk_enable(priv->clks[CLK_MAC]); - if (ret < 0) - return log_msg_ret("Failed to enable MAC clock", ret); + if (ret < 0) { + pr_err("%s: Failed to enable MAC clock %d\n", __func__, ret); + return log_msg_ret("clk", ret); + } ret = clk_enable(priv->clks[CLK_BUS]); - if (ret < 0) - return log_msg_ret("Failed to enable MAC bus clock", ret); + if (ret < 0) { + pr_err("%s: Failed to enable MAC bus clock %d\n", __func__, ret); + return log_msg_ret("clk", ret); + } return 0; } @@ -423,30 +449,40 @@ int hisi_femac_probe(struct udevice *dev) // Enable clocks for (i = 0; i < CLK_NUM; i++) { ret = clk_prepare_enable(priv->clks[i]); - if (ret < 0) - return log_msg_ret("Failed to enable clks", ret); + if (ret < 0) { + dev_err(dev, "Failed to enable clk %d: %d\n", i, ret); + return log_msg_ret("clk", ret); + } } // Reset MAC ret = reset_assert(priv->mac_rst); - if (ret < 0) - return log_msg_ret("Failed to assert MAC reset", ret); + if (ret < 0) { + dev_err(dev, "Failed to assert MAC reset: %d\n", ret); + return log_msg_ret("net", ret); + } udelay(priv->mac_reset_delay); ret = reset_deassert(priv->mac_rst); - if (ret < 0) - return log_msg_ret("Failed to deassert MAC reset", ret); + if (ret < 0) { + dev_err(dev, "Failed to deassert MAC reset: %d\n", ret); + return log_msg_ret("net", ret); + } // Reset PHY ret = hisi_femac_phy_reset(priv); - if (ret < 0) - return log_msg_ret("Failed to reset phy", ret); + if (ret < 0) { + dev_err(dev, "Failed to reset PHY: %d\n", ret); + return log_msg_ret("net", ret); + } // Connect to PHY priv->phy = dm_eth_phy_connect(dev); - if (!priv->phy) - return log_msg_ret("Failed to connect to phy", -EINVAL); + if (!priv->phy) { + dev_err(dev, "Failed to connect to phy\n"); + return log_msg_ret("phy", -EINVAL); + } hisi_femac_port_init(priv); return 0; -- cgit v1.3.1 From 561856ec5ead170396942a69504d03ba22f15def Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Mon, 22 Jan 2024 22:33:22 +0800 Subject: net: hifemac: register MDIO bus device for subnode register internal MDIO bus device if it is a subnode. Signed-off-by: Yang Xiwen --- drivers/net/hifemac.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c index 1088f3eca35..39c0233b626 100644 --- a/drivers/net/hifemac.c +++ b/drivers/net/hifemac.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -337,6 +338,8 @@ int hisi_femac_of_to_plat(struct udevice *dev) { int ret, i; struct hisi_femac_priv *priv = dev_get_priv(dev); + ofnode mdio_node; + bool mdio_registered = false; static const char * const clk_strs[] = { [CLK_MAC] = "mac", [CLK_BUS] = "bus", @@ -388,6 +391,31 @@ int hisi_femac_of_to_plat(struct udevice *dev) MAC_RESET_DELAY_PROPERTY, MAC_RESET_ASSERT_PERIOD); + /* Create MDIO bus */ + ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) { + const char *subnode_name = ofnode_get_name(mdio_node); + struct udevice *mdiodev; + + // Skip subnodes not starting with "mdio" + if (strncmp(subnode_name, "mdio", 4)) + continue; + + ret = device_bind_driver_to_node(dev, "hisi-femac-mdio", + subnode_name, mdio_node, &mdiodev); + if (ret) { + dev_err(dev, "Failed to register MDIO bus device %d\n", ret); + return log_msg_ret("net", ret); + } + + mdio_registered = true; + break; + } + + if (!mdio_registered) { + dev_err(dev, "No MDIO subnode is found!\n"); + return log_msg_ret("mdio", -ENODATA); + } + return 0; } -- cgit v1.3.1 From abcb26cb1f609a12d7073842bf2dae4808393cde Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Mon, 22 Jan 2024 22:33:23 +0800 Subject: net: hifemac: implement `net stats` needed ops 3 operations needed by `net stats` are implemented. New `net stats` output some useful info. Signed-off-by: Yang Xiwen --- drivers/net/hifemac.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c index 39c0233b626..d24023eefd1 100644 --- a/drivers/net/hifemac.c +++ b/drivers/net/hifemac.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -125,6 +127,57 @@ struct hisi_femac_priv { u32 link_status; }; +struct hisi_femac_stat_entry { + const char *name; + u32 offset; + u32 mask; +}; + +/* please refer to the datasheet for the description of these entries */ +static const struct hisi_femac_stat_entry hisi_femac_stats_table[] = { + { "rxsof_cnt", 0x584, GENMASK(31, 28) }, + { "rxeof_cnt", 0x584, GENMASK(27, 24) }, + { "rxcrcok_cnt", 0x584, GENMASK(23, 20) }, + { "rxcrcbad_cnt", 0x584, GENMASK(19, 16) }, + { "txsof_cnt", 0x584, GENMASK(15, 12) }, + { "txeof_cnt", 0x584, GENMASK(11, 8) }, + { "txcrcok_cnt", 0x584, GENMASK(7, 4) }, + { "txcrcbad_cnt", 0x584, GENMASK(3, 0) }, + { "pkts_cpu", 0x5a0, GENMASK(15, 0) }, + { "addr_cpu", 0x5a4, GENMASK(15, 0) }, + { "pkts_port", 0x5a8, GENMASK(15, 0) }, + { "pkts_cpu2tx", 0x5ac, GENMASK(15, 0) }, + { "rxdvrise", 0x600, GENMASK(31, 0) }, + { "ifinoctets", 0x604, GENMASK(31, 0) }, + { "octets_rx", 0x608, GENMASK(31, 0) }, + { "local_mac_match", 0x60c, GENMASK(31, 0) }, + { "pkts", 0x610, GENMASK(31, 0) }, + { "broadcastpkts", 0x614, GENMASK(31, 0) }, + { "multicastpkts", 0x618, GENMASK(31, 0) }, + { "ifinucastpkts", 0x61c, GENMASK(31, 0) }, + { "ifinerrors", 0x620, GENMASK(31, 0) }, + { "crcerr", 0x624, GENMASK(31, 0) }, + { "abnormalsizepkts", 0x628, GENMASK(31, 0) }, + { "dot3alignmenterr", 0x62c, GENMASK(31, 0) }, + { "dot3pause", 0x630, GENMASK(31, 0) }, + { "dropevents", 0x634, GENMASK(31, 0) }, + { "flux_frame_cnt", 0x638, GENMASK(31, 0) }, + { "flux_drop_cnt", 0x63c, GENMASK(31, 0) }, + { "mac_not2cpu_pkts", 0x64c, GENMASK(31, 0) }, + { "pkts_tx", 0x780, GENMASK(31, 0) }, + { "broadcastpkts_tx", 0x784, GENMASK(31, 0) }, + { "multicastpkts_tx", 0x788, GENMASK(31, 0) }, + { "ifoutucastpkts_tx", 0x78c, GENMASK(31, 0) }, + { "octets_tx", 0x790, GENMASK(31, 0) }, + { "dot3pause", 0x794, GENMASK(31, 0) }, + { "retry_times_tx", 0x798, GENMASK(31, 0) }, + { "collisions", 0x79c, GENMASK(31, 0) }, + { "dot3latecol", 0x7a0, GENMASK(31, 0) }, + { "dot3colok", 0x7a4, GENMASK(31, 0) }, + { "dot3excessivecol", 0x7a8, GENMASK(31, 0) }, + { "dot3colcnt", 0x7ac, GENMASK(31, 0) }, +}; + static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs) { u32 val; @@ -334,6 +387,37 @@ static void hisi_femac_stop(struct udevice *dev) writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET); } +static int hisi_femac_get_sset_count(struct udevice *dev) +{ + return ARRAY_SIZE(hisi_femac_stats_table); +} + +static void hisi_femac_get_strings(struct udevice *dev, u8 *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) + strcpy(data + i * ETH_GSTRING_LEN, hisi_femac_stats_table[i].name); +} + +/* Non-constant mask variant of FIELD_GET/FIELD_PREP */ +#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1)) + +static void hisi_femac_get_stats(struct udevice *dev, u64 *data) +{ + int i; + u32 mask, reg; + struct hisi_femac_priv *priv = dev_get_priv(dev); + void __iomem *port_base = priv->port_base; + + for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) { + mask = hisi_femac_stats_table[i].mask; + reg = readl(port_base + hisi_femac_stats_table[i].offset); + + data[i] = field_get(mask, reg); + } +} + int hisi_femac_of_to_plat(struct udevice *dev) { int ret, i; @@ -523,6 +607,9 @@ static const struct eth_ops hisi_femac_ops = { .free_pkt = hisi_femac_free_pkt, .stop = hisi_femac_stop, .write_hwaddr = hisi_femac_set_hw_mac_addr, + .get_sset_count = hisi_femac_get_sset_count, + .get_strings = hisi_femac_get_strings, + .get_stats = hisi_femac_get_stats, }; static const struct udevice_id hisi_femac_ids[] = { -- cgit v1.3.1 From 0eedd1e5643ad3247c4cf5b6f6a172c3decb79f3 Mon Sep 17 00:00:00 2001 From: Yang Xiwen Date: Mon, 22 Jan 2024 22:33:24 +0800 Subject: net: hifemac: make some functions static They are not required to be global, make them static. Signed-off-by: Yang Xiwen --- drivers/net/hifemac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c index d24023eefd1..90cc247b3b6 100644 --- a/drivers/net/hifemac.c +++ b/drivers/net/hifemac.c @@ -418,7 +418,7 @@ static void hisi_femac_get_stats(struct udevice *dev, u64 *data) } } -int hisi_femac_of_to_plat(struct udevice *dev) +static int hisi_femac_of_to_plat(struct udevice *dev) { int ret, i; struct hisi_femac_priv *priv = dev_get_priv(dev); @@ -553,7 +553,7 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv *priv) return 0; } -int hisi_femac_probe(struct udevice *dev) +static int hisi_femac_probe(struct udevice *dev) { struct hisi_femac_priv *priv = dev_get_priv(dev); int ret, i; -- cgit v1.3.1 From 60d77b6f91f08d3be3b03d188c30c9b47e800a62 Mon Sep 17 00:00:00 2001 From: Jacky Chou Date: Mon, 5 Feb 2024 16:02:28 +0800 Subject: net: phy: ncsi: Correct the endian of the checksum There is no need to perform the endian twice here. Signed-off-by: Jacky Chou Reviewed-by: Dan Carpenter --- drivers/net/phy/ncsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c index 96893858847..f9069c3a10d 100644 --- a/drivers/net/phy/ncsi.c +++ b/drivers/net/phy/ncsi.c @@ -551,7 +551,7 @@ static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd, checksum = ncsi_calculate_checksum((unsigned char *)hdr, sizeof(*hdr) + len); pchecksum = (__be32 *)((void *)(hdr + 1) + len); - put_unaligned_be32(htonl(checksum), pchecksum); + put_unaligned_be32(checksum, pchecksum); if (wait) { net_set_timeout_handler(1000UL, ncsi_timeout_handler); -- cgit v1.3.1 From cc09160f30b33ea365e89c445edfb4f3b985911b Mon Sep 17 00:00:00 2001 From: Jacky Chou Date: Mon, 5 Feb 2024 16:13:23 +0800 Subject: net: phy: ncsi: reslove the unaligned access issue From the ethernet header is not on aligned, because the length of the ethernet header is 14 bytes. Therefore, unaligned access must be done here. Signed-off-by: Jacky Chou --- drivers/net/phy/ncsi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c index f9069c3a10d..2bca116a9d8 100644 --- a/drivers/net/phy/ncsi.c +++ b/drivers/net/phy/ncsi.c @@ -286,11 +286,11 @@ static void ncsi_rsp_gc(struct ncsi_rsp_pkt *pkt) } c = &ncsi_priv->packages[np].channels[nc]; - c->cap_generic = ntohl(gc->cap) & NCSI_CAP_GENERIC_MASK; - c->cap_bc = ntohl(gc->bc_cap) & NCSI_CAP_BC_MASK; - c->cap_mc = ntohl(gc->mc_cap) & NCSI_CAP_MC_MASK; - c->cap_aen = ntohl(gc->aen_cap) & NCSI_CAP_AEN_MASK; - c->cap_vlan = ntohl(gc->vlan_mode) & NCSI_CAP_VLAN_MASK; + c->cap_generic = get_unaligned_be32(&gc->cap) & NCSI_CAP_GENERIC_MASK; + c->cap_bc = get_unaligned_be32(&gc->bc_cap) & NCSI_CAP_BC_MASK; + c->cap_mc = get_unaligned_be32(&gc->mc_cap) & NCSI_CAP_MC_MASK; + c->cap_aen = get_unaligned_be32(&gc->aen_cap) & NCSI_CAP_AEN_MASK; + c->cap_vlan = gc->vlan_mode & NCSI_CAP_VLAN_MASK; /* End of probe for this channel */ } -- cgit v1.3.1 From 85d44e424a32b49f2c9ddf002a684e43bb7828c1 Mon Sep 17 00:00:00 2001 From: Marjolaine Amate Date: Mon, 4 Mar 2024 16:23:38 +0100 Subject: e1000: add support for i225-IT This patch adds support for i225-IT in e1000 driver. Add e1000_phy_igc. Signed-off-by: Marjolaine Amate --- drivers/net/e1000.c | 15 ++++++++++++++- drivers/net/e1000.h | 2 ++ include/pci_ids.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 84a2a7cf904..4e7ba666770 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -116,6 +116,8 @@ static struct pci_device_id e1000_supported[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_1000BASEKX) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_IT) }, {} }; @@ -1575,6 +1577,8 @@ e1000_set_mac_type(struct e1000_hw *hw) case PCI_DEVICE_ID_INTEL_I210_SERDES: case PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS: case PCI_DEVICE_ID_INTEL_I210_1000BASEKX: + case PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED: + case PCI_DEVICE_ID_INTEL_I225_IT: hw->mac_type = e1000_igb; break; default: @@ -3258,7 +3262,8 @@ e1000_setup_copper_link(struct e1000_hw *hw) if (ret_val) return ret_val; } else if (hw->phy_type == e1000_phy_m88 || - hw->phy_type == e1000_phy_igb) { + hw->phy_type == e1000_phy_igb || + hw->phy_type == e1000_phy_igc) { ret_val = e1000_copper_link_mgp_setup(hw); if (ret_val) return ret_val; @@ -4531,6 +4536,8 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw) case e1000_igb: while (timeout) { if (hw->mac_type == e1000_igb) { + if (hw->phy_type == e1000_phy_igc) + break; if (E1000_READ_REG(hw, I210_EEMNGCTL) & cfg_mask) break; } else { @@ -4769,6 +4776,7 @@ e1000_phy_reset(struct e1000_hw *hw) case e1000_phy_igp_3: case e1000_phy_ife: case e1000_phy_igb: + case e1000_phy_igc: ret_val = e1000_phy_hw_reset(hw); if (ret_val) return ret_val; @@ -4834,6 +4842,9 @@ static int e1000_set_phy_type (struct e1000_hw *hw) case I210_I_PHY_ID: hw->phy_type = e1000_phy_igb; break; + case I225_I_PHY_ID: + hw->phy_type = e1000_phy_igc; + break; /* Fall Through */ default: /* Should never have loaded on this device */ @@ -4941,6 +4952,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw) case e1000_igb: if (hw->phy_id == I210_I_PHY_ID) match = true; + if (hw->phy_id == I225_I_PHY_ID) + match = true; break; default: DEBUGOUT("Invalid MAC type %d\n", hw->mac_type); diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index f788394da87..e1311126a3f 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -212,6 +212,7 @@ typedef enum { e1000_phy_igp_3, e1000_phy_ife, e1000_phy_igb, + e1000_phy_igc, e1000_phy_bm, e1000_phy_undefined = 0xFF } e1000_phy_type; @@ -2420,6 +2421,7 @@ struct e1000_hw { #define BME1000_E_PHY_ID 0x01410CB0 #define I210_I_PHY_ID 0x01410C00 +#define I225_I_PHY_ID 0x67C9DCC0 /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF diff --git a/include/pci_ids.h b/include/pci_ids.h index b63bf45168d..f1886c3a751 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -2710,6 +2710,8 @@ #define PCI_DEVICE_ID_INTEL_I211_COPPER 0x1539 #define PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS 0x157b #define PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS 0x157c +#define PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED 0x15dF +#define PCI_DEVICE_ID_INTEL_I225_IT 0x0d9f #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 -- cgit v1.3.1 From e99a6efa80eaf69aa07d5845f6d2bb362a81c0dd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 18 Mar 2024 15:57:01 +0100 Subject: net: phy: Factor out PHY GPIO reset code Pull the PHY GPIO reset code into separate function, since this is and will be reused multiple times. Set up default reset assert and deassert timing to generous 20ms and 1ms for maximum compatibility in case those DT properties are missing. Reviewed-by: Ramon Fried Signed-off-by: Marek Vasut --- drivers/net/phy/ethernet_id.c | 37 ++++------------------------- drivers/net/phy/phy.c | 55 +++++++++++++++++++++++++++++++++++++++++++ include/phy.h | 9 +++++++ 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c index 6cb1fd4453e..4dfdee60dcc 100644 --- a/drivers/net/phy/ethernet_id.c +++ b/drivers/net/phy/ethernet_id.c @@ -18,12 +18,11 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev, { struct phy_device *phydev; struct ofnode_phandle_args phandle_args; - struct gpio_desc gpio; const char *node_name; struct udevice *pdev; - ofnode node; - u32 id, assert, deassert; u16 vendor, device; + ofnode node; + u32 id; int ret; if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, @@ -41,35 +40,9 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev, return NULL; } - if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) { - ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, - GPIOD_IS_OUT | GPIOD_ACTIVE_LOW); - if (!ret) { - assert = ofnode_read_u32_default(node, - "reset-assert-us", 0); - deassert = ofnode_read_u32_default(node, - "reset-deassert-us", - 0); - ret = dm_gpio_set_value(&gpio, 1); - if (ret) { - dev_err(dev, - "Failed assert gpio, err: %d\n", ret); - return NULL; - } - - udelay(assert); - - ret = dm_gpio_set_value(&gpio, 0); - if (ret) { - dev_err(dev, - "Failed deassert gpio, err: %d\n", - ret); - return NULL; - } - - udelay(deassert); - } - } + ret = phy_gpio_reset(dev); + if (ret) + return NULL; if (phyaddr == -1) phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9cec04a0c94..270176cfe62 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -769,6 +771,59 @@ int miiphy_reset(const char *devname, unsigned char addr) return phy_reset(phydev); } +#if CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_REAL) && \ + !IS_ENABLED(CONFIG_DM_ETH_PHY) +int phy_gpio_reset(struct udevice *dev) +{ + struct ofnode_phandle_args phandle_args; + struct gpio_desc gpio; + u32 assert, deassert; + ofnode node; + int ret; + + ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, + &phandle_args); + /* No PHY handle is OK */ + if (ret) + return 0; + + node = phandle_args.node; + if (!ofnode_valid(node)) + return -EINVAL; + + ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, + GPIOD_IS_OUT | GPIOD_ACTIVE_LOW); + /* No PHY reset GPIO is OK */ + if (ret) + return 0; + + assert = ofnode_read_u32_default(node, "reset-assert-us", 20000); + deassert = ofnode_read_u32_default(node, "reset-deassert-us", 1000); + ret = dm_gpio_set_value(&gpio, 1); + if (ret) { + dev_err(dev, "Failed assert gpio, err: %d\n", ret); + return ret; + } + + udelay(assert); + + ret = dm_gpio_set_value(&gpio, 0); + if (ret) { + dev_err(dev, "Failed deassert gpio, err: %d\n", ret); + return ret; + } + + udelay(deassert); + + return 0; +} +#else +int phy_gpio_reset(struct udevice *dev) +{ + return 0; +} +#endif + struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask) { /* Reset the bus */ diff --git a/include/phy.h b/include/phy.h index ae23814bbf3..90b7e364101 100644 --- a/include/phy.h +++ b/include/phy.h @@ -183,6 +183,15 @@ struct fixed_link { */ int phy_reset(struct phy_device *phydev); +/** + * phy_gpio_reset() - Resets the specified PHY using GPIO reset + * Toggles the optional PHY reset GPIO + * + * @dev: PHY udevice to reset + * @return: 0 if OK, -ve on error + */ +int phy_gpio_reset(struct udevice *dev); + /** * phy_find_by_mask() - Searches for a PHY on the specified MDIO bus * The function checks the PHY addresses flagged in phy_mask and returns a -- cgit v1.3.1 From 052bff838ba34a8f882800fdd78d97370565d2c5 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 5 Mar 2024 15:24:53 +0200 Subject: net: mdio-uclass: Bind and probe generic Ethernet PHY driver If DM_ETH_PHY is enabled then try to bind and probe the generic Ethernet PHY driver for each child of MDIO bus. This is to ensure that GPIO reset handling is done if available before MDIO bus driver scans for the PHYs. Signed-off-by: Roger Quadros --- net/mdio-uclass.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c index 6fc7034111f..0ebfb2f1343 100644 --- a/net/mdio-uclass.c +++ b/net/mdio-uclass.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -121,6 +123,42 @@ static int mdio_reset(struct mii_dev *mii_bus) return dm_mdio_reset(mii_bus->priv); } +static int mdio_bind_phy_nodes(struct udevice *mdio_dev) +{ + ofnode mdio_node, phy_node; + struct udevice *phy_dev; + const char *node_name; + int ret; + + mdio_node = dev_ofnode(mdio_dev); + if (!ofnode_valid(mdio_node)) { + dev_dbg(mdio_dev, "invalid ofnode for mdio_dev\n"); + return -ENXIO; + } + + ofnode_for_each_subnode(phy_node, mdio_node) { + node_name = ofnode_get_name(phy_node); + dev_dbg(mdio_dev, "* Found child node: '%s'\n", node_name); + ret = device_bind_driver_to_node(mdio_dev, + "eth_phy_generic_drv", + node_name, phy_node, &phy_dev); + if (ret) { + dev_dbg(mdio_dev, " - Eth phy binding error: %d\n", ret); + continue; + } + + dev_dbg(mdio_dev, " - bound phy device: '%s'\n", node_name); + ret = device_probe(phy_dev); + if (ret) { + dev_dbg(mdio_dev, "Device '%s' probe failed\n", phy_dev->name); + device_unbind(phy_dev); + continue; + } + } + + return 0; +} + static int dm_mdio_post_probe(struct udevice *dev) { struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev); @@ -154,6 +192,9 @@ static int dm_mdio_post_probe(struct udevice *dev) } } + if (CONFIG_IS_ENABLED(DM_ETH_PHY)) + mdio_bind_phy_nodes(dev); + return mdio_register(pdata->mii_bus); } -- cgit v1.3.1 From ba291718d7ab9ca0dc1c3c357d817bb12f587af0 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 5 Mar 2024 15:24:54 +0200 Subject: configs/am62x_beagleplay_a53_defconfig: enable DM_ETH_PHY Reset GPIO handling is done in ETH PHY Class driver. Enable DM_ETH_PHY. We don't use Fixed PHY so disable PHY_FIXED. Signed-off-by: Roger Quadros --- configs/am62x_beagleplay_a53_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/am62x_beagleplay_a53_defconfig b/configs/am62x_beagleplay_a53_defconfig index 88784505c30..d9751bca666 100644 --- a/configs/am62x_beagleplay_a53_defconfig +++ b/configs/am62x_beagleplay_a53_defconfig @@ -88,9 +88,9 @@ CONFIG_SPL_MMC_SDHCI_ADMA=y CONFIG_MMC_SDHCI_AM654=y CONFIG_PHY_REALTEK=y CONFIG_PHY_TI=y -CONFIG_PHY_FIXED=y CONFIG_TI_AM65_CPSW_NUSS=y CONFIG_PHY=y +CONFIG_DM_ETH_PHY=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_SINGLE=y -- cgit v1.3.1