1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 2009-2012 Realtek Corporation.*/
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include "wifi.h"
5*4882a593Smuzhiyun #include "efuse.h"
6*4882a593Smuzhiyun #include "pci.h"
7*4882a593Smuzhiyun #include <linux/export.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun static const u8 PGPKT_DATA_SIZE = 8;
10*4882a593Smuzhiyun static const int EFUSE_MAX_SIZE = 512;
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define START_ADDRESS 0x1000
13*4882a593Smuzhiyun #define REG_MCUFWDL 0x0080
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun static const struct rtl_efuse_ops efuse_ops = {
16*4882a593Smuzhiyun .efuse_onebyte_read = efuse_one_byte_read,
17*4882a593Smuzhiyun .efuse_logical_map_read = efuse_shadow_read,
18*4882a593Smuzhiyun };
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset,
21*4882a593Smuzhiyun u8 *value);
22*4882a593Smuzhiyun static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset,
23*4882a593Smuzhiyun u16 *value);
24*4882a593Smuzhiyun static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, u16 offset,
25*4882a593Smuzhiyun u32 *value);
26*4882a593Smuzhiyun static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, u16 offset,
27*4882a593Smuzhiyun u8 value);
28*4882a593Smuzhiyun static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, u16 offset,
29*4882a593Smuzhiyun u16 value);
30*4882a593Smuzhiyun static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, u16 offset,
31*4882a593Smuzhiyun u32 value);
32*4882a593Smuzhiyun static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr,
33*4882a593Smuzhiyun u8 data);
34*4882a593Smuzhiyun static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse);
35*4882a593Smuzhiyun static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset,
36*4882a593Smuzhiyun u8 *data);
37*4882a593Smuzhiyun static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 offset,
38*4882a593Smuzhiyun u8 word_en, u8 *data);
39*4882a593Smuzhiyun static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata,
40*4882a593Smuzhiyun u8 *targetdata);
41*4882a593Smuzhiyun static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
42*4882a593Smuzhiyun u16 efuse_addr, u8 word_en, u8 *data);
43*4882a593Smuzhiyun static u16 efuse_get_current_size(struct ieee80211_hw *hw);
44*4882a593Smuzhiyun static u8 efuse_calculate_word_cnts(u8 word_en);
45*4882a593Smuzhiyun
efuse_initialize(struct ieee80211_hw * hw)46*4882a593Smuzhiyun void efuse_initialize(struct ieee80211_hw *hw)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
49*4882a593Smuzhiyun u8 bytetemp;
50*4882a593Smuzhiyun u8 temp;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1);
53*4882a593Smuzhiyun temp = bytetemp | 0x20;
54*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1, temp);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1);
57*4882a593Smuzhiyun temp = bytetemp & 0xFE;
58*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1, temp);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3);
61*4882a593Smuzhiyun temp = bytetemp | 0x80;
62*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, temp);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun rtl_write_byte(rtlpriv, 0x2F8, 0x3);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
efuse_read_1byte(struct ieee80211_hw * hw,u16 address)70*4882a593Smuzhiyun u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
73*4882a593Smuzhiyun u8 data;
74*4882a593Smuzhiyun u8 bytetemp;
75*4882a593Smuzhiyun u8 temp;
76*4882a593Smuzhiyun u32 k = 0;
77*4882a593Smuzhiyun const u32 efuse_len =
78*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (address < efuse_len) {
81*4882a593Smuzhiyun temp = address & 0xFF;
82*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
83*4882a593Smuzhiyun temp);
84*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
85*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
86*4882a593Smuzhiyun temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC);
87*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
88*4882a593Smuzhiyun temp);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
91*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
92*4882a593Smuzhiyun temp = bytetemp & 0x7F;
93*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3,
94*4882a593Smuzhiyun temp);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
97*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
98*4882a593Smuzhiyun while (!(bytetemp & 0x80)) {
99*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
100*4882a593Smuzhiyun rtlpriv->cfg->
101*4882a593Smuzhiyun maps[EFUSE_CTRL] + 3);
102*4882a593Smuzhiyun k++;
103*4882a593Smuzhiyun if (k == 1000)
104*4882a593Smuzhiyun break;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
107*4882a593Smuzhiyun return data;
108*4882a593Smuzhiyun } else
109*4882a593Smuzhiyun return 0xFF;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun EXPORT_SYMBOL(efuse_read_1byte);
113*4882a593Smuzhiyun
efuse_write_1byte(struct ieee80211_hw * hw,u16 address,u8 value)114*4882a593Smuzhiyun void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
117*4882a593Smuzhiyun u8 bytetemp;
118*4882a593Smuzhiyun u8 temp;
119*4882a593Smuzhiyun u32 k = 0;
120*4882a593Smuzhiyun const u32 efuse_len =
121*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n",
124*4882a593Smuzhiyun address, value);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun if (address < efuse_len) {
127*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun temp = address & 0xFF;
130*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
131*4882a593Smuzhiyun temp);
132*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
133*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC);
136*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
137*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 2, temp);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
140*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
141*4882a593Smuzhiyun temp = bytetemp | 0x80;
142*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
143*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3, temp);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
146*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun while (bytetemp & 0x80) {
149*4882a593Smuzhiyun bytetemp = rtl_read_byte(rtlpriv,
150*4882a593Smuzhiyun rtlpriv->cfg->
151*4882a593Smuzhiyun maps[EFUSE_CTRL] + 3);
152*4882a593Smuzhiyun k++;
153*4882a593Smuzhiyun if (k == 100) {
154*4882a593Smuzhiyun k = 0;
155*4882a593Smuzhiyun break;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
read_efuse_byte(struct ieee80211_hw * hw,u16 _offset,u8 * pbuf)162*4882a593Smuzhiyun void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
165*4882a593Smuzhiyun u32 value32;
166*4882a593Smuzhiyun u8 readbyte;
167*4882a593Smuzhiyun u16 retry;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
170*4882a593Smuzhiyun (_offset & 0xff));
171*4882a593Smuzhiyun readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
172*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
173*4882a593Smuzhiyun ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
176*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3,
177*4882a593Smuzhiyun (readbyte & 0x7f));
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun retry = 0;
180*4882a593Smuzhiyun value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
181*4882a593Smuzhiyun while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
182*4882a593Smuzhiyun value32 = rtl_read_dword(rtlpriv,
183*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL]);
184*4882a593Smuzhiyun retry++;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun udelay(50);
188*4882a593Smuzhiyun value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun *pbuf = (u8) (value32 & 0xff);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(read_efuse_byte);
193*4882a593Smuzhiyun
read_efuse(struct ieee80211_hw * hw,u16 _offset,u16 _size_byte,u8 * pbuf)194*4882a593Smuzhiyun void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
197*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
198*4882a593Smuzhiyun u8 *efuse_tbl;
199*4882a593Smuzhiyun u8 rtemp8[1];
200*4882a593Smuzhiyun u16 efuse_addr = 0;
201*4882a593Smuzhiyun u8 offset, wren;
202*4882a593Smuzhiyun u8 u1temp = 0;
203*4882a593Smuzhiyun u16 i;
204*4882a593Smuzhiyun u16 j;
205*4882a593Smuzhiyun const u16 efuse_max_section =
206*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP];
207*4882a593Smuzhiyun const u32 efuse_len =
208*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
209*4882a593Smuzhiyun u16 **efuse_word;
210*4882a593Smuzhiyun u16 efuse_utilized = 0;
211*4882a593Smuzhiyun u8 efuse_usage;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) {
214*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
215*4882a593Smuzhiyun "%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
216*4882a593Smuzhiyun __func__, _offset, _size_byte);
217*4882a593Smuzhiyun return;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /* allocate memory for efuse_tbl and efuse_word */
221*4882a593Smuzhiyun efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE],
222*4882a593Smuzhiyun GFP_ATOMIC);
223*4882a593Smuzhiyun if (!efuse_tbl)
224*4882a593Smuzhiyun return;
225*4882a593Smuzhiyun efuse_word = kcalloc(EFUSE_MAX_WORD_UNIT, sizeof(u16 *), GFP_ATOMIC);
226*4882a593Smuzhiyun if (!efuse_word)
227*4882a593Smuzhiyun goto out;
228*4882a593Smuzhiyun for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
229*4882a593Smuzhiyun efuse_word[i] = kcalloc(efuse_max_section, sizeof(u16),
230*4882a593Smuzhiyun GFP_ATOMIC);
231*4882a593Smuzhiyun if (!efuse_word[i])
232*4882a593Smuzhiyun goto done;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun for (i = 0; i < efuse_max_section; i++)
236*4882a593Smuzhiyun for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
237*4882a593Smuzhiyun efuse_word[j][i] = 0xFFFF;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
240*4882a593Smuzhiyun if (*rtemp8 != 0xFF) {
241*4882a593Smuzhiyun efuse_utilized++;
242*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
243*4882a593Smuzhiyun "Addr=%d\n", efuse_addr);
244*4882a593Smuzhiyun efuse_addr++;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) {
248*4882a593Smuzhiyun /* Check PG header for section num. */
249*4882a593Smuzhiyun if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */
250*4882a593Smuzhiyun u1temp = ((*rtemp8 & 0xE0) >> 5);
251*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if ((*rtemp8 & 0x0F) == 0x0F) {
254*4882a593Smuzhiyun efuse_addr++;
255*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun if (*rtemp8 != 0xFF &&
258*4882a593Smuzhiyun (efuse_addr < efuse_len)) {
259*4882a593Smuzhiyun efuse_addr++;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun continue;
262*4882a593Smuzhiyun } else {
263*4882a593Smuzhiyun offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
264*4882a593Smuzhiyun wren = (*rtemp8 & 0x0F);
265*4882a593Smuzhiyun efuse_addr++;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun } else {
268*4882a593Smuzhiyun offset = ((*rtemp8 >> 4) & 0x0f);
269*4882a593Smuzhiyun wren = (*rtemp8 & 0x0f);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (offset < efuse_max_section) {
273*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
274*4882a593Smuzhiyun "offset-%d Worden=%x\n", offset, wren);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
277*4882a593Smuzhiyun if (!(wren & 0x01)) {
278*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM,
279*4882a593Smuzhiyun EFUSE_READ_ALL,
280*4882a593Smuzhiyun "Addr=%d\n", efuse_addr);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
283*4882a593Smuzhiyun efuse_addr++;
284*4882a593Smuzhiyun efuse_utilized++;
285*4882a593Smuzhiyun efuse_word[i][offset] =
286*4882a593Smuzhiyun (*rtemp8 & 0xff);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun if (efuse_addr >= efuse_len)
289*4882a593Smuzhiyun break;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM,
292*4882a593Smuzhiyun EFUSE_READ_ALL,
293*4882a593Smuzhiyun "Addr=%d\n", efuse_addr);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
296*4882a593Smuzhiyun efuse_addr++;
297*4882a593Smuzhiyun efuse_utilized++;
298*4882a593Smuzhiyun efuse_word[i][offset] |=
299*4882a593Smuzhiyun (((u16)*rtemp8 << 8) & 0xff00);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (efuse_addr >= efuse_len)
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun wren >>= 1;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
310*4882a593Smuzhiyun "Addr=%d\n", efuse_addr);
311*4882a593Smuzhiyun read_efuse_byte(hw, efuse_addr, rtemp8);
312*4882a593Smuzhiyun if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) {
313*4882a593Smuzhiyun efuse_utilized++;
314*4882a593Smuzhiyun efuse_addr++;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun for (i = 0; i < efuse_max_section; i++) {
319*4882a593Smuzhiyun for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
320*4882a593Smuzhiyun efuse_tbl[(i * 8) + (j * 2)] =
321*4882a593Smuzhiyun (efuse_word[j][i] & 0xff);
322*4882a593Smuzhiyun efuse_tbl[(i * 8) + ((j * 2) + 1)] =
323*4882a593Smuzhiyun ((efuse_word[j][i] >> 8) & 0xff);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun for (i = 0; i < _size_byte; i++)
328*4882a593Smuzhiyun pbuf[i] = efuse_tbl[_offset + i];
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun rtlefuse->efuse_usedbytes = efuse_utilized;
331*4882a593Smuzhiyun efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len);
332*4882a593Smuzhiyun rtlefuse->efuse_usedpercentage = efuse_usage;
333*4882a593Smuzhiyun rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES,
334*4882a593Smuzhiyun (u8 *)&efuse_utilized);
335*4882a593Smuzhiyun rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE,
336*4882a593Smuzhiyun &efuse_usage);
337*4882a593Smuzhiyun done:
338*4882a593Smuzhiyun for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++)
339*4882a593Smuzhiyun kfree(efuse_word[i]);
340*4882a593Smuzhiyun kfree(efuse_word);
341*4882a593Smuzhiyun out:
342*4882a593Smuzhiyun kfree(efuse_tbl);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
efuse_shadow_update_chk(struct ieee80211_hw * hw)345*4882a593Smuzhiyun bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
348*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
349*4882a593Smuzhiyun u8 section_idx, i, base;
350*4882a593Smuzhiyun u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used;
351*4882a593Smuzhiyun bool wordchanged, result = true;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun for (section_idx = 0; section_idx < 16; section_idx++) {
354*4882a593Smuzhiyun base = section_idx * 8;
355*4882a593Smuzhiyun wordchanged = false;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun for (i = 0; i < 8; i = i + 2) {
358*4882a593Smuzhiyun if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] !=
359*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i] ||
360*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] !=
361*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i +
362*4882a593Smuzhiyun 1]) {
363*4882a593Smuzhiyun words_need++;
364*4882a593Smuzhiyun wordchanged = true;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (wordchanged)
369*4882a593Smuzhiyun hdr_num++;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun totalbytes = hdr_num + words_need * 2;
373*4882a593Smuzhiyun efuse_used = rtlefuse->efuse_usedbytes;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun if ((totalbytes + efuse_used) >=
376*4882a593Smuzhiyun (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))
377*4882a593Smuzhiyun result = false;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
380*4882a593Smuzhiyun "%s: totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n",
381*4882a593Smuzhiyun __func__, totalbytes, hdr_num, words_need, efuse_used);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun return result;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
efuse_shadow_read(struct ieee80211_hw * hw,u8 type,u16 offset,u32 * value)386*4882a593Smuzhiyun void efuse_shadow_read(struct ieee80211_hw *hw, u8 type,
387*4882a593Smuzhiyun u16 offset, u32 *value)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun if (type == 1)
390*4882a593Smuzhiyun efuse_shadow_read_1byte(hw, offset, (u8 *)value);
391*4882a593Smuzhiyun else if (type == 2)
392*4882a593Smuzhiyun efuse_shadow_read_2byte(hw, offset, (u16 *)value);
393*4882a593Smuzhiyun else if (type == 4)
394*4882a593Smuzhiyun efuse_shadow_read_4byte(hw, offset, value);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun EXPORT_SYMBOL(efuse_shadow_read);
398*4882a593Smuzhiyun
efuse_shadow_write(struct ieee80211_hw * hw,u8 type,u16 offset,u32 value)399*4882a593Smuzhiyun void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset,
400*4882a593Smuzhiyun u32 value)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun if (type == 1)
403*4882a593Smuzhiyun efuse_shadow_write_1byte(hw, offset, (u8) value);
404*4882a593Smuzhiyun else if (type == 2)
405*4882a593Smuzhiyun efuse_shadow_write_2byte(hw, offset, (u16) value);
406*4882a593Smuzhiyun else if (type == 4)
407*4882a593Smuzhiyun efuse_shadow_write_4byte(hw, offset, value);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
efuse_shadow_update(struct ieee80211_hw * hw)411*4882a593Smuzhiyun bool efuse_shadow_update(struct ieee80211_hw *hw)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
414*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
415*4882a593Smuzhiyun u16 i, offset, base;
416*4882a593Smuzhiyun u8 word_en = 0x0F;
417*4882a593Smuzhiyun u8 first_pg = false;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (!efuse_shadow_update_chk(hw)) {
422*4882a593Smuzhiyun efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
423*4882a593Smuzhiyun memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
424*4882a593Smuzhiyun &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
425*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
428*4882a593Smuzhiyun "efuse out of capacity!!\n");
429*4882a593Smuzhiyun return false;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun efuse_power_switch(hw, true, true);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun for (offset = 0; offset < 16; offset++) {
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun word_en = 0x0F;
436*4882a593Smuzhiyun base = offset * 8;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun for (i = 0; i < 8; i++) {
439*4882a593Smuzhiyun if (first_pg) {
440*4882a593Smuzhiyun word_en &= ~(BIT(i / 2));
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] =
443*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i];
444*4882a593Smuzhiyun } else {
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] !=
447*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) {
448*4882a593Smuzhiyun word_en &= ~(BIT(i / 2));
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] =
451*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i];
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (word_en != 0x0F) {
457*4882a593Smuzhiyun u8 tmpdata[8];
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun memcpy(tmpdata,
460*4882a593Smuzhiyun &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base],
461*4882a593Smuzhiyun 8);
462*4882a593Smuzhiyun RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD,
463*4882a593Smuzhiyun "U-efuse\n", tmpdata, 8);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (!efuse_pg_packet_write(hw, (u8) offset, word_en,
466*4882a593Smuzhiyun tmpdata)) {
467*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
468*4882a593Smuzhiyun "PG section(%#x) fail!!\n", offset);
469*4882a593Smuzhiyun break;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun efuse_power_switch(hw, true, false);
475*4882a593Smuzhiyun efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
478*4882a593Smuzhiyun &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
479*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
482*4882a593Smuzhiyun return true;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
rtl_efuse_shadow_map_update(struct ieee80211_hw * hw)485*4882a593Smuzhiyun void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
488*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun if (rtlefuse->autoload_failflag)
491*4882a593Smuzhiyun memset((&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]),
492*4882a593Smuzhiyun 0xFF, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
493*4882a593Smuzhiyun else
494*4882a593Smuzhiyun efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
497*4882a593Smuzhiyun &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
498*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
502*4882a593Smuzhiyun
efuse_force_write_vendor_id(struct ieee80211_hw * hw)503*4882a593Smuzhiyun void efuse_force_write_vendor_id(struct ieee80211_hw *hw)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF };
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun efuse_power_switch(hw, true, true);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun efuse_pg_packet_write(hw, 1, 0xD, tmpdata);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun efuse_power_switch(hw, true, false);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
efuse_re_pg_section(struct ieee80211_hw * hw,u8 section_idx)515*4882a593Smuzhiyun void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
efuse_shadow_read_1byte(struct ieee80211_hw * hw,u16 offset,u8 * value)519*4882a593Smuzhiyun static void efuse_shadow_read_1byte(struct ieee80211_hw *hw,
520*4882a593Smuzhiyun u16 offset, u8 *value)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
523*4882a593Smuzhiyun *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
efuse_shadow_read_2byte(struct ieee80211_hw * hw,u16 offset,u16 * value)526*4882a593Smuzhiyun static void efuse_shadow_read_2byte(struct ieee80211_hw *hw,
527*4882a593Smuzhiyun u16 offset, u16 *value)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
532*4882a593Smuzhiyun *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
efuse_shadow_read_4byte(struct ieee80211_hw * hw,u16 offset,u32 * value)536*4882a593Smuzhiyun static void efuse_shadow_read_4byte(struct ieee80211_hw *hw,
537*4882a593Smuzhiyun u16 offset, u32 *value)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
542*4882a593Smuzhiyun *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8;
543*4882a593Smuzhiyun *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] << 16;
544*4882a593Smuzhiyun *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] << 24;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
efuse_shadow_write_1byte(struct ieee80211_hw * hw,u16 offset,u8 value)547*4882a593Smuzhiyun static void efuse_shadow_write_1byte(struct ieee80211_hw *hw,
548*4882a593Smuzhiyun u16 offset, u8 value)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
efuse_shadow_write_2byte(struct ieee80211_hw * hw,u16 offset,u16 value)555*4882a593Smuzhiyun static void efuse_shadow_write_2byte(struct ieee80211_hw *hw,
556*4882a593Smuzhiyun u16 offset, u16 value)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value & 0x00FF;
561*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = value >> 8;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
efuse_shadow_write_4byte(struct ieee80211_hw * hw,u16 offset,u32 value)565*4882a593Smuzhiyun static void efuse_shadow_write_4byte(struct ieee80211_hw *hw,
566*4882a593Smuzhiyun u16 offset, u32 value)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] =
571*4882a593Smuzhiyun (u8) (value & 0x000000FF);
572*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] =
573*4882a593Smuzhiyun (u8) ((value >> 8) & 0x0000FF);
574*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] =
575*4882a593Smuzhiyun (u8) ((value >> 16) & 0x00FF);
576*4882a593Smuzhiyun rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] =
577*4882a593Smuzhiyun (u8) ((value >> 24) & 0xFF);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun
efuse_one_byte_read(struct ieee80211_hw * hw,u16 addr,u8 * data)581*4882a593Smuzhiyun int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
584*4882a593Smuzhiyun u8 tmpidx = 0;
585*4882a593Smuzhiyun int result;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
588*4882a593Smuzhiyun (u8) (addr & 0xff));
589*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
590*4882a593Smuzhiyun ((u8) ((addr >> 8) & 0x03)) |
591*4882a593Smuzhiyun (rtl_read_byte(rtlpriv,
592*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 2) &
593*4882a593Smuzhiyun 0xFC));
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72);
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun while (!(0x80 & rtl_read_byte(rtlpriv,
598*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3))
599*4882a593Smuzhiyun && (tmpidx < 100)) {
600*4882a593Smuzhiyun tmpidx++;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (tmpidx < 100) {
604*4882a593Smuzhiyun *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
605*4882a593Smuzhiyun result = true;
606*4882a593Smuzhiyun } else {
607*4882a593Smuzhiyun *data = 0xff;
608*4882a593Smuzhiyun result = false;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun return result;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun EXPORT_SYMBOL(efuse_one_byte_read);
613*4882a593Smuzhiyun
efuse_one_byte_write(struct ieee80211_hw * hw,u16 addr,u8 data)614*4882a593Smuzhiyun static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
617*4882a593Smuzhiyun u8 tmpidx = 0;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
620*4882a593Smuzhiyun "Addr = %x Data=%x\n", addr, data);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
623*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff));
624*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
625*4882a593Smuzhiyun (rtl_read_byte(rtlpriv,
626*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] +
627*4882a593Smuzhiyun 2) & 0xFC) | (u8) ((addr >> 8) & 0x03));
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], data);
630*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0xF2);
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun while ((0x80 & rtl_read_byte(rtlpriv,
633*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_CTRL] + 3))
634*4882a593Smuzhiyun && (tmpidx < 100)) {
635*4882a593Smuzhiyun tmpidx++;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun if (tmpidx < 100)
639*4882a593Smuzhiyun return true;
640*4882a593Smuzhiyun return false;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
efuse_read_all_map(struct ieee80211_hw * hw,u8 * efuse)643*4882a593Smuzhiyun static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun efuse_power_switch(hw, false, true);
648*4882a593Smuzhiyun read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse);
649*4882a593Smuzhiyun efuse_power_switch(hw, false, false);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
efuse_read_data_case1(struct ieee80211_hw * hw,u16 * efuse_addr,u8 efuse_data,u8 offset,u8 * tmpdata,u8 * readstate)652*4882a593Smuzhiyun static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
653*4882a593Smuzhiyun u8 efuse_data, u8 offset, u8 *tmpdata,
654*4882a593Smuzhiyun u8 *readstate)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun bool dataempty = true;
657*4882a593Smuzhiyun u8 hoffset;
658*4882a593Smuzhiyun u8 tmpidx;
659*4882a593Smuzhiyun u8 hworden;
660*4882a593Smuzhiyun u8 word_cnts;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun hoffset = (efuse_data >> 4) & 0x0F;
663*4882a593Smuzhiyun hworden = efuse_data & 0x0F;
664*4882a593Smuzhiyun word_cnts = efuse_calculate_word_cnts(hworden);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (hoffset == offset) {
667*4882a593Smuzhiyun for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
668*4882a593Smuzhiyun if (efuse_one_byte_read(hw, *efuse_addr + 1 + tmpidx,
669*4882a593Smuzhiyun &efuse_data)) {
670*4882a593Smuzhiyun tmpdata[tmpidx] = efuse_data;
671*4882a593Smuzhiyun if (efuse_data != 0xff)
672*4882a593Smuzhiyun dataempty = false;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun if (!dataempty) {
677*4882a593Smuzhiyun *readstate = PG_STATE_DATA;
678*4882a593Smuzhiyun } else {
679*4882a593Smuzhiyun *efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
680*4882a593Smuzhiyun *readstate = PG_STATE_HEADER;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun } else {
684*4882a593Smuzhiyun *efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
685*4882a593Smuzhiyun *readstate = PG_STATE_HEADER;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
efuse_pg_packet_read(struct ieee80211_hw * hw,u8 offset,u8 * data)689*4882a593Smuzhiyun static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun u8 readstate = PG_STATE_HEADER;
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun bool continual = true;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun u8 efuse_data, word_cnts = 0;
696*4882a593Smuzhiyun u16 efuse_addr = 0;
697*4882a593Smuzhiyun u8 tmpdata[8];
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (data == NULL)
700*4882a593Smuzhiyun return false;
701*4882a593Smuzhiyun if (offset > 15)
702*4882a593Smuzhiyun return false;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
705*4882a593Smuzhiyun memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun while (continual && (efuse_addr < EFUSE_MAX_SIZE)) {
708*4882a593Smuzhiyun if (readstate & PG_STATE_HEADER) {
709*4882a593Smuzhiyun if (efuse_one_byte_read(hw, efuse_addr, &efuse_data)
710*4882a593Smuzhiyun && (efuse_data != 0xFF))
711*4882a593Smuzhiyun efuse_read_data_case1(hw, &efuse_addr,
712*4882a593Smuzhiyun efuse_data, offset,
713*4882a593Smuzhiyun tmpdata, &readstate);
714*4882a593Smuzhiyun else
715*4882a593Smuzhiyun continual = false;
716*4882a593Smuzhiyun } else if (readstate & PG_STATE_DATA) {
717*4882a593Smuzhiyun efuse_word_enable_data_read(0, tmpdata, data);
718*4882a593Smuzhiyun efuse_addr = efuse_addr + (word_cnts * 2) + 1;
719*4882a593Smuzhiyun readstate = PG_STATE_HEADER;
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun if ((data[0] == 0xff) && (data[1] == 0xff) &&
725*4882a593Smuzhiyun (data[2] == 0xff) && (data[3] == 0xff) &&
726*4882a593Smuzhiyun (data[4] == 0xff) && (data[5] == 0xff) &&
727*4882a593Smuzhiyun (data[6] == 0xff) && (data[7] == 0xff))
728*4882a593Smuzhiyun return false;
729*4882a593Smuzhiyun else
730*4882a593Smuzhiyun return true;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
efuse_write_data_case1(struct ieee80211_hw * hw,u16 * efuse_addr,u8 efuse_data,u8 offset,int * continual,u8 * write_state,struct pgpkt_struct * target_pkt,int * repeat_times,int * result,u8 word_en)734*4882a593Smuzhiyun static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
735*4882a593Smuzhiyun u8 efuse_data, u8 offset,
736*4882a593Smuzhiyun int *continual, u8 *write_state,
737*4882a593Smuzhiyun struct pgpkt_struct *target_pkt,
738*4882a593Smuzhiyun int *repeat_times, int *result, u8 word_en)
739*4882a593Smuzhiyun {
740*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
741*4882a593Smuzhiyun struct pgpkt_struct tmp_pkt;
742*4882a593Smuzhiyun int dataempty = true;
743*4882a593Smuzhiyun u8 originaldata[8 * sizeof(u8)];
744*4882a593Smuzhiyun u8 badworden = 0x0F;
745*4882a593Smuzhiyun u8 match_word_en, tmp_word_en;
746*4882a593Smuzhiyun u8 tmpindex;
747*4882a593Smuzhiyun u8 tmp_header = efuse_data;
748*4882a593Smuzhiyun u8 tmp_word_cnts;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun tmp_pkt.offset = (tmp_header >> 4) & 0x0F;
751*4882a593Smuzhiyun tmp_pkt.word_en = tmp_header & 0x0F;
752*4882a593Smuzhiyun tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (tmp_pkt.offset != target_pkt->offset) {
755*4882a593Smuzhiyun *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
756*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
757*4882a593Smuzhiyun } else {
758*4882a593Smuzhiyun for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) {
759*4882a593Smuzhiyun if (efuse_one_byte_read(hw,
760*4882a593Smuzhiyun (*efuse_addr + 1 + tmpindex),
761*4882a593Smuzhiyun &efuse_data) &&
762*4882a593Smuzhiyun (efuse_data != 0xFF))
763*4882a593Smuzhiyun dataempty = false;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun if (!dataempty) {
767*4882a593Smuzhiyun *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
768*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
769*4882a593Smuzhiyun } else {
770*4882a593Smuzhiyun match_word_en = 0x0F;
771*4882a593Smuzhiyun if (!((target_pkt->word_en & BIT(0)) |
772*4882a593Smuzhiyun (tmp_pkt.word_en & BIT(0))))
773*4882a593Smuzhiyun match_word_en &= (~BIT(0));
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun if (!((target_pkt->word_en & BIT(1)) |
776*4882a593Smuzhiyun (tmp_pkt.word_en & BIT(1))))
777*4882a593Smuzhiyun match_word_en &= (~BIT(1));
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun if (!((target_pkt->word_en & BIT(2)) |
780*4882a593Smuzhiyun (tmp_pkt.word_en & BIT(2))))
781*4882a593Smuzhiyun match_word_en &= (~BIT(2));
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun if (!((target_pkt->word_en & BIT(3)) |
784*4882a593Smuzhiyun (tmp_pkt.word_en & BIT(3))))
785*4882a593Smuzhiyun match_word_en &= (~BIT(3));
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun if ((match_word_en & 0x0F) != 0x0F) {
788*4882a593Smuzhiyun badworden =
789*4882a593Smuzhiyun enable_efuse_data_write(hw,
790*4882a593Smuzhiyun *efuse_addr + 1,
791*4882a593Smuzhiyun tmp_pkt.word_en,
792*4882a593Smuzhiyun target_pkt->data);
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun if (0x0F != (badworden & 0x0F)) {
795*4882a593Smuzhiyun u8 reorg_offset = offset;
796*4882a593Smuzhiyun u8 reorg_worden = badworden;
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun efuse_pg_packet_write(hw, reorg_offset,
799*4882a593Smuzhiyun reorg_worden,
800*4882a593Smuzhiyun originaldata);
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun tmp_word_en = 0x0F;
804*4882a593Smuzhiyun if ((target_pkt->word_en & BIT(0)) ^
805*4882a593Smuzhiyun (match_word_en & BIT(0)))
806*4882a593Smuzhiyun tmp_word_en &= (~BIT(0));
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun if ((target_pkt->word_en & BIT(1)) ^
809*4882a593Smuzhiyun (match_word_en & BIT(1)))
810*4882a593Smuzhiyun tmp_word_en &= (~BIT(1));
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if ((target_pkt->word_en & BIT(2)) ^
813*4882a593Smuzhiyun (match_word_en & BIT(2)))
814*4882a593Smuzhiyun tmp_word_en &= (~BIT(2));
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun if ((target_pkt->word_en & BIT(3)) ^
817*4882a593Smuzhiyun (match_word_en & BIT(3)))
818*4882a593Smuzhiyun tmp_word_en &= (~BIT(3));
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if ((tmp_word_en & 0x0F) != 0x0F) {
821*4882a593Smuzhiyun *efuse_addr = efuse_get_current_size(hw);
822*4882a593Smuzhiyun target_pkt->offset = offset;
823*4882a593Smuzhiyun target_pkt->word_en = tmp_word_en;
824*4882a593Smuzhiyun } else {
825*4882a593Smuzhiyun *continual = false;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
828*4882a593Smuzhiyun *repeat_times += 1;
829*4882a593Smuzhiyun if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
830*4882a593Smuzhiyun *continual = false;
831*4882a593Smuzhiyun *result = false;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun } else {
834*4882a593Smuzhiyun *efuse_addr += (2 * tmp_word_cnts) + 1;
835*4882a593Smuzhiyun target_pkt->offset = offset;
836*4882a593Smuzhiyun target_pkt->word_en = word_en;
837*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse PG_STATE_HEADER-1\n");
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
efuse_write_data_case2(struct ieee80211_hw * hw,u16 * efuse_addr,int * continual,u8 * write_state,struct pgpkt_struct target_pkt,int * repeat_times,int * result)844*4882a593Smuzhiyun static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr,
845*4882a593Smuzhiyun int *continual, u8 *write_state,
846*4882a593Smuzhiyun struct pgpkt_struct target_pkt,
847*4882a593Smuzhiyun int *repeat_times, int *result)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
850*4882a593Smuzhiyun struct pgpkt_struct tmp_pkt;
851*4882a593Smuzhiyun u8 pg_header;
852*4882a593Smuzhiyun u8 tmp_header;
853*4882a593Smuzhiyun u8 originaldata[8 * sizeof(u8)];
854*4882a593Smuzhiyun u8 tmp_word_cnts;
855*4882a593Smuzhiyun u8 badworden = 0x0F;
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en;
858*4882a593Smuzhiyun efuse_one_byte_write(hw, *efuse_addr, pg_header);
859*4882a593Smuzhiyun efuse_one_byte_read(hw, *efuse_addr, &tmp_header);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (tmp_header == pg_header) {
862*4882a593Smuzhiyun *write_state = PG_STATE_DATA;
863*4882a593Smuzhiyun } else if (tmp_header == 0xFF) {
864*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
865*4882a593Smuzhiyun *repeat_times += 1;
866*4882a593Smuzhiyun if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
867*4882a593Smuzhiyun *continual = false;
868*4882a593Smuzhiyun *result = false;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun } else {
871*4882a593Smuzhiyun tmp_pkt.offset = (tmp_header >> 4) & 0x0F;
872*4882a593Smuzhiyun tmp_pkt.word_en = tmp_header & 0x0F;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun memset(originaldata, 0xff, 8 * sizeof(u8));
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) {
879*4882a593Smuzhiyun badworden = enable_efuse_data_write(hw,
880*4882a593Smuzhiyun *efuse_addr + 1,
881*4882a593Smuzhiyun tmp_pkt.word_en,
882*4882a593Smuzhiyun originaldata);
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun if (0x0F != (badworden & 0x0F)) {
885*4882a593Smuzhiyun u8 reorg_offset = tmp_pkt.offset;
886*4882a593Smuzhiyun u8 reorg_worden = badworden;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun efuse_pg_packet_write(hw, reorg_offset,
889*4882a593Smuzhiyun reorg_worden,
890*4882a593Smuzhiyun originaldata);
891*4882a593Smuzhiyun *efuse_addr = efuse_get_current_size(hw);
892*4882a593Smuzhiyun } else {
893*4882a593Smuzhiyun *efuse_addr = *efuse_addr +
894*4882a593Smuzhiyun (tmp_word_cnts * 2) + 1;
895*4882a593Smuzhiyun }
896*4882a593Smuzhiyun } else {
897*4882a593Smuzhiyun *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun *write_state = PG_STATE_HEADER;
901*4882a593Smuzhiyun *repeat_times += 1;
902*4882a593Smuzhiyun if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
903*4882a593Smuzhiyun *continual = false;
904*4882a593Smuzhiyun *result = false;
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
908*4882a593Smuzhiyun "efuse PG_STATE_HEADER-2\n");
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun
efuse_pg_packet_write(struct ieee80211_hw * hw,u8 offset,u8 word_en,u8 * data)912*4882a593Smuzhiyun static int efuse_pg_packet_write(struct ieee80211_hw *hw,
913*4882a593Smuzhiyun u8 offset, u8 word_en, u8 *data)
914*4882a593Smuzhiyun {
915*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
916*4882a593Smuzhiyun struct pgpkt_struct target_pkt;
917*4882a593Smuzhiyun u8 write_state = PG_STATE_HEADER;
918*4882a593Smuzhiyun int continual = true, result = true;
919*4882a593Smuzhiyun u16 efuse_addr = 0;
920*4882a593Smuzhiyun u8 efuse_data;
921*4882a593Smuzhiyun u8 target_word_cnts = 0;
922*4882a593Smuzhiyun u8 badworden = 0x0F;
923*4882a593Smuzhiyun static int repeat_times;
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE -
926*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
927*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
928*4882a593Smuzhiyun "efuse_pg_packet_write error\n");
929*4882a593Smuzhiyun return false;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun target_pkt.offset = offset;
933*4882a593Smuzhiyun target_pkt.word_en = word_en;
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun memset(target_pkt.data, 0xFF, 8 * sizeof(u8));
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun efuse_word_enable_data_read(word_en, data, target_pkt.data);
938*4882a593Smuzhiyun target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en);
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n");
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
943*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
944*4882a593Smuzhiyun if (write_state == PG_STATE_HEADER) {
945*4882a593Smuzhiyun badworden = 0x0F;
946*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
947*4882a593Smuzhiyun "efuse PG_STATE_HEADER\n");
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
950*4882a593Smuzhiyun (efuse_data != 0xFF))
951*4882a593Smuzhiyun efuse_write_data_case1(hw, &efuse_addr,
952*4882a593Smuzhiyun efuse_data, offset,
953*4882a593Smuzhiyun &continual,
954*4882a593Smuzhiyun &write_state,
955*4882a593Smuzhiyun &target_pkt,
956*4882a593Smuzhiyun &repeat_times, &result,
957*4882a593Smuzhiyun word_en);
958*4882a593Smuzhiyun else
959*4882a593Smuzhiyun efuse_write_data_case2(hw, &efuse_addr,
960*4882a593Smuzhiyun &continual,
961*4882a593Smuzhiyun &write_state,
962*4882a593Smuzhiyun target_pkt,
963*4882a593Smuzhiyun &repeat_times,
964*4882a593Smuzhiyun &result);
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun } else if (write_state == PG_STATE_DATA) {
967*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
968*4882a593Smuzhiyun "efuse PG_STATE_DATA\n");
969*4882a593Smuzhiyun badworden =
970*4882a593Smuzhiyun enable_efuse_data_write(hw, efuse_addr + 1,
971*4882a593Smuzhiyun target_pkt.word_en,
972*4882a593Smuzhiyun target_pkt.data);
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun if ((badworden & 0x0F) == 0x0F) {
975*4882a593Smuzhiyun continual = false;
976*4882a593Smuzhiyun } else {
977*4882a593Smuzhiyun efuse_addr =
978*4882a593Smuzhiyun efuse_addr + (2 * target_word_cnts) + 1;
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun target_pkt.offset = offset;
981*4882a593Smuzhiyun target_pkt.word_en = badworden;
982*4882a593Smuzhiyun target_word_cnts =
983*4882a593Smuzhiyun efuse_calculate_word_cnts(target_pkt.
984*4882a593Smuzhiyun word_en);
985*4882a593Smuzhiyun write_state = PG_STATE_HEADER;
986*4882a593Smuzhiyun repeat_times++;
987*4882a593Smuzhiyun if (repeat_times > EFUSE_REPEAT_THRESHOLD_) {
988*4882a593Smuzhiyun continual = false;
989*4882a593Smuzhiyun result = false;
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
992*4882a593Smuzhiyun "efuse PG_STATE_HEADER-3\n");
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun if (efuse_addr >= (EFUSE_MAX_SIZE -
998*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
999*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
1000*4882a593Smuzhiyun "efuse_addr(%#x) Out of size!!\n", efuse_addr);
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun return true;
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun
efuse_word_enable_data_read(u8 word_en,u8 * sourdata,u8 * targetdata)1006*4882a593Smuzhiyun static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata,
1007*4882a593Smuzhiyun u8 *targetdata)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun if (!(word_en & BIT(0))) {
1010*4882a593Smuzhiyun targetdata[0] = sourdata[0];
1011*4882a593Smuzhiyun targetdata[1] = sourdata[1];
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun if (!(word_en & BIT(1))) {
1015*4882a593Smuzhiyun targetdata[2] = sourdata[2];
1016*4882a593Smuzhiyun targetdata[3] = sourdata[3];
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun if (!(word_en & BIT(2))) {
1020*4882a593Smuzhiyun targetdata[4] = sourdata[4];
1021*4882a593Smuzhiyun targetdata[5] = sourdata[5];
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun if (!(word_en & BIT(3))) {
1025*4882a593Smuzhiyun targetdata[6] = sourdata[6];
1026*4882a593Smuzhiyun targetdata[7] = sourdata[7];
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun
enable_efuse_data_write(struct ieee80211_hw * hw,u16 efuse_addr,u8 word_en,u8 * data)1030*4882a593Smuzhiyun static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
1031*4882a593Smuzhiyun u16 efuse_addr, u8 word_en, u8 *data)
1032*4882a593Smuzhiyun {
1033*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1034*4882a593Smuzhiyun u16 tmpaddr;
1035*4882a593Smuzhiyun u16 start_addr = efuse_addr;
1036*4882a593Smuzhiyun u8 badworden = 0x0F;
1037*4882a593Smuzhiyun u8 tmpdata[8];
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
1040*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
1041*4882a593Smuzhiyun "word_en = %x efuse_addr=%x\n", word_en, efuse_addr);
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun if (!(word_en & BIT(0))) {
1044*4882a593Smuzhiyun tmpaddr = start_addr;
1045*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[0]);
1046*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[1]);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr, &tmpdata[0]);
1049*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[1]);
1050*4882a593Smuzhiyun if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
1051*4882a593Smuzhiyun badworden &= (~BIT(0));
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun if (!(word_en & BIT(1))) {
1055*4882a593Smuzhiyun tmpaddr = start_addr;
1056*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[2]);
1057*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[3]);
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr, &tmpdata[2]);
1060*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[3]);
1061*4882a593Smuzhiyun if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
1062*4882a593Smuzhiyun badworden &= (~BIT(1));
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun if (!(word_en & BIT(2))) {
1066*4882a593Smuzhiyun tmpaddr = start_addr;
1067*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[4]);
1068*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[5]);
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr, &tmpdata[4]);
1071*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[5]);
1072*4882a593Smuzhiyun if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
1073*4882a593Smuzhiyun badworden &= (~BIT(2));
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun if (!(word_en & BIT(3))) {
1077*4882a593Smuzhiyun tmpaddr = start_addr;
1078*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[6]);
1079*4882a593Smuzhiyun efuse_one_byte_write(hw, start_addr++, data[7]);
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr, &tmpdata[6]);
1082*4882a593Smuzhiyun efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[7]);
1083*4882a593Smuzhiyun if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
1084*4882a593Smuzhiyun badworden &= (~BIT(3));
1085*4882a593Smuzhiyun }
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun return badworden;
1088*4882a593Smuzhiyun }
1089*4882a593Smuzhiyun
efuse_power_switch(struct ieee80211_hw * hw,u8 write,u8 pwrstate)1090*4882a593Smuzhiyun void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
1091*4882a593Smuzhiyun {
1092*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1093*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1094*4882a593Smuzhiyun u8 tempval;
1095*4882a593Smuzhiyun u16 tmpv16;
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) {
1098*4882a593Smuzhiyun if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE &&
1099*4882a593Smuzhiyun rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) {
1100*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
1101*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
1102*4882a593Smuzhiyun } else {
1103*4882a593Smuzhiyun tmpv16 =
1104*4882a593Smuzhiyun rtl_read_word(rtlpriv,
1105*4882a593Smuzhiyun rtlpriv->cfg->maps[SYS_ISO_CTRL]);
1106*4882a593Smuzhiyun if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) {
1107*4882a593Smuzhiyun tmpv16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V];
1108*4882a593Smuzhiyun rtl_write_word(rtlpriv,
1109*4882a593Smuzhiyun rtlpriv->cfg->maps[SYS_ISO_CTRL],
1110*4882a593Smuzhiyun tmpv16);
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun tmpv16 = rtl_read_word(rtlpriv,
1114*4882a593Smuzhiyun rtlpriv->cfg->maps[SYS_FUNC_EN]);
1115*4882a593Smuzhiyun if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) {
1116*4882a593Smuzhiyun tmpv16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR];
1117*4882a593Smuzhiyun rtl_write_word(rtlpriv,
1118*4882a593Smuzhiyun rtlpriv->cfg->maps[SYS_FUNC_EN], tmpv16);
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun tmpv16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]);
1122*4882a593Smuzhiyun if ((!(tmpv16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) ||
1123*4882a593Smuzhiyun (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) {
1124*4882a593Smuzhiyun tmpv16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] |
1125*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_ANA8M]);
1126*4882a593Smuzhiyun rtl_write_word(rtlpriv,
1127*4882a593Smuzhiyun rtlpriv->cfg->maps[SYS_CLK], tmpv16);
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun if (pwrstate) {
1132*4882a593Smuzhiyun if (write) {
1133*4882a593Smuzhiyun tempval = rtl_read_byte(rtlpriv,
1134*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_TEST] +
1135*4882a593Smuzhiyun 3);
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
1138*4882a593Smuzhiyun tempval &= ~(BIT(3) | BIT(4) | BIT(5) | BIT(6));
1139*4882a593Smuzhiyun tempval |= (VOLTAGE_V25 << 3);
1140*4882a593Smuzhiyun } else if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) {
1141*4882a593Smuzhiyun tempval &= 0x0F;
1142*4882a593Smuzhiyun tempval |= (VOLTAGE_V25 << 4);
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
1146*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_TEST] + 3,
1147*4882a593Smuzhiyun (tempval | 0x80));
1148*4882a593Smuzhiyun }
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) {
1151*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK],
1152*4882a593Smuzhiyun 0x03);
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun } else {
1155*4882a593Smuzhiyun if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE &&
1156*4882a593Smuzhiyun rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE)
1157*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
1158*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_ACCESS], 0);
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun if (write) {
1161*4882a593Smuzhiyun tempval = rtl_read_byte(rtlpriv,
1162*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_TEST] +
1163*4882a593Smuzhiyun 3);
1164*4882a593Smuzhiyun rtl_write_byte(rtlpriv,
1165*4882a593Smuzhiyun rtlpriv->cfg->maps[EFUSE_TEST] + 3,
1166*4882a593Smuzhiyun (tempval & 0x7F));
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) {
1170*4882a593Smuzhiyun rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK],
1171*4882a593Smuzhiyun 0x02);
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun }
1174*4882a593Smuzhiyun }
1175*4882a593Smuzhiyun EXPORT_SYMBOL(efuse_power_switch);
1176*4882a593Smuzhiyun
efuse_get_current_size(struct ieee80211_hw * hw)1177*4882a593Smuzhiyun static u16 efuse_get_current_size(struct ieee80211_hw *hw)
1178*4882a593Smuzhiyun {
1179*4882a593Smuzhiyun int continual = true;
1180*4882a593Smuzhiyun u16 efuse_addr = 0;
1181*4882a593Smuzhiyun u8 hworden;
1182*4882a593Smuzhiyun u8 efuse_data, word_cnts;
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
1185*4882a593Smuzhiyun (efuse_addr < EFUSE_MAX_SIZE)) {
1186*4882a593Smuzhiyun if (efuse_data != 0xFF) {
1187*4882a593Smuzhiyun hworden = efuse_data & 0x0F;
1188*4882a593Smuzhiyun word_cnts = efuse_calculate_word_cnts(hworden);
1189*4882a593Smuzhiyun efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1190*4882a593Smuzhiyun } else {
1191*4882a593Smuzhiyun continual = false;
1192*4882a593Smuzhiyun }
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun return efuse_addr;
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
efuse_calculate_word_cnts(u8 word_en)1198*4882a593Smuzhiyun static u8 efuse_calculate_word_cnts(u8 word_en)
1199*4882a593Smuzhiyun {
1200*4882a593Smuzhiyun u8 word_cnts = 0;
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun if (!(word_en & BIT(0)))
1203*4882a593Smuzhiyun word_cnts++;
1204*4882a593Smuzhiyun if (!(word_en & BIT(1)))
1205*4882a593Smuzhiyun word_cnts++;
1206*4882a593Smuzhiyun if (!(word_en & BIT(2)))
1207*4882a593Smuzhiyun word_cnts++;
1208*4882a593Smuzhiyun if (!(word_en & BIT(3)))
1209*4882a593Smuzhiyun word_cnts++;
1210*4882a593Smuzhiyun return word_cnts;
1211*4882a593Smuzhiyun }
1212*4882a593Smuzhiyun
rtl_get_hwinfo(struct ieee80211_hw * hw,struct rtl_priv * rtlpriv,int max_size,u8 * hwinfo,int * params)1213*4882a593Smuzhiyun int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv,
1214*4882a593Smuzhiyun int max_size, u8 *hwinfo, int *params)
1215*4882a593Smuzhiyun {
1216*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1217*4882a593Smuzhiyun struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1218*4882a593Smuzhiyun struct device *dev = &rtlpcipriv->dev.pdev->dev;
1219*4882a593Smuzhiyun u16 eeprom_id;
1220*4882a593Smuzhiyun u16 i, usvalue;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun switch (rtlefuse->epromtype) {
1223*4882a593Smuzhiyun case EEPROM_BOOT_EFUSE:
1224*4882a593Smuzhiyun rtl_efuse_shadow_map_update(hw);
1225*4882a593Smuzhiyun break;
1226*4882a593Smuzhiyun
1227*4882a593Smuzhiyun case EEPROM_93C46:
1228*4882a593Smuzhiyun pr_err("RTL8XXX did not boot from eeprom, check it !!\n");
1229*4882a593Smuzhiyun return 1;
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun default:
1232*4882a593Smuzhiyun dev_warn(dev, "no efuse data\n");
1233*4882a593Smuzhiyun return 1;
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], max_size);
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP",
1239*4882a593Smuzhiyun hwinfo, max_size);
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun eeprom_id = *((u16 *)&hwinfo[0]);
1242*4882a593Smuzhiyun if (eeprom_id != params[0]) {
1243*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
1244*4882a593Smuzhiyun "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
1245*4882a593Smuzhiyun rtlefuse->autoload_failflag = true;
1246*4882a593Smuzhiyun } else {
1247*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
1248*4882a593Smuzhiyun rtlefuse->autoload_failflag = false;
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun
1251*4882a593Smuzhiyun if (rtlefuse->autoload_failflag)
1252*4882a593Smuzhiyun return 1;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun rtlefuse->eeprom_vid = *(u16 *)&hwinfo[params[1]];
1255*4882a593Smuzhiyun rtlefuse->eeprom_did = *(u16 *)&hwinfo[params[2]];
1256*4882a593Smuzhiyun rtlefuse->eeprom_svid = *(u16 *)&hwinfo[params[3]];
1257*4882a593Smuzhiyun rtlefuse->eeprom_smid = *(u16 *)&hwinfo[params[4]];
1258*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1259*4882a593Smuzhiyun "EEPROMId = 0x%4x\n", eeprom_id);
1260*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1261*4882a593Smuzhiyun "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
1262*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1263*4882a593Smuzhiyun "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
1264*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1265*4882a593Smuzhiyun "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
1266*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1267*4882a593Smuzhiyun "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
1268*4882a593Smuzhiyun
1269*4882a593Smuzhiyun for (i = 0; i < 6; i += 2) {
1270*4882a593Smuzhiyun usvalue = *(u16 *)&hwinfo[params[5] + i];
1271*4882a593Smuzhiyun *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue;
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr);
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun rtlefuse->eeprom_channelplan = *&hwinfo[params[6]];
1276*4882a593Smuzhiyun rtlefuse->eeprom_version = *(u16 *)&hwinfo[params[7]];
1277*4882a593Smuzhiyun rtlefuse->txpwr_fromeprom = true;
1278*4882a593Smuzhiyun rtlefuse->eeprom_oemid = *&hwinfo[params[8]];
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
1281*4882a593Smuzhiyun "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
1282*4882a593Smuzhiyun
1283*4882a593Smuzhiyun /* set channel plan to world wide 13 */
1284*4882a593Smuzhiyun rtlefuse->channel_plan = params[9];
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun return 0;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rtl_get_hwinfo);
1289*4882a593Smuzhiyun
rtl_fw_block_write(struct ieee80211_hw * hw,const u8 * buffer,u32 size)1290*4882a593Smuzhiyun void rtl_fw_block_write(struct ieee80211_hw *hw, const u8 *buffer, u32 size)
1291*4882a593Smuzhiyun {
1292*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1293*4882a593Smuzhiyun u8 *pu4byteptr = (u8 *)buffer;
1294*4882a593Smuzhiyun u32 i;
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun for (i = 0; i < size; i++)
1297*4882a593Smuzhiyun rtl_write_byte(rtlpriv, (START_ADDRESS + i), *(pu4byteptr + i));
1298*4882a593Smuzhiyun }
1299*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rtl_fw_block_write);
1300*4882a593Smuzhiyun
rtl_fw_page_write(struct ieee80211_hw * hw,u32 page,const u8 * buffer,u32 size)1301*4882a593Smuzhiyun void rtl_fw_page_write(struct ieee80211_hw *hw, u32 page, const u8 *buffer,
1302*4882a593Smuzhiyun u32 size)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1305*4882a593Smuzhiyun u8 value8;
1306*4882a593Smuzhiyun u8 u8page = (u8)(page & 0x07);
1307*4882a593Smuzhiyun
1308*4882a593Smuzhiyun value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
1311*4882a593Smuzhiyun rtl_fw_block_write(hw, buffer, size);
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rtl_fw_page_write);
1314*4882a593Smuzhiyun
rtl_fill_dummy(u8 * pfwbuf,u32 * pfwlen)1315*4882a593Smuzhiyun void rtl_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
1316*4882a593Smuzhiyun {
1317*4882a593Smuzhiyun u32 fwlen = *pfwlen;
1318*4882a593Smuzhiyun u8 remain = (u8)(fwlen % 4);
1319*4882a593Smuzhiyun
1320*4882a593Smuzhiyun remain = (remain == 0) ? 0 : (4 - remain);
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun while (remain > 0) {
1323*4882a593Smuzhiyun pfwbuf[fwlen] = 0;
1324*4882a593Smuzhiyun fwlen++;
1325*4882a593Smuzhiyun remain--;
1326*4882a593Smuzhiyun }
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun *pfwlen = fwlen;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rtl_fill_dummy);
1331*4882a593Smuzhiyun
rtl_efuse_ops_init(struct ieee80211_hw * hw)1332*4882a593Smuzhiyun void rtl_efuse_ops_init(struct ieee80211_hw *hw)
1333*4882a593Smuzhiyun {
1334*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1335*4882a593Smuzhiyun
1336*4882a593Smuzhiyun rtlpriv->efuse.efuse_ops = &efuse_ops;
1337*4882a593Smuzhiyun }
1338*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(rtl_efuse_ops_init);
1339