3
* Radio tuning for RTL8225 on RTL8180
5
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
6
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
8
* Based on the r8180 driver, which is:
9
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
11
* Thanks to Realtek for their support!
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License version 2 as
15
* published by the Free Software Foundation.
18
#include <linux/init.h>
19
#include <linux/pci.h>
20
#include <linux/delay.h>
21
#include <net/mac80211.h>
24
#include "rtl8180_rtl8225.h"
26
static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
28
struct rtl8180_priv *priv = dev->priv;
29
u16 reg80, reg84, reg82;
33
bangdata = (data << 4) | (addr & 0xf);
35
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
36
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
38
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
40
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
41
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
42
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
45
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
46
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
48
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
49
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
52
for (i = 15; i >= 0; i--) {
55
if (bangdata & (1 << i))
59
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
61
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
62
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
65
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
68
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
69
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
72
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
73
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
74
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
77
static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
79
struct rtl8180_priv *priv = dev->priv;
80
u16 reg80, reg82, reg84, out;
83
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
84
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
85
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
89
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
90
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
92
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
93
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
95
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
96
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
99
for (i = 4; i >= 0; i--) {
100
u16 reg = reg80 | ((addr >> i) & 1);
103
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
104
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
108
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
110
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
112
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
114
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
118
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
119
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
124
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
125
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
126
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
127
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
128
reg80 | (1 << 3) | (1 << 1));
129
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
131
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
133
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
135
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
137
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
141
for (i = 11; i >= 0; i--) {
142
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
144
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
146
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
147
reg80 | (1 << 3) | (1 << 1));
148
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
150
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
151
reg80 | (1 << 3) | (1 << 1));
152
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
154
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
155
reg80 | (1 << 3) | (1 << 1));
156
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
159
if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
162
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
164
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
168
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
169
reg80 | (1 << 3) | (1 << 2));
170
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
173
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
174
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
175
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
180
static const u16 rtl8225bcd_rxgain[] = {
181
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
182
0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
183
0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
184
0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
185
0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
186
0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
187
0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
188
0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
189
0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
190
0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
191
0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
192
0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
195
static const u8 rtl8225_agc[] = {
196
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
197
0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
198
0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
199
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
200
0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
201
0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
202
0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
203
0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
204
0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
205
0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
206
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
207
0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
208
0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
209
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
210
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
211
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
214
static const u8 rtl8225_gain[] = {
215
0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
216
0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
217
0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
218
0x33, 0x80, 0x79, 0xc5, /* -78dbm */
219
0x43, 0x78, 0x76, 0xc5, /* -74dbm */
220
0x53, 0x60, 0x73, 0xc5, /* -70dbm */
221
0x63, 0x58, 0x70, 0xc5, /* -66dbm */
224
static const u8 rtl8225_threshold[] = {
225
0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
228
static const u8 rtl8225_tx_gain_cck_ofdm[] = {
229
0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
232
static const u8 rtl8225_tx_power_cck[] = {
233
0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
234
0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
235
0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
236
0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
237
0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
238
0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
241
static const u8 rtl8225_tx_power_cck_ch14[] = {
242
0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
243
0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
244
0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
245
0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
246
0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
247
0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
250
static const u8 rtl8225_tx_power_ofdm[] = {
251
0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
254
static const u32 rtl8225_chan[] = {
255
0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
256
0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
259
static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
261
struct rtl8180_priv *priv = dev->priv;
262
u8 cck_power, ofdm_power;
267
cck_power = priv->channels[channel - 1].hw_value & 0xFF;
268
ofdm_power = priv->channels[channel - 1].hw_value >> 8;
270
cck_power = min(cck_power, (u8)35);
271
ofdm_power = min(ofdm_power, (u8)35);
273
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
274
rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
277
tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
279
tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
281
for (i = 0; i < 8; i++)
282
rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
284
msleep(1); /* FIXME: optional? */
287
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
288
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
289
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
290
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
291
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
292
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
294
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
295
rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
297
tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
299
rtl8225_write_phy_ofdm(dev, 5, *tmp);
300
rtl8225_write_phy_ofdm(dev, 7, *tmp);
305
static void rtl8225_rf_init(struct ieee80211_hw *dev)
307
struct rtl8180_priv *priv = dev->priv;
310
rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
313
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
314
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
315
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
316
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
317
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
318
msleep(200); /* FIXME: ehh?? */
319
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
321
rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
323
/* TODO: check if we need really to change BRSR to do RF config */
324
rtl818x_ioread16(priv, &priv->map->BRSR);
325
rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
326
rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
327
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
328
rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
329
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
331
rtl8225_write(dev, 0x0, 0x067);
332
rtl8225_write(dev, 0x1, 0xFE0);
333
rtl8225_write(dev, 0x2, 0x44D);
334
rtl8225_write(dev, 0x3, 0x441);
335
rtl8225_write(dev, 0x4, 0x8BE);
336
rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */
337
rtl8225_write(dev, 0x6, 0xAE6);
338
rtl8225_write(dev, 0x7, rtl8225_chan[0]);
339
rtl8225_write(dev, 0x8, 0x01F);
340
rtl8225_write(dev, 0x9, 0x334);
341
rtl8225_write(dev, 0xA, 0xFD4);
342
rtl8225_write(dev, 0xB, 0x391);
343
rtl8225_write(dev, 0xC, 0x050);
344
rtl8225_write(dev, 0xD, 0x6DB);
345
rtl8225_write(dev, 0xE, 0x029);
346
rtl8225_write(dev, 0xF, 0x914); msleep(1);
348
rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
350
rtl8225_write(dev, 0x0, 0x127);
352
for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
353
rtl8225_write(dev, 0x1, i + 1);
354
rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
357
rtl8225_write(dev, 0x0, 0x027);
358
rtl8225_write(dev, 0x0, 0x22F);
359
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
361
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
362
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
364
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
370
rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
371
rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
372
rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
373
rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
374
rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
375
rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
376
rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
377
rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
378
rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
379
rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
380
rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
381
rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
382
rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
383
rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
384
rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
385
rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
386
rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
387
rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
388
rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
389
rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
390
rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
391
rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
392
rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
393
rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
394
rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
395
rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
396
rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
397
rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
398
rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
399
rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
400
rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
401
rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
402
rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
403
rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
404
rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
405
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
406
rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
408
rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
409
rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
410
rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
411
rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
412
rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
413
rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
414
rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
415
rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
416
rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
417
rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
418
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
419
rtl8225_write_phy_cck(dev, 0x19, 0x00);
420
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
421
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
422
rtl8225_write_phy_cck(dev, 0x40, 0x86);
423
rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
424
rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
425
rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
426
rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
427
rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
428
rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
429
rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
430
rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
431
rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
432
rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
433
rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
434
rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
436
rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
438
rtl8225_rf_set_tx_power(dev, 1);
440
/* RX antenna default to A */
441
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
442
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
444
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
446
rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
447
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
449
rtl8225_write(dev, 0x0c, 0x50);
450
/* set OFDM initial gain */
451
rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
452
rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
453
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
454
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
455
/* set CCK threshold */
456
rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
459
static const u8 rtl8225z2_tx_power_cck_ch14[] = {
460
0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
463
static const u8 rtl8225z2_tx_power_cck_B[] = {
464
0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
467
static const u8 rtl8225z2_tx_power_cck_A[] = {
468
0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
471
static const u8 rtl8225z2_tx_power_cck[] = {
472
0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
475
static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
477
struct rtl8180_priv *priv = dev->priv;
478
u8 cck_power, ofdm_power;
482
cck_power = priv->channels[channel - 1].hw_value & 0xFF;
483
ofdm_power = priv->channels[channel - 1].hw_value >> 8;
486
tmp = rtl8225z2_tx_power_cck_ch14;
487
else if (cck_power == 12)
488
tmp = rtl8225z2_tx_power_cck_B;
489
else if (cck_power == 13)
490
tmp = rtl8225z2_tx_power_cck_A;
492
tmp = rtl8225z2_tx_power_cck;
494
for (i = 0; i < 8; i++)
495
rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
497
cck_power = min(cck_power, (u8)35);
498
if (cck_power == 13 || cck_power == 14)
503
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
504
rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
507
ofdm_power = min(ofdm_power, (u8)35);
508
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
510
rtl8225_write_phy_ofdm(dev, 2, 0x62);
511
rtl8225_write_phy_ofdm(dev, 5, 0x00);
512
rtl8225_write_phy_ofdm(dev, 6, 0x40);
513
rtl8225_write_phy_ofdm(dev, 7, 0x00);
514
rtl8225_write_phy_ofdm(dev, 8, 0x40);
519
static const u16 rtl8225z2_rxgain[] = {
520
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
521
0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
522
0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
523
0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
524
0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
525
0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
526
0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
527
0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
528
0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
529
0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
530
0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
531
0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
534
static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
536
struct rtl8180_priv *priv = dev->priv;
539
rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
542
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
543
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
544
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
545
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
546
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
547
msleep(200); /* FIXME: ehh?? */
548
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
550
rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
552
/* TODO: check if we need really to change BRSR to do RF config */
553
rtl818x_ioread16(priv, &priv->map->BRSR);
554
rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
555
rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
556
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
557
rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
558
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
560
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
562
rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
563
rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
564
rtl8225_write(dev, 0x2, 0x44D); msleep(1);
565
rtl8225_write(dev, 0x3, 0x441); msleep(1);
566
rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
567
rtl8225_write(dev, 0x5, 0xC72); msleep(1);
568
rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
569
rtl8225_write(dev, 0x7, 0x82A); msleep(1);
570
rtl8225_write(dev, 0x8, 0x03F); msleep(1);
571
rtl8225_write(dev, 0x9, 0x335); msleep(1);
572
rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
573
rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
574
rtl8225_write(dev, 0xc, 0x850); msleep(1);
575
rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
576
rtl8225_write(dev, 0xe, 0x02B); msleep(1);
577
rtl8225_write(dev, 0xf, 0x114); msleep(100);
579
if (!(rtl8225_read(dev, 6) & (1 << 7))) {
580
rtl8225_write(dev, 0x02, 0x0C4D);
582
rtl8225_write(dev, 0x02, 0x044D);
584
/* TODO: readd calibration failure message when the calibration
588
rtl8225_write(dev, 0x0, 0x1B7);
589
rtl8225_write(dev, 0x3, 0x002);
590
rtl8225_write(dev, 0x5, 0x004);
592
for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
593
rtl8225_write(dev, 0x1, i + 1);
594
rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
597
rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
598
rtl8225_write(dev, 0x2, 0xC4D);
601
rtl8225_write(dev, 0x2, 0x44D);
604
rtl8225_write(dev, 0x00, 0x2BF);
605
rtl8225_write(dev, 0xFF, 0xFFFF);
607
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
609
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
610
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
612
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
618
rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
619
rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
620
rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
621
rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
622
rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
623
rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
624
rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
625
rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
626
rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
627
rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
628
rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
629
rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
630
rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
631
rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
632
rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
633
rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
634
rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
635
rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
636
rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
637
rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
638
rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
639
rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
640
rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
641
rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
642
rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
643
rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
644
rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
645
rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
646
rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
647
rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
648
rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
649
rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
650
rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
651
rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
652
rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
653
rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
654
rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
655
rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
656
rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
657
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
658
rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
660
rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
661
rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
662
rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
663
rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
664
rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
665
rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
666
rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
667
rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
668
rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
669
rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
670
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
671
rtl8225_write_phy_cck(dev, 0x19, 0x00);
672
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
673
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
674
rtl8225_write_phy_cck(dev, 0x40, 0x86);
675
rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
676
rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
677
rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
678
rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
679
rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
680
rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
681
rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
682
rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
683
rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
684
rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
685
rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
686
rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
688
rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
690
rtl8225z2_rf_set_tx_power(dev, 1);
692
/* RX antenna default to A */
693
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
694
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
696
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
698
rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
699
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
702
static void rtl8225_rf_stop(struct ieee80211_hw *dev)
704
struct rtl8180_priv *priv = dev->priv;
707
rtl8225_write(dev, 0x4, 0x1f); msleep(1);
709
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
710
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
711
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
712
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
713
rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
714
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
715
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
718
static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
719
struct ieee80211_conf *conf)
721
struct rtl8180_priv *priv = dev->priv;
722
int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
724
if (priv->rf->init == rtl8225_rf_init)
725
rtl8225_rf_set_tx_power(dev, chan);
727
rtl8225z2_rf_set_tx_power(dev, chan);
729
rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
733
static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
734
struct ieee80211_bss_conf *info)
736
struct rtl8180_priv *priv = dev->priv;
738
if (info->use_short_slot) {
739
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
740
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
741
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
742
rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
743
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
745
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
746
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
747
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
748
rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
749
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
753
static const struct rtl818x_rf_ops rtl8225_ops = {
755
.init = rtl8225_rf_init,
756
.stop = rtl8225_rf_stop,
757
.set_chan = rtl8225_rf_set_channel,
758
.conf_erp = rtl8225_rf_conf_erp,
761
static const struct rtl818x_rf_ops rtl8225z2_ops = {
763
.init = rtl8225z2_rf_init,
764
.stop = rtl8225_rf_stop,
765
.set_chan = rtl8225_rf_set_channel,
766
.conf_erp = rtl8225_rf_conf_erp,
769
const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
771
struct rtl8180_priv *priv = dev->priv;
774
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
775
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
776
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
777
rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
780
rtl8225_write(dev, 0, 0x1B7);
782
reg8 = rtl8225_read(dev, 8);
783
reg9 = rtl8225_read(dev, 9);
785
rtl8225_write(dev, 0, 0x0B7);
787
if (reg8 != 0x588 || reg9 != 0x700)
790
return &rtl8225z2_ops;