diff options
| author | Tom Rini <[email protected]> | 2026-05-06 08:44:55 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-05-06 08:44:55 -0600 |
| commit | 980f8a4589626ca2b9c6c5f74eefe72f4b5606c6 (patch) | |
| tree | 85f6976ec8145a37453ede406afc5aad72811183 | |
| parent | ffdce9d3fbd7c4d0d4d9f241d32ef2970ee8800b (diff) | |
| parent | 5245bdc98b9fff46e4bcec2e44e915be44824537 (diff) | |
Merge tag 'net-20260506' of https://source.denx.de/u-boot/custodians/u-boot-net
Pull request net-20260506.
net:
- phy: dp83867: default to 2ns delay if unspecified in device-tree
- nfs: fix buffer overflow in nfs_readlink_reply()
- cpsw: Add cpsw-switch DT binding support
- phy: add common PHY polarity properties support
- phy: adin: add support for the ADIN1200 phy
- macb: support for instances with less features
- phy: mscc: add support for the VSC8572
net-lwip:
- wget: correct diagnostic output
| -rw-r--r-- | arch/sandbox/dts/test.dts | 60 | ||||
| -rw-r--r-- | configs/sandbox_defconfig | 1 | ||||
| -rw-r--r-- | drivers/net/macb.c | 94 | ||||
| -rw-r--r-- | drivers/net/macb.h | 2 | ||||
| -rw-r--r-- | drivers/net/phy/adin.c | 13 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/air_en8811.c | 60 | ||||
| -rw-r--r-- | drivers/net/phy/dp83867.c | 16 | ||||
| -rw-r--r-- | drivers/net/phy/mscc.c | 11 | ||||
| -rw-r--r-- | drivers/net/ti/cpsw.c | 188 | ||||
| -rw-r--r-- | drivers/phy/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/phy/phy-common-props.c | 286 | ||||
| -rw-r--r-- | include/linux/phy/phy-common-props.h | 69 | ||||
| -rw-r--r-- | net/lwip/wget.c | 18 | ||||
| -rw-r--r-- | net/nfs-common.c | 4 | ||||
| -rw-r--r-- | test/dm/Makefile | 1 | ||||
| -rw-r--r-- | test/dm/phy_common_props.c | 319 |
18 files changed, 1045 insertions, 107 deletions
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index ac92ebf1afd..0887de4333b 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -16,6 +16,7 @@ #include <dt-bindings/leds/common.h> #include <dt-bindings/pinctrl/sandbox-pinmux.h> #include <dt-bindings/mux/mux.h> +#include <dt-bindings/phy/phy.h> / { model = "sandbox"; @@ -502,6 +503,65 @@ phy-names = "phy1"; }; + /* PHY common props test nodes */ + phy_common_props_missing: phy-common-props-missing { + /* empty: no rx-polarity or tx-polarity properties */ + }; + + phy_common_props_more_values: phy-common-props-more-values { + /* 3 values but only 2 names => count mismatch */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + rx-polarity-names = "sgmii", "2500base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + tx-polarity-names = "sgmii", "2500base-x"; + }; + + phy_common_props_single: phy-common-props-single { + /* 1 value, no names array => value applies to all modes */ + rx-polarity = <PHY_POL_INVERT>; + tx-polarity = <PHY_POL_INVERT>; + }; + + phy_common_props_more_names: phy-common-props-more-names { + /* 2 values but 3 names => count mismatch */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + }; + + phy_common_props_find_by_name: phy-common-props-find-by-name { + /* valid 3-element arrays, lookup by mode name */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_AUTO>; + rx-polarity-names = "sgmii", "2500base-x", "usb-ss"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + tx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + }; + + phy_common_props_no_default: phy-common-props-no-default { + /* name not in array, no "default" entry => -EINVAL */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "2500base-x", "1000base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "2500base-x", "1000base-x"; + }; + + phy_common_props_with_default: phy-common-props-with-default { + /* name not in array, but "default" entry exists */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "2500base-x", "default"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "2500base-x", "default"; + }; + + phy_common_props_unsupported: phy-common-props-unsupported { + /* PHY_POL_AUTO is not supported for manual-only modes */ + rx-polarity = <PHY_POL_AUTO>; + rx-polarity-names = "sgmii"; + tx-polarity = <PHY_POL_AUTO>; + tx-polarity-names = "sgmii"; + }; + some-bus { #address-cells = <1>; #size-cells = <0>; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index f26295103f1..55dc7845544 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -285,6 +285,7 @@ CONFIG_PCI_REGION_MULTI_ENTRY=y CONFIG_PCI_FTPCI100=y CONFIG_PCI_SANDBOX=y CONFIG_PHY=y +CONFIG_PHY_COMMON_PROPS=y CONFIG_PHY_SANDBOX=y CONFIG_PINCTRL=y CONFIG_PINCONF=y diff --git a/drivers/net/macb.c b/drivers/net/macb.c index cbf5f605518..bea1dfed892 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -38,9 +38,13 @@ #include <linux/mii.h> #include <asm/io.h> #include <linux/dma-mapping.h> -#include <asm/arch/clk.h> #include <linux/errno.h> +/* Without CLK, we rely on the arch definition */ +#if !defined(CONFIG_CLK) +#include <asm/arch/clk.h> +#endif + #include "macb.h" DECLARE_GLOBAL_DATA_PTR; @@ -768,18 +772,40 @@ static int macb_phy_init(struct udevice *dev, const char *name) lpa); } else { /* if macb port is a fixed link */ - /* TODO : manage gigabit capable processors */ + const char *human_readable_speed; + speed = macb->speed; duplex = macb->duplex; + switch (speed) { + case 2: + human_readable_speed = "1000"; + break; + case 1: + human_readable_speed = "100"; + break; + case 0: + human_readable_speed = "10"; + break; + default: + printf("%s: speed %d not supported\n", name, speed); + return -EINVAL; + } printf("%s: link up, %sMbps %s-duplex\n", name, - speed ? "100" : "10", + human_readable_speed, duplex ? "full" : "half"); } ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); - if (speed) { + if (speed == 2) { + if (!gem_is_gigabit_capable(macb)) { + printf("%s: is not gigabit Ethernet capable\n", name); + return -EINVAL; + } + ncfgr |= GEM_BIT(GBE); + ret = macb_linkspd_cb(dev, _1000BASET); + } else if (speed == 1) { ncfgr |= MACB_BIT(SPD); ret = macb_linkspd_cb(dev, _100BASET); } else { @@ -923,26 +949,39 @@ static int _macb_init(struct udevice *dev, const char *name) /* Check the multi queue and initialize the queue for tx */ gmac_init_multi_queues(macb); - /* - * When the GMAC IP with GE feature, this bit is used to - * select interface between RGMII and GMII. - * When the GMAC IP without GE feature, this bit is used - * to select interface between RMII and MII. + /* This driver uses the user I/O to select the PHY features, + * but some GEM instances come with a fixed configuration and + * no USERIO. */ - if (macb->phy_interface == PHY_INTERFACE_MODE_RGMII || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) - val = macb->config->usrio->rgmii; - else if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) - val = macb->config->usrio->rmii; - else if (macb->phy_interface == PHY_INTERFACE_MODE_MII) - val = macb->config->usrio->mii; + if (gem_readl(macb, DCFG1) & GEM_BIT(USERIO)) { + /* + * When the GMAC IP with GE feature, this bit is used to + * select interface between RGMII and GMII. + * When he GMAC IP without GE feature, this bit is used + * to select interface between RMII and MII. + */ + switch (macb->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + val = macb->config->usrio->rgmii; + break; + case PHY_INTERFACE_MODE_RMII: + val = macb->config->usrio->rmii; + break; + case PHY_INTERFACE_MODE_MII: + val = macb->config->usrio->mii; + break; + default: + break; + } - if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN) - val |= macb->config->usrio->clken; + if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN) + val |= macb->config->usrio->clken; - gem_writel(macb, USRIO, val); + gem_writel(macb, USRIO, val); + } if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) { unsigned int ncfgr = macb_readl(macb, NCFGR); @@ -1003,9 +1042,14 @@ static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) /* set hardware address */ hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | enetaddr[2] << 16 | enetaddr[3] << 24; - macb_writel(macb, SA1B, hwaddr_bottom); hwaddr_top = enetaddr[4] | enetaddr[5] << 8; - macb_writel(macb, SA1T, hwaddr_top); + if (macb_is_gem(macb)) { + gem_writel(macb, SA1B, hwaddr_bottom); + gem_writel(macb, SA1T, hwaddr_top); + } else { + macb_writel(macb, SA1B, hwaddr_bottom); + macb_writel(macb, SA1T, hwaddr_top); + } return 0; } @@ -1307,7 +1351,9 @@ static int macb_eth_of_to_plat(struct udevice *dev) macb->phy_addr = PHY_MAX_ADDR + 1; macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0); - if (speed_fdt == 100) { + if (speed_fdt == 1000) { + macb->speed = 2; + } else if (speed_fdt == 100) { macb->speed = 1; } else if (speed_fdt == 10) { macb->speed = 0; diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 0eb90574618..002d5bd31b2 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -443,6 +443,8 @@ #define MACB_REV_SIZE 16 /* Bitfields in DCFG1. */ +#define GEM_USERIO_OFFSET 9 +#define GEM_USERIO_SIZE 1 #define GEM_IRQCOR_OFFSET 23 #define GEM_IRQCOR_SIZE 1 #define GEM_DBWDEF_OFFSET 25 diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c index ce448810ff6..4d42e56dada 100644 --- a/drivers/net/phy/adin.c +++ b/drivers/net/phy/adin.c @@ -10,6 +10,7 @@ #include <linux/bitops.h> #include <linux/bitfield.h> +#define PHY_ID_ADIN1200 0x0283bc20 #define PHY_ID_ADIN1300 0x0283bc30 #define ADIN1300_EXT_REG_PTR 0x10 #define ADIN1300_EXT_REG_DATA 0x11 @@ -263,6 +264,18 @@ static int adin1300_config(struct phy_device *phydev) return genphy_config(phydev); } +U_BOOT_PHY_DRIVER(ADIN1200) = { + .name = "ADIN1200", + .uid = PHY_ID_ADIN1200, + .mask = 0xffffffff, + .features = PHY_BASIC_FEATURES, + .config = adin1300_config, + .startup = genphy_startup, + .shutdown = genphy_shutdown, + .readext = adin_extread, + .writeext = adin_extwrite, +}; + U_BOOT_PHY_DRIVER(ADIN1300) = { .name = "ADIN1300", .uid = PHY_ID_ADIN1300, diff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig index da8747939e3..4139df343ad 100644 --- a/drivers/net/phy/airoha/Kconfig +++ b/drivers/net/phy/airoha/Kconfig @@ -7,6 +7,7 @@ config PHY_AIROHA_EN8811 depends on PHY_AIROHA depends on SUPPORTS_FW_LOADER select FW_LOADER + select PHY_COMMON_PROPS help AIROHA EN8811H supported. AIROHA AN8811HB supported. diff --git a/drivers/net/phy/airoha/air_en8811.c b/drivers/net/phy/airoha/air_en8811.c index 0b974472732..32f06dd6dfa 100644 --- a/drivers/net/phy/airoha/air_en8811.c +++ b/drivers/net/phy/airoha/air_en8811.c @@ -23,6 +23,7 @@ #include <linux/compat.h> #include <dm/device_compat.h> #include <u-boot/crc.h> +#include <linux/phy/phy-common-props.h> /* MII Registers */ #define AIR_AUX_CTRL_STATUS 0x1d @@ -1046,11 +1047,50 @@ static int air_leds_init(struct phy_device *phydev, int num, u16 dur, int mode) return 0; } -static int en8811h_config(struct phy_device *phydev) +static int en8811h_config_serdes_polarity(struct phy_device *phydev) { - struct en8811h_priv *priv = phydev->priv; ofnode node = phy_get_ofnode(phydev); + unsigned int pol, default_pol; u32 pbus_value = 0; + int ret; + + if (!ofnode_valid(node)) + return 0; + + default_pol = PHY_POL_NORMAL; + if (ofnode_read_bool(node, "airoha,pnswap-rx")) + default_pol = PHY_POL_INVERT; + + ret = phy_get_rx_polarity(node, + phy_string_for_interface(phydev->interface), + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + default_pol, &pol); + if (ret) + return ret; + if (pol == PHY_POL_INVERT) + pbus_value |= EN8811H_POLARITY_RX_REVERSE; + + default_pol = PHY_POL_NORMAL; + if (ofnode_read_bool(node, "airoha,pnswap-tx")) + default_pol = PHY_POL_INVERT; + + ret = phy_get_tx_polarity(node, + phy_string_for_interface(phydev->interface), + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + default_pol, &pol); + if (ret) + return ret; + if (pol == PHY_POL_NORMAL) + pbus_value |= EN8811H_POLARITY_TX_NORMAL; + + return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, + EN8811H_POLARITY_RX_REVERSE | + EN8811H_POLARITY_TX_NORMAL, pbus_value); +} + +static int en8811h_config(struct phy_device *phydev) +{ + struct en8811h_priv *priv = phydev->priv; int ret = 0; /* If restart happened in .probe(), no need to restart now */ @@ -1081,20 +1121,8 @@ static int en8811h_config(struct phy_device *phydev) if (ret < 0) return ret; - /* Serdes polarity */ - pbus_value = 0; - if (ofnode_read_bool(node, "airoha,pnswap-rx")) - pbus_value |= EN8811H_POLARITY_RX_REVERSE; - else - pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; - if (ofnode_read_bool(node, "airoha,pnswap-tx")) - pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; - else - pbus_value |= EN8811H_POLARITY_TX_NORMAL; - ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, - EN8811H_POLARITY_RX_REVERSE | - EN8811H_POLARITY_TX_NORMAL, - pbus_value); + /* Configure Serdes polarity from device tree */ + ret = en8811h_config_serdes_polarity(phydev); if (ret < 0) return ret; diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 7ce03b59b6a..ebed61de133 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -203,32 +203,24 @@ static int dp83867_of_init(struct phy_device *phydev) "Should be 'rgmii-id' to use internal delays\n"); } - /* RX delay *must* be specified if internal delay of RX is used. */ + dp83867->rx_id_delay = DP83867_RGMIIDCTL_2_00_NS; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { ret = ofnode_read_u32(node, "ti,rx-internal-delay", &dp83867->rx_id_delay); - if (ret) { - pr_debug("ti,rx-internal-delay must be specified\n"); - return ret; - } - if (dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { + if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { pr_debug("ti,rx-internal-delay value of %u out of range\n", dp83867->rx_id_delay); return -EINVAL; } } - /* TX delay *must* be specified if internal delay of RX is used. */ + dp83867->tx_id_delay = DP83867_RGMIIDCTL_2_00_NS; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { ret = ofnode_read_u32(node, "ti,tx-internal-delay", &dp83867->tx_id_delay); - if (ret) { - debug("ti,tx-internal-delay must be specified\n"); - return ret; - } - if (dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { + if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { pr_debug("ti,tx-internal-delay value of %u out of range\n", dp83867->tx_id_delay); return -EINVAL; diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index a65e81dff0c..d96970949bc 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -23,6 +23,7 @@ #define PHY_ID_VSC8502 0x00070630 #define PHY_ID_VSC8540 0x00070760 #define PHY_ID_VSC8541 0x00070770 +#define PHY_ID_VSC8572 0x000704d0 #define PHY_ID_VSC8574 0x000704a0 #define PHY_ID_VSC8584 0x000707c0 @@ -1612,6 +1613,16 @@ U_BOOT_PHY_DRIVER(vsc8541) = { .shutdown = &genphy_shutdown, }; +U_BOOT_PHY_DRIVER(vsc8572) = { + .name = "Microsemi VSC8572", + .uid = PHY_ID_VSC8572, + .mask = 0x000ffff0, + .features = PHY_GBIT_FEATURES, + .config = &vsc8574_config, + .startup = &mscc_startup, + .shutdown = &genphy_shutdown, +}; + U_BOOT_PHY_DRIVER(vsc8574) = { .name = "Microsemi VSC8574", .uid = PHY_ID_VSC8574, diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c index d7746f454ba..7a7cb83bd98 100644 --- a/drivers/net/ti/cpsw.c +++ b/drivers/net/ti/cpsw.c @@ -33,6 +33,7 @@ #define PKT_MAX (1500 + 14 + 4 + 4) #define CLEAR_BIT 1 #define GIGABITEN BIT(7) +#define GMII_EN BIT(5) #define FULLDUPLEXEN BIT(0) #define MIIEN BIT(15) #define CTL_EXT_EN BIT(18) @@ -216,6 +217,10 @@ struct cpsw_priv { u32 phy_mask; }; +struct cpsw_driver_data { + void (*gmii_sel)(struct cpsw_priv *priv, phy_interface_t phy_mode); +}; + static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) { int idx; @@ -1064,9 +1069,17 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, writel(reg, priv->data->gmii_sel); } -static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, - phy_interface_t phy_mode) +static void cpsw_phy_sel(struct cpsw_priv *priv, phy_interface_t phy_mode) { + const char *compat = priv->data->phy_sel_compat; + const struct cpsw_driver_data *drv_data = + (const struct cpsw_driver_data *)dev_get_driver_data(priv->dev); + + if (drv_data && drv_data->gmii_sel) { + drv_data->gmii_sel(priv, phy_mode); + return; + } + if (!strcmp(compat, "ti,am3352-cpsw-phy-sel")) cpsw_gmii_sel_am3352(priv, phy_mode); if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel")) @@ -1084,8 +1097,7 @@ static int cpsw_eth_probe(struct udevice *dev) priv->data = pdata->priv_pdata; ti_cm_get_macid(dev, priv->data, pdata->enetaddr); /* Select phy interface in control module */ - cpsw_phy_sel(priv, priv->data->phy_sel_compat, - pdata->phy_interface); + cpsw_phy_sel(priv, pdata->phy_interface); return _cpsw_register(priv); } @@ -1122,33 +1134,13 @@ static void cpsw_eth_of_parse_slave(struct cpsw_platform_data *data, "max-speed", 0); } -static int cpsw_eth_of_to_plat(struct udevice *dev) +static int cpsw_eth_of_to_plat_legacy(struct udevice *dev, + struct cpsw_platform_data *data) { - struct eth_pdata *pdata = dev_get_plat(dev); - struct cpsw_platform_data *data; - struct gpio_desc *mode_gpios; int slave_index = 0; - int num_mode_gpios; ofnode subnode; int ret; - data = calloc(1, sizeof(struct cpsw_platform_data)); - if (!data) - return -ENOMEM; - - pdata->priv_pdata = data; - pdata->iobase = dev_read_addr(dev); - data->version = CPSW_CTRL_VERSION_2; - data->bd_ram_ofs = CPSW_BD_OFFSET; - data->ale_reg_ofs = CPSW_ALE_OFFSET; - data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; - data->mdio_div = CPSW_MDIO_DIV; - data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, - - pdata->phy_interface = -1; - - data->cpsw_base = pdata->iobase; - ret = dev_read_s32(dev, "cpdma_channels", &data->channels); if (ret) { printf("error: cpdma_channels not found in dt\n"); @@ -1177,21 +1169,10 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) ret = dev_read_u32(dev, "mac_control", &data->mac_control); if (ret) { - printf("error: ale_entries not found in dt\n"); + printf("error: mac_control not found in dt\n"); return ret; } - num_mode_gpios = gpio_get_list_count(dev, "mode-gpios"); - if (num_mode_gpios > 0) { - mode_gpios = malloc(sizeof(struct gpio_desc) * - num_mode_gpios); - gpio_request_list_by_name(dev, "mode-gpios", mode_gpios, - num_mode_gpios, GPIOD_IS_OUT); - free(mode_gpios); - } - - data->active_slave = dev_read_u32_default(dev, "active_slave", 0); - ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { const char *name; @@ -1222,16 +1203,118 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) if (ofnode_read_bool(subnode, "rmii-clock-ext")) data->rmii_clock_external = true; + } + } - data->phy_sel_compat = ofnode_read_string(subnode, - "compatible"); - if (!data->phy_sel_compat) { - pr_err("Not able to get gmii_sel compatible\n"); - return -ENOENT; - } + return 0; +} + +static int cpsw_eth_of_to_plat_switch(struct udevice *dev, + struct cpsw_platform_data *data) +{ + ofnode eth_ports_node, subnode; + int ret; + + data->channels = 8; + data->ale_entries = 1024; + data->mac_control = GMII_EN; + + eth_ports_node = ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports"); + data->slaves = ofnode_get_child_count(eth_ports_node); + if (!data->slaves) { + pr_err("cpsw: No ethernet-ports defined\n"); + return -EINVAL; + } + + data->slave_data = malloc(sizeof(struct cpsw_slave_data) * data->slaves); + if (!data->slave_data) + return -ENOMEM; + + ofnode_for_each_subnode(subnode, eth_ports_node) { + struct ofnode_phandle_args args; + u32 port_id; + + ret = ofnode_read_u32(subnode, "reg", &port_id); + if (ret || !port_id || port_id > data->slaves) { + pr_err("cpsw: invalid or missing reg in port node\n"); + return -EINVAL; + } + + cpsw_eth_of_parse_slave(data, port_id - 1, subnode); + + if (!data->gmii_sel) { + ret = ofnode_parse_phandle_with_args(subnode, "phys", "#phy-cells", + 0, 0, &args); + if (!ret) + data->gmii_sel = ofnode_get_addr(args.node); + } + } + + if (!data->gmii_sel) { + pr_err("No port specified phys correctly\n"); + return -ENOENT; + } + + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + const char *name = ofnode_get_name(subnode); + + if (strncmp(name, "mdio", 4)) + continue; + + data->mdio_base = ofnode_get_addr(subnode); + if (data->mdio_base == FDT_ADDR_T_NONE) { + pr_err("Not able to get MDIO address space\n"); + return -ENOENT; } } + return 0; +} + +static int cpsw_eth_of_to_plat(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct cpsw_platform_data *data; + struct gpio_desc *mode_gpios; + int num_mode_gpios; + int ret; + bool switch_dt_bindings = + ofnode_valid(ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports")); + + data = calloc(1, sizeof(struct cpsw_platform_data)); + if (!data) + return -ENOMEM; + + pdata->priv_pdata = data; + pdata->iobase = dev_read_addr(dev); + data->version = CPSW_CTRL_VERSION_2; + data->bd_ram_ofs = CPSW_BD_OFFSET; + data->ale_reg_ofs = CPSW_ALE_OFFSET; + data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; + data->mdio_div = CPSW_MDIO_DIV; + data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET; + + pdata->phy_interface = -1; + + data->cpsw_base = pdata->iobase; + + num_mode_gpios = gpio_get_list_count(dev, "mode-gpios"); + if (num_mode_gpios > 0) { + mode_gpios = malloc(sizeof(struct gpio_desc) * num_mode_gpios); + gpio_request_list_by_name(dev, "mode-gpios", mode_gpios, + num_mode_gpios, GPIOD_IS_OUT); + free(mode_gpios); + } + + data->active_slave = dev_read_u32_default(dev, "active_slave", 0); + + if (switch_dt_bindings) + ret = cpsw_eth_of_to_plat_switch(dev, data); + else + ret = cpsw_eth_of_to_plat_legacy(dev, data); + if (ret) + return ret; + data->slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; data->slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; @@ -1253,9 +1336,22 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) return 0; } +static const struct cpsw_driver_data cpsw_data_am3352 = { + .gmii_sel = cpsw_gmii_sel_am3352, +}; + +static const struct cpsw_driver_data cpsw_data_dra7xx = { + .gmii_sel = cpsw_gmii_sel_dra7xx, +}; + static const struct udevice_id cpsw_eth_ids[] = { - { .compatible = "ti,cpsw" }, - { .compatible = "ti,am335x-cpsw" }, + { .compatible = "ti,cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am335x-cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am4372-cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,dra7-cpsw", .data = (ulong)&cpsw_data_dra7xx }, + { .compatible = "ti,am335x-cpsw-switch", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am4372-cpsw-switch", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,dra7-cpsw-switch", .data = (ulong)&cpsw_data_dra7xx }, { } }; #endif diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index fc4daa00661..5c8ec2b146f 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -350,4 +350,12 @@ source "drivers/phy/qcom/Kconfig" source "drivers/phy/renesas/Kconfig" source "drivers/phy/starfive/Kconfig" +config PHY_COMMON_PROPS + bool "Common PHY properties support" + help + Enable support for common PHY properties defined in the device tree, + such as rx-polarity and tx-polarity. This provides helpers for PHY + drivers to read polarity and other standard PHY properties from the + device tree node. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 684e9a99af8..e46c362878d 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o obj-$(CONFIG_$(PHASE_)PHY_IMX8MQ_USB) += phy-imx8mq-usb.o obj-$(CONFIG_PHY_IMX8M_PCIE) += phy-imx8m-pcie.o obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o +obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o obj-y += cadence/ obj-y += ti/ obj-y += qcom/ diff --git a/drivers/phy/phy-common-props.c b/drivers/phy/phy-common-props.c new file mode 100644 index 00000000000..0a0b4439430 --- /dev/null +++ b/drivers/phy/phy-common-props.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * phy-common-props.c -- Common PHY properties + * + * Copyright 2025-2026 NXP + */ +#include <dm/ofnode.h> +#include <log.h> +#include <malloc.h> +#include <linux/phy/phy-common-props.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/errno.h> + +/** + * ofnode_count_u32_prop - Count number of u32 elements in a property + * @node: Device tree node + * @propname: Property name + * + * Return: number of u32 elements, or negative error code + */ +static int ofnode_count_u32_prop(ofnode node, const char *propname) +{ + int size; + + size = ofnode_read_size(node, propname); + if (size < 0) { + pr_debug("%s: property '%s' not found (err=%d)\n", + __func__, propname, size); + return size; + } + + pr_debug("%s: property '%s' has %zu bytes (%zu elements)\n", + __func__, propname, (size_t)size, (size_t)(size / sizeof(u32))); + + return size / sizeof(u32); +} + +/** + * ofnode_get_u32_prop_for_name - Find u32 property by name, or default value + * @node: Device tree node; if invalid or @props_title is absent, @default_val is used + * @name: Property name used as lookup key in @names_title (must not be NULL) + * @props_title: Name of u32 array property holding values + * @names_title: Name of string array property holding lookup keys + * @default_val: Default value if @node is invalid, @props_title is absent, or empty + * @val: Pointer to store the returned value + * + * This function retrieves a u32 value from @props_title based on a name lookup + * in @names_title. The value stored in @val is determined as follows: + * + * - If @node is invalid or @props_title is absent: @default_val is used + * - If @props_title exists but is empty: @default_val is used + * - If @props_title has exactly one element and @names_title is empty: + * that element is used + * - Otherwise: @val is set to the element at the same index where @name is + * found in @names_title. + * - If @name is not found, the function looks for a "default" entry in + * @names_title and uses the corresponding value from @props_title + * + * When both @props_title and @names_title are present, they must have the + * same number of elements (except when @props_title has exactly one element). + * + * Return: zero on success, negative error on failure. + */ +static int ofnode_get_u32_prop_for_name(ofnode node, const char *name, + const char *props_title, + const char *names_title, + unsigned int default_val, + unsigned int *val) +{ + int err, n_props, n_names, idx; + u32 *props; + + if (!name) { + pr_err("Error: Lookup key inside \"%s\" is mandatory\n", + names_title); + return -EINVAL; + } + + pr_debug("%s: looking up '%s' in props='%s' names='%s' default=%u\n", + __func__, name, props_title, names_title, default_val); + + n_props = ofnode_count_u32_prop(node, props_title); + if (n_props < 0) { + /* property is absent */ + pr_debug("%s: '%s' is absent, using default value %u\n", + __func__, props_title, default_val); + *val = default_val; + return 0; + } + if (n_props == 0) { + /* property exists but is empty, use default */ + pr_debug("%s: '%s' is empty, using default value %u\n", + __func__, props_title, default_val); + *val = default_val; + return 0; + } + + n_names = ofnode_read_string_count(node, names_title); + + pr_debug("%s: '%s' has %d elements, '%s' has %d entries\n", + __func__, props_title, n_props, names_title, n_names); + if (n_names >= 0 && n_props != n_names) { + pr_err("Error: mismatch between \"%s\" and \"%s\" property count (%d vs %d)\n", + props_title, names_title, n_props, n_names); + return -EINVAL; + } + + idx = ofnode_stringlist_search(node, names_title, name); + if (idx >= 0) { + pr_debug("%s: found '%s' at index %d in '%s'\n", + __func__, name, idx, names_title); + } else { + pr_debug("%s: '%s' not found in '%s', trying 'default'\n", + __func__, name, names_title); + idx = ofnode_stringlist_search(node, names_title, "default"); + if (idx >= 0) + pr_debug("%s: 'default' entry found at index %d\n", + __func__, idx); + else + pr_debug("%s: 'default' entry not found in '%s'\n", + __func__, names_title); + } + /* + * If the mode name is missing, it can only mean the specified property + * is the default one for all modes, so reject any other property count + * than 1. + */ + if (idx < 0 && n_props != 1) { + pr_err("Error: \"%s\" property has %d elements, but cannot find \"%s\" in \"%s\" and there is no default value\n", + props_title, n_props, name, names_title); + return -EINVAL; + } + + if (n_props == 1) { + pr_debug("%s: single-element '%s', reading directly\n", + __func__, props_title); + err = ofnode_read_u32(node, props_title, val); + if (err) { + pr_debug("%s: failed to read '%s' (err=%d)\n", + __func__, props_title, err); + return err; + } + pr_debug("%s: resolved value %u for name '%s' from '%s'\n", + __func__, *val, name, props_title); + return 0; + } + + /* We implicitly know idx >= 0 here */ + props = calloc(n_props, sizeof(*props)); + if (!props) + return -ENOMEM; + + err = ofnode_read_u32_array(node, props_title, props, n_props); + if (err >= 0) { + *val = props[idx]; + pr_debug("%s: resolved value %u at index %d for name '%s' from '%s'\n", + __func__, *val, idx, name, props_title); + } else { + pr_debug("%s: failed to read u32 array '%s' (err=%d)\n", + __func__, props_title, err); + } + + free(props); + + return err; +} + +/** + * phy_get_polarity_for_mode - Get polarity for a specific PHY mode + * @node: Device tree node + * @mode_name: The name of the PHY mode to look up + * @supported: Bit mask of supported polarity values + * @default_val: Default polarity value if property is missing + * @polarity_prop: Name of the polarity property + * @names_prop: Name of the names property + * @val: Pointer to returned polarity + * + * Return: zero on success, negative error on failure. + */ +static int phy_get_polarity_for_mode(ofnode node, const char *mode_name, + unsigned int supported, + unsigned int default_val, + const char *polarity_prop, + const char *names_prop, + unsigned int *val) +{ + int err; + + pr_debug("%s: querying '%s' for mode '%s' (supported=0x%x, default=%u)\n", + __func__, polarity_prop, mode_name, supported, default_val); + + err = ofnode_get_u32_prop_for_name(node, mode_name, polarity_prop, + names_prop, default_val, val); + if (err) { + pr_debug("%s: '%s' lookup failed for mode '%s' (err=%d)\n", + __func__, polarity_prop, mode_name, err); + return err; + } + + pr_debug("%s: '%s' for mode '%s' = %u\n", + __func__, polarity_prop, mode_name, *val); + + if (!(supported & BIT(*val))) { + pr_err("Error: %d is not a supported value for '%s' element '%s'\n", + *val, polarity_prop, mode_name); + err = -EOPNOTSUPP; + } + + return err; +} + +/** + * phy_get_rx_polarity - Get RX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO + * @default_val: Default polarity value if property is missing + * @val: Pointer to returned polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_rx_polarity(ofnode node, const char *mode_name, + unsigned int supported, unsigned int default_val, + unsigned int *val) +{ + return phy_get_polarity_for_mode(node, mode_name, supported, + default_val, "rx-polarity", + "rx-polarity-names", val); +} + +/** + * phy_get_tx_polarity - Get TX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO + * @default_val: Default polarity value if property is missing + * @val: Pointer to returned polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_tx_polarity(ofnode node, const char *mode_name, + unsigned int supported, unsigned int default_val, + unsigned int *val) +{ + return phy_get_polarity_for_mode(node, mode_name, supported, + default_val, "tx-polarity", + "tx-polarity-names", val); +} + +/** + * phy_get_manual_rx_polarity - Get manual RX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @val: Pointer to returned polarity. + * + * Helper for PHYs which do not support protocols with automatic RX polarity + * detection and correction. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_manual_rx_polarity(ofnode node, const char *mode_name, + unsigned int *val) +{ + return phy_get_rx_polarity(node, mode_name, + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + PHY_POL_NORMAL, val); +} + +/** + * phy_get_manual_tx_polarity - Get manual TX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @val: Pointer to returned polarity. + * + * Helper for PHYs without any custom default value for the TX polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_manual_tx_polarity(ofnode node, const char *mode_name, + unsigned int *val) +{ + return phy_get_tx_polarity(node, mode_name, + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + PHY_POL_NORMAL, val); +} diff --git a/include/linux/phy/phy-common-props.h b/include/linux/phy/phy-common-props.h new file mode 100644 index 00000000000..9158851f2e1 --- /dev/null +++ b/include/linux/phy/phy-common-props.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * phy-common-props.h -- Common properties for generic PHYs + * + * Copyright 2025-2026 NXP + */ + +#ifndef __PHY_COMMON_PROPS_H +#define __PHY_COMMON_PROPS_H + +#include <dt-bindings/phy/phy.h> +#include <dm/ofnode.h> + +/** + * phy_get_rx_polarity - Get RX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO + * @default_val: Default polarity value if property is missing + * @val: Pointer to returned polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_rx_polarity(ofnode node, const char *mode_name, + unsigned int supported, unsigned int default_val, + unsigned int *val); + +/** + * phy_get_tx_polarity - Get TX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO + * @default_val: Default polarity value if property is missing + * @val: Pointer to returned polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_tx_polarity(ofnode node, const char *mode_name, + unsigned int supported, unsigned int default_val, + unsigned int *val); + +/** + * phy_get_manual_rx_polarity - Get manual RX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @val: Pointer to returned polarity. + * + * Helper for PHYs which do not support protocols with automatic RX polarity + * detection and correction. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_manual_rx_polarity(ofnode node, const char *mode_name, + unsigned int *val); + +/** + * phy_get_manual_tx_polarity - Get manual TX polarity for PHY differential lane + * @node: Pointer to the PHY's device tree node. + * @mode_name: The name of the PHY mode to look up. + * @val: Pointer to returned polarity. + * + * Helper for PHYs without any custom default value for the TX polarity. + * + * Return: zero on success, negative error on failure. + */ +int phy_get_manual_tx_polarity(ofnode node, const char *mode_name, + unsigned int *val); + +#endif /* __PHY_COMMON_PROPS_H */ diff --git a/net/lwip/wget.c b/net/lwip/wget.c index 008f3b395e7..502c0faebb2 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -20,7 +20,6 @@ #define SERVER_NAME_SIZE 254 #define HTTP_PORT_DEFAULT 80 #define HTTPS_PORT_DEFAULT 443 -#define PROGRESS_PRINT_STEP_BYTES (100 * 1024) enum done_state { NOT_DONE = 0, @@ -178,6 +177,9 @@ static int store_block(struct wget_ctx *ctx, void *src, u16_t len) ctx->daddr += len; ctx->size += len; + if (wget_info->silent) + return 0; + pos = clamp(ctx->size, 0UL, ctx->content_len); while (ctx->hash_count < pos * 50 / ctx->content_len) { @@ -240,20 +242,18 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result, } /* Print hash marks for the last packet received */ - while (ctx->hash_count < 49) { - putc('#'); - ctx->hash_count++; + if (!wget_info->silent) { + while (ctx->hash_count < 49) { + putc('#'); + ctx->hash_count++; + } } - puts(" "); - print_size(ctx->content_len, ""); elapsed = get_timer(ctx->start_time); if (!elapsed) elapsed = 1; if (!wget_info->silent) { - if (rx_content_len > PROGRESS_PRINT_STEP_BYTES) - printf("\n"); - printf("%u bytes transferred in %lu ms (", rx_content_len, + printf("\n%u bytes transferred in %lu ms (", rx_content_len, elapsed); print_size(rx_content_len / elapsed * 1000, "/s)\n"); printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, diff --git a/net/nfs-common.c b/net/nfs-common.c index 4fbde67a760..72d8fd823e3 100644 --- a/net/nfs-common.c +++ b/net/nfs-common.c @@ -674,11 +674,15 @@ static int nfs_readlink_reply(uchar *pkt, unsigned int len) strcat(nfs_path, "/"); pathlen = strlen(nfs_path); + if (pathlen + rlen >= sizeof(nfs_path_buff)) + return -NFS_RPC_DROP; memcpy(nfs_path + pathlen, (uchar *)&rpc_pkt.u.reply.data[2 + nfsv3_data_offset], rlen); nfs_path[pathlen + rlen] = 0; } else { + if (rlen >= sizeof(nfs_path_buff)) + return -NFS_RPC_DROP; memcpy(nfs_path, (uchar *)&rpc_pkt.u.reply.data[2 + nfsv3_data_offset], rlen); diff --git a/test/dm/Makefile b/test/dm/Makefile index 771b703b737..d69b0e08d66 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_P2SB) += p2sb.o obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o obj-$(CONFIG_PCH) += pch.o obj-$(CONFIG_PHY) += phy.o +obj-$(CONFIG_PHY_COMMON_PROPS) += phy_common_props.o ifneq ($(CONFIG_PINMUX),) obj-$(CONFIG_PINCONF) += pinmux.o endif diff --git a/test/dm/phy_common_props.c b/test/dm/phy_common_props.c new file mode 100644 index 00000000000..21f5042b7a0 --- /dev/null +++ b/test/dm/phy_common_props.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * U-Boot sandbox DM tests for PHY common props + * + * Ported from Linux KUnit test: + * linux/drivers/phy/phy-common-props-test.c + * + * Copyright 2025-2026 NXP + */ +#include <dm.h> +#include <dm/ofnode.h> +#include <dm/test.h> +#include <linux/bitops.h> +#include <linux/phy/phy-common-props.h> +#include <dt-bindings/phy/phy.h> +#include <test/test.h> +#include <test/ut.h> + +/* --- RX polarity tests -------------------------------------------------- */ + +/* Test: rx-polarity property is missing => default PHY_POL_NORMAL */ +static int dm_test_phy_common_props_rx_missing(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-missing"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_NORMAL, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_missing, UTF_SCAN_FDT); + +/* Test: rx-polarity has more values than rx-polarity-names => -EINVAL */ +static int dm_test_phy_common_props_rx_more_values(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-more-values"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_more_values, UTF_SCAN_FDT); + +/* Test: rx-polarity has 1 value and rx-polarity-names does not exist */ +static int dm_test_phy_common_props_rx_single_value(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-single"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_single_value, UTF_SCAN_FDT); + +/* Test: rx-polarity-names has more values than rx-polarity => -EINVAL */ +static int dm_test_phy_common_props_rx_more_names(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-more-names"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_more_names, UTF_SCAN_FDT); + +/* Test: valid arrays, find polarity by mode name */ +static int dm_test_phy_common_props_rx_find_by_name(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-find-by-name"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_NORMAL, val); + + ret = phy_get_manual_rx_polarity(node, "2500base-x", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + /* "usb-ss" has PHY_POL_AUTO; auto is supported here */ + ret = phy_get_rx_polarity(node, "usb-ss", BIT(PHY_POL_AUTO), + PHY_POL_AUTO, &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_AUTO, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_find_by_name, UTF_SCAN_FDT); + +/* Test: name not found, no "default" entry => -EINVAL */ +static int dm_test_phy_common_props_rx_no_default(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-no-default"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_no_default, UTF_SCAN_FDT); + +/* Test: name not found, "default" entry exists => use default polarity */ +static int dm_test_phy_common_props_rx_with_default(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-with-default"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_with_default, UTF_SCAN_FDT); + +/* Test: polarity value found but not in supported set => -EOPNOTSUPP */ +static int dm_test_phy_common_props_rx_unsupported(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-unsupported"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_asserteq(-EOPNOTSUPP, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_rx_unsupported, UTF_SCAN_FDT); + +/* --- TX polarity tests -------------------------------------------------- */ + +/* Test: tx-polarity property is missing => default PHY_POL_NORMAL */ +static int dm_test_phy_common_props_tx_missing(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-missing"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_NORMAL, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_missing, UTF_SCAN_FDT); + +/* Test: tx-polarity has more values than tx-polarity-names => -EINVAL */ +static int dm_test_phy_common_props_tx_more_values(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-more-values"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_more_values, UTF_SCAN_FDT); + +/* Test: tx-polarity has 1 value and tx-polarity-names does not exist */ +static int dm_test_phy_common_props_tx_single_value(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-single"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_single_value, UTF_SCAN_FDT); + +/* Test: tx-polarity-names has more values than tx-polarity => -EINVAL */ +static int dm_test_phy_common_props_tx_more_names(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-more-names"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_more_names, UTF_SCAN_FDT); + +/* Test: valid arrays, find polarity by mode name */ +static int dm_test_phy_common_props_tx_find_by_name(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-find-by-name"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_NORMAL, val); + + ret = phy_get_manual_tx_polarity(node, "2500base-x", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + ret = phy_get_manual_tx_polarity(node, "1000base-x", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_NORMAL, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_find_by_name, UTF_SCAN_FDT); + +/* Test: name not found, no "default" entry => -EINVAL */ +static int dm_test_phy_common_props_tx_no_default(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-no-default"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_no_default, UTF_SCAN_FDT); + +/* Test: name not found, "default" entry exists => use default polarity */ +static int dm_test_phy_common_props_tx_with_default(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-with-default"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(0, ret); + ut_asserteq(PHY_POL_INVERT, val); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_with_default, UTF_SCAN_FDT); + +/* Test: polarity value found but not in supported set => -EOPNOTSUPP */ +static int dm_test_phy_common_props_tx_unsupported(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-unsupported"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_tx_polarity(node, "sgmii", &val); + ut_asserteq(-EOPNOTSUPP, ret); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_unsupported, UTF_SCAN_FDT); |
