1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2019-2020 Realtek Corporation 3 */ 4 5 #include "debug.h" 6 #include "efuse.h" 7 #include "mac.h" 8 #include "reg.h" 9 10 #define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0) 11 #define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4) 12 #define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0) 13 #define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6) 14 15 #define EFUSE_EXTERNALPN_ADDR_AX 0x5EC 16 #define EFUSE_CUSTOMER_ADDR_AX 0x5ED 17 #define EFUSE_SERIALNUM_ADDR_AX 0x5ED 18 19 #define EFUSE_B1_EXTERNALPN_MASK GENMASK(7, 0) 20 #define EFUSE_B2_CUSTOMER_MASK GENMASK(3, 0) 21 #define EFUSE_B2_SERIALNUM_MASK GENMASK(6, 4) 22 23 #define OTP_KEY_INFO_NUM 2 24 25 static const u8 otp_key_info_externalPN[OTP_KEY_INFO_NUM] = {0x0, 0x0}; 26 static const u8 otp_key_info_customer[OTP_KEY_INFO_NUM] = {0x0, 0x1}; 27 static const u8 otp_key_info_serialNum[OTP_KEY_INFO_NUM] = {0x0, 0x1}; 28 29 enum rtw89_efuse_bank { 30 RTW89_EFUSE_BANK_WIFI, 31 RTW89_EFUSE_BANK_BT, 32 }; 33 34 enum rtw89_efuse_mss_dev_type { 35 MSS_DEV_TYPE_FWSEC_DEF = 0xF, 36 MSS_DEV_TYPE_FWSEC_WINLIN_INBOX = 0xC, 37 MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB = 0xA, 38 MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB = 0x9, 39 MSS_DEV_TYPE_FWSEC_NONWIN_INBOX = 0x6, 40 }; 41 42 static int rtw89_switch_efuse_bank(struct rtw89_dev *rtwdev, 43 enum rtw89_efuse_bank bank) 44 { 45 u8 val; 46 47 if (rtwdev->chip->chip_id != RTL8852A) 48 return 0; 49 50 val = rtw89_read32_mask(rtwdev, R_AX_EFUSE_CTRL_1, 51 B_AX_EF_CELL_SEL_MASK); 52 if (bank == val) 53 return 0; 54 55 rtw89_write32_mask(rtwdev, R_AX_EFUSE_CTRL_1, B_AX_EF_CELL_SEL_MASK, 56 bank); 57 58 val = rtw89_read32_mask(rtwdev, R_AX_EFUSE_CTRL_1, 59 B_AX_EF_CELL_SEL_MASK); 60 if (bank == val) 61 return 0; 62 63 return -EBUSY; 64 } 65 66 static void rtw89_enable_otp_burst_mode(struct rtw89_dev *rtwdev, bool en) 67 { 68 if (en) 69 rtw89_write32_set(rtwdev, R_AX_EFUSE_CTRL_1_V1, B_AX_EF_BURST); 70 else 71 rtw89_write32_clr(rtwdev, R_AX_EFUSE_CTRL_1_V1, B_AX_EF_BURST); 72 } 73 74 static void rtw89_enable_efuse_pwr_cut_ddv(struct rtw89_dev *rtwdev) 75 { 76 enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 77 struct rtw89_hal *hal = &rtwdev->hal; 78 79 if (chip_id == RTL8852A) 80 return; 81 82 rtw89_write8_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); 83 rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); 84 85 fsleep(1000); 86 87 rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15); 88 rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE); 89 if (chip_id == RTL8852B && hal->cv == CHIP_CAV) 90 rtw89_enable_otp_burst_mode(rtwdev, true); 91 } 92 93 static void rtw89_disable_efuse_pwr_cut_ddv(struct rtw89_dev *rtwdev) 94 { 95 enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 96 struct rtw89_hal *hal = &rtwdev->hal; 97 98 if (chip_id == RTL8852A) 99 return; 100 101 if (chip_id == RTL8852B && hal->cv == CHIP_CAV) 102 rtw89_enable_otp_burst_mode(rtwdev, false); 103 104 rtw89_write16_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE); 105 rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15); 106 107 fsleep(1000); 108 109 rtw89_write16_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); 110 rtw89_write8_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); 111 } 112 113 static int rtw89_dump_physical_efuse_map_ddv(struct rtw89_dev *rtwdev, u8 *map, 114 u32 dump_addr, u32 dump_size) 115 { 116 u32 efuse_ctl; 117 u32 addr; 118 int ret; 119 120 rtw89_enable_efuse_pwr_cut_ddv(rtwdev); 121 122 for (addr = dump_addr; addr < dump_addr + dump_size; addr++) { 123 efuse_ctl = u32_encode_bits(addr, B_AX_EF_ADDR_MASK); 124 rtw89_write32(rtwdev, R_AX_EFUSE_CTRL, efuse_ctl & ~B_AX_EF_RDY); 125 126 ret = read_poll_timeout_atomic(rtw89_read32, efuse_ctl, 127 efuse_ctl & B_AX_EF_RDY, 1, 1000000, 128 true, rtwdev, R_AX_EFUSE_CTRL); 129 if (ret) 130 return -EBUSY; 131 132 *map++ = (u8)(efuse_ctl & 0xff); 133 } 134 135 rtw89_disable_efuse_pwr_cut_ddv(rtwdev); 136 137 return 0; 138 } 139 140 int rtw89_cnv_efuse_state_ax(struct rtw89_dev *rtwdev, bool idle) 141 { 142 return 0; 143 } 144 145 static int rtw89_dump_physical_efuse_map_dav(struct rtw89_dev *rtwdev, u8 *map, 146 u32 dump_addr, u32 dump_size) 147 { 148 u32 addr; 149 u8 val8; 150 int err; 151 int ret; 152 153 for (addr = dump_addr; addr < dump_addr + dump_size; addr++) { 154 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0x40, FULL_BIT_MASK); 155 if (ret) 156 return ret; 157 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_LOW_ADDR, 158 addr & 0xff, XTAL_SI_LOW_ADDR_MASK); 159 if (ret) 160 return ret; 161 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, addr >> 8, 162 XTAL_SI_HIGH_ADDR_MASK); 163 if (ret) 164 return ret; 165 ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_CTRL, 0, 166 XTAL_SI_MODE_SEL_MASK); 167 if (ret) 168 return ret; 169 170 ret = read_poll_timeout_atomic(rtw89_mac_read_xtal_si, err, 171 !err && (val8 & XTAL_SI_RDY), 172 1, 10000, false, 173 rtwdev, XTAL_SI_CTRL, &val8); 174 if (ret) { 175 rtw89_warn(rtwdev, "failed to read dav efuse\n"); 176 return ret; 177 } 178 179 ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_READ_VAL, &val8); 180 if (ret) 181 return ret; 182 *map++ = val8; 183 } 184 185 return 0; 186 } 187 188 static int __rtw89_dump_physical_efuse_map(struct rtw89_dev *rtwdev, u8 *map, 189 u32 dump_addr, u32 dump_size, bool dav) 190 { 191 int ret; 192 193 if (!map || dump_size == 0) 194 return 0; 195 196 rtw89_switch_efuse_bank(rtwdev, RTW89_EFUSE_BANK_WIFI); 197 198 if (dav) { 199 ret = rtw89_dump_physical_efuse_map_dav(rtwdev, map, dump_addr, dump_size); 200 if (ret) 201 return ret; 202 } else { 203 ret = rtw89_dump_physical_efuse_map_ddv(rtwdev, map, dump_addr, dump_size); 204 if (ret) 205 return ret; 206 } 207 208 return 0; 209 } 210 211 static int rtw89_dump_physical_efuse_map(struct rtw89_dev *rtwdev, u8 *map, 212 u32 dump_addr, u32 dump_size, bool dav) 213 { 214 int retry; 215 int ret; 216 217 for (retry = 0; retry < 5; retry++) { 218 ret = __rtw89_dump_physical_efuse_map(rtwdev, map, dump_addr, 219 dump_size, dav); 220 if (!ret) 221 return 0; 222 223 rtw89_warn(rtwdev, "efuse dump (dav=%d) failed, retrying (%d)\n", 224 dav, retry); 225 } 226 227 return ret; 228 } 229 230 #define invalid_efuse_header(hdr1, hdr2) \ 231 ((hdr1) == 0xff || (hdr2) == 0xff) 232 #define invalid_efuse_content(word_en, i) \ 233 (((word_en) & BIT(i)) != 0x0) 234 #define get_efuse_blk_idx(hdr1, hdr2) \ 235 ((((hdr2) & 0xf0) >> 4) | (((hdr1) & 0x0f) << 4)) 236 #define block_idx_to_logical_idx(blk_idx, i) \ 237 (((blk_idx) << 3) + ((i) << 1)) 238 static int rtw89_dump_logical_efuse_map(struct rtw89_dev *rtwdev, u8 *phy_map, 239 u8 *log_map) 240 { 241 u32 physical_size = rtwdev->chip->physical_efuse_size; 242 u32 logical_size = rtwdev->chip->logical_efuse_size; 243 u8 sec_ctrl_size = rtwdev->chip->sec_ctrl_efuse_size; 244 u32 phy_idx = sec_ctrl_size; 245 u32 log_idx; 246 u8 hdr1, hdr2; 247 u8 blk_idx; 248 u8 word_en; 249 int i; 250 251 if (!phy_map) 252 return 0; 253 254 while (phy_idx < physical_size - sec_ctrl_size) { 255 hdr1 = phy_map[phy_idx]; 256 hdr2 = phy_map[phy_idx + 1]; 257 if (invalid_efuse_header(hdr1, hdr2)) 258 break; 259 260 blk_idx = get_efuse_blk_idx(hdr1, hdr2); 261 word_en = hdr2 & 0xf; 262 phy_idx += 2; 263 264 for (i = 0; i < 4; i++) { 265 if (invalid_efuse_content(word_en, i)) 266 continue; 267 268 log_idx = block_idx_to_logical_idx(blk_idx, i); 269 if (phy_idx + 1 > physical_size - sec_ctrl_size - 1 || 270 log_idx + 1 > logical_size) 271 return -EINVAL; 272 273 log_map[log_idx] = phy_map[phy_idx]; 274 log_map[log_idx + 1] = phy_map[phy_idx + 1]; 275 phy_idx += 2; 276 } 277 } 278 return 0; 279 } 280 281 int rtw89_parse_efuse_map_ax(struct rtw89_dev *rtwdev) 282 { 283 u32 phy_size = rtwdev->chip->physical_efuse_size; 284 u32 log_size = rtwdev->chip->logical_efuse_size; 285 u32 dav_phy_size = rtwdev->chip->dav_phy_efuse_size; 286 u32 dav_log_size = rtwdev->chip->dav_log_efuse_size; 287 u32 full_log_size = log_size + dav_log_size; 288 u8 *phy_map = NULL; 289 u8 *log_map = NULL; 290 u8 *dav_phy_map = NULL; 291 u8 *dav_log_map = NULL; 292 int ret; 293 294 if (rtw89_read16(rtwdev, R_AX_SYS_WL_EFUSE_CTRL) & B_AX_AUTOLOAD_SUS) 295 rtwdev->efuse.valid = true; 296 else 297 rtw89_warn(rtwdev, "failed to check efuse autoload\n"); 298 299 phy_map = kmalloc(phy_size, GFP_KERNEL); 300 log_map = kmalloc(full_log_size, GFP_KERNEL); 301 if (dav_phy_size && dav_log_size) { 302 dav_phy_map = kmalloc(dav_phy_size, GFP_KERNEL); 303 dav_log_map = log_map + log_size; 304 } 305 306 if (!phy_map || !log_map || (dav_phy_size && !dav_phy_map)) { 307 ret = -ENOMEM; 308 goto out_free; 309 } 310 311 ret = rtw89_dump_physical_efuse_map(rtwdev, phy_map, 0, phy_size, false); 312 if (ret) { 313 rtw89_warn(rtwdev, "failed to dump efuse physical map\n"); 314 goto out_free; 315 } 316 ret = rtw89_dump_physical_efuse_map(rtwdev, dav_phy_map, 0, dav_phy_size, true); 317 if (ret) { 318 rtw89_warn(rtwdev, "failed to dump efuse dav physical map\n"); 319 goto out_free; 320 } 321 322 memset(log_map, 0xff, full_log_size); 323 ret = rtw89_dump_logical_efuse_map(rtwdev, phy_map, log_map); 324 if (ret) { 325 rtw89_warn(rtwdev, "failed to dump efuse logical map\n"); 326 goto out_free; 327 } 328 ret = rtw89_dump_logical_efuse_map(rtwdev, dav_phy_map, dav_log_map); 329 if (ret) { 330 rtw89_warn(rtwdev, "failed to dump efuse dav logical map\n"); 331 goto out_free; 332 } 333 334 rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "log_map: ", log_map, full_log_size); 335 336 ret = rtwdev->chip->ops->read_efuse(rtwdev, log_map, RTW89_EFUSE_BLOCK_IGNORE); 337 if (ret) { 338 rtw89_warn(rtwdev, "failed to read efuse map\n"); 339 goto out_free; 340 } 341 342 out_free: 343 kfree(dav_phy_map); 344 kfree(log_map); 345 kfree(phy_map); 346 347 return ret; 348 } 349 350 int rtw89_parse_phycap_map_ax(struct rtw89_dev *rtwdev) 351 { 352 u32 phycap_addr = rtwdev->chip->phycap_addr; 353 u32 phycap_size = rtwdev->chip->phycap_size; 354 u8 *phycap_map = NULL; 355 int ret = 0; 356 357 if (!phycap_size) 358 return 0; 359 360 phycap_map = kmalloc(phycap_size, GFP_KERNEL); 361 if (!phycap_map) 362 return -ENOMEM; 363 364 ret = rtw89_dump_physical_efuse_map(rtwdev, phycap_map, 365 phycap_addr, phycap_size, false); 366 if (ret) { 367 rtw89_warn(rtwdev, "failed to dump phycap map\n"); 368 goto out_free; 369 } 370 371 ret = rtwdev->chip->ops->read_phycap(rtwdev, phycap_map); 372 if (ret) { 373 rtw89_warn(rtwdev, "failed to read phycap map\n"); 374 goto out_free; 375 } 376 377 out_free: 378 kfree(phycap_map); 379 380 return ret; 381 } 382 383 int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv) 384 { 385 int ret; 386 u8 val; 387 388 ret = rtw89_dump_physical_efuse_map(rtwdev, &val, EF_FV_OFSET, 1, false); 389 if (ret) 390 return ret; 391 392 *ecv = u8_get_bits(val, EF_CV_MASK); 393 if (*ecv == EF_CV_INV) 394 return -ENOENT; 395 396 return 0; 397 } 398 EXPORT_SYMBOL(rtw89_read_efuse_ver); 399 400 static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type) 401 { 402 switch (mss_dev_type) { 403 case MSS_DEV_TYPE_FWSEC_WINLIN_INBOX: 404 mss_dev_type = 0x0; 405 break; 406 case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB: 407 mss_dev_type = 0x1; 408 break; 409 case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB: 410 mss_dev_type = 0x2; 411 break; 412 case MSS_DEV_TYPE_FWSEC_NONWIN_INBOX: 413 mss_dev_type = 0x3; 414 break; 415 case MSS_DEV_TYPE_FWSEC_DEF: 416 mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF; 417 break; 418 default: 419 rtw89_warn(rtwdev, "unknown mss_dev_type %d", mss_dev_type); 420 mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_INV; 421 break; 422 } 423 424 return mss_dev_type; 425 } 426 427 int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2) 428 { 429 const struct rtw89_chip_info *chip = rtwdev->chip; 430 struct rtw89_fw_secure *sec = &rtwdev->fw.sec; 431 u8 mss_dev_type; 432 433 if (chip->chip_id == RTL8852B && b1 == 0xFF && b2 == 0x6E) { 434 mss_dev_type = MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB; 435 sec->mss_cust_idx = 0; 436 sec->mss_key_num = 0; 437 438 goto mss_dev_type; 439 } 440 441 mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK); 442 sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) | 443 u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4); 444 sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK); 445 446 mss_dev_type: 447 sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type); 448 if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) { 449 rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type); 450 return -ENOENT; 451 } 452 453 sec->can_mss_v1 = true; 454 455 return 0; 456 } 457 458 static 459 int rtw89_efuse_recognize_mss_index_v0(struct rtw89_dev *rtwdev, u8 b1, u8 b2) 460 { 461 struct rtw89_fw_secure *sec = &rtwdev->fw.sec; 462 u8 externalPN; 463 u8 serialNum; 464 u8 customer; 465 u8 i; 466 467 externalPN = 0xFF - u8_get_bits(b1, EFUSE_B1_EXTERNALPN_MASK); 468 customer = 0xF - u8_get_bits(b2, EFUSE_B2_CUSTOMER_MASK); 469 serialNum = 0x7 - u8_get_bits(b2, EFUSE_B2_SERIALNUM_MASK); 470 471 for (i = 0; i < OTP_KEY_INFO_NUM; i++) { 472 if (externalPN == otp_key_info_externalPN[i] && 473 customer == otp_key_info_customer[i] && 474 serialNum == otp_key_info_serialNum[i]) { 475 sec->mss_idx = i; 476 sec->can_mss_v0 = true; 477 return 0; 478 } 479 } 480 481 return -ENOENT; 482 } 483 484 int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev) 485 { 486 struct rtw89_fw_secure *sec = &rtwdev->fw.sec; 487 u32 sec_addr = EFUSE_EXTERNALPN_ADDR_AX; 488 u32 sec_size = 2; 489 u8 sec_map[2]; 490 u8 b1, b2; 491 int ret; 492 493 ret = rtw89_dump_physical_efuse_map(rtwdev, sec_map, 494 sec_addr, sec_size, false); 495 if (ret) { 496 rtw89_warn(rtwdev, "failed to dump secsel map\n"); 497 return ret; 498 } 499 500 b1 = sec_map[0]; 501 b2 = sec_map[1]; 502 503 if (b1 == 0xFF && b2 == 0xFF) 504 return 0; 505 506 rtw89_efuse_recognize_mss_index_v0(rtwdev, b1, b2); 507 rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2); 508 if (!sec->can_mss_v1 && !sec->can_mss_v0) 509 goto out; 510 511 sec->secure_boot = true; 512 513 out: 514 rtw89_debug(rtwdev, RTW89_DBG_FW, 515 "MSS secure_boot=%d(%d/%d) dev_type=%d cust_idx=%d key_num=%d mss_index=%d\n", 516 sec->secure_boot, sec->can_mss_v0, sec->can_mss_v1, 517 sec->mss_dev_type, sec->mss_cust_idx, 518 sec->mss_key_num, sec->mss_idx); 519 520 return 0; 521 } 522