1 /* 2 * Xilinx PCS/PMA Core phy driver 3 * 4 * Copyright (C) 2015 - 2016 Xilinx, Inc. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <config.h> 10 #include <common.h> 11 #include <phy.h> 12 #include <dm.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 #define MII_PHY_STATUS_SPD_MASK 0x0C00 17 #define MII_PHY_STATUS_FULLDUPLEX 0x1000 18 #define MII_PHY_STATUS_1000 0x0800 19 #define MII_PHY_STATUS_100 0x0400 20 #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF 21 22 /* Mask used for ID comparisons */ 23 #define XILINX_PHY_ID_MASK 0xfffffff0 24 25 /* Known PHY IDs */ 26 #define XILINX_PHY_ID 0x01740c00 27 28 /* struct phy_device dev_flags definitions */ 29 #define XAE_PHY_TYPE_MII 0 30 #define XAE_PHY_TYPE_GMII 1 31 #define XAE_PHY_TYPE_RGMII_1_3 2 32 #define XAE_PHY_TYPE_RGMII_2_0 3 33 #define XAE_PHY_TYPE_SGMII 4 34 #define XAE_PHY_TYPE_1000BASE_X 5 35 36 static int xilinxphy_startup(struct phy_device *phydev) 37 { 38 int err; 39 int status = 0; 40 41 debug("%s\n", __func__); 42 /* Update the link, but return if there 43 * was an error 44 */ 45 err = genphy_update_link(phydev); 46 if (err) 47 return err; 48 49 if (AUTONEG_ENABLE == phydev->autoneg) { 50 status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); 51 status = status & MII_PHY_STATUS_SPD_MASK; 52 53 if (status & MII_PHY_STATUS_FULLDUPLEX) 54 phydev->duplex = DUPLEX_FULL; 55 else 56 phydev->duplex = DUPLEX_HALF; 57 58 switch (status) { 59 case MII_PHY_STATUS_1000: 60 phydev->speed = SPEED_1000; 61 break; 62 63 case MII_PHY_STATUS_100: 64 phydev->speed = SPEED_100; 65 break; 66 67 default: 68 phydev->speed = SPEED_10; 69 break; 70 } 71 } else { 72 int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 73 74 if (bmcr < 0) 75 return bmcr; 76 77 if (bmcr & BMCR_FULLDPLX) 78 phydev->duplex = DUPLEX_FULL; 79 else 80 phydev->duplex = DUPLEX_HALF; 81 82 if (bmcr & BMCR_SPEED1000) 83 phydev->speed = SPEED_1000; 84 else if (bmcr & BMCR_SPEED100) 85 phydev->speed = SPEED_100; 86 else 87 phydev->speed = SPEED_10; 88 } 89 90 /* 91 * For 1000BASE-X Phy Mode the speed/duplex will always be 92 * 1000Mbps/fullduplex 93 */ 94 if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) { 95 phydev->duplex = DUPLEX_FULL; 96 phydev->speed = SPEED_1000; 97 } 98 99 return 0; 100 } 101 102 static int xilinxphy_of_init(struct phy_device *phydev) 103 { 104 struct udevice *dev = (struct udevice *)&phydev->dev; 105 u32 phytype; 106 107 debug("%s\n", __func__); 108 phytype = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "phy-type", -1); 109 if (phytype == XAE_PHY_TYPE_1000BASE_X) 110 phydev->flags |= XAE_PHY_TYPE_1000BASE_X; 111 112 return 0; 113 } 114 115 static int xilinxphy_config(struct phy_device *phydev) 116 { 117 int temp; 118 119 debug("%s\n", __func__); 120 xilinxphy_of_init(phydev); 121 temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 122 temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE; 123 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp); 124 125 return 0; 126 } 127 128 static struct phy_driver xilinxphy_driver = { 129 .uid = XILINX_PHY_ID, 130 .mask = XILINX_PHY_ID_MASK, 131 .name = "Xilinx PCS/PMA PHY", 132 .features = PHY_GBIT_FEATURES, 133 .config = &xilinxphy_config, 134 .startup = &xilinxphy_startup, 135 .shutdown = &genphy_shutdown, 136 }; 137 138 int phy_xilinx_init(void) 139 { 140 debug("%s\n", __func__); 141 phy_register(&xilinxphy_driver); 142 143 return 0; 144 } 145