1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2023 Realtek Corporation 3 */ 4 5 #include "debug.h" 6 #include "efuse.h" 7 #include "mac.h" 8 #include "reg.h" 9 10 static void rtw89_enable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev) 11 { 12 const struct rtw89_chip_info *chip = rtwdev->chip; 13 struct rtw89_hal *hal = &rtwdev->hal; 14 bool aphy_patch = true; 15 16 if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV) 17 aphy_patch = false; 18 19 rtw89_write8_set(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK); 20 21 if (aphy_patch) { 22 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S); 23 mdelay(1); 24 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B); 25 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE); 26 } 27 28 rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST); 29 } 30 31 static void rtw89_disable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev) 32 { 33 const struct rtw89_chip_info *chip = rtwdev->chip; 34 struct rtw89_hal *hal = &rtwdev->hal; 35 bool aphy_patch = true; 36 37 if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV) 38 aphy_patch = false; 39 40 if (aphy_patch) { 41 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE); 42 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B); 43 mdelay(1); 44 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S); 45 } 46 47 rtw89_write8_clr(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK); 48 rtw89_write32_clr(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST); 49 } 50 51 static int rtw89_dump_physical_efuse_map_ddv_be(struct rtw89_dev *rtwdev, u8 *map, 52 u32 dump_addr, u32 dump_size) 53 { 54 u32 efuse_ctl; 55 u32 addr; 56 u32 data; 57 int ret; 58 59 if (!IS_ALIGNED(dump_addr, 4) || !IS_ALIGNED(dump_size, 4)) { 60 rtw89_err(rtwdev, "Efuse addr 0x%x or size 0x%x not aligned\n", 61 dump_addr, dump_size); 62 return -EINVAL; 63 } 64 65 rtw89_enable_efuse_pwr_cut_ddv_be(rtwdev); 66 67 for (addr = dump_addr; addr < dump_addr + dump_size; addr += 4, map += 4) { 68 efuse_ctl = u32_encode_bits(addr, B_BE_EF_ADDR_MASK); 69 rtw89_write32(rtwdev, R_BE_EFUSE_CTRL, efuse_ctl & ~B_BE_EF_RDY); 70 71 ret = read_poll_timeout_atomic(rtw89_read32, efuse_ctl, 72 efuse_ctl & B_BE_EF_RDY, 1, 1000000, 73 true, rtwdev, R_BE_EFUSE_CTRL); 74 if (ret) 75 return -EBUSY; 76 77 data = rtw89_read32(rtwdev, R_BE_EFUSE_CTRL_1_V1); 78 *((__le32 *)map) = cpu_to_le32(data); 79 } 80 81 rtw89_disable_efuse_pwr_cut_ddv_be(rtwdev); 82 83 return 0; 84 } 85 86 static int rtw89_dump_physical_efuse_map_dav_be(struct rtw89_dev *rtwdev, u8 *map, 87 u32 dump_addr, u32 dump_size) 88 { 89 u32 addr; 90 u8 val8; 91 int err; 92 int ret; 93 94 for (addr = dump_addr; addr < dump_addr + dump_size; addr++) { 95 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0x40, 96 FULL_BIT_MASK); 97 if (ret) 98 return ret; 99 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_LOW_ADDR, addr & 0xff, 100 XTAL_SI_LOW_ADDR_MASK); 101 if (ret) 102 return ret; 103 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, addr >> 8, 104 XTAL_SI_HIGH_ADDR_MASK); 105 if (ret) 106 return ret; 107 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0, 108 XTAL_SI_MODE_SEL_MASK); 109 if (ret) 110 return ret; 111 112 ret = read_poll_timeout_atomic(rtw89_mac_read_xtal_si, err, 113 !err && (val8 & XTAL_SI_RDY), 114 1, 10000, false, 115 rtwdev, XTAL_SI_CTRL, &val8); 116 if (ret) { 117 rtw89_warn(rtwdev, "failed to read dav efuse\n"); 118 return ret; 119 } 120 121 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_READ_VAL, &val8); 122 if (ret) 123 return ret; 124 *map++ = val8; 125 } 126 127 return 0; 128 } 129 130 int rtw89_cnv_efuse_state_be(struct rtw89_dev *rtwdev, bool idle) 131 { 132 u32 val; 133 int ret = 0; 134 135 if (idle) { 136 rtw89_write32_set(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN); 137 } else { 138 rtw89_write32_clr(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN); 139 140 ret = read_poll_timeout(rtw89_read32_mask, val, 141 val == MAC_AX_SYS_ACT, 50, 5000, 142 false, rtwdev, R_BE_IC_PWR_STATE, 143 B_BE_WHOLE_SYS_PWR_STE_MASK); 144 if (ret) 145 rtw89_warn(rtwdev, "failed to convert efuse state\n"); 146 } 147 148 return ret; 149 } 150 151 static int rtw89_dump_physical_efuse_map_be(struct rtw89_dev *rtwdev, u8 *map, 152 u32 dump_addr, u32 dump_size, bool dav) 153 { 154 int ret; 155 156 if (!map || dump_size == 0) 157 return 0; 158 159 rtw89_cnv_efuse_state_be(rtwdev, false); 160 161 if (dav) { 162 ret = rtw89_dump_physical_efuse_map_dav_be(rtwdev, map, 163 dump_addr, dump_size); 164 if (ret) 165 return ret; 166 167 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map dav: ", map, dump_size); 168 } else { 169 ret = rtw89_dump_physical_efuse_map_ddv_be(rtwdev, map, 170 dump_addr, dump_size); 171 if (ret) 172 return ret; 173 174 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map ddv: ", map, dump_size); 175 } 176 177 rtw89_cnv_efuse_state_be(rtwdev, true); 178 179 return 0; 180 } 181 182 #define EFUSE_HDR_CONST_MASK GENMASK(23, 20) 183 #define EFUSE_HDR_PAGE_MASK GENMASK(19, 17) 184 #define EFUSE_HDR_OFFSET_MASK GENMASK(16, 4) 185 #define EFUSE_HDR_OFFSET_DAV_MASK GENMASK(11, 4) 186 #define EFUSE_HDR_WORD_EN_MASK GENMASK(3, 0) 187 188 #define invalid_efuse_header_be(hdr1, hdr2, hdr3) \ 189 ((hdr1) == 0xff || (hdr2) == 0xff || (hdr3) == 0xff) 190 #define invalid_efuse_content_be(word_en, i) \ 191 (((word_en) & BIT(i)) != 0x0) 192 #define get_efuse_blk_idx_be(hdr1, hdr2, hdr3) \ 193 (((hdr1) << 16) | ((hdr2) << 8) | (hdr3)) 194 #define block_idx_to_logical_idx_be(blk_idx, i) \ 195 (((blk_idx) << 3) + ((i) << 1)) 196 197 #define invalid_efuse_header_dav_be(hdr1, hdr2) \ 198 ((hdr1) == 0xff || (hdr2) == 0xff) 199 #define get_efuse_blk_idx_dav_be(hdr1, hdr2) \ 200 (((hdr1) << 8) | (hdr2)) 201 202 static int rtw89_eeprom_parser_be(struct rtw89_dev *rtwdev, 203 const u8 *phy_map, u32 phy_size, u8 *log_map, 204 const struct rtw89_efuse_block_cfg *efuse_block) 205 { 206 const struct rtw89_chip_info *chip = rtwdev->chip; 207 enum rtw89_efuse_block blk_page, page; 208 u32 size = efuse_block->size; 209 u32 phy_idx, log_idx; 210 u32 hdr, page_offset; 211 u8 hdr1, hdr2, hdr3; 212 u8 i, val0, val1; 213 u32 min, max; 214 u16 blk_idx; 215 u8 word_en; 216 217 page = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_ID_MASK); 218 page_offset = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_SIZE_MASK); 219 220 min = ALIGN_DOWN(page_offset, 2); 221 max = ALIGN(page_offset + size, 2); 222 223 memset(log_map, 0xff, size); 224 225 phy_idx = chip->sec_ctrl_efuse_size; 226 227 do { 228 if (page == RTW89_EFUSE_BLOCK_ADIE) { 229 hdr1 = phy_map[phy_idx]; 230 hdr2 = phy_map[phy_idx + 1]; 231 if (invalid_efuse_header_dav_be(hdr1, hdr2)) 232 break; 233 234 phy_idx += 2; 235 236 hdr = get_efuse_blk_idx_dav_be(hdr1, hdr2); 237 238 blk_page = RTW89_EFUSE_BLOCK_ADIE; 239 blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_DAV_MASK); 240 word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK); 241 } else { 242 hdr1 = phy_map[phy_idx]; 243 hdr2 = phy_map[phy_idx + 1]; 244 hdr3 = phy_map[phy_idx + 2]; 245 if (invalid_efuse_header_be(hdr1, hdr2, hdr3)) 246 break; 247 248 phy_idx += 3; 249 250 hdr = get_efuse_blk_idx_be(hdr1, hdr2, hdr3); 251 252 blk_page = u32_get_bits(hdr, EFUSE_HDR_PAGE_MASK); 253 blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_MASK); 254 word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK); 255 } 256 257 if (blk_idx >= RTW89_EFUSE_MAX_BLOCK_SIZE >> 3) { 258 rtw89_err(rtwdev, "[ERR]efuse idx:0x%X\n", phy_idx - 3); 259 rtw89_err(rtwdev, "[ERR]read hdr:0x%X\n", hdr); 260 return -EINVAL; 261 } 262 263 for (i = 0; i < 4; i++) { 264 if (invalid_efuse_content_be(word_en, i)) 265 continue; 266 267 if (phy_idx >= phy_size - 1) 268 return -EINVAL; 269 270 log_idx = block_idx_to_logical_idx_be(blk_idx, i); 271 272 if (blk_page == page && log_idx >= min && log_idx < max) { 273 val0 = phy_map[phy_idx]; 274 val1 = phy_map[phy_idx + 1]; 275 276 if (log_idx == min && page_offset > min) { 277 log_map[log_idx - page_offset + 1] = val1; 278 } else if (log_idx + 2 == max && 279 page_offset + size < max) { 280 log_map[log_idx - page_offset] = val0; 281 } else { 282 log_map[log_idx - page_offset] = val0; 283 log_map[log_idx - page_offset + 1] = val1; 284 } 285 } 286 phy_idx += 2; 287 } 288 } while (phy_idx < phy_size); 289 290 return 0; 291 } 292 293 static int rtw89_parse_logical_efuse_block_be(struct rtw89_dev *rtwdev, 294 const u8 *phy_map, u32 phy_size, 295 enum rtw89_efuse_block block) 296 { 297 const struct rtw89_chip_info *chip = rtwdev->chip; 298 const struct rtw89_efuse_block_cfg *efuse_block; 299 u8 *log_map; 300 int ret; 301 302 efuse_block = &chip->efuse_blocks[block]; 303 304 log_map = kmalloc(efuse_block->size, GFP_KERNEL); 305 if (!log_map) 306 return -ENOMEM; 307 308 ret = rtw89_eeprom_parser_be(rtwdev, phy_map, phy_size, log_map, efuse_block); 309 if (ret) { 310 rtw89_warn(rtwdev, "failed to dump efuse logical block %d\n", block); 311 goto out_free; 312 } 313 314 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, efuse_block->size); 315 316 ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map, block); 317 if (ret) { 318 rtw89_warn(rtwdev, "failed to read efuse map\n"); 319 goto out_free; 320 } 321 322 out_free: 323 kfree(log_map); 324 325 return ret; 326 } 327 328 int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev) 329 { 330 u32 phy_size = rtwdev->chip->physical_efuse_size; 331 u32 dav_phy_size = rtwdev->chip->dav_phy_efuse_size; 332 enum rtw89_efuse_block block; 333 u8 *phy_map = NULL; 334 u8 *dav_phy_map = NULL; 335 int ret; 336 337 if (rtw89_read16(rtwdev, R_BE_SYS_WL_EFUSE_CTRL) & B_BE_AUTOLOAD_SUS) 338 rtwdev->efuse.valid = true; 339 else 340 rtw89_warn(rtwdev, "failed to check efuse autoload\n"); 341 342 phy_map = kmalloc(phy_size, GFP_KERNEL); 343 if (dav_phy_size) 344 dav_phy_map = kmalloc(dav_phy_size, GFP_KERNEL); 345 346 if (!phy_map || (dav_phy_size && !dav_phy_map)) { 347 ret = -ENOMEM; 348 goto out_free; 349 } 350 351 ret = rtw89_dump_physical_efuse_map_be(rtwdev, phy_map, 0, phy_size, false); 352 if (ret) { 353 rtw89_warn(rtwdev, "failed to dump efuse physical map\n"); 354 goto out_free; 355 } 356 ret = rtw89_dump_physical_efuse_map_be(rtwdev, dav_phy_map, 0, dav_phy_size, true); 357 if (ret) { 358 rtw89_warn(rtwdev, "failed to dump efuse dav physical map\n"); 359 goto out_free; 360 } 361 362 if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) 363 block = RTW89_EFUSE_BLOCK_HCI_DIG_USB; 364 else 365 block = RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO; 366 367 ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, block); 368 if (ret) { 369 rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n", 370 RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO); 371 goto out_free; 372 } 373 374 ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, 375 RTW89_EFUSE_BLOCK_RF); 376 if (ret) { 377 rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n", 378 RTW89_EFUSE_BLOCK_RF); 379 goto out_free; 380 } 381 382 out_free: 383 kfree(dav_phy_map); 384 kfree(phy_map); 385 386 return ret; 387 } 388 389 int rtw89_parse_phycap_map_be(struct rtw89_dev *rtwdev) 390 { 391 u32 phycap_addr = rtwdev->chip->phycap_addr; 392 u32 phycap_size = rtwdev->chip->phycap_size; 393 u8 *phycap_map = NULL; 394 int ret = 0; 395 396 if (!phycap_size) 397 return 0; 398 399 phycap_map = kmalloc(phycap_size, GFP_KERNEL); 400 if (!phycap_map) 401 return -ENOMEM; 402 403 ret = rtw89_dump_physical_efuse_map_be(rtwdev, phycap_map, 404 phycap_addr, phycap_size, false); 405 if (ret) { 406 rtw89_warn(rtwdev, "failed to dump phycap map\n"); 407 goto out_free; 408 } 409 410 ret = rtwdev->chip->ops->read_phycap(rtwdev, phycap_map); 411 if (ret) { 412 rtw89_warn(rtwdev, "failed to read phycap map\n"); 413 goto out_free; 414 } 415 416 out_free: 417 kfree(phycap_map); 418 419 return ret; 420 } 421