Merge branch 'master' of git://git.denx.de/u-boot-net
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
source "drivers/net/phy/Kconfig"
|
||||
|
||||
config DM_ETH
|
||||
bool "Enable Driver Model for Ethernet drivers"
|
||||
depends on DM
|
||||
@@ -8,32 +10,6 @@ config DM_ETH
|
||||
This is currently implemented in net/eth.c
|
||||
Look in include/net.h for details.
|
||||
|
||||
config PHYLIB
|
||||
bool "Ethernet PHY (physical media interface) support"
|
||||
help
|
||||
Enable Ethernet PHY (physical media interface) support.
|
||||
|
||||
config RTL8211X_PHY_FORCE_MASTER
|
||||
bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode"
|
||||
depends on PHYLIB
|
||||
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.
|
||||
|
||||
menuconfig NETDEVICES
|
||||
bool "Network device support"
|
||||
depends on NET
|
||||
@@ -155,6 +131,16 @@ config MVPP2
|
||||
This driver supports the network interface units in the
|
||||
Marvell ARMADA 375 SoC.
|
||||
|
||||
config MACB
|
||||
bool "Cadence MACB/GEM Ethernet Interface"
|
||||
depends on DM_ETH
|
||||
select PHYLIB
|
||||
help
|
||||
The Cadence MACB ethernet interface is found on many Atmel
|
||||
AT91 and SAMA5 parts. This driver also supports the Cadence
|
||||
GEM (Gigabit Ethernet MAC) found in some ARM SoC devices.
|
||||
Say Y to include support for the MACB/GEM chip.
|
||||
|
||||
config PCH_GBE
|
||||
bool "Intel Platform Controller Hub EG20T GMAC driver"
|
||||
depends on DM_ETH && DM_PCI
|
||||
|
||||
@@ -764,6 +764,7 @@ static const struct udevice_id designware_eth_ids[] = {
|
||||
{ .compatible = "allwinner,sun7i-a20-gmac" },
|
||||
{ .compatible = "altr,socfpga-stmmac" },
|
||||
{ .compatible = "amlogic,meson6-dwmac" },
|
||||
{ .compatible = "amlogic,meson-gx-dwmac" },
|
||||
{ .compatible = "st,stm32-dwmac" },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -1240,7 +1240,6 @@ static int fecmxc_probe(struct udevice *dev)
|
||||
}
|
||||
|
||||
fec_reg_setup(priv);
|
||||
fec_set_dev_name((char *)dev->name, dev_id);
|
||||
priv->dev_id = (dev_id == -1) ? 0 : dev_id;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
|
||||
/*
|
||||
@@ -112,6 +113,7 @@ struct macb_device {
|
||||
struct mii_dev *bus;
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
unsigned long pclk_rate;
|
||||
phy_interface_t phy_interface;
|
||||
#endif
|
||||
};
|
||||
@@ -754,7 +756,11 @@ static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr)
|
||||
static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
|
||||
{
|
||||
u32 config;
|
||||
#ifdef CONFIG_DM_ETH
|
||||
unsigned long macb_hz = macb->pclk_rate;
|
||||
#else
|
||||
unsigned long macb_hz = get_macb_pclk_rate(id);
|
||||
#endif
|
||||
|
||||
if (macb_hz < 20000000)
|
||||
config = MACB_BF(CLK, MACB_CLK_DIV8);
|
||||
@@ -771,7 +777,12 @@ static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
|
||||
static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
|
||||
{
|
||||
u32 config;
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
unsigned long macb_hz = macb->pclk_rate;
|
||||
#else
|
||||
unsigned long macb_hz = get_macb_pclk_rate(id);
|
||||
#endif
|
||||
|
||||
if (macb_hz < 20000000)
|
||||
config = GEM_BF(CLK, GEM_CLK_DIV8);
|
||||
@@ -991,13 +1002,36 @@ static const struct eth_ops macb_eth_ops = {
|
||||
.write_hwaddr = macb_write_hwaddr,
|
||||
};
|
||||
|
||||
static int macb_enable_clk(struct udevice *dev)
|
||||
{
|
||||
struct macb_device *macb = dev_get_priv(dev);
|
||||
struct clk clk;
|
||||
ulong clk_rate;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_rate = clk_get_rate(&clk);
|
||||
if (!clk_rate)
|
||||
return -EINVAL;
|
||||
|
||||
macb->pclk_rate = clk_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int macb_eth_probe(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
struct macb_device *macb = dev_get_priv(dev);
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
const char *phy_mode;
|
||||
int ret;
|
||||
|
||||
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
|
||||
NULL);
|
||||
@@ -1007,11 +1041,15 @@ static int macb_eth_probe(struct udevice *dev)
|
||||
debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
macb->regs = (void *)pdata->iobase;
|
||||
|
||||
ret = macb_enable_clk(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
_macb_eth_initialize(macb);
|
||||
|
||||
#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
|
||||
93
drivers/net/phy/Kconfig
Normal file
93
drivers/net/phy/Kconfig
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
508
drivers/net/phy/mscc.c
Normal file
508
drivers/net/phy/mscc.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user