0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/pci.h>
0020 #include <linux/delay.h>
0021 #include <net/mac80211.h>
0022
0023 #include "rtl8180.h"
0024 #include "sa2400.h"
0025
0026 static const u32 sa2400_chan[] = {
0027 0x00096c,
0028 0x080970,
0029 0x100974,
0030 0x180978,
0031 0x000980,
0032 0x080984,
0033 0x100988,
0034 0x18098c,
0035 0x000994,
0036 0x080998,
0037 0x10099c,
0038 0x1809a0,
0039 0x0009a8,
0040 0x0009b4,
0041 };
0042
0043 static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data)
0044 {
0045 struct rtl8180_priv *priv = dev->priv;
0046 u32 phy_config;
0047
0048
0049 phy_config = 0xb0000000;
0050
0051 phy_config |= ((u32)(addr & 0xf)) << 24;
0052 phy_config |= data & 0xffffff;
0053
0054 rtl818x_iowrite32(priv,
0055 (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
0056
0057 msleep(3);
0058 }
0059
0060 static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)
0061 {
0062 struct rtl8180_priv *priv = dev->priv;
0063 u8 ant = SA2400_ANTENNA;
0064
0065 if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
0066 ant |= BB_ANTENNA_B;
0067
0068 if (chan == 14)
0069 ant |= BB_ANTATTEN_CHAN14;
0070
0071 rtl8180_write_phy(dev, 0x10, ant);
0072
0073 }
0074
0075 static u8 sa2400_rf_rssi_map[] = {
0076 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e,
0077 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50,
0078 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f,
0079 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b,
0080 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17,
0081 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13,
0082 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f,
0083 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
0084 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
0085 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02,
0086 };
0087
0088 static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq)
0089 {
0090 if (sq == 0x80)
0091 return 1;
0092
0093 if (sq > 78)
0094 return 32;
0095
0096
0097 return 65 * sa2400_rf_rssi_map[sq] / 100;
0098 }
0099
0100 static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
0101 struct ieee80211_conf *conf)
0102 {
0103 struct rtl8180_priv *priv = dev->priv;
0104 int channel =
0105 ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
0106 u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
0107 u32 chan = sa2400_chan[channel - 1];
0108
0109 write_sa2400(dev, 7, txpw);
0110
0111 sa2400_write_phy_antenna(dev, channel);
0112
0113 write_sa2400(dev, 0, chan);
0114 write_sa2400(dev, 1, 0xbb50);
0115 write_sa2400(dev, 2, 0x80);
0116 write_sa2400(dev, 3, 0);
0117 }
0118
0119 static void sa2400_rf_stop(struct ieee80211_hw *dev)
0120 {
0121 write_sa2400(dev, 4, 0);
0122 }
0123
0124 static void sa2400_rf_init(struct ieee80211_hw *dev)
0125 {
0126 struct rtl8180_priv *priv = dev->priv;
0127 u32 anaparam, txconf;
0128 u8 firdac;
0129 int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY;
0130
0131 anaparam = priv->anaparam;
0132 anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT);
0133 anaparam &= ~ANAPARAM_PWR1_MASK;
0134 anaparam &= ~ANAPARAM_PWR0_MASK;
0135
0136 if (analogphy) {
0137 anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT;
0138 firdac = 0;
0139 } else {
0140 anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT);
0141 anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT);
0142 firdac = 1 << SA2400_REG4_FIRDAC_SHIFT;
0143 }
0144
0145 rtl8180_set_anaparam(priv, anaparam);
0146
0147 write_sa2400(dev, 0, sa2400_chan[0]);
0148 write_sa2400(dev, 1, 0xbb50);
0149 write_sa2400(dev, 2, 0x80);
0150 write_sa2400(dev, 3, 0);
0151 write_sa2400(dev, 4, 0x19340 | firdac);
0152 write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15);
0153 write_sa2400(dev, 4, 0x19348 | firdac);
0154
0155 if (!analogphy)
0156 write_sa2400(dev, 4, 0x1938c);
0157
0158 write_sa2400(dev, 4, 0x19340 | firdac);
0159
0160 write_sa2400(dev, 0, sa2400_chan[0]);
0161 write_sa2400(dev, 1, 0xbb50);
0162 write_sa2400(dev, 2, 0x80);
0163 write_sa2400(dev, 3, 0);
0164 write_sa2400(dev, 4, 0x19344 | firdac);
0165
0166
0167 write_sa2400(dev, 6, 0x13ff | (1 << 23));
0168 write_sa2400(dev, 8, 0);
0169
0170 if (analogphy) {
0171 rtl8180_set_anaparam(priv, anaparam |
0172 (1 << ANAPARAM_TXDACOFF_SHIFT));
0173
0174 txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF);
0175 rtl818x_iowrite32(priv, &priv->map->TX_CONF,
0176 txconf | RTL818X_TX_CONF_LOOPBACK_CONT);
0177
0178 write_sa2400(dev, 4, 0x19341);
0179
0180
0181
0182 write_sa2400(dev, 4, 0x19345);
0183
0184
0185
0186
0187 rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf);
0188
0189 rtl8180_set_anaparam(priv, anaparam);
0190 }
0191
0192
0193 write_sa2400(dev, 4, 0x19341 | firdac);
0194
0195
0196 rtl8180_write_phy(dev, 0, 0x98);
0197 rtl8180_write_phy(dev, 3, 0x38);
0198 rtl8180_write_phy(dev, 4, 0xe0);
0199 rtl8180_write_phy(dev, 5, 0x90);
0200 rtl8180_write_phy(dev, 6, 0x1a);
0201 rtl8180_write_phy(dev, 7, 0x64);
0202
0203 sa2400_write_phy_antenna(dev, 1);
0204
0205 rtl8180_write_phy(dev, 0x11, 0x80);
0206
0207 if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
0208 RTL818X_CONFIG2_ANTENNA_DIV)
0209 rtl8180_write_phy(dev, 0x12, 0xc7);
0210 else
0211 rtl8180_write_phy(dev, 0x12, 0x47);
0212
0213 rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
0214
0215 rtl8180_write_phy(dev, 0x19, 0x0);
0216 rtl8180_write_phy(dev, 0x1a, 0xa0);
0217 }
0218
0219 const struct rtl818x_rf_ops sa2400_rf_ops = {
0220 .name = "Philips",
0221 .init = sa2400_rf_init,
0222 .stop = sa2400_rf_stop,
0223 .set_chan = sa2400_rf_set_channel,
0224 .calc_rssi = sa2400_rf_calc_rssi,
0225 };