uboot/drivers/net/phy/xilinx_phy.c
<<
>>
Prefs
   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
  14DECLARE_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
  36static 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
 102static int xilinxphy_of_init(struct phy_device *phydev)
 103{
 104        u32 phytype;
 105
 106        debug("%s\n", __func__);
 107        phytype = fdtdec_get_int(gd->fdt_blob, phydev->dev->of_offset, "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
 114static 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
 127static 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
 137int phy_xilinx_init(void)
 138{
 139        debug("%s\n", __func__);
 140        phy_register(&xilinxphy_driver);
 141
 142        return 0;
 143}
 144