Add sandbox DM unit tests for the PHY common properties library and the corresponding device tree test nodes to arch/sandbox/dts/test.dts. Also enable CONFIG_PHY_COMMON_PROPS in configs/sandbox_defconfig so the tests are built and run in the sandbox environment.
The test file covers rx/tx polarity lookups for all relevant cases: - missing property (defaults to PHY_POL_NORMAL) - single value without names array (applies to all modes) - count mismatch between values and names arrays (-EINVAL) - name found by exact match - name not found with no "default" fallback (-EINVAL) - name not found with a "default" entry (uses fallback value) - unsupported polarity value (-EOPNOTSUPP) Ported from Linux KUnit test: linux/drivers/phy/phy-common-props-test.c Signed-off-by: Lucien.Jheng <[email protected]> --- ``` execute phy common props tests in sandbox: Bloblist at 100 not found (err=-2) pinctrl_select_state_full() sandbox_serial serial: pinctrl_select_state_full: uclass_get_device_by_phandle_id: err=-19 U-Boot 2026.01-rc5--gd1a76e2e4a64-dirty (Apr 25 2026 - 15:40:39 +0800) Reset Status: WARM Reset Status: COLD Model: sandbox DRAM: 256 MiB Core: 294 devices, 105 uclasses, devicetree: board, universal payload active WDT: Not starting wdt-gpio-toggle WDT: Not starting wdt-gpio-level WDT: Not starting wdt@0 NAND: 4100 MiB MMC: Can't map file 'mmc1.img': Invalid argument sandbox_mmc_probe() mmc1: Unable to map file 'mmc1.img' Can't map file 'mmc1.img': Invalid argument sandbox_mmc_probe() mmc1: Unable to map file 'mmc1.img' mmc_probe() mmc1 - probe failed: -1 mmc2: 2 (SD)Can't map file 'mmc1.img': Invalid argument sandbox_mmc_probe() mmc1: Unable to map file 'mmc1.img' , mmc0: 0 (SD) Loading Environment from nowhere... OK In: serial Out: serial,vidconsole Err: serial,vidconsole Model: sandbox Net: eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000, eth8: phy-test-eth, eth4: dsa-test-eth, eth2: lan0, eth7: lan1 Test: phy_common_props_rx_find_by_name: phy_common_props.c Test: phy_common_props_rx_find_by_name: phy_common_props.c (flat tree) Test: phy_common_props_rx_missing: phy_common_props.c Test: phy_common_props_rx_missing: phy_common_props.c (flat tree) Test: phy_common_props_rx_more_names: phy_common_props.c Test: phy_common_props_rx_more_names: phy_common_props.c (flat tree) Test: phy_common_props_rx_more_values: phy_common_props.c Test: phy_common_props_rx_more_values: phy_common_props.c (flat tree) Test: phy_common_props_rx_no_default: phy_common_props.c Test: phy_common_props_rx_no_default: phy_common_props.c (flat tree) Test: phy_common_props_rx_single_value: phy_common_props.c Test: phy_common_props_rx_single_value: phy_common_props.c (flat tree) Test: phy_common_props_rx_unsupported: phy_common_props.c Test: phy_common_props_rx_unsupported: phy_common_props.c (flat tree) Test: phy_common_props_rx_with_default: phy_common_props.c Test: phy_common_props_rx_with_default: phy_common_props.c (flat tree) Test: phy_common_props_tx_find_by_name: phy_common_props.c Test: phy_common_props_tx_find_by_name: phy_common_props.c (flat tree) Test: phy_common_props_tx_missing: phy_common_props.c Test: phy_common_props_tx_missing: phy_common_props.c (flat tree) Test: phy_common_props_tx_more_names: phy_common_props.c Test: phy_common_props_tx_more_names: phy_common_props.c (flat tree) Test: phy_common_props_tx_more_values: phy_common_props.c Test: phy_common_props_tx_more_values: phy_common_props.c (flat tree) Test: phy_common_props_tx_no_default: phy_common_props.c Test: phy_common_props_tx_no_default: phy_common_props.c (flat tree) Test: phy_common_props_tx_single_value: phy_common_props.c Test: phy_common_props_tx_single_value: phy_common_props.c (flat tree) Test: phy_common_props_tx_unsupported: phy_common_props.c Test: phy_common_props_tx_unsupported: phy_common_props.c (flat tree) Test: phy_common_props_tx_with_default: phy_common_props.c Test: phy_common_props_tx_with_default: phy_common_props.c (flat tree) Tests run: 16, 41 ms, average: 2 ms, failures: 0 arch/sandbox/dts/test.dts | 60 +++++++ configs/sandbox_defconfig | 1 + test/dm/Makefile | 1 + test/dm/phy_common_props.c | 319 +++++++++++++++++++++++++++++++++++++ 4 files changed, 381 insertions(+) create mode 100644 test/dm/phy_common_props.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index ac92ebf1afd..0887de4333b 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -16,6 +16,7 @@ #include <dt-bindings/leds/common.h> #include <dt-bindings/pinctrl/sandbox-pinmux.h> #include <dt-bindings/mux/mux.h> +#include <dt-bindings/phy/phy.h> / { model = "sandbox"; @@ -502,6 +503,65 @@ phy-names = "phy1"; }; + /* PHY common props test nodes */ + phy_common_props_missing: phy-common-props-missing { + /* empty: no rx-polarity or tx-polarity properties */ + }; + + phy_common_props_more_values: phy-common-props-more-values { + /* 3 values but only 2 names => count mismatch */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + rx-polarity-names = "sgmii", "2500base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + tx-polarity-names = "sgmii", "2500base-x"; + }; + + phy_common_props_single: phy-common-props-single { + /* 1 value, no names array => value applies to all modes */ + rx-polarity = <PHY_POL_INVERT>; + tx-polarity = <PHY_POL_INVERT>; + }; + + phy_common_props_more_names: phy-common-props-more-names { + /* 2 values but 3 names => count mismatch */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + }; + + phy_common_props_find_by_name: phy-common-props-find-by-name { + /* valid 3-element arrays, lookup by mode name */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_AUTO>; + rx-polarity-names = "sgmii", "2500base-x", "usb-ss"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT PHY_POL_NORMAL>; + tx-polarity-names = "sgmii", "2500base-x", "1000base-x"; + }; + + phy_common_props_no_default: phy-common-props-no-default { + /* name not in array, no "default" entry => -EINVAL */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "2500base-x", "1000base-x"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "2500base-x", "1000base-x"; + }; + + phy_common_props_with_default: phy-common-props-with-default { + /* name not in array, but "default" entry exists */ + rx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + rx-polarity-names = "2500base-x", "default"; + tx-polarity = <PHY_POL_NORMAL PHY_POL_INVERT>; + tx-polarity-names = "2500base-x", "default"; + }; + + phy_common_props_unsupported: phy-common-props-unsupported { + /* PHY_POL_AUTO is not supported for manual-only modes */ + rx-polarity = <PHY_POL_AUTO>; + rx-polarity-names = "sgmii"; + tx-polarity = <PHY_POL_AUTO>; + tx-polarity-names = "sgmii"; + }; + some-bus { #address-cells = <1>; #size-cells = <0>; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index b681b91c3f9..487bb3ec03c 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -284,6 +284,7 @@ CONFIG_PCI_REGION_MULTI_ENTRY=y CONFIG_PCI_FTPCI100=y CONFIG_PCI_SANDBOX=y CONFIG_PHY=y +CONFIG_PHY_COMMON_PROPS=y CONFIG_PHY_SANDBOX=y CONFIG_PINCTRL=y CONFIG_PINCONF=y diff --git a/test/dm/Makefile b/test/dm/Makefile index 771b703b737..d69b0e08d66 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_P2SB) += p2sb.o obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o obj-$(CONFIG_PCH) += pch.o obj-$(CONFIG_PHY) += phy.o +obj-$(CONFIG_PHY_COMMON_PROPS) += phy_common_props.o ifneq ($(CONFIG_PINMUX),) obj-$(CONFIG_PINCONF) += pinmux.o endif diff --git a/test/dm/phy_common_props.c b/test/dm/phy_common_props.c new file mode 100644 index 00000000000..b9c081320ff --- /dev/null +++ b/test/dm/phy_common_props.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * U-Boot sandbox DM tests for PHY common props + * + * Ported from Linux KUnit test: + * linux/drivers/phy/phy-common-props-test.c + * + * Copyright 2025-2026 NXP + */ +#include <dm.h> +#include <dm/ofnode.h> +#include <dm/test.h> +#include <linux/bitops.h> +#include <linux/phy/phy-common-props.h> +#include <dt-bindings/phy/phy.h> +#include <test/test.h> +#include <test/ut.h> + +/* --- RX polarity tests -------------------------------------------------- */ + +/* Test: rx-polarity property is missing => default PHY_POL_NORMAL */ +static int dm_test_phy_common_props_rx_missing(struct unit_test_state *uts) +{ + ofnode node = ofnode_path("/phy-common-props-missing"); + unsigned int val; + int ret; + + ut_assert(ofnode_valid(node)); + + ret = phy_get_manual_rx_polarity(node, "sgmii", &val); + ut_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + ut_asserteq(PHY_POL_NORMAL, val); + + ret = phy_get_manual_rx_polarity(node, "2500base-x", &val); + ut_assert(ret == 0); + 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_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + 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_assert(ret == -EOPNOTSUPP); + + 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_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + ut_asserteq(PHY_POL_NORMAL, val); + + ret = phy_get_manual_tx_polarity(node, "2500base-x", &val); + ut_assert(ret == 0); + ut_asserteq(PHY_POL_INVERT, val); + + ret = phy_get_manual_tx_polarity(node, "1000base-x", &val); + ut_assert(ret == 0); + 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_assert(ret == -EINVAL); + + 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_assert(ret == 0); + 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_assert(ret == -EOPNOTSUPP); + + return 0; +} + +DM_TEST(dm_test_phy_common_props_tx_unsupported, UTF_SCAN_FDT); -- 2.34.1

