Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: mediatek: xsphy: support type switch by pericfg

Patch from Sam Shih <sam.shih@mediatek.com> found in MediaTek SDK
released under GPL.

Get syscon and use it to set the PHY type.
Extend support to PCIe and SGMII mode in addition to USB2 and USB3.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20250422132438.15735-7-linux@fw-web.de
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Daniel Golle and committed by
Vinod Koul
f85eb659 b484b25a

+84 -1
+84 -1
drivers/phy/mediatek/phy-mtk-xsphy.c
··· 11 11 #include <linux/clk.h> 12 12 #include <linux/delay.h> 13 13 #include <linux/iopoll.h> 14 + #include <linux/mfd/syscon.h> 14 15 #include <linux/module.h> 15 16 #include <linux/of_address.h> 16 17 #include <linux/phy/phy.h> 17 18 #include <linux/platform_device.h> 19 + #include <linux/regmap.h> 18 20 19 21 #include "phy-mtk-io.h" 20 22 ··· 83 81 #define XSP_SR_COEF_DIVISOR 1000 84 82 #define XSP_FM_DET_CYCLE_CNT 1024 85 83 84 + /* PHY switch between pcie/usb3/sgmii */ 85 + #define USB_PHY_SWITCH_CTRL 0x0 86 + #define RG_PHY_SW_TYPE GENMASK(3, 0) 87 + #define RG_PHY_SW_PCIE 0x0 88 + #define RG_PHY_SW_USB3 0x1 89 + #define RG_PHY_SW_SGMII 0x2 90 + 86 91 struct xsphy_instance { 87 92 struct phy *phy; 88 93 void __iomem *port_base; 89 94 struct clk *ref_clk; /* reference clock of anolog phy */ 90 95 u32 index; 91 96 u32 type; 97 + struct regmap *type_sw; 98 + u32 type_sw_reg; 99 + u32 type_sw_index; 92 100 /* only for HQA test */ 93 101 int efuse_intr; 94 102 int efuse_tx_imp; ··· 271 259 inst->efuse_intr, inst->efuse_tx_imp, 272 260 inst->efuse_rx_imp); 273 261 break; 262 + case PHY_TYPE_PCIE: 263 + case PHY_TYPE_SGMII: 264 + /* nothing to do */ 265 + break; 274 266 default: 275 267 dev_err(xsphy->dev, "incompatible phy type\n"); 276 268 return; ··· 321 305 RG_XTP_LN0_RX_IMPSEL, inst->efuse_rx_imp); 322 306 } 323 307 308 + /* type switch for usb3/pcie/sgmii */ 309 + static int phy_type_syscon_get(struct xsphy_instance *instance, 310 + struct device_node *dn) 311 + { 312 + struct of_phandle_args args; 313 + int ret; 314 + 315 + /* type switch function is optional */ 316 + if (!of_property_present(dn, "mediatek,syscon-type")) 317 + return 0; 318 + 319 + ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type", 320 + 2, 0, &args); 321 + if (ret) 322 + return ret; 323 + 324 + instance->type_sw_reg = args.args[0]; 325 + instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ 326 + instance->type_sw = syscon_node_to_regmap(args.np); 327 + of_node_put(args.np); 328 + dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n", 329 + instance->type_sw_reg, instance->type_sw_index); 330 + 331 + return PTR_ERR_OR_ZERO(instance->type_sw); 332 + } 333 + 334 + static int phy_type_set(struct xsphy_instance *instance) 335 + { 336 + int type; 337 + u32 offset; 338 + 339 + if (!instance->type_sw) 340 + return 0; 341 + 342 + switch (instance->type) { 343 + case PHY_TYPE_USB3: 344 + type = RG_PHY_SW_USB3; 345 + break; 346 + case PHY_TYPE_PCIE: 347 + type = RG_PHY_SW_PCIE; 348 + break; 349 + case PHY_TYPE_SGMII: 350 + type = RG_PHY_SW_SGMII; 351 + break; 352 + case PHY_TYPE_USB2: 353 + default: 354 + return 0; 355 + } 356 + 357 + offset = instance->type_sw_index * BITS_PER_BYTE; 358 + regmap_update_bits(instance->type_sw, instance->type_sw_reg, 359 + RG_PHY_SW_TYPE << offset, type << offset); 360 + 361 + return 0; 362 + } 363 + 324 364 static int mtk_phy_init(struct phy *phy) 325 365 { 326 366 struct xsphy_instance *inst = phy_get_drvdata(phy); ··· 396 324 break; 397 325 case PHY_TYPE_USB3: 398 326 u3_phy_props_set(xsphy, inst); 327 + break; 328 + case PHY_TYPE_PCIE: 329 + case PHY_TYPE_SGMII: 330 + /* nothing to do, only used to set type */ 399 331 break; 400 332 default: 401 333 dev_err(xsphy->dev, "incompatible phy type\n"); ··· 479 403 480 404 inst->type = args->args[0]; 481 405 if (!(inst->type == PHY_TYPE_USB2 || 482 - inst->type == PHY_TYPE_USB3)) { 406 + inst->type == PHY_TYPE_USB3 || 407 + inst->type == PHY_TYPE_PCIE || 408 + inst->type == PHY_TYPE_SGMII)) { 483 409 dev_err(dev, "unsupported phy type: %d\n", inst->type); 484 410 return ERR_PTR(-EINVAL); 485 411 } 486 412 487 413 phy_parse_property(xsphy, inst); 414 + phy_type_set(inst); 488 415 489 416 return inst->phy; 490 417 } ··· 589 510 dev_err(dev, "failed to get ref_clk(id-%d)\n", port); 590 511 return PTR_ERR(inst->ref_clk); 591 512 } 513 + 514 + retval = phy_type_syscon_get(inst, child_np); 515 + if (retval) 516 + return retval; 592 517 } 593 518 594 519 provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);