Commit | Line | Data |
---|---|---|
2865d42c LF |
1 | /* |
2 | * rtl8712_efuse.c | |
3 | * | |
4 | * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. | |
5 | * Linux device driver for RTL8192SU | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of version 2 of the GNU General Public License as | |
9 | * published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program; if not, write to the Free Software Foundation, Inc., | |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
19 | * | |
20 | * Modifications for inclusion into the Linux staging tree are | |
21 | * Copyright(c) 2010 Larry Finger. All rights reserved. | |
22 | * | |
23 | * Contact information: | |
24 | * WLAN FAE <wlanfae@realtek.com>. | |
25 | * Larry Finger <Larry.Finger@lwfinger.net> | |
26 | * | |
27 | ******************************************************************************/ | |
28 | ||
29 | #define _RTL8712_EFUSE_C_ | |
30 | ||
31 | #include "osdep_service.h" | |
32 | #include "drv_types.h" | |
33 | #include "rtl8712_efuse.h" | |
34 | ||
35 | /* reserve 3 bytes for HW stop read */ | |
36 | static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/; | |
37 | ||
38 | static void efuse_reg_ctrl(struct _adapter *padapter, u8 bPowerOn) | |
39 | { | |
40 | u8 tmpu8 = 0; | |
41 | ||
42 | if (true == bPowerOn) { | |
43 | /* -----------------e-fuse pwr & clk reg ctrl --------------- | |
44 | * Enable LDOE25 Macro Block | |
45 | */ | |
46 | tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3); | |
47 | tmpu8 |= 0x80; | |
48 | r8712_write8(padapter, EFUSE_TEST + 3, tmpu8); | |
49 | msleep(20); /* for some platform , need some delay time */ | |
50 | /* Change Efuse Clock for write action to 40MHZ */ | |
51 | r8712_write8(padapter, EFUSE_CLK_CTRL, 0x03); | |
52 | msleep(20); /* for some platform , need some delay time */ | |
53 | } else { | |
54 | /* -----------------e-fuse pwr & clk reg ctrl ----------------- | |
55 | * Disable LDOE25 Macro Block | |
56 | */ | |
57 | tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3); | |
58 | tmpu8 &= 0x7F; | |
59 | r8712_write8(padapter, EFUSE_TEST + 3, tmpu8); | |
60 | /* Change Efuse Clock for write action to 500K */ | |
61 | r8712_write8(padapter, EFUSE_CLK_CTRL, 0x02); | |
62 | } | |
63 | } | |
64 | ||
65 | /* | |
66 | * Before write E-Fuse, this function must be called. | |
67 | */ | |
68 | u8 r8712_efuse_reg_init(struct _adapter *padapter) | |
69 | { | |
70 | return true; | |
71 | } | |
72 | ||
73 | void r8712_efuse_reg_uninit(struct _adapter *padapter) | |
74 | { | |
75 | efuse_reg_ctrl(padapter, false); | |
76 | } | |
77 | ||
78 | static u8 efuse_one_byte_read(struct _adapter *padapter, u16 addr, u8 *data) | |
79 | { | |
80 | u8 tmpidx = 0, bResult; | |
81 | ||
82 | /* -----------------e-fuse reg ctrl --------------------------------- */ | |
83 | r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */ | |
84 | r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) | | |
85 | (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC)); | |
86 | r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */ | |
87 | /* wait for complete */ | |
88 | while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) | |
89 | tmpidx++; | |
90 | if (tmpidx < 100) { | |
91 | *data = r8712_read8(padapter, EFUSE_CTRL); | |
92 | bResult = true; | |
93 | } else { | |
94 | *data = 0xff; | |
95 | bResult = false; | |
96 | } | |
97 | return bResult; | |
98 | } | |
99 | ||
100 | static u8 efuse_one_byte_write(struct _adapter *padapter, u16 addr, u8 data) | |
101 | { | |
102 | u8 tmpidx = 0, bResult; | |
103 | ||
104 | /* -----------------e-fuse reg ctrl -------------------------------- */ | |
105 | r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */ | |
106 | r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) | | |
107 | (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC)); | |
108 | r8712_write8(padapter, EFUSE_CTRL, data); /* data */ | |
109 | r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */ | |
110 | /* wait for complete */ | |
111 | while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) | |
112 | tmpidx++; | |
113 | if (tmpidx < 100) | |
114 | bResult = true; | |
115 | else | |
116 | bResult = false; | |
117 | return bResult; | |
118 | } | |
119 | ||
120 | static u8 efuse_one_byte_rw(struct _adapter *padapter, u8 bRead, u16 addr, | |
121 | u8 *data) | |
122 | { | |
123 | u8 tmpidx = 0, tmpv8 = 0, bResult; | |
124 | ||
125 | /* -----------------e-fuse reg ctrl --------------------------------- */ | |
126 | r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */ | |
127 | tmpv8 = ((u8)((addr >> 8) & 0x03)) | | |
128 | (r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC); | |
129 | r8712_write8(padapter, EFUSE_CTRL+2, tmpv8); | |
130 | if (true == bRead) { | |
131 | r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */ | |
132 | while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && | |
133 | (tmpidx < 100)) | |
134 | tmpidx++; | |
135 | if (tmpidx < 100) { | |
136 | *data = r8712_read8(padapter, EFUSE_CTRL); | |
137 | bResult = true; | |
138 | } else { | |
139 | *data = 0; | |
140 | bResult = false; | |
141 | } | |
142 | } else { | |
143 | r8712_write8(padapter, EFUSE_CTRL, *data); /* data */ | |
144 | r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */ | |
145 | while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && | |
146 | (tmpidx < 100)) | |
147 | tmpidx++; | |
148 | if (tmpidx < 100) | |
149 | bResult = true; | |
150 | else | |
151 | bResult = false; | |
152 | } | |
153 | return bResult; | |
154 | } | |
155 | ||
156 | static u8 efuse_is_empty(struct _adapter *padapter, u8 *empty) | |
157 | { | |
158 | u8 value, ret = true; | |
159 | ||
160 | /* read one byte to check if E-Fuse is empty */ | |
161 | if (efuse_one_byte_rw(padapter, true, 0, &value) == true) { | |
162 | if (0xFF == value) | |
163 | *empty = true; | |
164 | else | |
165 | *empty = false; | |
166 | } else | |
167 | ret = false; | |
168 | return ret; | |
169 | } | |
170 | ||
171 | void r8712_efuse_change_max_size(struct _adapter *padapter) | |
172 | { | |
173 | u16 pre_pg_data_saddr = 0x1FB; | |
174 | u16 i; | |
175 | u16 pre_pg_data_size = 5; | |
176 | u8 pre_pg_data[5]; | |
177 | ||
178 | for (i = 0; i < pre_pg_data_size; i++) | |
179 | efuse_one_byte_read(padapter, pre_pg_data_saddr + i, | |
180 | &pre_pg_data[i]); | |
181 | if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) && | |
182 | (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) && | |
183 | (pre_pg_data[4] == 0x0C)) | |
184 | efuse_available_max_size -= pre_pg_data_size; | |
185 | } | |
186 | ||
187 | int r8712_efuse_get_max_size(struct _adapter *padapter) | |
188 | { | |
189 | return efuse_available_max_size; | |
190 | } | |
191 | ||
192 | static u8 calculate_word_cnts(const u8 word_en) | |
193 | { | |
194 | u8 word_cnts = 0; | |
195 | u8 word_idx; | |
196 | ||
197 | for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) | |
198 | if (!(word_en & BIT(word_idx))) | |
199 | word_cnts++; /* 0 : write enable */ | |
200 | return word_cnts; | |
201 | } | |
202 | ||
203 | static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata, | |
204 | u8 *targetdata) | |
205 | { | |
206 | u8 tmpindex = 0; | |
207 | u8 word_idx, byte_idx; | |
208 | ||
209 | for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) { | |
210 | if (!(word_en&BIT(word_idx))) { | |
211 | byte_idx = word_idx * 2; | |
212 | targetdata[byte_idx] = sourdata[tmpindex++]; | |
213 | targetdata[byte_idx + 1] = sourdata[tmpindex++]; | |
214 | } | |
215 | } | |
216 | } | |
217 | ||
218 | u16 r8712_efuse_get_current_size(struct _adapter *padapter) | |
219 | { | |
220 | int bContinual = true; | |
221 | u16 efuse_addr = 0; | |
222 | u8 hoffset = 0, hworden = 0; | |
223 | u8 efuse_data, word_cnts = 0; | |
224 | ||
225 | while (bContinual && efuse_one_byte_read(padapter, efuse_addr, | |
226 | &efuse_data) && (efuse_addr < efuse_available_max_size)) { | |
227 | if (efuse_data != 0xFF) { | |
228 | hoffset = (efuse_data >> 4) & 0x0F; | |
229 | hworden = efuse_data & 0x0F; | |
230 | word_cnts = calculate_word_cnts(hworden); | |
231 | /* read next header */ | |
232 | efuse_addr = efuse_addr + (word_cnts * 2) + 1; | |
233 | } else | |
234 | bContinual = false ; | |
235 | } | |
236 | return efuse_addr; | |
237 | } | |
238 | ||
239 | u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data) | |
240 | { | |
241 | u8 hoffset = 0, hworden = 0, word_cnts = 0; | |
242 | u16 efuse_addr = 0; | |
243 | u8 efuse_data; | |
244 | u8 tmpidx = 0; | |
245 | u8 tmpdata[PGPKT_DATA_SIZE]; | |
246 | u8 ret = true; | |
247 | ||
248 | if (data == NULL) | |
249 | return false; | |
250 | if (offset > 0x0f) | |
251 | return false; | |
252 | memset(data, 0xFF, sizeof(u8)*PGPKT_DATA_SIZE); | |
253 | while (efuse_addr < efuse_available_max_size) { | |
254 | if (efuse_one_byte_read(padapter, efuse_addr, &efuse_data) == | |
255 | true) { | |
256 | if (efuse_data == 0xFF) | |
257 | break; | |
258 | hoffset = (efuse_data >> 4) & 0x0F; | |
259 | hworden = efuse_data & 0x0F; | |
260 | word_cnts = calculate_word_cnts(hworden); | |
261 | if (hoffset == offset) { | |
262 | memset(tmpdata, 0xFF, PGPKT_DATA_SIZE); | |
263 | for (tmpidx = 0; tmpidx < word_cnts * 2; | |
264 | tmpidx++) { | |
265 | if (efuse_one_byte_read(padapter, | |
266 | efuse_addr+1+tmpidx, &efuse_data) == | |
267 | true) { | |
268 | tmpdata[tmpidx] = efuse_data; | |
269 | } else | |
270 | ret = false; | |
271 | } | |
272 | pgpacket_copy_data(hworden, tmpdata, data); | |
273 | } | |
274 | efuse_addr += 1 + (word_cnts*2); | |
275 | } else { | |
276 | ret = false; | |
277 | break; | |
278 | } | |
279 | } | |
280 | return ret; | |
281 | } | |
282 | ||
283 | static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr) | |
284 | { | |
285 | struct PGPKT_STRUCT pkt; | |
286 | u8 offset, word_en, value; | |
287 | u16 addr; | |
288 | int i; | |
289 | u8 ret = true; | |
290 | ||
291 | pkt.offset = GET_EFUSE_OFFSET(header); | |
292 | pkt.word_en = GET_EFUSE_WORD_EN(header); | |
293 | addr = header_addr + 1 + calculate_word_cnts(pkt.word_en) * 2; | |
294 | if (addr > efuse_available_max_size) | |
295 | return false; | |
296 | /* retrieve original data */ | |
297 | addr = 0; | |
298 | while (addr < header_addr) { | |
299 | if (efuse_one_byte_read(padapter, addr++, &value) == false) { | |
300 | ret = false; | |
301 | break; | |
302 | } | |
303 | offset = GET_EFUSE_OFFSET(value); | |
304 | word_en = GET_EFUSE_WORD_EN(value); | |
305 | if (pkt.offset != offset) { | |
306 | addr += calculate_word_cnts(word_en)*2; | |
307 | continue; | |
308 | } | |
309 | for (i = 0; i < PGPKG_MAX_WORDS; i++) { | |
310 | if (BIT(i) & word_en) | |
311 | continue; | |
312 | if (!(BIT(i) & pkt.word_en)) { | |
313 | if (efuse_one_byte_read(padapter, addr, | |
314 | &value) == true) | |
315 | pkt.data[i*2] = value; | |
316 | else | |
317 | return false; | |
318 | if (efuse_one_byte_read(padapter, addr + 1, | |
319 | &value) == true) | |
320 | pkt.data[i*2 + 1] = value; | |
321 | else | |
322 | return false; | |
323 | } | |
324 | addr += 2; | |
325 | } | |
326 | } | |
327 | if (addr != header_addr) | |
328 | return false; | |
329 | addr++; | |
330 | /* fill original data */ | |
331 | for (i = 0; i < PGPKG_MAX_WORDS; i++) { | |
332 | if (BIT(i) & pkt.word_en) | |
333 | continue; | |
334 | efuse_one_byte_write(padapter, addr, pkt.data[i*2]); | |
335 | efuse_one_byte_write(padapter, addr+1, pkt.data[i*2 + 1]); | |
336 | /* additional check */ | |
337 | if (efuse_one_byte_read(padapter, addr, &value) == false) | |
338 | ret = false; | |
339 | else if (pkt.data[i*2] != value) { | |
340 | ret = false; | |
341 | if (0xFF == value) /* write again */ | |
342 | efuse_one_byte_write(padapter, addr, | |
343 | pkt.data[i * 2]); | |
344 | } | |
345 | if (efuse_one_byte_read(padapter, addr+1, &value) == false) | |
346 | ret = false; | |
347 | else if (pkt.data[i*2 + 1] != value) { | |
348 | ret = false; | |
349 | if (0xFF == value) /* write again */ | |
350 | efuse_one_byte_write(padapter, addr+1, | |
351 | pkt.data[i*2 + 1]); | |
352 | } | |
353 | addr += 2; | |
354 | } | |
355 | return ret; | |
356 | } | |
357 | ||
358 | u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset, | |
359 | const u8 word_en, const u8 *data) | |
360 | { | |
361 | u8 pg_header = 0; | |
362 | u16 efuse_addr = 0, curr_size = 0; | |
363 | u8 efuse_data, target_word_cnts = 0; | |
364 | static int repeat_times; | |
365 | int sub_repeat; | |
366 | u8 bResult = true; | |
367 | ||
368 | /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */ | |
369 | efuse_data = r8712_read8(padapter, EFUSE_CLK_CTRL); | |
370 | if (efuse_data != 0x03) | |
371 | return false; | |
372 | pg_header = MAKE_EFUSE_HEADER(offset, word_en); | |
373 | target_word_cnts = calculate_word_cnts(word_en); | |
374 | repeat_times = 0; | |
375 | efuse_addr = 0; | |
376 | while (efuse_addr < efuse_available_max_size) { | |
377 | curr_size = r8712_efuse_get_current_size(padapter); | |
378 | if ((curr_size + 1 + target_word_cnts * 2) > | |
379 | efuse_available_max_size) | |
380 | return false; /*target_word_cnts + pg header(1 byte)*/ | |
381 | efuse_addr = curr_size; /* current size is also the last addr*/ | |
382 | efuse_one_byte_write(padapter, efuse_addr, pg_header); /*hdr*/ | |
383 | sub_repeat = 0; | |
384 | /* check if what we read is what we write */ | |
385 | while (efuse_one_byte_read(padapter, efuse_addr, | |
386 | &efuse_data) == false) { | |
387 | if (++sub_repeat > _REPEAT_THRESHOLD_) { | |
388 | bResult = false; /* continue to blind write */ | |
389 | break; /* continue to blind write */ | |
390 | } | |
391 | } | |
392 | if ((sub_repeat > _REPEAT_THRESHOLD_) || | |
393 | (pg_header == efuse_data)) { | |
394 | /* write header ok OR can't check header(creep) */ | |
395 | u8 i; | |
396 | ||
397 | /* go to next address */ | |
398 | efuse_addr++; | |
399 | for (i = 0; i < target_word_cnts*2; i++) { | |
400 | efuse_one_byte_write(padapter, | |
401 | efuse_addr + i, | |
402 | *(data + i)); | |
403 | if (efuse_one_byte_read(padapter, | |
404 | efuse_addr + i, &efuse_data) == false) | |
405 | bResult = false; | |
406 | else if (*(data+i) != efuse_data) /* fail */ | |
407 | bResult = false; | |
408 | } | |
409 | break; | |
410 | } else { /* write header fail */ | |
411 | bResult = false; | |
412 | if (0xFF == efuse_data) | |
413 | return bResult; /* not thing damaged. */ | |
414 | /* call rescue procedure */ | |
415 | if (fix_header(padapter, efuse_data, efuse_addr) == | |
416 | false) | |
417 | return false; /* rescue fail */ | |
418 | ||
419 | if (++repeat_times > _REPEAT_THRESHOLD_) /* fail */ | |
420 | break; | |
421 | /* otherwise, take another risk... */ | |
422 | } | |
423 | } | |
424 | return bResult; | |
425 | } | |
426 | ||
427 | u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead, u16 start_addr, | |
428 | u16 cnts, u8 *data) | |
429 | { | |
430 | int i; | |
431 | u8 res = true;; | |
432 | ||
433 | if (start_addr > EFUSE_MAX_SIZE) | |
434 | return false; | |
435 | if ((bRead == false) && ((start_addr + cnts) > | |
436 | efuse_available_max_size)) | |
437 | return false; | |
438 | if ((false == bRead) && (r8712_efuse_reg_init(padapter) == false)) | |
439 | return false; | |
440 | /* -----------------e-fuse one byte read / write ---------------------*/ | |
441 | for (i = 0; i < cnts; i++) { | |
442 | if ((start_addr + i) > EFUSE_MAX_SIZE) { | |
443 | res = false; | |
444 | break; | |
445 | } | |
446 | res = efuse_one_byte_rw(padapter, bRead, start_addr + i, | |
447 | data + i); | |
448 | if ((false == bRead) && (false == res)) | |
449 | break; | |
450 | } | |
451 | if (false == bRead) | |
452 | r8712_efuse_reg_uninit(padapter); | |
453 | return res; | |
454 | } | |
455 | ||
456 | u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr, u16 cnts, u8 *data) | |
457 | { | |
458 | u8 offset, ret = true; | |
459 | u8 pktdata[PGPKT_DATA_SIZE]; | |
460 | int i, idx; | |
461 | ||
462 | if ((addr + cnts) > EFUSE_MAP_MAX_SIZE) | |
463 | return false; | |
464 | if ((efuse_is_empty(padapter, &offset) == true) && (offset == | |
465 | true)) { | |
466 | for (i = 0; i < cnts; i++) | |
467 | data[i] = 0xFF; | |
468 | return ret; | |
469 | } | |
470 | offset = (addr >> 3) & 0xF; | |
471 | ret = r8712_efuse_pg_packet_read(padapter, offset, pktdata); | |
472 | i = addr & 0x7; /* pktdata index */ | |
473 | idx = 0; /* data index */ | |
474 | ||
475 | do { | |
476 | for (; i < PGPKT_DATA_SIZE; i++) { | |
477 | data[idx++] = pktdata[i]; | |
478 | if (idx == cnts) | |
479 | return ret; | |
480 | } | |
481 | offset++; | |
482 | if (!r8712_efuse_pg_packet_read(padapter, offset, pktdata)) | |
483 | ret = false; | |
484 | i = 0; | |
485 | } while (1); | |
486 | return ret; | |
487 | } | |
488 | ||
489 | u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, u16 cnts, | |
490 | u8 *data) | |
491 | { | |
492 | u8 offset, word_en, empty; | |
493 | u8 pktdata[PGPKT_DATA_SIZE], newdata[PGPKT_DATA_SIZE]; | |
494 | int i, j, idx; | |
495 | ||
496 | if ((addr + cnts) > EFUSE_MAP_MAX_SIZE) | |
497 | return false; | |
498 | /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */ | |
499 | empty = r8712_read8(padapter, EFUSE_CLK_CTRL); | |
500 | if (empty != 0x03) | |
501 | return false; | |
502 | if (efuse_is_empty(padapter, &empty) == true) { | |
503 | if (true == empty) | |
504 | memset(pktdata, 0xFF, PGPKT_DATA_SIZE); | |
505 | } else | |
506 | return false; | |
507 | offset = (addr >> 3) & 0xF; | |
508 | if (empty == false) | |
509 | if (!r8712_efuse_pg_packet_read(padapter, offset, pktdata)) | |
510 | return false; | |
511 | word_en = 0xF; | |
512 | memset(newdata, 0xFF, PGPKT_DATA_SIZE); | |
513 | i = addr & 0x7; /* pktdata index */ | |
514 | j = 0; /* newdata index */ | |
515 | idx = 0; /* data index */ | |
516 | ||
517 | if (i & 0x1) { | |
518 | /* odd start */ | |
519 | if (data[idx] != pktdata[i]) { | |
520 | word_en &= ~BIT(i >> 1); | |
521 | newdata[j++] = pktdata[i - 1]; | |
522 | newdata[j++] = data[idx]; | |
523 | } | |
524 | i++; | |
525 | idx++; | |
526 | } | |
527 | do { | |
528 | for (; i < PGPKT_DATA_SIZE; i += 2) { | |
529 | if ((cnts - idx) == 1) { | |
530 | if (data[idx] != pktdata[i]) { | |
531 | word_en &= ~BIT(i >> 1); | |
532 | newdata[j++] = data[idx]; | |
533 | newdata[j++] = pktdata[1 + 1]; | |
534 | } | |
535 | idx++; | |
536 | break; | |
537 | } else { | |
538 | if ((data[idx] != pktdata[i]) || (data[idx+1] != | |
539 | pktdata[i+1])) { | |
540 | word_en &= ~BIT(i >> 1); | |
541 | newdata[j++] = data[idx]; | |
542 | newdata[j++] = data[idx + 1]; | |
543 | } | |
544 | idx += 2; | |
545 | } | |
546 | if (idx == cnts) | |
547 | break; | |
548 | } | |
549 | ||
550 | if (word_en != 0xF) | |
551 | if (r8712_efuse_pg_packet_write(padapter, offset, | |
552 | word_en, newdata) == false) | |
553 | return false; | |
554 | if (idx == cnts) | |
555 | break; | |
556 | offset++; | |
557 | if (empty == false) | |
558 | if (!r8712_efuse_pg_packet_read(padapter, offset, | |
559 | pktdata)) | |
560 | return false; | |
561 | i = 0; | |
562 | j = 0; | |
563 | word_en = 0xF; | |
564 | memset(newdata, 0xFF, PGPKT_DATA_SIZE); | |
565 | } while (1); | |
566 | ||
567 | return true; | |
568 | } |