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 #define EFUSE_EXTERNALPN_ADDR_BE 0x1580 11 #define EFUSE_SERIALNUM_ADDR_BE 0x1581 12 #define EFUSE_SB_CRYP_SEL_ADDR 0x1582 13 #define EFUSE_SB_CRYP_SEL_SIZE 2 14 #define EFUSE_SB_CRYP_SEL_DEFAULT 0xFFFF 15 #define SB_SEL_MGN_MAX_SIZE 2 16 #define EFUSE_SEC_BE_START 0x1580 17 #define EFUSE_SEC_BE_SIZE 4 18 19 #define EFUSE_VCORE_PWR_BE 0x17D6 20 #define EFUSE_VCORE_PWR_BE_VALID BIT(12) 21 #define EFUSE_VCORE_PWR_BE_VAL GENMASK(11, 0) 22 #define SWR_DIG_MIN 860 23 #define EFUSE_DIG_K_STEP 0xC 24 #define EFUSE_DSWR_V0_86_BE 0x17DA 25 #define EFUSE_DSWR_V0_86_BE_VALID BIT(5) 26 #define EFUSE_DSWR_V0_86_BE_VAL GENMASK(4, 0) 27 28 static const u32 sb_sel_mgn[SB_SEL_MGN_MAX_SIZE] = { 29 0x8000100, 0xC000180 30 }; 31 32 static void rtw89_enable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev) 33 { 34 const struct rtw89_chip_info *chip = rtwdev->chip; 35 struct rtw89_hal *hal = &rtwdev->hal; 36 bool aphy_patch = true; 37 38 if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV) 39 aphy_patch = false; 40 41 rtw89_write8_set(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK); 42 43 if (aphy_patch) { 44 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S); 45 mdelay(1); 46 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B); 47 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE); 48 } 49 50 rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST); 51 } 52 53 static void rtw89_disable_efuse_pwr_cut_ddv_be(struct rtw89_dev *rtwdev) 54 { 55 const struct rtw89_chip_info *chip = rtwdev->chip; 56 struct rtw89_hal *hal = &rtwdev->hal; 57 bool aphy_patch = true; 58 59 if (chip->chip_id == RTL8922A && hal->cv == CHIP_CAV) 60 aphy_patch = false; 61 62 if (aphy_patch) { 63 rtw89_write16_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE); 64 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B); 65 mdelay(1); 66 rtw89_write16_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S); 67 } 68 69 rtw89_write8_clr(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK); 70 rtw89_write32_clr(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_EF_BURST); 71 } 72 73 static int rtw89_dump_physical_efuse_map_ddv_be(struct rtw89_dev *rtwdev, u8 *map, 74 u32 dump_addr, u32 dump_size) 75 { 76 u32 efuse_ctl; 77 u32 addr; 78 u32 data; 79 int ret; 80 81 if (!IS_ALIGNED(dump_addr, 4) || !IS_ALIGNED(dump_size, 4)) { 82 rtw89_err(rtwdev, "Efuse addr 0x%x or size 0x%x not aligned\n", 83 dump_addr, dump_size); 84 return -EINVAL; 85 } 86 87 rtw89_enable_efuse_pwr_cut_ddv_be(rtwdev); 88 89 for (addr = dump_addr; addr < dump_addr + dump_size; addr += 4, map += 4) { 90 efuse_ctl = u32_encode_bits(addr, B_BE_EF_ADDR_MASK); 91 rtw89_write32(rtwdev, R_BE_EFUSE_CTRL, efuse_ctl & ~B_BE_EF_RDY); 92 93 ret = read_poll_timeout_atomic(rtw89_read32, efuse_ctl, 94 efuse_ctl & B_BE_EF_RDY, 1, 1000000, 95 true, rtwdev, R_BE_EFUSE_CTRL); 96 if (ret) 97 return -EBUSY; 98 99 data = rtw89_read32(rtwdev, R_BE_EFUSE_CTRL_1_V1); 100 *((__le32 *)map) = cpu_to_le32(data); 101 } 102 103 rtw89_disable_efuse_pwr_cut_ddv_be(rtwdev); 104 105 return 0; 106 } 107 108 static int rtw89_dump_physical_efuse_map_dav_be(struct rtw89_dev *rtwdev, u8 *map, 109 u32 dump_addr, u32 dump_size) 110 { 111 u32 addr; 112 u8 val8; 113 int err; 114 int ret; 115 116 for (addr = dump_addr; addr < dump_addr + dump_size; addr++) { 117 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0x40, 118 FULL_BIT_MASK); 119 if (ret) 120 return ret; 121 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_LOW_ADDR, addr & 0xff, 122 XTAL_SI_LOW_ADDR_MASK); 123 if (ret) 124 return ret; 125 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, addr >> 8, 126 XTAL_SI_HIGH_ADDR_MASK); 127 if (ret) 128 return ret; 129 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0, 130 XTAL_SI_MODE_SEL_MASK); 131 if (ret) 132 return ret; 133 134 ret = read_poll_timeout_atomic(rtw89_mac_read_xtal_si, err, 135 !err && (val8 & XTAL_SI_RDY), 136 1, 10000, false, 137 rtwdev, XTAL_SI_CTRL, &val8); 138 if (ret) { 139 rtw89_warn(rtwdev, "failed to read dav efuse\n"); 140 return ret; 141 } 142 143 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_READ_VAL, &val8); 144 if (ret) 145 return ret; 146 *map++ = val8; 147 } 148 149 return 0; 150 } 151 152 int rtw89_cnv_efuse_state_be(struct rtw89_dev *rtwdev, bool idle) 153 { 154 u32 val; 155 int ret = 0; 156 157 if (idle) { 158 rtw89_write32_set(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN); 159 } else { 160 rtw89_write32_clr(rtwdev, R_BE_WL_BT_PWR_CTRL, B_BE_BT_DISN_EN); 161 162 ret = read_poll_timeout(rtw89_read32_mask, val, 163 val == MAC_AX_SYS_ACT, 50, 5000, 164 false, rtwdev, R_BE_IC_PWR_STATE, 165 B_BE_WHOLE_SYS_PWR_STE_MASK); 166 if (ret) 167 rtw89_warn(rtwdev, "failed to convert efuse state\n"); 168 } 169 170 return ret; 171 } 172 173 static int rtw89_dump_physical_efuse_map_be(struct rtw89_dev *rtwdev, u8 *map, 174 u32 dump_addr, u32 dump_size, bool dav) 175 { 176 int ret; 177 178 if (!map || dump_size == 0) 179 return 0; 180 181 rtw89_cnv_efuse_state_be(rtwdev, false); 182 183 if (dav) { 184 ret = rtw89_dump_physical_efuse_map_dav_be(rtwdev, map, 185 dump_addr, dump_size); 186 if (ret) 187 return ret; 188 189 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map dav: ", map, dump_size); 190 } else { 191 ret = rtw89_dump_physical_efuse_map_ddv_be(rtwdev, map, 192 dump_addr, dump_size); 193 if (ret) 194 return ret; 195 196 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "phy_map ddv: ", map, dump_size); 197 } 198 199 rtw89_cnv_efuse_state_be(rtwdev, true); 200 201 return 0; 202 } 203 204 #define EFUSE_HDR_CONST_MASK GENMASK(23, 20) 205 #define EFUSE_HDR_PAGE_MASK GENMASK(19, 17) 206 #define EFUSE_HDR_OFFSET_MASK GENMASK(16, 4) 207 #define EFUSE_HDR_OFFSET_DAV_MASK GENMASK(11, 4) 208 #define EFUSE_HDR_WORD_EN_MASK GENMASK(3, 0) 209 210 #define invalid_efuse_header_be(hdr1, hdr2, hdr3) \ 211 ((hdr1) == 0xff || (hdr2) == 0xff || (hdr3) == 0xff) 212 #define invalid_efuse_content_be(word_en, i) \ 213 (((word_en) & BIT(i)) != 0x0) 214 #define get_efuse_blk_idx_be(hdr1, hdr2, hdr3) \ 215 (((hdr1) << 16) | ((hdr2) << 8) | (hdr3)) 216 #define block_idx_to_logical_idx_be(blk_idx, i) \ 217 (((blk_idx) << 3) + ((i) << 1)) 218 219 #define invalid_efuse_header_dav_be(hdr1, hdr2) \ 220 ((hdr1) == 0xff || (hdr2) == 0xff) 221 #define get_efuse_blk_idx_dav_be(hdr1, hdr2) \ 222 (((hdr1) << 8) | (hdr2)) 223 224 static int rtw89_eeprom_parser_be(struct rtw89_dev *rtwdev, 225 const u8 *phy_map, u32 phy_size, u8 *log_map, 226 const struct rtw89_efuse_block_cfg *efuse_block) 227 { 228 const struct rtw89_chip_info *chip = rtwdev->chip; 229 enum rtw89_efuse_block blk_page, page; 230 u32 size = efuse_block->size; 231 u32 phy_idx, log_idx; 232 u32 hdr, page_offset; 233 u8 hdr1, hdr2, hdr3; 234 u8 i, val0, val1; 235 u32 min, max; 236 u16 blk_idx; 237 u8 word_en; 238 239 page = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_ID_MASK); 240 page_offset = u32_get_bits(efuse_block->offset, RTW89_EFUSE_BLOCK_SIZE_MASK); 241 242 min = ALIGN_DOWN(page_offset, 2); 243 max = ALIGN(page_offset + size, 2); 244 245 memset(log_map, 0xff, size); 246 247 phy_idx = chip->sec_ctrl_efuse_size; 248 249 do { 250 if (page == RTW89_EFUSE_BLOCK_ADIE) { 251 hdr1 = phy_map[phy_idx]; 252 hdr2 = phy_map[phy_idx + 1]; 253 if (invalid_efuse_header_dav_be(hdr1, hdr2)) 254 break; 255 256 phy_idx += 2; 257 258 hdr = get_efuse_blk_idx_dav_be(hdr1, hdr2); 259 260 blk_page = RTW89_EFUSE_BLOCK_ADIE; 261 blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_DAV_MASK); 262 word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK); 263 } else { 264 hdr1 = phy_map[phy_idx]; 265 hdr2 = phy_map[phy_idx + 1]; 266 hdr3 = phy_map[phy_idx + 2]; 267 if (invalid_efuse_header_be(hdr1, hdr2, hdr3)) 268 break; 269 270 phy_idx += 3; 271 272 hdr = get_efuse_blk_idx_be(hdr1, hdr2, hdr3); 273 274 blk_page = u32_get_bits(hdr, EFUSE_HDR_PAGE_MASK); 275 blk_idx = u32_get_bits(hdr, EFUSE_HDR_OFFSET_MASK); 276 word_en = u32_get_bits(hdr, EFUSE_HDR_WORD_EN_MASK); 277 } 278 279 if (blk_idx >= RTW89_EFUSE_MAX_BLOCK_SIZE >> 3) { 280 rtw89_err(rtwdev, "[ERR]efuse idx:0x%X\n", phy_idx - 3); 281 rtw89_err(rtwdev, "[ERR]read hdr:0x%X\n", hdr); 282 return -EINVAL; 283 } 284 285 for (i = 0; i < 4; i++) { 286 if (invalid_efuse_content_be(word_en, i)) 287 continue; 288 289 if (phy_idx >= phy_size - 1) 290 return -EINVAL; 291 292 log_idx = block_idx_to_logical_idx_be(blk_idx, i); 293 294 if (blk_page == page && log_idx >= min && log_idx < max) { 295 val0 = phy_map[phy_idx]; 296 val1 = phy_map[phy_idx + 1]; 297 298 if (log_idx == min && page_offset > min) { 299 log_map[log_idx - page_offset + 1] = val1; 300 } else if (log_idx + 2 == max && 301 page_offset + size < max) { 302 log_map[log_idx - page_offset] = val0; 303 } else { 304 log_map[log_idx - page_offset] = val0; 305 log_map[log_idx - page_offset + 1] = val1; 306 } 307 } 308 phy_idx += 2; 309 } 310 } while (phy_idx < phy_size); 311 312 return 0; 313 } 314 315 static int rtw89_parse_logical_efuse_block_be(struct rtw89_dev *rtwdev, 316 const u8 *phy_map, u32 phy_size, 317 enum rtw89_efuse_block block) 318 { 319 const struct rtw89_chip_info *chip = rtwdev->chip; 320 const struct rtw89_efuse_block_cfg *efuse_block; 321 u8 *log_map; 322 int ret; 323 324 efuse_block = &chip->efuse_blocks[block]; 325 326 log_map = kmalloc(efuse_block->size, GFP_KERNEL); 327 if (!log_map) 328 return -ENOMEM; 329 330 ret = rtw89_eeprom_parser_be(rtwdev, phy_map, phy_size, log_map, efuse_block); 331 if (ret) { 332 rtw89_warn(rtwdev, "failed to dump efuse logical block %d\n", block); 333 goto out_free; 334 } 335 336 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, efuse_block->size); 337 338 ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map, block); 339 if (ret) { 340 rtw89_warn(rtwdev, "failed to read efuse map\n"); 341 goto out_free; 342 } 343 344 out_free: 345 kfree(log_map); 346 347 return ret; 348 } 349 350 int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev) 351 { 352 u32 phy_size = rtwdev->chip->physical_efuse_size; 353 u32 dav_phy_size = rtwdev->chip->dav_phy_efuse_size; 354 enum rtw89_efuse_block block; 355 u8 *phy_map = NULL; 356 u8 *dav_phy_map = NULL; 357 int ret; 358 359 if (rtw89_read16(rtwdev, R_BE_SYS_WL_EFUSE_CTRL) & B_BE_AUTOLOAD_SUS) 360 rtwdev->efuse.valid = true; 361 else 362 rtw89_warn(rtwdev, "failed to check efuse autoload\n"); 363 364 phy_map = kmalloc(phy_size, GFP_KERNEL); 365 if (dav_phy_size) 366 dav_phy_map = kmalloc(dav_phy_size, GFP_KERNEL); 367 368 if (!phy_map || (dav_phy_size && !dav_phy_map)) { 369 ret = -ENOMEM; 370 goto out_free; 371 } 372 373 ret = rtw89_dump_physical_efuse_map_be(rtwdev, phy_map, 0, phy_size, false); 374 if (ret) { 375 rtw89_warn(rtwdev, "failed to dump efuse physical map\n"); 376 goto out_free; 377 } 378 ret = rtw89_dump_physical_efuse_map_be(rtwdev, dav_phy_map, 0, dav_phy_size, true); 379 if (ret) { 380 rtw89_warn(rtwdev, "failed to dump efuse dav physical map\n"); 381 goto out_free; 382 } 383 384 if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) 385 block = RTW89_EFUSE_BLOCK_HCI_DIG_USB; 386 else 387 block = RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO; 388 389 ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, block); 390 if (ret) { 391 rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n", 392 RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO); 393 goto out_free; 394 } 395 396 ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, 397 RTW89_EFUSE_BLOCK_RF); 398 if (ret) { 399 rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n", 400 RTW89_EFUSE_BLOCK_RF); 401 goto out_free; 402 } 403 404 if (rtwdev->chip->chip_id != RTL8922D) 405 goto out_free; 406 407 ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size, 408 RTW89_EFUSE_BLOCK_SYS); 409 if (ret) { 410 rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n", 411 RTW89_EFUSE_BLOCK_SYS); 412 goto out_free; 413 } 414 415 out_free: 416 kfree(dav_phy_map); 417 kfree(phy_map); 418 419 return ret; 420 } 421 422 int rtw89_parse_phycap_map_be(struct rtw89_dev *rtwdev) 423 { 424 u32 phycap_addr = rtwdev->chip->phycap_addr; 425 u32 phycap_size = rtwdev->chip->phycap_size; 426 u8 *phycap_map = NULL; 427 int ret = 0; 428 429 if (!phycap_size) 430 return 0; 431 432 phycap_map = kmalloc(phycap_size, GFP_KERNEL); 433 if (!phycap_map) 434 return -ENOMEM; 435 436 ret = rtw89_dump_physical_efuse_map_be(rtwdev, phycap_map, 437 phycap_addr, phycap_size, false); 438 if (ret) { 439 rtw89_warn(rtwdev, "failed to dump phycap map\n"); 440 goto out_free; 441 } 442 443 ret = rtwdev->chip->ops->read_phycap(rtwdev, phycap_map); 444 if (ret) { 445 rtw89_warn(rtwdev, "failed to read phycap map\n"); 446 goto out_free; 447 } 448 449 out_free: 450 kfree(phycap_map); 451 452 return ret; 453 } 454 455 static u16 get_sb_cryp_sel_idx(u16 sb_cryp_sel) 456 { 457 u8 low_bit, high_bit, cnt_zero = 0; 458 u8 idx, sel_form_v, sel_idx_v; 459 u16 sb_cryp_sel_v = 0x0; 460 461 sel_form_v = u16_get_bits(sb_cryp_sel, MASKBYTE0); 462 sel_idx_v = u16_get_bits(sb_cryp_sel, MASKBYTE1); 463 464 for (idx = 0; idx < 4; idx++) { 465 low_bit = !!(sel_form_v & BIT(idx)); 466 high_bit = !!(sel_form_v & BIT(7 - idx)); 467 if (low_bit != high_bit) 468 return U16_MAX; 469 if (low_bit) 470 continue; 471 472 cnt_zero++; 473 if (cnt_zero == 1) 474 sb_cryp_sel_v = idx * 16; 475 else if (cnt_zero > 1) 476 return U16_MAX; 477 } 478 479 low_bit = u8_get_bits(sel_idx_v, 0x0F); 480 high_bit = u8_get_bits(sel_idx_v, 0xF0); 481 482 if ((low_bit ^ high_bit) != 0xF) 483 return U16_MAX; 484 485 return sb_cryp_sel_v + low_bit; 486 } 487 488 int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev) 489 { 490 struct rtw89_fw_secure *sec = &rtwdev->fw.sec; 491 u32 sec_addr = EFUSE_SEC_BE_START; 492 u32 sec_size = EFUSE_SEC_BE_SIZE; 493 u16 sb_cryp_sel, sb_cryp_sel_idx; 494 u8 sec_map[EFUSE_SEC_BE_SIZE]; 495 u8 b1, b2; 496 int ret; 497 498 ret = rtw89_dump_physical_efuse_map_be(rtwdev, sec_map, 499 sec_addr, sec_size, false); 500 if (ret) { 501 rtw89_warn(rtwdev, "failed to dump secsel map\n"); 502 return ret; 503 } 504 505 sb_cryp_sel = sec_map[EFUSE_SB_CRYP_SEL_ADDR - sec_addr] | 506 sec_map[EFUSE_SB_CRYP_SEL_ADDR - sec_addr + 1] << 8; 507 if (sb_cryp_sel == EFUSE_SB_CRYP_SEL_DEFAULT) 508 goto out; 509 510 sb_cryp_sel_idx = get_sb_cryp_sel_idx(sb_cryp_sel); 511 if (sb_cryp_sel_idx >= SB_SEL_MGN_MAX_SIZE) { 512 rtw89_warn(rtwdev, "invalid SB cryp sel idx %d\n", sb_cryp_sel_idx); 513 goto out; 514 } 515 516 sec->sb_sel_mgn = sb_sel_mgn[sb_cryp_sel_idx]; 517 518 b1 = sec_map[EFUSE_EXTERNALPN_ADDR_BE - sec_addr]; 519 b2 = sec_map[EFUSE_SERIALNUM_ADDR_BE - sec_addr]; 520 521 ret = rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2); 522 if (ret) 523 goto out; 524 525 sec->secure_boot = true; 526 527 out: 528 rtw89_debug(rtwdev, RTW89_DBG_FW, 529 "MSS secure_boot=%d dev_type=%d cust_idx=%d key_num=%d\n", 530 sec->secure_boot, sec->mss_dev_type, sec->mss_cust_idx, 531 sec->mss_key_num); 532 533 return 0; 534 } 535 536 int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev) 537 { 538 u32 dump_addr; 539 u8 buff[4]; /* efuse access must 4 bytes align */ 540 int ret; 541 u8 ecv; 542 u8 val; 543 544 dump_addr = ALIGN_DOWN(EF_FV_OFSET_BE_V1, 4); 545 546 ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); 547 if (ret) 548 return ret; 549 550 val = buff[EF_FV_OFSET_BE_V1 & 0x3]; 551 552 ecv = u8_get_bits(val, EF_CV_MASK); 553 if (ecv == EF_CV_INV) 554 return -ENOENT; 555 556 rtwdev->hal.cv = ecv; 557 558 return 0; 559 } 560 561 int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev) 562 { 563 struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; 564 u32 dump_addr = EFUSE_THERMAL_K_OFFSET_BE; 565 u8 buff[4]; /* efuse access must be multiple of 4 bytes in size */ 566 bool no_k; 567 u16 val16; 568 int ret; 569 570 ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); 571 if (ret) 572 return ret; 573 574 val16 = buff[0] | buff[1] << 8; 575 576 no_k = !!u16_get_bits(val16, EFUSE_THERMAL_K_VALID_BE); 577 if (no_k) { 578 info->thermal_k = 0; 579 return -ENOENT; 580 } 581 582 info->thermal_k = u16_get_bits(val16, EFUSE_THERMAL_K_VAL_BE); 583 584 if (u16_get_bits(val16, EFUSE_THERMAL_K_SIGN_BE)) 585 info->thermal_k *= -1; 586 587 return 0; 588 } 589 590 static int rtw89_efuse_read_pwr_data_vcore_be(struct rtw89_dev *rtwdev) 591 { 592 struct rtw89_efuse *efuse = &rtwdev->efuse; 593 u32 dump_addr; 594 u8 buff[4]; /* efuse access must 4 bytes align */ 595 u16 val16; 596 int ret; 597 598 dump_addr = ALIGN_DOWN(EFUSE_VCORE_PWR_BE, 4); 599 600 ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); 601 if (ret) 602 return ret; 603 604 val16 = buff[EFUSE_VCORE_PWR_BE - dump_addr] | 605 buff[EFUSE_VCORE_PWR_BE - dump_addr + 1] << 8; 606 607 if (val16 & EFUSE_VCORE_PWR_BE_VALID) 608 return 0; 609 610 efuse->vcore_valid = true; 611 efuse->vcore_vmax_reduce = 612 (u16_get_bits(val16, EFUSE_VCORE_PWR_BE_VAL) - SWR_DIG_MIN) / 613 EFUSE_DIG_K_STEP; 614 615 return 0; 616 } 617 618 static int rtw89_efuse_read_pwr_data_dswr_be(struct rtw89_dev *rtwdev) 619 { 620 struct rtw89_efuse *efuse = &rtwdev->efuse; 621 u32 dump_addr; 622 u8 buff[4]; /* efuse access must 4 bytes align */ 623 u8 val8; 624 int ret; 625 626 dump_addr = ALIGN_DOWN(EFUSE_DSWR_V0_86_BE, 4); 627 628 ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); 629 if (ret) 630 return ret; 631 632 val8 = buff[EFUSE_DSWR_V0_86_BE - dump_addr]; 633 634 if (val8 & EFUSE_DSWR_V0_86_BE_VALID) 635 return 0; 636 637 efuse->dswr_valid = true; 638 efuse->dswr_vmin = u8_get_bits(val8, EFUSE_DSWR_V0_86_BE_VAL); 639 640 return 0; 641 } 642 643 int rtw89_efuse_read_pwr_data_be(struct rtw89_dev *rtwdev) 644 { 645 int ret; 646 647 if (rtwdev->chip->chip_id != RTL8922D) 648 return 0; 649 650 ret = rtw89_efuse_read_pwr_data_vcore_be(rtwdev); 651 if (ret) 652 return ret; 653 654 return rtw89_efuse_read_pwr_data_dswr_be(rtwdev); 655 } 656