diff options
author | Tom Rini | 2017-02-09 11:56:35 -0500 |
---|---|---|
committer | Tom Rini | 2017-02-09 11:56:35 -0500 |
commit | e1a71f8b339220fa74c9cd5d36ae9c444c492e83 (patch) | |
tree | 5eca7ff69f390f4c2f2df3459d3e2db3d91b7af9 /drivers/net/phy | |
parent | 6f57b19857b514f6e94e423c9bbe2d4b8973a0db (diff) | |
parent | a5fd13ad1913d9c66c47666dbedac7703a48e502 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-net
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/Kconfig | 93 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/marvell.c | 63 | ||||
-rw-r--r-- | drivers/net/phy/mscc.c | 508 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 3 | ||||
-rw-r--r-- | drivers/net/phy/ti.c | 34 | ||||
-rw-r--r-- | drivers/net/phy/vitesse.c | 4 |
7 files changed, 683 insertions, 23 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig new file mode 100644 index 00000000000..1d514e92d3b --- /dev/null +++ b/drivers/net/phy/Kconfig @@ -0,0 +1,93 @@ + +config BITBANGMII + bool "Bit-banged ethernet MII management channel support" + +config MV88E6352_SWITCH + bool "Marvell 88E6352 switch support" + +menuconfig PHYLIB + bool "Ethernet PHY (physical media interface) support" + help + Enable Ethernet PHY (physical media interface) support. + +if PHYLIB + +config MV88E61XX_SWITCH + bool "Marvel MV88E61xx Ethernet switch PHY support." + +config PHYLIB_10G + bool "Generic 10G PHY support" + +config PHY_AQUANTIA + bool "Aquantia Ethernet PHYs support" + +config PHY_ATHEROS + bool "Atheros Ethernet PHYs support" + +config PHY_BROADCOM + bool "Broadcom Ethernet PHYs support" + +config PHY_CORTINA + bool "Cortina Ethernet PHYs support" + +config PHY_DAVICOM + bool "Davicom Ethernet PHYs support" + +config PHY_ET1011C + bool "LSI TruePHY ET1011C support" + +config PHY_LXT + bool "LXT971 Ethernet PHY support" + +config PHY_MARVELL + bool "Marvell Ethernet PHYs support" + +config PHY_MICREL + bool "Micrel Ethernet PHYs support" + +config PHY_MSCC + bool "Microsemi Corp Ethernet PHYs support" + +config PHY_NATSEMI + bool "National Semiconductor Ethernet PHYs support" + +config PHY_REALTEK + bool "Realtek Ethernet PHYs support" + +config RTL8211X_PHY_FORCE_MASTER + bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode" + depends on PHY_REALTEK + help + Force master mode for 1000BASE-T on RTl8211x PHYs (except for RTL8211F). + This can work around link stability and data corruption issues on gigabit + links which can occur in slave mode on certain PHYs, e.g. on the + RTL8211C(L). + + Please note that two directly connected devices (i.e. via crossover cable) + will not be able to establish a link between each other if they both force + master mode. Multiple devices forcing master mode when connected by a + network switch do not pose a problem as the switch configures its affected + ports into slave mode. + + This option only affects gigabit links. If you must establish a direct + connection between two devices which both force master mode, try forcing + the link speed to 100MBit/s. + + If unsure, say N. + +config PHY_SMSC + bool "Microchip(SMSC) Ethernet PHYs support" + +config PHY_TERANETICS + bool "Teranetics Ethernet PHYs support" + +config PHY_TI + bool "Texas Instruments Ethernet PHYs support" + +config PHY_VITESSE + bool "Vitesse Ethernet PHYs support" + +config PHY_XILINX + bool "Xilinx Ethernet PHYs support" + +endif #PHYLIB diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1e299b97b96..d37297122ad 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_PHY_TERANETICS) += teranetics.o obj-$(CONFIG_PHY_TI) += ti.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o +obj-$(CONFIG_PHY_MSCC) += mscc.o diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index c3058a40b22..ab0c44354c3 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -82,6 +82,21 @@ #define MIIM_88E1310_PHY_RGMII_CTRL 21 #define MIIM_88E1310_PHY_PAGE 22 +/* 88E151x PHY defines */ +/* Page 3 registers */ +#define MIIM_88E151x_LED_FUNC_CTRL 16 +#define MIIM_88E151x_LED_FLD_SZ 4 +#define MIIM_88E151x_LED0_OFFS (0 * MIIM_88E151x_LED_FLD_SZ) +#define MIIM_88E151x_LED1_OFFS (1 * MIIM_88E151x_LED_FLD_SZ) +#define MIIM_88E151x_LED0_ACT 3 +#define MIIM_88E151x_LED1_100_1000_LINK 6 +#define MIIM_88E151x_LED_TIMER_CTRL 18 +#define MIIM_88E151x_INT_EN_OFFS 7 +/* Page 18 registers */ +#define MIIM_88E151x_GENERAL_CTRL 20 +#define MIIM_88E151x_MODE_SGMII 1 +#define MIIM_88E151x_RESET_OFFS 15 + /* Marvell 88E1011S */ static int m88e1011s_config(struct phy_device *phydev) { @@ -177,10 +192,7 @@ static int m88e1111s_config(struct phy_device *phydev) { int reg; - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { + if (phy_interface_is_rgmii(phydev)) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || @@ -289,7 +301,7 @@ static int m88e1518_config(struct phy_device *phydev) */ /* EEE initialization */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); @@ -298,21 +310,23 @@ static int m88e1518_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { /* Select page 18 */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 18); /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ - m88e1518_phy_writebits(phydev, 20, 0, 3, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, + 0, 3, MIIM_88E151x_MODE_SGMII); /* PHY reset is necessary after changing MODE[2:0] */ - m88e1518_phy_writebits(phydev, 20, 15, 1, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, + MIIM_88E151x_RESET_OFFS, 1, 1); /* Reset page selection */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0); udelay(100); } @@ -324,17 +338,25 @@ static int m88e1518_config(struct phy_device *phydev) static int m88e1510_config(struct phy_device *phydev) { /* Select page 3 */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 3); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, + MIIM_88E1118_PHY_LED_PAGE); /* Enable INTn output on LED[2] */ - m88e1518_phy_writebits(phydev, 18, 7, 1, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_TIMER_CTRL, + MIIM_88E151x_INT_EN_OFFS, 1, 1); /* Configure LEDs */ - m88e1518_phy_writebits(phydev, 16, 0, 4, 3); /* LED[0]:0011 (ACT) */ - m88e1518_phy_writebits(phydev, 16, 4, 4, 6); /* LED[1]:0110 (LINK) */ + /* LED[0]:0011 (ACT) */ + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL, + MIIM_88E151x_LED0_OFFS, MIIM_88E151x_LED_FLD_SZ, + MIIM_88E151x_LED0_ACT); + /* LED[1]:0110 (LINK 100/1000 Mbps) */ + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL, + MIIM_88E151x_LED1_OFFS, MIIM_88E151x_LED_FLD_SZ, + MIIM_88E151x_LED1_100_1000_LINK); /* Reset page selection */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0); return m88e1518_config(phydev); } @@ -596,17 +618,22 @@ static struct phy_driver M88E1149S_driver = { static struct phy_driver M88E1510_driver = { .name = "Marvell 88E1510", .uid = 0x1410dd0, - .mask = 0xffffff0, + .mask = 0xfffffff, .features = PHY_GBIT_FEATURES, .config = &m88e1510_config, .startup = &m88e1011s_startup, .shutdown = &genphy_shutdown, }; +/* + * This supports: + * 88E1518, uid 0x1410dd1 + * 88E1512, uid 0x1410dd4 + */ static struct phy_driver M88E1518_driver = { .name = "Marvell 88E1518", - .uid = 0x1410dd1, - .mask = 0xffffff0, + .uid = 0x1410dd0, + .mask = 0xffffffa, .features = PHY_GBIT_FEATURES, .config = &m88e1518_config, .startup = &m88e1011s_startup, diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c new file mode 100644 index 00000000000..439f5e3c5cf --- /dev/null +++ b/drivers/net/phy/mscc.c @@ -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; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 80bdfb6d9d5..8db65749b11 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -512,6 +512,9 @@ int phy_init(void) #ifdef CONFIG_PHY_XILINX phy_xilinx_init(); #endif +#ifdef CONFIG_PHY_MSCC + phy_mscc_init(); +#endif return 0; } diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index d1ce4060ff8..1d870806a35 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; /* Extended Registers */ #define DP83867_RGMIICTL 0x0032 #define DP83867_RGMIIDCTL 0x0086 +#define DP83867_IO_MUX_CFG 0x0170 #define DP83867_SW_RESET BIT(15) #define DP83867_SW_RESTART BIT(14) @@ -84,10 +85,17 @@ DECLARE_GLOBAL_DATA_PTR; #define DEFAULT_TX_ID_DELAY DP83867_RGMIIDCTL_2_75_NS #define DEFAULT_FIFO_DEPTH DP83867_PHYCR_FIFO_DEPTH_4_B_NIB +/* IO_MUX_CFG bits */ +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f + +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 +#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f + struct dp83867_private { int rx_id_delay; int tx_id_delay; int fifo_depth; + int io_impedance; }; /** @@ -166,6 +174,15 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; struct udevice *dev = phydev->dev; + int node = dev->of_offset; + const void *fdt = gd->fdt_blob; + + if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance")) + dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; + else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance")) + dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; + else + dp83867->io_impedance = -EINVAL; dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "ti,rx-internal-delay", -1); @@ -186,6 +203,7 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY; dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY; dp83867->fifo_depth = DEFAULT_FIFO_DEPTH; + dp83867->io_impedance = -EINVAL; return 0; } @@ -246,8 +264,7 @@ static int dp83867_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0); } - if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) && - (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) { + if (phy_interface_is_rgmii(phydev)) { val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr); @@ -269,6 +286,19 @@ static int dp83867_config(struct phy_device *phydev) phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL, DP83867_DEVADDR, phydev->addr, delay); + + if (dp83867->io_impedance >= 0) { + val = phy_read_mmd_indirect(phydev, + DP83867_IO_MUX_CFG, + DP83867_DEVADDR, + phydev->addr); + val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + val |= dp83867->io_impedance & + DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr, + val); + } } genphy_config_aneg(phydev); diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index a077b98d8c4..e5e9922b30f 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -127,9 +127,7 @@ static int cis8204_config(struct phy_device *phydev) genphy_config_aneg(phydev); - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) + if (phy_interface_is_rgmii(phydev)) phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII); |