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
This commit is contained in:
Tom Rini
2026-05-06 08:44:55 -06:00
18 changed files with 1046 additions and 108 deletions

View File

@@ -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>;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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,

View File

@@ -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.

View File

@@ -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_serdes_polarity(struct phy_device *phydev)
{
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;
ofnode node = phy_get_ofnode(phydev);
u32 pbus_value = 0;
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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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/

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

319
test/dm/phy_common_props.c Normal file
View File

@@ -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);