rt2x00: rt2800lib: add rt2800_hw_beacon_base helper
[deliverable/linux.git] / drivers / net / wireless / rt2x00 / rt2800lib.c
index dedc3d4ae3659e7e525c71b710b0e22af98e9f10..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.
@@ -1850,6 +1882,43 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
        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,
@@ -2298,7 +2367,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-       /* TODO: frequency calibration? */
+       rt2800_adjust_freq_offset(rt2x00dev);
 
        if (conf_is_ht40(conf)) {
                txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
@@ -2467,19 +2536,6 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 
 #define POWER_BOUND            0x27
 #define POWER_BOUND_5G         0x2b
-#define FREQ_OFFSET_BOUND      0x5f
-
-static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
-{
-       u8 rfcsr;
-
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-       if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
-       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
-}
 
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
                                         struct ieee80211_conf *conf,
@@ -4780,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);
This page took 0.02959 seconds and 5 git commands to generate.