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		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); | ||||||
| +				   QSGMII_PCS_ALL_CH_CTL, | +		if (qsgmii_pcs_speed != -1) { | ||||||
| +				   QSGMII_PCS_CH_SPEED_MASK << | +			regmap_update_bits( | ||||||
| +				    QSGMII_PCS_CH_SPEED_SHIFT(gmac->id), | +			    gmac->qsgmii_csr, | ||||||
| +				   0); | +			    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; |  	plat_dat->has_gmac = true; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user