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