Commit | Line | Data |
---|---|---|
f219eff1 CL |
1 | /****************************************************************************** |
2 | * | |
6a57b08e | 3 | * Copyright(c) 2009-2012 Realtek Corporation. |
f219eff1 CL |
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 | * The full GNU General Public License is included in this distribution in the | |
19 | * file called LICENSE. | |
20 | * | |
21 | * Contact Information: | |
22 | * wlanfae <wlanfae@realtek.com> | |
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | |
24 | * Hsinchu 300, Taiwan. | |
25 | * | |
26 | * Larry Finger <Larry.Finger@lwfinger.net> | |
27 | * | |
28 | *****************************************************************************/ | |
29 | ||
30 | #include "../wifi.h" | |
31 | #include "reg.h" | |
32 | #include "def.h" | |
33 | #include "phy.h" | |
34 | #include "rf.h" | |
35 | #include "dm.h" | |
36 | #include "hw.h" | |
37 | ||
38 | void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) | |
39 | { | |
40 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
41 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
42 | u8 rfpath; | |
43 | ||
44 | switch (bandwidth) { | |
45 | case HT_CHANNEL_WIDTH_20: | |
46 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | |
47 | rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval | |
48 | [rfpath] & 0xfffff3ff) | 0x0400); | |
49 | rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | | |
50 | BIT(11), 0x01); | |
51 | ||
52 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, | |
f30d7507 JP |
53 | "20M RF 0x18 = 0x%x\n", |
54 | rtlphy->rfreg_chnlval[rfpath]); | |
f219eff1 CL |
55 | } |
56 | ||
57 | break; | |
58 | case HT_CHANNEL_WIDTH_20_40: | |
59 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | |
60 | rtlphy->rfreg_chnlval[rfpath] = | |
61 | ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff)); | |
62 | rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11), | |
63 | 0x00); | |
64 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, | |
f30d7507 JP |
65 | "40M RF 0x18 = 0x%x\n", |
66 | rtlphy->rfreg_chnlval[rfpath]); | |
f219eff1 CL |
67 | } |
68 | break; | |
69 | default: | |
70 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
f30d7507 | 71 | "unknown bandwidth: %#X\n", bandwidth); |
f219eff1 CL |
72 | break; |
73 | } | |
74 | } | |
75 | ||
76 | void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |
77 | u8 *ppowerlevel) | |
78 | { | |
79 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
80 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
81 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | |
82 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | |
83 | u32 tx_agc[2] = {0, 0}, tmpval; | |
84 | bool turbo_scanoff = false; | |
85 | u8 idx1, idx2; | |
86 | u8 *ptr; | |
87 | ||
88 | if (rtlefuse->eeprom_regulatory != 0) | |
89 | turbo_scanoff = true; | |
9928c7d1 | 90 | if (mac->act_scanning) { |
f219eff1 CL |
91 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; |
92 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; | |
93 | if (turbo_scanoff) { | |
94 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | |
95 | tx_agc[idx1] = ppowerlevel[idx1] | | |
96 | (ppowerlevel[idx1] << 8) | | |
97 | (ppowerlevel[idx1] << 16) | | |
98 | (ppowerlevel[idx1] << 24); | |
99 | } | |
100 | } | |
101 | } else { | |
102 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | |
103 | tx_agc[idx1] = ppowerlevel[idx1] | | |
104 | (ppowerlevel[idx1] << 8) | | |
105 | (ppowerlevel[idx1] << 16) | | |
106 | (ppowerlevel[idx1] << 24); | |
107 | } | |
108 | if (rtlefuse->eeprom_regulatory == 0) { | |
da17fcff LF |
109 | tmpval = (rtlphy->mcs_offset[0][6]) + |
110 | (rtlphy->mcs_offset[0][7] << 8); | |
f219eff1 | 111 | tx_agc[RF90_PATH_A] += tmpval; |
da17fcff LF |
112 | tmpval = (rtlphy->mcs_offset[0][14]) + |
113 | (rtlphy->mcs_offset[0][15] << 24); | |
f219eff1 CL |
114 | tx_agc[RF90_PATH_B] += tmpval; |
115 | } | |
116 | } | |
117 | ||
118 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | |
119 | ptr = (u8 *) (&(tx_agc[idx1])); | |
120 | for (idx2 = 0; idx2 < 4; idx2++) { | |
121 | if (*ptr > RF6052_MAX_TX_PWR) | |
122 | *ptr = RF6052_MAX_TX_PWR; | |
123 | ptr++; | |
124 | } | |
125 | } | |
126 | ||
127 | tmpval = tx_agc[RF90_PATH_A] & 0xff; | |
25b13dbc | 128 | rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); |
f219eff1 | 129 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
4c48869f JP |
130 | "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", |
131 | tmpval, RTXAGC_A_CCK1_MCS32); | |
f219eff1 CL |
132 | tmpval = tx_agc[RF90_PATH_A] >> 8; |
133 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); | |
134 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
135 | "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", |
136 | tmpval, RTXAGC_B_CCK11_A_CCK2_11); | |
f219eff1 | 137 | tmpval = tx_agc[RF90_PATH_B] >> 24; |
25b13dbc | 138 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); |
f219eff1 | 139 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
4c48869f JP |
140 | "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", |
141 | tmpval, RTXAGC_B_CCK11_A_CCK2_11); | |
f219eff1 CL |
142 | tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; |
143 | rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); | |
144 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
145 | "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", |
146 | tmpval, RTXAGC_B_CCK1_55_MCS32); | |
f219eff1 CL |
147 | } |
148 | ||
149 | static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw, | |
150 | u8 *ppowerlevel, u8 channel, | |
151 | u32 *ofdmbase, u32 *mcsbase) | |
152 | { | |
153 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
154 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
155 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | |
156 | u32 powerbase0, powerbase1; | |
157 | u8 legacy_pwrdiff, ht20_pwrdiff; | |
158 | u8 i, powerlevel[2]; | |
159 | ||
160 | for (i = 0; i < 2; i++) { | |
161 | powerlevel[i] = ppowerlevel[i]; | |
162 | legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; | |
163 | powerbase0 = powerlevel[i] + legacy_pwrdiff; | |
164 | powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | | |
165 | (powerbase0 << 8) | powerbase0; | |
166 | *(ofdmbase + i) = powerbase0; | |
167 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
168 | " [OFDM power base index rf(%c) = 0x%x]\n", |
169 | i == 0 ? 'A' : 'B', *(ofdmbase + i)); | |
f219eff1 CL |
170 | } |
171 | ||
172 | for (i = 0; i < 2; i++) { | |
173 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { | |
174 | ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; | |
175 | powerlevel[i] += ht20_pwrdiff; | |
176 | } | |
177 | powerbase1 = powerlevel[i]; | |
178 | powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | | |
179 | (powerbase1 << 8) | powerbase1; | |
180 | *(mcsbase + i) = powerbase1; | |
181 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
182 | " [MCS power base index rf(%c) = 0x%x]\n", |
183 | i == 0 ? 'A' : 'B', *(mcsbase + i)); | |
f219eff1 CL |
184 | } |
185 | } | |
186 | ||
187 | static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex) | |
188 | { | |
189 | u8 group; | |
190 | u8 channel_info[59] = { | |
191 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
192 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, | |
193 | 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, | |
194 | 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, | |
195 | 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, | |
196 | 161, 163, 165 | |
197 | }; | |
198 | ||
199 | if (channel_info[chnlindex] <= 3) /* Chanel 1-3 */ | |
200 | group = 0; | |
201 | else if (channel_info[chnlindex] <= 9) /* Channel 4-9 */ | |
202 | group = 1; | |
203 | else if (channel_info[chnlindex] <= 14) /* Channel 10-14 */ | |
204 | group = 2; | |
205 | else if (channel_info[chnlindex] <= 64) | |
206 | group = 6; | |
207 | else if (channel_info[chnlindex] <= 140) | |
208 | group = 7; | |
209 | else | |
210 | group = 8; | |
211 | return group; | |
212 | } | |
213 | ||
214 | static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, | |
215 | u8 channel, u8 index, | |
216 | u32 *powerbase0, | |
217 | u32 *powerbase1, | |
218 | u32 *p_outwriteval) | |
219 | { | |
220 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
221 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
222 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | |
223 | u8 i, chnlgroup = 0, pwr_diff_limit[4]; | |
224 | u32 writeval = 0, customer_limit, rf; | |
225 | ||
226 | for (rf = 0; rf < 2; rf++) { | |
227 | switch (rtlefuse->eeprom_regulatory) { | |
228 | case 0: | |
229 | chnlgroup = 0; | |
da17fcff | 230 | writeval = rtlphy->mcs_offset |
f219eff1 CL |
231 | [chnlgroup][index + |
232 | (rf ? 8 : 0)] + ((index < 2) ? | |
233 | powerbase0[rf] : | |
234 | powerbase1[rf]); | |
4c48869f JP |
235 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
236 | "RTK better performance, writeval(%c) = 0x%x\n", | |
237 | rf == 0 ? 'A' : 'B', writeval); | |
f219eff1 CL |
238 | break; |
239 | case 1: | |
240 | if (rtlphy->pwrgroup_cnt == 1) | |
241 | chnlgroup = 0; | |
242 | if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) { | |
243 | chnlgroup = _rtl92d_phy_get_chnlgroup_bypg( | |
244 | channel - 1); | |
245 | if (rtlphy->current_chan_bw == | |
246 | HT_CHANNEL_WIDTH_20) | |
247 | chnlgroup++; | |
248 | else | |
249 | chnlgroup += 4; | |
da17fcff | 250 | writeval = rtlphy->mcs_offset |
f219eff1 CL |
251 | [chnlgroup][index + |
252 | (rf ? 8 : 0)] + ((index < 2) ? | |
253 | powerbase0[rf] : | |
254 | powerbase1[rf]); | |
255 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
256 | "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", |
257 | rf == 0 ? 'A' : 'B', writeval); | |
f219eff1 CL |
258 | } |
259 | break; | |
260 | case 2: | |
261 | writeval = ((index < 2) ? powerbase0[rf] : | |
262 | powerbase1[rf]); | |
4c48869f JP |
263 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
264 | "Better regulatory, writeval(%c) = 0x%x\n", | |
265 | rf == 0 ? 'A' : 'B', writeval); | |
f219eff1 CL |
266 | break; |
267 | case 3: | |
268 | chnlgroup = 0; | |
269 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | |
270 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
271 | "customer's limit, 40MHz rf(%c) = 0x%x\n", |
272 | rf == 0 ? 'A' : 'B', | |
f219eff1 | 273 | rtlefuse->pwrgroup_ht40[rf] |
4c48869f | 274 | [channel - 1]); |
f219eff1 CL |
275 | } else { |
276 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
277 | "customer's limit, 20MHz rf(%c) = 0x%x\n", |
278 | rf == 0 ? 'A' : 'B', | |
f219eff1 | 279 | rtlefuse->pwrgroup_ht20[rf] |
4c48869f | 280 | [channel - 1]); |
f219eff1 CL |
281 | } |
282 | for (i = 0; i < 4; i++) { | |
da17fcff | 283 | pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset |
f219eff1 CL |
284 | [chnlgroup][index + (rf ? 8 : 0)] & |
285 | (0x7f << (i * 8))) >> (i * 8)); | |
286 | if (rtlphy->current_chan_bw == | |
287 | HT_CHANNEL_WIDTH_20_40) { | |
288 | if (pwr_diff_limit[i] > | |
289 | rtlefuse->pwrgroup_ht40[rf] | |
290 | [channel - 1]) | |
291 | pwr_diff_limit[i] = | |
292 | rtlefuse->pwrgroup_ht40 | |
293 | [rf][channel - 1]; | |
294 | } else { | |
295 | if (pwr_diff_limit[i] > | |
296 | rtlefuse->pwrgroup_ht20[rf][ | |
297 | channel - 1]) | |
298 | pwr_diff_limit[i] = | |
299 | rtlefuse->pwrgroup_ht20[rf] | |
300 | [channel - 1]; | |
301 | } | |
302 | } | |
303 | customer_limit = (pwr_diff_limit[3] << 24) | | |
304 | (pwr_diff_limit[2] << 16) | | |
305 | (pwr_diff_limit[1] << 8) | | |
306 | (pwr_diff_limit[0]); | |
307 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
308 | "Customer's limit rf(%c) = 0x%x\n", |
309 | rf == 0 ? 'A' : 'B', customer_limit); | |
f219eff1 CL |
310 | writeval = customer_limit + ((index < 2) ? |
311 | powerbase0[rf] : powerbase1[rf]); | |
312 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
313 | "Customer, writeval rf(%c)= 0x%x\n", |
314 | rf == 0 ? 'A' : 'B', writeval); | |
f219eff1 CL |
315 | break; |
316 | default: | |
317 | chnlgroup = 0; | |
da17fcff | 318 | writeval = rtlphy->mcs_offset[chnlgroup][index + |
f219eff1 CL |
319 | (rf ? 8 : 0)] + ((index < 2) ? |
320 | powerbase0[rf] : powerbase1[rf]); | |
321 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | |
4c48869f JP |
322 | "RTK better performance, writeval rf(%c) = 0x%x\n", |
323 | rf == 0 ? 'A' : 'B', writeval); | |
f219eff1 CL |
324 | break; |
325 | } | |
326 | *(p_outwriteval + rf) = writeval; | |
327 | } | |
328 | } | |
329 | ||
330 | static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw, | |
331 | u8 index, u32 *pvalue) | |
332 | { | |
333 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
334 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
335 | static u16 regoffset_a[6] = { | |
336 | RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, | |
337 | RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, | |
338 | RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 | |
339 | }; | |
340 | static u16 regoffset_b[6] = { | |
341 | RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, | |
342 | RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, | |
343 | RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 | |
344 | }; | |
345 | u8 i, rf, pwr_val[4]; | |
346 | u32 writeval; | |
347 | u16 regoffset; | |
348 | ||
349 | for (rf = 0; rf < 2; rf++) { | |
350 | writeval = pvalue[rf]; | |
351 | for (i = 0; i < 4; i++) { | |
352 | pwr_val[i] = (u8) ((writeval & (0x7f << | |
353 | (i * 8))) >> (i * 8)); | |
354 | if (pwr_val[i] > RF6052_MAX_TX_PWR) | |
355 | pwr_val[i] = RF6052_MAX_TX_PWR; | |
356 | } | |
357 | writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | | |
358 | (pwr_val[1] << 8) | pwr_val[0]; | |
359 | if (rf == 0) | |
360 | regoffset = regoffset_a[index]; | |
361 | else | |
362 | regoffset = regoffset_b[index]; | |
25b13dbc | 363 | rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); |
f219eff1 | 364 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
4c48869f | 365 | "Set 0x%x = %08x\n", regoffset, writeval); |
f219eff1 CL |
366 | if (((get_rf_type(rtlphy) == RF_2T2R) && |
367 | (regoffset == RTXAGC_A_MCS15_MCS12 || | |
368 | regoffset == RTXAGC_B_MCS15_MCS12)) || | |
369 | ((get_rf_type(rtlphy) != RF_2T2R) && | |
370 | (regoffset == RTXAGC_A_MCS07_MCS04 || | |
371 | regoffset == RTXAGC_B_MCS07_MCS04))) { | |
372 | writeval = pwr_val[3]; | |
373 | if (regoffset == RTXAGC_A_MCS15_MCS12 || | |
374 | regoffset == RTXAGC_A_MCS07_MCS04) | |
375 | regoffset = 0xc90; | |
376 | if (regoffset == RTXAGC_B_MCS15_MCS12 || | |
377 | regoffset == RTXAGC_B_MCS07_MCS04) | |
378 | regoffset = 0xc98; | |
379 | for (i = 0; i < 3; i++) { | |
380 | if (i != 2) | |
381 | writeval = (writeval > 8) ? | |
382 | (writeval - 8) : 0; | |
383 | else | |
384 | writeval = (writeval > 6) ? | |
385 | (writeval - 6) : 0; | |
386 | rtl_write_byte(rtlpriv, (u32) (regoffset + i), | |
387 | (u8) writeval); | |
388 | } | |
389 | } | |
390 | } | |
391 | } | |
392 | ||
393 | void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | |
394 | u8 *ppowerlevel, u8 channel) | |
395 | { | |
396 | u32 writeval[2], powerbase0[2], powerbase1[2]; | |
397 | u8 index; | |
398 | ||
399 | _rtl92d_phy_get_power_base(hw, ppowerlevel, channel, | |
400 | &powerbase0[0], &powerbase1[0]); | |
401 | for (index = 0; index < 6; index++) { | |
402 | _rtl92d_get_txpower_writeval_by_regulatory(hw, | |
403 | channel, index, &powerbase0[0], | |
404 | &powerbase1[0], &writeval[0]); | |
405 | _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]); | |
406 | } | |
407 | } | |
408 | ||
409 | bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0) | |
410 | { | |
411 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
412 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | |
413 | u8 u1btmp; | |
9928c7d1 LF |
414 | u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); |
415 | u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; | |
416 | u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; | |
f219eff1 CL |
417 | bool bresult = true; /* true: need to enable BB/RF power */ |
418 | ||
419 | rtlhal->during_mac0init_radiob = false; | |
420 | rtlhal->during_mac1init_radioa = false; | |
f30d7507 | 421 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "===>\n"); |
f219eff1 CL |
422 | /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */ |
423 | u1btmp = rtl_read_byte(rtlpriv, mac_reg); | |
424 | if (!(u1btmp & mac_on_bit)) { | |
f30d7507 | 425 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable BB & RF\n"); |
f219eff1 CL |
426 | /* Enable BB and RF power */ |
427 | rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL, | |
428 | rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) | | |
429 | BIT(29) | BIT(16) | BIT(17), direct); | |
430 | } else { | |
431 | /* We think if MAC1 is ON,then radio_a.txt | |
432 | * and radio_b.txt has been load. */ | |
433 | bresult = false; | |
434 | } | |
f30d7507 | 435 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<===\n"); |
f219eff1 CL |
436 | return bresult; |
437 | ||
438 | } | |
439 | ||
440 | void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0) | |
441 | { | |
442 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
443 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | |
444 | u8 u1btmp; | |
9928c7d1 LF |
445 | u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); |
446 | u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; | |
447 | u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; | |
f219eff1 CL |
448 | |
449 | rtlhal->during_mac0init_radiob = false; | |
450 | rtlhal->during_mac1init_radioa = false; | |
f30d7507 | 451 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "====>\n"); |
f219eff1 CL |
452 | /* check MAC0 enable or not again now, if |
453 | * enabled, not power down radio A. */ | |
454 | u1btmp = rtl_read_byte(rtlpriv, mac_reg); | |
455 | if (!(u1btmp & mac_on_bit)) { | |
f30d7507 | 456 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "power down\n"); |
f219eff1 CL |
457 | /* power down RF radio A according to YuNan's advice. */ |
458 | rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER, | |
459 | 0x00000000, direct); | |
460 | } | |
f30d7507 | 461 | RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<====\n"); |
f219eff1 CL |
462 | } |
463 | ||
464 | bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw) | |
465 | { | |
466 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
467 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
468 | bool rtstatus = true; | |
469 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | |
470 | u32 u4_regvalue = 0; | |
471 | u8 rfpath; | |
472 | struct bb_reg_def *pphyreg; | |
473 | bool mac1_initradioa_first = false, mac0_initradiob_first = false; | |
474 | bool need_pwrdown_radioa = false, need_pwrdown_radiob = false; | |
475 | bool true_bpath = false; | |
476 | ||
477 | if (rtlphy->rf_type == RF_1T1R) | |
478 | rtlphy->num_total_rfpath = 1; | |
479 | else | |
480 | rtlphy->num_total_rfpath = 2; | |
481 | ||
482 | /* Single phy mode: use radio_a radio_b config path_A path_B */ | |
483 | /* seperately by MAC0, and MAC1 needn't configure RF; */ | |
484 | /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */ | |
485 | /* MAC1 use radio_b config 2nd PHY path_A. */ | |
486 | /* DMDP,MAC0 on G band,MAC1 on A band. */ | |
487 | if (rtlhal->macphymode == DUALMAC_DUALPHY) { | |
488 | if (rtlhal->current_bandtype == BAND_ON_2_4G && | |
489 | rtlhal->interfaceindex == 0) { | |
490 | /* MAC0 needs PHY1 load radio_b.txt. | |
491 | * Driver use DBI to write. */ | |
492 | if (rtl92d_phy_enable_anotherphy(hw, true)) { | |
493 | rtlphy->num_total_rfpath = 2; | |
494 | mac0_initradiob_first = true; | |
495 | } else { | |
496 | /* We think if MAC1 is ON,then radio_a.txt and | |
497 | * radio_b.txt has been load. */ | |
498 | return rtstatus; | |
499 | } | |
500 | } else if (rtlhal->current_bandtype == BAND_ON_5G && | |
501 | rtlhal->interfaceindex == 1) { | |
502 | /* MAC1 needs PHY0 load radio_a.txt. | |
503 | * Driver use DBI to write. */ | |
504 | if (rtl92d_phy_enable_anotherphy(hw, false)) { | |
505 | rtlphy->num_total_rfpath = 2; | |
506 | mac1_initradioa_first = true; | |
507 | } else { | |
508 | /* We think if MAC0 is ON,then radio_a.txt and | |
509 | * radio_b.txt has been load. */ | |
510 | return rtstatus; | |
511 | } | |
512 | } else if (rtlhal->interfaceindex == 1) { | |
513 | /* MAC0 enabled, only init radia B. */ | |
514 | true_bpath = true; | |
515 | } | |
516 | } | |
517 | ||
518 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | |
519 | /* Mac1 use PHY0 write */ | |
520 | if (mac1_initradioa_first) { | |
521 | if (rfpath == RF90_PATH_A) { | |
522 | rtlhal->during_mac1init_radioa = true; | |
523 | need_pwrdown_radioa = true; | |
524 | } else if (rfpath == RF90_PATH_B) { | |
525 | rtlhal->during_mac1init_radioa = false; | |
526 | mac1_initradioa_first = false; | |
527 | rfpath = RF90_PATH_A; | |
528 | true_bpath = true; | |
529 | rtlphy->num_total_rfpath = 1; | |
530 | } | |
531 | } else if (mac0_initradiob_first) { | |
532 | /* Mac0 use PHY1 write */ | |
533 | if (rfpath == RF90_PATH_A) | |
534 | rtlhal->during_mac0init_radiob = false; | |
535 | if (rfpath == RF90_PATH_B) { | |
536 | rtlhal->during_mac0init_radiob = true; | |
537 | mac0_initradiob_first = false; | |
538 | need_pwrdown_radiob = true; | |
539 | rfpath = RF90_PATH_A; | |
540 | true_bpath = true; | |
541 | rtlphy->num_total_rfpath = 1; | |
542 | } | |
543 | } | |
544 | pphyreg = &rtlphy->phyreg_def[rfpath]; | |
545 | switch (rfpath) { | |
546 | case RF90_PATH_A: | |
547 | case RF90_PATH_C: | |
548 | u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, | |
549 | BRFSI_RFENV); | |
550 | break; | |
551 | case RF90_PATH_B: | |
552 | case RF90_PATH_D: | |
553 | u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, | |
554 | BRFSI_RFENV << 16); | |
555 | break; | |
556 | } | |
557 | rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); | |
558 | udelay(1); | |
559 | rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); | |
560 | udelay(1); | |
561 | /* Set bit number of Address and Data for RF register */ | |
562 | /* Set 1 to 4 bits for 8255 */ | |
563 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, | |
564 | B3WIREADDRESSLENGTH, 0x0); | |
565 | udelay(1); | |
566 | /* Set 0 to 12 bits for 8255 */ | |
567 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); | |
568 | udelay(1); | |
569 | switch (rfpath) { | |
570 | case RF90_PATH_A: | |
9928c7d1 | 571 | if (true_bpath) |
f219eff1 CL |
572 | rtstatus = rtl92d_phy_config_rf_with_headerfile( |
573 | hw, radiob_txt, | |
574 | (enum radio_path)rfpath); | |
575 | else | |
576 | rtstatus = rtl92d_phy_config_rf_with_headerfile( | |
577 | hw, radioa_txt, | |
578 | (enum radio_path)rfpath); | |
579 | break; | |
580 | case RF90_PATH_B: | |
581 | rtstatus = | |
582 | rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt, | |
583 | (enum radio_path) rfpath); | |
584 | break; | |
585 | case RF90_PATH_C: | |
586 | break; | |
587 | case RF90_PATH_D: | |
588 | break; | |
589 | } | |
590 | switch (rfpath) { | |
591 | case RF90_PATH_A: | |
592 | case RF90_PATH_C: | |
593 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, | |
594 | u4_regvalue); | |
595 | break; | |
596 | case RF90_PATH_B: | |
597 | case RF90_PATH_D: | |
598 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, | |
599 | u4_regvalue); | |
600 | break; | |
601 | } | |
23677ce3 | 602 | if (!rtstatus) { |
f219eff1 | 603 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
f30d7507 | 604 | "Radio[%d] Fail!!", rfpath); |
f219eff1 CL |
605 | goto phy_rf_cfg_fail; |
606 | } | |
607 | ||
608 | } | |
609 | ||
610 | /* check MAC0 enable or not again, if enabled, | |
611 | * not power down radio A. */ | |
612 | /* check MAC1 enable or not again, if enabled, | |
613 | * not power down radio B. */ | |
614 | if (need_pwrdown_radioa) | |
615 | rtl92d_phy_powerdown_anotherphy(hw, false); | |
616 | else if (need_pwrdown_radiob) | |
617 | rtl92d_phy_powerdown_anotherphy(hw, true); | |
f30d7507 | 618 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); |
f219eff1 CL |
619 | return rtstatus; |
620 | ||
621 | phy_rf_cfg_fail: | |
622 | return rtstatus; | |
623 | } |