linux/drivers/net/phy/microchip.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Microchip Technology
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version 2
   7 * of the License, or (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16 */
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/mii.h>
  20#include <linux/ethtool.h>
  21#include <linux/phy.h>
  22#include <linux/microchipphy.h>
  23#include <linux/delay.h>
  24
  25#define DRIVER_AUTHOR   "WOOJUNG HUH <woojung.huh@microchip.com>"
  26#define DRIVER_DESC     "Microchip LAN88XX PHY driver"
  27
  28struct lan88xx_priv {
  29        int     chip_id;
  30        int     chip_rev;
  31        __u32   wolopts;
  32};
  33
  34static int lan88xx_read_page(struct phy_device *phydev)
  35{
  36        return __phy_read(phydev, LAN88XX_EXT_PAGE_ACCESS);
  37}
  38
  39static int lan88xx_write_page(struct phy_device *phydev, int page)
  40{
  41        return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
  42}
  43
  44static int lan88xx_phy_config_intr(struct phy_device *phydev)
  45{
  46        int rc;
  47
  48        if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
  49                /* unmask all source and clear them before enable */
  50                rc = phy_write(phydev, LAN88XX_INT_MASK, 0x7FFF);
  51                rc = phy_read(phydev, LAN88XX_INT_STS);
  52                rc = phy_write(phydev, LAN88XX_INT_MASK,
  53                               LAN88XX_INT_MASK_MDINTPIN_EN_ |
  54                               LAN88XX_INT_MASK_LINK_CHANGE_);
  55        } else {
  56                rc = phy_write(phydev, LAN88XX_INT_MASK, 0);
  57        }
  58
  59        return rc < 0 ? rc : 0;
  60}
  61
  62static int lan88xx_phy_ack_interrupt(struct phy_device *phydev)
  63{
  64        int rc = phy_read(phydev, LAN88XX_INT_STS);
  65
  66        return rc < 0 ? rc : 0;
  67}
  68
  69static int lan88xx_suspend(struct phy_device *phydev)
  70{
  71        struct lan88xx_priv *priv = phydev->priv;
  72
  73        /* do not power down PHY when WOL is enabled */
  74        if (!priv->wolopts)
  75                genphy_suspend(phydev);
  76
  77        return 0;
  78}
  79
  80static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
  81                              u32 data)
  82{
  83        int val, save_page, ret = 0;
  84        u16 buf;
  85
  86        /* Save current page */
  87        save_page = phy_save_page(phydev);
  88        if (save_page < 0) {
  89                pr_warn("Failed to get current page\n");
  90                goto err;
  91        }
  92
  93        /* Switch to TR page */
  94        lan88xx_write_page(phydev, LAN88XX_EXT_PAGE_ACCESS_TR);
  95
  96        ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA,
  97                          (data & 0xFFFF));
  98        if (ret < 0) {
  99                pr_warn("Failed to write TR low data\n");
 100                goto err;
 101        }
 102
 103        ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA,
 104                          (data & 0x00FF0000) >> 16);
 105        if (ret < 0) {
 106                pr_warn("Failed to write TR high data\n");
 107                goto err;
 108        }
 109
 110        /* Config control bits [15:13] of register */
 111        buf = (regaddr & ~(0x3 << 13));/* Clr [14:13] to write data in reg */
 112        buf |= 0x8000; /* Set [15] to Packet transmit */
 113
 114        ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf);
 115        if (ret < 0) {
 116                pr_warn("Failed to write data in reg\n");
 117                goto err;
 118        }
 119
 120        usleep_range(1000, 2000);/* Wait for Data to be written */
 121        val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR);
 122        if (!(val & 0x8000))
 123                pr_warn("TR Register[0x%X] configuration failed\n", regaddr);
 124err:
 125        return phy_restore_page(phydev, save_page, ret);
 126}
 127
 128static void lan88xx_config_TR_regs(struct phy_device *phydev)
 129{
 130        int err;
 131
 132        /* Get access to Channel 0x1, Node 0xF , Register 0x01.
 133         * Write 24-bit value 0x12B00A to register. Setting MrvlTrFix1000Kf,
 134         * MrvlTrFix1000Kp, MasterEnableTR bits.
 135         */
 136        err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A);
 137        if (err < 0)
 138                pr_warn("Failed to Set Register[0x0F82]\n");
 139
 140        /* Get access to Channel b'10, Node b'1101, Register 0x06.
 141         * Write 24-bit value 0xD2C46F to register. Setting SSTrKf1000Slv,
 142         * SSTrKp1000Mas bits.
 143         */
 144        err = lan88xx_TR_reg_set(phydev, 0x168C, 0xD2C46F);
 145        if (err < 0)
 146                pr_warn("Failed to Set Register[0x168C]\n");
 147
 148        /* Get access to Channel b'10, Node b'1111, Register 0x11.
 149         * Write 24-bit value 0x620 to register. Setting rem_upd_done_thresh
 150         * bits
 151         */
 152        err = lan88xx_TR_reg_set(phydev, 0x17A2, 0x620);
 153        if (err < 0)
 154                pr_warn("Failed to Set Register[0x17A2]\n");
 155
 156        /* Get access to Channel b'10, Node b'1101, Register 0x10.
 157         * Write 24-bit value 0xEEFFDD to register. Setting
 158         * eee_TrKp1Long_1000, eee_TrKp2Long_1000, eee_TrKp3Long_1000,
 159         * eee_TrKp1Short_1000,eee_TrKp2Short_1000, eee_TrKp3Short_1000 bits.
 160         */
 161        err = lan88xx_TR_reg_set(phydev, 0x16A0, 0xEEFFDD);
 162        if (err < 0)
 163                pr_warn("Failed to Set Register[0x16A0]\n");
 164
 165        /* Get access to Channel b'10, Node b'1101, Register 0x13.
 166         * Write 24-bit value 0x071448 to register. Setting
 167         * slv_lpi_tr_tmr_val1, slv_lpi_tr_tmr_val2 bits.
 168         */
 169        err = lan88xx_TR_reg_set(phydev, 0x16A6, 0x071448);
 170        if (err < 0)
 171                pr_warn("Failed to Set Register[0x16A6]\n");
 172
 173        /* Get access to Channel b'10, Node b'1101, Register 0x12.
 174         * Write 24-bit value 0x13132F to register. Setting
 175         * slv_sigdet_timer_val1, slv_sigdet_timer_val2 bits.
 176         */
 177        err = lan88xx_TR_reg_set(phydev, 0x16A4, 0x13132F);
 178        if (err < 0)
 179                pr_warn("Failed to Set Register[0x16A4]\n");
 180
 181        /* Get access to Channel b'10, Node b'1101, Register 0x14.
 182         * Write 24-bit value 0x0 to register. Setting eee_3level_delay,
 183         * eee_TrKf_freeze_delay bits.
 184         */
 185        err = lan88xx_TR_reg_set(phydev, 0x16A8, 0x0);
 186        if (err < 0)
 187                pr_warn("Failed to Set Register[0x16A8]\n");
 188
 189        /* Get access to Channel b'01, Node b'1111, Register 0x34.
 190         * Write 24-bit value 0x91B06C to register. Setting
 191         * FastMseSearchThreshLong1000, FastMseSearchThreshShort1000,
 192         * FastMseSearchUpdGain1000 bits.
 193         */
 194        err = lan88xx_TR_reg_set(phydev, 0x0FE8, 0x91B06C);
 195        if (err < 0)
 196                pr_warn("Failed to Set Register[0x0FE8]\n");
 197
 198        /* Get access to Channel b'01, Node b'1111, Register 0x3E.
 199         * Write 24-bit value 0xC0A028 to register. Setting
 200         * FastMseKp2ThreshLong1000, FastMseKp2ThreshShort1000,
 201         * FastMseKp2UpdGain1000, FastMseKp2ExitEn1000 bits.
 202         */
 203        err = lan88xx_TR_reg_set(phydev, 0x0FFC, 0xC0A028);
 204        if (err < 0)
 205                pr_warn("Failed to Set Register[0x0FFC]\n");
 206
 207        /* Get access to Channel b'01, Node b'1111, Register 0x35.
 208         * Write 24-bit value 0x041600 to register. Setting
 209         * FastMseSearchPhShNum1000, FastMseSearchClksPerPh1000,
 210         * FastMsePhChangeDelay1000 bits.
 211         */
 212        err = lan88xx_TR_reg_set(phydev, 0x0FEA, 0x041600);
 213        if (err < 0)
 214                pr_warn("Failed to Set Register[0x0FEA]\n");
 215
 216        /* Get access to Channel b'10, Node b'1101, Register 0x03.
 217         * Write 24-bit value 0x000004 to register. Setting TrFreeze bits.
 218         */
 219        err = lan88xx_TR_reg_set(phydev, 0x1686, 0x000004);
 220        if (err < 0)
 221                pr_warn("Failed to Set Register[0x1686]\n");
 222}
 223
 224static int lan88xx_probe(struct phy_device *phydev)
 225{
 226        struct device *dev = &phydev->mdio.dev;
 227        struct lan88xx_priv *priv;
 228
 229        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 230        if (!priv)
 231                return -ENOMEM;
 232
 233        priv->wolopts = 0;
 234
 235        /* these values can be used to identify internal PHY */
 236        priv->chip_id = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_ID);
 237        priv->chip_rev = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_REV);
 238
 239        phydev->priv = priv;
 240
 241        return 0;
 242}
 243
 244static void lan88xx_remove(struct phy_device *phydev)
 245{
 246        struct device *dev = &phydev->mdio.dev;
 247        struct lan88xx_priv *priv = phydev->priv;
 248
 249        if (priv)
 250                devm_kfree(dev, priv);
 251}
 252
 253static int lan88xx_set_wol(struct phy_device *phydev,
 254                           struct ethtool_wolinfo *wol)
 255{
 256        struct lan88xx_priv *priv = phydev->priv;
 257
 258        priv->wolopts = wol->wolopts;
 259
 260        return 0;
 261}
 262
 263static void lan88xx_set_mdix(struct phy_device *phydev)
 264{
 265        int buf;
 266        int val;
 267
 268        switch (phydev->mdix_ctrl) {
 269        case ETH_TP_MDI:
 270                val = LAN88XX_EXT_MODE_CTRL_MDI_;
 271                break;
 272        case ETH_TP_MDI_X:
 273                val = LAN88XX_EXT_MODE_CTRL_MDI_X_;
 274                break;
 275        case ETH_TP_MDI_AUTO:
 276                val = LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_;
 277                break;
 278        default:
 279                return;
 280        }
 281
 282        phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1);
 283        buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL);
 284        buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
 285        buf |= val;
 286        phy_write(phydev, LAN88XX_EXT_MODE_CTRL, buf);
 287        phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0);
 288}
 289
 290static int lan88xx_config_init(struct phy_device *phydev)
 291{
 292        int val;
 293
 294        genphy_config_init(phydev);
 295        /*Zerodetect delay enable */
 296        val = phy_read_mmd(phydev, MDIO_MMD_PCS,
 297                           PHY_ARDENNES_MMD_DEV_3_PHY_CFG);
 298        val |= PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_;
 299
 300        phy_write_mmd(phydev, MDIO_MMD_PCS, PHY_ARDENNES_MMD_DEV_3_PHY_CFG,
 301                      val);
 302
 303        /* Config DSP registers */
 304        lan88xx_config_TR_regs(phydev);
 305
 306        return 0;
 307}
 308
 309static int lan88xx_config_aneg(struct phy_device *phydev)
 310{
 311        lan88xx_set_mdix(phydev);
 312
 313        return genphy_config_aneg(phydev);
 314}
 315
 316static struct phy_driver microchip_phy_driver[] = {
 317{
 318        .phy_id         = 0x0007c130,
 319        .phy_id_mask    = 0xfffffff0,
 320        .name           = "Microchip LAN88xx",
 321
 322        .features       = PHY_GBIT_FEATURES,
 323        .flags          = PHY_HAS_INTERRUPT,
 324
 325        .probe          = lan88xx_probe,
 326        .remove         = lan88xx_remove,
 327
 328        .config_init    = lan88xx_config_init,
 329        .config_aneg    = lan88xx_config_aneg,
 330
 331        .ack_interrupt  = lan88xx_phy_ack_interrupt,
 332        .config_intr    = lan88xx_phy_config_intr,
 333
 334        .suspend        = lan88xx_suspend,
 335        .resume         = genphy_resume,
 336        .set_wol        = lan88xx_set_wol,
 337        .read_page      = lan88xx_read_page,
 338        .write_page     = lan88xx_write_page,
 339} };
 340
 341module_phy_driver(microchip_phy_driver);
 342
 343static struct mdio_device_id __maybe_unused microchip_tbl[] = {
 344        { 0x0007c130, 0xfffffff0 },
 345        { }
 346};
 347
 348MODULE_DEVICE_TABLE(mdio, microchip_tbl);
 349
 350MODULE_AUTHOR(DRIVER_AUTHOR);
 351MODULE_DESCRIPTION(DRIVER_DESC);
 352MODULE_LICENSE("GPL");
 353