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.

Merge branch 'phy-polarity-inversion-via-generic-device-tree-properties'

Vladimir Oltean says:

====================
PHY polarity inversion via generic device tree properties

Using the "rx-polarity" and "tx-polarity" device tree properties
introduced in linux-phy and merged into net-next in
commit 96a2d53f2478 ("Merge tag 'phy_common_properties' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy")
we convert here two existing networking use cases - the EN8811H Ethernet
PHY and the Mediatek LynxI PCS.

Original cover letter:

Polarity inversion (described in patch 4/10) is a feature with at least
4 potential new users waiting for a generic description:
- Horatiu Vultur with the lan966x SerDes
- Daniel Golle with the MaxLinear GSW1xx switches
- Bjørn Mork with the AN8811HB Ethernet PHY
- Me with a custom SJA1105 board, switch which uses the DesignWare XPCS

I became interested in exploring the problem space because I was averse
to the idea of adding vendor-specific device tree properties to describe
a common need.

This set contains an implementation of a generic feature that should
cater to all known needs that were identified during my documentation
phase.

Apart from what is converted here, we also have the following, which I
did not touch:
- "st,px_rx_pol_inv" - its binding is a .txt file and I don't have time
for such a large detour to convert it to dtschema.
- "st,pcie-tx-pol-inv" and "st,sata-tx-pol-inv" - these are defined in a
.txt schema but are not implemented in any driver. My verdict would be
"delete the properties" but again, I would prefer not introducing such
dependency to this series.
====================

Link: https://patch.msgid.link/20260119091220.1493761-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+121 -43
+10 -1
Documentation/devicetree/bindings/net/airoha,en8811h.yaml
··· 16 16 17 17 allOf: 18 18 - $ref: ethernet-phy.yaml# 19 + - $ref: /schemas/phy/phy-common-props.yaml# 19 20 20 21 properties: 21 22 compatible: ··· 31 30 description: 32 31 Reverse rx polarity of the SERDES. This is the receiving 33 32 side of the lines from the MAC towards the EN881H. 33 + This property is deprecated, for details please refer to 34 + Documentation/devicetree/bindings/phy/phy-common-props.yaml 35 + deprecated: true 34 36 35 37 airoha,pnswap-tx: 36 38 type: boolean 37 39 description: 38 40 Reverse tx polarity of SERDES. This is the transmitting 39 41 side of the lines from EN8811H towards the MAC. 42 + This property is deprecated, for details please refer to 43 + Documentation/devicetree/bindings/phy/phy-common-props.yaml 44 + deprecated: true 40 45 41 46 required: 42 47 - reg ··· 51 44 52 45 examples: 53 46 - | 47 + #include <dt-bindings/phy/phy.h> 48 + 54 49 mdio { 55 50 #address-cells = <1>; 56 51 #size-cells = <0>; ··· 60 51 ethernet-phy@1 { 61 52 compatible = "ethernet-phy-id03a2.a411"; 62 53 reg = <1>; 63 - airoha,pnswap-rx; 54 + rx-polarity = <PHY_POL_INVERT>; 64 55 }; 65 56 };
+6 -1
Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml
··· 39 39 const: 1 40 40 41 41 mediatek,pnswap: 42 - description: Invert polarity of the SGMII data lanes 42 + description: 43 + Invert polarity of the SGMII data lanes. 44 + This property is deprecated, for details please refer to 45 + Documentation/devicetree/bindings/phy/phy-common-props.yaml. 43 46 type: boolean 47 + deprecated: true 44 48 45 49 pcs: 46 50 type: object 47 51 description: MediaTek LynxI HSGMII PCS 52 + $ref: /schemas/phy/phy-common-props.yaml# 48 53 properties: 49 54 compatible: 50 55 const: mediatek,mt7988-sgmii
+2 -2
drivers/net/dsa/mt7530-mdio.c
··· 113 113 ret = PTR_ERR(regmap); 114 114 break; 115 115 } 116 - pcs = mtk_pcs_lynxi_create(priv->dev, regmap, 117 - MT7531_PHYA_CTRL_SIGNAL3, 0); 116 + pcs = mtk_pcs_lynxi_create(priv->dev, NULL, regmap, 117 + MT7531_PHYA_CTRL_SIGNAL3); 118 118 if (!pcs) { 119 119 ret = -ENXIO; 120 120 break;
+8 -11
drivers/net/ethernet/mediatek/mtk_eth_soc.c
··· 4994 4994 { 4995 4995 struct device_node *np; 4996 4996 struct regmap *regmap; 4997 - u32 flags; 4998 4997 int i; 4999 4998 5000 4999 for (i = 0; i < MTK_MAX_DEVS; i++) { ··· 5002 5003 break; 5003 5004 5004 5005 regmap = syscon_node_to_regmap(np); 5005 - flags = 0; 5006 - if (of_property_read_bool(np, "mediatek,pnswap")) 5007 - flags |= MTK_SGMII_FLAG_PN_SWAP; 5008 - 5009 - of_node_put(np); 5010 - 5011 - if (IS_ERR(regmap)) 5006 + if (IS_ERR(regmap)) { 5007 + of_node_put(np); 5012 5008 return PTR_ERR(regmap); 5009 + } 5013 5010 5014 - eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, regmap, 5015 - eth->soc->ana_rgc3, 5016 - flags); 5011 + eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, 5012 + of_fwnode_handle(np), 5013 + regmap, 5014 + eth->soc->ana_rgc3); 5015 + of_node_put(np); 5017 5016 } 5018 5017 5019 5018 return 0;
+1
drivers/net/pcs/Kconfig
··· 20 20 21 21 config PCS_MTK_LYNXI 22 22 tristate 23 + select PHY_COMMON_PROPS 23 24 select REGMAP 24 25 help 25 26 This module provides helpers to phylink for managing the LynxI PCS
+53 -10
drivers/net/pcs/pcs-mtk-lynxi.c
··· 11 11 #include <linux/mdio.h> 12 12 #include <linux/of.h> 13 13 #include <linux/pcs/pcs-mtk-lynxi.h> 14 + #include <linux/phy/phy-common-props.h> 14 15 #include <linux/phylink.h> 15 16 #include <linux/regmap.h> 16 17 ··· 63 62 64 63 /* Register to QPHY wrapper control */ 65 64 #define SGMSYS_QPHY_WRAP_CTRL 0xec 66 - #define SGMII_PN_SWAP_MASK GENMASK(1, 0) 67 - #define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) 65 + #define SGMII_PN_SWAP_RX BIT(1) 66 + #define SGMII_PN_SWAP_TX BIT(0) 67 + 68 68 69 69 /* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated 70 70 * data ··· 83 81 phy_interface_t interface; 84 82 struct phylink_pcs pcs; 85 83 u32 flags; 84 + struct fwnode_handle *fwnode; 86 85 }; 87 86 88 87 static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) ··· 123 120 FIELD_GET(SGMII_LPA, adv)); 124 121 } 125 122 123 + static int mtk_pcs_config_polarity(struct mtk_pcs_lynxi *mpcs, 124 + phy_interface_t interface) 125 + { 126 + struct fwnode_handle *fwnode = mpcs->fwnode, *pcs_fwnode; 127 + unsigned int pol, default_pol = PHY_POL_NORMAL; 128 + unsigned int val = 0; 129 + int ret; 130 + 131 + if (fwnode_property_read_bool(fwnode, "mediatek,pnswap")) 132 + default_pol = PHY_POL_INVERT; 133 + 134 + pcs_fwnode = fwnode_get_named_child_node(fwnode, "pcs"); 135 + 136 + ret = phy_get_rx_polarity(pcs_fwnode, phy_modes(interface), 137 + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), 138 + default_pol, &pol); 139 + if (ret) { 140 + fwnode_handle_put(pcs_fwnode); 141 + return ret; 142 + } 143 + if (pol == PHY_POL_INVERT) 144 + val |= SGMII_PN_SWAP_RX; 145 + 146 + ret = phy_get_tx_polarity(pcs_fwnode, phy_modes(interface), 147 + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), 148 + default_pol, &pol); 149 + fwnode_handle_put(pcs_fwnode); 150 + if (ret) 151 + return ret; 152 + if (pol == PHY_POL_INVERT) 153 + val |= SGMII_PN_SWAP_TX; 154 + 155 + return regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, 156 + SGMII_PN_SWAP_RX | SGMII_PN_SWAP_TX, val); 157 + } 158 + 126 159 static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, 127 160 phy_interface_t interface, 128 161 const unsigned long *advertising, ··· 168 129 bool mode_changed = false, changed; 169 130 unsigned int rgc3, sgm_mode, bmcr; 170 131 int advertise, link_timer; 132 + int ret; 171 133 172 134 advertise = phylink_mii_c22_pcs_encode_advertisement(interface, 173 135 advertising); ··· 208 168 regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, 209 169 SGMII_SW_RESET); 210 170 211 - if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) 212 - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, 213 - SGMII_PN_SWAP_MASK, 214 - SGMII_PN_SWAP_TX_RX); 171 + ret = mtk_pcs_config_polarity(mpcs, interface); 172 + if (ret) 173 + return ret; 215 174 216 175 if (interface == PHY_INTERFACE_MODE_2500BASEX) 217 176 rgc3 = SGMII_PHY_SPEED_3_125G; ··· 307 268 }; 308 269 309 270 struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, 310 - struct regmap *regmap, u32 ana_rgc3, 311 - u32 flags) 271 + struct fwnode_handle *fwnode, 272 + struct regmap *regmap, u32 ana_rgc3) 312 273 { 313 274 struct mtk_pcs_lynxi *mpcs; 314 275 u32 id, ver; ··· 342 303 343 304 mpcs->ana_rgc3 = ana_rgc3; 344 305 mpcs->regmap = regmap; 345 - mpcs->flags = flags; 346 306 mpcs->pcs.ops = &mtk_pcs_lynxi_ops; 347 307 mpcs->pcs.poll = true; 348 308 mpcs->interface = PHY_INTERFACE_MODE_NA; 309 + mpcs->fwnode = fwnode_handle_get(fwnode); 349 310 350 311 __set_bit(PHY_INTERFACE_MODE_SGMII, mpcs->pcs.supported_interfaces); 351 312 __set_bit(PHY_INTERFACE_MODE_1000BASEX, mpcs->pcs.supported_interfaces); ··· 357 318 358 319 void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs) 359 320 { 321 + struct mtk_pcs_lynxi *mpcs; 322 + 360 323 if (!pcs) 361 324 return; 362 325 363 - kfree(pcs_to_mtk_pcs_lynxi(pcs)); 326 + mpcs = pcs_to_mtk_pcs_lynxi(pcs); 327 + fwnode_handle_put(mpcs->fwnode); 328 + kfree(mpcs); 364 329 } 365 330 EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); 366 331
+1
drivers/net/phy/Kconfig
··· 98 98 99 99 config AIR_EN8811H_PHY 100 100 tristate "Airoha EN8811H 2.5 Gigabit PHY" 101 + select PHY_COMMON_PROPS 101 102 help 102 103 Currently supports the Airoha EN8811H PHY. 103 104
+38 -15
drivers/net/phy/air_en8811h.c
··· 14 14 #include <linux/clk.h> 15 15 #include <linux/clk-provider.h> 16 16 #include <linux/phy.h> 17 + #include <linux/phy/phy-common-props.h> 17 18 #include <linux/firmware.h> 18 19 #include <linux/property.h> 19 20 #include <linux/wordpart.h> ··· 967 966 return 0; 968 967 } 969 968 969 + static int en8811h_config_serdes_polarity(struct phy_device *phydev) 970 + { 971 + struct device *dev = &phydev->mdio.dev; 972 + unsigned int pol, default_pol; 973 + u32 pbus_value = 0; 974 + int ret; 975 + 976 + default_pol = PHY_POL_NORMAL; 977 + if (device_property_read_bool(dev, "airoha,pnswap-rx")) 978 + default_pol = PHY_POL_INVERT; 979 + 980 + ret = phy_get_rx_polarity(dev_fwnode(dev), phy_modes(phydev->interface), 981 + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), 982 + default_pol, &pol); 983 + if (ret) 984 + return ret; 985 + if (pol == PHY_POL_INVERT) 986 + pbus_value |= EN8811H_POLARITY_RX_REVERSE; 987 + 988 + default_pol = PHY_POL_NORMAL; 989 + if (device_property_read_bool(dev, "airoha,pnswap-tx")) 990 + default_pol = PHY_POL_INVERT; 991 + 992 + ret = phy_get_tx_polarity(dev_fwnode(dev), phy_modes(phydev->interface), 993 + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), 994 + default_pol, &pol); 995 + if (ret) 996 + return ret; 997 + if (pol == PHY_POL_NORMAL) 998 + pbus_value |= EN8811H_POLARITY_TX_NORMAL; 999 + 1000 + return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, 1001 + EN8811H_POLARITY_RX_REVERSE | 1002 + EN8811H_POLARITY_TX_NORMAL, pbus_value); 1003 + } 1004 + 970 1005 static int en8811h_config_init(struct phy_device *phydev) 971 1006 { 972 1007 struct en8811h_priv *priv = phydev->priv; 973 - struct device *dev = &phydev->mdio.dev; 974 - u32 pbus_value; 975 1008 int ret; 976 1009 977 1010 /* If restart happened in .probe(), no need to restart now */ ··· 1038 1003 if (ret < 0) 1039 1004 return ret; 1040 1005 1041 - /* Serdes polarity */ 1042 - pbus_value = 0; 1043 - if (device_property_read_bool(dev, "airoha,pnswap-rx")) 1044 - pbus_value |= EN8811H_POLARITY_RX_REVERSE; 1045 - else 1046 - pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; 1047 - if (device_property_read_bool(dev, "airoha,pnswap-tx")) 1048 - pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; 1049 - else 1050 - pbus_value |= EN8811H_POLARITY_TX_NORMAL; 1051 - ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, 1052 - EN8811H_POLARITY_RX_REVERSE | 1053 - EN8811H_POLARITY_TX_NORMAL, pbus_value); 1006 + ret = en8811h_config_serdes_polarity(phydev); 1054 1007 if (ret < 0) 1055 1008 return ret; 1056 1009
+2 -3
include/linux/pcs/pcs-mtk-lynxi.h
··· 5 5 #include <linux/phylink.h> 6 6 #include <linux/regmap.h> 7 7 8 - #define MTK_SGMII_FLAG_PN_SWAP BIT(0) 9 8 struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, 10 - struct regmap *regmap, 11 - u32 ana_rgc3, u32 flags); 9 + struct fwnode_handle *fwnode, 10 + struct regmap *regmap, u32 ana_rgc3); 12 11 void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); 13 12 #endif