blob: c592f7936ddb61a05fb636aab82c9e9b6f352807 [file] [log] [blame]
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001/*
Olimpiu Pascariu593ef412010-04-01 23:48:14 +03002 * This is part of the rtl8180-sa2400 driver
3 * released under the GPL (See file COPYING for details).
4 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
5 *
6 * This files contains programming code for the rtl8225
7 * radio frontend.
8 *
9 * *Many* thanks to Realtek Corp. for their great support!
10 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080011
12#include "r8180_hw.h"
13#include "r8180_rtl8225.h"
14#include "r8180_93cx6.h"
15
Bartlomiej Zolnierkiewiczfd9b8d62009-06-12 18:28:35 +020016#include "ieee80211/dot11d.h"
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080017
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020018static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
19{
20 int i;
21 u16 out, select;
22 u8 bit;
23 u32 bangdata = (data << 4) | (adr & 0xf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080024
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020025 out = read_nic_word(dev, RFPinsOutput) & 0xfff3;
26
27 write_nic_word(dev, RFPinsEnable,
28 (read_nic_word(dev, RFPinsEnable) | 0x7));
29
30 select = read_nic_word(dev, RFPinsSelect);
31
32 write_nic_word(dev, RFPinsSelect, select | 0x7 |
Larry Finger8eee44d2009-11-10 16:44:47 -060033 SW_CONTROL_GPIO);
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020034
35 force_pci_posting(dev);
36 udelay(10);
37
38 write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
39
40 force_pci_posting(dev);
41 udelay(2);
42
43 write_nic_word(dev, RFPinsOutput, out);
44
45 force_pci_posting(dev);
46 udelay(10);
47
48 for (i = 15; i >= 0; i--) {
49 bit = (bangdata & (1 << i)) >> i;
50
51 write_nic_word(dev, RFPinsOutput, bit | out);
52
53 write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
54 write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
55
56 i--;
57 bit = (bangdata & (1 << i)) >> i;
58
59 write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
60 write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
61
62 write_nic_word(dev, RFPinsOutput, bit | out);
63
64 }
65
66 write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
67
68 force_pci_posting(dev);
69 udelay(10);
70
Larry Finger8eee44d2009-11-10 16:44:47 -060071 write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020072
Larry Finger8eee44d2009-11-10 16:44:47 -060073 write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020074
Larry Finger8eee44d2009-11-10 16:44:47 -060075 rtl8185_rf_pins_enable(dev);
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020076}
77
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020078static const u8 rtl8225_agc[] = {
79 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
80 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
81 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
82 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
83 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
84 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
85 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
86 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
87 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
88 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
89 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
90 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
91 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
92 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
93 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
94 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
95};
96
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +020097static const u32 rtl8225_chan[] = {
98 0,
99 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
100 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
101};
102
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200103static const u8 rtl8225z2_gain_bg[] = {
104 0x23, 0x15, 0xa5, /* -82-1dBm */
105 0x23, 0x15, 0xb5, /* -82-2dBm */
106 0x23, 0x15, 0xc5, /* -82-3dBm */
107 0x33, 0x15, 0xc5, /* -78dBm */
108 0x43, 0x15, 0xc5, /* -74dBm */
109 0x53, 0x15, 0xc5, /* -70dBm */
110 0x63, 0x15, 0xc5, /* -66dBm */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800111};
112
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200113static const u8 rtl8225z2_gain_a[] = {
114 0x13, 0x27, 0x5a, /* -82dBm */
115 0x23, 0x23, 0x58, /* -82dBm */
116 0x33, 0x1f, 0x56, /* -82dBm */
117 0x43, 0x1b, 0x54, /* -78dBm */
118 0x53, 0x17, 0x51, /* -74dBm */
119 0x63, 0x24, 0x4f, /* -70dBm */
120 0x73, 0x0f, 0x4c, /* -66dBm */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800121};
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800122
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200123static const u16 rtl8225z2_rxgain[] = {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800124 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
125 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
126 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
127 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
128 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
129 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
130 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
131 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
132 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
133 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
134 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
Maxim Mikityanskiydfd6aef2012-11-13 19:28:19 +0200135 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800136
137};
138
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800139void rtl8225z2_set_gain(struct net_device *dev, short gain)
140{
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200141 const u8 *rtl8225_gain;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800142 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800143 u8 mode = priv->ieee80211->mode;
144
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200145 if (mode == IEEE_B || mode == IEEE_G)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800146 rtl8225_gain = rtl8225z2_gain_bg;
147 else
148 rtl8225_gain = rtl8225z2_gain_a;
149
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200150 write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
151 write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
152 write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800153 write_phy_ofdm(dev, 0x21, 0x37);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800154}
155
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200156static u32 read_rtl8225(struct net_device *dev, u8 adr)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800157{
158 u32 data2Write = ((u32)(adr & 0x1f)) << 27;
159 u32 dataRead;
160 u32 mask;
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300161 u16 oval, oval2, oval3, tmp;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800162 int i;
163 short bit, rw;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800164 u8 wLength = 6;
165 u8 rLength = 12;
166 u8 low2high = 0;
167
168 oval = read_nic_word(dev, RFPinsOutput);
169 oval2 = read_nic_word(dev, RFPinsEnable);
170 oval3 = read_nic_word(dev, RFPinsSelect);
171
172 write_nic_word(dev, RFPinsEnable, (oval2|0xf));
173 write_nic_word(dev, RFPinsSelect, (oval3|0xf));
174
175 dataRead = 0;
176
177 oval &= ~0xf;
178
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300179 write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
180 udelay(4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800181
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300182 write_nic_word(dev, RFPinsOutput, oval);
183 udelay(5);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800184
185 rw = 0;
186
187 mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200188
189 for (i = 0; i < wLength/2; i++) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800190 bit = ((data2Write&mask) != 0) ? 1 : 0;
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300191 write_nic_word(dev, RFPinsOutput, bit | oval | rw);
192 udelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800193
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300194 write_nic_word(dev, RFPinsOutput,
195 bit | oval | BB_HOST_BANG_CLK | rw);
196 udelay(2);
197 write_nic_word(dev, RFPinsOutput,
198 bit | oval | BB_HOST_BANG_CLK | rw);
199 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800200
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300201 mask = (low2high) ? (mask<<1) : (mask>>1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800202
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200203 if (i == 2) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800204 rw = BB_HOST_BANG_RW;
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300205 write_nic_word(dev, RFPinsOutput,
206 bit | oval | BB_HOST_BANG_CLK | rw);
207 udelay(2);
208 write_nic_word(dev, RFPinsOutput, bit | oval | rw);
209 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800210 break;
211 }
212
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300213 bit = ((data2Write&mask) != 0) ? 1 : 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800214
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300215 write_nic_word(dev, RFPinsOutput,
216 oval | bit | rw | BB_HOST_BANG_CLK);
217 udelay(2);
218 write_nic_word(dev, RFPinsOutput,
219 oval | bit | rw | BB_HOST_BANG_CLK);
220 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800221
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300222 write_nic_word(dev, RFPinsOutput, oval | bit | rw);
223 udelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800224
225 mask = (low2high) ? (mask<<1) : (mask>>1);
226 }
227
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300228 write_nic_word(dev, RFPinsOutput, rw|oval);
229 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800230 mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));
231
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200232 /*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300233 * We must set data pin to HW controlled, otherwise RF can't driver it
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200234 * and value RF register won't be able to read back properly.
235 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800236 write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));
237
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200238 for (i = 0; i < rLength; i++) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800239 write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);
240
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300241 write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
242 udelay(2);
243 write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
244 udelay(2);
245 write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
246 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800247 tmp = read_nic_word(dev, RFPinsInput);
248
249 dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);
250
251 write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);
252
253 mask = (low2high) ? (mask<<1) : (mask>>1);
254 }
255
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300256 write_nic_word(dev, RFPinsOutput,
257 BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
258 udelay(2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800259
260 write_nic_word(dev, RFPinsEnable, oval2);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200261 write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800262 write_nic_word(dev, RFPinsOutput, 0x3a0);
263
264 return dataRead;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800265}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800266
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800267void rtl8225z2_rf_close(struct net_device *dev)
268{
269 RF_WriteReg(dev, 0x4, 0x1f);
270
271 force_pci_posting(dev);
272 mdelay(1);
273
274 rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
275 rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
276}
277
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200278/*
279 * Map dBm into Tx power index according to current HW model, for example,
280 * RF and PA, and current wireless mode.
281 */
282s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode,
283 s32 PowerInDbm)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800284{
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300285 bool bUseDefault = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800286 s8 TxPwrIdx = 0;
287
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200288 /*
289 * OFDM Power in dBm = Index * 0.5 + 0
290 * CCK Power in dBm = Index * 0.25 + 13
291 */
Larry Fingerd44eb882009-11-09 10:53:20 -0600292 s32 tmp = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800293
Larry Fingerd44eb882009-11-09 10:53:20 -0600294 if (WirelessMode == WIRELESS_MODE_G) {
295 bUseDefault = false;
296 tmp = (2 * PowerInDbm);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800297
Larry Fingerd44eb882009-11-09 10:53:20 -0600298 if (tmp < 0)
299 TxPwrIdx = 0;
300 else if (tmp > 40) /* 40 means 20 dBm. */
301 TxPwrIdx = 40;
302 else
303 TxPwrIdx = (s8)tmp;
304 } else if (WirelessMode == WIRELESS_MODE_B) {
305 bUseDefault = false;
306 tmp = (4 * PowerInDbm) - 52;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800307
Larry Fingerd44eb882009-11-09 10:53:20 -0600308 if (tmp < 0)
309 TxPwrIdx = 0;
310 else if (tmp > 28) /* 28 means 20 dBm. */
311 TxPwrIdx = 28;
312 else
313 TxPwrIdx = (s8)tmp;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800314 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800315
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200316 /*
317 * TRUE if we want to use a default implementation.
Justin P. Mattocked2cb4f2012-04-17 06:56:43 -0700318 * We shall set it to FALSE when we have exact translation formula
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200319 * for target IC. 070622, by rcnjko.
320 */
321 if (bUseDefault) {
322 if (PowerInDbm < 0)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800323 TxPwrIdx = 0;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200324 else if (PowerInDbm > 35)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800325 TxPwrIdx = 35;
326 else
327 TxPwrIdx = (u8)PowerInDbm;
328 }
329
330 return TxPwrIdx;
331}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800332
333void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
334{
335 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800336 u8 max_cck_power_level;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800337 u8 max_ofdm_power_level;
338 u8 min_ofdm_power_level;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200339 char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
340 char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800341
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200342 if (IS_DOT11D_ENABLE(priv->ieee80211) &&
343 IS_DOT11D_STATE_DONE(priv->ieee80211)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800344 u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300345 u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
346 MaxTxPwrInDbm);
347 u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
348 MaxTxPwrInDbm);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800349
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200350 if (cck_power_level > CckMaxPwrIdx)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800351 cck_power_level = CckMaxPwrIdx;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200352 if (ofdm_power_level > OfdmMaxPwrIdx)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800353 ofdm_power_level = OfdmMaxPwrIdx;
354 }
355
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800356 max_cck_power_level = 15;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200357 max_ofdm_power_level = 25;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800358 min_ofdm_power_level = 10;
359
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200360 if (cck_power_level > 35)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800361 cck_power_level = 35;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800362
Maxim Mikityanskiy51150d22012-11-13 19:28:08 +0200363 write_nic_byte(dev, CCK_TXAGC, cck_power_level);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800364 force_pci_posting(dev);
365 mdelay(1);
366
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200367 if (ofdm_power_level > 35)
368 ofdm_power_level = 35;
369
370 if (priv->up == 0) {
371 write_phy_ofdm(dev, 2, 0x42);
372 write_phy_ofdm(dev, 5, 0x00);
373 write_phy_ofdm(dev, 6, 0x40);
374 write_phy_ofdm(dev, 7, 0x00);
375 write_phy_ofdm(dev, 8, 0x40);
376 }
377
Maxim Mikityanskiy51150d22012-11-13 19:28:08 +0200378 write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200379
380 if (ofdm_power_level <= 11) {
381 write_phy_ofdm(dev, 0x07, 0x5c);
382 write_phy_ofdm(dev, 0x09, 0x5c);
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300383 }
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200384
385 if (ofdm_power_level <= 17) {
386 write_phy_ofdm(dev, 0x07, 0x54);
387 write_phy_ofdm(dev, 0x09, 0x54);
388 } else {
389 write_phy_ofdm(dev, 0x07, 0x50);
390 write_phy_ofdm(dev, 0x09, 0x50);
391 }
392
393 force_pci_posting(dev);
394 mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800395}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800396
397void rtl8225z2_rf_set_chan(struct net_device *dev, short ch)
398{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800399 rtl8225z2_SetTXPowerLevel(dev, ch);
400
401 RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
402
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200403 if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch])
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800404 RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800405
406 mdelay(1);
407
408 force_pci_posting(dev);
409 mdelay(10);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800410}
411
Bartlomiej Zolnierkiewicz44a7dcb2009-06-28 16:19:57 +0200412static void rtl8225_host_pci_init(struct net_device *dev)
413{
414 write_nic_word(dev, RFPinsOutput, 0x480);
415
416 rtl8185_rf_pins_enable(dev);
417
418 write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO);
419
420 write_nic_byte(dev, GP_ENABLE, 0);
421
422 force_pci_posting(dev);
423 mdelay(200);
424
425 /* bit 6 is for RF on/off detection */
426 write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
427}
428
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800429void rtl8225z2_rf_init(struct net_device *dev)
430{
431 struct r8180_priv *priv = ieee80211_priv(dev);
432 int i;
433 short channel = 1;
Maxim Mikityanskiydfd6aef2012-11-13 19:28:19 +0200434 u16 brsr;
435 u32 data;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800436
437 priv->chan = channel;
438
Larry Finger8eee44d2009-11-10 16:44:47 -0600439 rtl8225_host_pci_init(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800440
441 write_nic_dword(dev, RF_TIMING, 0x000a8008);
442
443 brsr = read_nic_word(dev, BRSR);
444
445 write_nic_word(dev, BRSR, 0xffff);
446
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800447 write_nic_dword(dev, RF_PARA, 0x100044);
448
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800449 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
450 write_nic_byte(dev, CONFIG3, 0x44);
451 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800452
453 rtl8185_rf_pins_enable(dev);
454
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800455 write_rtl8225(dev, 0x0, 0x2bf); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800456 write_rtl8225(dev, 0x1, 0xee0); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800457 write_rtl8225(dev, 0x2, 0x44d); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800458 write_rtl8225(dev, 0x3, 0x441); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200459 write_rtl8225(dev, 0x4, 0x8c3); mdelay(1);
460 write_rtl8225(dev, 0x5, 0xc72); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800461 write_rtl8225(dev, 0x6, 0xe6); mdelay(1);
Larry Finger8eee44d2009-11-10 16:44:47 -0600462 write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800463 write_rtl8225(dev, 0x8, 0x3f); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200464 write_rtl8225(dev, 0x9, 0x335); mdelay(1);
465 write_rtl8225(dev, 0xa, 0x9d4); mdelay(1);
466 write_rtl8225(dev, 0xb, 0x7bb); mdelay(1);
467 write_rtl8225(dev, 0xc, 0x850); mdelay(1);
468 write_rtl8225(dev, 0xd, 0xcdf); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800469 write_rtl8225(dev, 0xe, 0x2b); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800470 write_rtl8225(dev, 0xf, 0x114);
471
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800472 mdelay(100);
473
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800474 write_rtl8225(dev, 0x0, 0x1b7);
475
Maxim Mikityanskiydfd6aef2012-11-13 19:28:19 +0200476 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
477 write_rtl8225(dev, 0x1, i + 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800478 write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
479 }
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200480
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800481 write_rtl8225(dev, 0x3, 0x80);
482 write_rtl8225(dev, 0x5, 0x4);
483
484 write_rtl8225(dev, 0x0, 0xb7);
485
486 write_rtl8225(dev, 0x2, 0xc4d);
487
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800488 /* FIXME!! rtl8187 we have to check if calibrarion
489 * is successful and eventually cal. again (repeat
490 * the two write on reg 2)
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200491 */
492 data = read_rtl8225(dev, 6);
493 if (!(data & 0x00000080)) {
494 write_rtl8225(dev, 0x02, 0x0c4d);
495 force_pci_posting(dev); mdelay(200);
496 write_rtl8225(dev, 0x02, 0x044d);
497 force_pci_posting(dev); mdelay(100);
498 data = read_rtl8225(dev, 6);
499 if (!(data & 0x00000080))
500 DMESGW("RF Calibration Failed!!!!\n");
501 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800502
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200503 mdelay(200);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800504
505 write_rtl8225(dev, 0x0, 0x2bf);
506
Maxim Mikityanskiydfd6aef2012-11-13 19:28:19 +0200507 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
508 write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200509 mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800510
Maxim Mikityanskiydfd6aef2012-11-13 19:28:19 +0200511 /* enable writing AGC table */
512 write_phy_ofdm(dev, 0xa, i + 0x80);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200513 mdelay(1);
514 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800515
516 force_pci_posting(dev);
517 mdelay(1);
518
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200519 write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
520 write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
Larry Finger8eee44d2009-11-10 16:44:47 -0600521 write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200522 write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
523 write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
524 write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
525 write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
526 write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
527 write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
528 write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
529 write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
530 write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
531 write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
532 write_phy_ofdm(dev, 0x0d, 0x43);
533 write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
534 write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
535 write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
536 write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
537 write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
538 write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
539 write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800540 write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200541 write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800542 write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200543 write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800544 write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
545 write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200546 write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
547 write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
548 write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
549 write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
550 write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
551 write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
552 write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
553 write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
554 write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800555 write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
556 write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
557 write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800558 write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
559
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300560 rtl8225z2_set_gain(dev, 4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800561
562 write_phy_cck(dev, 0x0, 0x98); mdelay(1);
563 write_phy_cck(dev, 0x3, 0x20); mdelay(1);
564 write_phy_cck(dev, 0x4, 0x7e); mdelay(1);
565 write_phy_cck(dev, 0x5, 0x12); mdelay(1);
566 write_phy_cck(dev, 0x6, 0xfc); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200567 write_phy_cck(dev, 0x7, 0x78); mdelay(1);
568 write_phy_cck(dev, 0x8, 0x2e); mdelay(1);
Larry Finger8eee44d2009-11-10 16:44:47 -0600569 write_phy_cck(dev, 0x10, 0x93); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800570 write_phy_cck(dev, 0x11, 0x88); mdelay(1);
571 write_phy_cck(dev, 0x12, 0x47); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200572 write_phy_cck(dev, 0x13, 0xd0);
573 write_phy_cck(dev, 0x19, 0x00);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800574 write_phy_cck(dev, 0x1a, 0xa0);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200575 write_phy_cck(dev, 0x1b, 0x08);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800576 write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200577 write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800578 write_phy_cck(dev, 0x42, 0x15); mdelay(1);
579 write_phy_cck(dev, 0x43, 0x18); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800580 write_phy_cck(dev, 0x44, 0x36); mdelay(1);
581 write_phy_cck(dev, 0x45, 0x35); mdelay(1);
582 write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
583 write_phy_cck(dev, 0x47, 0x25); mdelay(1);
584 write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
585 write_phy_cck(dev, 0x49, 0x12); mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200586 write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
587 write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
588 write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800589
590 write_nic_byte(dev, 0x5b, 0x0d); mdelay(1);
591
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800592 rtl8225z2_SetTXPowerLevel(dev, channel);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800593
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200594 /* RX antenna default to A */
595 write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */
596 write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
597
598 rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800599
600 /* switch to high-speed 3-wire
601 * last digit. 2 for both cck and ofdm
602 */
Larry Finger8eee44d2009-11-10 16:44:47 -0600603 write_nic_dword(dev, 0x94, 0x15c00002);
604 rtl8185_rf_pins_enable(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800605
Maxim Mikityanskiy51150d22012-11-13 19:28:08 +0200606 rtl8225z2_rf_set_chan(dev, priv->chan);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800607}
608
609void rtl8225z2_rf_set_mode(struct net_device *dev)
610{
611 struct r8180_priv *priv = ieee80211_priv(dev);
612
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200613 if (priv->ieee80211->mode == IEEE_A) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800614 write_rtl8225(dev, 0x5, 0x1865);
615 write_nic_dword(dev, RF_PARA, 0x10084);
616 write_nic_dword(dev, RF_TIMING, 0xa8008);
617 write_phy_ofdm(dev, 0x0, 0x0);
618 write_phy_ofdm(dev, 0xa, 0x6);
619 write_phy_ofdm(dev, 0xb, 0x99);
620 write_phy_ofdm(dev, 0xf, 0x20);
621 write_phy_ofdm(dev, 0x11, 0x7);
622
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300623 rtl8225z2_set_gain(dev, 4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800624
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300625 write_phy_ofdm(dev, 0x15, 0x40);
626 write_phy_ofdm(dev, 0x17, 0x40);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800627
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300628 write_nic_dword(dev, 0x94, 0x10000000);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200629 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800630 write_rtl8225(dev, 0x5, 0x1864);
631 write_nic_dword(dev, RF_PARA, 0x10044);
632 write_nic_dword(dev, RF_TIMING, 0xa8008);
633 write_phy_ofdm(dev, 0x0, 0x1);
634 write_phy_ofdm(dev, 0xa, 0x6);
635 write_phy_ofdm(dev, 0xb, 0x99);
636 write_phy_ofdm(dev, 0xf, 0x20);
637 write_phy_ofdm(dev, 0x11, 0x7);
638
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300639 rtl8225z2_set_gain(dev, 4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800640
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300641 write_phy_ofdm(dev, 0x15, 0x40);
642 write_phy_ofdm(dev, 0x17, 0x40);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800643
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300644 write_nic_dword(dev, 0x94, 0x04000002);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800645 }
646}
647
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300648#define MAX_DOZE_WAITING_TIMES_85B 20
649#define MAX_POLLING_24F_TIMES_87SE 10
650#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800651
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200652bool SetZebraRFPowerState8185(struct net_device *dev,
653 RT_RF_POWER_STATE eRFPowerState)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800654{
655 struct r8180_priv *priv = ieee80211_priv(dev);
656 u8 btCR9346, btConfig3;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200657 bool bActionAllowed = true, bTurnOffBB = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800658 u8 u1bTmp;
659 int i;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800660 bool bResult = true;
661 u8 QueueID;
662
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200663 if (priv->SetRFPowerStateInProgress == true)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800664 return false;
665
666 priv->SetRFPowerStateInProgress = true;
667
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800668 btCR9346 = read_nic_byte(dev, CR9346);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200669 write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800670
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200671 btConfig3 = read_nic_byte(dev, CONFIG3);
672 write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
673
Larry Finger8daba6b2010-02-14 22:04:56 -0600674 switch (eRFPowerState) {
675 case eRfOn:
676 write_nic_word(dev, 0x37C, 0x00EC);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800677
Larry Finger8daba6b2010-02-14 22:04:56 -0600678 /* turn on AFE */
679 write_nic_byte(dev, 0x54, 0x00);
680 write_nic_byte(dev, 0x62, 0x00);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800681
Larry Finger8daba6b2010-02-14 22:04:56 -0600682 /* turn on RF */
683 RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
684 RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800685
Larry Finger8daba6b2010-02-14 22:04:56 -0600686 /* turn on RF again */
687 RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
688 RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
689
690 /* turn on BB */
691 write_phy_ofdm(dev, 0x10, 0x40);
692 write_phy_ofdm(dev, 0x12, 0x40);
693
694 /* Avoid power down at init time. */
695 write_nic_byte(dev, CONFIG4, priv->RFProgType);
696
697 u1bTmp = read_nic_byte(dev, 0x24E);
698 write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800699 break;
Larry Finger8daba6b2010-02-14 22:04:56 -0600700 case eRfSleep:
701 for (QueueID = 0, i = 0; QueueID < 6;) {
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300702 if (get_curr_tx_free_desc(dev, QueueID) ==
703 priv->txringcount) {
Larry Finger8daba6b2010-02-14 22:04:56 -0600704 QueueID++;
705 continue;
706 } else {
707 priv->TxPollingTimes++;
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300708 if (priv->TxPollingTimes >=
709 LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
Larry Finger8daba6b2010-02-14 22:04:56 -0600710 bActionAllowed = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800711 break;
Larry Finger8daba6b2010-02-14 22:04:56 -0600712 } else
713 udelay(10);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800714 }
Larry Finger8daba6b2010-02-14 22:04:56 -0600715 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800716
Larry Finger8daba6b2010-02-14 22:04:56 -0600717 if (bActionAllowed) {
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200718 /* turn off BB RXIQ matrix to cut off rx signal */
719 write_phy_ofdm(dev, 0x10, 0x00);
720 write_phy_ofdm(dev, 0x12, 0x00);
721
722 /* turn off RF */
723 RF_WriteReg(dev, 0x4, 0x0000);
724 RF_WriteReg(dev, 0x0, 0x0000);
725
726 /* turn off AFE except PLL */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800727 write_nic_byte(dev, 0x62, 0xff);
728 write_nic_byte(dev, 0x54, 0xec);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200729
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800730 mdelay(1);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200731
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800732 {
733 int i = 0;
Larry Finger8daba6b2010-02-14 22:04:56 -0600734 while (true) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800735 u8 tmp24F = read_nic_byte(dev, 0x24f);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200736
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300737 if ((tmp24F == 0x01) ||
738 (tmp24F == 0x09)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800739 bTurnOffBB = true;
740 break;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200741 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800742 udelay(10);
743 i++;
Larry Finger8daba6b2010-02-14 22:04:56 -0600744 priv->TxPollingTimes++;
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200745
Larry Finger8daba6b2010-02-14 22:04:56 -0600746 if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
747 bTurnOffBB = false;
748 break;
749 } else
750 udelay(10);
751 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800752 }
753 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800754
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200755 if (bTurnOffBB) {
756 /* turn off BB */
757 u1bTmp = read_nic_byte(dev, 0x24E);
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300758 write_nic_byte(dev, 0x24E,
759 (u1bTmp | BIT5 | BIT6));
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200760
Larry Finger8daba6b2010-02-14 22:04:56 -0600761 /* turn off AFE PLL */
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200762 write_nic_byte(dev, 0x54, 0xFC);
763 write_nic_word(dev, 0x37C, 0x00FC);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800764 }
Larry Finger8daba6b2010-02-14 22:04:56 -0600765 }
766 break;
767 case eRfOff:
768 for (QueueID = 0, i = 0; QueueID < 6;) {
Olimpiu Pascariu593ef412010-04-01 23:48:14 +0300769 if (get_curr_tx_free_desc(dev, QueueID) ==
770 priv->txringcount) {
Larry Finger8daba6b2010-02-14 22:04:56 -0600771 QueueID++;
772 continue;
773 } else {
774 udelay(10);
775 i++;
776 }
777
778 if (i >= MAX_DOZE_WAITING_TIMES_85B)
779 break;
780 }
781
782 /* turn off BB RXIQ matrix to cut off rx signal */
783 write_phy_ofdm(dev, 0x10, 0x00);
784 write_phy_ofdm(dev, 0x12, 0x00);
785
786 /* turn off RF */
787 RF_WriteReg(dev, 0x4, 0x0000);
788 RF_WriteReg(dev, 0x0, 0x0000);
789
790 /* turn off AFE except PLL */
791 write_nic_byte(dev, 0x62, 0xff);
792 write_nic_byte(dev, 0x54, 0xec);
793
794 mdelay(1);
795
796 {
797 int i = 0;
798
799 while (true) {
800 u8 tmp24F = read_nic_byte(dev, 0x24f);
801
802 if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
803 bTurnOffBB = true;
804 break;
805 } else {
806 bTurnOffBB = false;
807 udelay(10);
808 i++;
809 }
810
811 if (i > MAX_POLLING_24F_TIMES_87SE)
812 break;
813 }
814 }
815
816 if (bTurnOffBB) {
817 /* turn off BB */
818 u1bTmp = read_nic_byte(dev, 0x24E);
819 write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
820
821 /* turn off AFE PLL (80M) */
822 write_nic_byte(dev, 0x54, 0xFC);
823 write_nic_word(dev, 0x37C, 0x00FC);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800824 }
825 break;
826 }
827
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800828 btConfig3 &= ~(CONFIG3_PARM_En);
829 write_nic_byte(dev, CONFIG3, btConfig3);
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200830
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800831 btCR9346 &= ~(0xC0);
832 write_nic_byte(dev, CR9346, btCR9346);
833
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200834 if (bResult && bActionAllowed)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800835 priv->eRFPowerState = eRFPowerState;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800836
837 priv->SetRFPowerStateInProgress = false;
838
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200839 return bResult && bActionAllowed;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800840}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800841
Bartlomiej Zolnierkiewicz22eec792009-06-28 16:20:32 +0200842void rtl8225z4_rf_sleep(struct net_device *dev)
843{
844 MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
845}
846
847void rtl8225z4_rf_wakeup(struct net_device *dev)
848{
849 MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
850}