Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / drivers / net / wireless / rtlwifi / rtl8192de / rf.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
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,
53                                  ("20M RF 0x18 = 0x%x\n",
54                                  rtlphy->rfreg_chnlval[rfpath]));
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,
65                                  ("40M RF 0x18 = 0x%x\n",
66                                  rtlphy->rfreg_chnlval[rfpath]));
67                 }
68                 break;
69         default:
70                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
71                          ("unknown bandwidth: %#X\n", bandwidth));
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;
90         if (mac->act_scanning) {
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) {
109                         tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
110                             (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
111                         tx_agc[RF90_PATH_A] += tmpval;
112                         tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
113                             (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
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;
128         rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, BMASKBYTE1, tmpval);
129         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
130                 ("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
131                 RTXAGC_A_CCK1_MCS32));
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,
135                 ("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
136                 RTXAGC_B_CCK11_A_CCK2_11));
137         tmpval = tx_agc[RF90_PATH_B] >> 24;
138         rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, BMASKBYTE0, tmpval);
139         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
140                 ("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
141                 RTXAGC_B_CCK11_A_CCK2_11));
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,
145                 ("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
146                 RTXAGC_B_CCK1_55_MCS32));
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,
168                         (" [OFDM power base index rf(%c) = 0x%x]\n",
169                         ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
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,
182                         (" [MCS power base index rf(%c) = 0x%x]\n",
183                         ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
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;
230                         writeval = rtlphy->mcs_txpwrlevel_origoffset
231                                         [chnlgroup][index +
232                                         (rf ? 8 : 0)] + ((index < 2) ?
233                                         powerbase0[rf] :
234                                         powerbase1[rf]);
235                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
236                                 "performance, writeval(%c) = 0x%x\n",
237                                 ((rf == 0) ? 'A' : 'B'), writeval));
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;
250                                 writeval = rtlphy->mcs_txpwrlevel_origoffset
251                                                 [chnlgroup][index +
252                                                 (rf ? 8 : 0)] + ((index < 2) ?
253                                                 powerbase0[rf] :
254                                                 powerbase1[rf]);
255                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
256                                         ("Realtek regulatory, "
257                                         "20MHz, writeval(%c) = 0x%x\n",
258                                         ((rf == 0) ? 'A' : 'B'),
259                                         writeval));
260                         }
261                         break;
262                 case 2:
263                         writeval = ((index < 2) ? powerbase0[rf] :
264                                    powerbase1[rf]);
265                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("Better regulatory, "
266                                 "writeval(%c) = 0x%x\n",
267                                 ((rf == 0) ? 'A' : 'B'), writeval));
268                         break;
269                 case 3:
270                         chnlgroup = 0;
271                         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
272                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
273                                         ("customer's limit, 40MHz rf(%c) = "
274                                         "0x%x\n", ((rf == 0) ? 'A' : 'B'),
275                                         rtlefuse->pwrgroup_ht40[rf]
276                                         [channel - 1]));
277                         } else {
278                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
279                                         ("customer's limit, 20MHz rf(%c) = "
280                                         "0x%x\n", ((rf == 0) ? 'A' : 'B'),
281                                         rtlefuse->pwrgroup_ht20[rf]
282                                         [channel - 1]));
283                         }
284                         for (i = 0; i < 4; i++) {
285                                 pwr_diff_limit[i] =
286                                         (u8)((rtlphy->mcs_txpwrlevel_origoffset
287                                         [chnlgroup][index + (rf ? 8 : 0)] &
288                                         (0x7f << (i * 8))) >> (i * 8));
289                                 if (rtlphy->current_chan_bw ==
290                                     HT_CHANNEL_WIDTH_20_40) {
291                                         if (pwr_diff_limit[i] >
292                                             rtlefuse->pwrgroup_ht40[rf]
293                                            [channel - 1])
294                                                 pwr_diff_limit[i] =
295                                                         rtlefuse->pwrgroup_ht40
296                                                         [rf][channel - 1];
297                                 } else {
298                                         if (pwr_diff_limit[i] >
299                                             rtlefuse->pwrgroup_ht20[rf][
300                                                 channel - 1])
301                                                 pwr_diff_limit[i] =
302                                                    rtlefuse->pwrgroup_ht20[rf]
303                                                    [channel - 1];
304                                 }
305                         }
306                         customer_limit = (pwr_diff_limit[3] << 24) |
307                                          (pwr_diff_limit[2] << 16) |
308                                          (pwr_diff_limit[1] << 8) |
309                                          (pwr_diff_limit[0]);
310                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
311                                 ("Customer's limit rf(%c) = 0x%x\n",
312                                 ((rf == 0) ? 'A' : 'B'), customer_limit));
313                         writeval = customer_limit + ((index < 2) ?
314                                    powerbase0[rf] : powerbase1[rf]);
315                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
316                                 ("Customer, writeval rf(%c)= 0x%x\n",
317                                 ((rf == 0) ? 'A' : 'B'), writeval));
318                         break;
319                 default:
320                         chnlgroup = 0;
321                         writeval = rtlphy->mcs_txpwrlevel_origoffset
322                                    [chnlgroup][index +
323                                    (rf ? 8 : 0)] + ((index < 2) ?
324                                    powerbase0[rf] : powerbase1[rf]);
325                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
326                                 ("RTK better performance, writeval "
327                                 "rf(%c) = 0x%x\n",
328                                 ((rf == 0) ? 'A' : 'B'), writeval));
329                         break;
330                 }
331                 *(p_outwriteval + rf) = writeval;
332         }
333 }
334
335 static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw,
336                                          u8 index, u32 *pvalue)
337 {
338         struct rtl_priv *rtlpriv = rtl_priv(hw);
339         struct rtl_phy *rtlphy = &(rtlpriv->phy);
340         static u16 regoffset_a[6] = {
341                 RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
342                 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
343                 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
344         };
345         static u16 regoffset_b[6] = {
346                 RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
347                 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
348                 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
349         };
350         u8 i, rf, pwr_val[4];
351         u32 writeval;
352         u16 regoffset;
353
354         for (rf = 0; rf < 2; rf++) {
355                 writeval = pvalue[rf];
356                 for (i = 0; i < 4; i++) {
357                         pwr_val[i] = (u8) ((writeval & (0x7f <<
358                                      (i * 8))) >> (i * 8));
359                         if (pwr_val[i] > RF6052_MAX_TX_PWR)
360                                 pwr_val[i] = RF6052_MAX_TX_PWR;
361                 }
362                 writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
363                            (pwr_val[1] << 8) | pwr_val[0];
364                 if (rf == 0)
365                         regoffset = regoffset_a[index];
366                 else
367                         regoffset = regoffset_b[index];
368                 rtl_set_bbreg(hw, regoffset, BMASKDWORD, writeval);
369                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
370                         ("Set 0x%x = %08x\n", regoffset, writeval));
371                 if (((get_rf_type(rtlphy) == RF_2T2R) &&
372                     (regoffset == RTXAGC_A_MCS15_MCS12 ||
373                     regoffset == RTXAGC_B_MCS15_MCS12)) ||
374                     ((get_rf_type(rtlphy) != RF_2T2R) &&
375                     (regoffset == RTXAGC_A_MCS07_MCS04 ||
376                     regoffset == RTXAGC_B_MCS07_MCS04))) {
377                         writeval = pwr_val[3];
378                         if (regoffset == RTXAGC_A_MCS15_MCS12 ||
379                             regoffset == RTXAGC_A_MCS07_MCS04)
380                                 regoffset = 0xc90;
381                         if (regoffset == RTXAGC_B_MCS15_MCS12 ||
382                             regoffset == RTXAGC_B_MCS07_MCS04)
383                                 regoffset = 0xc98;
384                         for (i = 0; i < 3; i++) {
385                                 if (i != 2)
386                                         writeval = (writeval > 8) ?
387                                                    (writeval - 8) : 0;
388                                 else
389                                         writeval = (writeval > 6) ?
390                                                    (writeval - 6) : 0;
391                                 rtl_write_byte(rtlpriv, (u32) (regoffset + i),
392                                                (u8) writeval);
393                         }
394                 }
395         }
396 }
397
398 void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
399                                         u8 *ppowerlevel, u8 channel)
400 {
401         u32 writeval[2], powerbase0[2], powerbase1[2];
402         u8 index;
403
404         _rtl92d_phy_get_power_base(hw, ppowerlevel, channel,
405                         &powerbase0[0], &powerbase1[0]);
406         for (index = 0; index < 6; index++) {
407                 _rtl92d_get_txpower_writeval_by_regulatory(hw,
408                                 channel, index, &powerbase0[0],
409                                 &powerbase1[0], &writeval[0]);
410                 _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]);
411         }
412 }
413
414 bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0)
415 {
416         struct rtl_priv *rtlpriv = rtl_priv(hw);
417         struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
418         u8 u1btmp;
419         u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
420         u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
421         u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
422         bool bresult = true; /* true: need to enable BB/RF power */
423
424         rtlhal->during_mac0init_radiob = false;
425         rtlhal->during_mac1init_radioa = false;
426         RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("===>\n"));
427         /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */
428         u1btmp = rtl_read_byte(rtlpriv, mac_reg);
429         if (!(u1btmp & mac_on_bit)) {
430                 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable BB & RF\n"));
431                 /* Enable BB and RF power */
432                 rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL,
433                         rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) |
434                                 BIT(29) | BIT(16) | BIT(17), direct);
435         } else {
436                 /* We think if MAC1 is ON,then radio_a.txt
437                  * and radio_b.txt has been load. */
438                 bresult = false;
439         }
440         RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<===\n"));
441         return bresult;
442
443 }
444
445 void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0)
446 {
447         struct rtl_priv *rtlpriv = rtl_priv(hw);
448         struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
449         u8 u1btmp;
450         u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
451         u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
452         u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
453
454         rtlhal->during_mac0init_radiob = false;
455         rtlhal->during_mac1init_radioa = false;
456         RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
457         /* check MAC0 enable or not again now, if
458          * enabled, not power down radio A. */
459         u1btmp = rtl_read_byte(rtlpriv, mac_reg);
460         if (!(u1btmp & mac_on_bit)) {
461                 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("power down\n"));
462                 /* power down RF radio A according to YuNan's advice. */
463                 rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER,
464                                         0x00000000, direct);
465         }
466         RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
467 }
468
469 bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw)
470 {
471         struct rtl_priv *rtlpriv = rtl_priv(hw);
472         struct rtl_phy *rtlphy = &(rtlpriv->phy);
473         bool rtstatus = true;
474         struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
475         u32 u4_regvalue = 0;
476         u8 rfpath;
477         struct bb_reg_def *pphyreg;
478         bool mac1_initradioa_first = false, mac0_initradiob_first = false;
479         bool need_pwrdown_radioa = false, need_pwrdown_radiob = false;
480         bool true_bpath = false;
481
482         if (rtlphy->rf_type == RF_1T1R)
483                 rtlphy->num_total_rfpath = 1;
484         else
485                 rtlphy->num_total_rfpath = 2;
486
487         /* Single phy mode: use radio_a radio_b config path_A path_B */
488         /* seperately by MAC0, and MAC1 needn't configure RF; */
489         /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */
490         /* MAC1 use radio_b config 2nd PHY path_A. */
491         /* DMDP,MAC0 on G band,MAC1 on A band. */
492         if (rtlhal->macphymode == DUALMAC_DUALPHY) {
493                 if (rtlhal->current_bandtype == BAND_ON_2_4G &&
494                     rtlhal->interfaceindex == 0) {
495                         /* MAC0 needs PHY1 load radio_b.txt.
496                          * Driver use DBI to write. */
497                         if (rtl92d_phy_enable_anotherphy(hw, true)) {
498                                 rtlphy->num_total_rfpath = 2;
499                                 mac0_initradiob_first = true;
500                         } else {
501                                 /* We think if MAC1 is ON,then radio_a.txt and
502                                  * radio_b.txt has been load. */
503                                 return rtstatus;
504                         }
505                 } else if (rtlhal->current_bandtype == BAND_ON_5G &&
506                            rtlhal->interfaceindex == 1) {
507                         /* MAC1 needs PHY0 load radio_a.txt.
508                          * Driver use DBI to write. */
509                         if (rtl92d_phy_enable_anotherphy(hw, false)) {
510                                 rtlphy->num_total_rfpath = 2;
511                                 mac1_initradioa_first = true;
512                         } else {
513                                 /* We think if MAC0 is ON,then radio_a.txt and
514                                  * radio_b.txt has been load. */
515                                 return rtstatus;
516                         }
517                 } else if (rtlhal->interfaceindex == 1) {
518                         /* MAC0 enabled, only init radia B.   */
519                         true_bpath = true;
520                 }
521         }
522
523         for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
524                 /* Mac1 use PHY0 write */
525                 if (mac1_initradioa_first) {
526                         if (rfpath == RF90_PATH_A) {
527                                 rtlhal->during_mac1init_radioa = true;
528                                 need_pwrdown_radioa = true;
529                         } else if (rfpath == RF90_PATH_B) {
530                                 rtlhal->during_mac1init_radioa = false;
531                                 mac1_initradioa_first = false;
532                                 rfpath = RF90_PATH_A;
533                                 true_bpath = true;
534                                 rtlphy->num_total_rfpath = 1;
535                         }
536                 } else if (mac0_initradiob_first) {
537                         /* Mac0 use PHY1 write */
538                         if (rfpath == RF90_PATH_A)
539                                 rtlhal->during_mac0init_radiob = false;
540                         if (rfpath == RF90_PATH_B) {
541                                 rtlhal->during_mac0init_radiob = true;
542                                 mac0_initradiob_first = false;
543                                 need_pwrdown_radiob = true;
544                                 rfpath = RF90_PATH_A;
545                                 true_bpath = true;
546                                 rtlphy->num_total_rfpath = 1;
547                         }
548                 }
549                 pphyreg = &rtlphy->phyreg_def[rfpath];
550                 switch (rfpath) {
551                 case RF90_PATH_A:
552                 case RF90_PATH_C:
553                         u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
554                                                     BRFSI_RFENV);
555                         break;
556                 case RF90_PATH_B:
557                 case RF90_PATH_D:
558                         u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
559                                 BRFSI_RFENV << 16);
560                         break;
561                 }
562                 rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
563                 udelay(1);
564                 rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
565                 udelay(1);
566                 /* Set bit number of Address and Data for RF register */
567                 /* Set 1 to 4 bits for 8255 */
568                 rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
569                               B3WIREADDRESSLENGTH, 0x0);
570                 udelay(1);
571                 /* Set 0 to 12  bits for 8255 */
572                 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
573                 udelay(1);
574                 switch (rfpath) {
575                 case RF90_PATH_A:
576                         if (true_bpath)
577                                 rtstatus = rtl92d_phy_config_rf_with_headerfile(
578                                                 hw, radiob_txt,
579                                                 (enum radio_path)rfpath);
580                         else
581                                 rtstatus = rtl92d_phy_config_rf_with_headerfile(
582                                              hw, radioa_txt,
583                                              (enum radio_path)rfpath);
584                         break;
585                 case RF90_PATH_B:
586                         rtstatus =
587                             rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt,
588                                                 (enum radio_path) rfpath);
589                         break;
590                 case RF90_PATH_C:
591                         break;
592                 case RF90_PATH_D:
593                         break;
594                 }
595                 switch (rfpath) {
596                 case RF90_PATH_A:
597                 case RF90_PATH_C:
598                         rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV,
599                                       u4_regvalue);
600                         break;
601                 case RF90_PATH_B:
602                 case RF90_PATH_D:
603                         rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
604                                       u4_regvalue);
605                         break;
606                 }
607                 if (rtstatus != true) {
608                         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
609                                 ("Radio[%d] Fail!!", rfpath));
610                         goto phy_rf_cfg_fail;
611                 }
612
613         }
614
615         /* check MAC0 enable or not again, if enabled,
616          * not power down radio A. */
617         /* check MAC1 enable or not again, if enabled,
618          * not power down radio B. */
619         if (need_pwrdown_radioa)
620                 rtl92d_phy_powerdown_anotherphy(hw, false);
621         else if (need_pwrdown_radiob)
622                 rtl92d_phy_powerdown_anotherphy(hw, true);
623         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
624         return rtstatus;
625
626 phy_rf_cfg_fail:
627         return rtstatus;
628 }