LCOV - code coverage report
Current view: top level - drivers/net/wireless/realtek/rtw88 - efuse.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 79 85 92.9 %
Date: 2022-03-28 16:04:14 Functions: 3 3 100.0 %
Branches: 29 38 76.3 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
       2                 :            : /* Copyright(c) 2018-2019  Realtek Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "main.h"
       6                 :            : #include "efuse.h"
       7                 :            : #include "reg.h"
       8                 :            : #include "debug.h"
       9                 :            : 
      10                 :            : #define RTW_EFUSE_BANK_WIFI             0x0
      11                 :            : 
      12                 :          9 : static void switch_efuse_bank(struct rtw_dev *rtwdev)
      13                 :            : {
      14                 :          9 :         rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL,
      15                 :            :                          RTW_EFUSE_BANK_WIFI);
      16                 :            : }
      17                 :            : 
      18                 :            : #define invalid_efuse_header(hdr1, hdr2) \
      19                 :            :         ((hdr1) == 0xff || (((hdr1) & 0x1f) == 0xf && (hdr2) == 0xff))
      20                 :            : #define invalid_efuse_content(word_en, i) \
      21                 :            :         (((word_en) & BIT(i)) != 0x0)
      22                 :            : #define get_efuse_blk_idx_2_byte(hdr1, hdr2) \
      23                 :            :         ((((hdr2) & 0xf0) >> 1) | (((hdr1) >> 5) & 0x07))
      24                 :            : #define get_efuse_blk_idx_1_byte(hdr1) \
      25                 :            :         (((hdr1) & 0xf0) >> 4)
      26                 :            : #define block_idx_to_logical_idx(blk_idx, i) \
      27                 :            :         (((blk_idx) << 3) + ((i) << 1))
      28                 :            : 
      29                 :            : /* efuse header format
      30                 :            :  *
      31                 :            :  * | 7        5   4    0 | 7        4   3          0 | 15  8  7   0 |
      32                 :            :  *   block[2:0]   0 1111   block[6:3]   word_en[3:0]   byte0  byte1
      33                 :            :  * | header 1 (optional) |          header 2         |    word N    |
      34                 :            :  *
      35                 :            :  * word_en: 4 bits each word. 0 -> write; 1 -> not write
      36                 :            :  * N: 1~4, depends on word_en
      37                 :            :  */
      38                 :          9 : static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
      39                 :            :                                       u8 *log_map)
      40                 :            : {
      41                 :          9 :         u32 physical_size = rtwdev->efuse.physical_size;
      42                 :          9 :         u32 protect_size = rtwdev->efuse.protect_size;
      43                 :          9 :         u32 logical_size = rtwdev->efuse.logical_size;
      44                 :          9 :         u32 phy_idx, log_idx;
      45                 :          9 :         u8 hdr1, hdr2;
      46                 :          9 :         u8 blk_idx;
      47                 :          9 :         u8 word_en;
      48                 :          9 :         int i;
      49                 :            : 
      50         [ +  + ]:        680 :         for (phy_idx = 0; phy_idx < physical_size - protect_size;) {
      51                 :        676 :                 hdr1 = phy_map[phy_idx];
      52                 :        676 :                 hdr2 = phy_map[phy_idx + 1];
      53   [ +  +  +  +  :        676 :                 if (invalid_efuse_header(hdr1, hdr2))
                   +  - ]
      54                 :            :                         break;
      55                 :            : 
      56         [ +  + ]:        672 :                 if ((hdr1 & 0x1f) == 0xf) {
      57                 :            :                         /* 2-byte header format */
      58                 :          8 :                         blk_idx = get_efuse_blk_idx_2_byte(hdr1, hdr2);
      59                 :          8 :                         word_en = hdr2 & 0xf;
      60                 :          8 :                         phy_idx += 2;
      61                 :            :                 } else {
      62                 :            :                         /* 1-byte header format */
      63                 :        664 :                         blk_idx = get_efuse_blk_idx_1_byte(hdr1);
      64                 :        664 :                         word_en = hdr1 & 0xf;
      65                 :        664 :                         phy_idx += 1;
      66                 :            :                 }
      67                 :            : 
      68         [ +  + ]:       3356 :                 for (i = 0; i < 4; i++) {
      69         [ +  + ]:       2685 :                         if (invalid_efuse_content(word_en, i))
      70                 :          1 :                                 continue;
      71                 :            : 
      72                 :       2684 :                         log_idx = block_idx_to_logical_idx(blk_idx, i);
      73         [ +  + ]:       2684 :                         if (phy_idx + 1 > physical_size - protect_size ||
      74         [ +  - ]:       2683 :                             log_idx + 1 > logical_size)
      75                 :            :                                 return -EINVAL;
      76                 :            : 
      77                 :       2683 :                         log_map[log_idx] = phy_map[phy_idx];
      78                 :       2683 :                         log_map[log_idx + 1] = phy_map[phy_idx + 1];
      79                 :       2683 :                         phy_idx += 2;
      80                 :            :                 }
      81                 :            :         }
      82                 :          8 :         printk(KERN_INFO "dump till: phy_idx %x\n", phy_idx);
      83                 :          8 :         return 0;
      84                 :            : }
      85                 :            : 
      86                 :          9 : static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
      87                 :            : {
      88                 :          9 :         struct rtw_chip_info *chip = rtwdev->chip;
      89                 :          9 :         u32 size = rtwdev->efuse.physical_size;
      90                 :          9 :         u32 efuse_ctl;
      91                 :          9 :         u32 addr;
      92                 :          9 :         u32 cnt;
      93                 :            : 
      94                 :          9 :         switch_efuse_bank(rtwdev);
      95                 :            : 
      96                 :            :         /* disable 2.5V LDO */
      97                 :          9 :         chip->ops->cfg_ldo25(rtwdev, false);
      98                 :            : 
      99                 :          9 :         efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
     100                 :            : 
     101         [ +  + ]:       9234 :         for (addr = 0; addr < size; addr++) {
     102                 :       9216 :                 efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
     103                 :       9216 :                 efuse_ctl |= (addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR;
     104                 :       9216 :                 rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG));
     105                 :            : 
     106                 :       9216 :                 cnt = 1000000;
     107                 :      18555 :                 do {
     108                 :      18555 :                         udelay(1);
     109                 :      18555 :                         efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
     110         [ +  - ]:      18555 :                         if (--cnt == 0)
     111                 :            :                                 return -EBUSY;
     112         [ +  + ]:      18555 :                 } while (!(efuse_ctl & BIT_EF_FLAG));
     113                 :            : 
     114                 :       9216 :                 *(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
     115                 :            :         }
     116                 :          9 :         printk(KERN_INFO "physical addr till: %x", addr);
     117                 :            : 
     118                 :          9 :         return 0;
     119                 :            : }
     120                 :            : 
     121                 :          9 : int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
     122                 :            : {
     123                 :          9 :         struct rtw_chip_info *chip = rtwdev->chip;
     124                 :          9 :         struct rtw_efuse *efuse = &rtwdev->efuse;
     125                 :          9 :         u32 phy_size = efuse->physical_size;
     126                 :          9 :         u32 log_size = efuse->logical_size;
     127                 :          9 :         u8 *phy_map = NULL;
     128                 :          9 :         u8 *log_map = NULL;
     129                 :          9 :         int ret = 0;
     130                 :            : 
     131         [ -  + ]:          9 :         phy_map = kmalloc(phy_size, GFP_KERNEL);
     132         [ -  + ]:          9 :         log_map = kmalloc(log_size, GFP_KERNEL);
     133   [ +  -  -  + ]:          9 :         if (!phy_map || !log_map) {
     134                 :          0 :                 ret = -ENOMEM;
     135                 :          0 :                 goto out_free;
     136                 :            :         }
     137                 :            : 
     138                 :          9 :         ret = rtw_dump_physical_efuse_map(rtwdev, phy_map);
     139         [ -  + ]:          9 :         if (ret) {
     140                 :          0 :                 rtw_err(rtwdev, "failed to dump efuse physical map\n");
     141                 :          0 :                 goto out_free;
     142                 :            :         }
     143                 :            : 
     144                 :          9 :         memset(log_map, 0xff, log_size);
     145                 :          9 :         ret = rtw_dump_logical_efuse_map(rtwdev, phy_map, log_map);
     146         [ +  + ]:          9 :         if (ret) {
     147                 :          1 :                 rtw_err(rtwdev, "failed to dump efuse logical map\n");
     148                 :          1 :                 goto out_free;
     149                 :            :         }
     150                 :            : 
     151                 :          8 :         ret = chip->ops->read_efuse(rtwdev, log_map);
     152         [ +  - ]:          8 :         if (ret) {
     153                 :          0 :                 rtw_err(rtwdev, "failed to read efuse map\n");
     154                 :          0 :                 goto out_free;
     155                 :            :         }
     156                 :            : 
     157                 :          8 : out_free:
     158                 :          9 :         kfree(log_map);
     159                 :          9 :         kfree(phy_map);
     160                 :            : 
     161                 :          9 :         return ret;
     162                 :            : }

Generated by: LCOV version 1.14