ipq806x: dwmac: fix GMACs connected via SGMII fixed-link
fa731838c5cleared 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:fa731838c5("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>
This commit is contained in:
		
				
					committed by
					
						
						Petr Štetiar
					
				
			
			
				
	
			
			
			
						parent
						
							f68c9474ac
						
					
				
				
					commit
					d62825dd77
				
			@@ -18,16 +18,66 @@
 | 
				
			|||||||
 #define QSGMII_PCS_CAL_LCKDT_CTL		0x120
 | 
					 #define QSGMII_PCS_CAL_LCKDT_CTL		0x120
 | 
				
			||||||
 #define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
 | 
					 #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 |
 | 
					 			     0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
 | 
				
			||||||
 			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
 | 
					 			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
 | 
				
			||||||
 			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
 | 
					 			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+		regmap_update_bits(gmac->qsgmii_csr,
 | 
					+		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_ALL_CH_CTL,
 | 
				
			||||||
+			    QSGMII_PCS_CH_SPEED_MASK <<
 | 
					+			    QSGMII_PCS_CH_SPEED_MASK <<
 | 
				
			||||||
+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
 | 
					+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
 | 
				
			||||||
+				   0);
 | 
					+			    qsgmii_pcs_speed <<
 | 
				
			||||||
 | 
					+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id));
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 	}
 | 
					 	}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 	plat_dat->has_gmac = true;
 | 
					 	plat_dat->has_gmac = true;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user