Add phy driver support for xilinx PCS/PMA core Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com> Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>master
parent
563d8d9358
commit
ed6fad3e25
@ -0,0 +1,144 @@ |
||||
/*
|
||||
* Xilinx PCS/PMA Core phy driver |
||||
* |
||||
* Copyright (C) 2015 - 2016 Xilinx, Inc. |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <config.h> |
||||
#include <common.h> |
||||
#include <phy.h> |
||||
#include <dm.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
#define MII_PHY_STATUS_SPD_MASK 0x0C00 |
||||
#define MII_PHY_STATUS_FULLDUPLEX 0x1000 |
||||
#define MII_PHY_STATUS_1000 0x0800 |
||||
#define MII_PHY_STATUS_100 0x0400 |
||||
#define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF |
||||
|
||||
/* Mask used for ID comparisons */ |
||||
#define XILINX_PHY_ID_MASK 0xfffffff0 |
||||
|
||||
/* Known PHY IDs */ |
||||
#define XILINX_PHY_ID 0x01740c00 |
||||
|
||||
/* struct phy_device dev_flags definitions */ |
||||
#define XAE_PHY_TYPE_MII 0 |
||||
#define XAE_PHY_TYPE_GMII 1 |
||||
#define XAE_PHY_TYPE_RGMII_1_3 2 |
||||
#define XAE_PHY_TYPE_RGMII_2_0 3 |
||||
#define XAE_PHY_TYPE_SGMII 4 |
||||
#define XAE_PHY_TYPE_1000BASE_X 5 |
||||
|
||||
static int xilinxphy_startup(struct phy_device *phydev) |
||||
{ |
||||
int err; |
||||
int status = 0; |
||||
|
||||
debug("%s\n", __func__); |
||||
/* Update the link, but return if there
|
||||
* was an error |
||||
*/ |
||||
err = genphy_update_link(phydev); |
||||
if (err) |
||||
return err; |
||||
|
||||
if (AUTONEG_ENABLE == phydev->autoneg) { |
||||
status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); |
||||
status = status & MII_PHY_STATUS_SPD_MASK; |
||||
|
||||
if (status & MII_PHY_STATUS_FULLDUPLEX) |
||||
phydev->duplex = DUPLEX_FULL; |
||||
else |
||||
phydev->duplex = DUPLEX_HALF; |
||||
|
||||
switch (status) { |
||||
case MII_PHY_STATUS_1000: |
||||
phydev->speed = SPEED_1000; |
||||
break; |
||||
|
||||
case MII_PHY_STATUS_100: |
||||
phydev->speed = SPEED_100; |
||||
break; |
||||
|
||||
default: |
||||
phydev->speed = SPEED_10; |
||||
break; |
||||
} |
||||
} else { |
||||
int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
||||
|
||||
if (bmcr < 0) |
||||
return bmcr; |
||||
|
||||
if (bmcr & BMCR_FULLDPLX) |
||||
phydev->duplex = DUPLEX_FULL; |
||||
else |
||||
phydev->duplex = DUPLEX_HALF; |
||||
|
||||
if (bmcr & BMCR_SPEED1000) |
||||
phydev->speed = SPEED_1000; |
||||
else if (bmcr & BMCR_SPEED100) |
||||
phydev->speed = SPEED_100; |
||||
else |
||||
phydev->speed = SPEED_10; |
||||
} |
||||
|
||||
/*
|
||||
* For 1000BASE-X Phy Mode the speed/duplex will always be |
||||
* 1000Mbps/fullduplex |
||||
*/ |
||||
if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) { |
||||
phydev->duplex = DUPLEX_FULL; |
||||
phydev->speed = SPEED_1000; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int xilinxphy_of_init(struct phy_device *phydev) |
||||
{ |
||||
struct udevice *dev = (struct udevice *)&phydev->dev; |
||||
u32 phytype; |
||||
|
||||
debug("%s\n", __func__); |
||||
phytype = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "phy-type", -1); |
||||
if (phytype == XAE_PHY_TYPE_1000BASE_X) |
||||
phydev->flags |= XAE_PHY_TYPE_1000BASE_X; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int xilinxphy_config(struct phy_device *phydev) |
||||
{ |
||||
int temp; |
||||
|
||||
debug("%s\n", __func__); |
||||
xilinxphy_of_init(phydev); |
||||
temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); |
||||
temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE; |
||||
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct phy_driver xilinxphy_driver = { |
||||
.uid = XILINX_PHY_ID, |
||||
.mask = XILINX_PHY_ID_MASK, |
||||
.name = "Xilinx PCS/PMA PHY", |
||||
.features = PHY_GBIT_FEATURES, |
||||
.config = &xilinxphy_config, |
||||
.startup = &xilinxphy_startup, |
||||
.shutdown = &genphy_shutdown, |
||||
}; |
||||
|
||||
int phy_xilinx_init(void) |
||||
{ |
||||
debug("%s\n", __func__); |
||||
phy_register(&xilinxphy_driver); |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue