1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3 
4 #include "../include/rtw_iol.h"
5 
CheckCondition(const u32 Condition,const u32 Hex)6 static bool CheckCondition(const u32  Condition, const u32  Hex)
7 {
8 	u32 _interface = (Hex & 0x0000FF00) >> 8;
9 	u32 _platform  = (Hex & 0x00FF0000) >> 16;
10 	u32 cond = Condition;
11 
12 	if (Condition == 0xCDCDCDCD)
13 		return true;
14 
15 	cond = Condition & 0x0000FF00;
16 	cond = cond >> 8;
17 	if ((_interface & cond) == 0 && cond != 0x07)
18 		return false;
19 
20 	cond = Condition & 0x00FF0000;
21 	cond = cond >> 16;
22 	if ((_platform & cond) == 0 && cond != 0x0F)
23 		return false;
24 	return true;
25 }
26 
27 /******************************************************************************
28 *                           RadioA_1T.TXT
29 ******************************************************************************/
30 
31 static u32 Array_RadioA_1T_8188E[] = {
32 		0x000, 0x00030000,
33 		0x008, 0x00084000,
34 		0x018, 0x00000407,
35 		0x019, 0x00000012,
36 		0x01E, 0x00080009,
37 		0x01F, 0x00000880,
38 		0x02F, 0x0001A060,
39 		0x03F, 0x00000000,
40 		0x042, 0x000060C0,
41 		0x057, 0x000D0000,
42 		0x058, 0x000BE180,
43 		0x067, 0x00001552,
44 		0x083, 0x00000000,
45 		0x0B0, 0x000FF8FC,
46 		0x0B1, 0x00054400,
47 		0x0B2, 0x000CCC19,
48 		0x0B4, 0x00043003,
49 		0x0B6, 0x0004953E,
50 		0x0B7, 0x0001C718,
51 		0x0B8, 0x000060FF,
52 		0x0B9, 0x00080001,
53 		0x0BA, 0x00040000,
54 		0x0BB, 0x00000400,
55 		0x0BF, 0x000C0000,
56 		0x0C2, 0x00002400,
57 		0x0C3, 0x00000009,
58 		0x0C4, 0x00040C91,
59 		0x0C5, 0x00099999,
60 		0x0C6, 0x000000A3,
61 		0x0C7, 0x00088820,
62 		0x0C8, 0x00076C06,
63 		0x0C9, 0x00000000,
64 		0x0CA, 0x00080000,
65 		0x0DF, 0x00000180,
66 		0x0EF, 0x000001A0,
67 		0x051, 0x0006B27D,
68 		0xFF0F041F, 0xABCD,
69 		0x052, 0x0007E4DD,
70 		0xCDCDCDCD, 0xCDCD,
71 		0x052, 0x0007E49D,
72 		0xFF0F041F, 0xDEAD,
73 		0x053, 0x00000073,
74 		0x056, 0x00051FF3,
75 		0x035, 0x00000086,
76 		0x035, 0x00000186,
77 		0x035, 0x00000286,
78 		0x036, 0x00001C25,
79 		0x036, 0x00009C25,
80 		0x036, 0x00011C25,
81 		0x036, 0x00019C25,
82 		0x0B6, 0x00048538,
83 		0x018, 0x00000C07,
84 		0x05A, 0x0004BD00,
85 		0x019, 0x000739D0,
86 		0x034, 0x0000ADF3,
87 		0x034, 0x00009DF0,
88 		0x034, 0x00008DED,
89 		0x034, 0x00007DEA,
90 		0x034, 0x00006DE7,
91 		0x034, 0x000054EE,
92 		0x034, 0x000044EB,
93 		0x034, 0x000034E8,
94 		0x034, 0x0000246B,
95 		0x034, 0x00001468,
96 		0x034, 0x0000006D,
97 		0x000, 0x00030159,
98 		0x084, 0x00068200,
99 		0x086, 0x000000CE,
100 		0x087, 0x00048A00,
101 		0x08E, 0x00065540,
102 		0x08F, 0x00088000,
103 		0x0EF, 0x000020A0,
104 		0x03B, 0x000F02B0,
105 		0x03B, 0x000EF7B0,
106 		0x03B, 0x000D4FB0,
107 		0x03B, 0x000CF060,
108 		0x03B, 0x000B0090,
109 		0x03B, 0x000A0080,
110 		0x03B, 0x00090080,
111 		0x03B, 0x0008F780,
112 		0x03B, 0x000722B0,
113 		0x03B, 0x0006F7B0,
114 		0x03B, 0x00054FB0,
115 		0x03B, 0x0004F060,
116 		0x03B, 0x00030090,
117 		0x03B, 0x00020080,
118 		0x03B, 0x00010080,
119 		0x03B, 0x0000F780,
120 		0x0EF, 0x000000A0,
121 		0x000, 0x00010159,
122 		0x018, 0x0000F407,
123 		0xFFE, 0x00000000,
124 		0xFFE, 0x00000000,
125 		0x01F, 0x00080003,
126 		0xFFE, 0x00000000,
127 		0xFFE, 0x00000000,
128 		0x01E, 0x00000001,
129 		0x01F, 0x00080000,
130 		0x000, 0x00033E60,
131 };
132 
odm_ConfigRFReg_8188E(struct odm_dm_struct * pDM_Odm,u32 Addr,u32 Data,u32 RegAddr)133 static void odm_ConfigRFReg_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
134 				  u32 Data, u32 RegAddr)
135 {
136 	if (Addr == 0xffe) {
137 		msleep(50);
138 	} else if (Addr == 0xfd) {
139 		mdelay(5);
140 	} else if (Addr == 0xfc) {
141 		mdelay(1);
142 	} else if (Addr == 0xfb) {
143 		udelay(50);
144 	} else if (Addr == 0xfa) {
145 		udelay(5);
146 	} else if (Addr == 0xf9) {
147 		udelay(1);
148 	} else {
149 		rtl8188e_PHY_SetRFReg(pDM_Odm->Adapter, RegAddr, bRFRegOffsetMask, Data);
150 		/*  Add 1us delay between BB/RF register setting. */
151 		udelay(1);
152 	}
153 }
154 
odm_ConfigRF_RadioA_8188E(struct odm_dm_struct * pDM_Odm,u32 Addr,u32 Data)155 static void odm_ConfigRF_RadioA_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data)
156 {
157 	u32  content = 0x1000; /*  RF_Content: radioa_txt */
158 	u32 maskforPhySet = (u32)(content & 0xE000);
159 
160 	odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, Addr | maskforPhySet);
161 }
162 
ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct * pDM_Odm)163 int ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *pDM_Odm)
164 {
165 	#define READ_NEXT_PAIR(v1, v2, i) do	\
166 		 { i += 2; v1 = Array[i];	\
167 		 v2 = Array[i + 1]; } while (0)
168 
169 	u32     hex         = 0;
170 	u32     i           = 0;
171 	u32     ArrayLen    = ARRAY_SIZE(Array_RadioA_1T_8188E);
172 	u32    *Array       = Array_RadioA_1T_8188E;
173 	bool		biol = false;
174 	struct adapter *Adapter =  pDM_Odm->Adapter;
175 	struct xmit_frame *pxmit_frame = NULL;
176 	u8 bndy_cnt = 1;
177 
178 	hex += ODM_ITRF_USB << 8;
179 	hex += ODM_CE << 16;
180 	hex += 0xFF000000;
181 	biol = rtw_IOL_applied(Adapter);
182 
183 	if (biol) {
184 		pxmit_frame = rtw_IOL_accquire_xmit_frame(Adapter);
185 		if (!pxmit_frame) {
186 			pr_info("rtw_IOL_accquire_xmit_frame failed\n");
187 			return -ENOMEM;
188 		}
189 	}
190 
191 	for (i = 0; i < ArrayLen; i += 2) {
192 		u32 v1 = Array[i];
193 		u32 v2 = Array[i + 1];
194 
195 		/*  This (offset, data) pair meets the condition. */
196 		if (v1 < 0xCDCDCDCD) {
197 			if (biol) {
198 				if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
199 					bndy_cnt++;
200 
201 				if (v1 == 0xffe)
202 					rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
203 				else if (v1 == 0xfd)
204 					rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
205 				else if (v1 == 0xfc)
206 					rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
207 				else if (v1 == 0xfb)
208 					rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
209 				else if (v1 == 0xfa)
210 					rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
211 				else if (v1 == 0xf9)
212 					rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
213 				else
214 					rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
215 			} else {
216 				odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
217 			}
218 			continue;
219 		} else { /*  This line is the start line of branch. */
220 			if (!CheckCondition(Array[i], hex)) {
221 				/*  Discard the following (offset, data) pairs. */
222 				READ_NEXT_PAIR(v1, v2, i);
223 				while (v2 != 0xDEAD &&
224 				       v2 != 0xCDEF &&
225 				       v2 != 0xCDCD && i < ArrayLen - 2)
226 					READ_NEXT_PAIR(v1, v2, i);
227 				i -= 2; /*  prevent from for-loop += 2 */
228 			} else { /*  Configure matched pairs and skip to end of if-else. */
229 			READ_NEXT_PAIR(v1, v2, i);
230 				while (v2 != 0xDEAD &&
231 				       v2 != 0xCDEF &&
232 				       v2 != 0xCDCD && i < ArrayLen - 2) {
233 					if (biol) {
234 						if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
235 							bndy_cnt++;
236 
237 						if (v1 == 0xffe)
238 							rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
239 						else if (v1 == 0xfd)
240 							rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
241 						else if (v1 == 0xfc)
242 							rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
243 						else if (v1 == 0xfb)
244 							rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
245 						else if (v1 == 0xfa)
246 							rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
247 						else if (v1 == 0xf9)
248 							rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
249 						else
250 							rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
251 					} else {
252 						odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
253 					}
254 					READ_NEXT_PAIR(v1, v2, i);
255 				}
256 
257 				while (v2 != 0xDEAD && i < ArrayLen - 2)
258 					READ_NEXT_PAIR(v1, v2, i);
259 			}
260 		}
261 	}
262 	if (biol) {
263 		if (!rtl8188e_IOL_exec_cmds_sync(pDM_Odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
264 			pr_info("~~~ IOL Config %s Failed !!!\n", __func__);
265 			return -1;
266 		}
267 	}
268 	return 0;
269 }
270