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