1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3 
4 #define _RTW_EFUSE_C_
5 
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_efuse.h"
9 
10 /*------------------------Define local variable------------------------------*/
11 u8 fakeEfuseBank;
12 u32 fakeEfuseUsedBytes;
13 u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
14 u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
15 u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
16 
17 u32 BTEfuseUsedBytes;
18 u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
19 u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
20 u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
21 
22 u32 fakeBTEfuseUsedBytes;
23 u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
24 u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
25 u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
26 /*------------------------Define local variable------------------------------*/
27 
28 /*  */
29 #define REG_EFUSE_CTRL		0x0030
30 #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
31 /*  */
Efuse_Read1ByteFromFakeContent(struct adapter * pAdapter,u16 Offset,u8 * Value)32 static bool Efuse_Read1ByteFromFakeContent(struct adapter *pAdapter,
33 					   u16 Offset,
34 					   u8 *Value)
35 {
36 	if (Offset >= EFUSE_MAX_HW_SIZE)
37 		return false;
38 	if (fakeEfuseBank == 0)
39 		*Value = fakeEfuseContent[Offset];
40 	else
41 		*Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
42 	return true;
43 }
44 
45 static bool
Efuse_Write1ByteToFakeContent(struct adapter * pAdapter,u16 Offset,u8 Value)46 Efuse_Write1ByteToFakeContent(
47 			struct adapter *pAdapter,
48 			u16 Offset,
49 			u8 Value)
50 {
51 	if (Offset >= EFUSE_MAX_HW_SIZE)
52 		return false;
53 	if (fakeEfuseBank == 0) {
54 		fakeEfuseContent[Offset] = Value;
55 	} else {
56 		fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
57 	}
58 	return true;
59 }
60 
61 /*-----------------------------------------------------------------------------
62  * Function:	Efuse_PowerSwitch
63  *
64  * Overview:	When we want to enable write operation, we should change to
65  *				pwr on state. When we stop write, we should switch to 500k mode
66  *				and disable LDO 2.5V.
67  *
68  * Input:       NONE
69  *
70  * Output:      NONE
71  *
72  * Return:      NONE
73  *
74  * Revised History:
75  * When			Who		Remark
76  * 11/17/2008	MHC		Create Version 0.
77  *
78  *---------------------------------------------------------------------------*/
79 void
Efuse_PowerSwitch(struct adapter * pAdapter,u8 write,u8 PwrState)80 Efuse_PowerSwitch(
81 		struct adapter *pAdapter,
82 		u8 write,
83 		u8 PwrState)
84 {
85 	pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
86 }
87 
88 /*-----------------------------------------------------------------------------
89  * Function:	efuse_GetCurrentSize
90  *
91  * Overview:	Get current efuse size!!!
92  *
93  * Input:       NONE
94  *
95  * Output:      NONE
96  *
97  * Return:      NONE
98  *
99  * Revised History:
100  * When			Who		Remark
101  * 11/16/2008	MHC		Create Version 0.
102  *
103  *---------------------------------------------------------------------------*/
104 u16
Efuse_GetCurrentSize(struct adapter * pAdapter,u8 efuseType,bool pseudo)105 Efuse_GetCurrentSize(
106 	struct adapter *pAdapter,
107 	u8 efuseType,
108 	bool pseudo)
109 {
110 	u16 ret = 0;
111 
112 	ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
113 
114 	return ret;
115 }
116 
117 /*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
118 u8
Efuse_CalculateWordCnts(u8 word_en)119 Efuse_CalculateWordCnts(u8 word_en)
120 {
121 	u8 word_cnts = 0;
122 	if (!(word_en & BIT(0)))
123 		word_cnts++; /*  0 : write enable */
124 	if (!(word_en & BIT(1)))
125 		word_cnts++;
126 	if (!(word_en & BIT(2)))
127 		word_cnts++;
128 	if (!(word_en & BIT(3)))
129 		word_cnts++;
130 	return word_cnts;
131 }
132 
133 /*  */
134 /* 	Description: */
135 /* 		Execute E-Fuse read byte operation. */
136 /* 		Referred from SD1 Richard. */
137 /*  */
138 /* 	Assumption: */
139 /* 		1. Boot from E-Fuse and successfully auto-load. */
140 /* 		2. PASSIVE_LEVEL (USB interface) */
141 /*  */
142 /* 	Created by Roger, 2008.10.21. */
143 /*  */
144 void
ReadEFuseByte(struct adapter * Adapter,u16 _offset,u8 * pbuf,bool pseudo)145 ReadEFuseByte(
146 		struct adapter *Adapter,
147 		u16 _offset,
148 		u8 *pbuf,
149 		bool pseudo)
150 {
151 	u32 value32;
152 	u8 readbyte;
153 	u16 retry;
154 
155 	if (pseudo) {
156 		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
157 		return;
158 	}
159 
160 	/* Write Address */
161 	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
162 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
163 	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
164 
165 	/* Write bit 32 0 */
166 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
167 	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
168 
169 	/* Check bit 32 read-ready */
170 	retry = 0;
171 	value32 = rtw_read32(Adapter, EFUSE_CTRL);
172 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
173 		value32 = rtw_read32(Adapter, EFUSE_CTRL);
174 		retry++;
175 	}
176 
177 	/*  20100205 Joseph: Add delay suggested by SD1 Victor. */
178 	/*  This fix the problem that Efuse read error in high temperature condition. */
179 	/*  Designer says that there shall be some delay after ready bit is set, or the */
180 	/*  result will always stay on last data we read. */
181 	udelay(50);
182 	value32 = rtw_read32(Adapter, EFUSE_CTRL);
183 
184 	*pbuf = (u8)(value32 & 0xff);
185 }
186 
187 /*  */
188 /* 	Description: */
189 /* 		1. Execute E-Fuse read byte operation according as map offset and */
190 /* 		    save to E-Fuse table. */
191 /* 		2. Referred from SD1 Richard. */
192 /*  */
193 /* 	Assumption: */
194 /* 		1. Boot from E-Fuse and successfully auto-load. */
195 /* 		2. PASSIVE_LEVEL (USB interface) */
196 /*  */
197 /* 	Created by Roger, 2008.10.21. */
198 /*  */
199 /* 	2008/12/12 MH	1. Reorganize code flow and reserve bytes. and add description. */
200 /* 					2. Add efuse utilization collect. */
201 /* 	2008/12/22 MH	Read Efuse must check if we write section 1 data again!!! Sec1 */
202 /* 					write addr must be after sec5. */
203 /*  */
204 
efuse_ReadEFuse(struct adapter * Adapter,u8 efuseType,u16 _offset,u16 _size_byte,u8 * pbuf,bool pseudo)205 static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
206 {
207 	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
208 }
209 
EFUSE_GetEfuseDefinition(struct adapter * pAdapter,u8 efuseType,u8 type,void * pOut,bool pseudo)210 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
211 	)
212 {
213 	pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
214 }
215 
216 /*-----------------------------------------------------------------------------
217  * Function:	EFUSE_Read1Byte
218  *
219  * Overview:	Copy from WMAC fot EFUSE read 1 byte.
220  *
221  * Input:       NONE
222  *
223  * Output:      NONE
224  *
225  * Return:      NONE
226  *
227  * Revised History:
228  * When			Who		Remark
229  * 09/23/2008	MHC		Copy from WMAC.
230  *
231  *---------------------------------------------------------------------------*/
EFUSE_Read1Byte(struct adapter * Adapter,u16 Address)232 u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
233 {
234 	u8 data;
235 	u8 Bytetemp = {0x00};
236 	u8 temp = {0x00};
237 	u32 k = 0;
238 	u16 contentLen = 0;
239 
240 	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
241 
242 	if (Address < contentLen) {	/* E-fuse 512Byte */
243 		/* Write E-fuse Register address bit0~7 */
244 		temp = Address & 0xFF;
245 		rtw_write8(Adapter, EFUSE_CTRL + 1, temp);
246 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 2);
247 		/* Write E-fuse Register address bit8~9 */
248 		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
249 		rtw_write8(Adapter, EFUSE_CTRL + 2, temp);
250 
251 		/* Write 0x30[31]= 0 */
252 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
253 		temp = Bytetemp & 0x7F;
254 		rtw_write8(Adapter, EFUSE_CTRL + 3, temp);
255 
256 		/* Wait Write-ready (0x30[31]= 1) */
257 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
258 		while (!(Bytetemp & 0x80)) {
259 			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
260 			k++;
261 			if (k == 1000) {
262 				k = 0;
263 				break;
264 			}
265 		}
266 		data = rtw_read8(Adapter, EFUSE_CTRL);
267 		return data;
268 	} else {
269 		return 0xFF;
270 	}
271 
272 } /* EFUSE_Read1Byte */
273 
274 /*  11/16/2008 MH Read one byte from real Efuse. */
efuse_OneByteRead(struct adapter * pAdapter,u16 addr,u8 * data,bool pseudo)275 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
276 {
277 	u8 tmpidx = 0;
278 	u8 result;
279 
280 	if (pseudo) {
281 		result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
282 		return result;
283 	}
284 	/*  -----------------e-fuse reg ctrl --------------------------------- */
285 	/* address */
286 	rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
287 	rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
288 		   (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
289 
290 	rtw_write8(pAdapter, EFUSE_CTRL + 3,  0x72);/* read cmd */
291 
292 	while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
293 		tmpidx++;
294 	if (tmpidx < 100) {
295 		*data = rtw_read8(pAdapter, EFUSE_CTRL);
296 		result = true;
297 	} else {
298 		*data = 0xff;
299 		result = false;
300 	}
301 	return result;
302 }
303 
304 /*  11/16/2008 MH Write one byte to reald Efuse. */
efuse_OneByteWrite(struct adapter * pAdapter,u16 addr,u8 data,bool pseudo)305 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
306 {
307 	u8 tmpidx = 0;
308 	u8 result;
309 
310 	if (pseudo) {
311 		result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
312 		return result;
313 	}
314 
315 	/*  -----------------e-fuse reg ctrl --------------------------------- */
316 	/* address */
317 	rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
318 	rtw_write8(pAdapter, EFUSE_CTRL + 2,
319 		   (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
320 		   (u8)((addr >> 8) & 0x03));
321 	rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
322 
323 	rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
324 
325 	while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
326 		tmpidx++;
327 
328 	if (tmpidx < 100)
329 		result = true;
330 	else
331 		result = false;
332 
333 	return result;
334 }
335 
Efuse_PgPacketRead(struct adapter * pAdapter,u8 offset,u8 * data,bool pseudo)336 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
337 {
338 	int	ret = 0;
339 
340 	ret =  pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
341 
342 	return ret;
343 }
344 
Efuse_PgPacketWrite(struct adapter * pAdapter,u8 offset,u8 word_en,u8 * data,bool pseudo)345 int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
346 {
347 	int ret;
348 
349 	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
350 
351 	return ret;
352 }
353 
Efuse_PgPacketWrite_BT(struct adapter * pAdapter,u8 offset,u8 word_en,u8 * data,bool pseudo)354 static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
355 {
356 	int ret;
357 
358 	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
359 
360 	return ret;
361 }
362 
363 /*-----------------------------------------------------------------------------
364  * Function:	efuse_WordEnableDataRead
365  *
366  * Overview:	Read allowed word in current efuse section data.
367  *
368  * Input:       NONE
369  *
370  * Output:      NONE
371  *
372  * Return:      NONE
373  *
374  * Revised History:
375  * When			Who		Remark
376  * 11/16/2008	MHC		Create Version 0.
377  * 11/21/2008	MHC		Fix Write bug when we only enable late word.
378  *
379  *---------------------------------------------------------------------------*/
efuse_WordEnableDataRead(u8 word_en,u8 * sourdata,u8 * targetdata)380 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
381 {
382 	if (!(word_en & BIT(0))) {
383 		targetdata[0] = sourdata[0];
384 		targetdata[1] = sourdata[1];
385 	}
386 	if (!(word_en & BIT(1))) {
387 		targetdata[2] = sourdata[2];
388 		targetdata[3] = sourdata[3];
389 	}
390 	if (!(word_en & BIT(2))) {
391 		targetdata[4] = sourdata[4];
392 		targetdata[5] = sourdata[5];
393 	}
394 	if (!(word_en & BIT(3))) {
395 		targetdata[6] = sourdata[6];
396 		targetdata[7] = sourdata[7];
397 	}
398 }
399 
Efuse_WordEnableDataWrite(struct adapter * pAdapter,u16 efuse_addr,u8 word_en,u8 * data,bool pseudo)400 u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
401 {
402 	u8 ret = 0;
403 
404 	ret =  pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
405 
406 	return ret;
407 }
408 
efuse_read8(struct adapter * padapter,u16 address,u8 * value)409 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
410 {
411 	return efuse_OneByteRead(padapter, address, value, false);
412 }
413 
efuse_write8(struct adapter * padapter,u16 address,u8 * value)414 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
415 {
416 	return efuse_OneByteWrite(padapter, address, *value, false);
417 }
418 
419 /*
420  * read/wirte raw efuse data
421  */
rtw_efuse_access(struct adapter * padapter,u8 write,u16 start_addr,u16 cnts,u8 * data)422 u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
423 {
424 	int i = 0;
425 	u16 real_content_len = 0, max_available_size = 0;
426 	u8 res = _FAIL;
427 	u8 (*rw8)(struct adapter *, u16, u8*);
428 
429 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
430 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
431 
432 	if (start_addr > real_content_len)
433 		return _FAIL;
434 
435 	if (write) {
436 		if ((start_addr + cnts) > max_available_size)
437 			return _FAIL;
438 		rw8 = &efuse_write8;
439 	} else {
440 		rw8 = &efuse_read8;
441 	}
442 
443 	Efuse_PowerSwitch(padapter, write, true);
444 
445 	/*  e-fuse one byte read / write */
446 	for (i = 0; i < cnts; i++) {
447 		if (start_addr >= real_content_len) {
448 			res = _FAIL;
449 			break;
450 		}
451 
452 		res = rw8(padapter, start_addr++, data++);
453 		if (_FAIL == res)
454 			break;
455 	}
456 
457 	Efuse_PowerSwitch(padapter, write, false);
458 
459 	return res;
460 }
461 /*  */
efuse_GetMaxSize(struct adapter * padapter)462 u16 efuse_GetMaxSize(struct adapter *padapter)
463 {
464 	u16 max_size;
465 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
466 	return max_size;
467 }
468 /*  */
efuse_GetCurrentSize(struct adapter * padapter,u16 * size)469 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
470 {
471 	Efuse_PowerSwitch(padapter, false, true);
472 	*size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
473 	Efuse_PowerSwitch(padapter, false, false);
474 
475 	return _SUCCESS;
476 }
477 /*  */
rtw_efuse_map_read(struct adapter * padapter,u16 addr,u16 cnts,u8 * data)478 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
479 {
480 	u16 mapLen = 0;
481 
482 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
483 
484 	if ((addr + cnts) > mapLen)
485 		return _FAIL;
486 
487 	Efuse_PowerSwitch(padapter, false, true);
488 
489 	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
490 
491 	Efuse_PowerSwitch(padapter, false, false);
492 
493 	return _SUCCESS;
494 }
495 
rtw_BT_efuse_map_read(struct adapter * padapter,u16 addr,u16 cnts,u8 * data)496 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
497 {
498 	u16 mapLen = 0;
499 
500 	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
501 
502 	if ((addr + cnts) > mapLen)
503 		return _FAIL;
504 
505 	Efuse_PowerSwitch(padapter, false, true);
506 
507 	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
508 
509 	Efuse_PowerSwitch(padapter, false, false);
510 
511 	return _SUCCESS;
512 }
513 /*  */
rtw_efuse_map_write(struct adapter * padapter,u16 addr,u16 cnts,u8 * data)514 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
515 {
516 	u8 offset, word_en;
517 	u8 *map;
518 	u8 newdata[PGPKT_DATA_SIZE + 1];
519 	s32	i, idx;
520 	u8 ret = _SUCCESS;
521 	u16 mapLen = 0;
522 
523 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
524 
525 	if ((addr + cnts) > mapLen)
526 		return _FAIL;
527 
528 	map = kzalloc(mapLen, GFP_KERNEL);
529 	if (!map)
530 		return _FAIL;
531 
532 	ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
533 	if (ret == _FAIL)
534 		goto exit;
535 
536 	Efuse_PowerSwitch(padapter, true, true);
537 
538 	offset = (addr >> 3);
539 	word_en = 0xF;
540 	memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
541 	i = addr & 0x7;	/*  index of one package */
542 	idx = 0;	/*  data index */
543 
544 	if (i & 0x1) {
545 		/*  odd start */
546 		if (data[idx] != map[addr + idx]) {
547 			word_en &= ~BIT(i >> 1);
548 			newdata[i - 1] = map[addr + idx - 1];
549 			newdata[i] = data[idx];
550 		}
551 		i++;
552 		idx++;
553 	}
554 	do {
555 		for (; i < PGPKT_DATA_SIZE; i += 2) {
556 			if (cnts == idx)
557 				break;
558 			if ((cnts - idx) == 1) {
559 				if (data[idx] != map[addr + idx]) {
560 					word_en &= ~BIT(i >> 1);
561 					newdata[i] = data[idx];
562 					newdata[i + 1] = map[addr + idx + 1];
563 				}
564 				idx++;
565 				break;
566 			} else {
567 				if ((data[idx] != map[addr + idx]) ||
568 				    (data[idx + 1] != map[addr + idx + 1])) {
569 					word_en &= ~BIT(i >> 1);
570 					newdata[i] = data[idx];
571 					newdata[i + 1] = data[idx + 1];
572 				}
573 				idx += 2;
574 			}
575 			if (idx == cnts)
576 				break;
577 		}
578 
579 		if (word_en != 0xF) {
580 			ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
581 			DBG_88E("offset=%x\n", offset);
582 			DBG_88E("word_en=%x\n", word_en);
583 
584 			for (i = 0; i < PGPKT_DATA_SIZE; i++)
585 				DBG_88E("data=%x \t", newdata[i]);
586 			if (ret == _FAIL)
587 				break;
588 		}
589 
590 		if (idx == cnts)
591 			break;
592 
593 		offset++;
594 		i = 0;
595 		word_en = 0xF;
596 		memset(newdata, 0xFF, PGPKT_DATA_SIZE);
597 	} while (1);
598 
599 	Efuse_PowerSwitch(padapter, true, false);
600 exit:
601 	kfree(map);
602 	return ret;
603 }
604 
605 /*  */
rtw_BT_efuse_map_write(struct adapter * padapter,u16 addr,u16 cnts,u8 * data)606 u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
607 {
608 	u8 offset, word_en;
609 	u8 *map;
610 	u8 newdata[PGPKT_DATA_SIZE + 1];
611 	s32	i, idx;
612 	u8 ret = _SUCCESS;
613 	u16 mapLen = 0;
614 
615 	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
616 
617 	if ((addr + cnts) > mapLen)
618 		return _FAIL;
619 
620 	map = kzalloc(mapLen, GFP_KERNEL);
621 	if (!map)
622 		return _FAIL;
623 
624 	ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
625 	if (ret == _FAIL)
626 		goto exit;
627 
628 	Efuse_PowerSwitch(padapter, true, true);
629 
630 	offset = (addr >> 3);
631 	word_en = 0xF;
632 	memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
633 	i = addr & 0x7;	/*  index of one package */
634 	idx = 0;	/*  data index */
635 
636 	if (i & 0x1) {
637 		/*  odd start */
638 		if (data[idx] != map[addr + idx]) {
639 			word_en &= ~BIT(i >> 1);
640 			newdata[i - 1] = map[addr + idx - 1];
641 			newdata[i] = data[idx];
642 		}
643 		i++;
644 		idx++;
645 	}
646 	do {
647 		for (; i < PGPKT_DATA_SIZE; i += 2) {
648 			if (cnts == idx)
649 				break;
650 			if ((cnts - idx) == 1) {
651 				if (data[idx] != map[addr + idx]) {
652 					word_en &= ~BIT(i >> 1);
653 					newdata[i] = data[idx];
654 					newdata[i + 1] = map[addr + idx + 1];
655 				}
656 				idx++;
657 				break;
658 			} else {
659 				if ((data[idx] != map[addr + idx]) ||
660 				    (data[idx + 1] != map[addr + idx + 1])) {
661 					word_en &= ~BIT(i >> 1);
662 					newdata[i] = data[idx];
663 					newdata[i + 1] = data[idx + 1];
664 				}
665 				idx += 2;
666 			}
667 			if (idx == cnts)
668 				break;
669 		}
670 
671 		if (word_en != 0xF) {
672 			DBG_88E("%s: offset=%#X\n", __func__, offset);
673 			DBG_88E("%s: word_en=%#X\n", __func__, word_en);
674 			DBG_88E("%s: data=", __func__);
675 			for (i = 0; i < PGPKT_DATA_SIZE; i++)
676 				DBG_88E("0x%02X ", newdata[i]);
677 			DBG_88E("\n");
678 
679 			ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
680 			if (ret == _FAIL)
681 				break;
682 		}
683 
684 		if (idx == cnts)
685 			break;
686 
687 		offset++;
688 		i = 0;
689 		word_en = 0xF;
690 		memset(newdata, 0xFF, PGPKT_DATA_SIZE);
691 	} while (1);
692 
693 	Efuse_PowerSwitch(padapter, true, false);
694 
695 exit:
696 
697 	kfree(map);
698 
699 	return ret;
700 }
701 
702 /*-----------------------------------------------------------------------------
703  * Function:	efuse_ShadowRead1Byte
704  *			efuse_ShadowRead2Byte
705  *			efuse_ShadowRead4Byte
706  *
707  * Overview:	Read from efuse init map by one/two/four bytes !!!!!
708  *
709  * Input:       NONE
710  *
711  * Output:      NONE
712  *
713  * Return:      NONE
714  *
715  * Revised History:
716  * When			Who		Remark
717  * 11/12/2008	MHC		Create Version 0.
718  *
719  *---------------------------------------------------------------------------*/
720 static void
efuse_ShadowRead1Byte(struct adapter * pAdapter,u16 Offset,u8 * Value)721 efuse_ShadowRead1Byte(
722 		struct adapter *pAdapter,
723 		u16 Offset,
724 		u8 *Value)
725 {
726 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
727 
728 	*Value = pEEPROM->efuse_eeprom_data[Offset];
729 
730 }	/*  EFUSE_ShadowRead1Byte */
731 
732 /* Read Two Bytes */
733 static void
efuse_ShadowRead2Byte(struct adapter * pAdapter,u16 Offset,u16 * Value)734 efuse_ShadowRead2Byte(
735 		struct adapter *pAdapter,
736 		u16 Offset,
737 		u16 *Value)
738 {
739 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
740 
741 	*Value = pEEPROM->efuse_eeprom_data[Offset];
742 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
743 
744 }	/*  EFUSE_ShadowRead2Byte */
745 
746 /* Read Four Bytes */
747 static void
efuse_ShadowRead4Byte(struct adapter * pAdapter,u16 Offset,u32 * Value)748 efuse_ShadowRead4Byte(
749 		struct adapter *pAdapter,
750 		u16 Offset,
751 		u32 *Value)
752 {
753 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
754 
755 	*Value = pEEPROM->efuse_eeprom_data[Offset];
756 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
757 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 2] << 16;
758 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 3] << 24;
759 
760 }	/*  efuse_ShadowRead4Byte */
761 
762 /*-----------------------------------------------------------------------------
763  * Function:	Efuse_ReadAllMap
764  *
765  * Overview:	Read All Efuse content
766  *
767  * Input:       NONE
768  *
769  * Output:      NONE
770  *
771  * Return:      NONE
772  *
773  * Revised History:
774  * When			Who		Remark
775  * 11/11/2008	MHC		Create Version 0.
776  *
777  *---------------------------------------------------------------------------*/
Efuse_ReadAllMap(struct adapter * pAdapter,u8 efuseType,u8 * Efuse,bool pseudo)778 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
779 {
780 	u16 mapLen = 0;
781 
782 	Efuse_PowerSwitch(pAdapter, false, true);
783 
784 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
785 
786 	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
787 
788 	Efuse_PowerSwitch(pAdapter, false, false);
789 }
790 
791 /*-----------------------------------------------------------------------------
792  * Function:	EFUSE_ShadowMapUpdate
793  *
794  * Overview:	Transfer current EFUSE content to shadow init and modify map.
795  *
796  * Input:       NONE
797  *
798  * Output:      NONE
799  *
800  * Return:      NONE
801  *
802  * Revised History:
803  * When			Who		Remark
804  * 11/13/2008	MHC		Create Version 0.
805  *
806  *---------------------------------------------------------------------------*/
EFUSE_ShadowMapUpdate(struct adapter * pAdapter,u8 efuseType,bool pseudo)807 void EFUSE_ShadowMapUpdate(
808 	struct adapter *pAdapter,
809 	u8 efuseType,
810 	bool pseudo)
811 {
812 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
813 	u16 mapLen = 0;
814 
815 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
816 
817 	if (pEEPROM->bautoload_fail_flag)
818 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
819 	else
820 		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
821 } /*  EFUSE_ShadowMapUpdate */
822 
823 /*-----------------------------------------------------------------------------
824  * Function:	EFUSE_ShadowRead
825  *
826  * Overview:	Read from efuse init map !!!!!
827  *
828  * Input:       NONE
829  *
830  * Output:      NONE
831  *
832  * Return:      NONE
833  *
834  * Revised History:
835  * When			Who		Remark
836  * 11/12/2008	MHC		Create Version 0.
837  *
838  *---------------------------------------------------------------------------*/
EFUSE_ShadowRead(struct adapter * pAdapter,u8 Type,u16 Offset,u32 * Value)839 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
840 {
841 	if (Type == 1)
842 		efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
843 	else if (Type == 2)
844 		efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
845 	else if (Type == 4)
846 		efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
847 
848 }	/*  EFUSE_ShadowRead */
849