1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_EFUSE_C_
8 
9 #include <osdep_service.h>
10 #include <drv_types.h>
11 #include <rtw_efuse.h>
12 #include <usb_ops_linux.h>
13 #include <rtl8188e_hal.h>
14 #include <rtw_iol.h>
15 
16 #define REG_EFUSE_CTRL		0x0030
17 #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
18 
19 enum{
20 		VOLTAGE_V25						= 0x03,
21 		LDOE25_SHIFT						= 28,
22 	};
23 
24 /*
25  * Function:	efuse_power_switch
26  *
27  * Overview:	When we want to enable write operation, we should change to
28  *				pwr on state. When we stop write, we should switch to 500k mode
29  *				and disable LDO 2.5V.
30  */
31 
efuse_power_switch(struct adapter * pAdapter,u8 write,u8 pwrstate)32 void efuse_power_switch(struct adapter *pAdapter, u8 write, u8 pwrstate)
33 {
34 	u8 tempval;
35 	u16 tmpv16;
36 
37 	if (pwrstate) {
38 		usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
39 
40 		/*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
41 		tmpv16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
42 		if (!(tmpv16 & PWC_EV12V)) {
43 			tmpv16 |= PWC_EV12V;
44 			 usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpv16);
45 		}
46 		/*  Reset: 0x0000h[28], default valid */
47 		tmpv16 =  usb_read16(pAdapter, REG_SYS_FUNC_EN);
48 		if (!(tmpv16 & FEN_ELDR)) {
49 			tmpv16 |= FEN_ELDR;
50 			usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpv16);
51 		}
52 
53 		/*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
54 		tmpv16 = usb_read16(pAdapter, REG_SYS_CLKR);
55 		if ((!(tmpv16 & LOADER_CLK_EN))  || (!(tmpv16 & ANA8M))) {
56 			tmpv16 |= (LOADER_CLK_EN | ANA8M);
57 			usb_write16(pAdapter, REG_SYS_CLKR, tmpv16);
58 		}
59 
60 		if (write) {
61 			/*  Enable LDO 2.5V before read/write action */
62 			tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
63 			tempval &= 0x0F;
64 			tempval |= (VOLTAGE_V25 << 4);
65 			usb_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80));
66 		}
67 	} else {
68 		usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
69 
70 		if (write) {
71 			/*  Disable LDO 2.5V after read/write action */
72 			tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
73 			usb_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F));
74 		}
75 	}
76 }
77 
78 static void
efuse_phymap_to_logical(u8 * phymap,u16 _offset,u16 _size_byte,u8 * pbuf)79 efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
80 {
81 	u8 *efuseTbl = NULL;
82 	u8 rtemp8;
83 	u16	eFuse_Addr = 0;
84 	u8 offset, wren;
85 	u16	i, j;
86 	u16	**eFuseWord = NULL;
87 	u16	efuse_utilized = 0;
88 	u8 u1temp = 0;
89 
90 	efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
91 	if (!efuseTbl)
92 		return;
93 
94 	eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
95 	if (!eFuseWord) {
96 		DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
97 		goto eFuseWord_failed;
98 	}
99 
100 	/*  0. Refresh efuse init map as all oxFF. */
101 	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
102 		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
103 			eFuseWord[i][j] = 0xFFFF;
104 
105 	/*  */
106 	/*  1. Read the first byte to check if efuse is empty!!! */
107 	/*  */
108 	/*  */
109 	rtemp8 = *(phymap+eFuse_Addr);
110 	if (rtemp8 != 0xFF) {
111 		efuse_utilized++;
112 		eFuse_Addr++;
113 	} else {
114 		DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
115 		goto exit;
116 	}
117 
118 	/*  */
119 	/*  2. Read real efuse content. Filter PG header and every section data. */
120 	/*  */
121 	while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
122 		/*  Check PG header for section num. */
123 		if ((rtemp8 & 0x1F) == 0x0F) {		/* extended header */
124 			u1temp = (rtemp8 & 0xE0) >> 5;
125 			rtemp8 = *(phymap+eFuse_Addr);
126 			if ((rtemp8 & 0x0F) == 0x0F) {
127 				eFuse_Addr++;
128 				rtemp8 = *(phymap+eFuse_Addr);
129 
130 				if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
131 					eFuse_Addr++;
132 				continue;
133 			} else {
134 				offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
135 				wren = rtemp8 & 0x0F;
136 				eFuse_Addr++;
137 			}
138 		} else {
139 			offset = (rtemp8 >> 4) & 0x0f;
140 			wren = rtemp8 & 0x0f;
141 		}
142 
143 		if (offset < EFUSE_MAX_SECTION_88E) {
144 			/*  Get word enable value from PG header */
145 			for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
146 				/*  Check word enable condition in the section */
147 				if (!(wren & 0x01)) {
148 					rtemp8 = *(phymap+eFuse_Addr);
149 					eFuse_Addr++;
150 					efuse_utilized++;
151 					eFuseWord[offset][i] = (rtemp8 & 0xff);
152 					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
153 						break;
154 					rtemp8 = *(phymap+eFuse_Addr);
155 					eFuse_Addr++;
156 					efuse_utilized++;
157 					eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
158 
159 					if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
160 						break;
161 				}
162 				wren >>= 1;
163 			}
164 		}
165 		/*  Read next PG header */
166 		rtemp8 = *(phymap+eFuse_Addr);
167 
168 		if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
169 			efuse_utilized++;
170 			eFuse_Addr++;
171 		}
172 	}
173 
174 	/*  */
175 	/*  3. Collect 16 sections and 4 word unit into Efuse map. */
176 	/*  */
177 	for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
178 		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
179 			efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
180 			efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
181 		}
182 	}
183 
184 	/*  */
185 	/*  4. Copy from Efuse map to output pointer memory!!! */
186 	/*  */
187 	for (i = 0; i < _size_byte; i++)
188 		pbuf[i] = efuseTbl[_offset+i];
189 
190 	/*  */
191 	/*  5. Calculate Efuse utilization. */
192 	/*  */
193 
194 exit:
195 	kfree(eFuseWord);
196 
197 eFuseWord_failed:
198 	kfree(efuseTbl);
199 }
200 
efuse_read_phymap_from_txpktbuf(struct adapter * adapter,int bcnhead,u8 * content,u16 * size)201 static void efuse_read_phymap_from_txpktbuf(
202 	struct adapter  *adapter,
203 	int bcnhead,	/* beacon head, where FW store len(2-byte) and efuse physical map. */
204 	u8 *content,	/* buffer to store efuse physical map */
205 	u16 *size	/* for efuse content: the max byte to read. will update to byte read */
206 	)
207 {
208 	u16 dbg_addr = 0;
209 	unsigned long start = 0;
210 	u8 reg_0x143 = 0;
211 	u32 lo32 = 0, hi32 = 0;
212 	u16 len = 0, count = 0;
213 	int i = 0;
214 	u16 limit = *size;
215 
216 	u8 *pos = content;
217 
218 	if (bcnhead < 0) /* if not valid */
219 		bcnhead = usb_read8(adapter, REG_TDECTRL+1);
220 
221 	DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
222 
223 	usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
224 
225 	dbg_addr = bcnhead*128/8; /* 8-bytes addressing */
226 
227 	while (1) {
228 		usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i);
229 
230 		usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
231 		start = jiffies;
232 		while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
233 		       jiffies_to_msecs(jiffies - start) < 1000) {
234 			DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
235 			usleep_range(1000, 2000);
236 		}
237 
238 		lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
239 		hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
240 
241 		if (i == 0) {
242 			u8 lenc[2];
243 			u16 lenbak, aaabak;
244 			u16 aaa;
245 
246 			lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
247 			lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1);
248 
249 			aaabak = le16_to_cpup((__le16 *)lenc);
250 			lenbak = le16_to_cpu(*((__le16 *)lenc));
251 			aaa = le16_to_cpup((__le16 *)&lo32);
252 			len = le16_to_cpu(*((__le16 *)&lo32));
253 
254 			limit = min_t(u16, len-2, limit);
255 
256 			DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
257 
258 			memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count);
259 			count += (limit >= count+2) ? 2 : limit-count;
260 			pos = content+count;
261 
262 		} else {
263 			memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count);
264 			count += (limit >= count+4) ? 4 : limit-count;
265 			pos = content+count;
266 		}
267 
268 		if (limit > count && len-2 > count) {
269 			memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count);
270 			count += (limit >= count+4) ? 4 : limit-count;
271 			pos = content+count;
272 		}
273 
274 		if (limit <= count || len-2 <= count)
275 			break;
276 		i++;
277 	}
278 	usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
279 	DBG_88E("%s read count:%u\n", __func__, count);
280 	*size = count;
281 }
282 
iol_read_efuse(struct adapter * padapter,u8 txpktbuf_bndy,u16 offset,u16 size_byte,u8 * logical_map)283 static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
284 {
285 	s32 status = _FAIL;
286 	u8 physical_map[512];
287 	u16 size = 512;
288 
289 	usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
290 	memset(physical_map, 0xFF, 512);
291 	usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
292 	status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
293 	if (status == _SUCCESS)
294 		efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
295 	efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
296 	return status;
297 }
298 
efuse_ReadEFuse(struct adapter * Adapter,u8 efuseType,u16 _offset,u16 _size_byte,u8 * pbuf)299 void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
300 {
301 	if (rtw_iol_applied(Adapter)) {
302 		rtw_hal_power_on(Adapter);
303 		iol_mode_enable(Adapter, 1);
304 		iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
305 		iol_mode_enable(Adapter, 0);
306 	}
307 }
308 
Efuse_WordEnableDataWrite(struct adapter * pAdapter,u16 efuse_addr,u8 word_en,u8 * data)309 u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
310 {
311 	u16	tmpaddr = 0;
312 	u16	start_addr = efuse_addr;
313 	u8 badworden = 0x0F;
314 	u8 tmpdata[8];
315 
316 	memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
317 
318 	if (!(word_en & BIT(0))) {
319 		tmpaddr = start_addr;
320 		efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
321 		efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
322 
323 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
324 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
325 		if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
326 			badworden &= (~BIT(0));
327 	}
328 	if (!(word_en & BIT(1))) {
329 		tmpaddr = start_addr;
330 		efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
331 		efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
332 
333 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
334 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
335 		if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
336 			badworden &= (~BIT(1));
337 	}
338 	if (!(word_en & BIT(2))) {
339 		tmpaddr = start_addr;
340 		efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
341 		efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
342 
343 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
344 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
345 		if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
346 			badworden &= (~BIT(2));
347 	}
348 	if (!(word_en & BIT(3))) {
349 		tmpaddr = start_addr;
350 		efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
351 		efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
352 
353 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
354 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
355 		if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
356 			badworden &= (~BIT(3));
357 	}
358 	return badworden;
359 }
360 
Efuse_GetCurrentSize(struct adapter * pAdapter)361 static u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
362 {
363 	int	bContinual = true;
364 	u16	efuse_addr = 0;
365 	u8 hoffset = 0, hworden = 0;
366 	u8 efuse_data, word_cnts = 0;
367 
368 	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
369 
370 	while (bContinual &&
371 	       efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
372 	       AVAILABLE_EFUSE_ADDR(efuse_addr)) {
373 		if (efuse_data != 0xFF) {
374 			if ((efuse_data&0x1F) == 0x0F) {		/* extended header */
375 				hoffset = efuse_data;
376 				efuse_addr++;
377 				efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
378 				if ((efuse_data & 0x0F) == 0x0F) {
379 					efuse_addr++;
380 					continue;
381 				} else {
382 					hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
383 					hworden = efuse_data & 0x0F;
384 				}
385 			} else {
386 				hoffset = (efuse_data>>4) & 0x0F;
387 				hworden =  efuse_data & 0x0F;
388 			}
389 			word_cnts = Efuse_CalculateWordCnts(hworden);
390 			/* read next header */
391 			efuse_addr = efuse_addr + (word_cnts*2)+1;
392 		} else {
393 			bContinual = false;
394 		}
395 	}
396 
397 	rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
398 
399 	return efuse_addr;
400 }
401 
Efuse_PgPacketRead(struct adapter * pAdapter,u8 offset,u8 * data)402 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
403 {
404 	u8 ReadState = PG_STATE_HEADER;
405 	int	bContinual = true;
406 	int	bDataEmpty = true;
407 	u8 efuse_data, word_cnts = 0;
408 	u16	efuse_addr = 0;
409 	u8 hoffset = 0, hworden = 0;
410 	u8 tmpidx = 0;
411 	u8 tmpdata[8];
412 	u8 tmp_header = 0;
413 
414 	if (!data)
415 		return false;
416 	if (offset > EFUSE_MAX_SECTION_88E)
417 		return false;
418 
419 	memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
420 	memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
421 
422 	/*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
423 	/*  Skip dummy parts to prevent unexpected data read from Efuse. */
424 	/*  By pass right now. 2009.02.19. */
425 	while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
426 		/*   Header Read ------------- */
427 		if (ReadState & PG_STATE_HEADER) {
428 			if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
429 				if (EXT_HEADER(efuse_data)) {
430 					tmp_header = efuse_data;
431 					efuse_addr++;
432 					efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
433 					if (!ALL_WORDS_DISABLED(efuse_data)) {
434 						hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
435 						hworden = efuse_data & 0x0F;
436 					} else {
437 						DBG_88E("Error, All words disabled\n");
438 						efuse_addr++;
439 						continue;
440 					}
441 				} else {
442 					hoffset = (efuse_data>>4) & 0x0F;
443 					hworden =  efuse_data & 0x0F;
444 				}
445 				word_cnts = Efuse_CalculateWordCnts(hworden);
446 				bDataEmpty = true;
447 
448 				if (hoffset == offset) {
449 					for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
450 						if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) {
451 							tmpdata[tmpidx] = efuse_data;
452 							if (efuse_data != 0xff)
453 								bDataEmpty = false;
454 						}
455 					}
456 					if (bDataEmpty == false) {
457 						ReadState = PG_STATE_DATA;
458 					} else {/* read next header */
459 						efuse_addr = efuse_addr + (word_cnts*2)+1;
460 						ReadState = PG_STATE_HEADER;
461 					}
462 				} else {/* read next header */
463 					efuse_addr = efuse_addr + (word_cnts*2)+1;
464 					ReadState = PG_STATE_HEADER;
465 				}
466 			} else {
467 				bContinual = false;
468 			}
469 		} else if (ReadState & PG_STATE_DATA) {
470 			/*   Data section Read ------------- */
471 			efuse_WordEnableDataRead(hworden, tmpdata, data);
472 			efuse_addr = efuse_addr + (word_cnts*2)+1;
473 			ReadState = PG_STATE_HEADER;
474 		}
475 	}
476 
477 	if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
478 	    (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
479 		return false;
480 	else
481 		return true;
482 }
483 
hal_EfuseFixHeaderProcess(struct adapter * pAdapter,u8 efuseType,struct pgpkt * pFixPkt,u16 * pAddr)484 static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
485 {
486 	u8 originaldata[8], badworden = 0;
487 	u16	efuse_addr = *pAddr;
488 	u32	PgWriteSuccess = 0;
489 
490 	memset(originaldata, 0xff, 8);
491 
492 	if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
493 		/* check if data exist */
494 		badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata);
495 
496 		if (badworden != 0xf) {	/*  write fail */
497 			PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
498 
499 			if (!PgWriteSuccess)
500 				return false;
501 			else
502 				efuse_addr = Efuse_GetCurrentSize(pAdapter);
503 		} else {
504 			efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
505 		}
506 	} else {
507 		efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
508 	}
509 	*pAddr = efuse_addr;
510 	return true;
511 }
512 
hal_EfusePgPacketWrite2ByteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)513 static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
514 {
515 	bool bRet = false;
516 	u16 efuse_addr = *pAddr;
517 	u16 efuse_max_available_len =
518 		EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
519 	u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
520 	u8 repeatcnt = 0;
521 
522 	while (efuse_addr < efuse_max_available_len) {
523 		pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
524 		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
525 		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
526 
527 		while (tmp_header == 0xFF) {
528 			if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
529 				return false;
530 
531 			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
532 			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
533 		}
534 
535 		/* to write ext_header */
536 		if (tmp_header == pg_header) {
537 			efuse_addr++;
538 			pg_header_temp = pg_header;
539 			pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
540 
541 			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
542 			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
543 
544 			while (tmp_header == 0xFF) {
545 				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
546 					return false;
547 
548 				efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
549 				efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
550 			}
551 
552 			if ((tmp_header & 0x0F) == 0x0F) {	/* word_en PG fail */
553 				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
554 					return false;
555 
556 				efuse_addr++;
557 				continue;
558 			} else if (pg_header != tmp_header) {	/* offset PG fail */
559 				struct pgpkt	fixPkt;
560 
561 				fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
562 				fixPkt.word_en = tmp_header & 0x0F;
563 				fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
564 				if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
565 					return false;
566 			} else {
567 				bRet = true;
568 				break;
569 			}
570 		} else if ((tmp_header & 0x1F) == 0x0F) {		/* wrong extended header */
571 			efuse_addr += 2;
572 			continue;
573 		}
574 	}
575 
576 	*pAddr = efuse_addr;
577 	return bRet;
578 }
579 
hal_EfusePgPacketWrite1ByteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)580 static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
581 {
582 	bool bRet = false;
583 	u8 pg_header = 0, tmp_header = 0;
584 	u16	efuse_addr = *pAddr;
585 	u8 repeatcnt = 0;
586 
587 	pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
588 
589 	efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
590 	efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
591 
592 	while (tmp_header == 0xFF) {
593 		if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
594 			return false;
595 		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
596 		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
597 	}
598 
599 	if (pg_header == tmp_header) {
600 		bRet = true;
601 	} else {
602 		struct pgpkt	fixPkt;
603 
604 		fixPkt.offset = (tmp_header>>4) & 0x0F;
605 		fixPkt.word_en = tmp_header & 0x0F;
606 		fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
607 		if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
608 			return false;
609 	}
610 
611 	*pAddr = efuse_addr;
612 	return bRet;
613 }
614 
hal_EfusePgPacketWriteData(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)615 static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
616 {
617 	u16	efuse_addr = *pAddr;
618 	u8 badworden = 0;
619 	u32	PgWriteSuccess = 0;
620 
621 	badworden = 0x0f;
622 	badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data);
623 	if (badworden == 0x0F) {
624 		/*  write ok */
625 		return true;
626 	}
627 	/* reorganize other pg packet */
628 	PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
629 	if (!PgWriteSuccess)
630 		return false;
631 	else
632 		return true;
633 }
634 
635 static bool
hal_EfusePgPacketWriteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)636 hal_EfusePgPacketWriteHeader(
637 				struct adapter *pAdapter,
638 				u8 efuseType,
639 				u16				*pAddr,
640 				struct pgpkt *pTargetPkt)
641 {
642 	bool bRet = false;
643 
644 	if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
645 		bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
646 	else
647 		bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
648 
649 	return bRet;
650 }
651 
wordEnMatched(struct pgpkt * pTargetPkt,struct pgpkt * pCurPkt,u8 * pWden)652 static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
653 			  u8 *pWden)
654 {
655 	u8 match_word_en = 0x0F;	/*  default all words are disabled */
656 
657 	/*  check if the same words are enabled both target and current PG packet */
658 	if (((pTargetPkt->word_en & BIT(0)) == 0) &&
659 	    ((pCurPkt->word_en & BIT(0)) == 0))
660 		match_word_en &= ~BIT(0);				/*  enable word 0 */
661 	if (((pTargetPkt->word_en & BIT(1)) == 0) &&
662 	    ((pCurPkt->word_en & BIT(1)) == 0))
663 		match_word_en &= ~BIT(1);				/*  enable word 1 */
664 	if (((pTargetPkt->word_en & BIT(2)) == 0) &&
665 	    ((pCurPkt->word_en & BIT(2)) == 0))
666 		match_word_en &= ~BIT(2);				/*  enable word 2 */
667 	if (((pTargetPkt->word_en & BIT(3)) == 0) &&
668 	    ((pCurPkt->word_en & BIT(3)) == 0))
669 		match_word_en &= ~BIT(3);				/*  enable word 3 */
670 
671 	*pWden = match_word_en;
672 
673 	if (match_word_en != 0xf)
674 		return true;
675 	else
676 		return false;
677 }
678 
hal_EfuseCheckIfDatafollowed(struct adapter * pAdapter,u8 word_cnts,u16 startAddr)679 static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
680 {
681 	bool bRet = false;
682 	u8 i, efuse_data;
683 
684 	for (i = 0; i < (word_cnts*2); i++) {
685 		if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF))
686 			bRet = true;
687 	}
688 	return bRet;
689 }
690 
hal_EfusePartialWriteCheck(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)691 static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
692 {
693 	bool bRet = false;
694 	u8 i, efuse_data = 0, cur_header = 0;
695 	u8 matched_wden = 0, badworden = 0;
696 	u16 startAddr = 0;
697 	u16 efuse_max_available_len =
698 		EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
699 	struct pgpkt curPkt;
700 
701 	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
702 	startAddr %= EFUSE_REAL_CONTENT_LEN;
703 
704 	while (1) {
705 		if (startAddr >= efuse_max_available_len) {
706 			bRet = false;
707 			break;
708 		}
709 
710 		if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
711 			if (EXT_HEADER(efuse_data)) {
712 				cur_header = efuse_data;
713 				startAddr++;
714 				efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
715 				if (ALL_WORDS_DISABLED(efuse_data)) {
716 					bRet = false;
717 					break;
718 				} else {
719 					curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
720 					curPkt.word_en = efuse_data & 0x0F;
721 				}
722 			} else {
723 				cur_header  =  efuse_data;
724 				curPkt.offset = (cur_header>>4) & 0x0F;
725 				curPkt.word_en = cur_header & 0x0F;
726 			}
727 
728 			curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
729 			/*  if same header is found but no data followed */
730 			/*  write some part of data followed by the header. */
731 			if ((curPkt.offset == pTargetPkt->offset) &&
732 			    (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) &&
733 			    wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
734 				/*  Here to write partial data */
735 				badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data);
736 				if (badworden != 0x0F) {
737 					u32	PgWriteSuccess = 0;
738 					/*  if write fail on some words, write these bad words again */
739 
740 					PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
741 
742 					if (!PgWriteSuccess) {
743 						bRet = false;	/*  write fail, return */
744 						break;
745 					}
746 				}
747 				/*  partial write ok, update the target packet for later use */
748 				for (i = 0; i < 4; i++) {
749 					if ((matched_wden & (0x1<<i)) == 0)	/*  this word has been written */
750 						pTargetPkt->word_en |= (0x1<<i);	/*  disable the word */
751 				}
752 				pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
753 			}
754 			/*  read from next header */
755 			startAddr = startAddr + (curPkt.word_cnts*2) + 1;
756 		} else {
757 			/*  not used header, 0xff */
758 			*pAddr = startAddr;
759 			bRet = true;
760 			break;
761 		}
762 	}
763 	return bRet;
764 }
765 
766 static bool
hal_EfusePgCheckAvailableAddr(struct adapter * pAdapter,u8 efuseType)767 hal_EfusePgCheckAvailableAddr(
768 		struct adapter *pAdapter,
769 		u8 efuseType
770 	)
771 {
772 	if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E)
773 		return false;
774 	return true;
775 }
776 
hal_EfuseConstructPGPkt(u8 offset,u8 word_en,u8 * pData,struct pgpkt * pTargetPkt)777 static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
778 {
779 	memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
780 	pTargetPkt->offset = offset;
781 	pTargetPkt->word_en = word_en;
782 	efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
783 	pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
784 }
785 
Efuse_PgPacketWrite(struct adapter * pAdapter,u8 offset,u8 word_en,u8 * pData)786 bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
787 {
788 	struct pgpkt	targetPkt;
789 	u16			startAddr = 0;
790 	u8 efuseType = EFUSE_WIFI;
791 
792 	if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
793 		return false;
794 
795 	hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
796 
797 	if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
798 		return false;
799 
800 	if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
801 		return false;
802 
803 	if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
804 		return false;
805 
806 	return true;
807 }
808 
Efuse_CalculateWordCnts(u8 word_en)809 u8 Efuse_CalculateWordCnts(u8 word_en)
810 {
811 	u8 word_cnts = 0;
812 
813 	if (!(word_en & BIT(0)))
814 		word_cnts++; /*  0 : write enable */
815 	if (!(word_en & BIT(1)))
816 		word_cnts++;
817 	if (!(word_en & BIT(2)))
818 		word_cnts++;
819 	if (!(word_en & BIT(3)))
820 		word_cnts++;
821 	return word_cnts;
822 }
823 
efuse_OneByteRead(struct adapter * pAdapter,u16 addr,u8 * data)824 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
825 {
826 	u8 tmpidx = 0;
827 	u8 result;
828 
829 	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
830 	usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
831 		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
832 
833 	usb_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
834 
835 	while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
836 		tmpidx++;
837 	if (tmpidx < 100) {
838 		*data = usb_read8(pAdapter, EFUSE_CTRL);
839 		result = true;
840 	} else {
841 		*data = 0xff;
842 		result = false;
843 	}
844 	return result;
845 }
846 
efuse_OneByteWrite(struct adapter * pAdapter,u16 addr,u8 data)847 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
848 {
849 	u8 tmpidx = 0;
850 	u8 result;
851 
852 	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
853 	usb_write8(pAdapter, EFUSE_CTRL+2,
854 		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
855 		   (u8)((addr>>8) & 0x03));
856 	usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
857 
858 	usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
859 
860 	while ((0x80 &  usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
861 		tmpidx++;
862 
863 	if (tmpidx < 100)
864 		result = true;
865 	else
866 		result = false;
867 
868 	return result;
869 }
870 
871 /*
872  * Overview:   Read allowed word in current efuse section data.
873  */
efuse_WordEnableDataRead(u8 word_en,u8 * sourdata,u8 * targetdata)874 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
875 {
876 	if (!(word_en & BIT(0))) {
877 		targetdata[0] = sourdata[0];
878 		targetdata[1] = sourdata[1];
879 	}
880 	if (!(word_en & BIT(1))) {
881 		targetdata[2] = sourdata[2];
882 		targetdata[3] = sourdata[3];
883 	}
884 	if (!(word_en & BIT(2))) {
885 		targetdata[4] = sourdata[4];
886 		targetdata[5] = sourdata[5];
887 	}
888 	if (!(word_en & BIT(3))) {
889 		targetdata[6] = sourdata[6];
890 		targetdata[7] = sourdata[7];
891 	}
892 }
893 
894 /*
895  * Overview:	Read All Efuse content
896  */
Efuse_ReadAllMap(struct adapter * pAdapter,u8 efuseType,u8 * Efuse)897 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
898 {
899 	efuse_power_switch(pAdapter, false, true);
900 
901 	efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse);
902 
903 	efuse_power_switch(pAdapter, false, false);
904 }
905 
906 /*
907  * Overview:	Transfer current EFUSE content to shadow init and modify map.
908  */
EFUSE_ShadowMapUpdate(struct adapter * pAdapter,u8 efuseType)909 void EFUSE_ShadowMapUpdate(
910 	struct adapter *pAdapter,
911 	u8 efuseType)
912 {
913 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
914 
915 	if (pEEPROM->bautoload_fail_flag)
916 		memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E);
917 	else
918 		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
919 }
920