• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		goto exit;
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 exit;
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(efuseTbl);
214 
215 	if (eFuseWord)
216 		kfree(eFuseWord);
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 			msleep(1);
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 = (len-2 < limit) ? 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 	return;
326 }
327 
328 /* Do not support BT */
EFUSE_GetEfuseDefinition(struct adapter * pAdapter,u8 efuseType,u8 type,void * pOut)329 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
330 {
331 	switch (type) {
332 	case TYPE_EFUSE_MAX_SECTION:
333 		{
334 			u8 *pMax_section;
335 			pMax_section = (u8 *)pOut;
336 			*pMax_section = EFUSE_MAX_SECTION_88E;
337 		}
338 		break;
339 	case TYPE_EFUSE_REAL_CONTENT_LEN:
340 		{
341 			u16 *pu2Tmp;
342 			pu2Tmp = (u16 *)pOut;
343 			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
344 		}
345 		break;
346 	case TYPE_EFUSE_CONTENT_LEN_BANK:
347 		{
348 			u16 *pu2Tmp;
349 			pu2Tmp = (u16 *)pOut;
350 			*pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
351 		}
352 		break;
353 	case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
354 		{
355 			u16 *pu2Tmp;
356 			pu2Tmp = (u16 *)pOut;
357 			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
358 		}
359 		break;
360 	case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
361 		{
362 			u16 *pu2Tmp;
363 			pu2Tmp = (u16 *)pOut;
364 			*pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
365 		}
366 		break;
367 	case TYPE_EFUSE_MAP_LEN:
368 		{
369 			u16 *pu2Tmp;
370 			pu2Tmp = (u16 *)pOut;
371 			*pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
372 		}
373 		break;
374 	case TYPE_EFUSE_PROTECT_BYTES_BANK:
375 		{
376 			u8 *pu1Tmp;
377 			pu1Tmp = (u8 *)pOut;
378 			*pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
379 		}
380 		break;
381 	default:
382 		{
383 			u8 *pu1Tmp;
384 			pu1Tmp = (u8 *)pOut;
385 			*pu1Tmp = 0;
386 		}
387 		break;
388 	}
389 }
390 
Efuse_WordEnableDataWrite(struct adapter * pAdapter,u16 efuse_addr,u8 word_en,u8 * data)391 u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
392 {
393 	u16	tmpaddr = 0;
394 	u16	start_addr = efuse_addr;
395 	u8 badworden = 0x0F;
396 	u8 tmpdata[8];
397 
398 	memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
399 
400 	if (!(word_en&BIT0)) {
401 		tmpaddr = start_addr;
402 		efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
403 		efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
404 
405 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
406 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
407 		if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
408 			badworden &= (~BIT0);
409 	}
410 	if (!(word_en&BIT1)) {
411 		tmpaddr = start_addr;
412 		efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
413 		efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
414 
415 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
416 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
417 		if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
418 			badworden &= (~BIT1);
419 	}
420 	if (!(word_en&BIT2)) {
421 		tmpaddr = start_addr;
422 		efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
423 		efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
424 
425 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
426 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
427 		if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
428 			badworden &= (~BIT2);
429 	}
430 	if (!(word_en&BIT3)) {
431 		tmpaddr = start_addr;
432 		efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
433 		efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
434 
435 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
436 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
437 		if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
438 			badworden &= (~BIT3);
439 	}
440 	return badworden;
441 }
442 
Efuse_GetCurrentSize(struct adapter * pAdapter)443 static u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
444 {
445 	int	bContinual = true;
446 	u16	efuse_addr = 0;
447 	u8 hoffset = 0, hworden = 0;
448 	u8 efuse_data, word_cnts = 0;
449 
450 	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
451 
452 	while (bContinual &&
453 	       efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
454 	       AVAILABLE_EFUSE_ADDR(efuse_addr)) {
455 		if (efuse_data != 0xFF) {
456 			if ((efuse_data&0x1F) == 0x0F) {		/* extended header */
457 				hoffset = efuse_data;
458 				efuse_addr++;
459 				efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
460 				if ((efuse_data & 0x0F) == 0x0F) {
461 					efuse_addr++;
462 					continue;
463 				} else {
464 					hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
465 					hworden = efuse_data & 0x0F;
466 				}
467 			} else {
468 				hoffset = (efuse_data>>4) & 0x0F;
469 				hworden =  efuse_data & 0x0F;
470 			}
471 			word_cnts = Efuse_CalculateWordCnts(hworden);
472 			/* read next header */
473 			efuse_addr = efuse_addr + (word_cnts*2)+1;
474 		} else {
475 			bContinual = false;
476 		}
477 	}
478 
479 	rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
480 
481 	return efuse_addr;
482 }
483 
Efuse_PgPacketRead(struct adapter * pAdapter,u8 offset,u8 * data)484 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
485 {
486 	u8 ReadState = PG_STATE_HEADER;
487 	int	bContinual = true;
488 	int	bDataEmpty = true;
489 	u8 efuse_data, word_cnts = 0;
490 	u16	efuse_addr = 0;
491 	u8 hoffset = 0, hworden = 0;
492 	u8 tmpidx = 0;
493 	u8 tmpdata[8];
494 	u8 max_section = 0;
495 	u8 tmp_header = 0;
496 
497 	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section);
498 
499 	if (data == NULL)
500 		return false;
501 	if (offset > max_section)
502 		return false;
503 
504 	memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
505 	memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
506 
507 	/*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
508 	/*  Skip dummy parts to prevent unexpected data read from Efuse. */
509 	/*  By pass right now. 2009.02.19. */
510 	while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
511 		/*   Header Read ------------- */
512 		if (ReadState & PG_STATE_HEADER) {
513 			if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
514 				if (EXT_HEADER(efuse_data)) {
515 					tmp_header = efuse_data;
516 					efuse_addr++;
517 					efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
518 					if (!ALL_WORDS_DISABLED(efuse_data)) {
519 						hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
520 						hworden = efuse_data & 0x0F;
521 					} else {
522 						DBG_88E("Error, All words disabled\n");
523 						efuse_addr++;
524 						continue;
525 					}
526 				} else {
527 					hoffset = (efuse_data>>4) & 0x0F;
528 					hworden =  efuse_data & 0x0F;
529 				}
530 				word_cnts = Efuse_CalculateWordCnts(hworden);
531 				bDataEmpty = true;
532 
533 				if (hoffset == offset) {
534 					for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
535 						if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) {
536 							tmpdata[tmpidx] = efuse_data;
537 							if (efuse_data != 0xff)
538 								bDataEmpty = false;
539 						}
540 					}
541 					if (bDataEmpty == false) {
542 						ReadState = PG_STATE_DATA;
543 					} else {/* read next header */
544 						efuse_addr = efuse_addr + (word_cnts*2)+1;
545 						ReadState = PG_STATE_HEADER;
546 					}
547 				} else {/* read next header */
548 					efuse_addr = efuse_addr + (word_cnts*2)+1;
549 					ReadState = PG_STATE_HEADER;
550 				}
551 			} else {
552 				bContinual = false;
553 			}
554 		} else if (ReadState & PG_STATE_DATA) {
555 		/*   Data section Read ------------- */
556 			efuse_WordEnableDataRead(hworden, tmpdata, data);
557 			efuse_addr = efuse_addr + (word_cnts*2)+1;
558 			ReadState = PG_STATE_HEADER;
559 		}
560 
561 	}
562 
563 	if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
564 	    (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
565 		return false;
566 	else
567 		return true;
568 }
569 
hal_EfuseFixHeaderProcess(struct adapter * pAdapter,u8 efuseType,struct pgpkt * pFixPkt,u16 * pAddr)570 static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
571 {
572 	u8 originaldata[8], badworden = 0;
573 	u16	efuse_addr = *pAddr;
574 	u32	PgWriteSuccess = 0;
575 
576 	memset((void *)originaldata, 0xff, 8);
577 
578 	if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
579 		/* check if data exist */
580 		badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata);
581 
582 		if (badworden != 0xf) {	/*  write fail */
583 			PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
584 
585 			if (!PgWriteSuccess)
586 				return false;
587 			else
588 				efuse_addr = Efuse_GetCurrentSize(pAdapter);
589 		} else {
590 			efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
591 		}
592 	} else {
593 		efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
594 	}
595 	*pAddr = efuse_addr;
596 	return true;
597 }
598 
hal_EfusePgPacketWrite2ByteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)599 static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
600 {
601 	bool bRet = false;
602 	u16	efuse_addr = *pAddr, efuse_max_available_len = 0;
603 	u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
604 	u8 repeatcnt = 0;
605 
606 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
607 
608 	while (efuse_addr < efuse_max_available_len) {
609 		pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
610 		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
611 		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
612 
613 		while (tmp_header == 0xFF) {
614 			if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
615 				return false;
616 
617 			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
618 			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
619 		}
620 
621 		/* to write ext_header */
622 		if (tmp_header == pg_header) {
623 			efuse_addr++;
624 			pg_header_temp = pg_header;
625 			pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
626 
627 			efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
628 			efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
629 
630 			while (tmp_header == 0xFF) {
631 				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
632 					return false;
633 
634 				efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
635 				efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
636 			}
637 
638 			if ((tmp_header & 0x0F) == 0x0F) {	/* word_en PG fail */
639 				if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
640 					return false;
641 				} else {
642 					efuse_addr++;
643 					continue;
644 				}
645 			} else if (pg_header != tmp_header) {	/* offset PG fail */
646 				struct pgpkt	fixPkt;
647 				fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
648 				fixPkt.word_en = tmp_header & 0x0F;
649 				fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
650 				if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
651 					return false;
652 			} else {
653 				bRet = true;
654 				break;
655 			}
656 		} else if ((tmp_header & 0x1F) == 0x0F) {		/* wrong extended header */
657 			efuse_addr += 2;
658 			continue;
659 		}
660 	}
661 
662 	*pAddr = efuse_addr;
663 	return bRet;
664 }
665 
hal_EfusePgPacketWrite1ByteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)666 static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
667 {
668 	bool bRet = false;
669 	u8 pg_header = 0, tmp_header = 0;
670 	u16	efuse_addr = *pAddr;
671 	u8 repeatcnt = 0;
672 
673 	pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
674 
675 	efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
676 	efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
677 
678 	while (tmp_header == 0xFF) {
679 		if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
680 			return false;
681 		efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
682 		efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
683 	}
684 
685 	if (pg_header == tmp_header) {
686 		bRet = true;
687 	} else {
688 		struct pgpkt	fixPkt;
689 		fixPkt.offset = (tmp_header>>4) & 0x0F;
690 		fixPkt.word_en = tmp_header & 0x0F;
691 		fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
692 		if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
693 			return false;
694 	}
695 
696 	*pAddr = efuse_addr;
697 	return bRet;
698 }
699 
hal_EfusePgPacketWriteData(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)700 static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
701 {
702 	u16	efuse_addr = *pAddr;
703 	u8 badworden = 0;
704 	u32	PgWriteSuccess = 0;
705 
706 	badworden = 0x0f;
707 	badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data);
708 	if (badworden == 0x0F) {
709 		/*  write ok */
710 		return true;
711 	} else {
712 		/* reorganize other pg packet */
713 		PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
714 		if (!PgWriteSuccess)
715 			return false;
716 		else
717 			return true;
718 	}
719 }
720 
721 static bool
hal_EfusePgPacketWriteHeader(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)722 hal_EfusePgPacketWriteHeader(
723 				struct adapter *pAdapter,
724 				u8 efuseType,
725 				u16				*pAddr,
726 				struct pgpkt *pTargetPkt)
727 {
728 	bool bRet = false;
729 
730 	if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
731 		bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
732 	else
733 		bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
734 
735 	return bRet;
736 }
737 
wordEnMatched(struct pgpkt * pTargetPkt,struct pgpkt * pCurPkt,u8 * pWden)738 static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
739 			  u8 *pWden)
740 {
741 	u8 match_word_en = 0x0F;	/*  default all words are disabled */
742 
743 	/*  check if the same words are enabled both target and current PG packet */
744 	if (((pTargetPkt->word_en & BIT0) == 0) &&
745 	    ((pCurPkt->word_en & BIT0) == 0))
746 		match_word_en &= ~BIT0;				/*  enable word 0 */
747 	if (((pTargetPkt->word_en & BIT1) == 0) &&
748 	    ((pCurPkt->word_en & BIT1) == 0))
749 		match_word_en &= ~BIT1;				/*  enable word 1 */
750 	if (((pTargetPkt->word_en & BIT2) == 0) &&
751 	    ((pCurPkt->word_en & BIT2) == 0))
752 		match_word_en &= ~BIT2;				/*  enable word 2 */
753 	if (((pTargetPkt->word_en & BIT3) == 0) &&
754 	    ((pCurPkt->word_en & BIT3) == 0))
755 		match_word_en &= ~BIT3;				/*  enable word 3 */
756 
757 	*pWden = match_word_en;
758 
759 	if (match_word_en != 0xf)
760 		return true;
761 	else
762 		return false;
763 }
764 
hal_EfuseCheckIfDatafollowed(struct adapter * pAdapter,u8 word_cnts,u16 startAddr)765 static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
766 {
767 	bool bRet = false;
768 	u8 i, efuse_data;
769 
770 	for (i = 0; i < (word_cnts*2); i++) {
771 		if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF))
772 			bRet = true;
773 	}
774 	return bRet;
775 }
776 
hal_EfusePartialWriteCheck(struct adapter * pAdapter,u8 efuseType,u16 * pAddr,struct pgpkt * pTargetPkt)777 static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
778 {
779 	bool bRet = false;
780 	u8 i, efuse_data = 0, cur_header = 0;
781 	u8 matched_wden = 0, badworden = 0;
782 	u16	startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
783 	struct pgpkt curPkt;
784 
785 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
786 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max);
787 
788 	rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
789 	startAddr %= EFUSE_REAL_CONTENT_LEN;
790 
791 	while (1) {
792 		if (startAddr >= efuse_max_available_len) {
793 			bRet = false;
794 			break;
795 		}
796 
797 		if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
798 			if (EXT_HEADER(efuse_data)) {
799 				cur_header = efuse_data;
800 				startAddr++;
801 				efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
802 				if (ALL_WORDS_DISABLED(efuse_data)) {
803 					bRet = false;
804 					break;
805 				} else {
806 					curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
807 					curPkt.word_en = efuse_data & 0x0F;
808 				}
809 			} else {
810 				cur_header  =  efuse_data;
811 				curPkt.offset = (cur_header>>4) & 0x0F;
812 				curPkt.word_en = cur_header & 0x0F;
813 			}
814 
815 			curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
816 			/*  if same header is found but no data followed */
817 			/*  write some part of data followed by the header. */
818 			if ((curPkt.offset == pTargetPkt->offset) &&
819 			    (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) &&
820 			    wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
821 				/*  Here to write partial data */
822 				badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data);
823 				if (badworden != 0x0F) {
824 					u32	PgWriteSuccess = 0;
825 					/*  if write fail on some words, write these bad words again */
826 
827 					PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
828 
829 					if (!PgWriteSuccess) {
830 						bRet = false;	/*  write fail, return */
831 						break;
832 					}
833 				}
834 				/*  partial write ok, update the target packet for later use */
835 				for (i = 0; i < 4; i++) {
836 					if ((matched_wden & (0x1<<i)) == 0)	/*  this word has been written */
837 						pTargetPkt->word_en |= (0x1<<i);	/*  disable the word */
838 				}
839 				pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
840 			}
841 			/*  read from next header */
842 			startAddr = startAddr + (curPkt.word_cnts*2) + 1;
843 		} else {
844 			/*  not used header, 0xff */
845 			*pAddr = startAddr;
846 			bRet = true;
847 			break;
848 		}
849 	}
850 	return bRet;
851 }
852 
853 static bool
hal_EfusePgCheckAvailableAddr(struct adapter * pAdapter,u8 efuseType)854 hal_EfusePgCheckAvailableAddr(
855 		struct adapter *pAdapter,
856 		u8 efuseType
857 	)
858 {
859 	u16	efuse_max_available_len = 0;
860 
861 	/* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
862 	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len);
863 
864 	if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len)
865 		return false;
866 	return true;
867 }
868 
hal_EfuseConstructPGPkt(u8 offset,u8 word_en,u8 * pData,struct pgpkt * pTargetPkt)869 static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
870 {
871 	memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
872 	pTargetPkt->offset = offset;
873 	pTargetPkt->word_en = word_en;
874 	efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
875 	pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
876 }
877 
Efuse_PgPacketWrite(struct adapter * pAdapter,u8 offset,u8 word_en,u8 * pData)878 bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
879 {
880 	struct pgpkt	targetPkt;
881 	u16			startAddr = 0;
882 	u8 efuseType = EFUSE_WIFI;
883 
884 	if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
885 		return false;
886 
887 	hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
888 
889 	if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
890 		return false;
891 
892 	if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
893 		return false;
894 
895 	if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
896 		return false;
897 
898 	return true;
899 }
900 
Efuse_CalculateWordCnts(u8 word_en)901 u8 Efuse_CalculateWordCnts(u8 word_en)
902 {
903 	u8 word_cnts = 0;
904 	if (!(word_en & BIT(0)))
905 		word_cnts++; /*  0 : write enable */
906 	if (!(word_en & BIT(1)))
907 		word_cnts++;
908 	if (!(word_en & BIT(2)))
909 		word_cnts++;
910 	if (!(word_en & BIT(3)))
911 		word_cnts++;
912 	return word_cnts;
913 }
914 
efuse_OneByteRead(struct adapter * pAdapter,u16 addr,u8 * data)915 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
916 {
917 	u8 tmpidx = 0;
918 	u8 result;
919 
920 	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
921 	usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
922 		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
923 
924 	usb_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
925 
926 	while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
927 		tmpidx++;
928 	if (tmpidx < 100) {
929 		*data = usb_read8(pAdapter, EFUSE_CTRL);
930 		result = true;
931 	} else {
932 		*data = 0xff;
933 		result = false;
934 	}
935 	return result;
936 }
937 
efuse_OneByteWrite(struct adapter * pAdapter,u16 addr,u8 data)938 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
939 {
940 	u8 tmpidx = 0;
941 	u8 result;
942 
943 	usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
944 	usb_write8(pAdapter, EFUSE_CTRL+2,
945 		   (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
946 		   (u8)((addr>>8) & 0x03));
947 	usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
948 
949 	usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
950 
951 	while ((0x80 &  usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
952 		tmpidx++;
953 
954 	if (tmpidx < 100)
955 		result = true;
956 	else
957 		result = false;
958 
959 	return result;
960 }
961 
962 /*
963  * Overview:   Read allowed word in current efuse section data.
964  */
efuse_WordEnableDataRead(u8 word_en,u8 * sourdata,u8 * targetdata)965 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
966 {
967 	if (!(word_en&BIT(0))) {
968 		targetdata[0] = sourdata[0];
969 		targetdata[1] = sourdata[1];
970 	}
971 	if (!(word_en&BIT(1))) {
972 		targetdata[2] = sourdata[2];
973 		targetdata[3] = sourdata[3];
974 	}
975 	if (!(word_en&BIT(2))) {
976 		targetdata[4] = sourdata[4];
977 		targetdata[5] = sourdata[5];
978 	}
979 	if (!(word_en&BIT(3))) {
980 		targetdata[6] = sourdata[6];
981 		targetdata[7] = sourdata[7];
982 	}
983 }
984 
985 /*
986  * Overview:	Read All Efuse content
987  */
Efuse_ReadAllMap(struct adapter * pAdapter,u8 efuseType,u8 * Efuse)988 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
989 {
990 	u16 mapLen = 0;
991 
992 	Efuse_PowerSwitch(pAdapter, false, true);
993 
994 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
995 
996 	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
997 
998 	Efuse_PowerSwitch(pAdapter, false, false);
999 }
1000 
1001 /*
1002  * Overview:	Transfer current EFUSE content to shadow init and modify map.
1003  */
EFUSE_ShadowMapUpdate(struct adapter * pAdapter,u8 efuseType)1004 void EFUSE_ShadowMapUpdate(
1005 	struct adapter *pAdapter,
1006 	u8 efuseType)
1007 {
1008 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
1009 	u16 mapLen = 0;
1010 
1011 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
1012 
1013 	if (pEEPROM->bautoload_fail_flag)
1014 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
1015 	else
1016 		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
1017 }
1018