forked from mirrors/linux
		
	net: phy: at803x: disable delay only for RGMII mode
Per "Documentation/devicetree/bindings/net/ethernet.txt" RGMII mode
should not have delay in PHY whereas RGMII_ID and RGMII_RXID/RGMII_TXID
can have delay in PHY.
So disable the delay only for RGMII mode and enable for other modes.
Also treat the default case as disabled delays.
Fixes: cd28d1d6e5: ("net: phy: at803x: Disable phy delay for RGMII mode")
Reported-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Reviewed-by: Niklas Cassel <niklas.cassel@linaro.org>
Tested-by: Peter Ujfalusi <peter.ujflausi@ti.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									43f2ebd557
								
							
						
					
					
						commit
						6d4cd041f0
					
				
					 1 changed files with 42 additions and 11 deletions
				
			
		|  | @ -103,6 +103,18 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, | |||
| 	return phy_write(phydev, AT803X_DEBUG_DATA, val); | ||||
| } | ||||
| 
 | ||||
| static int at803x_enable_rx_delay(struct phy_device *phydev) | ||||
| { | ||||
| 	return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, | ||||
| 				     AT803X_DEBUG_RX_CLK_DLY_EN); | ||||
| } | ||||
| 
 | ||||
| static int at803x_enable_tx_delay(struct phy_device *phydev) | ||||
| { | ||||
| 	return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, | ||||
| 				     AT803X_DEBUG_TX_CLK_DLY_EN); | ||||
| } | ||||
| 
 | ||||
| static int at803x_disable_rx_delay(struct phy_device *phydev) | ||||
| { | ||||
| 	return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, | ||||
|  | @ -241,23 +253,42 @@ static int at803x_config_init(struct phy_device *phydev) | |||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || | ||||
| 			phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || | ||||
| 			phydev->interface == PHY_INTERFACE_MODE_RGMII) { | ||||
| 		ret = at803x_disable_rx_delay(phydev); | ||||
| 	/* The RX and TX delay default is:
 | ||||
| 	 *   after HW reset: RX delay enabled and TX delay disabled | ||||
| 	 *   after SW reset: RX delay enabled, while TX delay retains the | ||||
| 	 *   value before reset. | ||||
| 	 * | ||||
| 	 * So let's first disable the RX and TX delays in PHY and enable | ||||
| 	 * them based on the mode selected (this also takes care of RGMII | ||||
| 	 * mode where we expect delays to be disabled) | ||||
| 	 */ | ||||
| 
 | ||||
| 	ret = at803x_disable_rx_delay(phydev); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	ret = at803x_disable_tx_delay(phydev); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || | ||||
| 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { | ||||
| 		/* If RGMII_ID or RGMII_RXID are specified enable RX delay,
 | ||||
| 		 * otherwise keep it disabled | ||||
| 		 */ | ||||
| 		ret = at803x_enable_rx_delay(phydev); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || | ||||
| 			phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || | ||||
| 			phydev->interface == PHY_INTERFACE_MODE_RGMII) { | ||||
| 		ret = at803x_disable_tx_delay(phydev); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || | ||||
| 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { | ||||
| 		/* If RGMII_ID or RGMII_TXID are specified enable TX delay,
 | ||||
| 		 * otherwise keep it disabled | ||||
| 		 */ | ||||
| 		ret = at803x_enable_tx_delay(phydev); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int at803x_ack_interrupt(struct phy_device *phydev) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Vinod Koul
						Vinod Koul