xref: /linux/drivers/net/wireless/realtek/rtw89/efuse_be.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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 
rtw89_enable_efuse_pwr_cut_ddv_be(struct rtw89_dev * rtwdev)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 
rtw89_disable_efuse_pwr_cut_ddv_be(struct rtw89_dev * rtwdev)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 
rtw89_dump_physical_efuse_map_ddv_be(struct rtw89_dev * rtwdev,u8 * map,u32 dump_addr,u32 dump_size)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 
rtw89_dump_physical_efuse_map_dav_be(struct rtw89_dev * rtwdev,u8 * map,u32 dump_addr,u32 dump_size)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 
rtw89_cnv_efuse_state_be(struct rtw89_dev * rtwdev,bool idle)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 
rtw89_dump_physical_efuse_map_be(struct rtw89_dev * rtwdev,u8 * map,u32 dump_addr,u32 dump_size,bool dav)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 
rtw89_eeprom_parser_be(struct rtw89_dev * rtwdev,const u8 * phy_map,u32 phy_size,u8 * log_map,const struct rtw89_efuse_block_cfg * efuse_block)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 
rtw89_parse_logical_efuse_block_be(struct rtw89_dev * rtwdev,const u8 * phy_map,u32 phy_size,enum rtw89_efuse_block block)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 
rtw89_parse_efuse_map_be(struct rtw89_dev * rtwdev)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 
rtw89_parse_phycap_map_be(struct rtw89_dev * rtwdev)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 
get_sb_cryp_sel_idx(u16 sb_cryp_sel)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 
rtw89_efuse_read_fw_secure_be(struct rtw89_dev * rtwdev)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 
rtw89_efuse_read_ecv_be(struct rtw89_dev * rtwdev)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 
rtw89_efuse_read_thermal_k_be(struct rtw89_dev * rtwdev)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 
rtw89_efuse_read_pwr_data_vcore_be(struct rtw89_dev * rtwdev)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 
rtw89_efuse_read_pwr_data_dswr_be(struct rtw89_dev * rtwdev)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 
rtw89_efuse_read_pwr_data_be(struct rtw89_dev * rtwdev)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