mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
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
This commit is contained in:
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
286
drivers/phy/phy-common-props.c
Normal file
286
drivers/phy/phy-common-props.c
Normal 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);
|
||||
}
|
||||
69
include/linux/phy/phy-common-props.h
Normal file
69
include/linux/phy/phy-common-props.h
Normal 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 */
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
319
test/dm/phy_common_props.c
Normal 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);
|
||||
Reference in New Issue
Block a user