linux/drivers/net/phy/phy-c45.c
<<
>>
Prefs
   1/*
   2 * Clause 45 PHY support
   3 */
   4#include <linux/ethtool.h>
   5#include <linux/export.h>
   6#include <linux/mdio.h>
   7#include <linux/mii.h>
   8#include <linux/phy.h>
   9
  10/**
  11 * genphy_c45_setup_forced - configures a forced speed
  12 * @phydev: target phy_device struct
  13 */
  14int genphy_c45_pma_setup_forced(struct phy_device *phydev)
  15{
  16        int ctrl1, ctrl2, ret;
  17
  18        /* Half duplex is not supported */
  19        if (phydev->duplex != DUPLEX_FULL)
  20                return -EINVAL;
  21
  22        ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
  23        if (ctrl1 < 0)
  24                return ctrl1;
  25
  26        ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
  27        if (ctrl2 < 0)
  28                return ctrl2;
  29
  30        ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
  31        /*
  32         * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0.  See 45.2.1.6.1
  33         * in 802.3-2012 and 802.3-2015.
  34         */
  35        ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
  36
  37        switch (phydev->speed) {
  38        case SPEED_10:
  39                ctrl2 |= MDIO_PMA_CTRL2_10BT;
  40                break;
  41        case SPEED_100:
  42                ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
  43                ctrl2 |= MDIO_PMA_CTRL2_100BTX;
  44                break;
  45        case SPEED_1000:
  46                ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
  47                /* Assume 1000base-T */
  48                ctrl2 |= MDIO_PMA_CTRL2_1000BT;
  49                break;
  50        case SPEED_10000:
  51                ctrl1 |= MDIO_CTRL1_SPEED10G;
  52                /* Assume 10Gbase-T */
  53                ctrl2 |= MDIO_PMA_CTRL2_10GBT;
  54                break;
  55        default:
  56                return -EINVAL;
  57        }
  58
  59        ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
  60        if (ret < 0)
  61                return ret;
  62
  63        return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
  64}
  65EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
  66
  67/**
  68 * genphy_c45_an_disable_aneg - disable auto-negotiation
  69 * @phydev: target phy_device struct
  70 *
  71 * Disable auto-negotiation in the Clause 45 PHY. The link parameters
  72 * parameters are controlled through the PMA/PMD MMD registers.
  73 *
  74 * Returns zero on success, negative errno code on failure.
  75 */
  76int genphy_c45_an_disable_aneg(struct phy_device *phydev)
  77{
  78        int val;
  79
  80        val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
  81        if (val < 0)
  82                return val;
  83
  84        val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
  85
  86        return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
  87}
  88EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
  89
  90/**
  91 * genphy_c45_restart_aneg - Enable and restart auto-negotiation
  92 * @phydev: target phy_device struct
  93 *
  94 * This assumes that the auto-negotiation MMD is present.
  95 *
  96 * Enable and restart auto-negotiation.
  97 */
  98int genphy_c45_restart_aneg(struct phy_device *phydev)
  99{
 100        int val;
 101
 102        val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
 103        if (val < 0)
 104                return val;
 105
 106        val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
 107
 108        return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
 109}
 110EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
 111
 112/**
 113 * genphy_c45_aneg_done - return auto-negotiation complete status
 114 * @phydev: target phy_device struct
 115 *
 116 * This assumes that the auto-negotiation MMD is present.
 117 *
 118 * Reads the status register from the auto-negotiation MMD, returning:
 119 * - positive if auto-negotiation is complete
 120 * - negative errno code on error
 121 * - zero otherwise
 122 */
 123int genphy_c45_aneg_done(struct phy_device *phydev)
 124{
 125        int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
 126
 127        return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
 128}
 129EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
 130
 131/**
 132 * genphy_c45_read_link - read the overall link status from the MMDs
 133 * @phydev: target phy_device struct
 134 * @mmd_mask: MMDs to read status from
 135 *
 136 * Read the link status from the specified MMDs, and if they all indicate
 137 * that the link is up, return positive.  If an error is encountered,
 138 * a negative errno will be returned, otherwise zero.
 139 */
 140int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
 141{
 142        int val, devad;
 143        bool link = true;
 144
 145        while (mmd_mask) {
 146                devad = __ffs(mmd_mask);
 147                mmd_mask &= ~BIT(devad);
 148
 149                /* The link state is latched low so that momentary link
 150                 * drops can be detected.  Do not double-read the status
 151                 * register if the link is down.
 152                 */
 153                val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 154                if (val < 0)
 155                        return val;
 156
 157                if (!(val & MDIO_STAT1_LSTATUS))
 158                        link = false;
 159        }
 160
 161        return link;
 162}
 163EXPORT_SYMBOL_GPL(genphy_c45_read_link);
 164
 165/**
 166 * genphy_c45_read_lpa - read the link partner advertisement and pause
 167 * @phydev: target phy_device struct
 168 *
 169 * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
 170 * filling in the link partner advertisement, pause and asym_pause members
 171 * in @phydev.  This assumes that the auto-negotiation MMD is present, and
 172 * the backplane bit (7.48.0) is clear.  Clause 45 PHY drivers are expected
 173 * to fill in the remainder of the link partner advert from vendor registers.
 174 */
 175int genphy_c45_read_lpa(struct phy_device *phydev)
 176{
 177        int val;
 178
 179        /* Read the link partner's base page advertisement */
 180        val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
 181        if (val < 0)
 182                return val;
 183
 184        phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val);
 185        phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
 186        phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
 187
 188        /* Read the link partner's 10G advertisement */
 189        val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
 190        if (val < 0)
 191                return val;
 192
 193        if (val & MDIO_AN_10GBT_STAT_LP10G)
 194                phydev->lp_advertising |= ADVERTISED_10000baseT_Full;
 195
 196        return 0;
 197}
 198EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
 199
 200/**
 201 * genphy_c45_read_pma - read link speed etc from PMA
 202 * @phydev: target phy_device struct
 203 */
 204int genphy_c45_read_pma(struct phy_device *phydev)
 205{
 206        int val;
 207
 208        val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
 209        if (val < 0)
 210                return val;
 211
 212        switch (val & MDIO_CTRL1_SPEEDSEL) {
 213        case 0:
 214                phydev->speed = SPEED_10;
 215                break;
 216        case MDIO_PMA_CTRL1_SPEED100:
 217                phydev->speed = SPEED_100;
 218                break;
 219        case MDIO_PMA_CTRL1_SPEED1000:
 220                phydev->speed = SPEED_1000;
 221                break;
 222        case MDIO_CTRL1_SPEED10G:
 223                phydev->speed = SPEED_10000;
 224                break;
 225        default:
 226                phydev->speed = SPEED_UNKNOWN;
 227                break;
 228        }
 229
 230        phydev->duplex = DUPLEX_FULL;
 231
 232        return 0;
 233}
 234EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
 235
 236/**
 237 * genphy_c45_read_mdix - read mdix status from PMA
 238 * @phydev: target phy_device struct
 239 */
 240int genphy_c45_read_mdix(struct phy_device *phydev)
 241{
 242        int val;
 243
 244        if (phydev->speed == SPEED_10000) {
 245                val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
 246                                   MDIO_PMA_10GBT_SWAPPOL);
 247                if (val < 0)
 248                        return val;
 249
 250                switch (val) {
 251                case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
 252                        phydev->mdix = ETH_TP_MDI;
 253                        break;
 254
 255                case 0:
 256                        phydev->mdix = ETH_TP_MDI_X;
 257                        break;
 258
 259                default:
 260                        phydev->mdix = ETH_TP_MDI_INVALID;
 261                        break;
 262                }
 263        }
 264
 265        return 0;
 266}
 267EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
 268
 269/* The gen10g_* functions are the old Clause 45 stub */
 270
 271int gen10g_config_aneg(struct phy_device *phydev)
 272{
 273        return 0;
 274}
 275EXPORT_SYMBOL_GPL(gen10g_config_aneg);
 276
 277int gen10g_read_status(struct phy_device *phydev)
 278{
 279        u32 mmd_mask = phydev->c45_ids.devices_in_package;
 280        int ret;
 281
 282        /* For now just lie and say it's 10G all the time */
 283        phydev->speed = SPEED_10000;
 284        phydev->duplex = DUPLEX_FULL;
 285
 286        /* Avoid reading the vendor MMDs */
 287        mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
 288
 289        ret = genphy_c45_read_link(phydev, mmd_mask);
 290
 291        phydev->link = ret > 0 ? 1 : 0;
 292
 293        return 0;
 294}
 295EXPORT_SYMBOL_GPL(gen10g_read_status);
 296
 297int gen10g_no_soft_reset(struct phy_device *phydev)
 298{
 299        /* Do nothing for now */
 300        return 0;
 301}
 302EXPORT_SYMBOL_GPL(gen10g_no_soft_reset);
 303
 304int gen10g_config_init(struct phy_device *phydev)
 305{
 306        /* Temporarily just say we support everything */
 307        phydev->supported = SUPPORTED_10000baseT_Full;
 308        phydev->advertising = SUPPORTED_10000baseT_Full;
 309
 310        return 0;
 311}
 312EXPORT_SYMBOL_GPL(gen10g_config_init);
 313
 314int gen10g_suspend(struct phy_device *phydev)
 315{
 316        return 0;
 317}
 318EXPORT_SYMBOL_GPL(gen10g_suspend);
 319
 320int gen10g_resume(struct phy_device *phydev)
 321{
 322        return 0;
 323}
 324EXPORT_SYMBOL_GPL(gen10g_resume);
 325
 326struct phy_driver genphy_10g_driver = {
 327        .phy_id         = 0xffffffff,
 328        .phy_id_mask    = 0xffffffff,
 329        .name           = "Generic 10G PHY",
 330        .soft_reset     = gen10g_no_soft_reset,
 331        .config_init    = gen10g_config_init,
 332        .features       = 0,
 333        .config_aneg    = gen10g_config_aneg,
 334        .read_status    = gen10g_read_status,
 335        .suspend        = gen10g_suspend,
 336        .resume         = gen10g_resume,
 337};
 338