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 : : }