0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <net/mac80211.h>
0017
0018 #include "rtl8180.h"
0019 #include "rtl8225se.h"
0020
0021 #define PFX "rtl8225 (se) "
0022
0023 static const u32 RF_GAIN_TABLE[] = {
0024 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
0025 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
0026 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
0027 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
0028 0x0183, 0x0163, 0x0143, 0x0123, 0x0103
0029 };
0030
0031 static const u8 cck_ofdm_gain_settings[] = {
0032 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0033 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0034 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0035 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0036 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0037 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0038 };
0039
0040 static const u32 rtl8225se_chan[] = {
0041 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
0042 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
0043 };
0044
0045 static const u8 ZEBRA_AGC[] = {
0046 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A,
0047 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
0048 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
0049 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
0050 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27,
0051 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
0052 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00,
0053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0054 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0055 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
0056 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b,
0057 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
0058 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21,
0059 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
0060 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0061 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
0062 };
0063
0064 static const u8 OFDM_CONFIG[] = {
0065 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
0066 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
0067 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
0068 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
0069 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
0070 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
0071 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
0072 0xD8, 0x3C, 0x7B, 0x10, 0x10
0073 };
0074
0075 static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data,
0076 u8 len, bool write)
0077 {
0078 struct rtl8180_priv *priv = dev->priv;
0079 int i;
0080 u8 tmp;
0081
0082 do {
0083 for (i = 0; i < 5; i++) {
0084 tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
0085 if (!(tmp & 0x3))
0086 break;
0087 udelay(10);
0088 }
0089 if (i == 5)
0090 wiphy_err(dev->wiphy, PFX
0091 "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp);
0092
0093 tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02;
0094 rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp);
0095
0096 tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7;
0097 rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp);
0098 if (write) {
0099 if (len == 16) {
0100 rtl818x_iowrite16(priv, SW_3W_DB0,
0101 *(u16 *)data);
0102 } else if (len == 64) {
0103 rtl818x_iowrite32(priv, SW_3W_DB0_4,
0104 *((u32 *)data));
0105 rtl818x_iowrite32(priv, SW_3W_DB1_4,
0106 *((u32 *)(data + 4)));
0107 } else
0108 wiphy_err(dev->wiphy, PFX
0109 "Unimplemented length\n");
0110 } else {
0111 rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data);
0112 }
0113 if (write)
0114 tmp = 2;
0115 else
0116 tmp = 1;
0117 rtl818x_iowrite8(priv, SW_3W_CMD1, tmp);
0118 for (i = 0; i < 5; i++) {
0119 tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
0120 if (!(tmp & 0x3))
0121 break;
0122 udelay(10);
0123 }
0124 rtl818x_iowrite8(priv, SW_3W_CMD1, 0);
0125 if (!write) {
0126 *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG);
0127 *((u16 *)data) &= 0x0FFF;
0128 }
0129 } while (0);
0130 }
0131
0132 static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr)
0133 {
0134 u32 dataread = addr & 0x0F;
0135 rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0);
0136 return dataread;
0137 }
0138
0139 static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data)
0140 {
0141 u32 outdata = (data << 4) | (u32)(addr & 0x0F);
0142 rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1);
0143 }
0144
0145
0146 static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev)
0147 {
0148 int i;
0149
0150 for (i = 0; i < 128; i++) {
0151 rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]);
0152 rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80);
0153 rtl8225se_write_phy_ofdm(dev, 0xE, 0);
0154 }
0155 }
0156
0157 static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev)
0158 {
0159
0160 int i;
0161
0162 for (i = 0; i < 60; i++)
0163 rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]);
0164
0165 }
0166
0167 static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
0168 {
0169 struct rtl8180_priv *priv = dev->priv;
0170 u8 cck_power, ofdm_power;
0171
0172 cck_power = priv->channels[channel - 1].hw_value & 0xFF;
0173 if (cck_power > 35)
0174 cck_power = 35;
0175 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
0176 cck_ofdm_gain_settings[cck_power]);
0177
0178 usleep_range(1000, 5000);
0179 ofdm_power = priv->channels[channel - 1].hw_value >> 8;
0180 if (ofdm_power > 35)
0181 ofdm_power = 35;
0182
0183 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
0184 cck_ofdm_gain_settings[ofdm_power]);
0185 if (ofdm_power < 12) {
0186 rtl8225se_write_phy_ofdm(dev, 7, 0x5C);
0187 rtl8225se_write_phy_ofdm(dev, 9, 0x5C);
0188 }
0189 if (ofdm_power < 18) {
0190 rtl8225se_write_phy_ofdm(dev, 7, 0x54);
0191 rtl8225se_write_phy_ofdm(dev, 9, 0x54);
0192 } else {
0193 rtl8225se_write_phy_ofdm(dev, 7, 0x50);
0194 rtl8225se_write_phy_ofdm(dev, 9, 0x50);
0195 }
0196
0197 usleep_range(1000, 5000);
0198 }
0199
0200 static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev)
0201 {
0202 int i;
0203
0204 for (i = 0; i <= 36; i++) {
0205 rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1);
0206 rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1);
0207 }
0208 }
0209
0210 static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev,
0211 int init_gain)
0212 {
0213 switch (init_gain) {
0214 default:
0215 rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
0216 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0217 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
0218 break;
0219 case 2:
0220 rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
0221 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0222 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
0223 break;
0224 case 3:
0225 rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
0226 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0227 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0228 break;
0229 case 4:
0230 rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
0231 rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
0232 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0233 break;
0234 case 5:
0235 rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
0236 rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
0237 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
0238 break;
0239 case 6:
0240 rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
0241 rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
0242 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0243 break;
0244 case 7:
0245 rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
0246 rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1);
0247 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0248 break;
0249 case 8:
0250 rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
0251 rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1);
0252 rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
0253 break;
0254 }
0255 }
0256
0257 void rtl8225se_rf_init(struct ieee80211_hw *dev)
0258 {
0259 struct rtl8180_priv *priv = dev->priv;
0260 u32 rf23, rf24;
0261 u8 d_cut = 0;
0262 u8 tmp;
0263
0264
0265 rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
0266 rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1);
0267 rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1);
0268 if (rf23 == 0x0818 && rf24 == 0x070C)
0269 d_cut = 1;
0270
0271 wiphy_info(dev->wiphy, "RTL8225-SE version %s\n",
0272 d_cut ? "D" : "not-D");
0273
0274
0275 rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
0276 rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1);
0277 rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
0278 rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1);
0279 rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1);
0280 rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1);
0281 rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1);
0282 rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1);
0283 rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1);
0284 rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1);
0285 rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1);
0286 rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1);
0287 rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1);
0288 rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
0289 rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1);
0290 rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1);
0291
0292 rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
0293 rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1);
0294 rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1);
0295 rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1);
0296 rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1);
0297 rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1);
0298 rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
0299 rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1);
0300 rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1);
0301 rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1);
0302 if (d_cut)
0303 rtl8187se_rf_writereg(dev, 0x0E, 0x0807);
0304 else
0305 rtl8187se_rf_writereg(dev, 0x0E, 0x0806);
0306 mdelay(1);
0307 rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1);
0308 rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1);
0309 rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1);
0310 rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1);
0311
0312 rtl8187se_write_rf_gain(dev);
0313
0314 rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1);
0315 rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1);
0316 rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
0317 rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11);
0318 rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11);
0319 rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11);
0320 rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11);
0321 rtl8187se_rf_writereg(dev, 0x02, 0x088D); msleep(221);
0322 rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
0323 rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1);
0324 rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1);
0325 rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1);
0326 rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1);
0327 rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1);
0328 rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
0329 if (priv->xtal_cal) {
0330 tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) |
0331 (1 << 11) | (1 << 9);
0332 rtl8187se_rf_writereg(dev, 0x0F, tmp);
0333 wiphy_info(dev->wiphy, "Xtal cal\n");
0334 mdelay(1);
0335 } else {
0336 wiphy_info(dev->wiphy, "NO Xtal cal\n");
0337 rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC);
0338 mdelay(1);
0339 }
0340
0341 rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1);
0342 rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
0343 rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
0344 rtl8187se_rf_writereg(dev, 0x04, 0x0975); msleep(31);
0345 rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1);
0346 rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1);
0347
0348 rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
0349 rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1);
0350 rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1);
0351
0352
0353 rtl818x_iowrite8(priv, REG_ADDR1(0x024E),
0354 rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F);
0355 rtl8225se_write_phy_cck(dev, 0x00, 0xC8);
0356 rtl8225se_write_phy_cck(dev, 0x06, 0x1C);
0357 rtl8225se_write_phy_cck(dev, 0x10, 0x78);
0358 rtl8225se_write_phy_cck(dev, 0x2E, 0xD0);
0359 rtl8225se_write_phy_cck(dev, 0x2F, 0x06);
0360 rtl8225se_write_phy_cck(dev, 0x01, 0x46);
0361
0362
0363 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10);
0364 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B);
0365
0366 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
0367 rtl8225se_write_phy_ofdm(dev, 0x00, 0x12);
0368
0369 rtl8225se_write_zebra_agc(dev);
0370
0371 rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
0372
0373 rtl8187se_write_ofdm_config(dev);
0374
0375
0376 rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
0377 rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
0378
0379 rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
0380 rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
0381
0382 rtl8225se_write_phy_ofdm(dev, 0x10, 0x40);
0383 rtl8225se_write_phy_ofdm(dev, 0x12, 0x40);
0384
0385 rtl8187se_write_initial_gain(dev, 4);
0386 }
0387
0388 void rtl8225se_rf_stop(struct ieee80211_hw *dev)
0389 {
0390
0391 struct rtl8180_priv *priv = dev->priv;
0392
0393
0394 rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
0395 rtl8225se_write_phy_ofdm(dev, 0x12, 0x00);
0396
0397 rtl8187se_rf_writereg(dev, 0x04, 0x0000);
0398 rtl8187se_rf_writereg(dev, 0x00, 0x0000);
0399
0400 usleep_range(1000, 5000);
0401
0402 rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF);
0403 rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF);
0404 }
0405
0406 void rtl8225se_rf_set_channel(struct ieee80211_hw *dev,
0407 struct ieee80211_conf *conf)
0408 {
0409 int chan =
0410 ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
0411
0412 rtl8225sez2_rf_set_tx_power(dev, chan);
0413 rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
0414 if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) !=
0415 rtl8225se_chan[chan - 1])
0416 rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
0417 usleep_range(10000, 20000);
0418 }
0419
0420 static const struct rtl818x_rf_ops rtl8225se_ops = {
0421 .name = "rtl8225-se",
0422 .init = rtl8225se_rf_init,
0423 .stop = rtl8225se_rf_stop,
0424 .set_chan = rtl8225se_rf_set_channel,
0425 };
0426
0427 const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev)
0428 {
0429 return &rtl8225se_ops;
0430 }