linux/drivers/net/phy/dp83tc811.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Driver for the Texas Instruments DP83TC811 PHY
   4 *
   5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
   6 *
   7 */
   8
   9#include <linux/ethtool.h>
  10#include <linux/etherdevice.h>
  11#include <linux/kernel.h>
  12#include <linux/mii.h>
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <linux/phy.h>
  16#include <linux/netdevice.h>
  17
  18#define DP83TC811_PHY_ID        0x2000a253
  19#define DP83811_DEVADDR         0x1f
  20
  21#define MII_DP83811_SGMII_CTRL  0x09
  22#define MII_DP83811_INT_STAT1   0x12
  23#define MII_DP83811_INT_STAT2   0x13
  24#define MII_DP83811_INT_STAT3   0x18
  25#define MII_DP83811_RESET_CTRL  0x1f
  26
  27#define DP83811_HW_RESET        BIT(15)
  28#define DP83811_SW_RESET        BIT(14)
  29
  30/* INT_STAT1 bits */
  31#define DP83811_RX_ERR_HF_INT_EN        BIT(0)
  32#define DP83811_MS_TRAINING_INT_EN      BIT(1)
  33#define DP83811_ANEG_COMPLETE_INT_EN    BIT(2)
  34#define DP83811_ESD_EVENT_INT_EN        BIT(3)
  35#define DP83811_WOL_INT_EN              BIT(4)
  36#define DP83811_LINK_STAT_INT_EN        BIT(5)
  37#define DP83811_ENERGY_DET_INT_EN       BIT(6)
  38#define DP83811_LINK_QUAL_INT_EN        BIT(7)
  39
  40/* INT_STAT2 bits */
  41#define DP83811_JABBER_DET_INT_EN       BIT(0)
  42#define DP83811_POLARITY_INT_EN         BIT(1)
  43#define DP83811_SLEEP_MODE_INT_EN       BIT(2)
  44#define DP83811_OVERTEMP_INT_EN         BIT(3)
  45#define DP83811_OVERVOLTAGE_INT_EN      BIT(6)
  46#define DP83811_UNDERVOLTAGE_INT_EN     BIT(7)
  47
  48/* INT_STAT3 bits */
  49#define DP83811_LPS_INT_EN      BIT(0)
  50#define DP83811_NO_FRAME_INT_EN BIT(3)
  51#define DP83811_POR_DONE_INT_EN BIT(4)
  52
  53#define MII_DP83811_RXSOP1      0x04a5
  54#define MII_DP83811_RXSOP2      0x04a6
  55#define MII_DP83811_RXSOP3      0x04a7
  56
  57/* WoL Registers */
  58#define MII_DP83811_WOL_CFG     0x04a0
  59#define MII_DP83811_WOL_STAT    0x04a1
  60#define MII_DP83811_WOL_DA1     0x04a2
  61#define MII_DP83811_WOL_DA2     0x04a3
  62#define MII_DP83811_WOL_DA3     0x04a4
  63
  64/* WoL bits */
  65#define DP83811_WOL_MAGIC_EN    BIT(0)
  66#define DP83811_WOL_SECURE_ON   BIT(5)
  67#define DP83811_WOL_EN          BIT(7)
  68#define DP83811_WOL_INDICATION_SEL BIT(8)
  69#define DP83811_WOL_CLR_INDICATION BIT(11)
  70
  71/* SGMII CTRL bits */
  72#define DP83811_TDR_AUTO                BIT(8)
  73#define DP83811_SGMII_EN                BIT(12)
  74#define DP83811_SGMII_AUTO_NEG_EN       BIT(13)
  75#define DP83811_SGMII_TX_ERR_DIS        BIT(14)
  76#define DP83811_SGMII_SOFT_RESET        BIT(15)
  77
  78static int dp83811_ack_interrupt(struct phy_device *phydev)
  79{
  80        int err;
  81
  82        err = phy_read(phydev, MII_DP83811_INT_STAT1);
  83        if (err < 0)
  84                return err;
  85
  86        err = phy_read(phydev, MII_DP83811_INT_STAT2);
  87        if (err < 0)
  88                return err;
  89
  90        err = phy_read(phydev, MII_DP83811_INT_STAT3);
  91        if (err < 0)
  92                return err;
  93
  94        return 0;
  95}
  96
  97static int dp83811_set_wol(struct phy_device *phydev,
  98                           struct ethtool_wolinfo *wol)
  99{
 100        struct net_device *ndev = phydev->attached_dev;
 101        const u8 *mac;
 102        u16 value;
 103
 104        if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
 105                mac = (const u8 *)ndev->dev_addr;
 106
 107                if (!is_valid_ether_addr(mac))
 108                        return -EINVAL;
 109
 110                /* MAC addresses start with byte 5, but stored in mac[0].
 111                 * 811 PHYs store bytes 4|5, 2|3, 0|1
 112                 */
 113                phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_DA1,
 114                              (mac[1] << 8) | mac[0]);
 115                phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_DA2,
 116                              (mac[3] << 8) | mac[2]);
 117                phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_DA3,
 118                              (mac[5] << 8) | mac[4]);
 119
 120                value = phy_read_mmd(phydev, DP83811_DEVADDR,
 121                                     MII_DP83811_WOL_CFG);
 122                if (wol->wolopts & WAKE_MAGIC)
 123                        value |= DP83811_WOL_MAGIC_EN;
 124                else
 125                        value &= ~DP83811_WOL_MAGIC_EN;
 126
 127                if (wol->wolopts & WAKE_MAGICSECURE) {
 128                        phy_write_mmd(phydev, DP83811_DEVADDR,
 129                                      MII_DP83811_RXSOP1,
 130                                      (wol->sopass[1] << 8) | wol->sopass[0]);
 131                        phy_write_mmd(phydev, DP83811_DEVADDR,
 132                                      MII_DP83811_RXSOP2,
 133                                      (wol->sopass[3] << 8) | wol->sopass[2]);
 134                        phy_write_mmd(phydev, DP83811_DEVADDR,
 135                                      MII_DP83811_RXSOP3,
 136                                      (wol->sopass[5] << 8) | wol->sopass[4]);
 137                        value |= DP83811_WOL_SECURE_ON;
 138                } else {
 139                        value &= ~DP83811_WOL_SECURE_ON;
 140                }
 141
 142                /* Clear any pending WoL interrupt */
 143                phy_read(phydev, MII_DP83811_INT_STAT1);
 144
 145                value |= DP83811_WOL_EN | DP83811_WOL_INDICATION_SEL |
 146                         DP83811_WOL_CLR_INDICATION;
 147
 148                return phy_write_mmd(phydev, DP83811_DEVADDR,
 149                                     MII_DP83811_WOL_CFG, value);
 150        } else {
 151                return phy_clear_bits_mmd(phydev, DP83811_DEVADDR,
 152                                          MII_DP83811_WOL_CFG, DP83811_WOL_EN);
 153        }
 154
 155}
 156
 157static void dp83811_get_wol(struct phy_device *phydev,
 158                            struct ethtool_wolinfo *wol)
 159{
 160        u16 sopass_val;
 161        int value;
 162
 163        wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE);
 164        wol->wolopts = 0;
 165
 166        value = phy_read_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG);
 167
 168        if (value & DP83811_WOL_MAGIC_EN)
 169                wol->wolopts |= WAKE_MAGIC;
 170
 171        if (value & DP83811_WOL_SECURE_ON) {
 172                sopass_val = phy_read_mmd(phydev, DP83811_DEVADDR,
 173                                          MII_DP83811_RXSOP1);
 174                wol->sopass[0] = (sopass_val & 0xff);
 175                wol->sopass[1] = (sopass_val >> 8);
 176
 177                sopass_val = phy_read_mmd(phydev, DP83811_DEVADDR,
 178                                          MII_DP83811_RXSOP2);
 179                wol->sopass[2] = (sopass_val & 0xff);
 180                wol->sopass[3] = (sopass_val >> 8);
 181
 182                sopass_val = phy_read_mmd(phydev, DP83811_DEVADDR,
 183                                          MII_DP83811_RXSOP3);
 184                wol->sopass[4] = (sopass_val & 0xff);
 185                wol->sopass[5] = (sopass_val >> 8);
 186
 187                wol->wolopts |= WAKE_MAGICSECURE;
 188        }
 189
 190        /* WoL is not enabled so set wolopts to 0 */
 191        if (!(value & DP83811_WOL_EN))
 192                wol->wolopts = 0;
 193}
 194
 195static int dp83811_config_intr(struct phy_device *phydev)
 196{
 197        int misr_status, err;
 198
 199        if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
 200                err = dp83811_ack_interrupt(phydev);
 201                if (err)
 202                        return err;
 203
 204                misr_status = phy_read(phydev, MII_DP83811_INT_STAT1);
 205                if (misr_status < 0)
 206                        return misr_status;
 207
 208                misr_status |= (DP83811_RX_ERR_HF_INT_EN |
 209                                DP83811_MS_TRAINING_INT_EN |
 210                                DP83811_ANEG_COMPLETE_INT_EN |
 211                                DP83811_ESD_EVENT_INT_EN |
 212                                DP83811_WOL_INT_EN |
 213                                DP83811_LINK_STAT_INT_EN |
 214                                DP83811_ENERGY_DET_INT_EN |
 215                                DP83811_LINK_QUAL_INT_EN);
 216
 217                err = phy_write(phydev, MII_DP83811_INT_STAT1, misr_status);
 218                if (err < 0)
 219                        return err;
 220
 221                misr_status = phy_read(phydev, MII_DP83811_INT_STAT2);
 222                if (misr_status < 0)
 223                        return misr_status;
 224
 225                misr_status |= (DP83811_JABBER_DET_INT_EN |
 226                                DP83811_POLARITY_INT_EN |
 227                                DP83811_SLEEP_MODE_INT_EN |
 228                                DP83811_OVERTEMP_INT_EN |
 229                                DP83811_OVERVOLTAGE_INT_EN |
 230                                DP83811_UNDERVOLTAGE_INT_EN);
 231
 232                err = phy_write(phydev, MII_DP83811_INT_STAT2, misr_status);
 233                if (err < 0)
 234                        return err;
 235
 236                misr_status = phy_read(phydev, MII_DP83811_INT_STAT3);
 237                if (misr_status < 0)
 238                        return misr_status;
 239
 240                misr_status |= (DP83811_LPS_INT_EN |
 241                                DP83811_NO_FRAME_INT_EN |
 242                                DP83811_POR_DONE_INT_EN);
 243
 244                err = phy_write(phydev, MII_DP83811_INT_STAT3, misr_status);
 245
 246        } else {
 247                err = phy_write(phydev, MII_DP83811_INT_STAT1, 0);
 248                if (err < 0)
 249                        return err;
 250
 251                err = phy_write(phydev, MII_DP83811_INT_STAT2, 0);
 252                if (err < 0)
 253                        return err;
 254
 255                err = phy_write(phydev, MII_DP83811_INT_STAT3, 0);
 256                if (err < 0)
 257                        return err;
 258
 259                err = dp83811_ack_interrupt(phydev);
 260        }
 261
 262        return err;
 263}
 264
 265static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
 266{
 267        bool trigger_machine = false;
 268        int irq_status;
 269
 270        /* The INT_STAT registers 1, 2 and 3 are holding the interrupt status
 271         * in the upper half (15:8), while the lower half (7:0) is used for
 272         * controlling the interrupt enable state of those individual interrupt
 273         * sources. To determine the possible interrupt sources, just read the
 274         * INT_STAT* register and use it directly to know which interrupts have
 275         * been enabled previously or not.
 276         */
 277        irq_status = phy_read(phydev, MII_DP83811_INT_STAT1);
 278        if (irq_status < 0) {
 279                phy_error(phydev);
 280                return IRQ_NONE;
 281        }
 282        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
 283                trigger_machine = true;
 284
 285        irq_status = phy_read(phydev, MII_DP83811_INT_STAT2);
 286        if (irq_status < 0) {
 287                phy_error(phydev);
 288                return IRQ_NONE;
 289        }
 290        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
 291                trigger_machine = true;
 292
 293        irq_status = phy_read(phydev, MII_DP83811_INT_STAT3);
 294        if (irq_status < 0) {
 295                phy_error(phydev);
 296                return IRQ_NONE;
 297        }
 298        if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
 299                trigger_machine = true;
 300
 301        if (!trigger_machine)
 302                return IRQ_NONE;
 303
 304        phy_trigger_machine(phydev);
 305
 306        return IRQ_HANDLED;
 307}
 308
 309static int dp83811_config_aneg(struct phy_device *phydev)
 310{
 311        int value, err;
 312
 313        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 314                value = phy_read(phydev, MII_DP83811_SGMII_CTRL);
 315                if (phydev->autoneg == AUTONEG_ENABLE) {
 316                        err = phy_write(phydev, MII_DP83811_SGMII_CTRL,
 317                                        (DP83811_SGMII_AUTO_NEG_EN | value));
 318                        if (err < 0)
 319                                return err;
 320                } else {
 321                        err = phy_write(phydev, MII_DP83811_SGMII_CTRL,
 322                                        (~DP83811_SGMII_AUTO_NEG_EN & value));
 323                        if (err < 0)
 324                                return err;
 325                }
 326        }
 327
 328        return genphy_config_aneg(phydev);
 329}
 330
 331static int dp83811_config_init(struct phy_device *phydev)
 332{
 333        int value, err;
 334
 335        value = phy_read(phydev, MII_DP83811_SGMII_CTRL);
 336        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 337                err = phy_write(phydev, MII_DP83811_SGMII_CTRL,
 338                                        (DP83811_SGMII_EN | value));
 339        } else {
 340                err = phy_write(phydev, MII_DP83811_SGMII_CTRL,
 341                                (~DP83811_SGMII_EN & value));
 342        }
 343
 344        if (err < 0)
 345
 346                return err;
 347
 348        value = DP83811_WOL_MAGIC_EN | DP83811_WOL_SECURE_ON | DP83811_WOL_EN;
 349
 350        return phy_clear_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
 351                                  value);
 352}
 353
 354static int dp83811_phy_reset(struct phy_device *phydev)
 355{
 356        int err;
 357
 358        err = phy_write(phydev, MII_DP83811_RESET_CTRL, DP83811_HW_RESET);
 359        if (err < 0)
 360                return err;
 361
 362        return 0;
 363}
 364
 365static int dp83811_suspend(struct phy_device *phydev)
 366{
 367        int value;
 368
 369        value = phy_read_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG);
 370
 371        if (!(value & DP83811_WOL_EN))
 372                genphy_suspend(phydev);
 373
 374        return 0;
 375}
 376
 377static int dp83811_resume(struct phy_device *phydev)
 378{
 379        genphy_resume(phydev);
 380
 381        phy_set_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG,
 382                         DP83811_WOL_CLR_INDICATION);
 383
 384        return 0;
 385}
 386
 387static struct phy_driver dp83811_driver[] = {
 388        {
 389                .phy_id = DP83TC811_PHY_ID,
 390                .phy_id_mask = 0xfffffff0,
 391                .name = "TI DP83TC811",
 392                /* PHY_BASIC_FEATURES */
 393                .config_init = dp83811_config_init,
 394                .config_aneg = dp83811_config_aneg,
 395                .soft_reset = dp83811_phy_reset,
 396                .get_wol = dp83811_get_wol,
 397                .set_wol = dp83811_set_wol,
 398                .config_intr = dp83811_config_intr,
 399                .handle_interrupt = dp83811_handle_interrupt,
 400                .suspend = dp83811_suspend,
 401                .resume = dp83811_resume,
 402         },
 403};
 404module_phy_driver(dp83811_driver);
 405
 406static struct mdio_device_id __maybe_unused dp83811_tbl[] = {
 407        { DP83TC811_PHY_ID, 0xfffffff0 },
 408        { },
 409};
 410MODULE_DEVICE_TABLE(mdio, dp83811_tbl);
 411
 412MODULE_DESCRIPTION("Texas Instruments DP83TC811 PHY driver");
 413MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
 414MODULE_LICENSE("GPL");
 415