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