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:
		 Mark Mentovai
					Mark Mentovai
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						Petr Štetiar
					
				
			
						parent
						
							f68c9474ac
						
					
				
				
					commit
					d62825dd77
				
			| @@ -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_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), | ||||
| +				   0); | ||||
| +			    qsgmii_pcs_speed << | ||||
| +				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id)); | ||||
| +		} | ||||
|  	} | ||||
|   | ||||
|  	plat_dat->has_gmac = true; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user