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