LCOV - code coverage report
Current view: top level - drivers/net/phy - phy.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 17 316 5.4 %
Date: 2014-02-18 Functions: 1 26 3.8 %
Branches: 9 235 3.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * drivers/net/phy/phy.c
       3                 :            :  *
       4                 :            :  * Framework for configuring and reading PHY devices
       5                 :            :  * Based on code in sungem_phy.c and gianfar_phy.c
       6                 :            :  *
       7                 :            :  * Author: Andy Fleming
       8                 :            :  *
       9                 :            :  * Copyright (c) 2004 Freescale Semiconductor, Inc.
      10                 :            :  * Copyright (c) 2006, 2007  Maciej W. Rozycki
      11                 :            :  *
      12                 :            :  * This program is free software; you can redistribute  it and/or modify it
      13                 :            :  * under  the terms of  the GNU General  Public License as published by the
      14                 :            :  * Free Software Foundation;  either version 2 of the  License, or (at your
      15                 :            :  * option) any later version.
      16                 :            :  *
      17                 :            :  */
      18                 :            : 
      19                 :            : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      20                 :            : 
      21                 :            : #include <linux/kernel.h>
      22                 :            : #include <linux/string.h>
      23                 :            : #include <linux/errno.h>
      24                 :            : #include <linux/unistd.h>
      25                 :            : #include <linux/interrupt.h>
      26                 :            : #include <linux/init.h>
      27                 :            : #include <linux/delay.h>
      28                 :            : #include <linux/netdevice.h>
      29                 :            : #include <linux/etherdevice.h>
      30                 :            : #include <linux/skbuff.h>
      31                 :            : #include <linux/mm.h>
      32                 :            : #include <linux/module.h>
      33                 :            : #include <linux/mii.h>
      34                 :            : #include <linux/ethtool.h>
      35                 :            : #include <linux/phy.h>
      36                 :            : #include <linux/timer.h>
      37                 :            : #include <linux/workqueue.h>
      38                 :            : #include <linux/mdio.h>
      39                 :            : 
      40                 :            : #include <linux/atomic.h>
      41                 :            : #include <asm/io.h>
      42                 :            : #include <asm/irq.h>
      43                 :            : #include <asm/uaccess.h>
      44                 :            : 
      45                 :            : /**
      46                 :            :  * phy_print_status - Convenience function to print out the current phy status
      47                 :            :  * @phydev: the phy_device struct
      48                 :            :  */
      49                 :          0 : void phy_print_status(struct phy_device *phydev)
      50                 :            : {
      51         [ #  # ]:          0 :         if (phydev->link)
      52         [ #  # ]:          0 :                 pr_info("%s - Link is Up - %d/%s\n",
      53                 :            :                         dev_name(&phydev->dev),
      54                 :            :                         phydev->speed,
      55                 :            :                         DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
      56                 :            :         else
      57                 :          0 :                 pr_info("%s - Link is Down\n", dev_name(&phydev->dev));
      58                 :          0 : }
      59                 :            : EXPORT_SYMBOL(phy_print_status);
      60                 :            : 
      61                 :            : /**
      62                 :            :  * phy_clear_interrupt - Ack the phy device's interrupt
      63                 :            :  * @phydev: the phy_device struct
      64                 :            :  *
      65                 :            :  * If the @phydev driver has an ack_interrupt function, call it to
      66                 :            :  * ack and clear the phy device's interrupt.
      67                 :            :  *
      68                 :            :  * Returns 0 on success on < 0 on error.
      69                 :            :  */
      70                 :            : static int phy_clear_interrupt(struct phy_device *phydev)
      71                 :            : {
      72                 :            :         int err = 0;
      73                 :            : 
      74 [ #  # ][ #  # ]:          0 :         if (phydev->drv->ack_interrupt)
         [ #  # ][ #  # ]
      75                 :          0 :                 err = phydev->drv->ack_interrupt(phydev);
      76                 :            : 
      77                 :            :         return err;
      78                 :            : }
      79                 :            : 
      80                 :            : /**
      81                 :            :  * phy_config_interrupt - configure the PHY device for the requested interrupts
      82                 :            :  * @phydev: the phy_device struct
      83                 :            :  * @interrupts: interrupt flags to configure for this @phydev
      84                 :            :  *
      85                 :            :  * Returns 0 on success on < 0 on error.
      86                 :            :  */
      87                 :            : static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
      88                 :            : {
      89                 :            :         int err = 0;
      90                 :            : 
      91                 :          0 :         phydev->interrupts = interrupts;
      92 [ #  # ][ #  # ]:          0 :         if (phydev->drv->config_intr)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      93                 :          0 :                 err = phydev->drv->config_intr(phydev);
      94                 :            : 
      95                 :            :         return err;
      96                 :            : }
      97                 :            : 
      98                 :            : 
      99                 :            : /**
     100                 :            :  * phy_aneg_done - return auto-negotiation status
     101                 :            :  * @phydev: target phy_device struct
     102                 :            :  *
     103                 :            :  * Description: Reads the status register and returns 0 either if
     104                 :            :  *   auto-negotiation is incomplete, or if there was an error.
     105                 :            :  *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
     106                 :            :  */
     107                 :          0 : static inline int phy_aneg_done(struct phy_device *phydev)
     108                 :            : {
     109                 :            :         int retval;
     110                 :            : 
     111                 :            :         retval = phy_read(phydev, MII_BMSR);
     112                 :            : 
     113 [ #  # ][ #  # ]:          0 :         return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
     114                 :            : }
     115                 :            : 
     116                 :            : /* A structure for mapping a particular speed and duplex
     117                 :            :  * combination to a particular SUPPORTED and ADVERTISED value */
     118                 :            : struct phy_setting {
     119                 :            :         int speed;
     120                 :            :         int duplex;
     121                 :            :         u32 setting;
     122                 :            : };
     123                 :            : 
     124                 :            : /* A mapping of all SUPPORTED settings to speed/duplex */
     125                 :            : static const struct phy_setting settings[] = {
     126                 :            :         {
     127                 :            :                 .speed = 10000,
     128                 :            :                 .duplex = DUPLEX_FULL,
     129                 :            :                 .setting = SUPPORTED_10000baseT_Full,
     130                 :            :         },
     131                 :            :         {
     132                 :            :                 .speed = SPEED_1000,
     133                 :            :                 .duplex = DUPLEX_FULL,
     134                 :            :                 .setting = SUPPORTED_1000baseT_Full,
     135                 :            :         },
     136                 :            :         {
     137                 :            :                 .speed = SPEED_1000,
     138                 :            :                 .duplex = DUPLEX_HALF,
     139                 :            :                 .setting = SUPPORTED_1000baseT_Half,
     140                 :            :         },
     141                 :            :         {
     142                 :            :                 .speed = SPEED_100,
     143                 :            :                 .duplex = DUPLEX_FULL,
     144                 :            :                 .setting = SUPPORTED_100baseT_Full,
     145                 :            :         },
     146                 :            :         {
     147                 :            :                 .speed = SPEED_100,
     148                 :            :                 .duplex = DUPLEX_HALF,
     149                 :            :                 .setting = SUPPORTED_100baseT_Half,
     150                 :            :         },
     151                 :            :         {
     152                 :            :                 .speed = SPEED_10,
     153                 :            :                 .duplex = DUPLEX_FULL,
     154                 :            :                 .setting = SUPPORTED_10baseT_Full,
     155                 :            :         },
     156                 :            :         {
     157                 :            :                 .speed = SPEED_10,
     158                 :            :                 .duplex = DUPLEX_HALF,
     159                 :            :                 .setting = SUPPORTED_10baseT_Half,
     160                 :            :         },
     161                 :            : };
     162                 :            : 
     163                 :            : #define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
     164                 :            : 
     165                 :            : /**
     166                 :            :  * phy_find_setting - find a PHY settings array entry that matches speed & duplex
     167                 :            :  * @speed: speed to match
     168                 :            :  * @duplex: duplex to match
     169                 :            :  *
     170                 :            :  * Description: Searches the settings array for the setting which
     171                 :            :  *   matches the desired speed and duplex, and returns the index
     172                 :            :  *   of that setting.  Returns the index of the last setting if
     173                 :            :  *   none of the others match.
     174                 :            :  */
     175                 :            : static inline int phy_find_setting(int speed, int duplex)
     176                 :            : {
     177                 :            :         int idx = 0;
     178                 :            : 
     179 [ #  # ][ #  # ]:          0 :         while (idx < ARRAY_SIZE(settings) &&
         [ #  # ][ #  # ]
     180 [ #  # ][ #  # ]:          0 :                         (settings[idx].speed != speed ||
     181                 :          0 :                         settings[idx].duplex != duplex))
     182                 :          0 :                 idx++;
     183                 :            : 
     184                 :          0 :         return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
     185                 :            : }
     186                 :            : 
     187                 :            : /**
     188                 :            :  * phy_find_valid - find a PHY setting that matches the requested features mask
     189                 :            :  * @idx: The first index in settings[] to search
     190                 :            :  * @features: A mask of the valid settings
     191                 :            :  *
     192                 :            :  * Description: Returns the index of the first valid setting less
     193                 :            :  *   than or equal to the one pointed to by idx, as determined by
     194                 :            :  *   the mask in features.  Returns the index of the last setting
     195                 :            :  *   if nothing else matches.
     196                 :            :  */
     197                 :            : static inline int phy_find_valid(int idx, u32 features)
     198                 :            : {
     199 [ #  # ][ #  # ]:          0 :         while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
     200                 :          0 :                 idx++;
     201                 :            : 
     202                 :          0 :         return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
     203                 :            : }
     204                 :            : 
     205                 :            : /**
     206                 :            :  * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex
     207                 :            :  * @phydev: the target phy_device struct
     208                 :            :  *
     209                 :            :  * Description: Make sure the PHY is set to supported speeds and
     210                 :            :  *   duplexes.  Drop down by one in this order:  1000/FULL,
     211                 :            :  *   1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF.
     212                 :            :  */
     213                 :          0 : static void phy_sanitize_settings(struct phy_device *phydev)
     214                 :            : {
     215                 :          0 :         u32 features = phydev->supported;
     216                 :            :         int idx;
     217                 :            : 
     218                 :            :         /* Sanitize settings based on PHY capabilities */
     219         [ #  # ]:          0 :         if ((features & SUPPORTED_Autoneg) == 0)
     220                 :          0 :                 phydev->autoneg = AUTONEG_DISABLE;
     221                 :            : 
     222                 :          0 :         idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
     223                 :            :                         features);
     224                 :            : 
     225                 :          0 :         phydev->speed = settings[idx].speed;
     226                 :          0 :         phydev->duplex = settings[idx].duplex;
     227                 :          0 : }
     228                 :            : 
     229                 :            : /**
     230                 :            :  * phy_ethtool_sset - generic ethtool sset function, handles all the details
     231                 :            :  * @phydev: target phy_device struct
     232                 :            :  * @cmd: ethtool_cmd
     233                 :            :  *
     234                 :            :  * A few notes about parameter checking:
     235                 :            :  * - We don't set port or transceiver, so we don't care what they
     236                 :            :  *   were set to.
     237                 :            :  * - phy_start_aneg() will make sure forced settings are sane, and
     238                 :            :  *   choose the next best ones from the ones selected, so we don't
     239                 :            :  *   care if ethtool tries to give us bad values.
     240                 :            :  */
     241                 :          0 : int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
     242                 :            : {
     243                 :            :         u32 speed = ethtool_cmd_speed(cmd);
     244                 :            : 
     245         [ #  # ]:          0 :         if (cmd->phy_address != phydev->addr)
     246                 :            :                 return -EINVAL;
     247                 :            : 
     248                 :            :         /* We make sure that we don't pass unsupported
     249                 :            :          * values in to the PHY */
     250                 :          0 :         cmd->advertising &= phydev->supported;
     251                 :            : 
     252                 :            :         /* Verify the settings we care about. */
     253         [ #  # ]:          0 :         if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
     254                 :            :                 return -EINVAL;
     255                 :            : 
     256 [ #  # ][ #  # ]:          0 :         if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
     257                 :            :                 return -EINVAL;
     258                 :            : 
     259 [ #  # ][ #  # ]:          0 :         if (cmd->autoneg == AUTONEG_DISABLE &&
     260                 :          0 :             ((speed != SPEED_1000 &&
     261         [ #  # ]:          0 :               speed != SPEED_100 &&
     262         [ #  # ]:          0 :               speed != SPEED_10) ||
     263                 :          0 :              (cmd->duplex != DUPLEX_HALF &&
     264                 :            :               cmd->duplex != DUPLEX_FULL)))
     265                 :            :                 return -EINVAL;
     266                 :            : 
     267                 :          0 :         phydev->autoneg = cmd->autoneg;
     268                 :            : 
     269                 :          0 :         phydev->speed = speed;
     270                 :            : 
     271                 :          0 :         phydev->advertising = cmd->advertising;
     272                 :            : 
     273         [ #  # ]:          0 :         if (AUTONEG_ENABLE == cmd->autoneg)
     274                 :          0 :                 phydev->advertising |= ADVERTISED_Autoneg;
     275                 :            :         else
     276                 :          0 :                 phydev->advertising &= ~ADVERTISED_Autoneg;
     277                 :            : 
     278                 :          0 :         phydev->duplex = cmd->duplex;
     279                 :            : 
     280                 :            :         /* Restart the PHY */
     281                 :          0 :         phy_start_aneg(phydev);
     282                 :            : 
     283                 :          0 :         return 0;
     284                 :            : }
     285                 :            : EXPORT_SYMBOL(phy_ethtool_sset);
     286                 :            : 
     287                 :          0 : int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
     288                 :            : {
     289                 :          0 :         cmd->supported = phydev->supported;
     290                 :            : 
     291                 :          0 :         cmd->advertising = phydev->advertising;
     292                 :            : 
     293                 :          0 :         ethtool_cmd_speed_set(cmd, phydev->speed);
     294                 :          0 :         cmd->duplex = phydev->duplex;
     295                 :          0 :         cmd->port = PORT_MII;
     296                 :          0 :         cmd->phy_address = phydev->addr;
     297         [ #  # ]:          0 :         cmd->transceiver = phy_is_internal(phydev) ?
     298                 :            :                 XCVR_INTERNAL : XCVR_EXTERNAL;
     299                 :          0 :         cmd->autoneg = phydev->autoneg;
     300                 :            : 
     301                 :          0 :         return 0;
     302                 :            : }
     303                 :            : EXPORT_SYMBOL(phy_ethtool_gset);
     304                 :            : 
     305                 :            : /**
     306                 :            :  * phy_mii_ioctl - generic PHY MII ioctl interface
     307                 :            :  * @phydev: the phy_device struct
     308                 :            :  * @ifr: &struct ifreq for socket ioctl's
     309                 :            :  * @cmd: ioctl cmd to execute
     310                 :            :  *
     311                 :            :  * Note that this function is currently incompatible with the
     312                 :            :  * PHYCONTROL layer.  It changes registers without regard to
     313                 :            :  * current state.  Use at own risk.
     314                 :            :  */
     315                 :          0 : int phy_mii_ioctl(struct phy_device *phydev,
     316                 :            :                 struct ifreq *ifr, int cmd)
     317                 :            : {
     318                 :            :         struct mii_ioctl_data *mii_data = if_mii(ifr);
     319                 :          0 :         u16 val = mii_data->val_in;
     320                 :            : 
     321   [ #  #  #  #  :          0 :         switch (cmd) {
                      # ]
     322                 :            :         case SIOCGMIIPHY:
     323                 :          0 :                 mii_data->phy_id = phydev->addr;
     324                 :            :                 /* fall through */
     325                 :            : 
     326                 :            :         case SIOCGMIIREG:
     327                 :          0 :                 mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
     328                 :          0 :                                                  mii_data->reg_num);
     329                 :          0 :                 break;
     330                 :            : 
     331                 :            :         case SIOCSMIIREG:
     332         [ #  # ]:          0 :                 if (mii_data->phy_id == phydev->addr) {
     333      [ #  #  # ]:          0 :                         switch(mii_data->reg_num) {
     334                 :            :                         case MII_BMCR:
     335         [ #  # ]:          0 :                                 if ((val & (BMCR_RESET|BMCR_ANENABLE)) == 0)
     336                 :          0 :                                         phydev->autoneg = AUTONEG_DISABLE;
     337                 :            :                                 else
     338                 :          0 :                                         phydev->autoneg = AUTONEG_ENABLE;
     339 [ #  # ][ #  # ]:          0 :                                 if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
     340                 :          0 :                                         phydev->duplex = DUPLEX_FULL;
     341                 :            :                                 else
     342                 :          0 :                                         phydev->duplex = DUPLEX_HALF;
     343 [ #  # ][ #  # ]:          0 :                                 if ((!phydev->autoneg) &&
     344                 :          0 :                                                 (val & BMCR_SPEED1000))
     345                 :          0 :                                         phydev->speed = SPEED_1000;
     346 [ #  # ][ #  # ]:          0 :                                 else if ((!phydev->autoneg) &&
     347                 :          0 :                                                 (val & BMCR_SPEED100))
     348                 :          0 :                                         phydev->speed = SPEED_100;
     349                 :            :                                 break;
     350                 :            :                         case MII_ADVERTISE:
     351                 :          0 :                                 phydev->advertising = val;
     352                 :          0 :                                 break;
     353                 :            :                         default:
     354                 :            :                                 /* do nothing */
     355                 :            :                                 break;
     356                 :            :                         }
     357                 :            :                 }
     358                 :            : 
     359                 :          0 :                 mdiobus_write(phydev->bus, mii_data->phy_id,
     360                 :          0 :                               mii_data->reg_num, val);
     361                 :            : 
     362 [ #  # ][ #  # ]:          0 :                 if (mii_data->reg_num == MII_BMCR &&
     363         [ #  # ]:          0 :                     val & BMCR_RESET &&
     364                 :          0 :                     phydev->drv->config_init) {
     365                 :          0 :                         phy_scan_fixups(phydev);
     366                 :          0 :                         phydev->drv->config_init(phydev);
     367                 :            :                 }
     368                 :            :                 break;
     369                 :            : 
     370                 :            :         case SIOCSHWTSTAMP:
     371         [ #  # ]:          0 :                 if (phydev->drv->hwtstamp)
     372                 :          0 :                         return phydev->drv->hwtstamp(phydev, ifr);
     373                 :            :                 /* fall through */
     374                 :            : 
     375                 :            :         default:
     376                 :            :                 return -EOPNOTSUPP;
     377                 :            :         }
     378                 :            : 
     379                 :            :         return 0;
     380                 :            : }
     381                 :            : EXPORT_SYMBOL(phy_mii_ioctl);
     382                 :            : 
     383                 :            : /**
     384                 :            :  * phy_start_aneg - start auto-negotiation for this PHY device
     385                 :            :  * @phydev: the phy_device struct
     386                 :            :  *
     387                 :            :  * Description: Sanitizes the settings (if we're not autonegotiating
     388                 :            :  *   them), and then calls the driver's config_aneg function.
     389                 :            :  *   If the PHYCONTROL Layer is operating, we change the state to
     390                 :            :  *   reflect the beginning of Auto-negotiation or forcing.
     391                 :            :  */
     392                 :          0 : int phy_start_aneg(struct phy_device *phydev)
     393                 :            : {
     394                 :            :         int err;
     395                 :            : 
     396                 :          0 :         mutex_lock(&phydev->lock);
     397                 :            : 
     398         [ #  # ]:          0 :         if (AUTONEG_DISABLE == phydev->autoneg)
     399                 :          0 :                 phy_sanitize_settings(phydev);
     400                 :            : 
     401                 :          0 :         err = phydev->drv->config_aneg(phydev);
     402                 :            : 
     403         [ #  # ]:          0 :         if (err < 0)
     404                 :            :                 goto out_unlock;
     405                 :            : 
     406         [ #  # ]:          0 :         if (phydev->state != PHY_HALTED) {
     407         [ #  # ]:          0 :                 if (AUTONEG_ENABLE == phydev->autoneg) {
     408                 :          0 :                         phydev->state = PHY_AN;
     409                 :          0 :                         phydev->link_timeout = PHY_AN_TIMEOUT;
     410                 :            :                 } else {
     411                 :          0 :                         phydev->state = PHY_FORCING;
     412                 :          0 :                         phydev->link_timeout = PHY_FORCE_TIMEOUT;
     413                 :            :                 }
     414                 :            :         }
     415                 :            : 
     416                 :            : out_unlock:
     417                 :          0 :         mutex_unlock(&phydev->lock);
     418                 :          0 :         return err;
     419                 :            : }
     420                 :            : EXPORT_SYMBOL(phy_start_aneg);
     421                 :            : 
     422                 :            : 
     423                 :            : /**
     424                 :            :  * phy_start_machine - start PHY state machine tracking
     425                 :            :  * @phydev: the phy_device struct
     426                 :            :  * @handler: callback function for state change notifications
     427                 :            :  *
     428                 :            :  * Description: The PHY infrastructure can run a state machine
     429                 :            :  *   which tracks whether the PHY is starting up, negotiating,
     430                 :            :  *   etc.  This function starts the timer which tracks the state
     431                 :            :  *   of the PHY.  If you want to be notified when the state changes,
     432                 :            :  *   pass in the callback @handler, otherwise, pass NULL.  If you
     433                 :            :  *   want to maintain your own state machine, do not call this
     434                 :            :  *   function.
     435                 :            :  */
     436                 :          0 : void phy_start_machine(struct phy_device *phydev,
     437                 :            :                 void (*handler)(struct net_device *))
     438                 :            : {
     439                 :          0 :         phydev->adjust_state = handler;
     440                 :            : 
     441                 :          0 :         queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
     442                 :          0 : }
     443                 :            : 
     444                 :            : /**
     445                 :            :  * phy_stop_machine - stop the PHY state machine tracking
     446                 :            :  * @phydev: target phy_device struct
     447                 :            :  *
     448                 :            :  * Description: Stops the state machine timer, sets the state to UP
     449                 :            :  *   (unless it wasn't up yet). This function must be called BEFORE
     450                 :            :  *   phy_detach.
     451                 :            :  */
     452                 :          0 : void phy_stop_machine(struct phy_device *phydev)
     453                 :            : {
     454                 :          0 :         cancel_delayed_work_sync(&phydev->state_queue);
     455                 :            : 
     456                 :          0 :         mutex_lock(&phydev->lock);
     457         [ #  # ]:          0 :         if (phydev->state > PHY_UP)
     458                 :          0 :                 phydev->state = PHY_UP;
     459                 :          0 :         mutex_unlock(&phydev->lock);
     460                 :            : 
     461                 :          0 :         phydev->adjust_state = NULL;
     462                 :          0 : }
     463                 :            : 
     464                 :            : /**
     465                 :            :  * phy_error - enter HALTED state for this PHY device
     466                 :            :  * @phydev: target phy_device struct
     467                 :            :  *
     468                 :            :  * Moves the PHY to the HALTED state in response to a read
     469                 :            :  * or write error, and tells the controller the link is down.
     470                 :            :  * Must not be called from interrupt context, or while the
     471                 :            :  * phydev->lock is held.
     472                 :            :  */
     473                 :            : static void phy_error(struct phy_device *phydev)
     474                 :            : {
     475                 :          0 :         mutex_lock(&phydev->lock);
     476                 :          0 :         phydev->state = PHY_HALTED;
     477                 :          0 :         mutex_unlock(&phydev->lock);
     478                 :            : }
     479                 :            : 
     480                 :            : /**
     481                 :            :  * phy_interrupt - PHY interrupt handler
     482                 :            :  * @irq: interrupt line
     483                 :            :  * @phy_dat: phy_device pointer
     484                 :            :  *
     485                 :            :  * Description: When a PHY interrupt occurs, the handler disables
     486                 :            :  * interrupts, and schedules a work task to clear the interrupt.
     487                 :            :  */
     488                 :          0 : static irqreturn_t phy_interrupt(int irq, void *phy_dat)
     489                 :            : {
     490                 :            :         struct phy_device *phydev = phy_dat;
     491                 :            : 
     492         [ #  # ]:          0 :         if (PHY_HALTED == phydev->state)
     493                 :            :                 return IRQ_NONE;                /* It can't be ours.  */
     494                 :            : 
     495                 :            :         /* The MDIO bus is not allowed to be written in interrupt
     496                 :            :          * context, so we need to disable the irq here.  A work
     497                 :            :          * queue will write the PHY to disable and clear the
     498                 :            :          * interrupt, and then reenable the irq line. */
     499                 :          0 :         disable_irq_nosync(irq);
     500                 :          0 :         atomic_inc(&phydev->irq_disable);
     501                 :            : 
     502                 :          0 :         queue_work(system_power_efficient_wq, &phydev->phy_queue);
     503                 :            : 
     504                 :          0 :         return IRQ_HANDLED;
     505                 :            : }
     506                 :            : 
     507                 :            : /**
     508                 :            :  * phy_enable_interrupts - Enable the interrupts from the PHY side
     509                 :            :  * @phydev: target phy_device struct
     510                 :            :  */
     511                 :          0 : static int phy_enable_interrupts(struct phy_device *phydev)
     512                 :            : {
     513                 :            :         int err;
     514                 :            : 
     515                 :            :         err = phy_clear_interrupt(phydev);
     516                 :            : 
     517         [ #  # ]:          0 :         if (err < 0)
     518                 :            :                 return err;
     519                 :            : 
     520                 :            :         err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
     521                 :            : 
     522                 :          0 :         return err;
     523                 :            : }
     524                 :            : 
     525                 :            : /**
     526                 :            :  * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
     527                 :            :  * @phydev: target phy_device struct
     528                 :            :  */
     529                 :          0 : static int phy_disable_interrupts(struct phy_device *phydev)
     530                 :            : {
     531                 :            :         int err;
     532                 :            : 
     533                 :            :         /* Disable PHY interrupts */
     534                 :            :         err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
     535                 :            : 
     536         [ #  # ]:          0 :         if (err)
     537                 :            :                 goto phy_err;
     538                 :            : 
     539                 :            :         /* Clear the interrupt */
     540                 :            :         err = phy_clear_interrupt(phydev);
     541                 :            : 
     542         [ #  # ]:          0 :         if (err)
     543                 :            :                 goto phy_err;
     544                 :            : 
     545                 :            :         return 0;
     546                 :            : 
     547                 :            : phy_err:
     548                 :            :         phy_error(phydev);
     549                 :            : 
     550                 :          0 :         return err;
     551                 :            : }
     552                 :            : 
     553                 :            : /**
     554                 :            :  * phy_start_interrupts - request and enable interrupts for a PHY device
     555                 :            :  * @phydev: target phy_device struct
     556                 :            :  *
     557                 :            :  * Description: Request the interrupt for the given PHY.
     558                 :            :  *   If this fails, then we set irq to PHY_POLL.
     559                 :            :  *   Otherwise, we enable the interrupts in the PHY.
     560                 :            :  *   This should only be called with a valid IRQ number.
     561                 :            :  *   Returns 0 on success or < 0 on error.
     562                 :            :  */
     563                 :          0 : int phy_start_interrupts(struct phy_device *phydev)
     564                 :            : {
     565                 :            :         int err = 0;
     566                 :            : 
     567                 :          0 :         atomic_set(&phydev->irq_disable, 0);
     568         [ #  # ]:          0 :         if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
     569                 :            :                         phydev) < 0) {
     570                 :          0 :                 pr_warn("%s: Can't get IRQ %d (PHY)\n",
     571                 :            :                         phydev->bus->name, phydev->irq);
     572                 :          0 :                 phydev->irq = PHY_POLL;
     573                 :          0 :                 return 0;
     574                 :            :         }
     575                 :            : 
     576                 :          0 :         err = phy_enable_interrupts(phydev);
     577                 :            : 
     578                 :          0 :         return err;
     579                 :            : }
     580                 :            : EXPORT_SYMBOL(phy_start_interrupts);
     581                 :            : 
     582                 :            : /**
     583                 :            :  * phy_stop_interrupts - disable interrupts from a PHY device
     584                 :            :  * @phydev: target phy_device struct
     585                 :            :  */
     586                 :          0 : int phy_stop_interrupts(struct phy_device *phydev)
     587                 :            : {
     588                 :            :         int err;
     589                 :            : 
     590                 :          0 :         err = phy_disable_interrupts(phydev);
     591                 :            : 
     592         [ #  # ]:          0 :         if (err)
     593                 :            :                 phy_error(phydev);
     594                 :            : 
     595                 :          0 :         free_irq(phydev->irq, phydev);
     596                 :            : 
     597                 :            :         /*
     598                 :            :          * Cannot call flush_scheduled_work() here as desired because
     599                 :            :          * of rtnl_lock(), but we do not really care about what would
     600                 :            :          * be done, except from enable_irq(), so cancel any work
     601                 :            :          * possibly pending and take care of the matter below.
     602                 :            :          */
     603                 :          0 :         cancel_work_sync(&phydev->phy_queue);
     604                 :            :         /*
     605                 :            :          * If work indeed has been cancelled, disable_irq() will have
     606                 :            :          * been left unbalanced from phy_interrupt() and enable_irq()
     607                 :            :          * has to be called so that other devices on the line work.
     608                 :            :          */
     609         [ #  # ]:          0 :         while (atomic_dec_return(&phydev->irq_disable) >= 0)
     610                 :          0 :                 enable_irq(phydev->irq);
     611                 :            : 
     612                 :          0 :         return err;
     613                 :            : }
     614                 :            : EXPORT_SYMBOL(phy_stop_interrupts);
     615                 :            : 
     616                 :            : 
     617                 :            : /**
     618                 :            :  * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
     619                 :            :  * @work: work_struct that describes the work to be done
     620                 :            :  */
     621                 :          0 : void phy_change(struct work_struct *work)
     622                 :            : {
     623                 :            :         int err;
     624                 :          0 :         struct phy_device *phydev =
     625                 :            :                 container_of(work, struct phy_device, phy_queue);
     626                 :            : 
     627   [ #  #  #  # ]:          0 :         if (phydev->drv->did_interrupt &&
     628                 :          0 :             !phydev->drv->did_interrupt(phydev))
     629                 :            :                 goto ignore;
     630                 :            : 
     631                 :          0 :         err = phy_disable_interrupts(phydev);
     632                 :            : 
     633         [ #  # ]:          0 :         if (err)
     634                 :            :                 goto phy_err;
     635                 :            : 
     636                 :          0 :         mutex_lock(&phydev->lock);
     637         [ #  # ]:          0 :         if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
     638                 :          0 :                 phydev->state = PHY_CHANGELINK;
     639                 :          0 :         mutex_unlock(&phydev->lock);
     640                 :            : 
     641                 :          0 :         atomic_dec(&phydev->irq_disable);
     642                 :          0 :         enable_irq(phydev->irq);
     643                 :            : 
     644                 :            :         /* Reenable interrupts */
     645         [ #  # ]:          0 :         if (PHY_HALTED != phydev->state)
     646                 :            :                 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
     647                 :            : 
     648         [ #  # ]:          0 :         if (err)
     649                 :            :                 goto irq_enable_err;
     650                 :            : 
     651                 :            :         /* reschedule state queue work to run as soon as possible */
     652                 :          0 :         cancel_delayed_work_sync(&phydev->state_queue);
     653                 :          0 :         queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
     654                 :            : 
     655                 :            :         return;
     656                 :            : 
     657                 :            : ignore:
     658                 :          0 :         atomic_dec(&phydev->irq_disable);
     659                 :          0 :         enable_irq(phydev->irq);
     660                 :          0 :         return;
     661                 :            : 
     662                 :            : irq_enable_err:
     663                 :          0 :         disable_irq(phydev->irq);
     664                 :            :         atomic_inc(&phydev->irq_disable);
     665                 :            : phy_err:
     666                 :            :         phy_error(phydev);
     667                 :            : }
     668                 :            : 
     669                 :            : /**
     670                 :            :  * phy_stop - Bring down the PHY link, and stop checking the status
     671                 :            :  * @phydev: target phy_device struct
     672                 :            :  */
     673                 :          0 : void phy_stop(struct phy_device *phydev)
     674                 :            : {
     675                 :          0 :         mutex_lock(&phydev->lock);
     676                 :            : 
     677         [ #  # ]:          0 :         if (PHY_HALTED == phydev->state)
     678                 :            :                 goto out_unlock;
     679                 :            : 
     680         [ #  # ]:          0 :         if (phy_interrupt_is_valid(phydev)) {
     681                 :            :                 /* Disable PHY Interrupts */
     682                 :            :                 phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
     683                 :            : 
     684                 :            :                 /* Clear any pending interrupts */
     685                 :            :                 phy_clear_interrupt(phydev);
     686                 :            :         }
     687                 :            : 
     688                 :          0 :         phydev->state = PHY_HALTED;
     689                 :            : 
     690                 :            : out_unlock:
     691                 :          0 :         mutex_unlock(&phydev->lock);
     692                 :            : 
     693                 :            :         /*
     694                 :            :          * Cannot call flush_scheduled_work() here as desired because
     695                 :            :          * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change()
     696                 :            :          * will not reenable interrupts.
     697                 :            :          */
     698                 :          0 : }
     699                 :            : 
     700                 :            : 
     701                 :            : /**
     702                 :            :  * phy_start - start or restart a PHY device
     703                 :            :  * @phydev: target phy_device struct
     704                 :            :  *
     705                 :            :  * Description: Indicates the attached device's readiness to
     706                 :            :  *   handle PHY-related work.  Used during startup to start the
     707                 :            :  *   PHY, and after a call to phy_stop() to resume operation.
     708                 :            :  *   Also used to indicate the MDIO bus has cleared an error
     709                 :            :  *   condition.
     710                 :            :  */
     711                 :          0 : void phy_start(struct phy_device *phydev)
     712                 :            : {
     713                 :          0 :         mutex_lock(&phydev->lock);
     714                 :            : 
     715   [ #  #  #  # ]:          0 :         switch (phydev->state) {
     716                 :            :                 case PHY_STARTING:
     717                 :          0 :                         phydev->state = PHY_PENDING;
     718                 :          0 :                         break;
     719                 :            :                 case PHY_READY:
     720                 :          0 :                         phydev->state = PHY_UP;
     721                 :          0 :                         break;
     722                 :            :                 case PHY_HALTED:
     723                 :          0 :                         phydev->state = PHY_RESUMING;
     724                 :            :                 default:
     725                 :            :                         break;
     726                 :            :         }
     727                 :          0 :         mutex_unlock(&phydev->lock);
     728                 :          0 : }
     729                 :            : EXPORT_SYMBOL(phy_stop);
     730                 :            : EXPORT_SYMBOL(phy_start);
     731                 :            : 
     732                 :            : /**
     733                 :            :  * phy_state_machine - Handle the state machine
     734                 :            :  * @work: work_struct that describes the work to be done
     735                 :            :  */
     736                 :          0 : void phy_state_machine(struct work_struct *work)
     737                 :            : {
     738                 :            :         struct delayed_work *dwork = to_delayed_work(work);
     739                 :     174458 :         struct phy_device *phydev =
     740                 :            :                         container_of(dwork, struct phy_device, state_queue);
     741                 :            :         int needs_aneg = 0;
     742                 :            :         int err = 0;
     743                 :            : 
     744                 :      87229 :         mutex_lock(&phydev->lock);
     745                 :            : 
     746         [ -  + ]:      87229 :         if (phydev->adjust_state)
     747                 :          0 :                 phydev->adjust_state(phydev->attached_dev);
     748                 :            : 
     749   [ -  -  -  -  :      87229 :         switch(phydev->state) {
             +  +  -  -  
                      - ]
     750                 :            :                 case PHY_DOWN:
     751                 :            :                 case PHY_STARTING:
     752                 :            :                 case PHY_READY:
     753                 :            :                 case PHY_PENDING:
     754                 :            :                         break;
     755                 :            :                 case PHY_UP:
     756                 :            :                         needs_aneg = 1;
     757                 :            : 
     758                 :          0 :                         phydev->link_timeout = PHY_AN_TIMEOUT;
     759                 :            : 
     760                 :          0 :                         break;
     761                 :            :                 case PHY_AN:
     762                 :            :                         err = phy_read_status(phydev);
     763                 :            : 
     764         [ #  # ]:          0 :                         if (err < 0)
     765                 :            :                                 break;
     766                 :            : 
     767                 :            :                         /* If the link is down, give up on
     768                 :            :                          * negotiation for now */
     769         [ #  # ]:          0 :                         if (!phydev->link) {
     770                 :          0 :                                 phydev->state = PHY_NOLINK;
     771                 :          0 :                                 netif_carrier_off(phydev->attached_dev);
     772                 :          0 :                                 phydev->adjust_link(phydev->attached_dev);
     773                 :          0 :                                 break;
     774                 :            :                         }
     775                 :            : 
     776                 :            :                         /* Check if negotiation is done.  Break
     777                 :            :                          * if there's an error */
     778                 :            :                         err = phy_aneg_done(phydev);
     779         [ #  # ]:          0 :                         if (err < 0)
     780                 :            :                                 break;
     781                 :            : 
     782                 :            :                         /* If AN is done, we're running */
     783         [ #  # ]:          0 :                         if (err > 0) {
     784                 :          0 :                                 phydev->state = PHY_RUNNING;
     785                 :          0 :                                 netif_carrier_on(phydev->attached_dev);
     786                 :          0 :                                 phydev->adjust_link(phydev->attached_dev);
     787                 :            : 
     788         [ #  # ]:          0 :                         } else if (0 == phydev->link_timeout--) {
     789                 :            :                                 needs_aneg = 1;
     790                 :            :                                 /* If we have the magic_aneg bit,
     791                 :            :                                  * we try again */
     792                 :            :                                 if (phydev->drv->flags & PHY_HAS_MAGICANEG)
     793                 :            :                                         break;
     794                 :            :                         }
     795                 :            :                         break;
     796                 :            :                 case PHY_NOLINK:
     797                 :            :                         err = phy_read_status(phydev);
     798                 :            : 
     799         [ #  # ]:          0 :                         if (err)
     800                 :            :                                 break;
     801                 :            : 
     802         [ #  # ]:          0 :                         if (phydev->link) {
     803                 :          0 :                                 phydev->state = PHY_RUNNING;
     804                 :          0 :                                 netif_carrier_on(phydev->attached_dev);
     805                 :          0 :                                 phydev->adjust_link(phydev->attached_dev);
     806                 :            :                         }
     807                 :            :                         break;
     808                 :            :                 case PHY_FORCING:
     809                 :          0 :                         err = genphy_update_link(phydev);
     810                 :            : 
     811         [ #  # ]:          0 :                         if (err)
     812                 :            :                                 break;
     813                 :            : 
     814         [ #  # ]:          0 :                         if (phydev->link) {
     815                 :          0 :                                 phydev->state = PHY_RUNNING;
     816                 :          0 :                                 netif_carrier_on(phydev->attached_dev);
     817                 :            :                         } else {
     818         [ #  # ]:          0 :                                 if (0 == phydev->link_timeout--)
     819                 :            :                                         needs_aneg = 1;
     820                 :            :                         }
     821                 :            : 
     822                 :          0 :                         phydev->adjust_link(phydev->attached_dev);
     823                 :          0 :                         break;
     824                 :            :                 case PHY_RUNNING:
     825                 :            :                         /* Only register a CHANGE if we are
     826                 :            :                          * polling or ignoring interrupts
     827                 :            :                          */
     828         [ +  - ]:      43614 :                         if (!phy_interrupt_is_valid(phydev))
     829                 :      43614 :                                 phydev->state = PHY_CHANGELINK;
     830                 :            :                         break;
     831                 :            :                 case PHY_CHANGELINK:
     832                 :            :                         err = phy_read_status(phydev);
     833                 :            : 
     834         [ +  - ]:      43615 :                         if (err)
     835                 :            :                                 break;
     836                 :            : 
     837         [ +  - ]:      43615 :                         if (phydev->link) {
     838                 :      43615 :                                 phydev->state = PHY_RUNNING;
     839                 :      43615 :                                 netif_carrier_on(phydev->attached_dev);
     840                 :            :                         } else {
     841                 :          0 :                                 phydev->state = PHY_NOLINK;
     842                 :          0 :                                 netif_carrier_off(phydev->attached_dev);
     843                 :            :                         }
     844                 :            : 
     845                 :      43615 :                         phydev->adjust_link(phydev->attached_dev);
     846                 :            : 
     847         [ -  + ]:      43615 :                         if (phy_interrupt_is_valid(phydev))
     848                 :            :                                 err = phy_config_interrupt(phydev,
     849                 :            :                                                 PHY_INTERRUPT_ENABLED);
     850                 :            :                         break;
     851                 :            :                 case PHY_HALTED:
     852         [ #  # ]:          0 :                         if (phydev->link) {
     853                 :          0 :                                 phydev->link = 0;
     854                 :          0 :                                 netif_carrier_off(phydev->attached_dev);
     855                 :          0 :                                 phydev->adjust_link(phydev->attached_dev);
     856                 :            :                         }
     857                 :            :                         break;
     858                 :            :                 case PHY_RESUMING:
     859                 :            : 
     860                 :            :                         err = phy_clear_interrupt(phydev);
     861                 :            : 
     862         [ #  # ]:          0 :                         if (err)
     863                 :            :                                 break;
     864                 :            : 
     865                 :            :                         err = phy_config_interrupt(phydev,
     866                 :            :                                         PHY_INTERRUPT_ENABLED);
     867                 :            : 
     868         [ #  # ]:          0 :                         if (err)
     869                 :            :                                 break;
     870                 :            : 
     871         [ #  # ]:          0 :                         if (AUTONEG_ENABLE == phydev->autoneg) {
     872                 :            :                                 err = phy_aneg_done(phydev);
     873         [ #  # ]:          0 :                                 if (err < 0)
     874                 :            :                                         break;
     875                 :            : 
     876                 :            :                                 /* err > 0 if AN is done.
     877                 :            :                                  * Otherwise, it's 0, and we're
     878                 :            :                                  * still waiting for AN */
     879         [ #  # ]:          0 :                                 if (err > 0) {
     880                 :            :                                         err = phy_read_status(phydev);
     881         [ #  # ]:          0 :                                         if (err)
     882                 :            :                                                 break;
     883                 :            : 
     884         [ #  # ]:          0 :                                         if (phydev->link) {
     885                 :          0 :                                                 phydev->state = PHY_RUNNING;
     886                 :          0 :                                                 netif_carrier_on(phydev->attached_dev);
     887                 :            :                                         } else
     888                 :          0 :                                                 phydev->state = PHY_NOLINK;
     889                 :          0 :                                         phydev->adjust_link(phydev->attached_dev);
     890                 :            :                                 } else {
     891                 :          0 :                                         phydev->state = PHY_AN;
     892                 :          0 :                                         phydev->link_timeout = PHY_AN_TIMEOUT;
     893                 :            :                                 }
     894                 :            :                         } else {
     895                 :            :                                 err = phy_read_status(phydev);
     896         [ #  # ]:          0 :                                 if (err)
     897                 :            :                                         break;
     898                 :            : 
     899         [ #  # ]:          0 :                                 if (phydev->link) {
     900                 :          0 :                                         phydev->state = PHY_RUNNING;
     901                 :          0 :                                         netif_carrier_on(phydev->attached_dev);
     902                 :            :                                 } else
     903                 :          0 :                                         phydev->state = PHY_NOLINK;
     904                 :          0 :                                 phydev->adjust_link(phydev->attached_dev);
     905                 :            :                         }
     906                 :            :                         break;
     907                 :            :         }
     908                 :            : 
     909                 :      87229 :         mutex_unlock(&phydev->lock);
     910                 :            : 
     911         [ -  + ]:      87229 :         if (needs_aneg)
     912                 :          0 :                 err = phy_start_aneg(phydev);
     913                 :            : 
     914         [ -  + ]:      87229 :         if (err < 0)
     915                 :            :                 phy_error(phydev);
     916                 :            : 
     917                 :      87229 :         queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
     918                 :            :                         PHY_STATE_TIME * HZ);
     919                 :      87229 : }
     920                 :            : 
     921                 :          0 : void phy_mac_interrupt(struct phy_device *phydev, int new_link)
     922                 :            : {
     923                 :          0 :         cancel_work_sync(&phydev->phy_queue);
     924                 :          0 :         phydev->link = new_link;
     925                 :            :         schedule_work(&phydev->phy_queue);
     926                 :          0 : }
     927                 :            : EXPORT_SYMBOL(phy_mac_interrupt);
     928                 :            : 
     929                 :            : static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
     930                 :            :                                     int addr)
     931                 :            : {
     932                 :            :         /* Write the desired MMD Devad */
     933                 :          0 :         bus->write(bus, addr, MII_MMD_CTRL, devad);
     934                 :            : 
     935                 :            :         /* Write the desired MMD register address */
     936                 :          0 :         bus->write(bus, addr, MII_MMD_DATA, prtad);
     937                 :            : 
     938                 :            :         /* Select the Function : DATA with no post increment */
     939                 :          0 :         bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
     940                 :            : }
     941                 :            : 
     942                 :            : /**
     943                 :            :  * phy_read_mmd_indirect - reads data from the MMD registers
     944                 :            :  * @bus: the target MII bus
     945                 :            :  * @prtad: MMD Address
     946                 :            :  * @devad: MMD DEVAD
     947                 :            :  * @addr: PHY address on the MII bus
     948                 :            :  *
     949                 :            :  * Description: it reads data from the MMD registers (clause 22 to access to
     950                 :            :  * clause 45) of the specified phy address.
     951                 :            :  * To read these register we have:
     952                 :            :  * 1) Write reg 13 // DEVAD
     953                 :            :  * 2) Write reg 14 // MMD Address
     954                 :            :  * 3) Write reg 13 // MMD Data Command for MMD DEVAD
     955                 :            :  * 3) Read  reg 14 // Read MMD data
     956                 :            :  */
     957                 :          0 : static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
     958                 :            :                                  int addr)
     959                 :            : {
     960                 :            :         u32 ret;
     961                 :            : 
     962                 :            :         mmd_phy_indirect(bus, prtad, devad, addr);
     963                 :            : 
     964                 :            :         /* Read the content of the MMD's selected register */
     965                 :          0 :         ret = bus->read(bus, addr, MII_MMD_DATA);
     966                 :            : 
     967                 :          0 :         return ret;
     968                 :            : }
     969                 :            : 
     970                 :            : /**
     971                 :            :  * phy_write_mmd_indirect - writes data to the MMD registers
     972                 :            :  * @bus: the target MII bus
     973                 :            :  * @prtad: MMD Address
     974                 :            :  * @devad: MMD DEVAD
     975                 :            :  * @addr: PHY address on the MII bus
     976                 :            :  * @data: data to write in the MMD register
     977                 :            :  *
     978                 :            :  * Description: Write data from the MMD registers of the specified
     979                 :            :  * phy address.
     980                 :            :  * To write these register we have:
     981                 :            :  * 1) Write reg 13 // DEVAD
     982                 :            :  * 2) Write reg 14 // MMD Address
     983                 :            :  * 3) Write reg 13 // MMD Data Command for MMD DEVAD
     984                 :            :  * 3) Write reg 14 // Write MMD data
     985                 :            :  */
     986                 :          0 : static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
     987                 :            :                                    int addr, u32 data)
     988                 :            : {
     989                 :            :         mmd_phy_indirect(bus, prtad, devad, addr);
     990                 :            : 
     991                 :            :         /* Write the data into MMD's selected register */
     992                 :          0 :         bus->write(bus, addr, MII_MMD_DATA, data);
     993                 :          0 : }
     994                 :            : 
     995                 :            : /**
     996                 :            :  * phy_init_eee - init and check the EEE feature
     997                 :            :  * @phydev: target phy_device struct
     998                 :            :  * @clk_stop_enable: PHY may stop the clock during LPI
     999                 :            :  *
    1000                 :            :  * Description: it checks if the Energy-Efficient Ethernet (EEE)
    1001                 :            :  * is supported by looking at the MMD registers 3.20 and 7.60/61
    1002                 :            :  * and it programs the MMD register 3.0 setting the "Clock stop enable"
    1003                 :            :  * bit if required.
    1004                 :            :  */
    1005                 :          0 : int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
    1006                 :            : {
    1007                 :            :         int ret = -EPROTONOSUPPORT;
    1008                 :            : 
    1009                 :            :         /* According to 802.3az,the EEE is supported only in full duplex-mode.
    1010                 :            :          * Also EEE feature is active when core is operating with MII, GMII
    1011                 :            :          * or RGMII.
    1012                 :            :          */
    1013 [ #  # ][ #  # ]:          0 :         if ((phydev->duplex == DUPLEX_FULL) &&
    1014                 :          0 :             ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
    1015                 :          0 :             (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
    1016                 :            :             (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
    1017                 :            :                 int eee_lp, eee_cap, eee_adv;
    1018                 :            :                 u32 lp, cap, adv;
    1019                 :            :                 int idx, status;
    1020                 :            : 
    1021                 :            :                 /* Read phy status to properly get the right settings */
    1022                 :            :                 status = phy_read_status(phydev);
    1023         [ #  # ]:          0 :                 if (status)
    1024                 :            :                         return status;
    1025                 :            : 
    1026                 :            :                 /* First check if the EEE ability is supported */
    1027                 :          0 :                 eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
    1028                 :            :                                                 MDIO_MMD_PCS, phydev->addr);
    1029         [ #  # ]:          0 :                 if (eee_cap < 0)
    1030                 :            :                         return eee_cap;
    1031                 :            : 
    1032                 :          0 :                 cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
    1033         [ #  # ]:          0 :                 if (!cap)
    1034                 :            :                         goto eee_exit;
    1035                 :            : 
    1036                 :            :                 /* Check which link settings negotiated and verify it in
    1037                 :            :                  * the EEE advertising registers.
    1038                 :            :                  */
    1039                 :          0 :                 eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
    1040                 :            :                                                MDIO_MMD_AN, phydev->addr);
    1041         [ #  # ]:          0 :                 if (eee_lp < 0)
    1042                 :            :                         return eee_lp;
    1043                 :            : 
    1044                 :          0 :                 eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
    1045                 :            :                                                 MDIO_MMD_AN, phydev->addr);
    1046         [ #  # ]:          0 :                 if (eee_adv < 0)
    1047                 :            :                         return eee_adv;
    1048                 :            : 
    1049                 :          0 :                 adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
    1050                 :          0 :                 lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
    1051                 :          0 :                 idx = phy_find_setting(phydev->speed, phydev->duplex);
    1052         [ #  # ]:          0 :                 if (!(lp & adv & settings[idx].setting))
    1053                 :            :                         goto eee_exit;
    1054                 :            : 
    1055         [ #  # ]:          0 :                 if (clk_stop_enable) {
    1056                 :            :                         /* Configure the PHY to stop receiving xMII
    1057                 :            :                          * clock while it is signaling LPI.
    1058                 :            :                          */
    1059                 :          0 :                         int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
    1060                 :            :                                                         MDIO_MMD_PCS,
    1061                 :            :                                                         phydev->addr);
    1062         [ #  # ]:          0 :                         if (val < 0)
    1063                 :            :                                 return val;
    1064                 :            : 
    1065                 :          0 :                         val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
    1066                 :          0 :                         phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
    1067                 :            :                                                MDIO_MMD_PCS, phydev->addr, val);
    1068                 :            :                 }
    1069                 :            : 
    1070                 :            :                 ret = 0; /* EEE supported */
    1071                 :            :         }
    1072                 :            : 
    1073                 :            : eee_exit:
    1074                 :          0 :         return ret;
    1075                 :            : }
    1076                 :            : EXPORT_SYMBOL(phy_init_eee);
    1077                 :            : 
    1078                 :            : /**
    1079                 :            :  * phy_get_eee_err - report the EEE wake error count
    1080                 :            :  * @phydev: target phy_device struct
    1081                 :            :  *
    1082                 :            :  * Description: it is to report the number of time where the PHY
    1083                 :            :  * failed to complete its normal wake sequence.
    1084                 :            :  */
    1085                 :          0 : int phy_get_eee_err(struct phy_device *phydev)
    1086                 :            : {
    1087                 :          0 :         return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
    1088                 :            :                                      MDIO_MMD_PCS, phydev->addr);
    1089                 :            : 
    1090                 :            : }
    1091                 :            : EXPORT_SYMBOL(phy_get_eee_err);
    1092                 :            : 
    1093                 :            : /**
    1094                 :            :  * phy_ethtool_get_eee - get EEE supported and status
    1095                 :            :  * @phydev: target phy_device struct
    1096                 :            :  * @data: ethtool_eee data
    1097                 :            :  *
    1098                 :            :  * Description: it reportes the Supported/Advertisement/LP Advertisement
    1099                 :            :  * capabilities.
    1100                 :            :  */
    1101                 :          0 : int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
    1102                 :            : {
    1103                 :            :         int val;
    1104                 :            : 
    1105                 :            :         /* Get Supported EEE */
    1106                 :          0 :         val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
    1107                 :            :                                     MDIO_MMD_PCS, phydev->addr);
    1108         [ #  # ]:          0 :         if (val < 0)
    1109                 :            :                 return val;
    1110                 :          0 :         data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
    1111                 :            : 
    1112                 :            :         /* Get advertisement EEE */
    1113                 :          0 :         val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
    1114                 :            :                                     MDIO_MMD_AN, phydev->addr);
    1115         [ #  # ]:          0 :         if (val < 0)
    1116                 :            :                 return val;
    1117                 :          0 :         data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
    1118                 :            : 
    1119                 :            :         /* Get LP advertisement EEE */
    1120                 :          0 :         val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
    1121                 :            :                                     MDIO_MMD_AN, phydev->addr);
    1122         [ #  # ]:          0 :         if (val < 0)
    1123                 :            :                 return val;
    1124                 :          0 :         data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
    1125                 :            : 
    1126                 :          0 :         return 0;
    1127                 :            : }
    1128                 :            : EXPORT_SYMBOL(phy_ethtool_get_eee);
    1129                 :            : 
    1130                 :            : /**
    1131                 :            :  * phy_ethtool_set_eee - set EEE supported and status
    1132                 :            :  * @phydev: target phy_device struct
    1133                 :            :  * @data: ethtool_eee data
    1134                 :            :  *
    1135                 :            :  * Description: it is to program the Advertisement EEE register.
    1136                 :            :  */
    1137                 :          0 : int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
    1138                 :            : {
    1139                 :            :         int val;
    1140                 :            : 
    1141                 :          0 :         val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
    1142                 :          0 :         phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
    1143                 :            :                                phydev->addr, val);
    1144                 :            : 
    1145                 :          0 :         return 0;
    1146                 :            : }
    1147                 :            : EXPORT_SYMBOL(phy_ethtool_set_eee);
    1148                 :            : 
    1149                 :          0 : int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
    1150                 :            : {
    1151         [ #  # ]:          0 :         if (phydev->drv->set_wol)
    1152                 :          0 :                 return phydev->drv->set_wol(phydev, wol);
    1153                 :            : 
    1154                 :            :         return -EOPNOTSUPP;
    1155                 :            : }
    1156                 :            : EXPORT_SYMBOL(phy_ethtool_set_wol);
    1157                 :            : 
    1158                 :          0 : void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
    1159                 :            : {
    1160         [ #  # ]:          0 :         if (phydev->drv->get_wol)
    1161                 :          0 :                 phydev->drv->get_wol(phydev, wol);
    1162                 :          0 : }
    1163                 :            : EXPORT_SYMBOL(phy_ethtool_get_wol);

Generated by: LCOV version 1.9