[U-Boot] [PATCH 1/1] Adding MSCC PHY-VSC8530-VSC8531-VSC8540-VSC8541

John Haechten john.haechten at microsemi.com
Wed Dec 7 18:11:04 CET 2016


>From 127c5fb9ef390cad5cf58e446110a696cf111345 Mon Sep 17 00:00:00 2001
From: John Haechten <john.haechten at microsemi.com>
Date: Wed, 7 Dec 2016 07:51:37 -0800
Subject: [PATCH] Adding MSCC PHY-VSC8530-VSC8531-VSC8540-VSC8541

(C) Copyright 2016 Microsemi Corporation, MIT License (MIT)
Author:John Haechten <john.haechten at microsemi.com>
Reviewed-by:Howard Hicks <howard.hicks at microsemi.com>
Reviewed-by:Joe Hershberger <joe.hershberger at ni.com>
Tested-by:Howard Hicks <howard.hicks at microsemi.com>
Version:1
Prefix:None
Signed-off-by: John Haechten <john.haechten at microsemi.com>

---

drivers/net/phy/Makefile            |   1 +
drivers/net/phy/mscc.c              | 480 ++++++++++++++++++++++++++++++++++++
drivers/net/phy/phy.c               |   3 +
include/config_phylib_all_drivers.h |   1 +
include/configs/am335x_evm.h        |   3 +
include/phy.h                       |   1 +
6 files changed, 489 insertions(+)
create mode 100644 drivers/net/phy/mscc.c

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 1e299b9..d372971 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/mscc.c b/drivers/net/phy/mscc.c
new file mode 100644
index 0000000..e63bd43
--- /dev/null
+++ b/drivers/net/phy/mscc.c
@@ -0,0 +1,480 @@
+/*
+ * Driver for Microsemi VSC85xx PHYs
+ *
+ * Author: John Haechten
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Microsemi Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <miiphy.h>
+#include <bitfield.h>
+
+/* Note: To include this PHY Driver file, #define CONFIG_PHY_MSCC */
+
+/* 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          0x1c
+#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         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             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 Registers */
+#define MSCC_PHY_TR_LINKDETCTRL_POS      3
+#define MSCC_PHY_TR_LINKDETCTRL_WIDTH    2
+#define MSCC_PHY_TR_LINKDETCTRL_MASK     0x18
+#define MSCC_PHY_TR_VGATHRESH100_POS     0
+#define MSCC_PHY_TR_VGATHRESH100_WIDTH   7
+#define MSCC_PHY_TR_VGATHRESH100_MASK    0x7f
+#define MSCC_PHY_TR_VGAGAIN10_U_POS      0
+#define MSCC_PHY_TR_VGAGAIN10_U_WIDTH    1
+#define MSCC_PHY_TR_VGAGAIN10_U_MASK     0x01
+#define MSCC_PHY_TR_VGAGAIN10_L_POS      12
+#define MSCC_PHY_TR_VGAGAIN10_L_WIDTH    4
+#define MSCC_PHY_TR_VGAGAIN10_L_MASK     0xf000
+/* 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_val17;
+     u16 reg_val18;
+
+     /* 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, 0xA7F8);
+     reg_val17 = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
+     reg_val17 = bitfield_replace(reg_val17, MSCC_PHY_TR_LINKDETCTRL_POS,
+                            MSCC_PHY_TR_LINKDETCTRL_WIDTH, 3);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val17);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x87F8);
+
+     /* Update VgaThresh100 defaults to optimized values */
+     /* Determined during Silicon Validation Testing */
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xAFA4);
+     reg_val18 = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
+     reg_val18 = bitfield_replace(reg_val18, MSCC_PHY_TR_VGATHRESH100_POS,
+                            MSCC_PHY_TR_VGATHRESH100_WIDTH, 24);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val18);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8FA4);
+
+     /* Update VgaGain10 defaults to optimized values */
+     /* Determined during Silicon Validation Testing */
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xAF92);
+     reg_val18 = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
+     reg_val17 = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
+     reg_val18 = bitfield_replace(reg_val18, MSCC_PHY_TR_VGAGAIN10_U_POS,
+                            MSCC_PHY_TR_VGAGAIN10_U_WIDTH, 0);
+
+     reg_val17 = bitfield_replace(reg_val17, MSCC_PHY_TR_VGAGAIN10_L_POS,
+                            MSCC_PHY_TR_VGAGAIN10_L_WIDTH, 1);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val18);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val17);
+     phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8F92);
+
+     /* 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 ret;
+
+     ret = genphy_update_link(phydev);
+     if (ret)
+           return ret;
+     return mscc_parse_status(phydev);
+}
+
+static int mscc_phy_soft_reset(struct phy_device *phydev)
+{
+     int     rc = 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);
+     reg_val |= BMCR_RESET;
+     phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg_val);
+
+     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);
+           rc = -ETIME;
+     }
+
+     return rc;
+}
+
+static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
+{
+     int   rc = 0;
+     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);
+
+     /* Read Reg23 */
+     reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
+                    MSCC_PHY_EXT_PHY_CNTL_1);
+     /* 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_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_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_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 rc;
+}
+
+static int vsc8531_config(struct phy_device *phydev)
+{
+     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:
+           vsc8531_vsc8541_mac_config(phydev);
+           mscc_phy_soft_reset(phydev);
+           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);
+
+     /* 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_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)
+{
+     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:
+           vsc8531_vsc8541_mac_config(phydev);
+           mscc_phy_soft_reset(phydev);
+           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);
+     /* 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_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 80bdfb6..8db6574 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/include/config_phylib_all_drivers.h b/include/config_phylib_all_drivers.h
index 12828c6..d2965ed 100644
--- a/include/config_phylib_all_drivers.h
+++ b/include/config_phylib_all_drivers.h
@@ -14,6 +14,7 @@

 #ifdef CONFIG_PHYLIB

+#define CONFIG_PHY_MSCC
#define CONFIG_PHY_VITESSE
#define CONFIG_PHY_MARVELL
#define CONFIG_PHY_MICREL
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index ec70b72..694e249 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -433,6 +433,9 @@
#define CONFIG_PHY_SMSC
/* Enable Atheros phy driver */
#define CONFIG_PHY_ATHEROS
+/* Enable MSCC phy driver */
+#define CONFIG_PHY_MSCC
+

 /*
  * NOR Size = 16 MiB
diff --git a/include/phy.h b/include/phy.h
index 268d9a1..5477496 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -266,6 +266,7 @@ int phy_teranetics_init(void);
int phy_ti_init(void);
int phy_vitesse_init(void);
int phy_xilinx_init(void);
+int phy_mscc_init(void);

 int board_phy_config(struct phy_device *phydev);
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id);
--
1.9.1





More information about the U-Boot mailing list