Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2019-2020  Realtek Corporation
0003  */
0004 
0005 #include "debug.h"
0006 #include "efuse.h"
0007 #include "mac.h"
0008 #include "reg.h"
0009 
0010 enum rtw89_efuse_bank {
0011     RTW89_EFUSE_BANK_WIFI,
0012     RTW89_EFUSE_BANK_BT,
0013 };
0014 
0015 static int rtw89_switch_efuse_bank(struct rtw89_dev *rtwdev,
0016                    enum rtw89_efuse_bank bank)
0017 {
0018     u8 val;
0019 
0020     if (rtwdev->chip->chip_id != RTL8852A)
0021         return 0;
0022 
0023     val = rtw89_read32_mask(rtwdev, R_AX_EFUSE_CTRL_1,
0024                 B_AX_EF_CELL_SEL_MASK);
0025     if (bank == val)
0026         return 0;
0027 
0028     rtw89_write32_mask(rtwdev, R_AX_EFUSE_CTRL_1, B_AX_EF_CELL_SEL_MASK,
0029                bank);
0030 
0031     val = rtw89_read32_mask(rtwdev, R_AX_EFUSE_CTRL_1,
0032                 B_AX_EF_CELL_SEL_MASK);
0033     if (bank == val)
0034         return 0;
0035 
0036     return -EBUSY;
0037 }
0038 
0039 static void rtw89_enable_otp_burst_mode(struct rtw89_dev *rtwdev, bool en)
0040 {
0041     if (en)
0042         rtw89_write32_set(rtwdev, R_AX_EFUSE_CTRL_1_V1, B_AX_EF_BURST);
0043     else
0044         rtw89_write32_clr(rtwdev, R_AX_EFUSE_CTRL_1_V1, B_AX_EF_BURST);
0045 }
0046 
0047 static void rtw89_enable_efuse_pwr_cut_ddv(struct rtw89_dev *rtwdev)
0048 {
0049     enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
0050     struct rtw89_hal *hal = &rtwdev->hal;
0051 
0052     if (chip_id == RTL8852A)
0053         return;
0054 
0055     rtw89_write8_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
0056     rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14);
0057 
0058     fsleep(1000);
0059 
0060     rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15);
0061     rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE);
0062     if (chip_id == RTL8852B && hal->cv == CHIP_CAV)
0063         rtw89_enable_otp_burst_mode(rtwdev, true);
0064 }
0065 
0066 static void rtw89_disable_efuse_pwr_cut_ddv(struct rtw89_dev *rtwdev)
0067 {
0068     enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
0069     struct rtw89_hal *hal = &rtwdev->hal;
0070 
0071     if (chip_id == RTL8852A)
0072         return;
0073 
0074     if (chip_id == RTL8852B && hal->cv == CHIP_CAV)
0075         rtw89_enable_otp_burst_mode(rtwdev, false);
0076 
0077     rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE);
0078     rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15);
0079 
0080     fsleep(1000);
0081 
0082     rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14);
0083     rtw89_write8_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
0084 }
0085 
0086 static int rtw89_dump_physical_efuse_map_ddv(struct rtw89_dev *rtwdev, u8 *map,
0087                          u32 dump_addr, u32 dump_size)
0088 {
0089     u32 efuse_ctl;
0090     u32 addr;
0091     int ret;
0092 
0093     rtw89_enable_efuse_pwr_cut_ddv(rtwdev);
0094 
0095     for (addr = dump_addr; addr < dump_addr + dump_size; addr++) {
0096         efuse_ctl = u32_encode_bits(addr, B_AX_EF_ADDR_MASK);
0097         rtw89_write32(rtwdev, R_AX_EFUSE_CTRL, efuse_ctl & ~B_AX_EF_RDY);
0098 
0099         ret = read_poll_timeout_atomic(rtw89_read32, efuse_ctl,
0100                            efuse_ctl & B_AX_EF_RDY, 1, 1000000,
0101                            true, rtwdev, R_AX_EFUSE_CTRL);
0102         if (ret)
0103             return -EBUSY;
0104 
0105         *map++ = (u8)(efuse_ctl & 0xff);
0106     }
0107 
0108     rtw89_disable_efuse_pwr_cut_ddv(rtwdev);
0109 
0110     return 0;
0111 }
0112 
0113 static int rtw89_dump_physical_efuse_map_dav(struct rtw89_dev *rtwdev, u8 *map,
0114                          u32 dump_addr, u32 dump_size)
0115 {
0116     u32 addr;
0117     u8 val8;
0118     int err;
0119     int ret;
0120 
0121     for (addr = dump_addr; addr < dump_addr + dump_size; addr++) {
0122         ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0x40, FULL_BIT_MASK);
0123         if (ret)
0124             return ret;
0125         ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_LOW_ADDR,
0126                           addr & 0xff, XTAL_SI_LOW_ADDR_MASK);
0127         if (ret)
0128             return ret;
0129         ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, addr >> 8,
0130                           XTAL_SI_HIGH_ADDR_MASK);
0131         if (ret)
0132             return ret;
0133         ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0,
0134                           XTAL_SI_MODE_SEL_MASK);
0135         if (ret)
0136             return ret;
0137 
0138         ret = read_poll_timeout_atomic(rtw89_mac_read_xtal_si, err,
0139                            !err && (val8 & XTAL_SI_RDY),
0140                            1, 10000, false,
0141                            rtwdev, XTAL_SI_CTRL, &val8);
0142         if (ret) {
0143             rtw89_warn(rtwdev, "failed to read dav efuse\n");
0144             return ret;
0145         }
0146 
0147         ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_READ_VAL, &val8);
0148         if (ret)
0149             return ret;
0150         *map++ = val8;
0151     }
0152 
0153     return 0;
0154 }
0155 
0156 static int rtw89_dump_physical_efuse_map(struct rtw89_dev *rtwdev, u8 *map,
0157                      u32 dump_addr, u32 dump_size, bool dav)
0158 {
0159     int ret;
0160 
0161     if (!map || dump_size == 0)
0162         return 0;
0163 
0164     rtw89_switch_efuse_bank(rtwdev, RTW89_EFUSE_BANK_WIFI);
0165 
0166     if (dav) {
0167         ret = rtw89_dump_physical_efuse_map_dav(rtwdev, map, dump_addr, dump_size);
0168         if (ret)
0169             return ret;
0170     } else {
0171         ret = rtw89_dump_physical_efuse_map_ddv(rtwdev, map, dump_addr, dump_size);
0172         if (ret)
0173             return ret;
0174     }
0175 
0176     return 0;
0177 }
0178 
0179 #define invalid_efuse_header(hdr1, hdr2) \
0180     ((hdr1) == 0xff || (hdr2) == 0xff)
0181 #define invalid_efuse_content(word_en, i) \
0182     (((word_en) & BIT(i)) != 0x0)
0183 #define get_efuse_blk_idx(hdr1, hdr2) \
0184     ((((hdr2) & 0xf0) >> 4) | (((hdr1) & 0x0f) << 4))
0185 #define block_idx_to_logical_idx(blk_idx, i) \
0186     (((blk_idx) << 3) + ((i) << 1))
0187 static int rtw89_dump_logical_efuse_map(struct rtw89_dev *rtwdev, u8 *phy_map,
0188                     u8 *log_map)
0189 {
0190     u32 physical_size = rtwdev->chip->physical_efuse_size;
0191     u32 logical_size = rtwdev->chip->logical_efuse_size;
0192     u8 sec_ctrl_size = rtwdev->chip->sec_ctrl_efuse_size;
0193     u32 phy_idx = sec_ctrl_size;
0194     u32 log_idx;
0195     u8 hdr1, hdr2;
0196     u8 blk_idx;
0197     u8 word_en;
0198     int i;
0199 
0200     if (!phy_map)
0201         return 0;
0202 
0203     while (phy_idx < physical_size - sec_ctrl_size) {
0204         hdr1 = phy_map[phy_idx];
0205         hdr2 = phy_map[phy_idx + 1];
0206         if (invalid_efuse_header(hdr1, hdr2))
0207             break;
0208 
0209         blk_idx = get_efuse_blk_idx(hdr1, hdr2);
0210         word_en = hdr2 & 0xf;
0211         phy_idx += 2;
0212 
0213         for (i = 0; i < 4; i++) {
0214             if (invalid_efuse_content(word_en, i))
0215                 continue;
0216 
0217             log_idx = block_idx_to_logical_idx(blk_idx, i);
0218             if (phy_idx + 1 > physical_size - sec_ctrl_size - 1 ||
0219                 log_idx + 1 > logical_size)
0220                 return -EINVAL;
0221 
0222             log_map[log_idx] = phy_map[phy_idx];
0223             log_map[log_idx + 1] = phy_map[phy_idx + 1];
0224             phy_idx += 2;
0225         }
0226     }
0227     return 0;
0228 }
0229 
0230 int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev)
0231 {
0232     u32 phy_size = rtwdev->chip->physical_efuse_size;
0233     u32 log_size = rtwdev->chip->logical_efuse_size;
0234     u32 dav_phy_size = rtwdev->chip->dav_phy_efuse_size;
0235     u32 dav_log_size = rtwdev->chip->dav_log_efuse_size;
0236     u32 full_log_size = log_size + dav_log_size;
0237     u8 *phy_map = NULL;
0238     u8 *log_map = NULL;
0239     u8 *dav_phy_map = NULL;
0240     u8 *dav_log_map = NULL;
0241     int ret;
0242 
0243     if (rtw89_read16(rtwdev, R_AX_SYS_WL_EFUSE_CTRL) & B_AX_AUTOLOAD_SUS)
0244         rtwdev->efuse.valid = true;
0245     else
0246         rtw89_warn(rtwdev, "failed to check efuse autoload\n");
0247 
0248     phy_map = kmalloc(phy_size, GFP_KERNEL);
0249     log_map = kmalloc(full_log_size, GFP_KERNEL);
0250     if (dav_phy_size && dav_log_size) {
0251         dav_phy_map = kmalloc(dav_phy_size, GFP_KERNEL);
0252         dav_log_map = log_map + log_size;
0253     }
0254 
0255     if (!phy_map || !log_map || (dav_phy_size && !dav_phy_map)) {
0256         ret = -ENOMEM;
0257         goto out_free;
0258     }
0259 
0260     ret = rtw89_dump_physical_efuse_map(rtwdev, phy_map, 0, phy_size, false);
0261     if (ret) {
0262         rtw89_warn(rtwdev, "failed to dump efuse physical map\n");
0263         goto out_free;
0264     }
0265     ret = rtw89_dump_physical_efuse_map(rtwdev, dav_phy_map, 0, dav_phy_size, true);
0266     if (ret) {
0267         rtw89_warn(rtwdev, "failed to dump efuse dav physical map\n");
0268         goto out_free;
0269     }
0270 
0271     memset(log_map, 0xff, full_log_size);
0272     ret = rtw89_dump_logical_efuse_map(rtwdev, phy_map, log_map);
0273     if (ret) {
0274         rtw89_warn(rtwdev, "failed to dump efuse logical map\n");
0275         goto out_free;
0276     }
0277     ret = rtw89_dump_logical_efuse_map(rtwdev, dav_phy_map, dav_log_map);
0278     if (ret) {
0279         rtw89_warn(rtwdev, "failed to dump efuse dav logical map\n");
0280         goto out_free;
0281     }
0282 
0283     rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, full_log_size);
0284 
0285     ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map);
0286     if (ret) {
0287         rtw89_warn(rtwdev, "failed to read efuse map\n");
0288         goto out_free;
0289     }
0290 
0291 out_free:
0292     kfree(dav_phy_map);
0293     kfree(log_map);
0294     kfree(phy_map);
0295 
0296     return ret;
0297 }
0298 
0299 int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev)
0300 {
0301     u32 phycap_addr = rtwdev->chip->phycap_addr;
0302     u32 phycap_size = rtwdev->chip->phycap_size;
0303     u8 *phycap_map = NULL;
0304     int ret = 0;
0305 
0306     if (!phycap_size)
0307         return 0;
0308 
0309     phycap_map = kmalloc(phycap_size, GFP_KERNEL);
0310     if (!phycap_map)
0311         return -ENOMEM;
0312 
0313     ret = rtw89_dump_physical_efuse_map(rtwdev, phycap_map,
0314                         phycap_addr, phycap_size, false);
0315     if (ret) {
0316         rtw89_warn(rtwdev, "failed to dump phycap map\n");
0317         goto out_free;
0318     }
0319 
0320     ret = rtwdev->chip->ops->read_phycap(rtwdev, phycap_map);
0321     if (ret) {
0322         rtw89_warn(rtwdev, "failed to read phycap map\n");
0323         goto out_free;
0324     }
0325 
0326 out_free:
0327     kfree(phycap_map);
0328 
0329     return ret;
0330 }