aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorTom Rini2017-02-09 11:56:35 -0500
committerTom Rini2017-02-09 11:56:35 -0500
commite1a71f8b339220fa74c9cd5d36ae9c444c492e83 (patch)
tree5eca7ff69f390f4c2f2df3459d3e2db3d91b7af9 /drivers/net/phy
parent6f57b19857b514f6e94e423c9bbe2d4b8973a0db (diff)
parenta5fd13ad1913d9c66c47666dbedac7703a48e502 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-net
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/Kconfig93
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/marvell.c63
-rw-r--r--drivers/net/phy/mscc.c508
-rw-r--r--drivers/net/phy/phy.c3
-rw-r--r--drivers/net/phy/ti.c34
-rw-r--r--drivers/net/phy/vitesse.c4
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);