rt2x00: rt2800lib: add rt2800_hw_beacon_base helper
[deliverable/linux.git] / drivers / net / wireless / rt2x00 / rt2800lib.c
index 1738a9d232c398ec56b9fa6d3994a6a48b759d57..38606e2f8a52329e53b15467753df6b41215b0d5 100644 (file)
@@ -521,6 +521,29 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_disable_wpdma);
 
+void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
+                              unsigned short *txwi_size,
+                              unsigned short *rxwi_size)
+{
+       switch (rt2x00dev->chip.rt) {
+       case RT3593:
+               *txwi_size = TXWI_DESC_SIZE_4WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_5WORDS;
+               break;
+
+       case RT5592:
+               *txwi_size = TXWI_DESC_SIZE_5WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_6WORDS;
+               break;
+
+       default:
+               *txwi_size = TXWI_DESC_SIZE_4WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_4WORDS;
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size);
+
 static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)
 {
        u16 fw_crc;
@@ -917,6 +940,12 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
+static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+                                         unsigned int index)
+{
+       return HW_BEACON_BASE(index);
+}
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -969,7 +998,8 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
                return;
        }
 
-       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
+
        rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
                                   entry->skb->len + padding_len);
 
@@ -988,10 +1018,13 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 
 static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
-                                               unsigned int beacon_base)
+                                               unsigned int index)
 {
        int i;
        const int txwi_desc_size = rt2x00dev->bcn->winfo_size;
+       unsigned int beacon_base;
+
+       beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 
        /*
         * For the Beacon base registers we only need to clear
@@ -1018,8 +1051,7 @@ void rt2800_clear_beacon(struct queue_entry *entry)
        /*
         * Clear beacon.
         */
-       rt2800_clear_beacon_register(rt2x00dev,
-                                    HW_BEACON_OFFSET(entry->entry_idx));
+       rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
 
        /*
         * Enabled beaconing again.
@@ -1826,16 +1858,67 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
                rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
                lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
        } else if (libconf->rf.channel <= 128) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
-               lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
+               if (rt2x00_rt(rt2x00dev, RT3593)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_EXT_LNA2_A1);
+               } else {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_RSSI_BG2_LNA_A1);
+               }
        } else {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
-               lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
+               if (rt2x00_rt(rt2x00dev, RT3593)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_EXT_LNA2_A2);
+               } else {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_RSSI_A2_LNA_A2);
+               }
        }
 
        rt2x00dev->lna_gain = lna_gain;
 }
 
+#define FREQ_OFFSET_BOUND      0x5f
+
+static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
+{
+       u8 freq_offset, prev_freq_offset;
+       u8 rfcsr, prev_rfcsr;
+
+       freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
+       freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
+
+       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       prev_rfcsr = rfcsr;
+
+       rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
+       if (rfcsr == prev_rfcsr)
+               return;
+
+       if (rt2x00_is_usb(rt2x00dev)) {
+               rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
+                                  freq_offset, prev_rfcsr);
+               return;
+       }
+
+       prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
+       while (prev_freq_offset != freq_offset) {
+               if (prev_freq_offset < freq_offset)
+                       prev_freq_offset++;
+               else
+                       prev_freq_offset--;
+
+               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
+               rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+               usleep_range(1000, 1500);
+       }
+}
+
 static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
                                         struct ieee80211_conf *conf,
                                         struct rf_channel *rf,
@@ -2154,22 +2237,306 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
-#define POWER_BOUND            0x27
-#define POWER_BOUND_5G         0x2b
-#define FREQ_OFFSET_BOUND      0x5f
-
-static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
+static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
 {
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 txrx_agc_fc;
+       u8 txrx_h20m;
        u8 rfcsr;
+       u8 bbp;
+       const bool txbf_enabled = false; /* TODO */
 
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-       if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
+       /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
+       rt2800_bbp_read(rt2x00dev, 109, &bbp);
+       rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
+       rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
+       rt2800_bbp_write(rt2x00dev, 109, bbp);
+
+       rt2800_bbp_read(rt2x00dev, 110, &bbp);
+       rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
+       rt2800_bbp_write(rt2x00dev, 110, bbp);
+
+       if (rf->channel <= 14) {
+               /* Restore BBP 25 & 26 for 2.4 GHz */
+               rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
+               rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
+       } else {
+               /* Hard code BBP 25 & 26 for 5GHz */
+
+               /* Enable IQ Phase correction */
+               rt2800_bbp_write(rt2x00dev, 25, 0x09);
+               /* Setup IQ Phase correction value */
+               rt2800_bbp_write(rt2x00dev, 26, 0xff);
+       }
+
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
+
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
        else
-               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
-       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+                                 info->default_power1 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+                                 ((info->default_power1 & 0x18) << 1) |
+                                 (info->default_power1 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+                                 info->default_power2 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+                                 ((info->default_power2 & 0x18) << 1) |
+                                 (info->default_power2 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+                                 info->default_power3 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+                                 ((info->default_power3 & 0x18) << 1) |
+                                 (info->default_power3 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+       switch (rt2x00dev->default_ant.tx_chain_num) {
+       case 3:
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+               /* fallthrough */
+       case 2:
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+               /* fallthrough */
+       case 1:
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+               break;
+       }
+
+       switch (rt2x00dev->default_ant.rx_chain_num) {
+       case 3:
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+               /* fallthrough */
+       case 2:
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+               /* fallthrough */
+       case 1:
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+               break;
+       }
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       if (conf_is_ht40(conf)) {
+               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
+                                               RFCSR24_TX_AGC_FC);
+               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40,
+                                             RFCSR24_TX_H20M);
+       } else {
+               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20,
+                                               RFCSR24_TX_AGC_FC);
+               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20,
+                                             RFCSR24_TX_H20M);
+       }
+
+       /* NOTE: the reference driver does not writes the new value
+        * back to RFCSR 32
+        */
+       rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
+
+       if (rf->channel <= 14)
+               rfcsr = 0xa0;
+       else
+               rfcsr = 0x80;
+       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+       /* Band selection */
+       rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
+       rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
+       if (rf->channel <= 14)
+               rfcsr = 0x3c;
+       else
+               rfcsr = 0x20;
+       rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       if (rf->channel <= 14)
+               rfcsr = 0x1a;
+       else
+               rfcsr = 0x12;
+       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       if (rf->channel >= 1 && rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+       else if (rf->channel >= 36 && rf->channel <= 64)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+       else if (rf->channel >= 100 && rf->channel <= 128)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+       rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xd8);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
+       }
+
+       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
+       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4);
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2);
+       }
+       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2);
+
+       if (txbf_enabled)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1);
+
+       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 57, rfcsr);
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+               rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
+               rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+       }
+
+       /* Initiate VCO calibration */
+       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+       }
+       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+       if (rf->channel >= 1 && rf->channel <= 14) {
+               rfcsr = 0x23;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+       } else if (rf->channel >= 36 && rf->channel <= 64) {
+               rfcsr = 0x36;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, 0x36);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xeb);
+       } else if (rf->channel >= 100 && rf->channel <= 128) {
+               rfcsr = 0x32;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xb3);
+       } else {
+               rfcsr = 0x30;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0x9b);
+       }
 }
 
+#define POWER_BOUND            0x27
+#define POWER_BOUND_5G         0x2b
+
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
                                         struct ieee80211_conf *conf,
                                         struct rf_channel *rf,
@@ -2728,8 +3095,15 @@ static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev,
                                  unsigned int channel,
                                  char txpower)
 {
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
+
        if (channel <= 14)
                return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
+                              MAX_A_TXPOWER_3593);
        else
                return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
 }
@@ -2747,6 +3121,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                                                     info->default_power1);
        info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
                                                     info->default_power2);
+       if (rt2x00dev->default_ant.tx_chain_num > 2)
+               info->default_power3 =
+                       rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+                                             info->default_power3);
 
        switch (rt2x00dev->chip.rf) {
        case RF2020:
@@ -2759,6 +3137,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        case RF3052:
                rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
                break;
+       case RF3053:
+               rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info);
+               break;
        case RF3290:
                rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
                break;
@@ -2804,6 +3185,23 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
                rt2800_bbp_write(rt2x00dev, 27, 0x20);
                rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rf->channel > 14) {
+                       /* Disable CCK Packet detection on 5GHz */
+                       rt2800_bbp_write(rt2x00dev, 70, 0x00);
+               } else {
+                       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+               }
+
+               if (conf_is_ht40(conf))
+                       rt2800_bbp_write(rt2x00dev, 105, 0x04);
+               else
+                       rt2800_bbp_write(rt2x00dev, 105, 0x34);
+
+               rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 77, 0x98);
        } else {
                rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
                rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
@@ -2819,16 +3217,27 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                                rt2800_bbp_write(rt2x00dev, 82, 0x62);
                                rt2800_bbp_write(rt2x00dev, 75, 0x46);
                        } else {
-                               rt2800_bbp_write(rt2x00dev, 82, 0x84);
+                               if (rt2x00_rt(rt2x00dev, RT3593))
+                                       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+                               else
+                                       rt2800_bbp_write(rt2x00dev, 82, 0x84);
                                rt2800_bbp_write(rt2x00dev, 75, 0x50);
                        }
+                       if (rt2x00_rt(rt2x00dev, RT3593))
+                               rt2800_bbp_write(rt2x00dev, 83, 0x8a);
                }
+
        } else {
                if (rt2x00_rt(rt2x00dev, RT3572))
                        rt2800_bbp_write(rt2x00dev, 82, 0x94);
+               else if (rt2x00_rt(rt2x00dev, RT3593))
+                       rt2800_bbp_write(rt2x00dev, 82, 0x82);
                else
                        rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
+               if (rt2x00_rt(rt2x00dev, RT3593))
+                       rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+
                if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
                        rt2800_bbp_write(rt2x00dev, 75, 0x46);
                else
@@ -2899,6 +3308,41 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        if (rt2x00_rt(rt2x00dev, RT3572))
                rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
 
+       if (rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rt2x00_is_usb(rt2x00dev)) {
+                       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+
+                       /* Band selection. GPIO #8 controls all paths */
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR8, 0);
+                       if (rf->channel <= 14)
+                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 1);
+                       else
+                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 0);
+
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
+
+                       /* LNA PE control.
+                       * GPIO #4 controls PE0 and PE1,
+                       * GPIO #7 controls PE2
+                       */
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
+
+                       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+               }
+
+               /* AGC init */
+               if (rf->channel <= 14)
+                       reg = 0x1c + 2 * rt2x00dev->lna_gain;
+               else
+                       reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3);
+
+               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
+               usleep_range(1000, 1500);
+       }
+
        if (rt2x00_rt(rt2x00dev, RT5592)) {
                rt2800_bbp_write(rt2x00dev, 195, 141);
                rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
@@ -3806,6 +4250,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
                rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
                rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
                break;
+       case RF3053:
        case RF3290:
        case RF5360:
        case RF5370:
@@ -4391,14 +4836,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * Clear all beacons
         */
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6);
-       rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7);
+       for (i = 0; i < 8; i++)
+               rt2800_clear_beacon_register(rt2x00dev, i);
 
        if (rt2x00_is_usb(rt2x00dev)) {
                rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
@@ -5858,6 +6297,7 @@ static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
 
        /* FIXME: BBP 105 owerwrite? */
        rt2800_bbp_write(rt2x00dev, 105, 0x04);
+
 }
 
 static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
@@ -6354,6 +6794,34 @@ int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
 
+static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return 0;
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+       if ((word & 0x00ff) != 0x00ff)
+               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
+
+       return 0;
+}
+
+static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return 0;
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+       if ((word & 0x00ff) != 0x00ff)
+               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
+
+       return 0;
+}
+
 static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 {
        struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -6448,30 +6916,20 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
        rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
-       if ((word & 0x00ff) != 0x00ff) {
-               drv_data->txmixer_gain_24g =
-                       rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
-       } else {
-               drv_data->txmixer_gain_24g = 0;
-       }
+       drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
 
        rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
-       if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
-           rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
-               rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
-                                  default_lna_gain);
+       if (!rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+                   rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+                                          default_lna_gain);
+       }
        rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
-       if ((word & 0x00ff) != 0x00ff) {
-               drv_data->txmixer_gain_5g =
-                       rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
-       } else {
-               drv_data->txmixer_gain_5g = 0;
-       }
+       drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
 
        rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
@@ -6483,12 +6941,27 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
-       if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
-           rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
-               rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
-                                  default_lna_gain);
+       if (!rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+                   rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+                                          default_lna_gain);
+       }
        rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 
+       if (rt2x00_rt(rt2x00dev, RT3593)) {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
+               if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
+                   rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
+                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+                                          default_lna_gain);
+               if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 ||
+                   rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff)
+                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+                                          default_lna_gain);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word);
+       }
+
        return 0;
 }
 
@@ -6525,6 +6998,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        case RF3021:
        case RF3022:
        case RF3052:
+       case RF3053:
        case RF3290:
        case RF3320:
        case RF3322:
@@ -6903,12 +7377,79 @@ static const struct rf_channel rf_vals_5592_xtal40[] = {
        {196, 83, 0, 12, 1},
 };
 
+static const struct rf_channel rf_vals_3053[] = {
+       /* Channel, N, R, K */
+       {1, 241, 2, 2},
+       {2, 241, 2, 7},
+       {3, 242, 2, 2},
+       {4, 242, 2, 7},
+       {5, 243, 2, 2},
+       {6, 243, 2, 7},
+       {7, 244, 2, 2},
+       {8, 244, 2, 7},
+       {9, 245, 2, 2},
+       {10, 245, 2, 7},
+       {11, 246, 2, 2},
+       {12, 246, 2, 7},
+       {13, 247, 2, 2},
+       {14, 248, 2, 4},
+
+       {36, 0x56, 0, 4},
+       {38, 0x56, 0, 6},
+       {40, 0x56, 0, 8},
+       {44, 0x57, 0, 0},
+       {46, 0x57, 0, 2},
+       {48, 0x57, 0, 4},
+       {52, 0x57, 0, 8},
+       {54, 0x57, 0, 10},
+       {56, 0x58, 0, 0},
+       {60, 0x58, 0, 4},
+       {62, 0x58, 0, 6},
+       {64, 0x58, 0, 8},
+
+       {100, 0x5B, 0, 8},
+       {102, 0x5B, 0, 10},
+       {104, 0x5C, 0, 0},
+       {108, 0x5C, 0, 4},
+       {110, 0x5C, 0, 6},
+       {112, 0x5C, 0, 8},
+
+       /* NOTE: Channel 114 has been removed intentionally.
+        * The EEPROM contains no TX power values for that,
+        * and it is disabled in the vendor driver as well.
+        */
+
+       {116, 0x5D, 0, 0},
+       {118, 0x5D, 0, 2},
+       {120, 0x5D, 0, 4},
+       {124, 0x5D, 0, 8},
+       {126, 0x5D, 0, 10},
+       {128, 0x5E, 0, 0},
+       {132, 0x5E, 0, 4},
+       {134, 0x5E, 0, 6},
+       {136, 0x5E, 0, 8},
+       {140, 0x5F, 0, 0},
+
+       {149, 0x5F, 0, 9},
+       {151, 0x5F, 0, 11},
+       {153, 0x60, 0, 1},
+       {157, 0x60, 0, 5},
+       {159, 0x60, 0, 7},
+       {161, 0x60, 0, 9},
+       {165, 0x61, 0, 1},
+       {167, 0x61, 0, 3},
+       {169, 0x61, 0, 5},
+       {171, 0x61, 0, 7},
+       {173, 0x61, 0, 9},
+};
+
 static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
        struct hw_mode_spec *spec = &rt2x00dev->spec;
        struct channel_info *info;
        char *default_power1;
        char *default_power2;
+       char *default_power3;
        unsigned int i;
        u16 eeprom;
        u32 reg;
@@ -6993,6 +7534,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                spec->supported_bands |= SUPPORT_BAND_5GHZ;
                spec->num_channels = ARRAY_SIZE(rf_vals_3x);
                spec->channels = rf_vals_3x;
+       } else if (rt2x00_rf(rt2x00dev, RF3053)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_3053);
+               spec->channels = rf_vals_3053;
        } else if (rt2x00_rf(rt2x00dev, RF5592)) {
                spec->supported_bands |= SUPPORT_BAND_5GHZ;
 
@@ -7061,9 +7606,17 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
        default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
 
+       if (rt2x00dev->default_ant.tx_chain_num > 2)
+               default_power3 = rt2800_eeprom_addr(rt2x00dev,
+                                                   EEPROM_EXT_TXPOWER_BG3);
+       else
+               default_power3 = NULL;
+
        for (i = 0; i < 14; i++) {
                info[i].default_power1 = default_power1[i];
                info[i].default_power2 = default_power2[i];
+               if (default_power3)
+                       info[i].default_power3 = default_power3[i];
        }
 
        if (spec->num_channels > 14) {
@@ -7072,9 +7625,18 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                default_power2 = rt2800_eeprom_addr(rt2x00dev,
                                                    EEPROM_TXPOWER_A2);
 
+               if (rt2x00dev->default_ant.tx_chain_num > 2)
+                       default_power3 =
+                               rt2800_eeprom_addr(rt2x00dev,
+                                                  EEPROM_EXT_TXPOWER_A3);
+               else
+                       default_power3 = NULL;
+
                for (i = 14; i < spec->num_channels; i++) {
                        info[i].default_power1 = default_power1[i - 14];
                        info[i].default_power2 = default_power2[i - 14];
+                       if (default_power3)
+                               info[i].default_power3 = default_power3[i - 14];
                }
        }
 
@@ -7085,6 +7647,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        case RF3022:
        case RF3320:
        case RF3052:
+       case RF3053:
        case RF3290:
        case RF5360:
        case RF5370:
@@ -7123,6 +7686,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
        case RT3352:
        case RT3390:
        case RT3572:
+       case RT3593:
        case RT5390:
        case RT5392:
        case RT5592:
This page took 0.048371 seconds and 5 git commands to generate.