Signed-off-by: John Haechten <john.haechten@microsemi.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>master
parent
af2cbfd6b9
commit
a5fd13ad19
@ -0,0 +1,508 @@ |
||||
/*
|
||||
* Microsemi PHY drivers |
||||
* |
||||
* SPDX-License-Identifier: The MIT License (MIT) |
||||
* |
||||
* Copyright (c) 2016 Microsemi Corporation |
||||
* |
||||
* Author: John Haechten |
||||
* |
||||
*/ |
||||
|
||||
#include <miiphy.h> |
||||
#include <bitfield.h> |
||||
|
||||
/* Microsemi PHY ID's */ |
||||
#define PHY_ID_VSC8530 0x00070560 |
||||
#define PHY_ID_VSC8531 0x00070570 |
||||
#define PHY_ID_VSC8540 0x00070760 |
||||
#define PHY_ID_VSC8541 0x00070770 |
||||
|
||||
/* Microsemi VSC85xx PHY Register Pages */ |
||||
#define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */ |
||||
#define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */ |
||||
#define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */ |
||||
#define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */ |
||||
#define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */ |
||||
#define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */ |
||||
#define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */ |
||||
#define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */ |
||||
#define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */ |
||||
|
||||
/* Std Page Register 28 - PHY AUX Control/Status */ |
||||
#define MIIM_AUX_CNTRL_STAT_REG 28 |
||||
#define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004) |
||||
#define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020) |
||||
#define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018) |
||||
#define MIIM_AUX_CNTRL_STAT_SPEED_POS (3) |
||||
#define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0) |
||||
#define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1) |
||||
#define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2) |
||||
|
||||
/* Std Page Register 23 - Extended PHY CTRL_1 */ |
||||
#define MSCC_PHY_EXT_PHY_CNTL_1_REG 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 MAC_IF_SELECTION_WIDTH (2) |
||||
|
||||
/* Extended Page 2 Register 20E2 */ |
||||
#define MSCC_PHY_RGMII_CNTL_REG 20 |
||||
#define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000) |
||||
#define RX_CLK_OUT_MASK (0x0800) |
||||
#define RX_CLK_OUT_POS (11) |
||||
#define RX_CLK_OUT_WIDTH (1) |
||||
#define RX_CLK_OUT_NORMAL (0) |
||||
#define RX_CLK_OUT_DISABLE (1) |
||||
#define RGMII_RX_CLK_DELAY_POS (4) |
||||
#define RGMII_RX_CLK_DELAY_WIDTH (3) |
||||
#define RGMII_RX_CLK_DELAY_MASK (0x0070) |
||||
#define RGMII_TX_CLK_DELAY_POS (0) |
||||
#define RGMII_TX_CLK_DELAY_WIDTH (3) |
||||
#define RGMII_TX_CLK_DELAY_MASK (0x0007) |
||||
|
||||
/* Extended Page 2 Register 27E2 */ |
||||
#define MSCC_PHY_WOL_MAC_CONTROL 27 |
||||
#define EDGE_RATE_CNTL_POS (5) |
||||
#define EDGE_RATE_CNTL_WIDTH (3) |
||||
#define EDGE_RATE_CNTL_MASK (0x00E0) |
||||
#define RMII_CLK_OUT_ENABLE_POS (4) |
||||
#define RMII_CLK_OUT_ENABLE_WIDTH (1) |
||||
#define RMII_CLK_OUT_ENABLE_MASK (0x10) |
||||
|
||||
/* Token Ring Page 0x52B5 Registers */ |
||||
#define MSCC_PHY_REG_TR_ADDR_16 16 |
||||
#define MSCC_PHY_REG_TR_DATA_17 17 |
||||
#define MSCC_PHY_REG_TR_DATA_18 18 |
||||
|
||||
/* Token Ring - Read Value in */ |
||||
#define MSCC_PHY_TR_16_READ (0xA000) |
||||
/* Token Ring - Write Value out */ |
||||
#define MSCC_PHY_TR_16_WRITE (0x8000) |
||||
|
||||
/* Token Ring Registers */ |
||||
#define MSCC_PHY_TR_LINKDETCTRL_POS (3) |
||||
#define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2) |
||||
#define MSCC_PHY_TR_LINKDETCTRL_VAL (3) |
||||
#define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018) |
||||
#define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8) |
||||
|
||||
#define MSCC_PHY_TR_VGATHRESH100_POS (0) |
||||
#define MSCC_PHY_TR_VGATHRESH100_WIDTH (7) |
||||
#define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018) |
||||
#define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f) |
||||
#define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4) |
||||
|
||||
#define MSCC_PHY_TR_VGAGAIN10_U_POS (0) |
||||
#define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1) |
||||
#define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001) |
||||
#define MSCC_PHY_TR_VGAGAIN10_U_VAL (0) |
||||
|
||||
#define MSCC_PHY_TR_VGAGAIN10_L_POS (12) |
||||
#define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4) |
||||
#define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000) |
||||
#define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001) |
||||
#define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92) |
||||
|
||||
/* General Timeout Values */ |
||||
#define MSCC_PHY_RESET_TIMEOUT (100) |
||||
#define MSCC_PHY_MICRO_TIMEOUT (500) |
||||
|
||||
/* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew { |
||||
VSC_PHY_RGMII_DELAY_200_PS, |
||||
VSC_PHY_RGMII_DELAY_800_PS, |
||||
VSC_PHY_RGMII_DELAY_1100_PS, |
||||
VSC_PHY_RGMII_DELAY_1700_PS, |
||||
VSC_PHY_RGMII_DELAY_2000_PS, |
||||
VSC_PHY_RGMII_DELAY_2300_PS, |
||||
VSC_PHY_RGMII_DELAY_2600_PS, |
||||
VSC_PHY_RGMII_DELAY_3400_PS, |
||||
}; |
||||
|
||||
/* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum |
||||
vsc_phy_clk_slew { |
||||
VSC_PHY_CLK_SLEW_RATE_0, |
||||
VSC_PHY_CLK_SLEW_RATE_1, |
||||
VSC_PHY_CLK_SLEW_RATE_2, |
||||
VSC_PHY_CLK_SLEW_RATE_3, |
||||
VSC_PHY_CLK_SLEW_RATE_4, |
||||
VSC_PHY_CLK_SLEW_RATE_5, |
||||
VSC_PHY_CLK_SLEW_RATE_6, |
||||
VSC_PHY_CLK_SLEW_RATE_7, |
||||
}; |
||||
|
||||
|
||||
static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev) |
||||
{ |
||||
u16 reg_val; |
||||
|
||||
/* Set to Access Token Ring Registers */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR); |
||||
|
||||
/* Update LinkDetectCtrl default to optimized values */ |
||||
/* Determined during Silicon Validation Testing */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ)); |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); |
||||
reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS, |
||||
MSCC_PHY_TR_LINKDETCTRL_WIDTH, |
||||
MSCC_PHY_TR_LINKDETCTRL_VAL); |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE)); |
||||
|
||||
/* Update VgaThresh100 defaults to optimized values */ |
||||
/* Determined during Silicon Validation Testing */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ)); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); |
||||
reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS, |
||||
MSCC_PHY_TR_VGATHRESH100_WIDTH, |
||||
MSCC_PHY_TR_VGATHRESH100_VAL); |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE)); |
||||
|
||||
/* Update VgaGain10 defaults to optimized values */ |
||||
/* Determined during Silicon Validation Testing */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ)); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); |
||||
reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS, |
||||
MSCC_PHY_TR_VGAGAIN10_U_WIDTH, |
||||
MSCC_PHY_TR_VGAGAIN10_U_VAL); |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); |
||||
reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS, |
||||
MSCC_PHY_TR_VGAGAIN10_L_WIDTH, |
||||
MSCC_PHY_TR_VGAGAIN10_L_VAL); |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, |
||||
(MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE)); |
||||
|
||||
/* Set back to Access Standard Page Registers */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int mscc_parse_status(struct phy_device *phydev) |
||||
{ |
||||
u16 speed; |
||||
u16 mii_reg; |
||||
|
||||
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG); |
||||
|
||||
if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX) |
||||
phydev->duplex = DUPLEX_FULL; |
||||
else |
||||
phydev->duplex = DUPLEX_HALF; |
||||
|
||||
speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK; |
||||
speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS; |
||||
|
||||
switch (speed) { |
||||
case MIIM_AUX_CNTRL_STAT_SPEED_1000M: |
||||
phydev->speed = SPEED_1000; |
||||
break; |
||||
case MIIM_AUX_CNTRL_STAT_SPEED_100M: |
||||
phydev->speed = SPEED_100; |
||||
break; |
||||
case MIIM_AUX_CNTRL_STAT_SPEED_10M: |
||||
phydev->speed = SPEED_10; |
||||
break; |
||||
default: |
||||
phydev->speed = SPEED_10; |
||||
break; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int mscc_startup(struct phy_device *phydev) |
||||
{ |
||||
int retval; |
||||
|
||||
retval = genphy_update_link(phydev); |
||||
|
||||
if (retval) |
||||
return retval; |
||||
|
||||
return mscc_parse_status(phydev); |
||||
} |
||||
|
||||
static int mscc_phy_soft_reset(struct phy_device *phydev) |
||||
{ |
||||
int retval = 0; |
||||
u16 timeout = MSCC_PHY_RESET_TIMEOUT; |
||||
u16 reg_val = 0; |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET)); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
||||
|
||||
while ((reg_val & BMCR_RESET) && (timeout > 0)) { |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
||||
timeout--; |
||||
udelay(1000); /* 1 ms */ |
||||
} |
||||
|
||||
if (timeout == 0) { |
||||
printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n", |
||||
phydev->interface); |
||||
retval = -ETIME; |
||||
} |
||||
|
||||
return retval; |
||||
} |
||||
|
||||
static int vsc8531_vsc8541_mac_config(struct phy_device *phydev) |
||||
{ |
||||
u16 reg_val = 0; |
||||
u16 mac_if = 0; |
||||
u16 rx_clk_out = 0; |
||||
|
||||
/* For VSC8530/31 the only MAC modes are RMII/RGMII. */ |
||||
/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ |
||||
/* Setup MAC Configuration */ |
||||
switch (phydev->interface) { |
||||
case PHY_INTERFACE_MODE_MII: |
||||
case PHY_INTERFACE_MODE_GMII: |
||||
/* Set Reg23.12:11=0 */ |
||||
mac_if = MAC_IF_SELECTION_GMII; |
||||
/* Set Reg20E2.11=1 */ |
||||
rx_clk_out = RX_CLK_OUT_DISABLE; |
||||
break; |
||||
|
||||
case PHY_INTERFACE_MODE_RMII: |
||||
/* Set Reg23.12:11=1 */ |
||||
mac_if = MAC_IF_SELECTION_RMII; |
||||
/* Set Reg20E2.11=0 */ |
||||
rx_clk_out = RX_CLK_OUT_NORMAL; |
||||
break; |
||||
|
||||
case PHY_INTERFACE_MODE_RGMII: |
||||
/* Set Reg23.12:11=2 */ |
||||
mac_if = MAC_IF_SELECTION_RGMII; |
||||
/* Set Reg20E2.11=0 */ |
||||
rx_clk_out = RX_CLK_OUT_NORMAL; |
||||
break; |
||||
|
||||
default: |
||||
printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n", |
||||
phydev->interface); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_PHY_EXT_PHY_CNTL_1_REG); |
||||
/* Set MAC i/f bits Reg23.12:11 */ |
||||
reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS, |
||||
MAC_IF_SELECTION_WIDTH, mac_if); |
||||
/* Update Reg23.12:11 */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val); |
||||
/* Setup ExtPg_2 Register Access */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2); |
||||
/* Read Reg20E2 */ |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_PHY_RGMII_CNTL_REG); |
||||
reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS, |
||||
RX_CLK_OUT_WIDTH, rx_clk_out); |
||||
/* Update Reg20E2.11 */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, |
||||
MSCC_PHY_RGMII_CNTL_REG, reg_val); |
||||
/* Before leaving - Change back to Std Page Register Access */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int vsc8531_config(struct phy_device *phydev) |
||||
{ |
||||
int retval = -EINVAL; |
||||
u16 reg_val; |
||||
u16 rmii_clk_out; |
||||
enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; |
||||
enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; |
||||
enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; |
||||
|
||||
/* For VSC8530/31 and VSC8540/41 the init scripts are the same */ |
||||
mscc_vsc8531_vsc8541_init_scripts(phydev); |
||||
|
||||
/* For VSC8530/31 the only MAC modes are RMII/RGMII. */ |
||||
switch (phydev->interface) { |
||||
case PHY_INTERFACE_MODE_RMII: |
||||
case PHY_INTERFACE_MODE_RGMII: |
||||
retval = vsc8531_vsc8541_mac_config(phydev); |
||||
if (retval != 0) |
||||
return retval; |
||||
|
||||
retval = mscc_phy_soft_reset(phydev); |
||||
if (retval != 0) |
||||
return retval; |
||||
break; |
||||
default: |
||||
printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n", |
||||
phydev->interface); |
||||
return -EINVAL; |
||||
} |
||||
/* Default RMII Clk Output to 0=OFF/1=ON */ |
||||
rmii_clk_out = 0; |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_EXT2); |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); |
||||
|
||||
/* Reg20E2 - Update RGMII RX_Clk Skews. */ |
||||
reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, |
||||
RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); |
||||
/* Reg20E2 - Update RGMII TX_Clk Skews. */ |
||||
reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, |
||||
RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); |
||||
/* Reg27E2 - Update Clk Slew Rate. */ |
||||
reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, |
||||
EDGE_RATE_CNTL_WIDTH, edge_rate); |
||||
/* Reg27E2 - Update RMII Clk Out. */ |
||||
reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, |
||||
RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); |
||||
/* Update Reg27E2 */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
return genphy_config_aneg(phydev); |
||||
} |
||||
|
||||
static int vsc8541_config(struct phy_device *phydev) |
||||
{ |
||||
int retval = -EINVAL; |
||||
u16 reg_val; |
||||
u16 rmii_clk_out; |
||||
enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; |
||||
enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; |
||||
enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; |
||||
|
||||
/* For VSC8530/31 and VSC8540/41 the init scripts are the same */ |
||||
mscc_vsc8531_vsc8541_init_scripts(phydev); |
||||
|
||||
/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ |
||||
switch (phydev->interface) { |
||||
case PHY_INTERFACE_MODE_MII: |
||||
case PHY_INTERFACE_MODE_GMII: |
||||
case PHY_INTERFACE_MODE_RMII: |
||||
case PHY_INTERFACE_MODE_RGMII: |
||||
retval = vsc8531_vsc8541_mac_config(phydev); |
||||
if (retval != 0) |
||||
return retval; |
||||
|
||||
retval = mscc_phy_soft_reset(phydev); |
||||
if (retval != 0) |
||||
return retval; |
||||
break; |
||||
default: |
||||
printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n", |
||||
phydev->interface); |
||||
return -EINVAL; |
||||
} |
||||
/* Default RMII Clk Output to 0=OFF/1=ON */ |
||||
rmii_clk_out = 0; |
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_EXT2); |
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); |
||||
/* Reg20E2 - Update RGMII RX_Clk Skews. */ |
||||
reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, |
||||
RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); |
||||
/* Reg20E2 - Update RGMII TX_Clk Skews. */ |
||||
reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, |
||||
RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); |
||||
|
||||
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); |
||||
/* Reg27E2 - Update Clk Slew Rate. */ |
||||
reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, |
||||
EDGE_RATE_CNTL_WIDTH, edge_rate); |
||||
/* Reg27E2 - Update RMII Clk Out. */ |
||||
reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, |
||||
RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); |
||||
/* Update Reg27E2 */ |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, |
||||
MSCC_PHY_PAGE_STD); |
||||
|
||||
return genphy_config_aneg(phydev); |
||||
} |
||||
|
||||
static struct phy_driver VSC8530_driver = { |
||||
.name = "Microsemi VSC8530", |
||||
.uid = PHY_ID_VSC8530, |
||||
.mask = 0x000ffff0, |
||||
.features = PHY_BASIC_FEATURES, |
||||
.config = &vsc8531_config, |
||||
.startup = &mscc_startup, |
||||
.shutdown = &genphy_shutdown, |
||||
}; |
||||
|
||||
static struct phy_driver VSC8531_driver = { |
||||
.name = "Microsemi VSC8531", |
||||
.uid = PHY_ID_VSC8531, |
||||
.mask = 0x000ffff0, |
||||
.features = PHY_GBIT_FEATURES, |
||||
.config = &vsc8531_config, |
||||
.startup = &mscc_startup, |
||||
.shutdown = &genphy_shutdown, |
||||
}; |
||||
|
||||
static struct phy_driver VSC8540_driver = { |
||||
.name = "Microsemi VSC8540", |
||||
.uid = PHY_ID_VSC8540, |
||||
.mask = 0x000ffff0, |
||||
.features = PHY_BASIC_FEATURES, |
||||
.config = &vsc8541_config, |
||||
.startup = &mscc_startup, |
||||
.shutdown = &genphy_shutdown, |
||||
}; |
||||
|
||||
static struct phy_driver VSC8541_driver = { |
||||
.name = "Microsemi VSC8541", |
||||
.uid = PHY_ID_VSC8541, |
||||
.mask = 0x000ffff0, |
||||
.features = PHY_GBIT_FEATURES, |
||||
.config = &vsc8541_config, |
||||
.startup = &mscc_startup, |
||||
.shutdown = &genphy_shutdown, |
||||
}; |
||||
|
||||
int phy_mscc_init(void) |
||||
{ |
||||
phy_register(&VSC8530_driver); |
||||
phy_register(&VSC8531_driver); |
||||
phy_register(&VSC8540_driver); |
||||
phy_register(&VSC8541_driver); |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue