LCOV - code coverage report
Current view: top level - drivers/net/ethernet/aquantia/atlantic - aq_phy.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 39 57 68.4 %
Date: 2022-04-01 13:59:58 Functions: 5 7 71.4 %
Branches: 16 22 72.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /* aQuantia Corporation Network Driver
       3                 :            :  * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "aq_phy.h"
       7                 :            : 
       8                 :        136 : bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw)
       9                 :            : {
      10                 :        136 :         int err = 0;
      11                 :        136 :         u32 val;
      12                 :            : 
      13   [ +  +  -  + ]:        280 :         err = readx_poll_timeout_atomic(hw_atl_mdio_busy_get, aq_hw,
      14                 :            :                                         val, val == 0U, 10U, 100000U);
      15                 :            : 
      16                 :          0 :         if (err < 0)
      17                 :          0 :                 return false;
      18                 :            : 
      19                 :            :         return true;
      20                 :            : }
      21                 :            : 
      22                 :         68 : u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr)
      23                 :            : {
      24                 :         68 :         u16 phy_addr = aq_hw->phy_id << 5 | mmd;
      25                 :            : 
      26                 :            :         /* Set Address register. */
      27                 :         68 :         hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<
      28                 :            :                                    HW_ATL_MDIO_ADDRESS_SHIFT);
      29                 :            :         /* Send Address command. */
      30                 :         68 :         hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
      31                 :            :                                    (3 << HW_ATL_MDIO_OP_MODE_SHIFT) |
      32                 :            :                                    ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
      33                 :            :                                     HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
      34                 :            : 
      35                 :         68 :         aq_mdio_busy_wait(aq_hw);
      36                 :            : 
      37                 :            :         /* Send Read command. */
      38                 :         68 :         hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
      39                 :            :                                    (1 << HW_ATL_MDIO_OP_MODE_SHIFT) |
      40                 :            :                                    ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
      41                 :            :                                     HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
      42                 :            :         /* Read result. */
      43                 :         68 :         aq_mdio_busy_wait(aq_hw);
      44                 :            : 
      45                 :         68 :         return (u16)hw_atl_glb_mdio_iface5_get(aq_hw);
      46                 :            : }
      47                 :            : 
      48                 :          0 : void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data)
      49                 :            : {
      50                 :          0 :         u16 phy_addr = aq_hw->phy_id << 5 | mmd;
      51                 :            : 
      52                 :            :         /* Set Address register. */
      53                 :          0 :         hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<
      54                 :            :                                    HW_ATL_MDIO_ADDRESS_SHIFT);
      55                 :            :         /* Send Address command. */
      56                 :          0 :         hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
      57                 :            :                                    (3 << HW_ATL_MDIO_OP_MODE_SHIFT) |
      58                 :            :                                    ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
      59                 :            :                                     HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
      60                 :            : 
      61                 :          0 :         aq_mdio_busy_wait(aq_hw);
      62                 :            : 
      63                 :          0 :         hw_atl_glb_mdio_iface3_set(aq_hw, (data & HW_ATL_MDIO_WRITE_DATA_MSK) <<
      64                 :            :                                    HW_ATL_MDIO_WRITE_DATA_SHIFT);
      65                 :            :         /* Send Write command. */
      66                 :          0 :         hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |
      67                 :            :                                    (2 << HW_ATL_MDIO_OP_MODE_SHIFT) |
      68                 :            :                                    ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<
      69                 :            :                                     HW_ATL_MDIO_PHY_ADDRESS_SHIFT));
      70                 :            : 
      71                 :          0 :         aq_mdio_busy_wait(aq_hw);
      72                 :          0 : }
      73                 :            : 
      74                 :        307 : u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address)
      75                 :            : {
      76                 :        307 :         int err = 0;
      77                 :        307 :         u32 val;
      78                 :            : 
      79   [ +  +  +  + ]:     605639 :         err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,
      80                 :            :                                         val, val == 1U, 10U, 100000U);
      81                 :            : 
      82                 :        307 :         if (err < 0) {
      83                 :        239 :                 err = 0xffff;
      84                 :        239 :                 goto err_exit;
      85                 :            :         }
      86                 :            : 
      87                 :         68 :         err = aq_mdio_read_word(aq_hw, mmd, address);
      88                 :            : 
      89                 :         68 :         hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);
      90                 :            : 
      91                 :        307 : err_exit:
      92                 :        307 :         return err;
      93                 :            : }
      94                 :            : 
      95                 :          0 : void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data)
      96                 :            : {
      97                 :          0 :         int err = 0;
      98                 :          0 :         u32 val;
      99                 :            : 
     100   [ #  #  #  # ]:          0 :         err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,
     101                 :            :                                         val, val == 1U, 10U, 100000U);
     102                 :          0 :         if (err < 0)
     103                 :            :                 return;
     104                 :            : 
     105                 :          0 :         aq_mdio_write_word(aq_hw, mmd, address, data);
     106                 :          0 :         hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);
     107                 :            : }
     108                 :            : 
     109                 :         33 : bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw)
     110                 :            : {
     111                 :         33 :         u16 val;
     112                 :            : 
     113         [ +  + ]:        256 :         for (aq_hw->phy_id = 0; aq_hw->phy_id < HW_ATL_PHY_ID_MAX;
     114                 :        223 :              ++aq_hw->phy_id) {
     115                 :            :                 /* PMA Standard Device Identifier 2: Address 1.3 */
     116                 :        251 :                 val = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);
     117                 :            : 
     118         [ +  + ]:        251 :                 if (val != 0xffff)
     119                 :            :                         return true;
     120                 :            :         }
     121                 :            : 
     122                 :            :         return false;
     123                 :            : }
     124                 :            : 
     125                 :         33 : bool aq_phy_init(struct aq_hw_s *aq_hw)
     126                 :            : {
     127                 :         33 :         u32 dev_id;
     128                 :            : 
     129         [ +  - ]:         33 :         if (aq_hw->phy_id == HW_ATL_PHY_ID_MAX)
     130         [ +  + ]:         33 :                 if (!aq_phy_init_phy_id(aq_hw))
     131                 :            :                         return false;
     132                 :            : 
     133                 :            :         /* PMA Standard Device Identifier:
     134                 :            :          * Address 1.2 = MSW,
     135                 :            :          * Address 1.3 = LSW
     136                 :            :          */
     137                 :         28 :         dev_id = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 2);
     138                 :         28 :         dev_id <<= 16;
     139                 :         28 :         dev_id |= aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);
     140                 :            : 
     141         [ +  + ]:         28 :         if (dev_id == 0xffffffff) {
     142                 :          3 :                 aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
     143                 :          3 :                 return false;
     144                 :            :         }
     145                 :            : 
     146                 :            :         return true;
     147                 :            : }

Generated by: LCOV version 1.14