diff options
author | Raju Lakkaraju <Raju.Lakkaraju@microsemi.com> | 2016-09-19 15:33:54 +0530 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-09-20 04:39:23 -0400 |
commit | 1a21101d21d7ef056dfda1d7b843289e05ecd034 (patch) | |
tree | 3fd3f817a3622d9a7ac5af7d2dfb7e2f83f86df6 /drivers/net/phy | |
parent | 1a9234e66eddb0f18447532ab3f12bd136473ed6 (diff) | |
download | op-kernel-dev-1a21101d21d7ef056dfda1d7b843289e05ecd034.zip op-kernel-dev-1a21101d21d7ef056dfda1d7b843289e05ecd034.tar.gz |
net: phy: Add MAC-IF driver for Microsemi PHYs.
All the review comments updated and resending for review.
This is MAC interface feature.
Microsemi PHY can support RGMII, RMII or GMII/MII interface between MAC and PHY.
MAC-IF function program the right value based on Device tree configuration.
Tested on Beaglebone Black with VSC 8531 PHY.
Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/mscc.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index c09cc4a..d350debd 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -23,6 +23,16 @@ enum rgmii_rx_clock_delay { RGMII_RX_CLK_DELAY_3_4_NS = 7 }; +/* Microsemi VSC85xx PHY registers */ +/* IEEE 802. Std Registers */ +#define MSCC_PHY_EXT_PHY_CNTL_1 23 +#define MAC_IF_SELECTION_MASK 0x1800 +#define MAC_IF_SELECTION_GMII 0 +#define MAC_IF_SELECTION_RMII 1 +#define MAC_IF_SELECTION_RGMII 2 +#define MAC_IF_SELECTION_POS 11 +#define FAR_END_LOOPBACK_MODE_MASK 0x0008 + #define MII_VSC85XX_INT_MASK 25 #define MII_VSC85XX_INT_MASK_MASK 0xa000 #define MII_VSC85XX_INT_STATUS 26 @@ -48,6 +58,42 @@ static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page) return rc; } +static int vsc85xx_mac_if_set(struct phy_device *phydev, + phy_interface_t interface) +{ + int rc; + u16 reg_val; + + mutex_lock(&phydev->lock); + reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1); + reg_val &= ~(MAC_IF_SELECTION_MASK); + switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS); + break; + case PHY_INTERFACE_MODE_RMII: + reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS); + break; + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: + reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS); + break; + default: + rc = -EINVAL; + goto out_unlock; + } + rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val); + if (rc != 0) + goto out_unlock; + + rc = genphy_soft_reset(phydev); + +out_unlock: + mutex_unlock(&phydev->lock); + + return rc; +} + static int vsc85xx_default_config(struct phy_device *phydev) { int rc; @@ -77,6 +123,11 @@ static int vsc85xx_config_init(struct phy_device *phydev) rc = vsc85xx_default_config(phydev); if (rc) return rc; + + rc = vsc85xx_mac_if_set(phydev, phydev->interface); + if (rc) + return rc; + rc = genphy_config_init(phydev); return rc; |