LCOV - code coverage report
Current view: top level - drivers/net/ngbe/base - ngbe_phy_mvl.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 190 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 11 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 62 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "ngbe_phy_mvl.h"
       6                 :            : 
       7                 :            : #define MVL_PHY_RST_WAIT_PERIOD  5
       8                 :            : 
       9                 :          0 : s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw,
      10                 :            :                 u32 reg_addr, u32 device_type, u16 *phy_data)
      11                 :            : {
      12                 :            :         mdi_reg_t reg;
      13                 :            :         mdi_reg_22_t reg22;
      14                 :            : 
      15                 :          0 :         reg.device_type = device_type;
      16                 :          0 :         reg.addr = reg_addr;
      17                 :            : 
      18         [ #  # ]:          0 :         if (hw->phy.media_type == ngbe_media_type_fiber)
      19                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1);
      20                 :            :         else
      21                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0);
      22                 :            : 
      23                 :          0 :         ngbe_mdi_map_register(&reg, &reg22);
      24                 :            : 
      25                 :          0 :         ngbe_read_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data);
      26                 :            : 
      27                 :          0 :         return 0;
      28                 :            : }
      29                 :            : 
      30                 :          0 : s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw,
      31                 :            :                 u32 reg_addr, u32 device_type, u16 phy_data)
      32                 :            : {
      33                 :            :         mdi_reg_t reg;
      34                 :            :         mdi_reg_22_t reg22;
      35                 :            : 
      36                 :          0 :         reg.device_type = device_type;
      37                 :          0 :         reg.addr = reg_addr;
      38                 :            : 
      39         [ #  # ]:          0 :         if (hw->phy.media_type == ngbe_media_type_fiber)
      40                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1);
      41                 :            :         else
      42                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0);
      43                 :            : 
      44                 :          0 :         ngbe_mdi_map_register(&reg, &reg22);
      45                 :            : 
      46                 :          0 :         ngbe_write_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data);
      47                 :            : 
      48                 :          0 :         return 0;
      49                 :            : }
      50                 :            : 
      51                 :          0 : s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw)
      52                 :            : {
      53                 :            :         u8 value = 0;
      54                 :            :         u32 phy_mode = 0;
      55                 :            : 
      56                 :          0 :         phy_mode = ngbe_flash_read_dword(hw, 0xFF010);
      57                 :          0 :         value = (u8)(phy_mode >> (hw->bus.lan_id * 8));
      58                 :            : 
      59         [ #  # ]:          0 :         if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_COPPER) {
      60                 :            :                 /* mode select to RGMII-to-copper */
      61                 :          0 :                 hw->phy.type = ngbe_phy_mvl;
      62                 :          0 :                 hw->phy.media_type = ngbe_media_type_copper;
      63                 :          0 :                 hw->mac.link_type = ngbe_link_copper;
      64         [ #  # ]:          0 :         } else if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_FIBER) {
      65                 :            :                 /* mode select to RGMII-to-sfi */
      66                 :          0 :                 hw->phy.type = ngbe_phy_mvl_sfi;
      67                 :          0 :                 hw->phy.media_type = ngbe_media_type_fiber;
      68                 :          0 :                 hw->mac.link_type = ngbe_link_fiber;
      69                 :            :         } else {
      70                 :          0 :                 DEBUGOUT("marvell 88E1512 mode %x is not supported.", value);
      71                 :          0 :                 return NGBE_ERR_DEVICE_NOT_SUPPORTED;
      72                 :            :         }
      73                 :            : 
      74                 :            :         return 0;
      75                 :            : }
      76                 :            : 
      77                 :          0 : s32 ngbe_init_phy_mvl(struct ngbe_hw *hw)
      78                 :            : {
      79                 :            :         s32 ret_val = 0;
      80                 :          0 :         u16 value = 0;
      81                 :            :         int i;
      82                 :            : 
      83                 :            :         /* enable interrupts, only link status change and an done is allowed */
      84                 :          0 :         ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 2);
      85                 :          0 :         ngbe_read_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, &value);
      86                 :          0 :         value &= ~MVL_RGM_CTL2_TTC;
      87                 :          0 :         value |= MVL_RGM_CTL2_RTC;
      88                 :          0 :         ngbe_write_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, value);
      89                 :            : 
      90                 :          0 :         hw->phy.write_reg(hw, MVL_CTRL, 0, MVL_CTRL_RESET);
      91         [ #  # ]:          0 :         for (i = 0; i < 15; i++) {
      92                 :          0 :                 ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value);
      93         [ #  # ]:          0 :                 if (value & MVL_CTRL_RESET)
      94                 :            :                         msleep(1);
      95                 :            :                 else
      96                 :            :                         break;
      97                 :            :         }
      98                 :            : 
      99         [ #  # ]:          0 :         if (i == 15) {
     100                 :          0 :                 DEBUGOUT("phy reset exceeds maximum waiting period.");
     101                 :          0 :                 return NGBE_ERR_TIMEOUT;
     102                 :            :         }
     103                 :            : 
     104                 :          0 :         ret_val = hw->phy.reset_hw(hw);
     105         [ #  # ]:          0 :         if (ret_val)
     106                 :            :                 return ret_val;
     107                 :            : 
     108                 :            :         /* set LED2 to interrupt output and INTn active low */
     109                 :          0 :         ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3);
     110                 :          0 :         ngbe_read_phy_reg_mdi(hw, MVL_LEDTCR, 0, &value);
     111                 :          0 :         value |= MVL_LEDTCR_INTR_EN;
     112                 :          0 :         value &= ~(MVL_LEDTCR_INTR_POL);
     113                 :          0 :         ngbe_write_phy_reg_mdi(hw, MVL_LEDTCR, 0, value);
     114                 :            : 
     115         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl_sfi) {
     116                 :          0 :                 hw->phy.read_reg(hw, MVL_CTRL1, 0, &value);
     117                 :          0 :                 value &= ~MVL_CTRL1_INTR_POL;
     118                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_CTRL1, 0, value);
     119                 :            :         }
     120                 :            : 
     121                 :            :         /* enable link status change and AN complete interrupts */
     122                 :          0 :         value = MVL_INTR_EN_ANC | MVL_INTR_EN_LSC;
     123                 :          0 :         hw->phy.write_reg(hw, MVL_INTR_EN, 0, value);
     124                 :            : 
     125                 :          0 :         hw->phy.set_phy_power(hw, false);
     126                 :            : 
     127                 :          0 :         return ret_val;
     128                 :            : }
     129                 :            : 
     130                 :          0 : s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
     131                 :            :                                 bool autoneg_wait_to_complete)
     132                 :            : {
     133                 :            :         u16 value_r4 = 0;
     134                 :            :         u16 value_r9 = 0;
     135                 :            :         u16 value;
     136                 :            : 
     137                 :            :         UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
     138                 :            : 
     139         [ #  # ]:          0 :         if (hw->led_conf == 0xFFFF) {
     140                 :            :                 /* LED control */
     141                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3);
     142                 :          0 :                 ngbe_read_phy_reg_mdi(hw, MVL_LEDFCR, 0, &value);
     143                 :          0 :                 value &= ~(MVL_LEDFCR_CTL0 | MVL_LEDFCR_CTL1);
     144                 :          0 :                 value |= MVL_LEDFCR_CTL0_CONF | MVL_LEDFCR_CTL1_CONF;
     145                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_LEDFCR, 0, value);
     146                 :          0 :                 ngbe_read_phy_reg_mdi(hw, MVL_LEDPCR, 0, &value);
     147                 :          0 :                 value &= ~(MVL_LEDPCR_CTL0 | MVL_LEDPCR_CTL1);
     148                 :          0 :                 value |= MVL_LEDPCR_CTL0_CONF | MVL_LEDPCR_CTL1_CONF;
     149                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_LEDPCR, 0, value);
     150                 :            :         }
     151                 :            : 
     152                 :          0 :         hw->phy.autoneg_advertised = 0;
     153                 :            : 
     154         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl) {
     155         [ #  # ]:          0 :                 if (!hw->mac.autoneg) {
     156   [ #  #  #  # ]:          0 :                         switch (speed) {
     157                 :          0 :                         case NGBE_LINK_SPEED_1GB_FULL:
     158                 :          0 :                                 value = MVL_CTRL_SPEED_SELECT1;
     159                 :          0 :                                 break;
     160                 :          0 :                         case NGBE_LINK_SPEED_100M_FULL:
     161                 :          0 :                                 value = MVL_CTRL_SPEED_SELECT0;
     162                 :          0 :                                 break;
     163                 :          0 :                         case NGBE_LINK_SPEED_10M_FULL:
     164                 :          0 :                                 value = 0;
     165                 :          0 :                                 break;
     166                 :          0 :                         default:
     167                 :          0 :                                 value = MVL_CTRL_SPEED_SELECT0 |
     168                 :            :                                         MVL_CTRL_SPEED_SELECT1;
     169                 :          0 :                                 DEBUGOUT("unknown speed = 0x%x.", speed);
     170                 :          0 :                                 break;
     171                 :            :                         }
     172                 :            :                         /* duplex full */
     173                 :          0 :                         value |= MVL_CTRL_DUPLEX | MVL_CTRL_RESET;
     174                 :          0 :                         ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
     175                 :            : 
     176                 :          0 :                         goto skip_an;
     177                 :            :                 }
     178         [ #  # ]:          0 :                 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
     179                 :            :                         value_r9 |= MVL_PHY_1000BASET_FULL;
     180                 :          0 :                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
     181                 :            :                 }
     182                 :            : 
     183         [ #  # ]:          0 :                 if (speed & NGBE_LINK_SPEED_100M_FULL) {
     184                 :            :                         value_r4 |= MVL_PHY_100BASET_FULL;
     185                 :          0 :                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
     186                 :            :                 }
     187                 :            : 
     188         [ #  # ]:          0 :                 if (speed & NGBE_LINK_SPEED_10M_FULL) {
     189                 :          0 :                         value_r4 |= MVL_PHY_10BASET_FULL;
     190                 :          0 :                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
     191                 :            :                 }
     192                 :            : 
     193                 :          0 :                 hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     194                 :          0 :                 value &= ~(MVL_PHY_100BASET_FULL |
     195                 :            :                            MVL_PHY_100BASET_HALF |
     196                 :            :                            MVL_PHY_10BASET_FULL |
     197                 :            :                            MVL_PHY_10BASET_HALF);
     198                 :          0 :                 value_r4 |= value;
     199                 :          0 :                 hw->phy.write_reg(hw, MVL_ANA, 0, value_r4);
     200                 :            : 
     201                 :          0 :                 hw->phy.read_reg(hw, MVL_PHY_1000BASET, 0, &value);
     202                 :          0 :                 value &= ~(MVL_PHY_1000BASET_FULL |
     203                 :            :                            MVL_PHY_1000BASET_HALF);
     204                 :          0 :                 value_r9 |= value;
     205                 :          0 :                 hw->phy.write_reg(hw, MVL_PHY_1000BASET, 0, value_r9);
     206                 :            : 
     207                 :          0 :                 value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE |
     208                 :            :                         MVL_CTRL_RESET | MVL_CTRL_DUPLEX;
     209                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
     210                 :            :         } else {
     211                 :          0 :                 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
     212                 :            : 
     213                 :          0 :                 hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     214                 :          0 :                 value &= ~(MVL_PHY_1000BASEX_HALF | MVL_PHY_1000BASEX_FULL);
     215                 :          0 :                 value |= MVL_PHY_1000BASEX_FULL;
     216                 :          0 :                 hw->phy.write_reg(hw, MVL_ANA, 0, value);
     217                 :            : 
     218         [ #  # ]:          0 :                 if (hw->mac.autoneg)
     219                 :          0 :                         value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE |
     220                 :            :                                 MVL_CTRL_RESET | MVL_CTRL_DUPLEX |
     221                 :            :                                 MVL_CTRL_SPEED_SELECT1;
     222                 :            :                 else
     223                 :          0 :                         value = MVL_CTRL_RESET | MVL_CTRL_DUPLEX |
     224                 :            :                                 MVL_CTRL_SPEED_SELECT1;
     225                 :          0 :                 ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
     226                 :            :         }
     227                 :            : 
     228                 :          0 : skip_an:
     229                 :          0 :         hw->phy.set_phy_power(hw, true);
     230                 :            : 
     231                 :          0 :         hw->phy.read_reg(hw, MVL_INTR, 0, &value);
     232                 :            : 
     233                 :          0 :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :          0 : s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw)
     237                 :            : {
     238                 :            :         u32 i;
     239                 :          0 :         u16 ctrl = 0;
     240                 :            :         s32 status = 0;
     241                 :            : 
     242         [ #  # ]:          0 :         if (hw->phy.type != ngbe_phy_mvl && hw->phy.type != ngbe_phy_mvl_sfi)
     243                 :            :                 return NGBE_ERR_PHY_TYPE;
     244                 :            : 
     245                 :            :         /* select page 18 reg 20 */
     246                 :          0 :         status = ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18);
     247                 :            : 
     248                 :            :         /* mode select to RGMII-to-copper or RGMII-to-sfi*/
     249         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl)
     250                 :          0 :                 ctrl = MVL_GEN_CTL_MODE_COPPER;
     251                 :            :         else
     252                 :          0 :                 ctrl = MVL_GEN_CTL_MODE_FIBER;
     253                 :          0 :         status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl);
     254                 :            :         /* mode reset */
     255                 :          0 :         ctrl |= MVL_GEN_CTL_RESET;
     256                 :          0 :         status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl);
     257                 :            : 
     258         [ #  # ]:          0 :         for (i = 0; i < MVL_PHY_RST_WAIT_PERIOD; i++) {
     259                 :          0 :                 status = ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &ctrl);
     260         [ #  # ]:          0 :                 if (!(ctrl & MVL_GEN_CTL_RESET))
     261                 :            :                         break;
     262                 :            :                 msleep(1);
     263                 :            :         }
     264                 :            : 
     265         [ #  # ]:          0 :         if (i == MVL_PHY_RST_WAIT_PERIOD) {
     266                 :          0 :                 DEBUGOUT("PHY reset polling failed to complete.");
     267                 :          0 :                 return NGBE_ERR_RESET_FAILED;
     268                 :            :         }
     269                 :            : 
     270                 :            :         return status;
     271                 :            : }
     272                 :            : 
     273                 :          0 : s32 ngbe_get_phy_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit)
     274                 :            : {
     275                 :            :         u16 value;
     276                 :            :         s32 status = 0;
     277                 :            : 
     278         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl) {
     279                 :          0 :                 status = hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     280                 :          0 :                 value &= MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE;
     281                 :          0 :                 *pause_bit = (u8)(value >> 10);
     282                 :            :         } else {
     283                 :          0 :                 status = hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     284                 :          0 :                 value &= MVL_FANA_PAUSE_MASK;
     285                 :          0 :                 *pause_bit = (u8)(value >> 7);
     286                 :            :         }
     287                 :            : 
     288                 :          0 :         return status;
     289                 :            : }
     290                 :            : 
     291                 :          0 : s32 ngbe_get_phy_lp_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit)
     292                 :            : {
     293                 :            :         u16 value;
     294                 :            :         s32 status = 0;
     295                 :            : 
     296         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl) {
     297                 :          0 :                 status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value);
     298                 :          0 :                 value &= MVL_CLPAR_ASM_PAUSE | MVL_CLPAR_PAUSE;
     299                 :          0 :                 *pause_bit = (u8)(value >> 10);
     300                 :            :         } else {
     301                 :          0 :                 status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value);
     302                 :          0 :                 value &= MVL_FLPAR_PAUSE_MASK;
     303                 :          0 :                 *pause_bit = (u8)(value >> 7);
     304                 :            :         }
     305                 :            : 
     306                 :          0 :         return status;
     307                 :            : }
     308                 :            : 
     309                 :          0 : s32 ngbe_set_phy_pause_adv_mvl(struct ngbe_hw *hw, u16 pause_bit)
     310                 :            : {
     311                 :            :         u16 value;
     312                 :            :         s32 status = 0;
     313                 :            : 
     314         [ #  # ]:          0 :         if (hw->phy.type == ngbe_phy_mvl) {
     315                 :          0 :                 status = hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     316                 :          0 :                 value &= ~(MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE);
     317                 :            :         } else {
     318                 :          0 :                 status = hw->phy.read_reg(hw, MVL_ANA, 0, &value);
     319                 :          0 :                 value &= ~MVL_FANA_PAUSE_MASK;
     320                 :            :         }
     321                 :            : 
     322                 :          0 :         value |= pause_bit;
     323                 :          0 :         status = hw->phy.write_reg(hw, MVL_ANA, 0, value);
     324                 :            : 
     325                 :          0 :         return status;
     326                 :            : }
     327                 :            : 
     328                 :          0 : s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw,
     329                 :            :                 u32 *speed, bool *link_up)
     330                 :            : {
     331                 :            :         s32 status = 0;
     332                 :            :         u16 phy_link = 0;
     333                 :            :         u16 phy_speed = 0;
     334                 :          0 :         u16 phy_data = 0;
     335                 :          0 :         u16 insr = 0;
     336                 :            : 
     337                 :            :         /* Initialize speed and link to default case */
     338                 :          0 :         *link_up = false;
     339                 :          0 :         *speed = NGBE_LINK_SPEED_UNKNOWN;
     340                 :            : 
     341                 :          0 :         hw->phy.read_reg(hw, MVL_INTR, 0, &insr);
     342                 :            : 
     343                 :            :         /*
     344                 :            :          * Check current speed and link status of the PHY register.
     345                 :            :          * This is a vendor specific register and may have to
     346                 :            :          * be changed for other copper PHYs.
     347                 :            :          */
     348                 :          0 :         status = hw->phy.read_reg(hw, MVL_PHYSR, 0, &phy_data);
     349                 :          0 :         phy_link = phy_data & MVL_PHYSR_LINK;
     350                 :          0 :         phy_speed = phy_data & MVL_PHYSR_SPEED_MASK;
     351                 :            : 
     352         [ #  # ]:          0 :         if (phy_link == MVL_PHYSR_LINK) {
     353                 :          0 :                 *link_up = true;
     354                 :            : 
     355         [ #  # ]:          0 :                 if (phy_speed == MVL_PHYSR_SPEED_1000M)
     356                 :          0 :                         *speed = NGBE_LINK_SPEED_1GB_FULL;
     357         [ #  # ]:          0 :                 else if (phy_speed == MVL_PHYSR_SPEED_100M)
     358                 :          0 :                         *speed = NGBE_LINK_SPEED_100M_FULL;
     359         [ #  # ]:          0 :                 else if (phy_speed == MVL_PHYSR_SPEED_10M)
     360                 :          0 :                         *speed = NGBE_LINK_SPEED_10M_FULL;
     361                 :            :         }
     362                 :            : 
     363                 :          0 :         return status;
     364                 :            : }
     365                 :            : 
     366                 :          0 : s32 ngbe_set_phy_power_mvl(struct ngbe_hw *hw, bool on)
     367                 :            : {
     368                 :          0 :         u16 value = 0;
     369                 :            : 
     370                 :          0 :         hw->phy.read_reg(hw, MVL_CTRL, 0, &value);
     371         [ #  # ]:          0 :         if (on)
     372                 :          0 :                 value &= ~MVL_CTRL_PWDN;
     373                 :            :         else
     374                 :          0 :                 value |= MVL_CTRL_PWDN;
     375                 :          0 :         hw->phy.write_reg(hw, MVL_CTRL, 0, value);
     376                 :            : 
     377                 :          0 :         return 0;
     378                 :            : }

Generated by: LCOV version 1.14