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