diff options
author | Mark Mentovai <mark@moxienet.com> | 2021-05-08 11:00:55 -0400 |
---|---|---|
committer | Petr Štetiar <ynezz@true.cz> | 2021-05-08 18:45:42 +0200 |
commit | d62825dd77b3990b8ff2cf341ff3a8b16f4883d1 (patch) | |
tree | 16c9214756637f0692547e5c9182316c403794ec | |
parent | f68c9474acf9a65b5a9538db8e45c173462487e3 (diff) | |
download | upstream-d62825dd77b3990b8ff2cf341ff3a8b16f4883d1.tar.gz upstream-d62825dd77b3990b8ff2cf341ff3a8b16f4883d1.tar.bz2 upstream-d62825dd77b3990b8ff2cf341ff3a8b16f4883d1.zip |
ipq806x: dwmac: fix GMACs connected via SGMII fixed-link
fa731838c524 cleared the forced speed in the QSGMII PCS_ALL_CH_CTL
register during probe, but this is only correct for GMACs that are not
configured with fixed-link. This prevented GMACs configured with both
phy-mode = "sgmii" and fixed-link from working properly, as discussed at
https://github.com/openwrt/openwrt/pull/3954#issuecomment-834625090 and
the comments that follow. Notably, this prevented all communication
between gmac2 and the switch on the Netgear R7800.
The correct behavior is to set the QSGMII PCS_ALL_CH_CTL register by
considering the gmac's fixed-link child, setting the speed as directed by
fixed-link if present, and otherwise clearing it as was done previously.
Fixes: fa731838c524 ("ipq806x: dwmac: clear forced speed during probe")
Signed-off-by: Mark Mentovai <mark@moxienet.com>
Tested-by: Hannu Nyman <hannu.nyman@iki.fi>
Run-tested: ipq806x/ubnt,unifi-ac-hd, ipq806x/netgear,r7800
Cc: Petr Štetiar <ynezz@true.cz>
Cc: Ansuel Smith <ansuelsmth@gmail.com>
Tested-by: Ansuel Smith <ansuelsmth@gmail.com>
-rw-r--r-- | target/linux/ipq806x/patches-5.4/100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/target/linux/ipq806x/patches-5.4/100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch b/target/linux/ipq806x/patches-5.4/100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch index 6cdbf4d3dc..3c497ead6a 100644 --- a/target/linux/ipq806x/patches-5.4/100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch +++ b/target/linux/ipq806x/patches-5.4/100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch @@ -18,16 +18,66 @@ #define QSGMII_PCS_CAL_LCKDT_CTL 0x120 #define QSGMII_PCS_CAL_LCKDT_CTL_RST BIT(19) -@@ -345,6 +356,12 @@ static int ipq806x_gmac_probe(struct pla +@@ -241,6 +252,36 @@ static void ipq806x_gmac_fix_mac_speed(v + ipq806x_gmac_set_speed(gmac, speed); + } + ++static int ++ipq806x_gmac_get_qsgmii_pcs_speed_val(struct platform_device *pdev) { ++ struct device_node *fixed_link_node; ++ int rv; ++ int fixed_link_speed; ++ ++ if (!of_phy_is_fixed_link(pdev->dev.of_node)) ++ return 0; ++ ++ fixed_link_node = of_get_child_by_name(pdev->dev.of_node, "fixed-link"); ++ if (!fixed_link_node) ++ return -1; ++ ++ rv = of_property_read_u32(fixed_link_node, "speed", &fixed_link_speed); ++ of_node_put(fixed_link_node); ++ if (rv) ++ return -1; ++ ++ switch (fixed_link_speed) { ++ case SPEED_1000: ++ return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_1000; ++ case SPEED_100: ++ return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_100; ++ case SPEED_10: ++ return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_10; ++ } ++ ++ return -1; ++} ++ + static int ipq806x_gmac_probe(struct platform_device *pdev) + { + struct plat_stmmacenet_data *plat_dat; +@@ -249,6 +290,7 @@ static int ipq806x_gmac_probe(struct pla + struct ipq806x_gmac *gmac; + int val; + int err; ++ int qsgmii_pcs_speed; + + val = stmmac_get_platform_resources(pdev, &stmmac_res); + if (val) +@@ -345,6 +387,17 @@ static int ipq806x_gmac_probe(struct pla 0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET | 0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET | 0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET); + -+ regmap_update_bits(gmac->qsgmii_csr, -+ QSGMII_PCS_ALL_CH_CTL, -+ QSGMII_PCS_CH_SPEED_MASK << -+ QSGMII_PCS_CH_SPEED_SHIFT(gmac->id), -+ 0); ++ qsgmii_pcs_speed = ipq806x_gmac_get_qsgmii_pcs_speed_val(pdev); ++ if (qsgmii_pcs_speed != -1) { ++ regmap_update_bits( ++ gmac->qsgmii_csr, ++ QSGMII_PCS_ALL_CH_CTL, ++ QSGMII_PCS_CH_SPEED_MASK << ++ QSGMII_PCS_CH_SPEED_SHIFT(gmac->id), ++ qsgmii_pcs_speed << ++ QSGMII_PCS_CH_SPEED_SHIFT(gmac->id)); ++ } } plat_dat->has_gmac = true; |