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 'net-phy-realtek-various-improvements-for-2-5ge-phys'

Daniel Golle says:

====================
net: phy: realtek: various improvements for 2.5GE PHYs

This series improves the RealTek PHY driver, mostly for 2.5GE PHYs.
It implements configuring SGMII and 2500Base-X in-band auto-negotiation
and improves using the PHYs in Clause-22-only mode.

Note that the rtl822x_serdes_write() function introduced by this series
is going to be reused to configure polarities of SerDes RX and TX lanes
once series "PHY polarity inversion via generic device tree properties"
has been applied.

Access to other registers on MDIO_MMD_VEND2 is important for more than
just configuring autonegotiation, it is also used to setup ALDPS or to
disable the PHY responding to the MDIO broadcast address 0. Both will be
implemented by follow-up patches.

The address translation function for registers on MDIO_MMD_VEND2 into
paged registers can potentially also be used to describe other paged
access in a more consistent way, but that mostly makes sense on PHYs
which also support Clause-45, so this series doesn't convert all the
existing paged access on RealTek's 1GE PHYs which do not support
Clause-45.
====================

Link: https://patch.msgid.link/cover.1767630451.git.daniel@makrotopia.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+235 -83
-6
drivers/net/phy/phylib-internal.h
··· 7 7 #define __PHYLIB_INTERNAL_H 8 8 9 9 struct phy_device; 10 - struct mii_bus; 11 10 12 11 /* 13 12 * phy_supported_speeds - return all speeds currently supported by a PHY device ··· 19 20 void of_set_phy_timing_role(struct phy_device *phydev); 20 21 int phy_speed_down_core(struct phy_device *phydev); 21 22 void phy_check_downshift(struct phy_device *phydev); 22 - 23 - int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, 24 - int devad, u32 regnum); 25 - int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, 26 - int devad, u32 regnum, u16 val); 27 23 28 24 int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv); 29 25
+5
drivers/net/phy/phylib.h
··· 8 8 9 9 struct device_node; 10 10 struct phy_device; 11 + struct mii_bus; 11 12 12 13 struct device_node *phy_package_get_node(struct phy_device *phydev); 13 14 void *phy_package_get_priv(struct phy_device *phydev); ··· 31 30 int base_addr, size_t priv_size); 32 31 int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, 33 32 size_t priv_size); 33 + int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, 34 + int devad, u32 regnum); 35 + int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, 36 + int devad, u32 regnum, u16 val); 34 37 35 38 #endif /* __PHYLIB_H */
+230 -77
drivers/net/phy/realtek/realtek_main.c
··· 18 18 #include <linux/clk.h> 19 19 #include <linux/string_choices.h> 20 20 21 + #include "../phylib.h" 21 22 #include "realtek.h" 22 23 23 24 #define RTL8201F_IER 0x13 ··· 132 131 #define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 133 132 #define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 134 133 135 - /* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 136 - * is set, they cannot be accessed by C45-over-C22. 137 - */ 134 + #define RTL822X_VND1_SERDES_CMD 0x7587 135 + #define RTL822X_VND1_SERDES_CMD_WRITE BIT(1) 136 + #define RTL822X_VND1_SERDES_CMD_BUSY BIT(0) 137 + #define RTL822X_VND1_SERDES_ADDR 0x7588 138 + #define RTL822X_VND1_SERDES_ADDR_AUTONEG 0x2 139 + #define RTL822X_VND1_SERDES_INBAND_DISABLE 0x71d0 140 + #define RTL822X_VND1_SERDES_INBAND_ENABLE 0x70d0 141 + #define RTL822X_VND1_SERDES_DATA 0x7589 142 + 143 + #define RTL822X_VND2_TO_PAGE(reg) ((reg) >> 4) 144 + #define RTL822X_VND2_TO_PAGE_REG(reg) (16 + (((reg) & GENMASK(3, 0)) >> 1)) 138 145 #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) 139 146 140 147 #define RTL8221B_VND2_INER 0xa4d2 ··· 1154 1145 if (!phydev->link) 1155 1146 return 0; 1156 1147 1157 - val = phy_read_paged(phydev, 0xa43, 0x12); 1148 + val = phy_read_paged(phydev, RTL822X_VND2_TO_PAGE(RTL_VND2_PHYSR), 1149 + RTL822X_VND2_TO_PAGE_REG(RTL_VND2_PHYSR)); 1158 1150 if (val < 0) 1159 1151 return val; 1160 1152 ··· 1248 1238 return 0; 1249 1239 } 1250 1240 1241 + /* RTL822x cannot access MDIO_MMD_VEND2 via MII_MMD_CTRL/MII_MMD_DATA. 1242 + * A mapping to use paged access needs to be used instead. 1243 + * All other MMD devices can be accessed as usual. 1244 + */ 1245 + static int rtl822xb_read_mmd(struct phy_device *phydev, int devnum, u16 reg) 1246 + { 1247 + int oldpage, ret, read_ret; 1248 + u16 page; 1249 + 1250 + /* Use default method for all MMDs except MDIO_MMD_VEND2 or in case 1251 + * Clause-45 access is available 1252 + */ 1253 + if (devnum != MDIO_MMD_VEND2 || phydev->is_c45) 1254 + return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr, 1255 + phydev->is_c45, devnum, reg); 1256 + 1257 + /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */ 1258 + page = RTL822X_VND2_TO_PAGE(reg); 1259 + oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT); 1260 + if (oldpage < 0) 1261 + return oldpage; 1262 + 1263 + if (oldpage != page) { 1264 + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, page); 1265 + if (ret < 0) 1266 + return ret; 1267 + } 1268 + 1269 + read_ret = __phy_read(phydev, RTL822X_VND2_TO_PAGE_REG(reg)); 1270 + if (oldpage != page) { 1271 + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, oldpage); 1272 + if (ret < 0) 1273 + return ret; 1274 + } 1275 + 1276 + return read_ret; 1277 + } 1278 + 1279 + static int rtl822xb_write_mmd(struct phy_device *phydev, int devnum, u16 reg, 1280 + u16 val) 1281 + { 1282 + int oldpage, ret, write_ret; 1283 + u16 page; 1284 + 1285 + /* Use default method for all MMDs except MDIO_MMD_VEND2 or in case 1286 + * Clause-45 access is available 1287 + */ 1288 + if (devnum != MDIO_MMD_VEND2 || phydev->is_c45) 1289 + return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr, 1290 + phydev->is_c45, devnum, reg, val); 1291 + 1292 + /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */ 1293 + page = RTL822X_VND2_TO_PAGE(reg); 1294 + oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT); 1295 + if (oldpage < 0) 1296 + return oldpage; 1297 + 1298 + if (oldpage != page) { 1299 + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, page); 1300 + if (ret < 0) 1301 + return ret; 1302 + } 1303 + 1304 + write_ret = __phy_write(phydev, RTL822X_VND2_TO_PAGE_REG(reg), val); 1305 + if (oldpage != page) { 1306 + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, oldpage); 1307 + if (ret < 0) 1308 + return ret; 1309 + } 1310 + 1311 + return write_ret; 1312 + } 1313 + 1251 1314 static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1) 1252 1315 { 1253 1316 bool has_2500, has_sgmii; ··· 1389 1306 static int rtl822xb_config_init(struct phy_device *phydev) 1390 1307 { 1391 1308 return rtl822x_set_serdes_option_mode(phydev, false); 1309 + } 1310 + 1311 + static int rtl822x_serdes_write(struct phy_device *phydev, u16 reg, u16 val) 1312 + { 1313 + int ret, poll; 1314 + 1315 + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_ADDR, reg); 1316 + if (ret < 0) 1317 + return ret; 1318 + 1319 + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_DATA, val); 1320 + if (ret < 0) 1321 + return ret; 1322 + 1323 + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CMD, 1324 + RTL822X_VND1_SERDES_CMD_WRITE | 1325 + RTL822X_VND1_SERDES_CMD_BUSY); 1326 + if (ret < 0) 1327 + return ret; 1328 + 1329 + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 1330 + RTL822X_VND1_SERDES_CMD, poll, 1331 + !(poll & RTL822X_VND1_SERDES_CMD_BUSY), 1332 + 500, 100000, false); 1333 + } 1334 + 1335 + static int rtl822x_config_inband(struct phy_device *phydev, unsigned int modes) 1336 + { 1337 + return rtl822x_serdes_write(phydev, RTL822X_VND1_SERDES_ADDR_AUTONEG, 1338 + (modes != LINK_INBAND_DISABLE) ? 1339 + RTL822X_VND1_SERDES_INBAND_ENABLE : 1340 + RTL822X_VND1_SERDES_INBAND_DISABLE); 1341 + } 1342 + 1343 + static unsigned int rtl822x_inband_caps(struct phy_device *phydev, 1344 + phy_interface_t interface) 1345 + { 1346 + switch (interface) { 1347 + case PHY_INTERFACE_MODE_2500BASEX: 1348 + case PHY_INTERFACE_MODE_SGMII: 1349 + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; 1350 + default: 1351 + return 0; 1352 + } 1392 1353 } 1393 1354 1394 1355 static int rtl822xb_get_rate_matching(struct phy_device *phydev, ··· 2103 1976 static struct phy_driver realtek_drvs[] = { 2104 1977 { 2105 1978 PHY_ID_MATCH_EXACT(0x00008201), 2106 - .name = "RTL8201CP Ethernet", 1979 + .name = "RTL8201CP Ethernet", 2107 1980 .read_page = rtl821x_read_page, 2108 1981 .write_page = rtl821x_write_page, 2109 1982 }, { ··· 2224 2097 .resume = rtlgen_resume, 2225 2098 .read_page = rtl821x_read_page, 2226 2099 .write_page = rtl821x_write_page, 2100 + .read_mmd = rtl822xb_read_mmd, 2101 + .write_mmd = rtl822xb_write_mmd, 2227 2102 }, { 2228 2103 .match_phy_device = rtl8221b_match_phy_device, 2229 2104 .name = "RTL8226B_RTL8221B 2.5Gbps PHY", 2230 2105 .get_features = rtl822x_get_features, 2231 2106 .config_aneg = rtl822x_config_aneg, 2232 - .config_init = rtl822xb_config_init, 2107 + .config_init = rtl822xb_config_init, 2108 + .inband_caps = rtl822x_inband_caps, 2109 + .config_inband = rtl822x_config_inband, 2233 2110 .get_rate_matching = rtl822xb_get_rate_matching, 2234 2111 .read_status = rtl822xb_read_status, 2235 2112 .suspend = genphy_suspend, 2236 2113 .resume = rtlgen_resume, 2237 2114 .read_page = rtl821x_read_page, 2238 2115 .write_page = rtl821x_write_page, 2116 + .read_mmd = rtl822xb_read_mmd, 2117 + .write_mmd = rtl822xb_write_mmd, 2239 2118 }, { 2240 2119 PHY_ID_MATCH_EXACT(0x001cc838), 2241 - .name = "RTL8226-CG 2.5Gbps PHY", 2242 - .soft_reset = rtl822x_c45_soft_reset, 2243 - .get_features = rtl822x_c45_get_features, 2244 - .config_aneg = rtl822x_c45_config_aneg, 2245 - .config_init = rtl822x_config_init, 2246 - .read_status = rtl822xb_c45_read_status, 2247 - .suspend = genphy_c45_pma_suspend, 2248 - .resume = rtlgen_c45_resume, 2120 + .name = "RTL8226-CG 2.5Gbps PHY", 2121 + .soft_reset = rtl822x_c45_soft_reset, 2122 + .get_features = rtl822x_c45_get_features, 2123 + .config_aneg = rtl822x_c45_config_aneg, 2124 + .config_init = rtl822x_config_init, 2125 + .inband_caps = rtl822x_inband_caps, 2126 + .config_inband = rtl822x_config_inband, 2127 + .read_status = rtl822xb_c45_read_status, 2128 + .suspend = genphy_c45_pma_suspend, 2129 + .resume = rtlgen_c45_resume, 2130 + .read_mmd = rtl822xb_read_mmd, 2131 + .write_mmd = rtl822xb_write_mmd, 2249 2132 }, { 2250 2133 PHY_ID_MATCH_EXACT(0x001cc848), 2251 - .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", 2252 - .get_features = rtl822x_get_features, 2253 - .config_aneg = rtl822x_config_aneg, 2254 - .config_init = rtl822xb_config_init, 2134 + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", 2135 + .get_features = rtl822x_get_features, 2136 + .config_aneg = rtl822x_config_aneg, 2137 + .config_init = rtl822xb_config_init, 2138 + .inband_caps = rtl822x_inband_caps, 2139 + .config_inband = rtl822x_config_inband, 2255 2140 .get_rate_matching = rtl822xb_get_rate_matching, 2256 - .read_status = rtl822xb_read_status, 2257 - .suspend = genphy_suspend, 2258 - .resume = rtlgen_resume, 2259 - .read_page = rtl821x_read_page, 2260 - .write_page = rtl821x_write_page, 2141 + .read_status = rtl822xb_read_status, 2142 + .suspend = genphy_suspend, 2143 + .resume = rtlgen_resume, 2144 + .read_page = rtl821x_read_page, 2145 + .write_page = rtl821x_write_page, 2146 + .read_mmd = rtl822xb_read_mmd, 2147 + .write_mmd = rtl822xb_write_mmd, 2261 2148 }, { 2262 2149 .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, 2263 - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", 2150 + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", 2264 2151 .probe = rtl822x_probe, 2265 - .get_features = rtl822x_get_features, 2266 - .config_aneg = rtl822x_config_aneg, 2267 - .config_init = rtl822xb_config_init, 2152 + .get_features = rtl822x_get_features, 2153 + .config_aneg = rtl822x_config_aneg, 2154 + .config_init = rtl822xb_config_init, 2155 + .inband_caps = rtl822x_inband_caps, 2156 + .config_inband = rtl822x_config_inband, 2268 2157 .get_rate_matching = rtl822xb_get_rate_matching, 2269 - .read_status = rtl822xb_read_status, 2270 - .suspend = genphy_suspend, 2271 - .resume = rtlgen_resume, 2272 - .read_page = rtl821x_read_page, 2273 - .write_page = rtl821x_write_page, 2158 + .read_status = rtl822xb_read_status, 2159 + .suspend = genphy_suspend, 2160 + .resume = rtlgen_resume, 2161 + .read_page = rtl821x_read_page, 2162 + .write_page = rtl821x_write_page, 2163 + .read_mmd = rtl822xb_read_mmd, 2164 + .write_mmd = rtl822xb_write_mmd, 2274 2165 }, { 2275 2166 .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, 2276 - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", 2167 + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", 2277 2168 .config_intr = rtl8221b_config_intr, 2278 2169 .handle_interrupt = rtl8221b_handle_interrupt, 2279 2170 .probe = rtl822x_probe, 2280 - .config_init = rtl822xb_config_init, 2171 + .config_init = rtl822xb_config_init, 2172 + .inband_caps = rtl822x_inband_caps, 2173 + .config_inband = rtl822x_config_inband, 2281 2174 .get_rate_matching = rtl822xb_get_rate_matching, 2282 - .get_features = rtl822x_c45_get_features, 2283 - .config_aneg = rtl822x_c45_config_aneg, 2284 - .read_status = rtl822xb_c45_read_status, 2285 - .suspend = genphy_c45_pma_suspend, 2286 - .resume = rtlgen_c45_resume, 2175 + .get_features = rtl822x_c45_get_features, 2176 + .config_aneg = rtl822x_c45_config_aneg, 2177 + .read_status = rtl822xb_c45_read_status, 2178 + .suspend = genphy_c45_pma_suspend, 2179 + .resume = rtlgen_c45_resume, 2287 2180 }, { 2288 2181 .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, 2289 - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", 2182 + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", 2290 2183 .probe = rtl822x_probe, 2291 - .get_features = rtl822x_get_features, 2292 - .config_aneg = rtl822x_config_aneg, 2293 - .config_init = rtl822xb_config_init, 2184 + .get_features = rtl822x_get_features, 2185 + .config_aneg = rtl822x_config_aneg, 2186 + .config_init = rtl822xb_config_init, 2187 + .inband_caps = rtl822x_inband_caps, 2188 + .config_inband = rtl822x_config_inband, 2294 2189 .get_rate_matching = rtl822xb_get_rate_matching, 2295 - .read_status = rtl822xb_read_status, 2296 - .suspend = genphy_suspend, 2297 - .resume = rtlgen_resume, 2298 - .read_page = rtl821x_read_page, 2299 - .write_page = rtl821x_write_page, 2190 + .read_status = rtl822xb_read_status, 2191 + .suspend = genphy_suspend, 2192 + .resume = rtlgen_resume, 2193 + .read_page = rtl821x_read_page, 2194 + .write_page = rtl821x_write_page, 2195 + .read_mmd = rtl822xb_read_mmd, 2196 + .write_mmd = rtl822xb_write_mmd, 2300 2197 }, { 2301 2198 .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, 2302 - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", 2199 + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", 2303 2200 .config_intr = rtl8221b_config_intr, 2304 2201 .handle_interrupt = rtl8221b_handle_interrupt, 2305 2202 .probe = rtl822x_probe, 2306 - .config_init = rtl822xb_config_init, 2203 + .config_init = rtl822xb_config_init, 2204 + .inband_caps = rtl822x_inband_caps, 2205 + .config_inband = rtl822x_config_inband, 2307 2206 .get_rate_matching = rtl822xb_get_rate_matching, 2308 - .get_features = rtl822x_c45_get_features, 2309 - .config_aneg = rtl822x_c45_config_aneg, 2310 - .read_status = rtl822xb_c45_read_status, 2311 - .suspend = genphy_c45_pma_suspend, 2312 - .resume = rtlgen_c45_resume, 2207 + .get_features = rtl822x_c45_get_features, 2208 + .config_aneg = rtl822x_c45_config_aneg, 2209 + .read_status = rtl822xb_c45_read_status, 2210 + .suspend = genphy_c45_pma_suspend, 2211 + .resume = rtlgen_c45_resume, 2313 2212 }, { 2314 2213 .match_phy_device = rtl8251b_c45_match_phy_device, 2315 - .name = "RTL8251B 5Gbps PHY", 2214 + .name = "RTL8251B 5Gbps PHY", 2316 2215 .probe = rtl822x_probe, 2317 - .get_features = rtl822x_get_features, 2318 - .config_aneg = rtl822x_config_aneg, 2319 - .read_status = rtl822x_read_status, 2320 - .suspend = genphy_suspend, 2321 - .resume = rtlgen_resume, 2322 - .read_page = rtl821x_read_page, 2323 - .write_page = rtl821x_write_page, 2216 + .get_features = rtl822x_get_features, 2217 + .config_aneg = rtl822x_config_aneg, 2218 + .read_status = rtl822x_read_status, 2219 + .suspend = genphy_suspend, 2220 + .resume = rtlgen_resume, 2221 + .read_page = rtl821x_read_page, 2222 + .write_page = rtl821x_write_page, 2324 2223 }, { 2325 2224 .match_phy_device = rtl_internal_nbaset_match_phy_device, 2326 - .name = "Realtek Internal NBASE-T PHY", 2225 + .name = "Realtek Internal NBASE-T PHY", 2327 2226 .flags = PHY_IS_INTERNAL, 2328 2227 .probe = rtl822x_probe, 2329 - .get_features = rtl822x_get_features, 2330 - .config_aneg = rtl822x_config_aneg, 2331 - .read_status = rtl822x_read_status, 2332 - .suspend = genphy_suspend, 2333 - .resume = rtlgen_resume, 2334 - .read_page = rtl821x_read_page, 2335 - .write_page = rtl821x_write_page, 2228 + .get_features = rtl822x_get_features, 2229 + .config_aneg = rtl822x_config_aneg, 2230 + .read_status = rtl822x_read_status, 2231 + .suspend = genphy_suspend, 2232 + .resume = rtlgen_resume, 2233 + .read_page = rtl821x_read_page, 2234 + .write_page = rtl821x_write_page, 2336 2235 .read_mmd = rtl822x_read_mmd, 2337 2236 .write_mmd = rtl822x_write_mmd, 2338 2237 }, { 2339 2238 PHY_ID_MATCH_EXACT(0x001ccad0), 2340 2239 .name = "RTL8224 2.5Gbps PHY", 2341 2240 .flags = PHY_POLL_CABLE_TEST, 2342 - .get_features = rtl822x_c45_get_features, 2343 - .config_aneg = rtl822x_c45_config_aneg, 2344 - .read_status = rtl822x_c45_read_status, 2345 - .suspend = genphy_c45_pma_suspend, 2346 - .resume = rtlgen_c45_resume, 2241 + .get_features = rtl822x_c45_get_features, 2242 + .config_aneg = rtl822x_c45_config_aneg, 2243 + .read_status = rtl822x_c45_read_status, 2244 + .suspend = genphy_c45_pma_suspend, 2245 + .resume = rtlgen_c45_resume, 2347 2246 .cable_test_start = rtl8224_cable_test_start, 2348 2247 .cable_test_get_status = rtl8224_cable_test_get_status, 2349 2248 }, { ··· 2388 2235 }, { 2389 2236 PHY_ID_MATCH_EXACT(0x001ccb00), 2390 2237 .name = "RTL9000AA_RTL9000AN Ethernet", 2391 - .features = PHY_BASIC_T1_FEATURES, 2238 + .features = PHY_BASIC_T1_FEATURES, 2392 2239 .config_init = rtl9000a_config_init, 2393 2240 .config_aneg = rtl9000a_config_aneg, 2394 2241 .read_status = rtl9000a_read_status,