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

net: ethernet: stmmac: reset force speed bit for ipq806x

Some bootloader may set the force speed regs even if the actual
interface should use autonegotiation between PCS and PHY.
This cause the complete malfuction of the interface.

To fix this correctly reset the force speed regs if a fixed-link is not
defined in the DTS. With a fixed-link node correctly configure the
forced speed regs to handle any misconfiguration by the bootloader.

Reported-by: Mark Mentovai <mark@moxienet.com>
Co-developed-by: Mark Mentovai <mark@moxienet.com>
Signed-off-by: Mark Mentovai <mark@moxienet.com>
Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20220614112228.1998-2-ansuelsmth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Christian 'Ansuel' Marangi and committed by
Paolo Abeni
8bca4589 9ec092d2

+64
+64
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
··· 66 66 #define NSS_COMMON_CLK_DIV_SGMII_100 4 67 67 #define NSS_COMMON_CLK_DIV_SGMII_10 49 68 68 69 + #define QSGMII_PCS_ALL_CH_CTL 0x80 70 + #define QSGMII_PCS_CH_SPEED_FORCE BIT(1) 71 + #define QSGMII_PCS_CH_SPEED_10 0x0 72 + #define QSGMII_PCS_CH_SPEED_100 BIT(2) 73 + #define QSGMII_PCS_CH_SPEED_1000 BIT(3) 74 + #define QSGMII_PCS_CH_SPEED_MASK (QSGMII_PCS_CH_SPEED_FORCE | \ 75 + QSGMII_PCS_CH_SPEED_10 | \ 76 + QSGMII_PCS_CH_SPEED_100 | \ 77 + QSGMII_PCS_CH_SPEED_1000) 78 + #define QSGMII_PCS_CH_SPEED_SHIFT(x) ((x) * 4) 79 + 69 80 #define QSGMII_PCS_CAL_LCKDT_CTL 0x120 70 81 #define QSGMII_PCS_CAL_LCKDT_CTL_RST BIT(19) 71 82 ··· 264 253 ipq806x_gmac_set_speed(gmac, speed); 265 254 } 266 255 256 + static int 257 + ipq806x_gmac_configure_qsgmii_pcs_speed(struct ipq806x_gmac *gmac) 258 + { 259 + struct platform_device *pdev = gmac->pdev; 260 + struct device *dev = &pdev->dev; 261 + struct device_node *dn; 262 + int link_speed; 263 + int val = 0; 264 + int ret; 265 + 266 + /* Some bootloader may apply wrong configuration and cause 267 + * not functioning port. If fixed link is not set, 268 + * reset the force speed bit. 269 + */ 270 + if (!of_phy_is_fixed_link(pdev->dev.of_node)) 271 + goto write; 272 + 273 + dn = of_get_child_by_name(pdev->dev.of_node, "fixed-link"); 274 + ret = of_property_read_u32(dn, "speed", &link_speed); 275 + of_node_put(dn); 276 + if (ret) { 277 + dev_err(dev, "found fixed-link node with no speed"); 278 + return ret; 279 + } 280 + 281 + val = QSGMII_PCS_CH_SPEED_FORCE; 282 + 283 + switch (link_speed) { 284 + case SPEED_1000: 285 + val |= QSGMII_PCS_CH_SPEED_1000; 286 + break; 287 + case SPEED_100: 288 + val |= QSGMII_PCS_CH_SPEED_100; 289 + break; 290 + case SPEED_10: 291 + val |= QSGMII_PCS_CH_SPEED_10; 292 + break; 293 + } 294 + 295 + write: 296 + regmap_update_bits(gmac->qsgmii_csr, QSGMII_PCS_ALL_CH_CTL, 297 + QSGMII_PCS_CH_SPEED_MASK << 298 + QSGMII_PCS_CH_SPEED_SHIFT(gmac->id), 299 + val << 300 + QSGMII_PCS_CH_SPEED_SHIFT(gmac->id)); 301 + 302 + return 0; 303 + } 304 + 267 305 static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = { 268 306 { 269 307 .revision = "1.*", ··· 458 398 459 399 if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) { 460 400 err = ipq806x_gmac_configure_qsgmii_params(gmac); 401 + if (err) 402 + goto err_remove_config_dt; 403 + 404 + err = ipq806x_gmac_configure_qsgmii_pcs_speed(gmac); 461 405 if (err) 462 406 goto err_remove_config_dt; 463 407 }