linux/drivers/net/phy/micrel.c
<<
>>
Prefs
   1/*
   2 * drivers/net/phy/micrel.c
   3 *
   4 * Driver for Micrel PHYs
   5 *
   6 * Author: David J. Choi
   7 *
   8 * Copyright (c) 2010-2013 Micrel, Inc.
   9 * Copyright (c) 2014 Johan Hovold <johan@kernel.org>
  10 *
  11 * This program is free software; you can redistribute  it and/or modify it
  12 * under  the terms of  the GNU General  Public License as published by the
  13 * Free Software Foundation;  either version 2 of the  License, or (at your
  14 * option) any later version.
  15 *
  16 * Support : Micrel Phys:
  17 *              Giga phys: ksz9021, ksz9031
  18 *              100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
  19 *                         ksz8021, ksz8031, ksz8051,
  20 *                         ksz8081, ksz8091,
  21 *                         ksz8061,
  22 *              Switch : ksz8873, ksz886x
  23 */
  24
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/phy.h>
  28#include <linux/micrel_phy.h>
  29#include <linux/of.h>
  30#include <linux/clk.h>
  31
  32/* Operation Mode Strap Override */
  33#define MII_KSZPHY_OMSO                         0x16
  34#define KSZPHY_OMSO_B_CAST_OFF                  BIT(9)
  35#define KSZPHY_OMSO_NAND_TREE_ON                BIT(5)
  36#define KSZPHY_OMSO_RMII_OVERRIDE               BIT(1)
  37#define KSZPHY_OMSO_MII_OVERRIDE                BIT(0)
  38
  39/* general Interrupt control/status reg in vendor specific block. */
  40#define MII_KSZPHY_INTCS                        0x1B
  41#define KSZPHY_INTCS_JABBER                     BIT(15)
  42#define KSZPHY_INTCS_RECEIVE_ERR                BIT(14)
  43#define KSZPHY_INTCS_PAGE_RECEIVE               BIT(13)
  44#define KSZPHY_INTCS_PARELLEL                   BIT(12)
  45#define KSZPHY_INTCS_LINK_PARTNER_ACK           BIT(11)
  46#define KSZPHY_INTCS_LINK_DOWN                  BIT(10)
  47#define KSZPHY_INTCS_REMOTE_FAULT               BIT(9)
  48#define KSZPHY_INTCS_LINK_UP                    BIT(8)
  49#define KSZPHY_INTCS_ALL                        (KSZPHY_INTCS_LINK_UP |\
  50                                                KSZPHY_INTCS_LINK_DOWN)
  51
  52/* PHY Control 1 */
  53#define MII_KSZPHY_CTRL_1                       0x1e
  54
  55/* PHY Control 2 / PHY Control (if no PHY Control 1) */
  56#define MII_KSZPHY_CTRL_2                       0x1f
  57#define MII_KSZPHY_CTRL                         MII_KSZPHY_CTRL_2
  58/* bitmap of PHY register to set interrupt mode */
  59#define KSZPHY_CTRL_INT_ACTIVE_HIGH             BIT(9)
  60#define KSZPHY_RMII_REF_CLK_SEL                 BIT(7)
  61
  62/* Write/read to/from extended registers */
  63#define MII_KSZPHY_EXTREG                       0x0b
  64#define KSZPHY_EXTREG_WRITE                     0x8000
  65
  66#define MII_KSZPHY_EXTREG_WRITE                 0x0c
  67#define MII_KSZPHY_EXTREG_READ                  0x0d
  68
  69/* Extended registers */
  70#define MII_KSZPHY_CLK_CONTROL_PAD_SKEW         0x104
  71#define MII_KSZPHY_RX_DATA_PAD_SKEW             0x105
  72#define MII_KSZPHY_TX_DATA_PAD_SKEW             0x106
  73
  74#define PS_TO_REG                               200
  75
  76struct kszphy_hw_stat {
  77        const char *string;
  78        u8 reg;
  79        u8 bits;
  80};
  81
  82static struct kszphy_hw_stat kszphy_hw_stats[] = {
  83        { "phy_receive_errors", 21, 16},
  84        { "phy_idle_errors", 10, 8 },
  85};
  86
  87struct kszphy_type {
  88        u32 led_mode_reg;
  89        u16 interrupt_level_mask;
  90        bool has_broadcast_disable;
  91        bool has_nand_tree_disable;
  92        bool has_rmii_ref_clk_sel;
  93};
  94
  95struct kszphy_priv {
  96        const struct kszphy_type *type;
  97        int led_mode;
  98        bool rmii_ref_clk_sel;
  99        bool rmii_ref_clk_sel_val;
 100        u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
 101};
 102
 103static const struct kszphy_type ksz8021_type = {
 104        .led_mode_reg           = MII_KSZPHY_CTRL_2,
 105        .has_broadcast_disable  = true,
 106        .has_nand_tree_disable  = true,
 107        .has_rmii_ref_clk_sel   = true,
 108};
 109
 110static const struct kszphy_type ksz8041_type = {
 111        .led_mode_reg           = MII_KSZPHY_CTRL_1,
 112};
 113
 114static const struct kszphy_type ksz8051_type = {
 115        .led_mode_reg           = MII_KSZPHY_CTRL_2,
 116        .has_nand_tree_disable  = true,
 117};
 118
 119static const struct kszphy_type ksz8081_type = {
 120        .led_mode_reg           = MII_KSZPHY_CTRL_2,
 121        .has_broadcast_disable  = true,
 122        .has_nand_tree_disable  = true,
 123        .has_rmii_ref_clk_sel   = true,
 124};
 125
 126static const struct kszphy_type ks8737_type = {
 127        .interrupt_level_mask   = BIT(14),
 128};
 129
 130static const struct kszphy_type ksz9021_type = {
 131        .interrupt_level_mask   = BIT(14),
 132};
 133
 134static int kszphy_extended_write(struct phy_device *phydev,
 135                                u32 regnum, u16 val)
 136{
 137        phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum);
 138        return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val);
 139}
 140
 141static int kszphy_extended_read(struct phy_device *phydev,
 142                                u32 regnum)
 143{
 144        phy_write(phydev, MII_KSZPHY_EXTREG, regnum);
 145        return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
 146}
 147
 148static int kszphy_ack_interrupt(struct phy_device *phydev)
 149{
 150        /* bit[7..0] int status, which is a read and clear register. */
 151        int rc;
 152
 153        rc = phy_read(phydev, MII_KSZPHY_INTCS);
 154
 155        return (rc < 0) ? rc : 0;
 156}
 157
 158static int kszphy_config_intr(struct phy_device *phydev)
 159{
 160        const struct kszphy_type *type = phydev->drv->driver_data;
 161        int temp;
 162        u16 mask;
 163
 164        if (type && type->interrupt_level_mask)
 165                mask = type->interrupt_level_mask;
 166        else
 167                mask = KSZPHY_CTRL_INT_ACTIVE_HIGH;
 168
 169        /* set the interrupt pin active low */
 170        temp = phy_read(phydev, MII_KSZPHY_CTRL);
 171        if (temp < 0)
 172                return temp;
 173        temp &= ~mask;
 174        phy_write(phydev, MII_KSZPHY_CTRL, temp);
 175
 176        /* enable / disable interrupts */
 177        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 178                temp = KSZPHY_INTCS_ALL;
 179        else
 180                temp = 0;
 181
 182        return phy_write(phydev, MII_KSZPHY_INTCS, temp);
 183}
 184
 185static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val)
 186{
 187        int ctrl;
 188
 189        ctrl = phy_read(phydev, MII_KSZPHY_CTRL);
 190        if (ctrl < 0)
 191                return ctrl;
 192
 193        if (val)
 194                ctrl |= KSZPHY_RMII_REF_CLK_SEL;
 195        else
 196                ctrl &= ~KSZPHY_RMII_REF_CLK_SEL;
 197
 198        return phy_write(phydev, MII_KSZPHY_CTRL, ctrl);
 199}
 200
 201static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val)
 202{
 203        int rc, temp, shift;
 204
 205        switch (reg) {
 206        case MII_KSZPHY_CTRL_1:
 207                shift = 14;
 208                break;
 209        case MII_KSZPHY_CTRL_2:
 210                shift = 4;
 211                break;
 212        default:
 213                return -EINVAL;
 214        }
 215
 216        temp = phy_read(phydev, reg);
 217        if (temp < 0) {
 218                rc = temp;
 219                goto out;
 220        }
 221
 222        temp &= ~(3 << shift);
 223        temp |= val << shift;
 224        rc = phy_write(phydev, reg, temp);
 225out:
 226        if (rc < 0)
 227                phydev_err(phydev, "failed to set led mode\n");
 228
 229        return rc;
 230}
 231
 232/* Disable PHY address 0 as the broadcast address, so that it can be used as a
 233 * unique (non-broadcast) address on a shared bus.
 234 */
 235static int kszphy_broadcast_disable(struct phy_device *phydev)
 236{
 237        int ret;
 238
 239        ret = phy_read(phydev, MII_KSZPHY_OMSO);
 240        if (ret < 0)
 241                goto out;
 242
 243        ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
 244out:
 245        if (ret)
 246                phydev_err(phydev, "failed to disable broadcast address\n");
 247
 248        return ret;
 249}
 250
 251static int kszphy_nand_tree_disable(struct phy_device *phydev)
 252{
 253        int ret;
 254
 255        ret = phy_read(phydev, MII_KSZPHY_OMSO);
 256        if (ret < 0)
 257                goto out;
 258
 259        if (!(ret & KSZPHY_OMSO_NAND_TREE_ON))
 260                return 0;
 261
 262        ret = phy_write(phydev, MII_KSZPHY_OMSO,
 263                        ret & ~KSZPHY_OMSO_NAND_TREE_ON);
 264out:
 265        if (ret)
 266                phydev_err(phydev, "failed to disable NAND tree mode\n");
 267
 268        return ret;
 269}
 270
 271static int kszphy_config_init(struct phy_device *phydev)
 272{
 273        struct kszphy_priv *priv = phydev->priv;
 274        const struct kszphy_type *type;
 275        int ret;
 276
 277        if (!priv)
 278                return 0;
 279
 280        type = priv->type;
 281
 282        if (type->has_broadcast_disable)
 283                kszphy_broadcast_disable(phydev);
 284
 285        if (type->has_nand_tree_disable)
 286                kszphy_nand_tree_disable(phydev);
 287
 288        if (priv->rmii_ref_clk_sel) {
 289                ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
 290                if (ret) {
 291                        phydev_err(phydev,
 292                                   "failed to set rmii reference clock\n");
 293                        return ret;
 294                }
 295        }
 296
 297        if (priv->led_mode >= 0)
 298                kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
 299
 300        if (phy_interrupt_is_valid(phydev)) {
 301                int ctl = phy_read(phydev, MII_BMCR);
 302
 303                if (ctl < 0)
 304                        return ctl;
 305
 306                ret = phy_write(phydev, MII_BMCR, ctl & ~BMCR_ANENABLE);
 307                if (ret < 0)
 308                        return ret;
 309        }
 310
 311        return 0;
 312}
 313
 314static int ksz9021_load_values_from_of(struct phy_device *phydev,
 315                                       const struct device_node *of_node,
 316                                       u16 reg,
 317                                       const char *field1, const char *field2,
 318                                       const char *field3, const char *field4)
 319{
 320        int val1 = -1;
 321        int val2 = -2;
 322        int val3 = -3;
 323        int val4 = -4;
 324        int newval;
 325        int matches = 0;
 326
 327        if (!of_property_read_u32(of_node, field1, &val1))
 328                matches++;
 329
 330        if (!of_property_read_u32(of_node, field2, &val2))
 331                matches++;
 332
 333        if (!of_property_read_u32(of_node, field3, &val3))
 334                matches++;
 335
 336        if (!of_property_read_u32(of_node, field4, &val4))
 337                matches++;
 338
 339        if (!matches)
 340                return 0;
 341
 342        if (matches < 4)
 343                newval = kszphy_extended_read(phydev, reg);
 344        else
 345                newval = 0;
 346
 347        if (val1 != -1)
 348                newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0);
 349
 350        if (val2 != -2)
 351                newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4);
 352
 353        if (val3 != -3)
 354                newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8);
 355
 356        if (val4 != -4)
 357                newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12);
 358
 359        return kszphy_extended_write(phydev, reg, newval);
 360}
 361
 362static int ksz9021_config_init(struct phy_device *phydev)
 363{
 364        const struct device *dev = &phydev->mdio.dev;
 365        const struct device_node *of_node = dev->of_node;
 366        const struct device *dev_walker;
 367
 368        /* The Micrel driver has a deprecated option to place phy OF
 369         * properties in the MAC node. Walk up the tree of devices to
 370         * find a device with an OF node.
 371         */
 372        dev_walker = &phydev->mdio.dev;
 373        do {
 374                of_node = dev_walker->of_node;
 375                dev_walker = dev_walker->parent;
 376
 377        } while (!of_node && dev_walker);
 378
 379        if (of_node) {
 380                ksz9021_load_values_from_of(phydev, of_node,
 381                                    MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
 382                                    "txen-skew-ps", "txc-skew-ps",
 383                                    "rxdv-skew-ps", "rxc-skew-ps");
 384                ksz9021_load_values_from_of(phydev, of_node,
 385                                    MII_KSZPHY_RX_DATA_PAD_SKEW,
 386                                    "rxd0-skew-ps", "rxd1-skew-ps",
 387                                    "rxd2-skew-ps", "rxd3-skew-ps");
 388                ksz9021_load_values_from_of(phydev, of_node,
 389                                    MII_KSZPHY_TX_DATA_PAD_SKEW,
 390                                    "txd0-skew-ps", "txd1-skew-ps",
 391                                    "txd2-skew-ps", "txd3-skew-ps");
 392        }
 393        return 0;
 394}
 395
 396#define MII_KSZ9031RN_MMD_CTRL_REG      0x0d
 397#define MII_KSZ9031RN_MMD_REGDATA_REG   0x0e
 398#define OP_DATA                         1
 399#define KSZ9031_PS_TO_REG               60
 400
 401/* Extended registers */
 402/* MMD Address 0x0 */
 403#define MII_KSZ9031RN_FLP_BURST_TX_LO   3
 404#define MII_KSZ9031RN_FLP_BURST_TX_HI   4
 405
 406/* MMD Address 0x2 */
 407#define MII_KSZ9031RN_CONTROL_PAD_SKEW  4
 408#define MII_KSZ9031RN_RX_DATA_PAD_SKEW  5
 409#define MII_KSZ9031RN_TX_DATA_PAD_SKEW  6
 410#define MII_KSZ9031RN_CLK_PAD_SKEW      8
 411
 412static int ksz9031_extended_write(struct phy_device *phydev,
 413                                  u8 mode, u32 dev_addr, u32 regnum, u16 val)
 414{
 415        phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
 416        phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
 417        phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
 418        return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val);
 419}
 420
 421static int ksz9031_extended_read(struct phy_device *phydev,
 422                                 u8 mode, u32 dev_addr, u32 regnum)
 423{
 424        phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
 425        phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
 426        phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
 427        return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG);
 428}
 429
 430static int ksz9031_of_load_skew_values(struct phy_device *phydev,
 431                                       const struct device_node *of_node,
 432                                       u16 reg, size_t field_sz,
 433                                       const char *field[], u8 numfields)
 434{
 435        int val[4] = {-1, -2, -3, -4};
 436        int matches = 0;
 437        u16 mask;
 438        u16 maxval;
 439        u16 newval;
 440        int i;
 441
 442        for (i = 0; i < numfields; i++)
 443                if (!of_property_read_u32(of_node, field[i], val + i))
 444                        matches++;
 445
 446        if (!matches)
 447                return 0;
 448
 449        if (matches < numfields)
 450                newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
 451        else
 452                newval = 0;
 453
 454        maxval = (field_sz == 4) ? 0xf : 0x1f;
 455        for (i = 0; i < numfields; i++)
 456                if (val[i] != -(i + 1)) {
 457                        mask = 0xffff;
 458                        mask ^= maxval << (field_sz * i);
 459                        newval = (newval & mask) |
 460                                (((val[i] / KSZ9031_PS_TO_REG) & maxval)
 461                                        << (field_sz * i));
 462                }
 463
 464        return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
 465}
 466
 467static int ksz9031_center_flp_timing(struct phy_device *phydev)
 468{
 469        int result;
 470
 471        /* Center KSZ9031RNX FLP timing at 16ms. */
 472        result = ksz9031_extended_write(phydev, OP_DATA, 0,
 473                                        MII_KSZ9031RN_FLP_BURST_TX_HI, 0x0006);
 474        result = ksz9031_extended_write(phydev, OP_DATA, 0,
 475                                        MII_KSZ9031RN_FLP_BURST_TX_LO, 0x1A80);
 476
 477        if (result)
 478                return result;
 479
 480        return genphy_restart_aneg(phydev);
 481}
 482
 483static int ksz9031_config_init(struct phy_device *phydev)
 484{
 485        const struct device *dev = &phydev->mdio.dev;
 486        const struct device_node *of_node = dev->of_node;
 487        static const char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"};
 488        static const char *rx_data_skews[4] = {
 489                "rxd0-skew-ps", "rxd1-skew-ps",
 490                "rxd2-skew-ps", "rxd3-skew-ps"
 491        };
 492        static const char *tx_data_skews[4] = {
 493                "txd0-skew-ps", "txd1-skew-ps",
 494                "txd2-skew-ps", "txd3-skew-ps"
 495        };
 496        static const char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
 497        const struct device *dev_walker;
 498
 499        /* The Micrel driver has a deprecated option to place phy OF
 500         * properties in the MAC node. Walk up the tree of devices to
 501         * find a device with an OF node.
 502         */
 503        dev_walker = &phydev->mdio.dev;
 504        do {
 505                of_node = dev_walker->of_node;
 506                dev_walker = dev_walker->parent;
 507        } while (!of_node && dev_walker);
 508
 509        if (of_node) {
 510                ksz9031_of_load_skew_values(phydev, of_node,
 511                                MII_KSZ9031RN_CLK_PAD_SKEW, 5,
 512                                clk_skews, 2);
 513
 514                ksz9031_of_load_skew_values(phydev, of_node,
 515                                MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
 516                                control_skews, 2);
 517
 518                ksz9031_of_load_skew_values(phydev, of_node,
 519                                MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
 520                                rx_data_skews, 4);
 521
 522                ksz9031_of_load_skew_values(phydev, of_node,
 523                                MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
 524                                tx_data_skews, 4);
 525        }
 526
 527        return ksz9031_center_flp_timing(phydev);
 528}
 529
 530#define KSZ8873MLL_GLOBAL_CONTROL_4     0x06
 531#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX      BIT(6)
 532#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED       BIT(4)
 533static int ksz8873mll_read_status(struct phy_device *phydev)
 534{
 535        int regval;
 536
 537        /* dummy read */
 538        regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
 539
 540        regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
 541
 542        if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
 543                phydev->duplex = DUPLEX_HALF;
 544        else
 545                phydev->duplex = DUPLEX_FULL;
 546
 547        if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
 548                phydev->speed = SPEED_10;
 549        else
 550                phydev->speed = SPEED_100;
 551
 552        phydev->link = 1;
 553        phydev->pause = phydev->asym_pause = 0;
 554
 555        return 0;
 556}
 557
 558static int ksz9031_read_status(struct phy_device *phydev)
 559{
 560        int err;
 561        int regval;
 562
 563        err = genphy_read_status(phydev);
 564        if (err)
 565                return err;
 566
 567        /* Make sure the PHY is not broken. Read idle error count,
 568         * and reset the PHY if it is maxed out.
 569         */
 570        regval = phy_read(phydev, MII_STAT1000);
 571        if ((regval & 0xFF) == 0xFF) {
 572                phy_init_hw(phydev);
 573                phydev->link = 0;
 574        }
 575
 576        return 0;
 577}
 578
 579static int ksz8873mll_config_aneg(struct phy_device *phydev)
 580{
 581        return 0;
 582}
 583
 584/* This routine returns -1 as an indication to the caller that the
 585 * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE
 586 * MMD extended PHY registers.
 587 */
 588static int
 589ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
 590                      int regnum)
 591{
 592        return -1;
 593}
 594
 595/* This routine does nothing since the Micrel ksz9021 does not support
 596 * standard IEEE MMD extended PHY registers.
 597 */
 598static void
 599ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
 600                      int regnum, u32 val)
 601{
 602}
 603
 604static int kszphy_get_sset_count(struct phy_device *phydev)
 605{
 606        return ARRAY_SIZE(kszphy_hw_stats);
 607}
 608
 609static void kszphy_get_strings(struct phy_device *phydev, u8 *data)
 610{
 611        int i;
 612
 613        for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++) {
 614                memcpy(data + i * ETH_GSTRING_LEN,
 615                       kszphy_hw_stats[i].string, ETH_GSTRING_LEN);
 616        }
 617}
 618
 619#ifndef UINT64_MAX
 620#define UINT64_MAX              (u64)(~((u64)0))
 621#endif
 622static u64 kszphy_get_stat(struct phy_device *phydev, int i)
 623{
 624        struct kszphy_hw_stat stat = kszphy_hw_stats[i];
 625        struct kszphy_priv *priv = phydev->priv;
 626        int val;
 627        u64 ret;
 628
 629        val = phy_read(phydev, stat.reg);
 630        if (val < 0) {
 631                ret = UINT64_MAX;
 632        } else {
 633                val = val & ((1 << stat.bits) - 1);
 634                priv->stats[i] += val;
 635                ret = priv->stats[i];
 636        }
 637
 638        return ret;
 639}
 640
 641static void kszphy_get_stats(struct phy_device *phydev,
 642                             struct ethtool_stats *stats, u64 *data)
 643{
 644        int i;
 645
 646        for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++)
 647                data[i] = kszphy_get_stat(phydev, i);
 648}
 649
 650static int kszphy_resume(struct phy_device *phydev)
 651{
 652        int value;
 653
 654        mutex_lock(&phydev->lock);
 655
 656        value = phy_read(phydev, MII_BMCR);
 657        phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
 658
 659        kszphy_config_intr(phydev);
 660        mutex_unlock(&phydev->lock);
 661
 662        return 0;
 663}
 664
 665static int kszphy_probe(struct phy_device *phydev)
 666{
 667        const struct kszphy_type *type = phydev->drv->driver_data;
 668        const struct device_node *np = phydev->mdio.dev.of_node;
 669        struct kszphy_priv *priv;
 670        struct clk *clk;
 671        int ret;
 672
 673        priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
 674        if (!priv)
 675                return -ENOMEM;
 676
 677        phydev->priv = priv;
 678
 679        priv->type = type;
 680
 681        if (type->led_mode_reg) {
 682                ret = of_property_read_u32(np, "micrel,led-mode",
 683                                &priv->led_mode);
 684                if (ret)
 685                        priv->led_mode = -1;
 686
 687                if (priv->led_mode > 3) {
 688                        phydev_err(phydev, "invalid led mode: 0x%02x\n",
 689                                   priv->led_mode);
 690                        priv->led_mode = -1;
 691                }
 692        } else {
 693                priv->led_mode = -1;
 694        }
 695
 696        clk = devm_clk_get(&phydev->mdio.dev, "rmii-ref");
 697        /* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */
 698        if (!IS_ERR_OR_NULL(clk)) {
 699                unsigned long rate = clk_get_rate(clk);
 700                bool rmii_ref_clk_sel_25_mhz;
 701
 702                priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
 703                rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
 704                                "micrel,rmii-reference-clock-select-25-mhz");
 705
 706                if (rate > 24500000 && rate < 25500000) {
 707                        priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz;
 708                } else if (rate > 49500000 && rate < 50500000) {
 709                        priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
 710                } else {
 711                        phydev_err(phydev, "Clock rate out of range: %ld\n",
 712                                   rate);
 713                        return -EINVAL;
 714                }
 715        }
 716
 717        /* Support legacy board-file configuration */
 718        if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
 719                priv->rmii_ref_clk_sel = true;
 720                priv->rmii_ref_clk_sel_val = true;
 721        }
 722
 723        return 0;
 724}
 725
 726static struct phy_driver ksphy_driver[] = {
 727{
 728        .phy_id         = PHY_ID_KS8737,
 729        .phy_id_mask    = 0x00fffff0,
 730        .name           = "Micrel KS8737",
 731        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 732        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 733        .driver_data    = &ks8737_type,
 734        .config_init    = kszphy_config_init,
 735        .config_aneg    = genphy_config_aneg,
 736        .read_status    = genphy_read_status,
 737        .ack_interrupt  = kszphy_ack_interrupt,
 738        .config_intr    = kszphy_config_intr,
 739        .get_sset_count = kszphy_get_sset_count,
 740        .get_strings    = kszphy_get_strings,
 741        .get_stats      = kszphy_get_stats,
 742        .suspend        = genphy_suspend,
 743        .resume         = genphy_resume,
 744}, {
 745        .phy_id         = PHY_ID_KSZ8021,
 746        .phy_id_mask    = 0x00ffffff,
 747        .name           = "Micrel KSZ8021 or KSZ8031",
 748        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
 749                           SUPPORTED_Asym_Pause),
 750        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 751        .driver_data    = &ksz8021_type,
 752        .probe          = kszphy_probe,
 753        .config_init    = kszphy_config_init,
 754        .config_aneg    = genphy_config_aneg,
 755        .read_status    = genphy_read_status,
 756        .ack_interrupt  = kszphy_ack_interrupt,
 757        .config_intr    = kszphy_config_intr,
 758        .get_sset_count = kszphy_get_sset_count,
 759        .get_strings    = kszphy_get_strings,
 760        .get_stats      = kszphy_get_stats,
 761        .suspend        = genphy_suspend,
 762        .resume         = genphy_resume,
 763}, {
 764        .phy_id         = PHY_ID_KSZ8031,
 765        .phy_id_mask    = 0x00ffffff,
 766        .name           = "Micrel KSZ8031",
 767        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
 768                           SUPPORTED_Asym_Pause),
 769        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 770        .driver_data    = &ksz8021_type,
 771        .probe          = kszphy_probe,
 772        .config_init    = kszphy_config_init,
 773        .config_aneg    = genphy_config_aneg,
 774        .read_status    = genphy_read_status,
 775        .ack_interrupt  = kszphy_ack_interrupt,
 776        .config_intr    = kszphy_config_intr,
 777        .get_sset_count = kszphy_get_sset_count,
 778        .get_strings    = kszphy_get_strings,
 779        .get_stats      = kszphy_get_stats,
 780        .suspend        = genphy_suspend,
 781        .resume         = genphy_resume,
 782}, {
 783        .phy_id         = PHY_ID_KSZ8041,
 784        .phy_id_mask    = 0x00fffff0,
 785        .name           = "Micrel KSZ8041",
 786        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
 787                                | SUPPORTED_Asym_Pause),
 788        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 789        .driver_data    = &ksz8041_type,
 790        .probe          = kszphy_probe,
 791        .config_init    = kszphy_config_init,
 792        .config_aneg    = genphy_config_aneg,
 793        .read_status    = genphy_read_status,
 794        .ack_interrupt  = kszphy_ack_interrupt,
 795        .config_intr    = kszphy_config_intr,
 796        .get_sset_count = kszphy_get_sset_count,
 797        .get_strings    = kszphy_get_strings,
 798        .get_stats      = kszphy_get_stats,
 799        .suspend        = genphy_suspend,
 800        .resume         = genphy_resume,
 801}, {
 802        .phy_id         = PHY_ID_KSZ8041RNLI,
 803        .phy_id_mask    = 0x00fffff0,
 804        .name           = "Micrel KSZ8041RNLI",
 805        .features       = PHY_BASIC_FEATURES |
 806                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 807        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 808        .driver_data    = &ksz8041_type,
 809        .probe          = kszphy_probe,
 810        .config_init    = kszphy_config_init,
 811        .config_aneg    = genphy_config_aneg,
 812        .read_status    = genphy_read_status,
 813        .ack_interrupt  = kszphy_ack_interrupt,
 814        .config_intr    = kszphy_config_intr,
 815        .get_sset_count = kszphy_get_sset_count,
 816        .get_strings    = kszphy_get_strings,
 817        .get_stats      = kszphy_get_stats,
 818        .suspend        = genphy_suspend,
 819        .resume         = genphy_resume,
 820}, {
 821        .phy_id         = PHY_ID_KSZ8051,
 822        .phy_id_mask    = 0x00fffff0,
 823        .name           = "Micrel KSZ8051",
 824        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
 825                                | SUPPORTED_Asym_Pause),
 826        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 827        .driver_data    = &ksz8051_type,
 828        .probe          = kszphy_probe,
 829        .config_init    = kszphy_config_init,
 830        .config_aneg    = genphy_config_aneg,
 831        .read_status    = genphy_read_status,
 832        .ack_interrupt  = kszphy_ack_interrupt,
 833        .config_intr    = kszphy_config_intr,
 834        .get_sset_count = kszphy_get_sset_count,
 835        .get_strings    = kszphy_get_strings,
 836        .get_stats      = kszphy_get_stats,
 837        .suspend        = genphy_suspend,
 838        .resume         = genphy_resume,
 839}, {
 840        .phy_id         = PHY_ID_KSZ8001,
 841        .name           = "Micrel KSZ8001 or KS8721",
 842        .phy_id_mask    = 0x00ffffff,
 843        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 844        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 845        .driver_data    = &ksz8041_type,
 846        .probe          = kszphy_probe,
 847        .config_init    = kszphy_config_init,
 848        .config_aneg    = genphy_config_aneg,
 849        .read_status    = genphy_read_status,
 850        .ack_interrupt  = kszphy_ack_interrupt,
 851        .config_intr    = kszphy_config_intr,
 852        .get_sset_count = kszphy_get_sset_count,
 853        .get_strings    = kszphy_get_strings,
 854        .get_stats      = kszphy_get_stats,
 855        .suspend        = genphy_suspend,
 856        .resume         = genphy_resume,
 857}, {
 858        .phy_id         = PHY_ID_KSZ8081,
 859        .name           = "Micrel KSZ8081 or KSZ8091",
 860        .phy_id_mask    = 0x00fffff0,
 861        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 862        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 863        .driver_data    = &ksz8081_type,
 864        .probe          = kszphy_probe,
 865        .config_init    = kszphy_config_init,
 866        .config_aneg    = genphy_config_aneg,
 867        .read_status    = genphy_read_status,
 868        .ack_interrupt  = kszphy_ack_interrupt,
 869        .config_intr    = kszphy_config_intr,
 870        .get_sset_count = kszphy_get_sset_count,
 871        .get_strings    = kszphy_get_strings,
 872        .get_stats      = kszphy_get_stats,
 873        .suspend        = genphy_suspend,
 874        .resume         = kszphy_resume,
 875}, {
 876        .phy_id         = PHY_ID_KSZ8061,
 877        .name           = "Micrel KSZ8061",
 878        .phy_id_mask    = 0x00fffff0,
 879        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 880        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 881        .config_init    = kszphy_config_init,
 882        .config_aneg    = genphy_config_aneg,
 883        .read_status    = genphy_read_status,
 884        .ack_interrupt  = kszphy_ack_interrupt,
 885        .config_intr    = kszphy_config_intr,
 886        .get_sset_count = kszphy_get_sset_count,
 887        .get_strings    = kszphy_get_strings,
 888        .get_stats      = kszphy_get_stats,
 889        .suspend        = genphy_suspend,
 890        .resume         = genphy_resume,
 891}, {
 892        .phy_id         = PHY_ID_KSZ9021,
 893        .phy_id_mask    = 0x000ffffe,
 894        .name           = "Micrel KSZ9021 Gigabit PHY",
 895        .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
 896        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 897        .driver_data    = &ksz9021_type,
 898        .config_init    = ksz9021_config_init,
 899        .config_aneg    = genphy_config_aneg,
 900        .read_status    = genphy_read_status,
 901        .ack_interrupt  = kszphy_ack_interrupt,
 902        .config_intr    = kszphy_config_intr,
 903        .get_sset_count = kszphy_get_sset_count,
 904        .get_strings    = kszphy_get_strings,
 905        .get_stats      = kszphy_get_stats,
 906        .suspend        = genphy_suspend,
 907        .resume         = genphy_resume,
 908        .read_mmd_indirect = ksz9021_rd_mmd_phyreg,
 909        .write_mmd_indirect = ksz9021_wr_mmd_phyreg,
 910}, {
 911        .phy_id         = PHY_ID_KSZ9031,
 912        .phy_id_mask    = 0x00fffff0,
 913        .name           = "Micrel KSZ9031 Gigabit PHY",
 914        .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
 915        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 916        .driver_data    = &ksz9021_type,
 917        .config_init    = ksz9031_config_init,
 918        .config_aneg    = genphy_config_aneg,
 919        .read_status    = ksz9031_read_status,
 920        .ack_interrupt  = kszphy_ack_interrupt,
 921        .config_intr    = kszphy_config_intr,
 922        .get_sset_count = kszphy_get_sset_count,
 923        .get_strings    = kszphy_get_strings,
 924        .get_stats      = kszphy_get_stats,
 925        .suspend        = genphy_suspend,
 926        .resume         = genphy_resume,
 927}, {
 928        .phy_id         = PHY_ID_KSZ8873MLL,
 929        .phy_id_mask    = 0x00fffff0,
 930        .name           = "Micrel KSZ8873MLL Switch",
 931        .features       = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
 932        .flags          = PHY_HAS_MAGICANEG,
 933        .config_init    = kszphy_config_init,
 934        .config_aneg    = ksz8873mll_config_aneg,
 935        .read_status    = ksz8873mll_read_status,
 936        .get_sset_count = kszphy_get_sset_count,
 937        .get_strings    = kszphy_get_strings,
 938        .get_stats      = kszphy_get_stats,
 939        .suspend        = genphy_suspend,
 940        .resume         = genphy_resume,
 941}, {
 942        .phy_id         = PHY_ID_KSZ886X,
 943        .phy_id_mask    = 0x00fffff0,
 944        .name           = "Micrel KSZ886X Switch",
 945        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
 946        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 947        .config_init    = kszphy_config_init,
 948        .config_aneg    = genphy_config_aneg,
 949        .read_status    = genphy_read_status,
 950        .get_sset_count = kszphy_get_sset_count,
 951        .get_strings    = kszphy_get_strings,
 952        .get_stats      = kszphy_get_stats,
 953        .suspend        = genphy_suspend,
 954        .resume         = genphy_resume,
 955} };
 956
 957module_phy_driver(ksphy_driver);
 958
 959MODULE_DESCRIPTION("Micrel PHY driver");
 960MODULE_AUTHOR("David J. Choi");
 961MODULE_LICENSE("GPL");
 962
 963static struct mdio_device_id __maybe_unused micrel_tbl[] = {
 964        { PHY_ID_KSZ9021, 0x000ffffe },
 965        { PHY_ID_KSZ9031, 0x00fffff0 },
 966        { PHY_ID_KSZ8001, 0x00ffffff },
 967        { PHY_ID_KS8737, 0x00fffff0 },
 968        { PHY_ID_KSZ8021, 0x00ffffff },
 969        { PHY_ID_KSZ8031, 0x00ffffff },
 970        { PHY_ID_KSZ8041, 0x00fffff0 },
 971        { PHY_ID_KSZ8051, 0x00fffff0 },
 972        { PHY_ID_KSZ8061, 0x00fffff0 },
 973        { PHY_ID_KSZ8081, 0x00fffff0 },
 974        { PHY_ID_KSZ8873MLL, 0x00fffff0 },
 975        { PHY_ID_KSZ886X, 0x00fffff0 },
 976        { }
 977};
 978
 979MODULE_DEVICE_TABLE(mdio, micrel_tbl);
 980