* Re: [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
From: kernel test robot @ 2026-02-11 16:21 UTC (permalink / raw)
To: Geert Uytterhoeven, Yoshihiro Shimoda, Vinod Koul, Neil Armstrong,
Josua Mayer, Ulf Hansson, Wolfram Sang, Tommaso Merciai
Cc: llvm, oe-kbuild-all, linux-phy, linux-mmc, linux-renesas-soc,
linux-next, linux-kernel, Geert Uytterhoeven
In-Reply-To: <67c8c4f9bf9f09fd0c13daedef27b82ff389ddfb.1770720452.git.geert+renesas@glider.be>
Hi Geert,
kernel test robot noticed the following build errors:
[auto build test ERROR on next-20260209]
url: https://github.com/intel-lab-lkp/linux/commits/Geert-Uytterhoeven/phy-renesas-rcar-gen3-usb2-Drop-local-devm_mux_state_get_optional/20260210-185437
base: next-20260209
patch link: https://lore.kernel.org/r/67c8c4f9bf9f09fd0c13daedef27b82ff389ddfb.1770720452.git.geert%2Brenesas%40glider.be
patch subject: [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260212/202602120031.iupmQxdk-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260212/202602120031.iupmQxdk-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602120031.iupmQxdk-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/phy/renesas/phy-rcar-gen3-usb2.c:1029:14: error: call to undeclared function 'devm_mux_state_get_optional'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
mux_state = devm_mux_state_get_optional(dev, NULL);
^
drivers/phy/renesas/phy-rcar-gen3-usb2.c:1029:14: note: did you mean 'devm_regulator_get_optional'?
include/linux/regulator/consumer.h:163:32: note: 'devm_regulator_get_optional' declared here
struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
^
>> drivers/phy/renesas/phy-rcar-gen3-usb2.c:1029:12: error: incompatible integer to pointer conversion assigning to 'struct mux_state *' from 'int' [-Wint-conversion]
mux_state = devm_mux_state_get_optional(dev, NULL);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
vim +/devm_mux_state_get_optional +1029 drivers/phy/renesas/phy-rcar-gen3-usb2.c
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 946
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 947 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 948 {
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 949 struct device *dev = &pdev->dev;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 950 struct rcar_gen3_chan *channel;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 951 struct phy_provider *provider;
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 952 struct mux_state *mux_state;
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 953 int ret = 0, i, irq;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 954
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 955 if (!dev->of_node) {
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 956 dev_err(dev, "This driver needs device tree\n");
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 957 return -EINVAL;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 958 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 959
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 960 channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 961 if (!channel)
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 962 return -ENOMEM;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 963
0b5604affbec02 drivers/phy/renesas/phy-rcar-gen3-usb2.c Chunfeng Yun 2020-11-06 964 channel->base = devm_platform_ioremap_resource(pdev, 0);
801a69c787812f drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 965 if (IS_ERR(channel->base))
801a69c787812f drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 966 return PTR_ERR(channel->base);
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 967
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 968 channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
73801b90a38ff1 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2018-09-21 969 if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
979b519c7a1bff drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2018-09-21 970 channel->is_otg_channel = true;
8dde0008ffc9e2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2018-09-21 971 channel->uses_otg_pins = !of_property_read_bool(dev->of_node,
8dde0008ffc9e2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2018-09-21 972 "renesas,no-otg-pins");
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 973 channel->extcon = devm_extcon_dev_allocate(dev,
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 974 rcar_gen3_phy_cable);
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 975 if (IS_ERR(channel->extcon))
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 976 return PTR_ERR(channel->extcon);
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 977
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 978 ret = devm_extcon_dev_register(dev, channel->extcon);
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 979 if (ret < 0) {
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 980 dev_err(dev, "Failed to register extcon\n");
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 981 return ret;
2b38543c8db1c7 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-04-29 982 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 983 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 984
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 985 channel->rstc = devm_reset_control_array_get_optional_shared(dev);
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 986 if (IS_ERR(channel->rstc))
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 987 return PTR_ERR(channel->rstc);
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 988
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 989 ret = reset_control_deassert(channel->rstc);
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 990 if (ret)
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 991 return ret;
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 992
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 993 ret = devm_add_action_or_reset(dev, rcar_gen3_reset_assert, channel->rstc);
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 994 if (ret)
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 995 return ret;
942a7a6bf4c6a8 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-11-19 996
441a681b884347 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2017-03-14 997 /*
441a681b884347 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2017-03-14 998 * devm_phy_create() will call pm_runtime_enable(&phy->dev);
441a681b884347 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2017-03-14 999 * And then, phy-core will manage runtime pm for this device.
441a681b884347 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2017-03-14 1000 */
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1001 ret = devm_pm_runtime_enable(dev);
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1002 if (ret)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1003 return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");
b0512a6ec0cd6d drivers/phy/renesas/phy-rcar-gen3-usb2.c Biju Das 2021-07-27 1004
f75806d26318c0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Lad Prabhakar 2025-08-08 1005 channel->phy_data = of_device_get_match_data(dev);
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1006 if (!channel->phy_data)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1007 return -EINVAL;
5d8042e95fd471 drivers/phy/renesas/phy-rcar-gen3-usb2.c Biju Das 2019-04-10 1008
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1009 platform_set_drvdata(pdev, channel);
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1010 channel->dev = dev;
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1011
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1012 ret = rcar_gen3_phy_usb2_init_bus(channel);
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1013 if (ret)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1014 return ret;
4eae16375357a2 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2024-08-22 1015
55a387ebb9219c drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1016 spin_lock_init(&channel->lock);
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1017 for (i = 0; i < NUM_OF_PHYS; i++) {
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1018 channel->rphys[i].phy = devm_phy_create(dev, NULL,
f75806d26318c0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Lad Prabhakar 2025-08-08 1019 channel->phy_data->phy_usb2_ops);
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1020 if (IS_ERR(channel->rphys[i].phy))
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1021 return dev_err_probe(dev, PTR_ERR(channel->rphys[i].phy),
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1022 "Failed to create USB2 PHY\n");
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1023
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1024 channel->rphys[i].ch = channel;
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1025 channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i];
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1026 phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1027 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 1028
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 @1029 mux_state = devm_mux_state_get_optional(dev, NULL);
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1030 if (IS_ERR(mux_state))
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1031 return PTR_ERR(mux_state);
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1032 if (mux_state) {
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1033 ret = mux_state_select(mux_state);
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1034 if (ret)
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1035 return dev_err_probe(dev, ret, "Failed to select USB mux\n");
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1036
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1037 ret = devm_add_action_or_reset(dev, rcar_gen3_phy_mux_state_deselect,
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1038 mux_state);
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1039 if (ret)
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1040 return dev_err_probe(dev, ret,
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1041 "Failed to register USB mux state deselect\n");
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1042 }
8bb92fd7a04077 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1043
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1044 if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel) {
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1045 ret = rcar_gen3_phy_usb2_vbus_regulator_register(channel);
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1046 if (ret)
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1047 return ret;
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1048 } else {
6dcfd7c300bf35 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 1049 channel->vbus = devm_regulator_get_optional(dev, "vbus");
b6d7dd157763e0 drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1050 }
6dcfd7c300bf35 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 1051 if (IS_ERR(channel->vbus)) {
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1052 if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1053 return PTR_ERR(channel->vbus);
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1054
6dcfd7c300bf35 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 1055 channel->vbus = NULL;
6dcfd7c300bf35 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 1056 }
6dcfd7c300bf35 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-03-03 1057
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1058 irq = platform_get_irq_optional(pdev, 0);
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1059 if (irq < 0 && irq != -ENXIO) {
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1060 return irq;
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1061 } else if (irq > 0) {
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1062 INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1063 ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1064 IRQF_SHARED, dev_name(dev), channel);
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1065 if (ret < 0)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1066 return dev_err_probe(dev, ret,
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1067 "Failed to request irq (%d)\n",
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1068 irq);
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1069 }
de76809f60cc93 drivers/phy/renesas/phy-rcar-gen3-usb2.c Claudiu Beznea 2025-05-07 1070
549b6b55b00558 drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2019-04-11 1071 provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
9bb86777fb71ee drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-11-09 1072 if (IS_ERR(provider)) {
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1073 return dev_err_probe(dev, PTR_ERR(provider),
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1074 "Failed to register PHY provider\n");
979b519c7a1bff drivers/phy/renesas/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2018-09-21 1075 } else if (channel->is_otg_channel) {
9bb86777fb71ee drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-11-09 1076 ret = device_create_file(dev, &dev_attr_role);
9bb86777fb71ee drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-11-09 1077 if (ret < 0)
230c817a1601af drivers/phy/renesas/phy-rcar-gen3-usb2.c Tommaso Merciai 2025-12-22 1078 return ret;
9bb86777fb71ee drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2016-11-09 1079 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 1080
441a681b884347 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2017-03-14 1081 return 0;
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 1082 }
f3b5a8d9b50d71 drivers/phy/phy-rcar-gen3-usb2.c Yoshihiro Shimoda 2015-11-30 1083
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
From: Vinod Koul @ 2026-02-11 16:17 UTC (permalink / raw)
To: Ulf Hansson
Cc: Geert Uytterhoeven, Vladimir Oltean, Yoshihiro Shimoda,
Neil Armstrong, Josua Mayer, Wolfram Sang, Tommaso Merciai,
linux-phy, linux-mmc, linux-renesas-soc, linux-next, linux-kernel
In-Reply-To: <CAPDyKFpY2X8hephSfHq7rj_DaKX76ZSkWSCYXrGTEBUFHkvOzg@mail.gmail.com>
On 10-02-26, 14:34, Ulf Hansson wrote:
> On Tue, 10 Feb 2026 at 11:53, Geert Uytterhoeven
> <geert+renesas@glider.be> wrote:
> >
> > Now the mux core provides devm_mux_state_get_optional():
> >
> > drivers/phy/renesas/phy-rcar-gen3-usb2.c:944:1: error: static declaration of ‘devm_mux_state_get_optional’ follows non-static
> > declaration
> > 944 | devm_mux_state_get_optional(struct device *dev, const char *mux_name)
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> > In file included from drivers/phy/renesas/phy-rcar-gen3-usb2.c:20:
> > include/linux/mux/consumer.h:64:19: note: previous declaration of ‘devm_mux_state_get_optional’ with type ‘struct mux_state *(struct device *, const char *)’
> > 64 | struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name);
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> >
> > Fix this by dropping the temporary local wrapper.
> >
> > Fixes: ad314348ceb4fe1f ("mux: Add helper functions for getting optional and selected mux-state")
> > Fixes: 8bb92fd7a0407792 ("phy: renesas: rcar-gen3-usb2: Use mux-state for phyrst management")
> > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> Thanks Geert for helping out!
>
> > ---
> > - ad314348ceb4fe1f is in mmc/next, and a PR has already been sent
> > https://lore.kernel.org/20260209133441.556464-1-ulf.hansson@linaro.org
> > - 8bb92fd7a0407792 is in phy/next
>
> Vinod, do you want to pick up the $subject patch as a fix for 7.0-rc1
> or do you prefer me to handle it?
Should I drop the 8bb92fd7a0407792 and it makes things easier for
everyone and then we can pick fixed commit for 7.1 cycle..
Does that work for everyone. I was about to send PR, will hold off for a
bit.
Thanks
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next] doc: generic phy: update generic PHY documentation
From: Vladimir Oltean @ 2026-02-11 15:48 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Vinod Koul, Neil Armstrong, Jonathan Corbet, linux-doc, linux-phy
In-Reply-To: <E1vo0mF-00000007kbg-1OeA@rmk-PC.armlinux.org.uk>
On Thu, Feb 05, 2026 at 02:56:15PM +0000, Russell King (Oracle) wrote:
> Update the generic PHY documentation as a result of the discussion for
> the s32g submission.
>
> Link: https://lore.kernel.org/r/aXtvDn_-pCuKPrnf@vaman
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
> ---
> I didn't get any replies to my follow-up question to Vinod:
>
> Please also indicate in the documentation whether changing the submode
> of the serdes (particularly for ethernet) is permitted without doing a
> phy_power_down()..phy_power_up() dance around the phy_set_mode_ext()
> call.
There's certainly nothing *not* permitting that call sequence.
> I also didn't get any response to:
>
> For drivers such as stmmac, it will be important that details such as
> whether phy_est_mode*() can be called with the PHY powered on are
> riveted down and not left up to the generic PHY driver author - without
> that, generic PHYs basically aren't usable from SoC/platform
> independent code, and stmmac has bazillions of platform specific glue
> already because of (a) bad code structuring and (b) lack of
> generalisation through standardised interfaces that abstract platform
> differences.
>
> I want to be able for core stmmac code, or even phylink code (which
> is even more platform generic) to be able to make use of generic PHY
> stuff, but if the calls that can be made into generic PHY are platform
> dependent, that is a blocking issue against that, and makes me question
> why we have the generic PHY subsystem... it's not very generic if it
> exposes the differences of each implementation to users of its
> interfaces.
It may well be that the "one consumer, multiple PHY providers, requiring
unified behaviour" situation you bring up is sufficiently unique here,
with stmmac/phylink, that local conventions are not sufficient.
I'm not sure that precise answers exist for your questions. Rather,
it's best if you could lay out common sense requirements, and generic
PHY reviewers will make sure they are followed.
As far as the framework is concerned, power and mode are fundamentally
decoupled, so I think the documentation is actually muddying the waters,
more than anything, by talking about a preferred calling order.
If there's any connection between power and mode, it should be handled
internally by the PHY provider driver.
> Documentation/driver-api/phy/phy.rst | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/driver-api/phy/phy.rst b/Documentation/driver-api/phy/phy.rst
> index 719a2b3fd2ab..cf73e4fb0951 100644
> --- a/Documentation/driver-api/phy/phy.rst
> +++ b/Documentation/driver-api/phy/phy.rst
> @@ -142,6 +142,7 @@ Order of API calls
>
> [devm_][of_]phy_get()
> phy_init()
> + [phy_set_mode[_ext]()]
> phy_power_on()
> [phy_set_mode[_ext]()]
> ...
> @@ -154,7 +155,7 @@ but controllers should always call these functions to be compatible with other
> PHYs. Some PHYs may require :c:func:`phy_set_mode <phy_set_mode_ext>`, while
> others may use a default mode (typically configured via devicetree or other
> firmware). For compatibility, you should always call this function if you know
> -what mode you will be using. Generally, this function should be called after
> +what mode you will be using. Generally, this function should be called before
> :c:func:`phy_power_on`, although some PHY drivers may allow it at any time.
My 2 cents: I would actually remove any reference to any sort of preferred
call order. There's nothing in the framework to back up such a concept.
Just say that it is recommended for PHY provider drivers to not rely on
a particular calling order, such that PHY consumers have the freedom to
choose depending on what suits them best.
>
> Releasing a reference to the PHY
> --
> 2.47.3
>
>
> --
> linux-phy mailing list
> linux-phy@lists.infradead.org
> https://lists.infradead.org/mailman/listinfo/linux-phy
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RESEND 1/1] phy: freescale: imx8qm-hsio: provide regmap names
From: Frank Li @ 2026-02-11 15:31 UTC (permalink / raw)
To: Alexander Stein
Cc: Vinod Koul, Neil Armstrong, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-phy, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260211144949.1128122-1-alexander.stein@ew.tq-group.com>
On Wed, Feb 11, 2026 at 03:49:48PM +0100, Alexander Stein wrote:
> This driver uses multiple regmaps, which will causes name conflicts
> in debugfs like:
> debugfs: '5f1a0000.phy' already exists in 'regmap'
> Fix this by using a dedicated regmap config for each resource, each
> having a dedicated regmap name.
>
> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Same as the one sent in December but with an updated CC list.
>
> drivers/phy/freescale/phy-fsl-imx8qm-hsio.c | 23 +++++++++++++++++----
> 1 file changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
> index 279b8ac7822df..4ab45c9f53dff 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
> @@ -107,7 +107,22 @@ static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr",
> static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx",
> "phy1_crr", "misc_crr"};
>
> -static const struct regmap_config regmap_config = {
> +static const struct regmap_config regmap_phy_config = {
> + .name = "phy",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static const struct regmap_config regmap_ctrl_config = {
> + .name = "ctrl",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static const struct regmap_config regmap_misc_config = {
> + .name = "misc",
> .reg_bits = 32,
> .val_bits = 32,
> .reg_stride = 4,
> @@ -562,19 +577,19 @@ static int imx_hsio_probe(struct platform_device *pdev)
> return PTR_ERR(priv->base);
>
> off = devm_platform_ioremap_resource_byname(pdev, "phy");
> - priv->phy = devm_regmap_init_mmio(dev, off, ®map_config);
> + priv->phy = devm_regmap_init_mmio(dev, off, ®map_phy_config);
> if (IS_ERR(priv->phy))
> return dev_err_probe(dev, PTR_ERR(priv->phy),
> "unable to find phy csr registers\n");
>
> off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
> - priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_config);
> + priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_ctrl_config);
> if (IS_ERR(priv->ctrl))
> return dev_err_probe(dev, PTR_ERR(priv->ctrl),
> "unable to find ctrl csr registers\n");
>
> off = devm_platform_ioremap_resource_byname(pdev, "misc");
> - priv->misc = devm_regmap_init_mmio(dev, off, ®map_config);
> + priv->misc = devm_regmap_init_mmio(dev, off, ®map_misc_config);
> if (IS_ERR(priv->misc))
> return dev_err_probe(dev, PTR_ERR(priv->misc),
> "unable to find misc csr registers\n");
> --
> 2.43.0
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [RESEND 1/1] phy: freescale: imx8qm-hsio: provide regmap names
From: Alexander Stein @ 2026-02-11 14:49 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: Alexander Stein, linux-phy, imx, linux-arm-kernel, linux-kernel
This driver uses multiple regmaps, which will causes name conflicts
in debugfs like:
debugfs: '5f1a0000.phy' already exists in 'regmap'
Fix this by using a dedicated regmap config for each resource, each
having a dedicated regmap name.
Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
Same as the one sent in December but with an updated CC list.
drivers/phy/freescale/phy-fsl-imx8qm-hsio.c | 23 +++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
index 279b8ac7822df..4ab45c9f53dff 100644
--- a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
@@ -107,7 +107,22 @@ static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr",
static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx",
"phy1_crr", "misc_crr"};
-static const struct regmap_config regmap_config = {
+static const struct regmap_config regmap_phy_config = {
+ .name = "phy",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static const struct regmap_config regmap_ctrl_config = {
+ .name = "ctrl",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static const struct regmap_config regmap_misc_config = {
+ .name = "misc",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
@@ -562,19 +577,19 @@ static int imx_hsio_probe(struct platform_device *pdev)
return PTR_ERR(priv->base);
off = devm_platform_ioremap_resource_byname(pdev, "phy");
- priv->phy = devm_regmap_init_mmio(dev, off, ®map_config);
+ priv->phy = devm_regmap_init_mmio(dev, off, ®map_phy_config);
if (IS_ERR(priv->phy))
return dev_err_probe(dev, PTR_ERR(priv->phy),
"unable to find phy csr registers\n");
off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
- priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_config);
+ priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_ctrl_config);
if (IS_ERR(priv->ctrl))
return dev_err_probe(dev, PTR_ERR(priv->ctrl),
"unable to find ctrl csr registers\n");
off = devm_platform_ioremap_resource_byname(pdev, "misc");
- priv->misc = devm_regmap_init_mmio(dev, off, ®map_config);
+ priv->misc = devm_regmap_init_mmio(dev, off, ®map_misc_config);
if (IS_ERR(priv->misc))
return dev_err_probe(dev, PTR_ERR(priv->misc),
"unable to find misc csr registers\n");
--
2.43.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH V5 3/3] arm64: dts: qcom: hamoa-iot-evk: Enable UFS
From: Pradeep P V K @ 2026-02-11 13:29 UTC (permalink / raw)
To: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, martin.petersen,
andersson, konradybcio, taniya.das, dmitry.baryshkov,
manivannan.sadhasivam
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, linux-scsi,
nitin.rawat, Pradeep P V K, Konrad Dybcio, Manivannan Sadhasivam
In-Reply-To: <20260211132926.3716716-1-pradeep.pragallapati@oss.qualcomm.com>
Enable UFS for HAMOA-IOT-EVK board.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Pradeep P V K <pradeep.pragallapati@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
index 2390648a248f..fccf1d1bdc60 100644
--- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
+++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts
@@ -1461,6 +1461,24 @@ &uart21 {
status = "okay";
};
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l3i_0p8>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 238 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l17b_2p5>;
+ vcc-max-microamp = <1300000>;
+ vccq-supply = <&vreg_l2i_1p2>;
+ vccq-max-microamp = <1200000>;
+
+ status = "okay";
+};
+
&usb_1_ss0_dwc3_hs {
remote-endpoint = <&pmic_glink_ss0_hs_in>;
};
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH V5 2/3] arm64: dts: qcom: hamoa: Add UFS nodes for x1e80100 SoC
From: Pradeep P V K @ 2026-02-11 13:29 UTC (permalink / raw)
To: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, martin.petersen,
andersson, konradybcio, taniya.das, dmitry.baryshkov,
manivannan.sadhasivam
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, linux-scsi,
nitin.rawat, Pradeep P V K, Konrad Dybcio, Abel Vesa,
Manivannan Sadhasivam
In-Reply-To: <20260211132926.3716716-1-pradeep.pragallapati@oss.qualcomm.com>
Add UFS host controller and PHY nodes for x1e80100 SoC.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
Reviewed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Pradeep P V K <pradeep.pragallapati@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/hamoa.dtsi | 122 +++++++++++++++++++++++++++-
1 file changed, 119 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
index db65c392e618..5bffff1046e2 100644
--- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
+++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
@@ -835,9 +835,9 @@ gcc: clock-controller@100000 {
<0>,
<0>,
<0>,
- <0>,
- <0>,
- <0>;
+ <&ufs_mem_phy 0>,
+ <&ufs_mem_phy 1>,
+ <&ufs_mem_phy 2>;
power-domains = <&rpmhpd RPMHPD_CX>;
#clock-cells = <1>;
@@ -3869,6 +3869,122 @@ pcie4_phy: phy@1c0e000 {
status = "disabled";
};
+ ufs_mem_phy: phy@1d80000 {
+ compatible = "qcom,x1e80100-qmp-ufs-phy",
+ "qcom,sm8550-qmp-ufs-phy";
+ reg = <0x0 0x01d80000 0x0 0x2000>;
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_UFS_PHY_PHY_AUX_CLK>,
+ <&tcsr TCSR_UFS_PHY_CLKREF_EN>;
+
+ clock-names = "ref",
+ "ref_aux",
+ "qref";
+ resets = <&ufs_mem_hc 0>;
+ reset-names = "ufsphy";
+
+ power-domains = <&gcc GCC_UFS_MEM_PHY_GDSC>;
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ ufs_mem_hc: ufshc@1d84000 {
+ compatible = "qcom,x1e80100-ufshc",
+ "qcom,sm8550-ufshc",
+ "qcom,ufshc";
+ reg = <0x0 0x01d84000 0x0 0x3000>;
+
+ interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_UFS_PHY_AHB_CLK>,
+ <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>,
+ <&rpmhcc RPMH_LN_BB_CLK3>,
+ <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>;
+ clock-names = "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk",
+ "rx_lane1_sync_clk";
+
+ operating-points-v2 = <&ufs_opp_table>;
+
+ resets = <&gcc GCC_UFS_PHY_BCR>;
+ reset-names = "rst";
+
+ interconnects = <&aggre1_noc MASTER_UFS_MEM QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_UFS_MEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
+ interconnect-names = "ufs-ddr",
+ "cpu-ufs";
+
+ power-domains = <&gcc GCC_UFS_PHY_GDSC>;
+ required-opps = <&rpmhpd_opp_nom>;
+
+ iommus = <&apps_smmu 0x1a0 0>;
+ dma-coherent;
+
+ lanes-per-direction = <2>;
+
+ phys = <&ufs_mem_phy>;
+ phy-names = "ufsphy";
+
+ #reset-cells = <1>;
+
+ status = "disabled";
+
+ ufs_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-75000000 {
+ opp-hz = /bits/ 64 <75000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <75000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-150000000 {
+ opp-hz = /bits/ 64 <150000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <150000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <300000000>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>,
+ /bits/ 64 <0>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
cryptobam: dma-controller@1dc4000 {
compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
reg = <0x0 0x01dc4000 0x0 0x28000>;
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH V5 1/3] dt-bindings: ufs: qcom,sc7180-ufshc: Add UFSHC compatible for x1e80100
From: Pradeep P V K @ 2026-02-11 13:29 UTC (permalink / raw)
To: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, martin.petersen,
andersson, konradybcio, taniya.das, dmitry.baryshkov,
manivannan.sadhasivam
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, linux-scsi,
nitin.rawat, Pradeep P V K, Manivannan Sadhasivam,
Krzysztof Kozlowski
In-Reply-To: <20260211132926.3716716-1-pradeep.pragallapati@oss.qualcomm.com>
Add UFS Host Controller (UFSHC) compatible for x1e80100 SoC. Use
SM8550 as a fallback since x1e80100 is fully compatible with it.
Qualcomm UFSHC is no longer compatible with JEDEC UFS-2.0 binding.
Avoid using the "jedec,ufs-2.0" string in the compatible property.
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Pradeep P V K <pradeep.pragallapati@oss.qualcomm.com>
---
.../bindings/ufs/qcom,sc7180-ufshc.yaml | 36 +++++++++++--------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/Documentation/devicetree/bindings/ufs/qcom,sc7180-ufshc.yaml b/Documentation/devicetree/bindings/ufs/qcom,sc7180-ufshc.yaml
index d94ef4e6b85a..fe18e41ebac7 100644
--- a/Documentation/devicetree/bindings/ufs/qcom,sc7180-ufshc.yaml
+++ b/Documentation/devicetree/bindings/ufs/qcom,sc7180-ufshc.yaml
@@ -31,21 +31,27 @@ select:
properties:
compatible:
- items:
- - enum:
- - qcom,msm8998-ufshc
- - qcom,qcs8300-ufshc
- - qcom,sa8775p-ufshc
- - qcom,sc7180-ufshc
- - qcom,sc7280-ufshc
- - qcom,sc8180x-ufshc
- - qcom,sc8280xp-ufshc
- - qcom,sm8250-ufshc
- - qcom,sm8350-ufshc
- - qcom,sm8450-ufshc
- - qcom,sm8550-ufshc
- - const: qcom,ufshc
- - const: jedec,ufs-2.0
+ oneOf:
+ - items:
+ - enum:
+ - qcom,x1e80100-ufshc
+ - const: qcom,sm8550-ufshc
+ - const: qcom,ufshc
+ - items:
+ - enum:
+ - qcom,msm8998-ufshc
+ - qcom,qcs8300-ufshc
+ - qcom,sa8775p-ufshc
+ - qcom,sc7180-ufshc
+ - qcom,sc7280-ufshc
+ - qcom,sc8180x-ufshc
+ - qcom,sc8280xp-ufshc
+ - qcom,sm8250-ufshc
+ - qcom,sm8350-ufshc
+ - qcom,sm8450-ufshc
+ - qcom,sm8550-ufshc
+ - const: qcom,ufshc
+ - const: jedec,ufs-2.0
reg:
maxItems: 1
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH V5 0/3] Add UFS support for x1e80100 SoC
From: Pradeep P V K @ 2026-02-11 13:29 UTC (permalink / raw)
To: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, martin.petersen,
andersson, konradybcio, taniya.das, dmitry.baryshkov,
manivannan.sadhasivam
Cc: linux-arm-msm, linux-phy, devicetree, linux-kernel, linux-scsi,
nitin.rawat, Pradeep P V K
Add UFSPHY, UFSHC compatible binding names and UFS devicetree
enablement changes for Qualcomm x1e80100 SoC.
Changes in V5:
- Rebased on linux-next (next-20260210) to resolve merge conflicts.
- Add RB-by for UFSHC dt-binding [Krzysztof]
- Add AB-by for UFSHC dt-binding [Mani]
- Add RB-by for SoC dtsi [Konrad, Abel, Taniya, Mani]
- Add RB-by for board dts [Konrad, Mani]
- Link to V4:
https://lore.kernel.org/all/20260106154207.1871487-1-pradeep.pragallapati@oss.qualcomm.com
Changes in V4:
- Update ufs@ with ufshc@ in SoC dtsi [Mani]
- Retain complete change history in cover letter [Dmitry]
- Remove "jedec,ufs-2.0" compatible from ufshc dt-bindings
and SoC dtsi files [Krzysztof, Mani]
- Remove RB-by tag from Krzysztof and AB-by tag from Mani on
UFSHC dt-binding file as it has changes and needs re-review.
- Add RB-by for QMP UFS PHY dt-binding [Krzysztof]
- Add RB-by for SoC dtsi [Konrad, Abel, Taniya, Mani]
- Add RB-by for board dts [Konrad]
- Link to V3:
https://lore.kernel.org/all/0689ae93-0684-4bf8-9bce-f9f32e56fe06@oss.qualcomm.com
Changes in V3:
- Update all dt-bindings commit messages with concise and informative
statements [Krzysztof]
- keep the QMP UFS PHY order by last compatible in numerical ascending
order [Krzysztof]
- Remove qcom,x1e80100-ufshc from select: enum: list of
qcom,sc7180-ufshc.yaml file [Krzysztof]
- Update subject prefix for all dt-bindings [Krzysztof]
- Add RB-by for SoC dtsi [Konrad, Abel, Taniya]
- Add RB-by for board dts [Konrad]
- Link to V2:
https://lore.kernel.org/all/20251231101951.1026163-1-pradeep.pragallapati@oss.qualcomm.com
Changes in V2:
- Update all dt-bindings commit messages to explain fallback
to SM8550 [Krzysztof]
- Pad register addresses to 8-digit hex format [Konrad]
- Place one compatible string per line [Konrad]
- Replace chip codenames with numeric identifiers throughout [Konrad]
- Fix dt_binding_check error in UFSHC dt-bindings [Rob]
- This series is rebased on GCC bindings and driver changes:
https://lore.kernel.org/lkml/20251230-ufs_symbol_clk-v1-0-47d46b24c087@oss.qualcomm.com/
- This series address issues and gaps noticed on:
https://lore.kernel.org/linux-devicetree/20250814005904.39173-2-harrison.vanderbyl@gmail.com/
https://lore.kernel.org/linux-devicetree/p3mhtj2rp6y2ezuwpd2gu7dwx5cbckfu4s4pazcudi4j2wogtr@4yecb2bkeyms/
- Link to V1:
https://lore.kernel.org/linux-phy/20251229060642.2807165-1-pradeep.pragallapati@oss.qualcomm.com/
---
Pradeep P V K (3):
dt-bindings: ufs: qcom,sc7180-ufshc: Add UFSHC compatible for x1e80100
arm64: dts: qcom: hamoa: Add UFS nodes for x1e80100 SoC
arm64: dts: qcom: hamoa-iot-evk: Enable UFS
.../bindings/ufs/qcom,sc7180-ufshc.yaml | 36 +++---
arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 18 +++
arch/arm64/boot/dts/qcom/hamoa.dtsi | 122 +++++++++++++++++-
3 files changed, 158 insertions(+), 18 deletions(-)
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 0/2] phy: microchip: lan966x: Allow to invert N and P signals
From: Vladimir Oltean @ 2026-02-11 12:22 UTC (permalink / raw)
To: Horatiu Vultur
Cc: Vladimir Oltean, vkoul, kishon, robh, krzk+dt, conor+dt,
linux-phy, devicetree, linux-kernel, Daniel Golle
In-Reply-To: <20251119192326.4bflaqkh4zvz2rib@skbuf>
Hi Horatiu,
On Wed, Nov 19, 2025 at 09:23:26PM +0200, Vladimir Oltean wrote:
> > Anyway I can wait with this patch series until you get your changes in.
>
> I will keep you copied to the patch set which I hope to send later today.
The generic description I was talking about has been merged as commit
e7556b59ba65 ("phy: add phy_get_rx_polarity() and phy_get_tx_polarity()").
This set should be dropped from Patchwork. You can send a new version
after the merge window closes, or an RFC at any time.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH phy-next] phy: apple: apple: Check the actual ioremap return value
From: Vladimir Oltean @ 2026-02-10 20:48 UTC (permalink / raw)
To: Janne Grunau
Cc: Sven Peter, Neal Gompa, Vinod Koul, Neil Armstrong, Philipp Zabel,
asahi, linux-phy, linux-kernel, Dan Carpenter
In-Reply-To: <20260207-phy-apple-resource-err-ptr-v1-1-78735b07ed2d@jannau.net>
Hello Janne,
On Sat, Feb 07, 2026 at 05:40:34PM +0100, Janne Grunau wrote:
> The address where the devm_ioremap_resource() return value is stored is
> always a valid pointer. Check the actual return value instead as that
> that might be an error value.
>
> Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> Closes: https://lore.kernel.org/asahi/aYXvX1bYOXtYCgfC@stanley.mountain/
> Fixes: 8e98ca1e74db ("phy: apple: Add Apple Type-C PHY")
> Signed-off-by: Janne Grunau <j@jannau.net>
> ---
> drivers/phy/apple/atc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/phy/apple/atc.c b/drivers/phy/apple/atc.c
> index dc867f368b68748ea953e594ad998d7f965d8d1d..c144e273a555a741b49adfccbe046df83d193e03 100644
> --- a/drivers/phy/apple/atc.c
> +++ b/drivers/phy/apple/atc.c
> @@ -2206,7 +2206,7 @@ static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcph
> for (int i = 0; i < ARRAY_SIZE(resources); i++) {
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name);
> *resources[i].addr = devm_ioremap_resource(&pdev->dev, res);
> - if (IS_ERR(resources[i].addr))
> + if (IS_ERR(*resources[i].addr))
> return dev_err_probe(atcphy->dev, PTR_ERR(resources[i].addr),
> "Unable to map %s regs", resources[i].name);
This does not seem correct - every call site that tests a pointer for
IS_ERR() also decodes the error using PTR_ERR(). Whereas you are here
creating the pattern "if (IS_ERR(*a)) return PTR_ERR(a)".
Proven practice seems to tell us that insisting to save the
devm_ioremap_resource() return code directly in *resources[i].addr
is too complex here.
Would you consider creating a temporary "void __iomem *addr" local
variable, and set "*resources[i].addr = addr" only once it's validated?
This would make the code obviously correct upon review.
>
>
> ---
> base-commit: dbeea86fecef7cf2b93aded4525d74f6277376ef
> change-id: 20260207-phy-apple-resource-err-ptr-5923d1130465
>
> Best regards,
> --
> Janne Grunau <j@jannau.net>
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH] phy: ti: j721e-wiz: Fix device_node leak in wiz_get_lane_phy_types()
From: Vladimir Oltean @ 2026-02-10 20:30 UTC (permalink / raw)
To: Felix Gu
Cc: Vinod Koul, Neil Armstrong, Kishon Vijay Abraham I, Jyri Sarha,
linux-phy, linux-kernel
In-Reply-To: <20260211-wiz-v1-1-fdd018d02f33@gmail.com>
Hi Felix,
On Wed, Feb 11, 2026 at 02:14:11AM +0800, Felix Gu wrote:
> The 'serdes' device_node is obtained using of_get_child_by_name(),
> which increments the reference count. However, it is never put,
> leading to a memory leak.
>
> Use the __free(device_node) attribute to automatically decrement
> the reference count when the 'serdes' variable goes out of scope.
>
> Fixes: 7ae14cf581f2 ("phy: ti: j721e-wiz: Implement DisplayPort mode to the wiz driver")
> Signed-off-by: Felix Gu <ustc.gu@gmail.com>
> ---
> drivers/phy/ti/phy-j721e-wiz.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
> index 12a19bf2875c..904541e9138e 100644
> --- a/drivers/phy/ti/phy-j721e-wiz.c
> +++ b/drivers/phy/ti/phy-j721e-wiz.c
> @@ -1407,9 +1407,8 @@ MODULE_DEVICE_TABLE(of, wiz_id_table);
>
> static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
> {
> - struct device_node *serdes;
> -
> - serdes = of_get_child_by_name(dev->of_node, "serdes");
> + struct device_node *serdes __free(device_node) =
> + of_get_child_by_name(dev->of_node, "serdes");
> if (!serdes) {
> dev_err(dev, "%s: Getting \"serdes\"-node failed\n", __func__);
> return -EINVAL;
>
> ---
> base-commit: 193579fe01389bc21aff0051d13f24e8ea95b47d
> change-id: 20260204-wiz-9a67604a034f
>
> Best regards,
> --
> Felix Gu <ustc.gu@gmail.com>
>
>
You are fixing a bug from 2020 (v5.8) with functionality introduced in 2023,
creating avoidable headache for backporters (the oldest supported LTS is
5.10, where the cleanup API does not exist). Could we reimplement this
the "normal" of_node_put() way?
I realize this is not netdev, but this piece of advice from
Documentation/process/maintainer-netdev.rst regarding use in drivers
seems common sense and relevant here:
Low level cleanup constructs (such as ``__free()``) can be used when building
APIs and helpers, especially scoped iterators. However, direct use of
``__free()`` within networking core and drivers is discouraged.
Similar guidance applies to declaring variables mid-function.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 2/8] phy: sort Kconfig and Makefile
From: Vladimir Oltean @ 2026-02-10 19:37 UTC (permalink / raw)
To: Théo Lebrun
Cc: Grégory Clement, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Kishon Vijay Abraham I,
Michael Turquette, Stephen Boyd, Philipp Zabel,
Thomas Bogendoerfer, Neil Armstrong, linux-mips, devicetree,
linux-kernel, linux-phy, linux-clk, Benoît Monin,
Tawfik Bayouk, Thomas Petazzoni, Luca Ceresoli
In-Reply-To: <20260127-macb-phy-v6-2-cdd840588188@bootlin.com>
Hi Theo,
On Tue, Jan 27, 2026 at 06:09:30PM +0100, Théo Lebrun wrote:
> Neither Kconfig nor Makefile are sorted; reorder them.
>
> $ diff -U100 <(grep ^config drivers/phy/Kconfig) \
> <(grep ^config drivers/phy/Kconfig | sort)
>
> $ diff -U100 <(grep ^obj-\\$ drivers/phy/Makefile) \
> <(grep ^obj-\\$ drivers/phy/Makefile | sort)
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
This patch is appreciated, however it no longer applies on top of
current linux-phy/next.
Since we are in the merge window currently, would you mind reposting in
2 weeks (or as RFC in the meantime)?
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 3/8] phy: Add driver for EyeQ5 Ethernet PHY wrapper
From: Vladimir Oltean @ 2026-02-10 19:35 UTC (permalink / raw)
To: Théo Lebrun
Cc: Vladimir Kondratiev, Grégory Clement, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul,
Kishon Vijay Abraham I, Michael Turquette, Stephen Boyd,
Philipp Zabel, Thomas Bogendoerfer, Neil Armstrong, linux-mips,
devicetree, linux-kernel, linux-phy, linux-clk, Benoît Monin,
Tawfik Bayouk, Thomas Petazzoni, Luca Ceresoli
In-Reply-To: <20260127-macb-phy-v6-3-cdd840588188@bootlin.com>
Hi Theo,
On Tue, Jan 27, 2026 at 06:09:31PM +0100, Théo Lebrun wrote:
> +static int eq5_phy_init(struct phy *phy)
> +{
> + struct eq5_phy_inst *inst = phy_get_drvdata(phy);
> + struct eq5_phy_private *priv = inst->priv;
> + struct device *dev = priv->dev;
> + u32 reg;
> +
> + dev_dbg(dev, "phy_init(inst=%td)\n", inst - priv->phys);
Nitpick: can you please remove the debugging prints and maybe add some
trace points to the PHY core if you feel strongly about having some
introspection?
> +
> + writel(0, inst->gp);
> + writel(0, inst->sgmii);
> +
> + udelay(5);
Could you please add a macro or comment hinting at the origin of the
magic number 5 here? You could also place these 3 lines in a common
helper, also called from eq5_phy_exit(), to avoid minor code
duplication.
> +
> + reg = readl(inst->gp) | EQ5_GP_TX_SWRST_DIS | EQ5_GP_TX_M_CLKE |
When you write 0 to inst->gp and then read it back, do you expect to
(a) get back 0 or
(b) are some fields non-resetting?
I see both as inconsistent, since if (a), you can remove the
readl(inst->gp) and expect the same result. And if (b), it also
shouldn't matter if you write zeroes a second time, if it was fine the
first time?
Shortly said, is readl(inst->gp) really needed?
> + EQ5_GP_SYS_SWRST_DIS | EQ5_GP_SYS_M_CLKE |
> + FIELD_PREP(EQ5_GP_RGMII_DRV, 0x9);
Quick sanity check on your proposal to use #phy-cells = <1>. This is not
a request to change anything.
What if you need to customize the RGMII drive strength (or some other
setting, maybe SGMII polarity if that is available) per lane, for a
particular board? How would you do that if each PHY does not have its
own OF node?
> + writel(reg, inst->gp);
> +
> + return 0;
> +}
> +
> +static int eq5_phy_exit(struct phy *phy)
> +{
> + struct eq5_phy_inst *inst = phy_get_drvdata(phy);
> + struct eq5_phy_private *priv = inst->priv;
> + struct device *dev = priv->dev;
> +
> + dev_dbg(dev, "phy_exit(inst=%td)\n", inst - priv->phys);
> +
> + writel(0, inst->gp);
> + writel(0, inst->sgmii);
> + udelay(5);
> +
> + return 0;
> +}
> +
> +static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> +{
> + struct eq5_phy_inst *inst = phy_get_drvdata(phy);
> + struct eq5_phy_private *priv = inst->priv;
> + struct device *dev = priv->dev;
> +
> + dev_dbg(dev, "phy_set_mode(inst=%td, mode=%d, submode=%d)\n",
> + inst - priv->phys, mode, submode);
> +
> + if (mode != PHY_MODE_ETHERNET)
> + return -EOPNOTSUPP;
> +
> + if (!phy_interface_mode_is_rgmii(submode) &&
> + submode != PHY_INTERFACE_MODE_SGMII)
> + return -EOPNOTSUPP;
Both PHYs are equal in capabilities, and support both RGMII and SGMII,
correct? I see the driver is implemented as if they were, but it doesn't
hurt to ask.
> +
> + inst->phy_interface = submode;
Short story: don't rely on the phy_set_mode_ext() -> phy_power_on() order.
Implement the driver so that it works the other way around too.
Long story:
https://lore.kernel.org/netdev/aXzFH09AeIRawCwU@shell.armlinux.org.uk/
> + return 0;
> +}
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH] phy: ti: j721e-wiz: Fix device_node leak in wiz_get_lane_phy_types()
From: Felix Gu @ 2026-02-10 18:14 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Kishon Vijay Abraham I, Jyri Sarha
Cc: linux-phy, linux-kernel, Felix Gu
The 'serdes' device_node is obtained using of_get_child_by_name(),
which increments the reference count. However, it is never put,
leading to a memory leak.
Use the __free(device_node) attribute to automatically decrement
the reference count when the 'serdes' variable goes out of scope.
Fixes: 7ae14cf581f2 ("phy: ti: j721e-wiz: Implement DisplayPort mode to the wiz driver")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
---
drivers/phy/ti/phy-j721e-wiz.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 12a19bf2875c..904541e9138e 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1407,9 +1407,8 @@ MODULE_DEVICE_TABLE(of, wiz_id_table);
static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
{
- struct device_node *serdes;
-
- serdes = of_get_child_by_name(dev->of_node, "serdes");
+ struct device_node *serdes __free(device_node) =
+ of_get_child_by_name(dev->of_node, "serdes");
if (!serdes) {
dev_err(dev, "%s: Getting \"serdes\"-node failed\n", __func__);
return -EINVAL;
---
base-commit: 193579fe01389bc21aff0051d13f24e8ea95b47d
change-id: 20260204-wiz-9a67604a034f
Best regards,
--
Felix Gu <ustc.gu@gmail.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH 4/8] phy: zynqmp: Calibrate ILL if necessary
From: Sean Anderson @ 2026-02-10 16:42 UTC (permalink / raw)
To: Pandey, Radhey Shyam, Laurent Pinchart, Vinod Koul,
linux-phy@lists.infradead.org
Cc: Krzysztof Wilczyński, Lorenzo Pieralisi,
linux-kernel@vger.kernel.org, Simek, Michal,
linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
Neil Armstrong, Rob Herring, Havalige, Thippeswamy,
Manivannan Sadhasivam, Bjorn Helgaas
In-Reply-To: <CY1PR12MB9697F67210064132883611A8B762A@CY1PR12MB9697.namprd12.prod.outlook.com>
On 2/10/26 11:04, Pandey, Radhey Shyam wrote:
> [Public]
>
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Tuesday, February 3, 2026 5:51 AM
>> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>; Vinod Koul
>> <vkoul@kernel.org>; linux-phy@lists.infradead.org
>> Cc: Krzysztof Wilczyński <kwilczynski@kernel.org>; Lorenzo Pieralisi
>> <lpieralisi@kernel.org>; Pandey, Radhey Shyam
>> <radhey.shyam.pandey@amd.com>; linux-kernel@vger.kernel.org; Simek, Michal
>> <michal.simek@amd.com>; linux-arm-kernel@lists.infradead.org; linux-
>> pci@vger.kernel.org; Neil Armstrong <neil.armstrong@linaro.org>; Rob Herring
>> <robh@kernel.org>; Havalige, Thippeswamy <thippeswamy.havalige@amd.com>;
>> Manivannan Sadhasivam <mani@kernel.org>; Bjorn Helgaas
>> <bhelgaas@google.com>; Sean Anderson <sean.anderson@linux.dev>
>> Subject: [PATCH 4/8] phy: zynqmp: Calibrate ILL if necessary
>>
>> init_serdes in psu_init_gpl is supposed to calibrate the ILL. However, this
>> may fail if the reference clock is not running, such as if the clock needs
>> to be configured on boot. To work around this, add support for ILL
>> calibration in U-Boot. If the ILL is already calibrated (any non-zero
>> value) we skip calibration.
>>
>> The algorithm is substantially the same as serdes_illcalib [1], but it has
>> been updated for readability (and to remove all the "if (lane0_active)"
>> conditions). Due to the amount of register fields, many of which are
>> undocumented (especially the chicken bits), I have mostly used defines only
>> for the register names. There are certainly areas where register writes are
>> superfluous, but I have left these in order to minimize deviation from the
>> procedure in serdes_illcalib.
>
> Please consider splitting the patch in introducing calibrate ILL functions
> and then subsequently using them.
OK
> How did you validate the changes? functional testing is one part
> but I think better to match register configuration done in psu_init vs
> this series?
I've done this in the past, but I didn't do so with this version of the
driver. I'll make sure to do this comparison for v2. FWIW the ILL
values achieved through this procedure are fairly close to the values I
got from the firmware.
> Have we tried running on multiple designs having
> different GT lane and protocol combinations .
Currently tested with SATA on GTR2 (on [1]) and PCIe on GTR0/1 (custom
design). I've also tested SGMII and DP on the other lanes (although not
USB as mentioned in the cover letter). I'd definitely appreciate if you
(or anyone else) could test on some other boards.
[1] https://developer.seco.com/hardware/product/computer-on-modules/smarc-modules/som-smarc-zu-b71/
> There are multiple magic numbers. Consider renaming it to
> meaningful defines.
Some of the fields have very long names. E.g. L0_TX_ANA_TM_3 has two
fields that we set: TX_serializer_enable and
force_TX_serializer_enabled. Setting it would look like
xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3,
L0_TX_ANA_TM_3_TX_SERIALIZER_ENABLE |
L0_TX_ANA_TM_3_FORCE_TX_SERIALIZER_ENABLE);
and there's really no way to get that under 80 characters. This is
probably the area where I could most improve things. But I'm not a fan
of tripling the line count since I think it makes it harder to follow
the flow of the initialization.
Other fields have poor documentation. E.g. L0_TM_IQ_ILL8 has a single
field ill_bypass_iq_polytrim_val documented as "IQ ILL polytrim bypass
value." I have no idea what this field does or why it needs to be set to
0xf3 so I can't really define a meaningful constant for it.
Lastly, some fields are not documented at all, notably UPHY_SPARE0.
In these latter two cases, I have not guessed at the semantics, but I'd
more than welcome any additional info.
>>
>> [1] Example implementation; xpsgtr_phy_illcalib coresponds to
>> serdes_illcalib_pcie_gen1:
>> https://source.denx.de/u-boot/u-boot/-/blob/v2026.01/board/xilinx/zynqmp/zynqmp-
>> zcu208-revA/psu_init_gpl.c?ref_type=tags#L710
>>
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> ---
>>
>> drivers/phy/xilinx/phy-zynqmp.c | 421 +++++++++++++++++++++++++++++++-
>> 1 file changed, 420 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
>> index 152af1702bbd..854b0ea04648 100644
>> --- a/drivers/phy/xilinx/phy-zynqmp.c
>> +++ b/drivers/phy/xilinx/phy-zynqmp.c
>> @@ -12,6 +12,7 @@
>> * PCIe should also work but that is experimental as of now.
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/clk.h>
>> #include <linux/debugfs.h>
>> #include <linux/delay.h>
>> @@ -31,6 +32,7 @@
>> */
>>
>> /* TX De-emphasis parameters */
>> +#define L0_TX_ANA_TM_3 0x000c
>> #define L0_TX_ANA_TM_18 0x0048
>> #define L0_TX_ANA_TM_118 0x01d8
>> #define L0_TX_ANA_TM_118_FORCE_17_0 BIT(0)
>> @@ -50,16 +52,49 @@
>> #define L0_TXPMD_TM_45_ENABLE_DP_POST2 BIT(5)
>>
>> /* PCS control parameters */
>> +#define L0_TM_ANA_BYP_4 0x1010
>> +#define L0_TM_ANA_BYP_7 0x1018
>> #define L0_TM_DIG_6 0x106c
>> +#define L0_TM_DIG_22 0x10ac
>> #define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f
>> #define L0_TX_DIG_61 0x00f4
>> #define L0_TM_DISABLE_SCRAMBLE_ENCODER 0x0f
>> +#define L0_TM_AUX_0 0x10cc
>> +#define L0_TM_MISC2 0x189c
>> +#define L0_TM_MISC2_ILL_CAL_BYPASS BIT(7)
>> +#define L0_TM_IQ_ILL1 0x18f8
>> +#define L0_TM_IQ_ILL2 0x18fc
>
> #define L0_TM_IQ_ILL3 0x1900
>
> IQ_ILL(n) = 0x18f8 + (n - 1) * 4 ?
>
> Similarly for others (when applicable)?
OK
>> +#define L0_TM_ILL11 0x198c
>> +#define L0_TM_ILL12 0x1990
>> +#define L0_TM_E_ILL1 0x1924
>> +#define L0_TM_E_ILL2 0x1928
>> +#define L0_TM_IQ_ILL3 0x1900
>> +#define L0_TM_E_ILL3 0x192c
>> +#define L0_TM_IQ_ILL7 0x1910
>> +#define L0_TM_E_ILL7 0x193c
>> +#define L0_TM_ILL8 0x1980
>> +#define L0_TM_IQ_ILL8 0x1914
>> +#define L0_TM_IQ_ILL9 0x1918
>> +#define L0_TM_EQ0 0x194c
>> +#define L0_TM_EQ0_EQ_STG2_CTRL_BYP BIT(5)
>> +#define L0_TM_EQ1 0x1950
>> +#define L0_TM_EQ1_EQ_STG2_RL_PROG GENMASK(1, 0)
>> +#define L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL BIT(2)
>> +#define L0_TM_E_ILL8 0x1940
>> +#define L0_TM_E_ILL9 0x1944
>> +#define L0_TM_ILL13 0x1994
>> +#define L0_TM_CDR5 0x1c14
>> +#define L0_TM_CDR5_FPHL_FSM_ACC_CYCLES GENMASK(7, 5)
>> +#define L0_TM_CDR5_FFL_PH0_INT_GAIN GENMASK(4, 0)
>> +#define L0_TM_CDR16 0x1c40
>>
>> /* PLL Test Mode register parameters */
>> +#define L0_TM_PLL_DIG_33 0x2084
>> #define L0_TM_PLL_DIG_37 0x2094
>> #define L0_TM_COARSE_CODE_LIMIT 0x10
>>
>> /* PLL SSC step size offsets */
>> +#define L0_PLL_FBDIV_FRAC_3_MSB 0x2360
>> #define L0_PLL_SS_STEPS_0_LSB 0x2368
>> #define L0_PLL_SS_STEPS_1_MSB 0x236c
>> #define L0_PLL_SS_STEP_SIZE_0_LSB 0x2370
>> @@ -69,6 +104,7 @@
>> #define L0_PLL_STATUS_READ_1 0x23e4
>>
>> /* SSC step size parameters */
>> +#define TM_FORCE_EN_FRAC BIT(6)
>> #define STEP_SIZE_0_MASK 0xff
>> #define STEP_SIZE_1_MASK 0xff
>> #define STEP_SIZE_2_MASK 0xff
>> @@ -76,6 +112,7 @@
>> #define STEP_SIZE_SHIFT 8
>> #define FORCE_STEP_SIZE 0x10
>> #define FORCE_STEPS 0x20
>> +#define TM_FORCE_EN BIT(7)
>> #define STEPS_0_MASK 0xff
>> #define STEPS_1_MASK 0x07
>>
>> @@ -84,6 +121,32 @@
>> #define L0_REF_CLK_LCL_SEL BIT(7)
>> #define L0_REF_CLK_SEL_MASK 0x9f
>>
>> +/* Built-in self-test parameters */
>> +#define L0_BIST_CTRL_1 0x3004
>> +#define L0_BIST_CTRL_2 0x3008
>> +#define L0_BIST_RUN_LEN_L 0x300c
>> +#define L0_BIST_ERR_INJ_POINT_L 0x3010
>> +#define L0_BIST_RUNLEN_ERR_INJ_H 0x3014
>> +#define L0_BIST_IDLE_TIME 0x3018
>> +#define L0_BIST_MARKER_L 0x301c
>> +#define L0_BIST_IDLE_CHAR_L 0x3020
>> +#define L0_BIST_MARKER_IDLE_H 0x3024
>> +#define L0_BIST_LOW_PULSE_TIME 0x3028
>> +#define L0_BIST_TOTAL_PULSE_TIME 0x302c
>> +#define L0_BIST_TEST_PAT_1 0x3030
>> +#define L0_BIST_TEST_PAT_2 0x3034
>> +#define L0_BIST_TEST_PAT_3 0x3038
>> +#define L0_BIST_TEST_PAT_4 0x303c
>> +#define L0_BIST_TEST_PAT_MSBS 0x3040
>> +#define L0_BIST_PKT_NUM 0x3044
>> +#define L0_BIST_FRM_IDLE_TIME 0x3048
>> +#define L0_BIST_PKT_CTR_L 0x304c
>> +#define L0_BIST_PKT_CTR_H 0x3050
>> +#define L0_BIST_ERR_CTR_L 0x3054
>> +#define L0_BIST_ERR_CTR_H 0x3058
>> +#define L0_BIST_FILLER_OUT 0x3068
>> +#define L0_BIST_FORCE_MK_RST 0x306c
>> +
>> /* Calibration digital logic parameters */
>> #define L3_TM_CALIB_DIG19 0xec4c
>> #define L3_CALIB_DONE_STATUS 0xef14
>> @@ -139,6 +202,9 @@ static const char *const xpsgtr_icm_str[] = {
>> #define TM_CMN_RST_SET 0x2
>> #define TM_CMN_RST_MASK 0x3
>>
>> +#define LPBK_CTRL0 0x10038
>> +#define LPBK_CTRL1 0x1003c
>> +
>> /* Bus width parameters */
>> #define TX_PROT_BUS_WIDTH 0x10040
>> #define RX_PROT_BUS_WIDTH 0x10044
>> @@ -148,9 +214,13 @@ static const char *const xpsgtr_icm_str[] = {
>> #define PROT_BUS_WIDTH_SHIFT(n) ((n) * 2)
>> #define PROT_BUS_WIDTH_MASK(n) GENMASK((n) * 2 + 1, (n) * 2)
>>
>> +#define UPHY_SPARE0 0X10098
>> +
>> /* Number of GT lanes */
>> #define NUM_LANES 4
>>
>> +#define SIOU_ECO_0 0x1c
>> +
>> /* SIOU SATA control register */
>> #define SATA_CONTROL_OFFSET 0x0100
>>
>> @@ -338,6 +408,33 @@ static void xpsgtr_restore_lane_regs(struct xpsgtr_dev
>> *gtr_dev)
>> gtr_dev->saved_regs[i]);
>> }
>>
>> +static inline void xpsgtr_write_lanes(struct xpsgtr_dev *gtr_dev,
>> + unsigned long *lanes, u32 reg, u32 value)
>> +{
>> + unsigned long lane;
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + void __iomem *addr = gtr_dev->serdes + lane * PHY_REG_OFFSET
>> + + reg;
>> +
>> + writel(value, addr);
>> + }
>> +}
>> +
>> +static inline void xpsgtr_clr_set_lanes(struct xpsgtr_dev *gtr_dev,
>> + unsigned long *lanes, u32 reg, u32 clr,
>> + u32 set)
>> +{
>> + unsigned long lane;
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + void __iomem *addr = gtr_dev->serdes + lane * PHY_REG_OFFSET
>> + + reg;
>> +
>> + writel((readl(addr) & ~clr) | set, addr);
>> + }
>> +}
>> +
>> /*
>> * Hardware Configuration
>> */
>> @@ -351,7 +448,7 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
>> u8 protocol = gtr_phy->protocol;
>> int ret;
>>
>> - dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n");
>> + dev_vdbg(gtr_dev->dev, "Waiting for PLL lock\n");
>
> Unrelated change.
We reconfigure the PLL many times during ILL training, and this debug
output makes it difficult to read the ILL calibration debug.
>>
>> /*
>> * For DP and PCIe, only the instance 0 PLL is used. Switch to that phy
>> @@ -520,6 +617,231 @@ static void xpsgtr_bypass_scrambler_8b10b(struct
>> xpsgtr_phy *gtr_phy)
>> xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61,
>> L0_TM_DISABLE_SCRAMBLE_ENCODER);
>> }
>>
>> +/* Enable or disable loopback */
>> +static void xpsgtr_phy_set_loopback(struct xpsgtr_phy *gtr_phy, bool enabled)
>> +{
>> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
>> + u32 reg = gtr_phy->lane >= 2 ? LPBK_CTRL1 : LPBK_CTRL0;
>> + u32 shift = gtr_phy->lane & 1 ? 4 : 0;
>> +
>> + xpsgtr_clr_set(gtr_dev, reg, 7 << shift, (u32)enabled << shift);
>> +}
>> +
>> +static void xpsgtr_phy_set_ill(struct xpsgtr_phy *gtr_phy, u32 ill, bool gen2)
>> +{
>> + u32 val = 4 + ill * 8;
>> +
>> + if (gen2) {
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL2, val & 0xff);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0x0f,
>> + 1 << (val >> 8));
>> + } else {
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL1, val & 0xff);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0xf0,
>> + (val >> 4) & 0x10);
>> + }
>> +}
>> +
>> +static bool xpsgtr_ill_calibrated(struct xpsgtr_phy *gtr_phy)
>> +{
>> + u32 ill1 = xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL1);
>> + u32 ill2 = xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL2);
>> + u32 ill12 = xpsgtr_read_phy(gtr_phy, L0_TM_ILL12);
>> +
>> + dev_dbg(gtr_phy->dev->dev, "lane %u gen1 ILL was %u gen2 ILL was
>> %u\n",
>> + gtr_phy->lane, ill1 / 8 + (ill12 & 0x10 ? 32 : 0),
>> + ill2 / 8 + (ill12 & 0x02 ? 32 : 0));
>> + return ill1 || ill2 || ill12;
>> +}
>> +
>> +static void xpsgtr_init_ill(struct xpsgtr_phy *gtr_phy)
>> +{
>> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
>> + struct clk *clk = gtr_dev->clk[gtr_phy->refclk];
>> + u32 ill123 = DIV_ROUND_CLOSEST(clk_get_rate(clk), 1000000);
>> +
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_MISC2, 0,
>> L0_TM_MISC2_ILL_CAL_BYPASS);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL1, ill123);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL2, ill123);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL3, ill123);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL7, 0xf3);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL7, 0xf3);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_ILL8, 0xff);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL9, 1);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL9, 1);
>> + xpsgtr_clr_set(gtr_dev, UPHY_SPARE0, BIT(5), 0);
>> +}
>> +
>> +static void xpsgtr_phy_illcalib(struct xpsgtr_dev *gtr_dev,
>> + unsigned long *lanes, bool gen2)
>> +{
>> + bool last_ok[NUM_LANES] = { 0 };
>> + int pass[NUM_LANES] = { 0 }, altpass[NUM_LANES] = { 0 };
>> + int best[NUM_LANES] = { 0 }, altbest[NUM_LANES] = { 0 };
>> + unsigned long lane;
>> + int i;
>> +
>> + /* Initialize the BIST */
>> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 1);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0x20);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0xf4);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0xfb);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0xff);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0x4a);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0x4a);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0x4a);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0x4a);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0x14);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 2);
>> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0);
>> +
>> + for (i = 0; i < 64; i++) {
>> + bool ok[NUM_LANES];
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES)
>> + xpsgtr_phy_set_ill(>r_dev->phys[lane], i, gen2);
>> +
>> + /* Reset lanes */
>> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x20,
>> + 0x10);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x40);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x04);
>> + udelay(50);
>> + if (gen2)
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0e);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x06);
>> + if (gen2) {
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x04);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x07);
>> + udelay(400);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x0c);
>> + udelay(15);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0f);
>> + udelay(100);
>> + }
>> +
>> + if (xpsgtr_wait_pll_lock(gtr_dev->phys[0].phy)) {
>> + memset(last_ok, 0, sizeof(last_ok));
>> + continue;
>> + }
>> +
>> + udelay(50);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0xc0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x80);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0xc0);
>> + udelay(50);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80);
>> + udelay(50);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0);
>> + udelay(500);
>> +
>> + /* Do the BIST */
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
>> + u32 packets, errors;
>> +
>> + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_10);
>> + xpsgtr_phy_set_loopback(gtr_phy, true);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_DIG_22, 0x20);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_BIST_CTRL_1, 0, 1);
>> +
>> + udelay(200);
>> + xpsgtr_write_phy(gtr_phy, L0_BIST_CTRL_1, 0);
>> + packets = xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_L);
>> + packets |= xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_H)
>> << 8;
>> + errors = xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_L);
>> + errors |= xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_H)
>> << 8;
>> + ok[lane] = packets && !errors;
>> +
>> + dev_dbg(gtr_dev->dev,
>> + "lane %lu ILL %d packets %10u errors %10u\n",
>> + lane, i, packets, errors);
>> + }
>> +
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x02);
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + pass[lane] += ok[lane] && last_ok[lane];
>> + if (pass[lane] < 4) {
>> + if (!ok[lane] && i > 2) {
>> + if (altpass[lane] < pass[lane]) {
>> + altpass[lane] = pass[lane];
>> + altbest[lane] =
>> + (i - 1) - (pass[lane] + 1) / 2;
>> + }
>> + pass[lane] = 0;
>> + }
>> + } else if (!best[lane] && (!ok[lane] || i == 63) &&
>> + last_ok[lane]) {
>> + best[lane] = (i - 1) - (pass[lane] + 1) / 2;
>> + }
>> + }
>> +
>> + memcpy(last_ok, ok, sizeof(ok));
>> + }
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + dev_dbg(gtr_dev->dev, "lane %lu ILL best %d alt best %d\n",
>> + lane, best[lane], altbest[lane]);
>> +
>> + xpsgtr_phy_set_ill(>r_dev->phys[lane],
>> + best[lane] ?: altbest[lane], gen2);
>> + }
>> +
>> + /* Clean up */
>> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x30, 0);
>> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_L, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_H, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 0);
>> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0);
>> +
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
>> +
>> + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_20);
>> + xpsgtr_phy_set_loopback(gtr_phy, false);
>> + }
>> +}
>> +
>> static int xpsgtr_common_init(struct xpsgtr_phy *gtr_phy)
>> {
>> int ret;
>> @@ -553,6 +875,37 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy
>> *gtr_phy)
>> {
>> struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
>>
>> + if (!xpsgtr_ill_calibrated(gtr_phy)) {
>> + DECLARE_BITMAP(lanes, NUM_LANES) = { 0 };
>> +
>> + xpsgtr_init_ill(gtr_phy);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL3, 100);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL11, 0xf0, 0x20);
>> +
>> + __set_bit(gtr_phy->lane, lanes);
>> + xpsgtr_phy_illcalib(gtr_dev, lanes, false);
>> + xpsgtr_phy_set_ill(gtr_phy, 7, true);
>> + }
>> +
>> + /* Disable SSC */
>> + xpsgtr_write_phy(gtr_phy, L0_PLL_FBDIV_FRAC_3_MSB,
>> TM_FORCE_EN_FRAC);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB, 0,
>> TM_FORCE_EN);
>> +
>> + /* Disable Tx deemphasis */
>> + xpsgtr_write_phy(gtr_phy, L0_TM_CDR5,
>> + FIELD_PREP(L0_TM_CDR5_FPHL_FSM_ACC_CYCLES,
>> 7) |
>> + FIELD_PREP(L0_TM_CDR5_FFL_PH0_INT_GAIN, 6));
>> + xpsgtr_write_phy(gtr_phy, L0_TM_CDR16, 12);
>> +
>> + /* Configure equalization */
>> + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_118,
>> + L0_TX_ANA_TM_118_FORCE_17_0);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ0, 0,
>> L0_TM_EQ0_EQ_STG2_CTRL_BYP);
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ1,
>> L0_TM_EQ1_EQ_STG2_RL_PROG,
>> + FIELD_PREP(L0_TM_EQ1_EQ_STG2_RL_PROG, 2) |
>> + L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL);
>> + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_18, 2); /* -3.5 dB deemphasis */
>> +
>> xpsgtr_bypass_scrambler_8b10b(gtr_phy);
>>
>> writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET);
>> @@ -565,6 +918,64 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy
>> *gtr_phy)
>> xpsgtr_bypass_scrambler_8b10b(gtr_phy);
>> }
>>
>> +/* PCIe-specific initialization. */
>> +static int xpsgtr_phy_init_pcie(struct xpsgtr_phy *gtr_phy)
>> +{
>> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
>> + DECLARE_BITMAP(lanes, NUM_LANES) = { 0 };
>> + unsigned long lane;
>> + bool calibrated = false;
>> +
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20);
>> +
>> + for (lane = 0; lane < NUM_LANES; lane++) {
>> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
>> +
>> + if (gtr_phy->protocol != ICM_PROTOCOL_PCIE)
>> + continue;
>> +
>> + __set_bit(lane, lanes);
>> + calibrated = calibrated || xpsgtr_ill_calibrated(gtr_phy);
>> + }
>> +
>> + if (calibrated)
>> + return 0;
>> +
>> + /* Write default ILL config */
>> + for_each_set_bit(lane, lanes, NUM_LANES) {
>> + struct xpsgtr_phy *p = >r_dev->phys[lane];
>> +
>> + if (lane != gtr_phy->lane) {
>> + int ret = xpsgtr_common_init(p);
>> +
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + xpsgtr_init_ill(p);
>> + xpsgtr_write_phy(p, L0_TM_E_ILL3, 0);
>> + xpsgtr_clr_set_phy(p, L0_TM_MISC2, 0,
>> + L0_TM_MISC2_ILL_CAL_BYPASS);
>> + }
>> +
>> + /* Perform the ILL calibration procedure */
>> + xpsgtr_phy_illcalib(gtr_dev, lanes, false);
>> + xpsgtr_phy_illcalib(gtr_dev, lanes, true);
>> +
>> + /* Disable PCIe ECO */
>> + writel(1, gtr_dev->siou + SIOU_ECO_0);
>> + return 0;
>> +}
>> +
>> +/* USB-specific initialization. */
>> +static void xpsgtr_phy_init_usb(struct xpsgtr_phy *gtr_phy)
>> +{
>> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3);
>> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3);
>> + xpsgtr_phy_set_ill(gtr_phy, 7, false);
>> +}
>> +
>> /* Configure TX de-emphasis and margining for DP. */
>> static void xpsgtr_phy_configure_dp(struct xpsgtr_phy *gtr_phy, unsigned int pre,
>> unsigned int voltage)
>> @@ -710,6 +1121,10 @@ static int xpsgtr_phy_init(struct phy *phy)
>> xpsgtr_phy_init_dp(gtr_phy);
>> break;
>>
>> + case ICM_PROTOCOL_PCIE:
>> + ret = xpsgtr_phy_init_pcie(gtr_phy);
>> + break;
>> +
>> case ICM_PROTOCOL_SATA:
>> xpsgtr_phy_init_sata(gtr_phy);
>> break;
>> @@ -717,6 +1132,10 @@ static int xpsgtr_phy_init(struct phy *phy)
>> case ICM_PROTOCOL_SGMII:
>> xpsgtr_phy_init_sgmii(gtr_phy);
>> break;
>> +
>> + case ICM_PROTOCOL_USB:
>> + xpsgtr_phy_init_usb(gtr_phy);
>> + break;
>> }
>>
>> out:
>> --
>> 2.35.1.1320.gc452695387.dirty
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* RE: [PATCH 4/8] phy: zynqmp: Calibrate ILL if necessary
From: Pandey, Radhey Shyam @ 2026-02-10 16:04 UTC (permalink / raw)
To: Sean Anderson, Laurent Pinchart, Vinod Koul,
linux-phy@lists.infradead.org
Cc: Krzysztof Wilczyński, Lorenzo Pieralisi,
linux-kernel@vger.kernel.org, Simek, Michal,
linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
Neil Armstrong, Rob Herring, Havalige, Thippeswamy,
Manivannan Sadhasivam, Bjorn Helgaas
In-Reply-To: <20260203002128.935842-5-sean.anderson@linux.dev>
[Public]
> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Tuesday, February 3, 2026 5:51 AM
> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>; Vinod Koul
> <vkoul@kernel.org>; linux-phy@lists.infradead.org
> Cc: Krzysztof Wilczyński <kwilczynski@kernel.org>; Lorenzo Pieralisi
> <lpieralisi@kernel.org>; Pandey, Radhey Shyam
> <radhey.shyam.pandey@amd.com>; linux-kernel@vger.kernel.org; Simek, Michal
> <michal.simek@amd.com>; linux-arm-kernel@lists.infradead.org; linux-
> pci@vger.kernel.org; Neil Armstrong <neil.armstrong@linaro.org>; Rob Herring
> <robh@kernel.org>; Havalige, Thippeswamy <thippeswamy.havalige@amd.com>;
> Manivannan Sadhasivam <mani@kernel.org>; Bjorn Helgaas
> <bhelgaas@google.com>; Sean Anderson <sean.anderson@linux.dev>
> Subject: [PATCH 4/8] phy: zynqmp: Calibrate ILL if necessary
>
> init_serdes in psu_init_gpl is supposed to calibrate the ILL. However, this
> may fail if the reference clock is not running, such as if the clock needs
> to be configured on boot. To work around this, add support for ILL
> calibration in U-Boot. If the ILL is already calibrated (any non-zero
> value) we skip calibration.
>
> The algorithm is substantially the same as serdes_illcalib [1], but it has
> been updated for readability (and to remove all the "if (lane0_active)"
> conditions). Due to the amount of register fields, many of which are
> undocumented (especially the chicken bits), I have mostly used defines only
> for the register names. There are certainly areas where register writes are
> superfluous, but I have left these in order to minimize deviation from the
> procedure in serdes_illcalib.
Please consider splitting the patch in introducing calibrate ILL functions
and then subsequently using them.
How did you validate the changes? functional testing is one part
but I think better to match register configuration done in psu_init vs
this series? Have we tried running on multiple designs having
different GT lane and protocol combinations .
There are multiple magic numbers. Consider renaming it to
meaningful defines.
>
> [1] Example implementation; xpsgtr_phy_illcalib coresponds to
> serdes_illcalib_pcie_gen1:
> https://source.denx.de/u-boot/u-boot/-/blob/v2026.01/board/xilinx/zynqmp/zynqmp-
> zcu208-revA/psu_init_gpl.c?ref_type=tags#L710
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> ---
>
> drivers/phy/xilinx/phy-zynqmp.c | 421 +++++++++++++++++++++++++++++++-
> 1 file changed, 420 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
> index 152af1702bbd..854b0ea04648 100644
> --- a/drivers/phy/xilinx/phy-zynqmp.c
> +++ b/drivers/phy/xilinx/phy-zynqmp.c
> @@ -12,6 +12,7 @@
> * PCIe should also work but that is experimental as of now.
> */
>
> +#include <linux/bitfield.h>
> #include <linux/clk.h>
> #include <linux/debugfs.h>
> #include <linux/delay.h>
> @@ -31,6 +32,7 @@
> */
>
> /* TX De-emphasis parameters */
> +#define L0_TX_ANA_TM_3 0x000c
> #define L0_TX_ANA_TM_18 0x0048
> #define L0_TX_ANA_TM_118 0x01d8
> #define L0_TX_ANA_TM_118_FORCE_17_0 BIT(0)
> @@ -50,16 +52,49 @@
> #define L0_TXPMD_TM_45_ENABLE_DP_POST2 BIT(5)
>
> /* PCS control parameters */
> +#define L0_TM_ANA_BYP_4 0x1010
> +#define L0_TM_ANA_BYP_7 0x1018
> #define L0_TM_DIG_6 0x106c
> +#define L0_TM_DIG_22 0x10ac
> #define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f
> #define L0_TX_DIG_61 0x00f4
> #define L0_TM_DISABLE_SCRAMBLE_ENCODER 0x0f
> +#define L0_TM_AUX_0 0x10cc
> +#define L0_TM_MISC2 0x189c
> +#define L0_TM_MISC2_ILL_CAL_BYPASS BIT(7)
> +#define L0_TM_IQ_ILL1 0x18f8
> +#define L0_TM_IQ_ILL2 0x18fc
#define L0_TM_IQ_ILL3 0x1900
IQ_ILL(n) = 0x18f8 + (n - 1) * 4 ?
Similarly for others (when applicable)?
> +#define L0_TM_ILL11 0x198c
> +#define L0_TM_ILL12 0x1990
> +#define L0_TM_E_ILL1 0x1924
> +#define L0_TM_E_ILL2 0x1928
> +#define L0_TM_IQ_ILL3 0x1900
> +#define L0_TM_E_ILL3 0x192c
> +#define L0_TM_IQ_ILL7 0x1910
> +#define L0_TM_E_ILL7 0x193c
> +#define L0_TM_ILL8 0x1980
> +#define L0_TM_IQ_ILL8 0x1914
> +#define L0_TM_IQ_ILL9 0x1918
> +#define L0_TM_EQ0 0x194c
> +#define L0_TM_EQ0_EQ_STG2_CTRL_BYP BIT(5)
> +#define L0_TM_EQ1 0x1950
> +#define L0_TM_EQ1_EQ_STG2_RL_PROG GENMASK(1, 0)
> +#define L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL BIT(2)
> +#define L0_TM_E_ILL8 0x1940
> +#define L0_TM_E_ILL9 0x1944
> +#define L0_TM_ILL13 0x1994
> +#define L0_TM_CDR5 0x1c14
> +#define L0_TM_CDR5_FPHL_FSM_ACC_CYCLES GENMASK(7, 5)
> +#define L0_TM_CDR5_FFL_PH0_INT_GAIN GENMASK(4, 0)
> +#define L0_TM_CDR16 0x1c40
>
> /* PLL Test Mode register parameters */
> +#define L0_TM_PLL_DIG_33 0x2084
> #define L0_TM_PLL_DIG_37 0x2094
> #define L0_TM_COARSE_CODE_LIMIT 0x10
>
> /* PLL SSC step size offsets */
> +#define L0_PLL_FBDIV_FRAC_3_MSB 0x2360
> #define L0_PLL_SS_STEPS_0_LSB 0x2368
> #define L0_PLL_SS_STEPS_1_MSB 0x236c
> #define L0_PLL_SS_STEP_SIZE_0_LSB 0x2370
> @@ -69,6 +104,7 @@
> #define L0_PLL_STATUS_READ_1 0x23e4
>
> /* SSC step size parameters */
> +#define TM_FORCE_EN_FRAC BIT(6)
> #define STEP_SIZE_0_MASK 0xff
> #define STEP_SIZE_1_MASK 0xff
> #define STEP_SIZE_2_MASK 0xff
> @@ -76,6 +112,7 @@
> #define STEP_SIZE_SHIFT 8
> #define FORCE_STEP_SIZE 0x10
> #define FORCE_STEPS 0x20
> +#define TM_FORCE_EN BIT(7)
> #define STEPS_0_MASK 0xff
> #define STEPS_1_MASK 0x07
>
> @@ -84,6 +121,32 @@
> #define L0_REF_CLK_LCL_SEL BIT(7)
> #define L0_REF_CLK_SEL_MASK 0x9f
>
> +/* Built-in self-test parameters */
> +#define L0_BIST_CTRL_1 0x3004
> +#define L0_BIST_CTRL_2 0x3008
> +#define L0_BIST_RUN_LEN_L 0x300c
> +#define L0_BIST_ERR_INJ_POINT_L 0x3010
> +#define L0_BIST_RUNLEN_ERR_INJ_H 0x3014
> +#define L0_BIST_IDLE_TIME 0x3018
> +#define L0_BIST_MARKER_L 0x301c
> +#define L0_BIST_IDLE_CHAR_L 0x3020
> +#define L0_BIST_MARKER_IDLE_H 0x3024
> +#define L0_BIST_LOW_PULSE_TIME 0x3028
> +#define L0_BIST_TOTAL_PULSE_TIME 0x302c
> +#define L0_BIST_TEST_PAT_1 0x3030
> +#define L0_BIST_TEST_PAT_2 0x3034
> +#define L0_BIST_TEST_PAT_3 0x3038
> +#define L0_BIST_TEST_PAT_4 0x303c
> +#define L0_BIST_TEST_PAT_MSBS 0x3040
> +#define L0_BIST_PKT_NUM 0x3044
> +#define L0_BIST_FRM_IDLE_TIME 0x3048
> +#define L0_BIST_PKT_CTR_L 0x304c
> +#define L0_BIST_PKT_CTR_H 0x3050
> +#define L0_BIST_ERR_CTR_L 0x3054
> +#define L0_BIST_ERR_CTR_H 0x3058
> +#define L0_BIST_FILLER_OUT 0x3068
> +#define L0_BIST_FORCE_MK_RST 0x306c
> +
> /* Calibration digital logic parameters */
> #define L3_TM_CALIB_DIG19 0xec4c
> #define L3_CALIB_DONE_STATUS 0xef14
> @@ -139,6 +202,9 @@ static const char *const xpsgtr_icm_str[] = {
> #define TM_CMN_RST_SET 0x2
> #define TM_CMN_RST_MASK 0x3
>
> +#define LPBK_CTRL0 0x10038
> +#define LPBK_CTRL1 0x1003c
> +
> /* Bus width parameters */
> #define TX_PROT_BUS_WIDTH 0x10040
> #define RX_PROT_BUS_WIDTH 0x10044
> @@ -148,9 +214,13 @@ static const char *const xpsgtr_icm_str[] = {
> #define PROT_BUS_WIDTH_SHIFT(n) ((n) * 2)
> #define PROT_BUS_WIDTH_MASK(n) GENMASK((n) * 2 + 1, (n) * 2)
>
> +#define UPHY_SPARE0 0X10098
> +
> /* Number of GT lanes */
> #define NUM_LANES 4
>
> +#define SIOU_ECO_0 0x1c
> +
> /* SIOU SATA control register */
> #define SATA_CONTROL_OFFSET 0x0100
>
> @@ -338,6 +408,33 @@ static void xpsgtr_restore_lane_regs(struct xpsgtr_dev
> *gtr_dev)
> gtr_dev->saved_regs[i]);
> }
>
> +static inline void xpsgtr_write_lanes(struct xpsgtr_dev *gtr_dev,
> + unsigned long *lanes, u32 reg, u32 value)
> +{
> + unsigned long lane;
> +
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + void __iomem *addr = gtr_dev->serdes + lane * PHY_REG_OFFSET
> + + reg;
> +
> + writel(value, addr);
> + }
> +}
> +
> +static inline void xpsgtr_clr_set_lanes(struct xpsgtr_dev *gtr_dev,
> + unsigned long *lanes, u32 reg, u32 clr,
> + u32 set)
> +{
> + unsigned long lane;
> +
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + void __iomem *addr = gtr_dev->serdes + lane * PHY_REG_OFFSET
> + + reg;
> +
> + writel((readl(addr) & ~clr) | set, addr);
> + }
> +}
> +
> /*
> * Hardware Configuration
> */
> @@ -351,7 +448,7 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
> u8 protocol = gtr_phy->protocol;
> int ret;
>
> - dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n");
> + dev_vdbg(gtr_dev->dev, "Waiting for PLL lock\n");
Unrelated change.
>
> /*
> * For DP and PCIe, only the instance 0 PLL is used. Switch to that phy
> @@ -520,6 +617,231 @@ static void xpsgtr_bypass_scrambler_8b10b(struct
> xpsgtr_phy *gtr_phy)
> xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61,
> L0_TM_DISABLE_SCRAMBLE_ENCODER);
> }
>
> +/* Enable or disable loopback */
> +static void xpsgtr_phy_set_loopback(struct xpsgtr_phy *gtr_phy, bool enabled)
> +{
> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
> + u32 reg = gtr_phy->lane >= 2 ? LPBK_CTRL1 : LPBK_CTRL0;
> + u32 shift = gtr_phy->lane & 1 ? 4 : 0;
> +
> + xpsgtr_clr_set(gtr_dev, reg, 7 << shift, (u32)enabled << shift);
> +}
> +
> +static void xpsgtr_phy_set_ill(struct xpsgtr_phy *gtr_phy, u32 ill, bool gen2)
> +{
> + u32 val = 4 + ill * 8;
> +
> + if (gen2) {
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL2, val & 0xff);
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0x0f,
> + 1 << (val >> 8));
> + } else {
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL1, val & 0xff);
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0xf0,
> + (val >> 4) & 0x10);
> + }
> +}
> +
> +static bool xpsgtr_ill_calibrated(struct xpsgtr_phy *gtr_phy)
> +{
> + u32 ill1 = xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL1);
> + u32 ill2 = xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL2);
> + u32 ill12 = xpsgtr_read_phy(gtr_phy, L0_TM_ILL12);
> +
> + dev_dbg(gtr_phy->dev->dev, "lane %u gen1 ILL was %u gen2 ILL was
> %u\n",
> + gtr_phy->lane, ill1 / 8 + (ill12 & 0x10 ? 32 : 0),
> + ill2 / 8 + (ill12 & 0x02 ? 32 : 0));
> + return ill1 || ill2 || ill12;
> +}
> +
> +static void xpsgtr_init_ill(struct xpsgtr_phy *gtr_phy)
> +{
> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
> + struct clk *clk = gtr_dev->clk[gtr_phy->refclk];
> + u32 ill123 = DIV_ROUND_CLOSEST(clk_get_rate(clk), 1000000);
> +
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_MISC2, 0,
> L0_TM_MISC2_ILL_CAL_BYPASS);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL1, ill123);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL2, ill123);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL3, ill123);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL7, 0xf3);
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL7, 0xf3);
> + xpsgtr_write_phy(gtr_phy, L0_TM_ILL8, 0xff);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3);
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL9, 1);
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL9, 1);
> + xpsgtr_clr_set(gtr_dev, UPHY_SPARE0, BIT(5), 0);
> +}
> +
> +static void xpsgtr_phy_illcalib(struct xpsgtr_dev *gtr_dev,
> + unsigned long *lanes, bool gen2)
> +{
> + bool last_ok[NUM_LANES] = { 0 };
> + int pass[NUM_LANES] = { 0 }, altpass[NUM_LANES] = { 0 };
> + int best[NUM_LANES] = { 0 }, altbest[NUM_LANES] = { 0 };
> + unsigned long lane;
> + int i;
> +
> + /* Initialize the BIST */
> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 1);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0x20);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0xf4);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0xfb);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0xff);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0x4a);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0x4a);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0x4a);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0x4a);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0x14);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 2);
> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0);
> +
> + for (i = 0; i < 64; i++) {
> + bool ok[NUM_LANES];
> +
> + for_each_set_bit(lane, lanes, NUM_LANES)
> + xpsgtr_phy_set_ill(>r_dev->phys[lane], i, gen2);
> +
> + /* Reset lanes */
> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x20,
> + 0x10);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x40);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x04);
> + udelay(50);
> + if (gen2)
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0e);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x06);
> + if (gen2) {
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x04);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x07);
> + udelay(400);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x0c);
> + udelay(15);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0f);
> + udelay(100);
> + }
> +
> + if (xpsgtr_wait_pll_lock(gtr_dev->phys[0].phy)) {
> + memset(last_ok, 0, sizeof(last_ok));
> + continue;
> + }
> +
> + udelay(50);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0xc0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x80);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0xc0);
> + udelay(50);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80);
> + udelay(50);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0);
> + udelay(500);
> +
> + /* Do the BIST */
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
> + u32 packets, errors;
> +
> + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_10);
> + xpsgtr_phy_set_loopback(gtr_phy, true);
> + xpsgtr_write_phy(gtr_phy, L0_TM_DIG_22, 0x20);
> + xpsgtr_clr_set_phy(gtr_phy, L0_BIST_CTRL_1, 0, 1);
> +
> + udelay(200);
> + xpsgtr_write_phy(gtr_phy, L0_BIST_CTRL_1, 0);
> + packets = xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_L);
> + packets |= xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_H)
> << 8;
> + errors = xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_L);
> + errors |= xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_H)
> << 8;
> + ok[lane] = packets && !errors;
> +
> + dev_dbg(gtr_dev->dev,
> + "lane %lu ILL %d packets %10u errors %10u\n",
> + lane, i, packets, errors);
> + }
> +
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x02);
> +
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + pass[lane] += ok[lane] && last_ok[lane];
> + if (pass[lane] < 4) {
> + if (!ok[lane] && i > 2) {
> + if (altpass[lane] < pass[lane]) {
> + altpass[lane] = pass[lane];
> + altbest[lane] =
> + (i - 1) - (pass[lane] + 1) / 2;
> + }
> + pass[lane] = 0;
> + }
> + } else if (!best[lane] && (!ok[lane] || i == 63) &&
> + last_ok[lane]) {
> + best[lane] = (i - 1) - (pass[lane] + 1) / 2;
> + }
> + }
> +
> + memcpy(last_ok, ok, sizeof(ok));
> + }
> +
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + dev_dbg(gtr_dev->dev, "lane %lu ILL best %d alt best %d\n",
> + lane, best[lane], altbest[lane]);
> +
> + xpsgtr_phy_set_ill(>r_dev->phys[lane],
> + best[lane] ?: altbest[lane], gen2);
> + }
> +
> + /* Clean up */
> + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x30, 0);
> + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_L, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_H, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 0);
> + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0);
> +
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
> +
> + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_20);
> + xpsgtr_phy_set_loopback(gtr_phy, false);
> + }
> +}
> +
> static int xpsgtr_common_init(struct xpsgtr_phy *gtr_phy)
> {
> int ret;
> @@ -553,6 +875,37 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy
> *gtr_phy)
> {
> struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
>
> + if (!xpsgtr_ill_calibrated(gtr_phy)) {
> + DECLARE_BITMAP(lanes, NUM_LANES) = { 0 };
> +
> + xpsgtr_init_ill(gtr_phy);
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL3, 100);
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL11, 0xf0, 0x20);
> +
> + __set_bit(gtr_phy->lane, lanes);
> + xpsgtr_phy_illcalib(gtr_dev, lanes, false);
> + xpsgtr_phy_set_ill(gtr_phy, 7, true);
> + }
> +
> + /* Disable SSC */
> + xpsgtr_write_phy(gtr_phy, L0_PLL_FBDIV_FRAC_3_MSB,
> TM_FORCE_EN_FRAC);
> + xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB, 0,
> TM_FORCE_EN);
> +
> + /* Disable Tx deemphasis */
> + xpsgtr_write_phy(gtr_phy, L0_TM_CDR5,
> + FIELD_PREP(L0_TM_CDR5_FPHL_FSM_ACC_CYCLES,
> 7) |
> + FIELD_PREP(L0_TM_CDR5_FFL_PH0_INT_GAIN, 6));
> + xpsgtr_write_phy(gtr_phy, L0_TM_CDR16, 12);
> +
> + /* Configure equalization */
> + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_118,
> + L0_TX_ANA_TM_118_FORCE_17_0);
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ0, 0,
> L0_TM_EQ0_EQ_STG2_CTRL_BYP);
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ1,
> L0_TM_EQ1_EQ_STG2_RL_PROG,
> + FIELD_PREP(L0_TM_EQ1_EQ_STG2_RL_PROG, 2) |
> + L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL);
> + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_18, 2); /* -3.5 dB deemphasis */
> +
> xpsgtr_bypass_scrambler_8b10b(gtr_phy);
>
> writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET);
> @@ -565,6 +918,64 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy
> *gtr_phy)
> xpsgtr_bypass_scrambler_8b10b(gtr_phy);
> }
>
> +/* PCIe-specific initialization. */
> +static int xpsgtr_phy_init_pcie(struct xpsgtr_phy *gtr_phy)
> +{
> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
> + DECLARE_BITMAP(lanes, NUM_LANES) = { 0 };
> + unsigned long lane;
> + bool calibrated = false;
> +
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20);
> +
> + for (lane = 0; lane < NUM_LANES; lane++) {
> + struct xpsgtr_phy *gtr_phy = >r_dev->phys[lane];
> +
> + if (gtr_phy->protocol != ICM_PROTOCOL_PCIE)
> + continue;
> +
> + __set_bit(lane, lanes);
> + calibrated = calibrated || xpsgtr_ill_calibrated(gtr_phy);
> + }
> +
> + if (calibrated)
> + return 0;
> +
> + /* Write default ILL config */
> + for_each_set_bit(lane, lanes, NUM_LANES) {
> + struct xpsgtr_phy *p = >r_dev->phys[lane];
> +
> + if (lane != gtr_phy->lane) {
> + int ret = xpsgtr_common_init(p);
> +
> + if (ret)
> + return ret;
> + }
> +
> + xpsgtr_init_ill(p);
> + xpsgtr_write_phy(p, L0_TM_E_ILL3, 0);
> + xpsgtr_clr_set_phy(p, L0_TM_MISC2, 0,
> + L0_TM_MISC2_ILL_CAL_BYPASS);
> + }
> +
> + /* Perform the ILL calibration procedure */
> + xpsgtr_phy_illcalib(gtr_dev, lanes, false);
> + xpsgtr_phy_illcalib(gtr_dev, lanes, true);
> +
> + /* Disable PCIe ECO */
> + writel(1, gtr_dev->siou + SIOU_ECO_0);
> + return 0;
> +}
> +
> +/* USB-specific initialization. */
> +static void xpsgtr_phy_init_usb(struct xpsgtr_phy *gtr_phy)
> +{
> + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20);
> + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3);
> + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3);
> + xpsgtr_phy_set_ill(gtr_phy, 7, false);
> +}
> +
> /* Configure TX de-emphasis and margining for DP. */
> static void xpsgtr_phy_configure_dp(struct xpsgtr_phy *gtr_phy, unsigned int pre,
> unsigned int voltage)
> @@ -710,6 +1121,10 @@ static int xpsgtr_phy_init(struct phy *phy)
> xpsgtr_phy_init_dp(gtr_phy);
> break;
>
> + case ICM_PROTOCOL_PCIE:
> + ret = xpsgtr_phy_init_pcie(gtr_phy);
> + break;
> +
> case ICM_PROTOCOL_SATA:
> xpsgtr_phy_init_sata(gtr_phy);
> break;
> @@ -717,6 +1132,10 @@ static int xpsgtr_phy_init(struct phy *phy)
> case ICM_PROTOCOL_SGMII:
> xpsgtr_phy_init_sgmii(gtr_phy);
> break;
> +
> + case ICM_PROTOCOL_USB:
> + xpsgtr_phy_init_usb(gtr_phy);
> + break;
> }
>
> out:
> --
> 2.35.1.1320.gc452695387.dirty
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* RE: [PATCH 3/8] phy: zynqmp: Refactor common phy initialization into a helper
From: Pandey, Radhey Shyam @ 2026-02-10 15:05 UTC (permalink / raw)
To: Sean Anderson, Laurent Pinchart, Vinod Koul,
linux-phy@lists.infradead.org
Cc: Krzysztof Wilczyński, Lorenzo Pieralisi,
linux-kernel@vger.kernel.org, Simek, Michal,
linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
Neil Armstrong, Rob Herring, Havalige, Thippeswamy,
Manivannan Sadhasivam, Bjorn Helgaas
In-Reply-To: <20260203002128.935842-4-sean.anderson@linux.dev>
[Public]
> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Tuesday, February 3, 2026 5:51 AM
> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>; Vinod Koul
> <vkoul@kernel.org>; linux-phy@lists.infradead.org
> Cc: Krzysztof Wilczyński <kwilczynski@kernel.org>; Lorenzo Pieralisi
> <lpieralisi@kernel.org>; Pandey, Radhey Shyam
> <radhey.shyam.pandey@amd.com>; linux-kernel@vger.kernel.org; Simek, Michal
> <michal.simek@amd.com>; linux-arm-kernel@lists.infradead.org; linux-
> pci@vger.kernel.org; Neil Armstrong <neil.armstrong@linaro.org>; Rob Herring
> <robh@kernel.org>; Havalige, Thippeswamy <thippeswamy.havalige@amd.com>;
> Manivannan Sadhasivam <mani@kernel.org>; Bjorn Helgaas
> <bhelgaas@google.com>; Sean Anderson <sean.anderson@linux.dev>
> Subject: [PATCH 3/8] phy: zynqmp: Refactor common phy initialization into a helper
>
> All lanes undergoing ILL calibration must be initialized. Split off
> common phy initialization into a helper so that we can ensure all lanes
> are initialized before performing calibration.
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Thanks!
> ---
>
> drivers/phy/xilinx/phy-zynqmp.c | 22 ++++++++++++++++------
> 1 file changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
> index 0d3c578d0f3f..152af1702bbd 100644
> --- a/drivers/phy/xilinx/phy-zynqmp.c
> +++ b/drivers/phy/xilinx/phy-zynqmp.c
> @@ -520,6 +520,21 @@ static void xpsgtr_bypass_scrambler_8b10b(struct
> xpsgtr_phy *gtr_phy)
> xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61,
> L0_TM_DISABLE_SCRAMBLE_ENCODER);
> }
>
> +static int xpsgtr_common_init(struct xpsgtr_phy *gtr_phy)
> +{
> + int ret;
> +
> + /* Enable coarse code saturation limiting logic. */
> + xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37,
> L0_TM_COARSE_CODE_LIMIT);
> +
> + ret = xpsgtr_configure_pll(gtr_phy);
> + if (ret)
> + return ret;
> +
> + xpsgtr_lane_set_protocol(gtr_phy);
> + return 0;
> +}
> +
> /* DP-specific initialization. */
> static void xpsgtr_phy_init_dp(struct xpsgtr_phy *gtr_phy)
> {
> @@ -682,19 +697,14 @@ static int xpsgtr_phy_init(struct phy *phy)
> gtr_dev->tx_term_fix = false;
> }
>
> - /* Enable coarse code saturation limiting logic. */
> - xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37,
> L0_TM_COARSE_CODE_LIMIT);
> -
> /*
> * Configure the PLL, the lane protocol, and perform protocol-specific
> * initialization.
> */
> - ret = xpsgtr_configure_pll(gtr_phy);
> + ret = xpsgtr_common_init(gtr_phy);
> if (ret)
> goto out;
>
> - xpsgtr_lane_set_protocol(gtr_phy);
> -
> switch (gtr_phy->protocol) {
> case ICM_PROTOCOL_DP:
> xpsgtr_phy_init_dp(gtr_phy);
> --
> 2.35.1.1320.gc452695387.dirty
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* RE: [PATCH 2/8] phy: zynqmp: Refactor bus width configuration into helper
From: Pandey, Radhey Shyam @ 2026-02-10 15:00 UTC (permalink / raw)
To: Sean Anderson, Laurent Pinchart, Vinod Koul,
linux-phy@lists.infradead.org
Cc: Krzysztof Wilczyński, Lorenzo Pieralisi,
linux-kernel@vger.kernel.org, Simek, Michal,
linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
Neil Armstrong, Rob Herring, Havalige, Thippeswamy,
Manivannan Sadhasivam, Bjorn Helgaas
In-Reply-To: <20260203002128.935842-3-sean.anderson@linux.dev>
[Public]
> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Tuesday, February 3, 2026 5:51 AM
> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>; Vinod Koul
> <vkoul@kernel.org>; linux-phy@lists.infradead.org
> Cc: Krzysztof Wilczyński <kwilczynski@kernel.org>; Lorenzo Pieralisi
> <lpieralisi@kernel.org>; Pandey, Radhey Shyam
> <radhey.shyam.pandey@amd.com>; linux-kernel@vger.kernel.org; Simek, Michal
> <michal.simek@amd.com>; linux-arm-kernel@lists.infradead.org; linux-
> pci@vger.kernel.org; Neil Armstrong <neil.armstrong@linaro.org>; Rob Herring
> <robh@kernel.org>; Havalige, Thippeswamy <thippeswamy.havalige@amd.com>;
> Manivannan Sadhasivam <mani@kernel.org>; Bjorn Helgaas
> <bhelgaas@google.com>; Sean Anderson <sean.anderson@linux.dev>
> Subject: [PATCH 2/8] phy: zynqmp: Refactor bus width configuration into helper
>
> Split off the bus width configuration into a helper function for reuse.
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Thanks!
> ---
>
> drivers/phy/xilinx/phy-zynqmp.c | 20 ++++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
> index fe6b4925d166..0d3c578d0f3f 100644
> --- a/drivers/phy/xilinx/phy-zynqmp.c
> +++ b/drivers/phy/xilinx/phy-zynqmp.c
> @@ -502,6 +502,17 @@ static void xpsgtr_lane_set_protocol(struct xpsgtr_phy
> *gtr_phy)
> }
> }
>
> +/* Set the bus width */
> +static void xpsgtr_phy_init_bus_width(struct xpsgtr_phy *gtr_phy, u32 width)
> +{
> + struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
> + u32 mask = PROT_BUS_WIDTH_MASK(gtr_phy->lane);
> + u32 val = width << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane);
> +
> + xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val);
> + xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val);
> +}
> +
> /* Bypass (de)scrambler and 8b/10b decoder and encoder. */
> static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy)
> {
> @@ -535,14 +546,7 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy
> *gtr_phy)
> /* SGMII-specific initialization. */
> static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy)
> {
> - struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
> - u32 mask = PROT_BUS_WIDTH_MASK(gtr_phy->lane);
> - u32 val = PROT_BUS_WIDTH_10 << PROT_BUS_WIDTH_SHIFT(gtr_phy-
> >lane);
> -
> - /* Set SGMII protocol TX and RX bus width to 10 bits. */
> - xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val);
> - xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val);
> -
> + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_10);
> xpsgtr_bypass_scrambler_8b10b(gtr_phy);
> }
>
> --
> 2.35.1.1320.gc452695387.dirty
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 3/7] mux: add help text for MULTIPLEXER config option
From: Peter Rosin @ 2026-02-10 14:45 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Josua Mayer, Marc Kleine-Budde, Vincent Mailhol, Vinod Koul,
Neil Armstrong, Aaro Koskinen, Andreas Kemnade, Kevin Hilman,
Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R,
Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang,
Yazan Shhady, Jon Nettleton, Mikhail Anikin,
linux-can@vger.kernel.org, linux-phy@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org,
linux-i2c@vger.kernel.org, linux-mmc@vger.kernel.org,
devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org
In-Reply-To: <CAMuHMdUEZZ+p+yaQDWhVCRNEQUygR2j=HpCp5LuzFU3E=qVNXg@mail.gmail.com>
Hi!
2026-02-10 at 08:50, Geert Uytterhoeven wrote:
> In the other thread, Josua pointed out that there are already several
> drivers that cannot be enabled if MULTIPLEXER is not selected by
> something else:
>
> drivers/mux/Kconfig:
>
> menu "Multiplexer drivers"
> depends on MULTIPLEXER
>
> config MUX_ADG792A
> tristate "Analog Devices ADG792A/ADG792G Multiplexers"
> depends on I2C
>
> config MUX_ADGS1408
> tristate "Analog Devices ADGS1408/ADGS1409 Multiplexers"
> depends on SPI
>
> config MUX_GPIO
> tristate "GPIO-controlled Multiplexer"
> depends on GPIOLIB || COMPILE_TEST
>
> config MUX_MMIO
> tristate "MMIO/Regmap register bitfield-controlled Multiplexer"
> depends on OF
>
> While MUX_MMIO is selected by some/all(?) symbols that need it,
> the other three are not. Are these three really dependent on another
> symbol selecting MULTIPLEXER?
I think you have the gist of it, yes. It's of course not ideal...
Cheers,
Peter
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 3/7] mux: add help text for MULTIPLEXER config option
From: Peter Rosin @ 2026-02-10 14:42 UTC (permalink / raw)
To: Josua Mayer, Marc Kleine-Budde, Vincent Mailhol, Vinod Koul,
Neil Armstrong, Aaro Koskinen, Andreas Kemnade, Kevin Hilman,
Roger Quadros, Tony Lindgren, Janusz Krzysztofik, Vignesh R,
Andi Shyti, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Geert Uytterhoeven, Magnus Damm, Wolfram Sang
Cc: Yazan Shhady, Jon Nettleton, Mikhail Anikin,
linux-can@vger.kernel.org, linux-phy@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org,
linux-i2c@vger.kernel.org, linux-mmc@vger.kernel.org,
devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org
In-Reply-To: <de20903c-cae3-4f2e-8784-5b04421fdf4e@solid-run.com>
Hi!
2026-02-09 at 21:02, Josua Mayer wrote:
> Any suggestion how to name the new config symbol that can have
> a visible prompt?
MULTIPLEXER_CORE perhaps? Or maybe just MUX_CORE?
Cheers,
Peter
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
From: Ulf Hansson @ 2026-02-10 13:34 UTC (permalink / raw)
To: Vinod Koul, Geert Uytterhoeven
Cc: Yoshihiro Shimoda, Neil Armstrong, Josua Mayer, Wolfram Sang,
Tommaso Merciai, linux-phy, linux-mmc, linux-renesas-soc,
linux-next, linux-kernel
In-Reply-To: <67c8c4f9bf9f09fd0c13daedef27b82ff389ddfb.1770720452.git.geert+renesas@glider.be>
On Tue, 10 Feb 2026 at 11:53, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
>
> Now the mux core provides devm_mux_state_get_optional():
>
> drivers/phy/renesas/phy-rcar-gen3-usb2.c:944:1: error: static declaration of ‘devm_mux_state_get_optional’ follows non-static
> declaration
> 944 | devm_mux_state_get_optional(struct device *dev, const char *mux_name)
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> In file included from drivers/phy/renesas/phy-rcar-gen3-usb2.c:20:
> include/linux/mux/consumer.h:64:19: note: previous declaration of ‘devm_mux_state_get_optional’ with type ‘struct mux_state *(struct device *, const char *)’
> 64 | struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> Fix this by dropping the temporary local wrapper.
>
> Fixes: ad314348ceb4fe1f ("mux: Add helper functions for getting optional and selected mux-state")
> Fixes: 8bb92fd7a0407792 ("phy: renesas: rcar-gen3-usb2: Use mux-state for phyrst management")
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Thanks Geert for helping out!
> ---
> - ad314348ceb4fe1f is in mmc/next, and a PR has already been sent
> https://lore.kernel.org/20260209133441.556464-1-ulf.hansson@linaro.org
> - 8bb92fd7a0407792 is in phy/next
Vinod, do you want to pick up the $subject patch as a fix for 7.0-rc1
or do you prefer me to handle it?
Kind regards
Uffe
> ---
> drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 ----------
> 1 file changed, 10 deletions(-)
>
> diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> index cfc2a8d9028d58d0..65cbf330bd8fa10c 100644
> --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> @@ -939,16 +939,6 @@ static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *cha
> return rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(channel, enable);
> }
>
> -/* Temporary wrapper until the multiplexer subsystem supports optional muxes */
> -static inline struct mux_state *
> -devm_mux_state_get_optional(struct device *dev, const char *mux_name)
> -{
> - if (!of_property_present(dev->of_node, "mux-states"))
> - return NULL;
> -
> - return devm_mux_state_get(dev, mux_name);
> -}
> -
> static void rcar_gen3_phy_mux_state_deselect(void *data)
> {
> mux_state_deselect(data);
> --
> 2.43.0
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 1/3] phy: qcom: edp: Correct and clean up eDP/DP combo PHY configuration values
From: Dmitry Baryshkov @ 2026-02-10 12:33 UTC (permalink / raw)
To: Yongxing Mou
Cc: Vinod Koul, Neil Armstrong, linux-arm-msm, linux-phy,
linux-kernel
In-Reply-To: <23e007dc-4145-4260-8810-1e98e533b1b5@oss.qualcomm.com>
On Tue, Feb 10, 2026 at 06:17:07PM +0800, Yongxing Mou wrote:
>
>
> On 2/9/2026 8:47 PM, Dmitry Baryshkov wrote:
> > On Mon, Feb 09, 2026 at 05:52:22PM +0800, Yongxing Mou wrote:
> > >
> > >
> > > On 2/7/2026 6:22 PM, Dmitry Baryshkov wrote:
> > > > On Thu, Feb 05, 2026 at 05:20:53PM +0800, Yongxing Mou wrote:
> > > > > According to the current HPG settings, most eDP/DP combo PHYs can reuse the
> > > > > same configuration values.
> > > > > DP mode:
> > > > > -sa8775p/sc7280/sc8280xp/x1e80100
> > > > > -glymur
> > > > > eDP mode(low vdiff):
> > > > > -glymur/sa8775p/sc8280xp/x1e80100
> > > > > -sc7280
> > > > > The current driver still keeps multiple versions of these tables and
> > > > > doesn't fully support every combo PHY mode. This patch removes the
> > > >
> > > > See Documentation/process/submitting-patches.rst, "This patch".
> > > >
> > > Sure. got it thanks, will remove "This patch".
> > > > > redundant configs and keeps only the sets we actually use, matching the
> > > > > platforms listed above.
> > > >
> > > > Should it be combined with the 3rd patch? There you sort out all the
> > > > tables, it makes more sense to review all programming together.
> > > >
> > > Hi, if this would help with your review work, I’m very happy to do it.
> > > My original intention was to do some cleanup in this patch—correct the table
> > > values so that more platforms can reuse the same table.
> >
> > Fixed should come before cleanups (so that they can be backported to
> > stable kernels).
> >
> Hi, do you mean the second LDO patch should come before the first patch?In
More like 3rd patch should be combined with the first and come before /
with LDO fixes.
> fact, maybe three patches should go into the stable branch. The LDO patch
> cannot be used on its own. On both sa8775p and hamoa, their eDP/DP modes do
> not match the tables they are currently using (hamoa should use the eDP
> table, while sa8775p should use the DP table). If only the LDO patch is
> applied, it may cause link training to fail.
> > > From Konard’s comments, it seems that the HPG table may not be the most
> > > appropriate one either.
> > > Maybe shoud first determine what the correct table values should be.
> >
> > Please follow the tables for each SKU separately (that's the 'fix'
> > part).
> >
> Sure.
>
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
From: Tommaso Merciai @ 2026-02-10 11:26 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Yoshihiro Shimoda, Vinod Koul, Neil Armstrong, Josua Mayer,
Ulf Hansson, Wolfram Sang, linux-phy, linux-mmc,
linux-renesas-soc, linux-next, linux-kernel
In-Reply-To: <67c8c4f9bf9f09fd0c13daedef27b82ff389ddfb.1770720452.git.geert+renesas@glider.be>
Hi Geert,
Thanks for your patch!
On Tue, Feb 10, 2026 at 11:53:00AM +0100, Geert Uytterhoeven wrote:
> Now the mux core provides devm_mux_state_get_optional():
>
> drivers/phy/renesas/phy-rcar-gen3-usb2.c:944:1: error: static declaration of ‘devm_mux_state_get_optional’ follows non-static
> declaration
> 944 | devm_mux_state_get_optional(struct device *dev, const char *mux_name)
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> In file included from drivers/phy/renesas/phy-rcar-gen3-usb2.c:20:
> include/linux/mux/consumer.h:64:19: note: previous declaration of ‘devm_mux_state_get_optional’ with type ‘struct mux_state *(struct device *, const char *)’
> 64 | struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> Fix this by dropping the temporary local wrapper.
>
> Fixes: ad314348ceb4fe1f ("mux: Add helper functions for getting optional and selected mux-state")
> Fixes: 8bb92fd7a0407792 ("phy: renesas: rcar-gen3-usb2: Use mux-state for phyrst management")
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> - ad314348ceb4fe1f is in mmc/next, and a PR has already been sent
> https://lore.kernel.org/20260209133441.556464-1-ulf.hansson@linaro.org
> - 8bb92fd7a0407792 is in phy/next
Thanks for sharing :)
> ---
> drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 ----------
> 1 file changed, 10 deletions(-)
>
> diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> index cfc2a8d9028d58d0..65cbf330bd8fa10c 100644
> --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
> @@ -939,16 +939,6 @@ static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *cha
> return rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(channel, enable);
> }
>
> -/* Temporary wrapper until the multiplexer subsystem supports optional muxes */
> -static inline struct mux_state *
> -devm_mux_state_get_optional(struct device *dev, const char *mux_name)
> -{
> - if (!of_property_present(dev->of_node, "mux-states"))
> - return NULL;
> -
> - return devm_mux_state_get(dev, mux_name);
> -}
> -
> static void rcar_gen3_phy_mux_state_deselect(void *data)
> {
> mux_state_deselect(data);
> --
> 2.43.0
LGTM.
Tested on RZ/G3E.
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Reviewed-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Kind Regards,
Tommaso
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH next] phy: renesas: rcar-gen3-usb2: Drop local devm_mux_state_get_optional()
From: Geert Uytterhoeven @ 2026-02-10 10:53 UTC (permalink / raw)
To: Yoshihiro Shimoda, Vinod Koul, Neil Armstrong, Josua Mayer,
Ulf Hansson, Wolfram Sang, Tommaso Merciai
Cc: linux-phy, linux-mmc, linux-renesas-soc, linux-next, linux-kernel,
Geert Uytterhoeven
Now the mux core provides devm_mux_state_get_optional():
drivers/phy/renesas/phy-rcar-gen3-usb2.c:944:1: error: static declaration of ‘devm_mux_state_get_optional’ follows non-static
declaration
944 | devm_mux_state_get_optional(struct device *dev, const char *mux_name)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/phy/renesas/phy-rcar-gen3-usb2.c:20:
include/linux/mux/consumer.h:64:19: note: previous declaration of ‘devm_mux_state_get_optional’ with type ‘struct mux_state *(struct device *, const char *)’
64 | struct mux_state *devm_mux_state_get_optional(struct device *dev, const char *mux_name);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
Fix this by dropping the temporary local wrapper.
Fixes: ad314348ceb4fe1f ("mux: Add helper functions for getting optional and selected mux-state")
Fixes: 8bb92fd7a0407792 ("phy: renesas: rcar-gen3-usb2: Use mux-state for phyrst management")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
- ad314348ceb4fe1f is in mmc/next, and a PR has already been sent
https://lore.kernel.org/20260209133441.556464-1-ulf.hansson@linaro.org
- 8bb92fd7a0407792 is in phy/next
---
drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index cfc2a8d9028d58d0..65cbf330bd8fa10c 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -939,16 +939,6 @@ static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *cha
return rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(channel, enable);
}
-/* Temporary wrapper until the multiplexer subsystem supports optional muxes */
-static inline struct mux_state *
-devm_mux_state_get_optional(struct device *dev, const char *mux_name)
-{
- if (!of_property_present(dev->of_node, "mux-states"))
- return NULL;
-
- return devm_mux_state_get(dev, mux_name);
-}
-
static void rcar_gen3_phy_mux_state_deselect(void *data)
{
mux_state_deselect(data);
--
2.43.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox