1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20 
21 #include "odm_precomp.h"
22 
23 #include <phy.h>
24 
check_condition(struct adapter * adapt,const u32 condition)25 static bool check_condition(struct adapter *adapt, const u32  condition)
26 {
27 	struct odm_dm_struct *odm = &GET_HAL_DATA(adapt)->odmpriv;
28 	u32 _board = odm->BoardType;
29 	u32 _platform = odm->SupportPlatform;
30 	u32 _interface = odm->SupportInterface;
31 	u32 cond = condition;
32 
33 	if (condition == 0xCDCDCDCD)
34 		return true;
35 
36 	cond = condition & 0x000000FF;
37 	if ((_board == cond) && cond != 0x00)
38 		return false;
39 
40 	cond = condition & 0x0000FF00;
41 	cond >>= 8;
42 	if ((_interface & cond) == 0 && cond != 0x07)
43 		return false;
44 
45 	cond = condition & 0x00FF0000;
46 	cond >>= 16;
47 	if ((_platform & cond) == 0 && cond != 0x0F)
48 		return false;
49 	return true;
50 }
51 
52 /* RadioA_1T.TXT */
53 
54 static u32 Array_RadioA_1T_8188E[] = {
55 		0x000, 0x00030000,
56 		0x008, 0x00084000,
57 		0x018, 0x00000407,
58 		0x019, 0x00000012,
59 		0x01E, 0x00080009,
60 		0x01F, 0x00000880,
61 		0x02F, 0x0001A060,
62 		0x03F, 0x00000000,
63 		0x042, 0x000060C0,
64 		0x057, 0x000D0000,
65 		0x058, 0x000BE180,
66 		0x067, 0x00001552,
67 		0x083, 0x00000000,
68 		0x0B0, 0x000FF8FC,
69 		0x0B1, 0x00054400,
70 		0x0B2, 0x000CCC19,
71 		0x0B4, 0x00043003,
72 		0x0B6, 0x0004953E,
73 		0x0B7, 0x0001C718,
74 		0x0B8, 0x000060FF,
75 		0x0B9, 0x00080001,
76 		0x0BA, 0x00040000,
77 		0x0BB, 0x00000400,
78 		0x0BF, 0x000C0000,
79 		0x0C2, 0x00002400,
80 		0x0C3, 0x00000009,
81 		0x0C4, 0x00040C91,
82 		0x0C5, 0x00099999,
83 		0x0C6, 0x000000A3,
84 		0x0C7, 0x00088820,
85 		0x0C8, 0x00076C06,
86 		0x0C9, 0x00000000,
87 		0x0CA, 0x00080000,
88 		0x0DF, 0x00000180,
89 		0x0EF, 0x000001A0,
90 		0x051, 0x0006B27D,
91 		0xFF0F041F, 0xABCD,
92 		0x052, 0x0007E4DD,
93 		0xCDCDCDCD, 0xCDCD,
94 		0x052, 0x0007E49D,
95 		0xFF0F041F, 0xDEAD,
96 		0x053, 0x00000073,
97 		0x056, 0x00051FF3,
98 		0x035, 0x00000086,
99 		0x035, 0x00000186,
100 		0x035, 0x00000286,
101 		0x036, 0x00001C25,
102 		0x036, 0x00009C25,
103 		0x036, 0x00011C25,
104 		0x036, 0x00019C25,
105 		0x0B6, 0x00048538,
106 		0x018, 0x00000C07,
107 		0x05A, 0x0004BD00,
108 		0x019, 0x000739D0,
109 		0x034, 0x0000ADF3,
110 		0x034, 0x00009DF0,
111 		0x034, 0x00008DED,
112 		0x034, 0x00007DEA,
113 		0x034, 0x00006DE7,
114 		0x034, 0x000054EE,
115 		0x034, 0x000044EB,
116 		0x034, 0x000034E8,
117 		0x034, 0x0000246B,
118 		0x034, 0x00001468,
119 		0x034, 0x0000006D,
120 		0x000, 0x00030159,
121 		0x084, 0x00068200,
122 		0x086, 0x000000CE,
123 		0x087, 0x00048A00,
124 		0x08E, 0x00065540,
125 		0x08F, 0x00088000,
126 		0x0EF, 0x000020A0,
127 		0x03B, 0x000F02B0,
128 		0x03B, 0x000EF7B0,
129 		0x03B, 0x000D4FB0,
130 		0x03B, 0x000CF060,
131 		0x03B, 0x000B0090,
132 		0x03B, 0x000A0080,
133 		0x03B, 0x00090080,
134 		0x03B, 0x0008F780,
135 		0x03B, 0x000722B0,
136 		0x03B, 0x0006F7B0,
137 		0x03B, 0x00054FB0,
138 		0x03B, 0x0004F060,
139 		0x03B, 0x00030090,
140 		0x03B, 0x00020080,
141 		0x03B, 0x00010080,
142 		0x03B, 0x0000F780,
143 		0x0EF, 0x000000A0,
144 		0x000, 0x00010159,
145 		0x018, 0x0000F407,
146 		0xFFE, 0x00000000,
147 		0xFFE, 0x00000000,
148 		0x01F, 0x00080003,
149 		0xFFE, 0x00000000,
150 		0xFFE, 0x00000000,
151 		0x01E, 0x00000001,
152 		0x01F, 0x00080000,
153 		0x000, 0x00033E60,
154 };
155 
156 #define READ_NEXT_PAIR(v1, v2, i)	\
157 do {								\
158 	i += 2; v1 = array[i];			\
159 	v2 = array[i+1];				\
160 } while (0)
161 
162 #define RFREG_OFFSET_MASK 0xfffff
163 #define B3WIREADDREAALENGTH 0x400
164 #define B3WIREDATALENGTH 0x800
165 #define BRFSI_RFENV 0x10
166 
rtl_rfreg_delay(struct adapter * adapt,enum rf_radio_path rfpath,u32 addr,u32 mask,u32 data)167 static void rtl_rfreg_delay(struct adapter *adapt, enum rf_radio_path rfpath, u32 addr, u32 mask, u32 data)
168 {
169 	if (addr == 0xfe) {
170 		mdelay(50);
171 	} else if (addr == 0xfd) {
172 		mdelay(5);
173 	} else if (addr == 0xfc) {
174 		mdelay(1);
175 	} else if (addr == 0xfb) {
176 		udelay(50);
177 	} else if (addr == 0xfa) {
178 		udelay(5);
179 	} else if (addr == 0xf9) {
180 		udelay(1);
181 	} else {
182 		phy_set_rf_reg(adapt, rfpath, addr, mask, data);
183 		udelay(1);
184 	}
185 }
186 
rtl8188e_config_rf_reg(struct adapter * adapt,u32 addr,u32 data)187 static void rtl8188e_config_rf_reg(struct adapter *adapt,
188 	u32 addr, u32 data)
189 {
190 	u32 content = 0x1000; /*RF Content: radio_a_txt*/
191 	u32 maskforphyset = content & 0xE000;
192 
193 	rtl_rfreg_delay(adapt, RF90_PATH_A, addr | maskforphyset,
194 			RFREG_OFFSET_MASK,
195 			data);
196 }
197 
rtl88e_phy_config_rf_with_headerfile(struct adapter * adapt)198 static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt)
199 {
200 	u32 i;
201 	u32 array_len = ARRAY_SIZE(Array_RadioA_1T_8188E);
202 	u32 *array = Array_RadioA_1T_8188E;
203 
204 	for (i = 0; i < array_len; i += 2) {
205 		u32 v1 = array[i];
206 		u32 v2 = array[i+1];
207 
208 		if (v1 < 0xCDCDCDCD) {
209 			rtl8188e_config_rf_reg(adapt, v1, v2);
210 			continue;
211 		} else {
212 			if (!check_condition(adapt, array[i])) {
213 				READ_NEXT_PAIR(v1, v2, i);
214 				while (v2 != 0xDEAD && v2 != 0xCDEF &&
215 				       v2 != 0xCDCD && i < array_len - 2)
216 					READ_NEXT_PAIR(v1, v2, i);
217 				i -= 2;
218 			} else {
219 				READ_NEXT_PAIR(v1, v2, i);
220 				while (v2 != 0xDEAD && v2 != 0xCDEF &&
221 				       v2 != 0xCDCD && i < array_len - 2) {
222 						rtl8188e_config_rf_reg(adapt, v1, v2);
223 						READ_NEXT_PAIR(v1, v2, i);
224 				}
225 
226 				while (v2 != 0xDEAD && i < array_len - 2)
227 					READ_NEXT_PAIR(v1, v2, i);
228 			}
229 		}
230 	}
231 	return true;
232 }
233 
rf6052_conf_para(struct adapter * adapt)234 static bool rf6052_conf_para(struct adapter *adapt)
235 {
236 	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
237 	u32 u4val = 0;
238 	u8 rfpath;
239 	bool rtstatus = true;
240 	struct bb_reg_def *pphyreg;
241 
242 	for (rfpath = 0; rfpath < hal_data->NumTotalRFPath; rfpath++) {
243 		pphyreg = &hal_data->PHYRegDef[rfpath];
244 
245 		switch (rfpath) {
246 		case RF90_PATH_A:
247 		case RF90_PATH_C:
248 			u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs,
249 						 BRFSI_RFENV);
250 			break;
251 		case RF90_PATH_B:
252 		case RF90_PATH_D:
253 			u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs,
254 						 BRFSI_RFENV << 16);
255 			break;
256 		}
257 
258 		phy_set_bb_reg(adapt, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
259 		udelay(1);
260 
261 		phy_set_bb_reg(adapt, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
262 		udelay(1);
263 
264 		phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2,
265 			      B3WIREADDREAALENGTH, 0x0);
266 		udelay(1);
267 
268 		phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2,
269 			       B3WIREDATALENGTH, 0x0);
270 		udelay(1);
271 
272 		switch (rfpath) {
273 		case RF90_PATH_A:
274 			rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt);
275 			break;
276 		case RF90_PATH_B:
277 			rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt);
278 			break;
279 		case RF90_PATH_C:
280 			break;
281 		case RF90_PATH_D:
282 			break;
283 		}
284 
285 		switch (rfpath) {
286 		case RF90_PATH_A:
287 		case RF90_PATH_C:
288 			phy_set_bb_reg(adapt, pphyreg->rfintfs,
289 				       BRFSI_RFENV, u4val);
290 			break;
291 		case RF90_PATH_B:
292 		case RF90_PATH_D:
293 			phy_set_bb_reg(adapt, pphyreg->rfintfs,
294 				       BRFSI_RFENV << 16, u4val);
295 			break;
296 		}
297 
298 		if (!rtstatus)
299 			return false;
300 	}
301 
302 	return rtstatus;
303 }
304 
rtl88e_phy_rf6052_config(struct adapter * adapt)305 static bool rtl88e_phy_rf6052_config(struct adapter *adapt)
306 {
307 	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
308 
309 	if (hal_data->rf_type == RF_1T1R)
310 		hal_data->NumTotalRFPath = 1;
311 	else
312 		hal_data->NumTotalRFPath = 2;
313 
314 	return rf6052_conf_para(adapt);
315 }
316 
rtl88eu_phy_rf_config(struct adapter * adapt)317 bool rtl88eu_phy_rf_config(struct adapter *adapt)
318 {
319 	return rtl88e_phy_rf6052_config(adapt);
320 }
321