mirror of
https://github.com/ipxe/ipxe
synced 2025-12-08 10:20:24 +03:00
committed by
Michael Brown
parent
c28053027b
commit
aaf7a35207
@@ -68,7 +68,9 @@ SRCDIRS += drivers/net/igb
|
||||
SRCDIRS += drivers/net/igbvf
|
||||
SRCDIRS += drivers/net/phantom
|
||||
SRCDIRS += drivers/net/rtl818x
|
||||
SRCDIRS += drivers/net/ath5k
|
||||
SRCDIRS += drivers/net/ath
|
||||
SRCDIRS += drivers/net/ath/ath5k
|
||||
SRCDIRS += drivers/net/ath/ath9k
|
||||
SRCDIRS += drivers/net/vxge
|
||||
SRCDIRS += drivers/net/efi
|
||||
SRCDIRS += drivers/block
|
||||
|
||||
239
src/drivers/net/ath/ath.h
Normal file
239
src/drivers/net/ath/ath.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH_H
|
||||
#define ATH_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ipxe/net80211.h>
|
||||
|
||||
/* This block of functions are from kernel.h v3.0.1 */
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||
#define BITS_PER_BYTE 8
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
||||
#define min(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
typeof(y) _min2 = (y); \
|
||||
(void) (&_min1 == &_min2); \
|
||||
_min1 < _min2 ? _min1 : _min2; })
|
||||
#define max(x, y) ({ \
|
||||
typeof(x) _max1 = (x); \
|
||||
typeof(y) _max2 = (y); \
|
||||
(void) (&_max1 == &_max2); \
|
||||
_max1 > _max2 ? _max1 : _max2; })
|
||||
#define abs(x) ({ \
|
||||
long ret; \
|
||||
if (sizeof(x) == sizeof(long)) { \
|
||||
long __x = (x); \
|
||||
ret = (__x < 0) ? -__x : __x; \
|
||||
} else { \
|
||||
int __x = (x); \
|
||||
ret = (__x < 0) ? -__x : __x; \
|
||||
} \
|
||||
ret; \
|
||||
})
|
||||
|
||||
#define ___constant_swab16(x) ((uint16_t)( \
|
||||
(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
|
||||
(((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
|
||||
#define ___constant_swab32(x) ((uint32_t)( \
|
||||
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
|
||||
#define __swab16(x) ___constant_swab16(x)
|
||||
#define __swab32(x) ___constant_swab32(x)
|
||||
#define swab16 __swab16
|
||||
#define swab32 __swab32
|
||||
|
||||
static inline int32_t sign_extend32(uint32_t value, int index)
|
||||
{
|
||||
uint8_t shift = 31 - index;
|
||||
return (int32_t)(value << shift) >> shift;
|
||||
}
|
||||
|
||||
static inline u16 __get_unaligned_le16(const u8 *p)
|
||||
{
|
||||
return p[0] | p[1] << 8;
|
||||
}
|
||||
static inline u32 __get_unaligned_le32(const u8 *p)
|
||||
{
|
||||
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
|
||||
}
|
||||
static inline u16 get_unaligned_le16(const void *p)
|
||||
{
|
||||
return __get_unaligned_le16((const u8 *)p);
|
||||
}
|
||||
static inline u32 get_unaligned_le32(const void *p)
|
||||
{
|
||||
return __get_unaligned_le32((const u8 *)p);
|
||||
}
|
||||
/* End Kernel Block */
|
||||
|
||||
/*
|
||||
* The key cache is used for h/w cipher state and also for
|
||||
* tracking station state such as the current tx antenna.
|
||||
* We also setup a mapping table between key cache slot indices
|
||||
* and station state to short-circuit node lookups on rx.
|
||||
* Different parts have different size key caches. We handle
|
||||
* up to ATH_KEYMAX entries (could dynamically allocate state).
|
||||
*/
|
||||
#define ATH_KEYMAX 128 /* max key cache size we handle */
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
struct ath_ani {
|
||||
int caldone;
|
||||
unsigned int longcal_timer;
|
||||
unsigned int shortcal_timer;
|
||||
unsigned int resetcal_timer;
|
||||
unsigned int checkani_timer;
|
||||
int timer;
|
||||
};
|
||||
|
||||
struct ath_cycle_counters {
|
||||
u32 cycles;
|
||||
u32 rx_busy;
|
||||
u32 rx_frame;
|
||||
u32 tx_frame;
|
||||
};
|
||||
|
||||
enum ath_device_state {
|
||||
ATH_HW_UNAVAILABLE,
|
||||
ATH_HW_INITIALIZED,
|
||||
};
|
||||
|
||||
enum ath_bus_type {
|
||||
ATH_PCI,
|
||||
ATH_AHB,
|
||||
ATH_USB,
|
||||
};
|
||||
|
||||
struct reg_dmn_pair_mapping {
|
||||
u16 regDmnEnum;
|
||||
u16 reg_5ghz_ctl;
|
||||
u16 reg_2ghz_ctl;
|
||||
};
|
||||
|
||||
struct ath_regulatory {
|
||||
char alpha2[2];
|
||||
u16 country_code;
|
||||
u16 max_power_level;
|
||||
u32 tp_scale;
|
||||
u16 current_rd;
|
||||
u16 current_rd_ext;
|
||||
int16_t power_limit;
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
};
|
||||
|
||||
enum ath_crypt_caps {
|
||||
ATH_CRYPT_CAP_CIPHER_AESCCM = BIT(0),
|
||||
ATH_CRYPT_CAP_MIC_COMBINED = BIT(1),
|
||||
};
|
||||
|
||||
struct ath_keyval {
|
||||
u8 kv_type;
|
||||
u8 kv_pad;
|
||||
u16 kv_len;
|
||||
u8 kv_val[16]; /* TK */
|
||||
u8 kv_mic[8]; /* Michael MIC key */
|
||||
u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
|
||||
* supports both MIC keys in the same key cache entry;
|
||||
* in that case, kv_mic is the RX key) */
|
||||
};
|
||||
|
||||
enum ath_cipher {
|
||||
ATH_CIPHER_WEP = 0,
|
||||
ATH_CIPHER_AES_OCB = 1,
|
||||
ATH_CIPHER_AES_CCM = 2,
|
||||
ATH_CIPHER_CKIP = 3,
|
||||
ATH_CIPHER_TKIP = 4,
|
||||
ATH_CIPHER_CLR = 5,
|
||||
ATH_CIPHER_MIC = 127
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_ops - Register read/write operations
|
||||
*
|
||||
* @read: Register read
|
||||
* @multi_read: Multiple register read
|
||||
* @write: Register write
|
||||
* @enable_write_buffer: Enable multiple register writes
|
||||
* @write_flush: flush buffered register writes and disable buffering
|
||||
*/
|
||||
struct ath_ops {
|
||||
unsigned int (*read)(void *, u32 reg_offset);
|
||||
void (*multi_read)(void *, u32 *addr, u32 *val, u16 count);
|
||||
void (*write)(void *, u32 val, u32 reg_offset);
|
||||
void (*enable_write_buffer)(void *);
|
||||
void (*write_flush) (void *);
|
||||
u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr);
|
||||
};
|
||||
|
||||
struct ath_common;
|
||||
struct ath_bus_ops;
|
||||
|
||||
struct ath_common {
|
||||
void *ah;
|
||||
void *priv;
|
||||
struct net80211_device *dev;
|
||||
int debug_mask;
|
||||
enum ath_device_state state;
|
||||
|
||||
struct ath_ani ani;
|
||||
|
||||
u16 cachelsz;
|
||||
u16 curaid;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
u8 curbssid[ETH_ALEN];
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
|
||||
u8 tx_chainmask;
|
||||
u8 rx_chainmask;
|
||||
|
||||
u32 rx_bufsize;
|
||||
|
||||
u32 keymax;
|
||||
enum ath_crypt_caps crypt_caps;
|
||||
|
||||
unsigned int clockrate;
|
||||
|
||||
struct ath_cycle_counters cc_ani;
|
||||
struct ath_cycle_counters cc_survey;
|
||||
|
||||
struct ath_regulatory regulatory;
|
||||
const struct ath_ops *ops;
|
||||
const struct ath_bus_ops *bus_ops;
|
||||
|
||||
int btcoex_enabled;
|
||||
};
|
||||
|
||||
struct io_buffer *ath_rxbuf_alloc(struct ath_common *common,
|
||||
u32 len,
|
||||
u32 *iob_addr);
|
||||
|
||||
void ath_hw_setbssidmask(struct ath_common *common);
|
||||
int ath_hw_keyreset(struct ath_common *common, u16 entry);
|
||||
void ath_hw_cycle_counters_update(struct ath_common *common);
|
||||
int32_t ath_hw_get_listen_time(struct ath_common *common);
|
||||
|
||||
#endif /* ATH_H */
|
||||
168
src/drivers/net/ath/ath9k/ani.h
Normal file
168
src/drivers/net/ath/ath9k/ani.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ANI_H
|
||||
#define ANI_H
|
||||
|
||||
#define HAL_PROCESS_ANI 0x00000001
|
||||
|
||||
#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
|
||||
|
||||
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
|
||||
#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
|
||||
#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
|
||||
|
||||
#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
|
||||
#define ATH9K_ANI_USE_OFDM_WEAK_SIG 1
|
||||
#define ATH9K_ANI_CCK_WEAK_SIG_THR 0
|
||||
|
||||
#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
|
||||
#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
|
||||
|
||||
#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
|
||||
#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
|
||||
|
||||
#define ATH9K_ANI_RSSI_THR_HIGH 40
|
||||
#define ATH9K_ANI_RSSI_THR_LOW 7
|
||||
|
||||
#define ATH9K_ANI_PERIOD_OLD 100
|
||||
#define ATH9K_ANI_PERIOD_NEW 1000
|
||||
|
||||
/* in ms */
|
||||
#define ATH9K_ANI_POLLINTERVAL_OLD 100
|
||||
#define ATH9K_ANI_POLLINTERVAL_NEW 1000
|
||||
|
||||
#define HAL_NOISE_IMMUNE_MAX 4
|
||||
#define HAL_SPUR_IMMUNE_MAX 7
|
||||
#define HAL_FIRST_STEP_MAX 2
|
||||
|
||||
#define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
|
||||
#define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
|
||||
#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
|
||||
#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
|
||||
|
||||
#define ATH9K_ANI_ENABLE_MRC_CCK 1
|
||||
|
||||
/* values here are relative to the INI */
|
||||
|
||||
enum ath9k_ani_cmd {
|
||||
ATH9K_ANI_PRESENT = 0x1,
|
||||
ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
|
||||
ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
|
||||
ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
|
||||
ATH9K_ANI_MODE = 0x40,
|
||||
ATH9K_ANI_PHYERR_RESET = 0x80,
|
||||
ATH9K_ANI_MRC_CCK = 0x100,
|
||||
ATH9K_ANI_ALL = 0xfff
|
||||
};
|
||||
|
||||
struct ath9k_mib_stats {
|
||||
u32 ackrcv_bad;
|
||||
u32 rts_bad;
|
||||
u32 rts_good;
|
||||
u32 fcs_bad;
|
||||
u32 beacons;
|
||||
};
|
||||
|
||||
/* INI default values for ANI registers */
|
||||
struct ath9k_ani_default {
|
||||
u16 m1ThreshLow;
|
||||
u16 m2ThreshLow;
|
||||
u16 m1Thresh;
|
||||
u16 m2Thresh;
|
||||
u16 m2CountThr;
|
||||
u16 m2CountThrLow;
|
||||
u16 m1ThreshLowExt;
|
||||
u16 m2ThreshLowExt;
|
||||
u16 m1ThreshExt;
|
||||
u16 m2ThreshExt;
|
||||
u16 firstep;
|
||||
u16 firstepLow;
|
||||
u16 cycpwrThr1;
|
||||
u16 cycpwrThr1Ext;
|
||||
};
|
||||
|
||||
struct ar5416AniState {
|
||||
struct ath9k_channel *c;
|
||||
u8 noiseImmunityLevel;
|
||||
u8 ofdmNoiseImmunityLevel;
|
||||
u8 cckNoiseImmunityLevel;
|
||||
int ofdmsTurn;
|
||||
u8 mrcCCKOff;
|
||||
u8 spurImmunityLevel;
|
||||
u8 firstepLevel;
|
||||
u8 ofdmWeakSigDetectOff;
|
||||
u8 cckWeakSigThreshold;
|
||||
u32 listenTime;
|
||||
int32_t rssiThrLow;
|
||||
int32_t rssiThrHigh;
|
||||
u32 noiseFloor;
|
||||
u32 ofdmPhyErrCount;
|
||||
u32 cckPhyErrCount;
|
||||
int16_t pktRssi[2];
|
||||
int16_t ofdmErrRssi[2];
|
||||
int16_t cckErrRssi[2];
|
||||
struct ath9k_ani_default iniDef;
|
||||
};
|
||||
|
||||
struct ar5416Stats {
|
||||
u32 ast_ani_niup;
|
||||
u32 ast_ani_nidown;
|
||||
u32 ast_ani_spurup;
|
||||
u32 ast_ani_spurdown;
|
||||
u32 ast_ani_ofdmon;
|
||||
u32 ast_ani_ofdmoff;
|
||||
u32 ast_ani_cckhigh;
|
||||
u32 ast_ani_ccklow;
|
||||
u32 ast_ani_stepup;
|
||||
u32 ast_ani_stepdown;
|
||||
u32 ast_ani_ofdmerrs;
|
||||
u32 ast_ani_cckerrs;
|
||||
u32 ast_ani_reset;
|
||||
u32 ast_ani_lzero;
|
||||
u32 ast_ani_lneg;
|
||||
u32 avgbrssi;
|
||||
struct ath9k_mib_stats ast_mibstats;
|
||||
};
|
||||
#define ah_mibStats stats.ast_mibstats
|
||||
|
||||
void ath9k_enable_mib_counters(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
||||
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
|
||||
#endif /* ANI_H */
|
||||
672
src/drivers/net/ath/ath9k/ar5008_initvals.h
Normal file
672
src/drivers/net/ath/ath9k/ar5008_initvals.h
Normal file
@@ -0,0 +1,672 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
static const u32 ar5416Modes[][6] = {
|
||||
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
|
||||
{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
|
||||
{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
|
||||
{0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
|
||||
{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
|
||||
{0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
|
||||
{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
|
||||
{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
|
||||
{0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
|
||||
{0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
|
||||
{0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
|
||||
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
|
||||
{0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
|
||||
{0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
|
||||
{0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
|
||||
{0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
|
||||
{0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
|
||||
{0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
|
||||
{0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
|
||||
{0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
|
||||
{0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
|
||||
{0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
|
||||
{0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
|
||||
{0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
|
||||
{0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
|
||||
{0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
|
||||
{0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
|
||||
{0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
|
||||
{0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
|
||||
{0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
|
||||
{0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
|
||||
{0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
|
||||
{0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
|
||||
{0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
|
||||
{0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
|
||||
{0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
|
||||
{0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
|
||||
{0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
|
||||
{0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
|
||||
{0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
|
||||
{0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
|
||||
{0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
|
||||
{0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
|
||||
{0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
|
||||
{0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
|
||||
{0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
|
||||
{0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
|
||||
{0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
|
||||
{0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
|
||||
{0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
|
||||
{0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
|
||||
{0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
|
||||
{0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
|
||||
{0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
|
||||
{0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
|
||||
{0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
|
||||
{0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
|
||||
{0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
};
|
||||
|
||||
static const u32 ar5416Common[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000000c, 0x00000000},
|
||||
{0x00000030, 0x00020015},
|
||||
{0x00000034, 0x00000005},
|
||||
{0x00000040, 0x00000000},
|
||||
{0x00000044, 0x00000008},
|
||||
{0x00000048, 0x00000008},
|
||||
{0x0000004c, 0x00000010},
|
||||
{0x00000050, 0x00000000},
|
||||
{0x00000054, 0x0000001f},
|
||||
{0x00000800, 0x00000000},
|
||||
{0x00000804, 0x00000000},
|
||||
{0x00000808, 0x00000000},
|
||||
{0x0000080c, 0x00000000},
|
||||
{0x00000810, 0x00000000},
|
||||
{0x00000814, 0x00000000},
|
||||
{0x00000818, 0x00000000},
|
||||
{0x0000081c, 0x00000000},
|
||||
{0x00000820, 0x00000000},
|
||||
{0x00000824, 0x00000000},
|
||||
{0x00001040, 0x002ffc0f},
|
||||
{0x00001044, 0x002ffc0f},
|
||||
{0x00001048, 0x002ffc0f},
|
||||
{0x0000104c, 0x002ffc0f},
|
||||
{0x00001050, 0x002ffc0f},
|
||||
{0x00001054, 0x002ffc0f},
|
||||
{0x00001058, 0x002ffc0f},
|
||||
{0x0000105c, 0x002ffc0f},
|
||||
{0x00001060, 0x002ffc0f},
|
||||
{0x00001064, 0x002ffc0f},
|
||||
{0x00001230, 0x00000000},
|
||||
{0x00001270, 0x00000000},
|
||||
{0x00001038, 0x00000000},
|
||||
{0x00001078, 0x00000000},
|
||||
{0x000010b8, 0x00000000},
|
||||
{0x000010f8, 0x00000000},
|
||||
{0x00001138, 0x00000000},
|
||||
{0x00001178, 0x00000000},
|
||||
{0x000011b8, 0x00000000},
|
||||
{0x000011f8, 0x00000000},
|
||||
{0x00001238, 0x00000000},
|
||||
{0x00001278, 0x00000000},
|
||||
{0x000012b8, 0x00000000},
|
||||
{0x000012f8, 0x00000000},
|
||||
{0x00001338, 0x00000000},
|
||||
{0x00001378, 0x00000000},
|
||||
{0x000013b8, 0x00000000},
|
||||
{0x000013f8, 0x00000000},
|
||||
{0x00001438, 0x00000000},
|
||||
{0x00001478, 0x00000000},
|
||||
{0x000014b8, 0x00000000},
|
||||
{0x000014f8, 0x00000000},
|
||||
{0x00001538, 0x00000000},
|
||||
{0x00001578, 0x00000000},
|
||||
{0x000015b8, 0x00000000},
|
||||
{0x000015f8, 0x00000000},
|
||||
{0x00001638, 0x00000000},
|
||||
{0x00001678, 0x00000000},
|
||||
{0x000016b8, 0x00000000},
|
||||
{0x000016f8, 0x00000000},
|
||||
{0x00001738, 0x00000000},
|
||||
{0x00001778, 0x00000000},
|
||||
{0x000017b8, 0x00000000},
|
||||
{0x000017f8, 0x00000000},
|
||||
{0x0000103c, 0x00000000},
|
||||
{0x0000107c, 0x00000000},
|
||||
{0x000010bc, 0x00000000},
|
||||
{0x000010fc, 0x00000000},
|
||||
{0x0000113c, 0x00000000},
|
||||
{0x0000117c, 0x00000000},
|
||||
{0x000011bc, 0x00000000},
|
||||
{0x000011fc, 0x00000000},
|
||||
{0x0000123c, 0x00000000},
|
||||
{0x0000127c, 0x00000000},
|
||||
{0x000012bc, 0x00000000},
|
||||
{0x000012fc, 0x00000000},
|
||||
{0x0000133c, 0x00000000},
|
||||
{0x0000137c, 0x00000000},
|
||||
{0x000013bc, 0x00000000},
|
||||
{0x000013fc, 0x00000000},
|
||||
{0x0000143c, 0x00000000},
|
||||
{0x0000147c, 0x00000000},
|
||||
{0x00004030, 0x00000002},
|
||||
{0x0000403c, 0x00000002},
|
||||
{0x00007010, 0x00000000},
|
||||
{0x00007038, 0x000004c2},
|
||||
{0x00008004, 0x00000000},
|
||||
{0x00008008, 0x00000000},
|
||||
{0x0000800c, 0x00000000},
|
||||
{0x00008018, 0x00000700},
|
||||
{0x00008020, 0x00000000},
|
||||
{0x00008038, 0x00000000},
|
||||
{0x0000803c, 0x00000000},
|
||||
{0x00008048, 0x40000000},
|
||||
{0x00008054, 0x00000000},
|
||||
{0x00008058, 0x00000000},
|
||||
{0x0000805c, 0x000fc78f},
|
||||
{0x00008060, 0x0000000f},
|
||||
{0x00008064, 0x00000000},
|
||||
{0x000080c0, 0x2a82301a},
|
||||
{0x000080c4, 0x05dc01e0},
|
||||
{0x000080c8, 0x1f402710},
|
||||
{0x000080cc, 0x01f40000},
|
||||
{0x000080d0, 0x00001e00},
|
||||
{0x000080d4, 0x00000000},
|
||||
{0x000080d8, 0x00400000},
|
||||
{0x000080e0, 0xffffffff},
|
||||
{0x000080e4, 0x0000ffff},
|
||||
{0x000080e8, 0x003f3f3f},
|
||||
{0x000080ec, 0x00000000},
|
||||
{0x000080f0, 0x00000000},
|
||||
{0x000080f4, 0x00000000},
|
||||
{0x000080f8, 0x00000000},
|
||||
{0x000080fc, 0x00020000},
|
||||
{0x00008100, 0x00020000},
|
||||
{0x00008104, 0x00000001},
|
||||
{0x00008108, 0x00000052},
|
||||
{0x0000810c, 0x00000000},
|
||||
{0x00008110, 0x00000168},
|
||||
{0x00008118, 0x000100aa},
|
||||
{0x0000811c, 0x00003210},
|
||||
{0x00008124, 0x00000000},
|
||||
{0x00008128, 0x00000000},
|
||||
{0x0000812c, 0x00000000},
|
||||
{0x00008130, 0x00000000},
|
||||
{0x00008134, 0x00000000},
|
||||
{0x00008138, 0x00000000},
|
||||
{0x0000813c, 0x00000000},
|
||||
{0x00008144, 0xffffffff},
|
||||
{0x00008168, 0x00000000},
|
||||
{0x0000816c, 0x00000000},
|
||||
{0x00008170, 0x32143320},
|
||||
{0x00008174, 0xfaa4fa50},
|
||||
{0x00008178, 0x00000100},
|
||||
{0x0000817c, 0x00000000},
|
||||
{0x000081c4, 0x00000000},
|
||||
{0x000081ec, 0x00000000},
|
||||
{0x000081f0, 0x00000000},
|
||||
{0x000081f4, 0x00000000},
|
||||
{0x000081f8, 0x00000000},
|
||||
{0x000081fc, 0x00000000},
|
||||
{0x00008200, 0x00000000},
|
||||
{0x00008204, 0x00000000},
|
||||
{0x00008208, 0x00000000},
|
||||
{0x0000820c, 0x00000000},
|
||||
{0x00008210, 0x00000000},
|
||||
{0x00008214, 0x00000000},
|
||||
{0x00008218, 0x00000000},
|
||||
{0x0000821c, 0x00000000},
|
||||
{0x00008220, 0x00000000},
|
||||
{0x00008224, 0x00000000},
|
||||
{0x00008228, 0x00000000},
|
||||
{0x0000822c, 0x00000000},
|
||||
{0x00008230, 0x00000000},
|
||||
{0x00008234, 0x00000000},
|
||||
{0x00008238, 0x00000000},
|
||||
{0x0000823c, 0x00000000},
|
||||
{0x00008240, 0x00100000},
|
||||
{0x00008244, 0x0010f400},
|
||||
{0x00008248, 0x00000100},
|
||||
{0x0000824c, 0x0001e800},
|
||||
{0x00008250, 0x00000000},
|
||||
{0x00008254, 0x00000000},
|
||||
{0x00008258, 0x00000000},
|
||||
{0x0000825c, 0x400000ff},
|
||||
{0x00008260, 0x00080922},
|
||||
{0x00008264, 0x88000010},
|
||||
{0x00008270, 0x00000000},
|
||||
{0x00008274, 0x40000000},
|
||||
{0x00008278, 0x003e4180},
|
||||
{0x0000827c, 0x00000000},
|
||||
{0x00008284, 0x0000002c},
|
||||
{0x00008288, 0x0000002c},
|
||||
{0x0000828c, 0x00000000},
|
||||
{0x00008294, 0x00000000},
|
||||
{0x00008298, 0x00000000},
|
||||
{0x00008300, 0x00000000},
|
||||
{0x00008304, 0x00000000},
|
||||
{0x00008308, 0x00000000},
|
||||
{0x0000830c, 0x00000000},
|
||||
{0x00008310, 0x00000000},
|
||||
{0x00008314, 0x00000000},
|
||||
{0x00008318, 0x00000000},
|
||||
{0x00008328, 0x00000000},
|
||||
{0x0000832c, 0x00000007},
|
||||
{0x00008330, 0x00000302},
|
||||
{0x00008334, 0x00000e00},
|
||||
{0x00008338, 0x00070000},
|
||||
{0x0000833c, 0x00000000},
|
||||
{0x00008340, 0x000107ff},
|
||||
{0x00009808, 0x00000000},
|
||||
{0x0000980c, 0xad848e19},
|
||||
{0x00009810, 0x7d14e000},
|
||||
{0x00009814, 0x9c0a9f6b},
|
||||
{0x0000981c, 0x00000000},
|
||||
{0x0000982c, 0x0000a000},
|
||||
{0x00009830, 0x00000000},
|
||||
{0x0000983c, 0x00200400},
|
||||
{0x00009840, 0x206a002e},
|
||||
{0x0000984c, 0x1284233c},
|
||||
{0x00009854, 0x00000859},
|
||||
{0x00009900, 0x00000000},
|
||||
{0x00009904, 0x00000000},
|
||||
{0x00009908, 0x00000000},
|
||||
{0x0000990c, 0x00000000},
|
||||
{0x0000991c, 0x10000fff},
|
||||
{0x00009920, 0x05100000},
|
||||
{0x0000a920, 0x05100000},
|
||||
{0x0000b920, 0x05100000},
|
||||
{0x00009928, 0x00000001},
|
||||
{0x0000992c, 0x00000004},
|
||||
{0x00009934, 0x1e1f2022},
|
||||
{0x00009938, 0x0a0b0c0d},
|
||||
{0x0000993c, 0x00000000},
|
||||
{0x00009948, 0x9280b212},
|
||||
{0x0000994c, 0x00020028},
|
||||
{0x00009954, 0x5d50e188},
|
||||
{0x00009958, 0x00081fff},
|
||||
{0x0000c95c, 0x004b6a8e},
|
||||
{0x0000c968, 0x000003ce},
|
||||
{0x00009970, 0x190fb515},
|
||||
{0x00009974, 0x00000000},
|
||||
{0x00009978, 0x00000001},
|
||||
{0x0000997c, 0x00000000},
|
||||
{0x00009980, 0x00000000},
|
||||
{0x00009984, 0x00000000},
|
||||
{0x00009988, 0x00000000},
|
||||
{0x0000998c, 0x00000000},
|
||||
{0x00009990, 0x00000000},
|
||||
{0x00009994, 0x00000000},
|
||||
{0x00009998, 0x00000000},
|
||||
{0x0000999c, 0x00000000},
|
||||
{0x000099a0, 0x00000000},
|
||||
{0x000099a4, 0x00000001},
|
||||
{0x000099a8, 0x001fff00},
|
||||
{0x000099ac, 0x00000000},
|
||||
{0x000099b0, 0x03051000},
|
||||
{0x000099dc, 0x00000000},
|
||||
{0x000099e0, 0x00000200},
|
||||
{0x000099e4, 0xaaaaaaaa},
|
||||
{0x000099e8, 0x3c466478},
|
||||
{0x000099ec, 0x000000aa},
|
||||
{0x000099fc, 0x00001042},
|
||||
{0x00009b00, 0x00000000},
|
||||
{0x00009b04, 0x00000001},
|
||||
{0x00009b08, 0x00000002},
|
||||
{0x00009b0c, 0x00000003},
|
||||
{0x00009b10, 0x00000004},
|
||||
{0x00009b14, 0x00000005},
|
||||
{0x00009b18, 0x00000008},
|
||||
{0x00009b1c, 0x00000009},
|
||||
{0x00009b20, 0x0000000a},
|
||||
{0x00009b24, 0x0000000b},
|
||||
{0x00009b28, 0x0000000c},
|
||||
{0x00009b2c, 0x0000000d},
|
||||
{0x00009b30, 0x00000010},
|
||||
{0x00009b34, 0x00000011},
|
||||
{0x00009b38, 0x00000012},
|
||||
{0x00009b3c, 0x00000013},
|
||||
{0x00009b40, 0x00000014},
|
||||
{0x00009b44, 0x00000015},
|
||||
{0x00009b48, 0x00000018},
|
||||
{0x00009b4c, 0x00000019},
|
||||
{0x00009b50, 0x0000001a},
|
||||
{0x00009b54, 0x0000001b},
|
||||
{0x00009b58, 0x0000001c},
|
||||
{0x00009b5c, 0x0000001d},
|
||||
{0x00009b60, 0x00000020},
|
||||
{0x00009b64, 0x00000021},
|
||||
{0x00009b68, 0x00000022},
|
||||
{0x00009b6c, 0x00000023},
|
||||
{0x00009b70, 0x00000024},
|
||||
{0x00009b74, 0x00000025},
|
||||
{0x00009b78, 0x00000028},
|
||||
{0x00009b7c, 0x00000029},
|
||||
{0x00009b80, 0x0000002a},
|
||||
{0x00009b84, 0x0000002b},
|
||||
{0x00009b88, 0x0000002c},
|
||||
{0x00009b8c, 0x0000002d},
|
||||
{0x00009b90, 0x00000030},
|
||||
{0x00009b94, 0x00000031},
|
||||
{0x00009b98, 0x00000032},
|
||||
{0x00009b9c, 0x00000033},
|
||||
{0x00009ba0, 0x00000034},
|
||||
{0x00009ba4, 0x00000035},
|
||||
{0x00009ba8, 0x00000035},
|
||||
{0x00009bac, 0x00000035},
|
||||
{0x00009bb0, 0x00000035},
|
||||
{0x00009bb4, 0x00000035},
|
||||
{0x00009bb8, 0x00000035},
|
||||
{0x00009bbc, 0x00000035},
|
||||
{0x00009bc0, 0x00000035},
|
||||
{0x00009bc4, 0x00000035},
|
||||
{0x00009bc8, 0x00000035},
|
||||
{0x00009bcc, 0x00000035},
|
||||
{0x00009bd0, 0x00000035},
|
||||
{0x00009bd4, 0x00000035},
|
||||
{0x00009bd8, 0x00000035},
|
||||
{0x00009bdc, 0x00000035},
|
||||
{0x00009be0, 0x00000035},
|
||||
{0x00009be4, 0x00000035},
|
||||
{0x00009be8, 0x00000035},
|
||||
{0x00009bec, 0x00000035},
|
||||
{0x00009bf0, 0x00000035},
|
||||
{0x00009bf4, 0x00000035},
|
||||
{0x00009bf8, 0x00000010},
|
||||
{0x00009bfc, 0x0000001a},
|
||||
{0x0000a210, 0x40806333},
|
||||
{0x0000a214, 0x00106c10},
|
||||
{0x0000a218, 0x009c4060},
|
||||
{0x0000a220, 0x018830c6},
|
||||
{0x0000a224, 0x00000400},
|
||||
{0x0000a228, 0x00000bb5},
|
||||
{0x0000a22c, 0x00000011},
|
||||
{0x0000a234, 0x20202020},
|
||||
{0x0000a238, 0x20202020},
|
||||
{0x0000a23c, 0x13c889af},
|
||||
{0x0000a240, 0x38490a20},
|
||||
{0x0000a244, 0x00007bb6},
|
||||
{0x0000a248, 0x0fff3ffc},
|
||||
{0x0000a24c, 0x00000001},
|
||||
{0x0000a250, 0x0000a000},
|
||||
{0x0000a254, 0x00000000},
|
||||
{0x0000a258, 0x0cc75380},
|
||||
{0x0000a25c, 0x0f0f0f01},
|
||||
{0x0000a260, 0xdfa91f01},
|
||||
{0x0000a268, 0x00000000},
|
||||
{0x0000a26c, 0x0e79e5c6},
|
||||
{0x0000b26c, 0x0e79e5c6},
|
||||
{0x0000c26c, 0x0e79e5c6},
|
||||
{0x0000d270, 0x00820820},
|
||||
{0x0000a278, 0x1ce739ce},
|
||||
{0x0000a27c, 0x051701ce},
|
||||
{0x0000a338, 0x00000000},
|
||||
{0x0000a33c, 0x00000000},
|
||||
{0x0000a340, 0x00000000},
|
||||
{0x0000a344, 0x00000000},
|
||||
{0x0000a348, 0x3fffffff},
|
||||
{0x0000a34c, 0x3fffffff},
|
||||
{0x0000a350, 0x3fffffff},
|
||||
{0x0000a354, 0x0003ffff},
|
||||
{0x0000a358, 0x79a8aa1f},
|
||||
{0x0000d35c, 0x07ffffef},
|
||||
{0x0000d360, 0x0fffffe7},
|
||||
{0x0000d364, 0x17ffffe5},
|
||||
{0x0000d368, 0x1fffffe4},
|
||||
{0x0000d36c, 0x37ffffe3},
|
||||
{0x0000d370, 0x3fffffe3},
|
||||
{0x0000d374, 0x57ffffe3},
|
||||
{0x0000d378, 0x5fffffe2},
|
||||
{0x0000d37c, 0x7fffffe2},
|
||||
{0x0000d380, 0x7f3c7bba},
|
||||
{0x0000d384, 0xf3307ff0},
|
||||
{0x0000a388, 0x08000000},
|
||||
{0x0000a38c, 0x20202020},
|
||||
{0x0000a390, 0x20202020},
|
||||
{0x0000a394, 0x1ce739ce},
|
||||
{0x0000a398, 0x000001ce},
|
||||
{0x0000a39c, 0x00000001},
|
||||
{0x0000a3a0, 0x00000000},
|
||||
{0x0000a3a4, 0x00000000},
|
||||
{0x0000a3a8, 0x00000000},
|
||||
{0x0000a3ac, 0x00000000},
|
||||
{0x0000a3b0, 0x00000000},
|
||||
{0x0000a3b4, 0x00000000},
|
||||
{0x0000a3b8, 0x00000000},
|
||||
{0x0000a3bc, 0x00000000},
|
||||
{0x0000a3c0, 0x00000000},
|
||||
{0x0000a3c4, 0x00000000},
|
||||
{0x0000a3c8, 0x00000246},
|
||||
{0x0000a3cc, 0x20202020},
|
||||
{0x0000a3d0, 0x20202020},
|
||||
{0x0000a3d4, 0x20202020},
|
||||
{0x0000a3dc, 0x1ce739ce},
|
||||
{0x0000a3e0, 0x000001ce},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x1e5795e5},
|
||||
{0x000098e0, 0x02008020},
|
||||
};
|
||||
|
||||
static const u32 ar5416BB_RfGain[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
{0x00009a00, 0x00000000, 0x00000000},
|
||||
{0x00009a04, 0x00000040, 0x00000040},
|
||||
{0x00009a08, 0x00000080, 0x00000080},
|
||||
{0x00009a0c, 0x000001a1, 0x00000141},
|
||||
{0x00009a10, 0x000001e1, 0x00000181},
|
||||
{0x00009a14, 0x00000021, 0x000001c1},
|
||||
{0x00009a18, 0x00000061, 0x00000001},
|
||||
{0x00009a1c, 0x00000168, 0x00000041},
|
||||
{0x00009a20, 0x000001a8, 0x000001a8},
|
||||
{0x00009a24, 0x000001e8, 0x000001e8},
|
||||
{0x00009a28, 0x00000028, 0x00000028},
|
||||
{0x00009a2c, 0x00000068, 0x00000068},
|
||||
{0x00009a30, 0x00000189, 0x000000a8},
|
||||
{0x00009a34, 0x000001c9, 0x00000169},
|
||||
{0x00009a38, 0x00000009, 0x000001a9},
|
||||
{0x00009a3c, 0x00000049, 0x000001e9},
|
||||
{0x00009a40, 0x00000089, 0x00000029},
|
||||
{0x00009a44, 0x00000170, 0x00000069},
|
||||
{0x00009a48, 0x000001b0, 0x00000190},
|
||||
{0x00009a4c, 0x000001f0, 0x000001d0},
|
||||
{0x00009a50, 0x00000030, 0x00000010},
|
||||
{0x00009a54, 0x00000070, 0x00000050},
|
||||
{0x00009a58, 0x00000191, 0x00000090},
|
||||
{0x00009a5c, 0x000001d1, 0x00000151},
|
||||
{0x00009a60, 0x00000011, 0x00000191},
|
||||
{0x00009a64, 0x00000051, 0x000001d1},
|
||||
{0x00009a68, 0x00000091, 0x00000011},
|
||||
{0x00009a6c, 0x000001b8, 0x00000051},
|
||||
{0x00009a70, 0x000001f8, 0x00000198},
|
||||
{0x00009a74, 0x00000038, 0x000001d8},
|
||||
{0x00009a78, 0x00000078, 0x00000018},
|
||||
{0x00009a7c, 0x00000199, 0x00000058},
|
||||
{0x00009a80, 0x000001d9, 0x00000098},
|
||||
{0x00009a84, 0x00000019, 0x00000159},
|
||||
{0x00009a88, 0x00000059, 0x00000199},
|
||||
{0x00009a8c, 0x00000099, 0x000001d9},
|
||||
{0x00009a90, 0x000000d9, 0x00000019},
|
||||
{0x00009a94, 0x000000f9, 0x00000059},
|
||||
{0x00009a98, 0x000000f9, 0x00000099},
|
||||
{0x00009a9c, 0x000000f9, 0x000000d9},
|
||||
{0x00009aa0, 0x000000f9, 0x000000f9},
|
||||
{0x00009aa4, 0x000000f9, 0x000000f9},
|
||||
{0x00009aa8, 0x000000f9, 0x000000f9},
|
||||
{0x00009aac, 0x000000f9, 0x000000f9},
|
||||
{0x00009ab0, 0x000000f9, 0x000000f9},
|
||||
{0x00009ab4, 0x000000f9, 0x000000f9},
|
||||
{0x00009ab8, 0x000000f9, 0x000000f9},
|
||||
{0x00009abc, 0x000000f9, 0x000000f9},
|
||||
{0x00009ac0, 0x000000f9, 0x000000f9},
|
||||
{0x00009ac4, 0x000000f9, 0x000000f9},
|
||||
{0x00009ac8, 0x000000f9, 0x000000f9},
|
||||
{0x00009acc, 0x000000f9, 0x000000f9},
|
||||
{0x00009ad0, 0x000000f9, 0x000000f9},
|
||||
{0x00009ad4, 0x000000f9, 0x000000f9},
|
||||
{0x00009ad8, 0x000000f9, 0x000000f9},
|
||||
{0x00009adc, 0x000000f9, 0x000000f9},
|
||||
{0x00009ae0, 0x000000f9, 0x000000f9},
|
||||
{0x00009ae4, 0x000000f9, 0x000000f9},
|
||||
{0x00009ae8, 0x000000f9, 0x000000f9},
|
||||
{0x00009aec, 0x000000f9, 0x000000f9},
|
||||
{0x00009af0, 0x000000f9, 0x000000f9},
|
||||
{0x00009af4, 0x000000f9, 0x000000f9},
|
||||
{0x00009af8, 0x000000f9, 0x000000f9},
|
||||
{0x00009afc, 0x000000f9, 0x000000f9},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x02108421},
|
||||
{0x000098ec, 0x00000008},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank2[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x0e73ff17},
|
||||
{0x000098e0, 0x00000420},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank3[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
{0x000098f0, 0x01400018, 0x01c00018},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00e00000, 0x00e00000},
|
||||
{0x0000989c, 0x005e0000, 0x005e0000},
|
||||
{0x0000989c, 0x00120000, 0x00120000},
|
||||
{0x0000989c, 0x00620000, 0x00620000},
|
||||
{0x0000989c, 0x00020000, 0x00020000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x40ff0000, 0x40ff0000},
|
||||
{0x0000989c, 0x005f0000, 0x005f0000},
|
||||
{0x0000989c, 0x00870000, 0x00870000},
|
||||
{0x0000989c, 0x00f90000, 0x00f90000},
|
||||
{0x0000989c, 0x007b0000, 0x007b0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00f50000, 0x00f50000},
|
||||
{0x0000989c, 0x00dc0000, 0x00dc0000},
|
||||
{0x0000989c, 0x00110000, 0x00110000},
|
||||
{0x0000989c, 0x006100a8, 0x006100a8},
|
||||
{0x0000989c, 0x004210a2, 0x004210a2},
|
||||
{0x0000989c, 0x0014008f, 0x0014008f},
|
||||
{0x0000989c, 0x00c40003, 0x00c40003},
|
||||
{0x0000989c, 0x003000f2, 0x003000f2},
|
||||
{0x0000989c, 0x00440016, 0x00440016},
|
||||
{0x0000989c, 0x00410040, 0x00410040},
|
||||
{0x0000989c, 0x0001805e, 0x0001805e},
|
||||
{0x0000989c, 0x0000c0ab, 0x0000c0ab},
|
||||
{0x0000989c, 0x000000f1, 0x000000f1},
|
||||
{0x0000989c, 0x00002081, 0x00002081},
|
||||
{0x0000989c, 0x000000d4, 0x000000d4},
|
||||
{0x000098d0, 0x0000000f, 0x0010000f},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6TPC[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00e00000, 0x00e00000},
|
||||
{0x0000989c, 0x005e0000, 0x005e0000},
|
||||
{0x0000989c, 0x00120000, 0x00120000},
|
||||
{0x0000989c, 0x00620000, 0x00620000},
|
||||
{0x0000989c, 0x00020000, 0x00020000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x40ff0000, 0x40ff0000},
|
||||
{0x0000989c, 0x005f0000, 0x005f0000},
|
||||
{0x0000989c, 0x00870000, 0x00870000},
|
||||
{0x0000989c, 0x00f90000, 0x00f90000},
|
||||
{0x0000989c, 0x007b0000, 0x007b0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00f50000, 0x00f50000},
|
||||
{0x0000989c, 0x00dc0000, 0x00dc0000},
|
||||
{0x0000989c, 0x00110000, 0x00110000},
|
||||
{0x0000989c, 0x006100a8, 0x006100a8},
|
||||
{0x0000989c, 0x00423022, 0x00423022},
|
||||
{0x0000989c, 0x201400df, 0x201400df},
|
||||
{0x0000989c, 0x00c40002, 0x00c40002},
|
||||
{0x0000989c, 0x003000f2, 0x003000f2},
|
||||
{0x0000989c, 0x00440016, 0x00440016},
|
||||
{0x0000989c, 0x00410040, 0x00410040},
|
||||
{0x0000989c, 0x0001805e, 0x0001805e},
|
||||
{0x0000989c, 0x0000c0ab, 0x0000c0ab},
|
||||
{0x0000989c, 0x000000e1, 0x000000e1},
|
||||
{0x0000989c, 0x00007081, 0x00007081},
|
||||
{0x0000989c, 0x000000d4, 0x000000d4},
|
||||
{0x000098d0, 0x0000000f, 0x0010000f},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank7[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000989c, 0x00000500},
|
||||
{0x0000989c, 0x00000800},
|
||||
{0x000098cc, 0x0000000e},
|
||||
};
|
||||
|
||||
static const u32 ar5416Addac[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000003},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x0000000c},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000030},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000060},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000058},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x000098cc, 0x00000000},
|
||||
};
|
||||
1356
src/drivers/net/ath/ath9k/ar9001_initvals.h
Normal file
1356
src/drivers/net/ath/ath9k/ar9001_initvals.h
Normal file
File diff suppressed because it is too large
Load Diff
3264
src/drivers/net/ath/ath9k/ar9002_initvals.h
Normal file
3264
src/drivers/net/ath/ath9k/ar9002_initvals.h
Normal file
File diff suppressed because it is too large
Load Diff
613
src/drivers/net/ath/ath9k/ar9002_phy.h
Normal file
613
src/drivers/net/ath/ath9k/ar9002_phy.h
Normal file
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef AR9002_PHY_H
|
||||
#define AR9002_PHY_H
|
||||
|
||||
#define AR_PHY_TEST 0x9800
|
||||
#define PHY_AGC_CLR 0x10000000
|
||||
#define RFSILENT_BB 0x00002000
|
||||
|
||||
#define AR_PHY_TURBO 0x9804
|
||||
#define AR_PHY_FC_TURBO_MODE 0x00000001
|
||||
#define AR_PHY_FC_TURBO_SHORT 0x00000002
|
||||
#define AR_PHY_FC_DYN2040_EN 0x00000004
|
||||
#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
|
||||
#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
|
||||
/* For 25 MHz channel spacing -- not used but supported by hw */
|
||||
#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
|
||||
#define AR_PHY_FC_HT_EN 0x00000040
|
||||
#define AR_PHY_FC_SHORT_GI_40 0x00000080
|
||||
#define AR_PHY_FC_WALSH 0x00000100
|
||||
#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
|
||||
#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
|
||||
|
||||
#define AR_PHY_TEST2 0x9808
|
||||
|
||||
#define AR_PHY_TIMING2 0x9810
|
||||
#define AR_PHY_TIMING3 0x9814
|
||||
#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
|
||||
#define AR_PHY_TIMING3_DSC_MAN_S 17
|
||||
#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
|
||||
#define AR_PHY_TIMING3_DSC_EXP_S 13
|
||||
|
||||
#define AR_PHY_CHIP_ID_REV_0 0x80
|
||||
#define AR_PHY_CHIP_ID_REV_1 0x81
|
||||
#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
|
||||
|
||||
#define AR_PHY_ACTIVE 0x981C
|
||||
#define AR_PHY_ACTIVE_EN 0x00000001
|
||||
#define AR_PHY_ACTIVE_DIS 0x00000000
|
||||
|
||||
#define AR_PHY_RF_CTL2 0x9824
|
||||
#define AR_PHY_TX_END_DATA_START 0x000000FF
|
||||
#define AR_PHY_TX_END_DATA_START_S 0
|
||||
#define AR_PHY_TX_END_PA_ON 0x0000FF00
|
||||
#define AR_PHY_TX_END_PA_ON_S 8
|
||||
|
||||
#define AR_PHY_RF_CTL3 0x9828
|
||||
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
|
||||
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
|
||||
|
||||
#define AR_PHY_ADC_CTL 0x982C
|
||||
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
|
||||
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
|
||||
#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
|
||||
#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
|
||||
#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
|
||||
#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
|
||||
#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
|
||||
|
||||
#define AR_PHY_ADC_SERIAL_CTL 0x9830
|
||||
#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
|
||||
#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
|
||||
|
||||
#define AR_PHY_RF_CTL4 0x9834
|
||||
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
|
||||
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
|
||||
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
|
||||
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
|
||||
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
|
||||
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
|
||||
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
|
||||
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
|
||||
|
||||
#define AR_PHY_TSTDAC_CONST 0x983c
|
||||
|
||||
#define AR_PHY_SETTLING 0x9844
|
||||
#define AR_PHY_SETTLING_SWITCH 0x00003F80
|
||||
#define AR_PHY_SETTLING_SWITCH_S 7
|
||||
|
||||
#define AR_PHY_RXGAIN 0x9848
|
||||
#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
|
||||
#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
|
||||
#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
|
||||
#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
|
||||
#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
|
||||
#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
|
||||
#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
|
||||
#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
|
||||
|
||||
#define AR_PHY_DESIRED_SZ 0x9850
|
||||
#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
|
||||
#define AR_PHY_DESIRED_SZ_ADC_S 0
|
||||
#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
|
||||
#define AR_PHY_DESIRED_SZ_PGA_S 8
|
||||
#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
|
||||
#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
|
||||
|
||||
#define AR_PHY_FIND_SIG 0x9858
|
||||
#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
|
||||
#define AR_PHY_FIND_SIG_FIRSTEP_S 12
|
||||
#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
|
||||
#define AR_PHY_FIND_SIG_FIRPWR_S 18
|
||||
|
||||
#define AR_PHY_FIND_SIG_LOW 0x9840
|
||||
#define AR_PHY_FIND_SIG_FIRSTEP_LOW 0x00000FC0L
|
||||
#define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6
|
||||
|
||||
#define AR_PHY_AGC_CTL1 0x985C
|
||||
#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
|
||||
#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
|
||||
#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
|
||||
#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
|
||||
|
||||
#define AR_PHY_CCA 0x9864
|
||||
#define AR_PHY_MINCCA_PWR 0x0FF80000
|
||||
#define AR_PHY_MINCCA_PWR_S 19
|
||||
#define AR_PHY_CCA_THRESH62 0x0007F000
|
||||
#define AR_PHY_CCA_THRESH62_S 12
|
||||
#define AR9280_PHY_MINCCA_PWR 0x1FF00000
|
||||
#define AR9280_PHY_MINCCA_PWR_S 20
|
||||
#define AR9280_PHY_CCA_THRESH62 0x000FF000
|
||||
#define AR9280_PHY_CCA_THRESH62_S 12
|
||||
|
||||
#define AR_PHY_SFCORR_LOW 0x986C
|
||||
#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
|
||||
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
|
||||
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
|
||||
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
|
||||
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
|
||||
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
|
||||
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
|
||||
|
||||
#define AR_PHY_SFCORR 0x9868
|
||||
#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
|
||||
#define AR_PHY_SFCORR_M2COUNT_THR_S 0
|
||||
#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
|
||||
#define AR_PHY_SFCORR_M1_THRESH_S 17
|
||||
#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
|
||||
#define AR_PHY_SFCORR_M2_THRESH_S 24
|
||||
|
||||
#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
|
||||
#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
|
||||
#define AR_PHY_SYNTH_CONTROL 0x9874
|
||||
#define AR_PHY_SLEEP_SCAL 0x9878
|
||||
|
||||
#define AR_PHY_PLL_CTL 0x987c
|
||||
#define AR_PHY_PLL_CTL_40 0xaa
|
||||
#define AR_PHY_PLL_CTL_40_5413 0x04
|
||||
#define AR_PHY_PLL_CTL_44 0xab
|
||||
#define AR_PHY_PLL_CTL_44_2133 0xeb
|
||||
#define AR_PHY_PLL_CTL_40_2133 0xea
|
||||
|
||||
#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */
|
||||
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
|
||||
#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */
|
||||
#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */
|
||||
#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
|
||||
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
|
||||
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
|
||||
|
||||
#define AR_PHY_RX_DELAY 0x9914
|
||||
#define AR_PHY_SEARCH_START_DELAY 0x9918
|
||||
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
|
||||
|
||||
#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
|
||||
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
|
||||
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
|
||||
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
|
||||
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
|
||||
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
|
||||
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
|
||||
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
|
||||
#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
|
||||
|
||||
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
|
||||
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
|
||||
#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
|
||||
#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
|
||||
|
||||
#define AR_PHY_TIMING5 0x9924
|
||||
#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
|
||||
#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
|
||||
|
||||
#define AR_PHY_POWER_TX_RATE1 0x9934
|
||||
#define AR_PHY_POWER_TX_RATE2 0x9938
|
||||
#define AR_PHY_POWER_TX_RATE_MAX 0x993c
|
||||
#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
|
||||
|
||||
#define AR_PHY_FRAME_CTL 0x9944
|
||||
#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
|
||||
#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
|
||||
|
||||
#define AR_PHY_TXPWRADJ 0x994C
|
||||
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
|
||||
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
|
||||
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
|
||||
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
|
||||
|
||||
#define AR_PHY_RADAR_EXT 0x9940
|
||||
#define AR_PHY_RADAR_EXT_ENA 0x00004000
|
||||
|
||||
#define AR_PHY_RADAR_0 0x9954
|
||||
#define AR_PHY_RADAR_0_ENA 0x00000001
|
||||
#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
|
||||
#define AR_PHY_RADAR_0_INBAND 0x0000003e
|
||||
#define AR_PHY_RADAR_0_INBAND_S 1
|
||||
#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
|
||||
#define AR_PHY_RADAR_0_PRSSI_S 6
|
||||
#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
|
||||
#define AR_PHY_RADAR_0_HEIGHT_S 12
|
||||
#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
|
||||
#define AR_PHY_RADAR_0_RRSSI_S 18
|
||||
#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
|
||||
#define AR_PHY_RADAR_0_FIRPWR_S 24
|
||||
|
||||
#define AR_PHY_RADAR_1 0x9958
|
||||
#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
|
||||
#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
|
||||
#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
|
||||
#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
|
||||
#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
|
||||
#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
|
||||
#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
|
||||
#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
|
||||
#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
|
||||
#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
|
||||
#define AR_PHY_RADAR_1_MAXLEN_S 0
|
||||
|
||||
#define AR_PHY_SWITCH_CHAIN_0 0x9960
|
||||
#define AR_PHY_SWITCH_COM 0x9964
|
||||
|
||||
#define AR_PHY_SIGMA_DELTA 0x996C
|
||||
#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
|
||||
#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
|
||||
#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
|
||||
#define AR_PHY_SIGMA_DELTA_FILT2_S 3
|
||||
#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
|
||||
#define AR_PHY_SIGMA_DELTA_FILT1_S 8
|
||||
#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
|
||||
#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
|
||||
|
||||
#define AR_PHY_RESTART 0x9970
|
||||
#define AR_PHY_RESTART_DIV_GC 0x001C0000
|
||||
#define AR_PHY_RESTART_DIV_GC_S 18
|
||||
|
||||
#define AR_PHY_RFBUS_REQ 0x997C
|
||||
#define AR_PHY_RFBUS_REQ_EN 0x00000001
|
||||
|
||||
#define AR_PHY_TIMING7 0x9980
|
||||
#define AR_PHY_TIMING8 0x9984
|
||||
#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
|
||||
#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
|
||||
|
||||
#define AR_PHY_BIN_MASK2_1 0x9988
|
||||
#define AR_PHY_BIN_MASK2_2 0x998c
|
||||
#define AR_PHY_BIN_MASK2_3 0x9990
|
||||
#define AR_PHY_BIN_MASK2_4 0x9994
|
||||
|
||||
#define AR_PHY_BIN_MASK_1 0x9900
|
||||
#define AR_PHY_BIN_MASK_2 0x9904
|
||||
#define AR_PHY_BIN_MASK_3 0x9908
|
||||
|
||||
#define AR_PHY_MASK_CTL 0x990c
|
||||
|
||||
#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
|
||||
#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
|
||||
|
||||
#define AR_PHY_TIMING9 0x9998
|
||||
#define AR_PHY_TIMING10 0x999c
|
||||
#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
|
||||
#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
|
||||
|
||||
#define AR_PHY_TIMING11 0x99a0
|
||||
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
|
||||
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
|
||||
#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
|
||||
#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
|
||||
|
||||
#define AR_PHY_RX_CHAINMASK 0x99a4
|
||||
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
|
||||
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
|
||||
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
|
||||
|
||||
#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
|
||||
#define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00
|
||||
#define AR_PHY_9285_FAST_DIV_BIAS_S 9
|
||||
#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
|
||||
#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
|
||||
#define AR_PHY_9285_ANT_DIV_CTL_S 24
|
||||
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
|
||||
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
|
||||
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
|
||||
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
|
||||
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
|
||||
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
|
||||
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
|
||||
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
|
||||
#define AR_PHY_9285_ANT_DIV_LNA1 2
|
||||
#define AR_PHY_9285_ANT_DIV_LNA2 1
|
||||
#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
|
||||
#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
|
||||
#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
|
||||
#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
|
||||
|
||||
#define AR_PHY_EXT_CCA0 0x99b8
|
||||
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
|
||||
#define AR_PHY_EXT_CCA0_THRESH62_S 0
|
||||
|
||||
#define AR_PHY_EXT_CCA 0x99bc
|
||||
#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
|
||||
#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
|
||||
#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
|
||||
#define AR_PHY_EXT_CCA_THRESH62_S 16
|
||||
#define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00L
|
||||
#define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9
|
||||
|
||||
#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
|
||||
#define AR_PHY_EXT_MINCCA_PWR_S 23
|
||||
#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
|
||||
#define AR9280_PHY_EXT_MINCCA_PWR_S 16
|
||||
|
||||
#define AR_PHY_SFCORR_EXT 0x99c0
|
||||
#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
|
||||
#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
|
||||
#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
|
||||
#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
|
||||
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
|
||||
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
|
||||
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
|
||||
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
|
||||
#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
|
||||
|
||||
#define AR_PHY_HALFGI 0x99D0
|
||||
#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
|
||||
#define AR_PHY_HALFGI_DSC_MAN_S 4
|
||||
#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
|
||||
#define AR_PHY_HALFGI_DSC_EXP_S 0
|
||||
|
||||
#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
|
||||
#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
|
||||
|
||||
#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
|
||||
|
||||
#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC
|
||||
#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000
|
||||
|
||||
#define AR_PHY_M_SLEEP 0x99f0
|
||||
#define AR_PHY_REFCLKDLY 0x99f4
|
||||
#define AR_PHY_REFCLKPD 0x99f8
|
||||
|
||||
#define AR_PHY_CALMODE 0x99f0
|
||||
|
||||
#define AR_PHY_CALMODE_IQ 0x00000000
|
||||
#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
|
||||
#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
|
||||
#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
|
||||
|
||||
#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
|
||||
#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
|
||||
#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
|
||||
#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
|
||||
|
||||
#define AR_PHY_CURRENT_RSSI 0x9c1c
|
||||
#define AR9280_PHY_CURRENT_RSSI 0x9c3c
|
||||
|
||||
#define AR_PHY_RFBUS_GRANT 0x9C20
|
||||
#define AR_PHY_RFBUS_GRANT_EN 0x00000001
|
||||
|
||||
#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
|
||||
#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
|
||||
|
||||
#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
|
||||
|
||||
#define AR_PHY_MODE 0xA200
|
||||
#define AR_PHY_MODE_ASYNCFIFO 0x80
|
||||
#define AR_PHY_MODE_AR2133 0x08
|
||||
#define AR_PHY_MODE_AR5111 0x00
|
||||
#define AR_PHY_MODE_AR5112 0x08
|
||||
#define AR_PHY_MODE_DYNAMIC 0x04
|
||||
#define AR_PHY_MODE_RF2GHZ 0x02
|
||||
#define AR_PHY_MODE_RF5GHZ 0x00
|
||||
#define AR_PHY_MODE_CCK 0x01
|
||||
#define AR_PHY_MODE_OFDM 0x00
|
||||
#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
|
||||
|
||||
#define AR_PHY_CCK_TX_CTRL 0xA204
|
||||
#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
|
||||
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
|
||||
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
|
||||
|
||||
#define AR_PHY_CCK_DETECT 0xA208
|
||||
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
|
||||
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
|
||||
/* [12:6] settling time for antenna switch */
|
||||
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
|
||||
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
|
||||
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
|
||||
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
|
||||
|
||||
#define AR_PHY_GAIN_2GHZ 0xA20C
|
||||
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
|
||||
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
|
||||
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
|
||||
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
|
||||
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
|
||||
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
|
||||
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
|
||||
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
|
||||
|
||||
#define AR_PHY_CCK_RXCTRL4 0xA21C
|
||||
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
|
||||
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
|
||||
|
||||
#define AR_PHY_DAG_CTRLCCK 0xA228
|
||||
#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
|
||||
#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
|
||||
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
|
||||
|
||||
#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
|
||||
#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
|
||||
|
||||
#define AR_PHY_POWER_TX_RATE3 0xA234
|
||||
#define AR_PHY_POWER_TX_RATE4 0xA238
|
||||
|
||||
#define AR_PHY_SCRM_SEQ_XR 0xA23C
|
||||
#define AR_PHY_HEADER_DETECT_XR 0xA240
|
||||
#define AR_PHY_CHIRP_DETECTED_XR 0xA244
|
||||
#define AR_PHY_BLUETOOTH 0xA254
|
||||
|
||||
#define AR_PHY_TPCRG1 0xA258
|
||||
#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
|
||||
#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
|
||||
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
|
||||
#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
|
||||
|
||||
#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
|
||||
#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL4 0xa264
|
||||
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
|
||||
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
|
||||
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
|
||||
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL6_0 0xa270
|
||||
#define AR_PHY_TX_PWRCTRL6_1 0xb270
|
||||
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
|
||||
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL7 0xa274
|
||||
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
|
||||
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL8 0xa278
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL9 0xa27C
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL10 0xa394
|
||||
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
|
||||
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
|
||||
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
|
||||
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
|
||||
|
||||
#define AR_PHY_TX_GAIN_TBL1 0xa300
|
||||
#define AR_PHY_TX_GAIN 0x0007F000
|
||||
#define AR_PHY_TX_GAIN_S 12
|
||||
|
||||
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
|
||||
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
|
||||
#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc
|
||||
#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0
|
||||
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
|
||||
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
|
||||
|
||||
#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
|
||||
#define AR_PHY_MASK2_M_31_45 0xa3a4
|
||||
#define AR_PHY_MASK2_M_16_30 0xa3a8
|
||||
#define AR_PHY_MASK2_M_00_15 0xa3ac
|
||||
#define AR_PHY_MASK2_P_15_01 0xa3b8
|
||||
#define AR_PHY_MASK2_P_30_16 0xa3bc
|
||||
#define AR_PHY_MASK2_P_45_31 0xa3c0
|
||||
#define AR_PHY_MASK2_P_61_45 0xa3c4
|
||||
#define AR_PHY_SPUR_REG 0x994c
|
||||
|
||||
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
|
||||
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
|
||||
|
||||
#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
|
||||
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
|
||||
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
|
||||
#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
|
||||
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
|
||||
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
|
||||
|
||||
#define AR_PHY_PILOT_MASK_01_30 0xa3b0
|
||||
#define AR_PHY_PILOT_MASK_31_60 0xa3b4
|
||||
|
||||
#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
|
||||
#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
|
||||
|
||||
#define AR_PHY_ANALOG_SWAP 0xa268
|
||||
#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
|
||||
|
||||
#define AR_PHY_TPCRG5 0xA26C
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
|
||||
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
|
||||
|
||||
/* Carrier leak calibration control, do it after AGC calibration */
|
||||
#define AR_PHY_CL_CAL_CTL 0xA358
|
||||
#define AR_PHY_CL_CAL_ENABLE 0x00000002
|
||||
#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
|
||||
|
||||
#define AR_PHY_POWER_TX_RATE5 0xA38C
|
||||
#define AR_PHY_POWER_TX_RATE6 0xA390
|
||||
|
||||
#define AR_PHY_CAL_CHAINMASK 0xA39C
|
||||
|
||||
#define AR_PHY_POWER_TX_SUB 0xA3C8
|
||||
#define AR_PHY_POWER_TX_RATE7 0xA3CC
|
||||
#define AR_PHY_POWER_TX_RATE8 0xA3D0
|
||||
#define AR_PHY_POWER_TX_RATE9 0xA3D4
|
||||
|
||||
#define AR_PHY_XPA_CFG 0xA3D8
|
||||
#define AR_PHY_FORCE_XPA_CFG 0x000000001
|
||||
#define AR_PHY_FORCE_XPA_CFG_S 0
|
||||
|
||||
#define AR_PHY_CH1_CCA 0xa864
|
||||
#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
|
||||
#define AR_PHY_CH1_MINCCA_PWR_S 19
|
||||
#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
|
||||
#define AR9280_PHY_CH1_MINCCA_PWR_S 20
|
||||
|
||||
#define AR_PHY_CH2_CCA 0xb864
|
||||
#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
|
||||
#define AR_PHY_CH2_MINCCA_PWR_S 19
|
||||
|
||||
#define AR_PHY_CH1_EXT_CCA 0xa9bc
|
||||
#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
|
||||
#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
|
||||
#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
|
||||
#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
|
||||
|
||||
#define AR_PHY_CH2_EXT_CCA 0xb9bc
|
||||
#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
|
||||
#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
|
||||
|
||||
#define AR_PHY_CCA_NOM_VAL_5416_2GHZ -90
|
||||
#define AR_PHY_CCA_NOM_VAL_5416_5GHZ -100
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ -100
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ -110
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ -80
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ -90
|
||||
|
||||
#define AR_PHY_CCA_NOM_VAL_9280_2GHZ -112
|
||||
#define AR_PHY_CCA_NOM_VAL_9280_5GHZ -112
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ -127
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ -122
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ -97
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ -102
|
||||
|
||||
#define AR_PHY_CCA_NOM_VAL_9285_2GHZ -118
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ -127
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ -108
|
||||
|
||||
#define AR_PHY_CCA_NOM_VAL_9271_2GHZ -118
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116
|
||||
|
||||
#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110
|
||||
|
||||
#endif
|
||||
1864
src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h
Normal file
1864
src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h
Normal file
File diff suppressed because it is too large
Load Diff
338
src/drivers/net/ath/ath9k/ar9003_eeprom.h
Normal file
338
src/drivers/net/ath/ath9k/ar9003_eeprom.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef AR9003_EEPROM_H
|
||||
#define AR9003_EEPROM_H
|
||||
|
||||
#define AR9300_EEP_VER 0xD000
|
||||
#define AR9300_EEP_VER_MINOR_MASK 0xFFF
|
||||
#define AR9300_EEP_MINOR_VER_1 0x1
|
||||
#define AR9300_EEP_MINOR_VER AR9300_EEP_MINOR_VER_1
|
||||
|
||||
/* 16-bit offset location start of calibration struct */
|
||||
#define AR9300_EEP_START_LOC 256
|
||||
#define AR9300_NUM_5G_CAL_PIERS 8
|
||||
#define AR9300_NUM_2G_CAL_PIERS 3
|
||||
#define AR9300_NUM_5G_20_TARGET_POWERS 8
|
||||
#define AR9300_NUM_5G_40_TARGET_POWERS 8
|
||||
#define AR9300_NUM_2G_CCK_TARGET_POWERS 2
|
||||
#define AR9300_NUM_2G_20_TARGET_POWERS 3
|
||||
#define AR9300_NUM_2G_40_TARGET_POWERS 3
|
||||
/* #define AR9300_NUM_CTLS 21 */
|
||||
#define AR9300_NUM_CTLS_5G 9
|
||||
#define AR9300_NUM_CTLS_2G 12
|
||||
#define AR9300_NUM_BAND_EDGES_5G 8
|
||||
#define AR9300_NUM_BAND_EDGES_2G 4
|
||||
#define AR9300_EEPMISC_BIG_ENDIAN 0x01
|
||||
#define AR9300_EEPMISC_WOW 0x02
|
||||
#define AR9300_CUSTOMER_DATA_SIZE 20
|
||||
|
||||
#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
|
||||
#define AR9300_MAX_CHAINS 3
|
||||
#define AR9300_ANT_16S 25
|
||||
#define AR9300_FUTURE_MODAL_SZ 6
|
||||
|
||||
#define AR9300_PAPRD_RATE_MASK 0x01ffffff
|
||||
#define AR9300_PAPRD_SCALE_1 0x0e000000
|
||||
#define AR9300_PAPRD_SCALE_1_S 25
|
||||
#define AR9300_PAPRD_SCALE_2 0x70000000
|
||||
#define AR9300_PAPRD_SCALE_2_S 28
|
||||
|
||||
/* Delta from which to start power to pdadc table */
|
||||
/* This offset is used in both open loop and closed loop power control
|
||||
* schemes. In open loop power control, it is not really needed, but for
|
||||
* the "sake of consistency" it was kept. For certain AP designs, this
|
||||
* value is overwritten by the value in the flag "pwrTableOffset" just
|
||||
* before writing the pdadc vs pwr into the chip registers.
|
||||
*/
|
||||
#define AR9300_PWR_TABLE_OFFSET 0
|
||||
|
||||
/* byte addressable */
|
||||
#define AR9300_EEPROM_SIZE (16*1024)
|
||||
|
||||
#define AR9300_BASE_ADDR_4K 0xfff
|
||||
#define AR9300_BASE_ADDR 0x3ff
|
||||
#define AR9300_BASE_ADDR_512 0x1ff
|
||||
|
||||
#define AR9300_OTP_BASE 0x14000
|
||||
#define AR9300_OTP_STATUS 0x15f18
|
||||
#define AR9300_OTP_STATUS_TYPE 0x7
|
||||
#define AR9300_OTP_STATUS_VALID 0x4
|
||||
#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
|
||||
#define AR9300_OTP_STATUS_SM_BUSY 0x1
|
||||
#define AR9300_OTP_READ_DATA 0x15f1c
|
||||
|
||||
enum targetPowerHTRates {
|
||||
HT_TARGET_RATE_0_8_16,
|
||||
HT_TARGET_RATE_1_3_9_11_17_19,
|
||||
HT_TARGET_RATE_4,
|
||||
HT_TARGET_RATE_5,
|
||||
HT_TARGET_RATE_6,
|
||||
HT_TARGET_RATE_7,
|
||||
HT_TARGET_RATE_12,
|
||||
HT_TARGET_RATE_13,
|
||||
HT_TARGET_RATE_14,
|
||||
HT_TARGET_RATE_15,
|
||||
HT_TARGET_RATE_20,
|
||||
HT_TARGET_RATE_21,
|
||||
HT_TARGET_RATE_22,
|
||||
HT_TARGET_RATE_23
|
||||
};
|
||||
|
||||
enum targetPowerLegacyRates {
|
||||
LEGACY_TARGET_RATE_6_24,
|
||||
LEGACY_TARGET_RATE_36,
|
||||
LEGACY_TARGET_RATE_48,
|
||||
LEGACY_TARGET_RATE_54
|
||||
};
|
||||
|
||||
enum targetPowerCckRates {
|
||||
LEGACY_TARGET_RATE_1L_5L,
|
||||
LEGACY_TARGET_RATE_5S,
|
||||
LEGACY_TARGET_RATE_11L,
|
||||
LEGACY_TARGET_RATE_11S
|
||||
};
|
||||
|
||||
enum ar9300_Rates {
|
||||
ALL_TARGET_LEGACY_6_24,
|
||||
ALL_TARGET_LEGACY_36,
|
||||
ALL_TARGET_LEGACY_48,
|
||||
ALL_TARGET_LEGACY_54,
|
||||
ALL_TARGET_LEGACY_1L_5L,
|
||||
ALL_TARGET_LEGACY_5S,
|
||||
ALL_TARGET_LEGACY_11L,
|
||||
ALL_TARGET_LEGACY_11S,
|
||||
ALL_TARGET_HT20_0_8_16,
|
||||
ALL_TARGET_HT20_1_3_9_11_17_19,
|
||||
ALL_TARGET_HT20_4,
|
||||
ALL_TARGET_HT20_5,
|
||||
ALL_TARGET_HT20_6,
|
||||
ALL_TARGET_HT20_7,
|
||||
ALL_TARGET_HT20_12,
|
||||
ALL_TARGET_HT20_13,
|
||||
ALL_TARGET_HT20_14,
|
||||
ALL_TARGET_HT20_15,
|
||||
ALL_TARGET_HT20_20,
|
||||
ALL_TARGET_HT20_21,
|
||||
ALL_TARGET_HT20_22,
|
||||
ALL_TARGET_HT20_23,
|
||||
ALL_TARGET_HT40_0_8_16,
|
||||
ALL_TARGET_HT40_1_3_9_11_17_19,
|
||||
ALL_TARGET_HT40_4,
|
||||
ALL_TARGET_HT40_5,
|
||||
ALL_TARGET_HT40_6,
|
||||
ALL_TARGET_HT40_7,
|
||||
ALL_TARGET_HT40_12,
|
||||
ALL_TARGET_HT40_13,
|
||||
ALL_TARGET_HT40_14,
|
||||
ALL_TARGET_HT40_15,
|
||||
ALL_TARGET_HT40_20,
|
||||
ALL_TARGET_HT40_21,
|
||||
ALL_TARGET_HT40_22,
|
||||
ALL_TARGET_HT40_23,
|
||||
ar9300RateSize,
|
||||
};
|
||||
|
||||
|
||||
struct eepFlags {
|
||||
u8 opFlags;
|
||||
u8 eepMisc;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum CompressAlgorithm {
|
||||
_CompressNone = 0,
|
||||
_CompressLzma,
|
||||
_CompressPairs,
|
||||
_CompressBlock,
|
||||
_Compress4,
|
||||
_Compress5,
|
||||
_Compress6,
|
||||
_Compress7,
|
||||
};
|
||||
|
||||
struct ar9300_base_eep_hdr {
|
||||
uint16_t regDmn[2];
|
||||
/* 4 bits tx and 4 bits rx */
|
||||
u8 txrxMask;
|
||||
struct eepFlags opCapFlags;
|
||||
u8 rfSilent;
|
||||
u8 blueToothOptions;
|
||||
u8 deviceCap;
|
||||
/* takes lower byte in eeprom location */
|
||||
u8 deviceType;
|
||||
/* offset in dB to be added to beginning
|
||||
* of pdadc table in calibration
|
||||
*/
|
||||
int8_t pwrTableOffset;
|
||||
u8 params_for_tuning_caps[2];
|
||||
/*
|
||||
* bit0 - enable tx temp comp
|
||||
* bit1 - enable tx volt comp
|
||||
* bit2 - enable fastClock - default to 1
|
||||
* bit3 - enable doubling - default to 1
|
||||
* bit4 - enable internal regulator - default to 1
|
||||
*/
|
||||
u8 featureEnable;
|
||||
/* misc flags: bit0 - turn down drivestrength */
|
||||
u8 miscConfiguration;
|
||||
u8 eepromWriteEnableGpio;
|
||||
u8 wlanDisableGpio;
|
||||
u8 wlanLedGpio;
|
||||
u8 rxBandSelectGpio;
|
||||
u8 txrxgain;
|
||||
/* SW controlled internal regulator fields */
|
||||
uint32_t swreg;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9300_modal_eep_header {
|
||||
/* 4 idle, t1, t2, b (4 bits per setting) */
|
||||
uint32_t antCtrlCommon;
|
||||
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
||||
uint32_t antCtrlCommon2;
|
||||
/* 6 idle, t, r, rx1, rx12, b (2 bits each) */
|
||||
uint16_t antCtrlChain[AR9300_MAX_CHAINS];
|
||||
/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
||||
u8 xatten1DB[AR9300_MAX_CHAINS];
|
||||
/* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
|
||||
u8 xatten1Margin[AR9300_MAX_CHAINS];
|
||||
int8_t tempSlope;
|
||||
int8_t voltSlope;
|
||||
/* spur channels in usual fbin coding format */
|
||||
u8 spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
/* 3 Check if the register is per chain */
|
||||
int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
|
||||
u8 ob[AR9300_MAX_CHAINS];
|
||||
u8 db_stage2[AR9300_MAX_CHAINS];
|
||||
u8 db_stage3[AR9300_MAX_CHAINS];
|
||||
u8 db_stage4[AR9300_MAX_CHAINS];
|
||||
u8 xpaBiasLvl;
|
||||
u8 txFrameToDataStart;
|
||||
u8 txFrameToPaOn;
|
||||
u8 txClip;
|
||||
int8_t antennaGain;
|
||||
u8 switchSettling;
|
||||
int8_t adcDesiredSize;
|
||||
u8 txEndToXpaOff;
|
||||
u8 txEndToRxOn;
|
||||
u8 txFrameToXpaOn;
|
||||
u8 thresh62;
|
||||
uint32_t papdRateMaskHt20;
|
||||
uint32_t papdRateMaskHt40;
|
||||
u8 futureModal[10];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9300_cal_data_per_freq_op_loop {
|
||||
int8_t refPower;
|
||||
/* pdadc voltage at power measurement */
|
||||
u8 voltMeas;
|
||||
/* pcdac used for power measurement */
|
||||
u8 tempMeas;
|
||||
/* range is -60 to -127 create a mapping equation 1db resolution */
|
||||
int8_t rxNoisefloorCal;
|
||||
/*range is same as noisefloor */
|
||||
int8_t rxNoisefloorPower;
|
||||
/* temp measured when noisefloor cal was performed */
|
||||
u8 rxTempMeas;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_tgt_pow_legacy {
|
||||
u8 tPow2x[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_tgt_pow_ht {
|
||||
u8 tPow2x[14];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_data_2g {
|
||||
u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_data_5g {
|
||||
u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9300_BaseExtension_1 {
|
||||
u8 ant_div_control;
|
||||
u8 future[13];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9300_BaseExtension_2 {
|
||||
int8_t tempSlopeLow;
|
||||
int8_t tempSlopeHigh;
|
||||
u8 xatten1DBLow[AR9300_MAX_CHAINS];
|
||||
u8 xatten1MarginLow[AR9300_MAX_CHAINS];
|
||||
u8 xatten1DBHigh[AR9300_MAX_CHAINS];
|
||||
u8 xatten1MarginHigh[AR9300_MAX_CHAINS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9300_eeprom {
|
||||
u8 eepromVersion;
|
||||
u8 templateVersion;
|
||||
u8 macAddr[6];
|
||||
u8 custData[AR9300_CUSTOMER_DATA_SIZE];
|
||||
|
||||
struct ar9300_base_eep_hdr baseEepHeader;
|
||||
|
||||
struct ar9300_modal_eep_header modalHeader2G;
|
||||
struct ar9300_BaseExtension_1 base_ext1;
|
||||
u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
|
||||
struct ar9300_cal_data_per_freq_op_loop
|
||||
calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
|
||||
u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS];
|
||||
u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS];
|
||||
u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
|
||||
u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
|
||||
struct cal_tgt_pow_legacy
|
||||
calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct cal_tgt_pow_legacy
|
||||
calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_tgt_pow_ht
|
||||
calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_tgt_pow_ht
|
||||
calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
|
||||
u8 ctlIndex_2G[AR9300_NUM_CTLS_2G];
|
||||
u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
|
||||
struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
|
||||
struct ar9300_modal_eep_header modalHeader5G;
|
||||
struct ar9300_BaseExtension_2 base_ext2;
|
||||
u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
|
||||
struct ar9300_cal_data_per_freq_op_loop
|
||||
calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
|
||||
u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS];
|
||||
u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
|
||||
u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
|
||||
struct cal_tgt_pow_legacy
|
||||
calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS];
|
||||
struct cal_tgt_pow_ht
|
||||
calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
|
||||
struct cal_tgt_pow_ht
|
||||
calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
|
||||
u8 ctlIndex_5G[AR9300_NUM_CTLS_5G];
|
||||
u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G];
|
||||
struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G];
|
||||
} __attribute__((packed));
|
||||
|
||||
s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
|
||||
s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
|
||||
|
||||
u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, int is_2ghz);
|
||||
|
||||
unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
#endif
|
||||
125
src/drivers/net/ath/ath9k/ar9003_mac.h
Normal file
125
src/drivers/net/ath/ath9k/ar9003_mac.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef AR9003_MAC_H
|
||||
#define AR9003_MAC_H
|
||||
|
||||
#define AR_DescId 0xffff0000
|
||||
#define AR_DescId_S 16
|
||||
#define AR_CtrlStat 0x00004000
|
||||
#define AR_CtrlStat_S 14
|
||||
#define AR_TxRxDesc 0x00008000
|
||||
#define AR_TxRxDesc_S 15
|
||||
#define AR_TxQcuNum 0x00000f00
|
||||
#define AR_TxQcuNum_S 8
|
||||
|
||||
#define AR_BufLen 0x0fff0000
|
||||
#define AR_BufLen_S 16
|
||||
|
||||
#define AR_TxDescId 0xffff0000
|
||||
#define AR_TxDescId_S 16
|
||||
#define AR_TxPtrChkSum 0x0000ffff
|
||||
|
||||
#define AR_LowRxChain 0x00004000
|
||||
|
||||
#define AR_Not_Sounding 0x20000000
|
||||
|
||||
/* ctl 12 */
|
||||
#define AR_PAPRDChainMask 0x00000e00
|
||||
#define AR_PAPRDChainMask_S 9
|
||||
|
||||
#define MAP_ISR_S2_CST 6
|
||||
#define MAP_ISR_S2_GTT 6
|
||||
#define MAP_ISR_S2_TIM 3
|
||||
#define MAP_ISR_S2_CABEND 0
|
||||
#define MAP_ISR_S2_DTIMSYNC 7
|
||||
#define MAP_ISR_S2_DTIM 7
|
||||
#define MAP_ISR_S2_TSFOOR 4
|
||||
#define MAP_ISR_S2_BB_WATCHDOG 6
|
||||
|
||||
#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
|
||||
|
||||
struct ar9003_rxs {
|
||||
u32 ds_info;
|
||||
u32 status1;
|
||||
u32 status2;
|
||||
u32 status3;
|
||||
u32 status4;
|
||||
u32 status5;
|
||||
u32 status6;
|
||||
u32 status7;
|
||||
u32 status8;
|
||||
u32 status9;
|
||||
u32 status10;
|
||||
u32 status11;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
/* Transmit Control Descriptor */
|
||||
struct ar9003_txc {
|
||||
u32 info; /* descriptor information */
|
||||
u32 link; /* link pointer */
|
||||
u32 data0; /* data pointer to 1st buffer */
|
||||
u32 ctl3; /* DMA control 3 */
|
||||
u32 data1; /* data pointer to 2nd buffer */
|
||||
u32 ctl5; /* DMA control 5 */
|
||||
u32 data2; /* data pointer to 3rd buffer */
|
||||
u32 ctl7; /* DMA control 7 */
|
||||
u32 data3; /* data pointer to 4th buffer */
|
||||
u32 ctl9; /* DMA control 9 */
|
||||
u32 ctl10; /* DMA control 10 */
|
||||
u32 ctl11; /* DMA control 11 */
|
||||
u32 ctl12; /* DMA control 12 */
|
||||
u32 ctl13; /* DMA control 13 */
|
||||
u32 ctl14; /* DMA control 14 */
|
||||
u32 ctl15; /* DMA control 15 */
|
||||
u32 ctl16; /* DMA control 16 */
|
||||
u32 ctl17; /* DMA control 17 */
|
||||
u32 ctl18; /* DMA control 18 */
|
||||
u32 ctl19; /* DMA control 19 */
|
||||
u32 ctl20; /* DMA control 20 */
|
||||
u32 ctl21; /* DMA control 21 */
|
||||
u32 ctl22; /* DMA control 22 */
|
||||
u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct ar9003_txs {
|
||||
u32 ds_info;
|
||||
u32 status1;
|
||||
u32 status2;
|
||||
u32 status3;
|
||||
u32 status4;
|
||||
u32 status5;
|
||||
u32 status6;
|
||||
u32 status7;
|
||||
u32 status8;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
|
||||
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
|
||||
void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
|
||||
enum ath9k_rx_qtype qtype);
|
||||
|
||||
int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah,
|
||||
struct ath_rx_status *rxs,
|
||||
void *buf_addr);
|
||||
void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah);
|
||||
void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
|
||||
u32 ts_paddr_start,
|
||||
u8 size);
|
||||
#endif
|
||||
1124
src/drivers/net/ath/ath9k/ar9003_phy.h
Normal file
1124
src/drivers/net/ath/ath9k/ar9003_phy.h
Normal file
File diff suppressed because it is too large
Load Diff
1525
src/drivers/net/ath/ath9k/ar9340_initvals.h
Normal file
1525
src/drivers/net/ath/ath9k/ar9340_initvals.h
Normal file
File diff suppressed because it is too large
Load Diff
1161
src/drivers/net/ath/ath9k/ar9485_initvals.h
Normal file
1161
src/drivers/net/ath/ath9k/ar9485_initvals.h
Normal file
File diff suppressed because it is too large
Load Diff
208
src/drivers/net/ath/ath9k/ath9k.c
Normal file
208
src/drivers/net/ath/ath9k/ath9k.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/pci.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
static struct pci_device_id ath_pci_id_table[] = {
|
||||
PCI_ROM(0x168c, 0x0023, "ar5416", "Atheros 5416 PCI", 0), /* PCI */
|
||||
PCI_ROM(0x168c, 0x0024, "ar5416", "Atheros 5416 PCI-E", 0), /* PCI-E */
|
||||
PCI_ROM(0x168c, 0x0027, "ar9160", "Atheros 9160 PCI", 0), /* PCI */
|
||||
PCI_ROM(0x168c, 0x0029, "ar9280", "Atheros 9280 PCI", 0), /* PCI */
|
||||
PCI_ROM(0x168c, 0x002A, "ar9280", "Atheros 9280 PCI-E", 0), /* PCI-E */
|
||||
PCI_ROM(0x168c, 0x002B, "ar9285", "Atheros 9285 PCI-E", 0), /* PCI-E */
|
||||
PCI_ROM(0x168c, 0x002C, "ar2427", "Atheros 2427 PCI-E", 0), /* PCI-E 802.11n bonded out */
|
||||
PCI_ROM(0x168c, 0x002D, "ar9287", "Atheros 9287 PCI", 0), /* PCI */
|
||||
PCI_ROM(0x168c, 0x002E, "ar9287", "Atheros 9287 PCI-E", 0), /* PCI-E */
|
||||
PCI_ROM(0x168c, 0x0030, "ar9300", "Atheros 9300 PCI-E", 0), /* PCI-E AR9300 */
|
||||
PCI_ROM(0x168c, 0x0032, "ar9485", "Atheros 9485 PCI-E", 0), /* PCI-E AR9485 */
|
||||
};
|
||||
|
||||
|
||||
/* return bus cachesize in 4B word units */
|
||||
static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
u8 u8tmp;
|
||||
|
||||
pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
|
||||
*csz = (int)u8tmp;
|
||||
|
||||
/*
|
||||
* This check was put in to avoid "unpleasant" consequences if
|
||||
* the bootrom has not fully initialized all PCI devices.
|
||||
* Sometimes the cache line size register is not set
|
||||
*/
|
||||
|
||||
if (*csz == 0)
|
||||
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
|
||||
}
|
||||
|
||||
static int ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
|
||||
common->ops->read(ah, AR5416_EEPROM_OFFSET +
|
||||
(off << AR5416_EEPROM_S));
|
||||
|
||||
if (!ath9k_hw_wait(ah,
|
||||
AR_EEPROM_STATUS_DATA,
|
||||
AR_EEPROM_STATUS_DATA_BUSY |
|
||||
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
|
||||
AH_WAIT_TIMEOUT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
|
||||
AR_EEPROM_STATUS_DATA_VAL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ath_pci_extn_synch_enable(struct ath_common *common)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
struct pci_device *pdev = sc->pdev;
|
||||
u8 lnkctl;
|
||||
|
||||
pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
|
||||
lnkctl |= 0x0080;
|
||||
pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
|
||||
}
|
||||
|
||||
static const struct ath_bus_ops ath_pci_bus_ops = {
|
||||
.ath_bus_type = ATH_PCI,
|
||||
.read_cachesize = ath_pci_read_cachesize,
|
||||
.eeprom_read = ath_pci_eeprom_read,
|
||||
.extn_synch_en = ath_pci_extn_synch_enable,
|
||||
};
|
||||
|
||||
static int ath_pci_probe(struct pci_device *pdev)
|
||||
{
|
||||
void *mem;
|
||||
struct ath_softc *sc;
|
||||
struct net80211_device *dev;
|
||||
u8 csz;
|
||||
u16 subsysid;
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
char hw_name[64];
|
||||
|
||||
adjust_pci_device(pdev);
|
||||
|
||||
/*
|
||||
* Cache line size is used to size and align various
|
||||
* structures used to communicate with the hardware.
|
||||
*/
|
||||
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
|
||||
if (csz == 0) {
|
||||
/*
|
||||
* Linux 2.4.18 (at least) writes the cache line size
|
||||
* register as a 16-bit wide register which is wrong.
|
||||
* We must have this setup properly for rx buffer
|
||||
* DMA to work so force a reasonable value here if it
|
||||
* comes up zero.
|
||||
*/
|
||||
csz =16;
|
||||
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
|
||||
}
|
||||
/*
|
||||
* The default setting of latency timer yields poor results,
|
||||
* set it to the value used by other systems. It may be worth
|
||||
* tweaking this setting more.
|
||||
*/
|
||||
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
|
||||
|
||||
/*
|
||||
* Disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state.
|
||||
*/
|
||||
pci_read_config_dword(pdev, 0x40, &val);
|
||||
if ((val & 0x0000ff00) != 0)
|
||||
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
||||
|
||||
mem = ioremap(pdev->membase, 0x10000);
|
||||
if (!mem) {
|
||||
DBG("ath9K: PCI memory map error\n") ;
|
||||
ret = -EIO;
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
dev = net80211_alloc(sizeof(struct ath_softc));
|
||||
if (!dev) {
|
||||
DBG("ath9k: No memory for net80211_device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_hw;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
dev->netdev->dev = (struct device *)pdev;
|
||||
|
||||
sc = dev->priv;
|
||||
sc->dev = dev;
|
||||
sc->pdev = pdev;
|
||||
sc->mem = mem;
|
||||
|
||||
/* Will be cleared in ath9k_start() */
|
||||
sc->sc_flags |= SC_OP_INVALID;
|
||||
|
||||
sc->irq = pdev->irq;
|
||||
|
||||
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
|
||||
ret = ath9k_init_device(pdev->device, sc, subsysid, &ath_pci_bus_ops);
|
||||
if (ret) {
|
||||
DBG("ath9k: Failed to initialize device\n");
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
|
||||
DBG("ath9k: %s mem=0x%lx, irq=%d\n",
|
||||
hw_name, (unsigned long)mem, pdev->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_init:
|
||||
net80211_free(dev);
|
||||
err_alloc_hw:
|
||||
iounmap(mem);
|
||||
err_iomap:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath_pci_remove(struct pci_device *pdev)
|
||||
{
|
||||
struct net80211_device *dev = pci_get_drvdata(pdev);
|
||||
struct ath_softc *sc = dev->priv;
|
||||
void *mem = sc->mem;
|
||||
|
||||
if (!is_ath9k_unloaded)
|
||||
sc->sc_ah->ah_flags |= AH_UNPLUGGED;
|
||||
ath9k_deinit_device(sc);
|
||||
net80211_free(sc->dev);
|
||||
|
||||
iounmap(mem);
|
||||
}
|
||||
|
||||
struct pci_driver ath_pci_driver __pci_driver = {
|
||||
.id_count = ARRAY_SIZE(ath_pci_id_table),
|
||||
.ids = ath_pci_id_table,
|
||||
.probe = ath_pci_probe,
|
||||
.remove = ath_pci_remove,
|
||||
};
|
||||
521
src/drivers/net/ath/ath9k/ath9k.h
Normal file
521
src/drivers/net/ath/ath9k/ath9k.h
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH9K_H
|
||||
#define ATH9K_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Header for the ath9k.ko driver core *only* -- hw code nor any other driver
|
||||
* should rely on this file or its contents.
|
||||
*/
|
||||
|
||||
struct ath_node;
|
||||
struct ath_softc;
|
||||
|
||||
/* Macro to expand scalars to 64-bit objects */
|
||||
|
||||
#define ito64(x) (sizeof(x) == 1) ? \
|
||||
(((unsigned long long int)(x)) & (0xff)) : \
|
||||
(sizeof(x) == 2) ? \
|
||||
(((unsigned long long int)(x)) & 0xffff) : \
|
||||
((sizeof(x) == 4) ? \
|
||||
(((unsigned long long int)(x)) & 0xffffffff) : \
|
||||
(unsigned long long int)(x))
|
||||
|
||||
/* increment with wrap-around */
|
||||
#define INCR(_l, _sz) do { \
|
||||
(_l)++; \
|
||||
(_l) &= ((_sz) - 1); \
|
||||
} while (0)
|
||||
|
||||
/* decrement with wrap-around */
|
||||
#define DECR(_l, _sz) do { \
|
||||
(_l)--; \
|
||||
(_l) &= ((_sz) - 1); \
|
||||
} while (0)
|
||||
|
||||
#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define TSF_TO_TU(_h,_l) \
|
||||
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
|
||||
|
||||
#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
|
||||
|
||||
struct ath_config {
|
||||
u16 txpowlimit;
|
||||
u8 cabqReadytime;
|
||||
};
|
||||
|
||||
/*************************/
|
||||
/* Descriptor Management */
|
||||
/*************************/
|
||||
|
||||
#define ATH_TXBUF_RESET(_bf) do { \
|
||||
(_bf)->bf_stale = 0; \
|
||||
(_bf)->bf_lastbf = NULL; \
|
||||
(_bf)->bf_next = NULL; \
|
||||
memset(&((_bf)->bf_state), 0, \
|
||||
sizeof(struct ath_buf_state)); \
|
||||
} while (0)
|
||||
|
||||
#define ATH_RXBUF_RESET(_bf) do { \
|
||||
(_bf)->bf_stale = 0; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* enum buffer_type - Buffer type flags
|
||||
*
|
||||
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
|
||||
* @BUF_AGGR: Indicates whether the buffer can be aggregated
|
||||
* (used in aggregation scheduling)
|
||||
* @BUF_XRETRY: To denote excessive retries of the buffer
|
||||
*/
|
||||
enum buffer_type {
|
||||
BUF_AMPDU = BIT(0),
|
||||
BUF_AGGR = BIT(1),
|
||||
BUF_XRETRY = BIT(2),
|
||||
};
|
||||
|
||||
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
|
||||
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
|
||||
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
|
||||
|
||||
#define ATH_TXSTATUS_RING_SIZE 64
|
||||
|
||||
struct ath_descdma {
|
||||
void *dd_desc;
|
||||
u32 dd_desc_paddr;
|
||||
u32 dd_desc_len;
|
||||
struct ath_buf *dd_bufptr;
|
||||
};
|
||||
|
||||
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head, const char *name,
|
||||
int nbuf, int ndesc, int is_tx);
|
||||
void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head);
|
||||
|
||||
/***********/
|
||||
/* RX / TX */
|
||||
/***********/
|
||||
|
||||
#define ATH_RXBUF 16
|
||||
#define ATH_TXBUF 16
|
||||
#define ATH_TXBUF_RESERVE 5
|
||||
#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
|
||||
#define ATH_TXMAXTRY 13
|
||||
|
||||
#define TID_TO_WME_AC(_tid) \
|
||||
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
|
||||
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
|
||||
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
|
||||
WME_AC_VO)
|
||||
|
||||
#define ATH_AGGR_DELIM_SZ 4
|
||||
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
|
||||
/* number of delimiters for encryption padding */
|
||||
#define ATH_AGGR_ENCRYPTDELIM 10
|
||||
/* minimum h/w qdepth to be sustained to maximize aggregation */
|
||||
#define ATH_AGGR_MIN_QDEPTH 2
|
||||
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
|
||||
|
||||
#define FCS_LEN 4
|
||||
#define IEEE80211_SEQ_SEQ_SHIFT 4
|
||||
#define IEEE80211_SEQ_MAX 4096
|
||||
#define IEEE80211_WEP_IVLEN 3
|
||||
#define IEEE80211_WEP_KIDLEN 1
|
||||
#define IEEE80211_WEP_CRCLEN 4
|
||||
#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \
|
||||
(IEEE80211_WEP_IVLEN + \
|
||||
IEEE80211_WEP_KIDLEN + \
|
||||
IEEE80211_WEP_CRCLEN))
|
||||
|
||||
/* return whether a bit at index _n in bitmap _bm is set
|
||||
* _sz is the size of the bitmap */
|
||||
#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
|
||||
((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
|
||||
|
||||
/* return block-ack bitmap index given sequence and starting sequence */
|
||||
#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
|
||||
|
||||
/* returns delimiter padding required given the packet length */
|
||||
#define ATH_AGGR_GET_NDELIM(_len) \
|
||||
(((_len) >= ATH_AGGR_MINPLEN) ? 0 : \
|
||||
DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
|
||||
|
||||
#define BAW_WITHIN(_start, _bawsz, _seqno) \
|
||||
((((_seqno) - (_start)) & 4095) < (_bawsz))
|
||||
|
||||
#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
|
||||
|
||||
#define ATH_TX_COMPLETE_POLL_INT 1000
|
||||
|
||||
enum ATH_AGGR_STATUS {
|
||||
ATH_AGGR_DONE,
|
||||
ATH_AGGR_BAW_CLOSED,
|
||||
ATH_AGGR_LIMITED,
|
||||
};
|
||||
|
||||
#define ATH_TXFIFO_DEPTH 8
|
||||
struct ath_txq {
|
||||
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
|
||||
u32 axq_qnum; /* ath9k hardware queue number */
|
||||
u32 *axq_link;
|
||||
struct list_head axq_q;
|
||||
u32 axq_depth;
|
||||
u32 axq_ampdu_depth;
|
||||
int stopped;
|
||||
int axq_tx_inprogress;
|
||||
struct list_head axq_acq;
|
||||
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
|
||||
struct list_head txq_fifo_pending;
|
||||
u8 txq_headidx;
|
||||
u8 txq_tailidx;
|
||||
int pending_frames;
|
||||
};
|
||||
|
||||
struct ath_atx_ac {
|
||||
struct ath_txq *txq;
|
||||
int sched;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
int clear_ps_filter;
|
||||
};
|
||||
|
||||
struct ath_frame_info {
|
||||
int framelen;
|
||||
u32 keyix;
|
||||
enum ath9k_key_type keytype;
|
||||
u8 retries;
|
||||
u16 seqno;
|
||||
};
|
||||
|
||||
struct ath_buf_state {
|
||||
u8 bf_type;
|
||||
u8 bfs_paprd;
|
||||
unsigned long bfs_paprd_timestamp;
|
||||
};
|
||||
|
||||
struct ath_buf {
|
||||
struct list_head list;
|
||||
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
|
||||
an aggregate) */
|
||||
struct ath_buf *bf_next; /* next subframe in the aggregate */
|
||||
struct io_buffer *bf_mpdu; /* enclosing frame structure */
|
||||
void *bf_desc; /* virtual addr of desc */
|
||||
u32 bf_daddr; /* physical addr of desc */
|
||||
u32 bf_buf_addr; /* physical addr of data buffer, for DMA */
|
||||
int bf_stale;
|
||||
u16 bf_flags;
|
||||
struct ath_buf_state bf_state;
|
||||
};
|
||||
|
||||
struct ath_atx_tid {
|
||||
struct list_head list;
|
||||
struct list_head buf_q;
|
||||
struct ath_node *an;
|
||||
struct ath_atx_ac *ac;
|
||||
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
|
||||
u16 seq_start;
|
||||
u16 seq_next;
|
||||
u16 baw_size;
|
||||
int tidno;
|
||||
int baw_head; /* first un-acked tx buffer */
|
||||
int baw_tail; /* next unused tx buffer slot */
|
||||
int sched;
|
||||
int paused;
|
||||
u8 state;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
int ps_key;
|
||||
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
|
||||
int sleeping;
|
||||
};
|
||||
|
||||
#define AGGR_CLEANUP BIT(1)
|
||||
#define AGGR_ADDBA_COMPLETE BIT(2)
|
||||
#define AGGR_ADDBA_PROGRESS BIT(3)
|
||||
|
||||
struct ath_tx_control {
|
||||
struct ath_txq *txq;
|
||||
struct ath_node *an;
|
||||
int if_id;
|
||||
u8 paprd;
|
||||
};
|
||||
|
||||
#define ATH_TX_ERROR 0x01
|
||||
#define ATH_TX_XRETRY 0x02
|
||||
#define ATH_TX_BAR 0x04
|
||||
|
||||
/**
|
||||
* @txq_map: Index is mac80211 queue number. This is
|
||||
* not necessarily the same as the hardware queue number
|
||||
* (axq_qnum).
|
||||
*/
|
||||
struct ath_tx {
|
||||
u16 seq_no;
|
||||
u32 txqsetup;
|
||||
struct list_head txbuf;
|
||||
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
|
||||
struct ath_descdma txdma;
|
||||
struct ath_txq *txq_map[WME_NUM_AC];
|
||||
};
|
||||
|
||||
struct ath_rx_edma {
|
||||
struct list_head rx_fifo;
|
||||
struct list_head rx_buffers;
|
||||
u32 rx_fifo_hwsize;
|
||||
};
|
||||
|
||||
struct ath_rx {
|
||||
u8 defant;
|
||||
u8 rxotherant;
|
||||
u32 *rxlink;
|
||||
unsigned int rxfilter;
|
||||
struct list_head rxbuf;
|
||||
struct ath_descdma rxdma;
|
||||
struct ath_buf *rx_bufptr;
|
||||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
|
||||
struct io_buffer *frag;
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
int ath_stoprecv(struct ath_softc *sc);
|
||||
void ath_flushrecv(struct ath_softc *sc);
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||
int ath_rx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_rx_cleanup(struct ath_softc *sc);
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp);
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
|
||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
|
||||
int ath_drain_all_txq(struct ath_softc *sc, int retry_tx);
|
||||
void ath_draintxq(struct ath_softc *sc,
|
||||
struct ath_txq *txq, int retry_tx);
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_tx_cleanup(struct ath_softc *sc);
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *q);
|
||||
int ath_tx_start(struct net80211_device *dev, struct io_buffer *iob,
|
||||
struct ath_tx_control *txctl);
|
||||
void ath_tx_tasklet(struct ath_softc *sc);
|
||||
|
||||
/*******/
|
||||
/* ANI */
|
||||
/*******/
|
||||
|
||||
#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */
|
||||
#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
|
||||
#define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */
|
||||
#define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */
|
||||
#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
|
||||
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
|
||||
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
|
||||
|
||||
void ath_hw_pll_work(struct ath_softc *sc);
|
||||
void ath_ani_calibrate(struct ath_softc *sc);
|
||||
|
||||
/********************/
|
||||
/* Main driver core */
|
||||
/********************/
|
||||
|
||||
/*
|
||||
* Default cache line size, in bytes.
|
||||
* Used when PCI device not fully initialized by bootrom/BIOS
|
||||
*/
|
||||
#define DEFAULT_CACHELINE 32
|
||||
#define ATH_REGCLASSIDS_MAX 10
|
||||
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
|
||||
#define ATH_MAX_SW_RETRIES 10
|
||||
#define ATH_CHAN_MAX 255
|
||||
|
||||
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
|
||||
#define ATH_RATE_DUMMY_MARKER 0
|
||||
|
||||
#define SC_OP_INVALID BIT(0)
|
||||
#define SC_OP_BEACONS BIT(1)
|
||||
#define SC_OP_RXAGGR BIT(2)
|
||||
#define SC_OP_TXAGGR BIT(3)
|
||||
#define SC_OP_OFFCHANNEL BIT(4)
|
||||
#define SC_OP_PREAMBLE_SHORT BIT(5)
|
||||
#define SC_OP_PROTECT_ENABLE BIT(6)
|
||||
#define SC_OP_RXFLUSH BIT(7)
|
||||
#define SC_OP_LED_ASSOCIATED BIT(8)
|
||||
#define SC_OP_LED_ON BIT(9)
|
||||
#define SC_OP_TSF_RESET BIT(11)
|
||||
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
|
||||
#define SC_OP_BT_SCAN BIT(13)
|
||||
#define SC_OP_ANI_RUN BIT(14)
|
||||
#define SC_OP_ENABLE_APM BIT(15)
|
||||
#define SC_OP_PRIM_STA_VIF BIT(16)
|
||||
|
||||
/* Powersave flags */
|
||||
#define PS_WAIT_FOR_BEACON BIT(0)
|
||||
#define PS_WAIT_FOR_CAB BIT(1)
|
||||
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
|
||||
#define PS_WAIT_FOR_TX_ACK BIT(3)
|
||||
#define PS_BEACON_SYNC BIT(4)
|
||||
#define PS_TSFOOR_SYNC BIT(5)
|
||||
|
||||
struct ath_rate_table;
|
||||
|
||||
struct ath9k_legacy_rate {
|
||||
u16 bitrate;
|
||||
u32 flags;
|
||||
u16 hw_value;
|
||||
u16 hw_value_short;
|
||||
};
|
||||
|
||||
enum ath9k_rate_control_flags {
|
||||
IEEE80211_TX_RC_USE_RTS_CTS = BIT(0),
|
||||
IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
|
||||
IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
|
||||
|
||||
/* rate index is an MCS rate number instead of an index */
|
||||
IEEE80211_TX_RC_MCS = BIT(3),
|
||||
IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
|
||||
IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
|
||||
IEEE80211_TX_RC_DUP_DATA = BIT(6),
|
||||
IEEE80211_TX_RC_SHORT_GI = BIT(7),
|
||||
};
|
||||
|
||||
struct survey_info {
|
||||
struct net80211_channel *channel;
|
||||
u64 channel_time;
|
||||
u64 channel_time_busy;
|
||||
u64 channel_time_ext_busy;
|
||||
u64 channel_time_rx;
|
||||
u64 channel_time_tx;
|
||||
u32 filled;
|
||||
s8 noise;
|
||||
};
|
||||
|
||||
enum survey_info_flags {
|
||||
SURVEY_INFO_NOISE_DBM = 1<<0,
|
||||
SURVEY_INFO_IN_USE = 1<<1,
|
||||
SURVEY_INFO_CHANNEL_TIME = 1<<2,
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
|
||||
SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
|
||||
SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
|
||||
SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
|
||||
};
|
||||
|
||||
struct ath9k_vif_iter_data {
|
||||
const u8 *hw_macaddr; /* phy's hardware address, set
|
||||
* before starting iteration for
|
||||
* valid bssid mask.
|
||||
*/
|
||||
u8 mask[ETH_ALEN]; /* bssid mask */
|
||||
int naps; /* number of AP vifs */
|
||||
int nmeshes; /* number of mesh vifs */
|
||||
int nstations; /* number of station vifs */
|
||||
int nwds; /* number of nwd vifs */
|
||||
int nadhocs; /* number of adhoc vifs */
|
||||
int nothers; /* number of vifs not specified above. */
|
||||
};
|
||||
|
||||
struct ath_softc {
|
||||
struct net80211_device *dev;
|
||||
struct pci_device *pdev;
|
||||
|
||||
int chan_idx;
|
||||
int chan_is_ht;
|
||||
struct survey_info *cur_survey;
|
||||
struct survey_info survey[ATH9K_NUM_CHANNELS];
|
||||
|
||||
void (*intr_tq)(struct ath_softc *sc);
|
||||
struct ath_hw *sc_ah;
|
||||
void *mem;
|
||||
int irq;
|
||||
|
||||
void (*paprd_work)(struct ath_softc *sc);
|
||||
void (*hw_check_work)(struct ath_softc *sc);
|
||||
void (*paprd_complete)(struct ath_softc *sc);
|
||||
|
||||
unsigned int hw_busy_count;
|
||||
|
||||
u32 intrstatus;
|
||||
u32 sc_flags; /* SC_OP_* */
|
||||
u16 ps_flags; /* PS_* */
|
||||
u16 curtxpow;
|
||||
int ps_enabled;
|
||||
int ps_idle;
|
||||
short nbcnvifs;
|
||||
short nvifs;
|
||||
unsigned long ps_usecount;
|
||||
|
||||
struct ath_config config;
|
||||
struct ath_rx rx;
|
||||
struct ath_tx tx;
|
||||
struct net80211_hw_info *hwinfo;
|
||||
struct ath9k_legacy_rate rates[NET80211_MAX_RATES];
|
||||
int hw_rix;
|
||||
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
int last_rssi;
|
||||
|
||||
void (*tx_complete_work)(struct ath_softc *sc);
|
||||
unsigned long tx_complete_work_timer;
|
||||
void (*hw_pll_work)(struct ath_softc *sc);
|
||||
unsigned long hw_pll_work_timer;
|
||||
|
||||
struct ath_descdma txsdma;
|
||||
};
|
||||
|
||||
void ath9k_tasklet(struct ath_softc *sc);
|
||||
int ath_reset(struct ath_softc *sc, int retry_tx);
|
||||
|
||||
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||
{
|
||||
common->bus_ops->read_cachesize(common, csz);
|
||||
}
|
||||
|
||||
extern struct net80211_device_operations ath9k_ops;
|
||||
extern int ath9k_modparam_nohwcrypt;
|
||||
extern int is_ath9k_unloaded;
|
||||
|
||||
void ath_isr(struct net80211_device *dev);
|
||||
void ath9k_init_crypto(struct ath_softc *sc);
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops);
|
||||
void ath9k_deinit_device(struct ath_softc *sc);
|
||||
void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev);
|
||||
int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev,
|
||||
struct ath9k_channel *hchan);
|
||||
|
||||
void ath_radio_enable(struct ath_softc *sc, struct net80211_device *dev);
|
||||
void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev);
|
||||
int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
|
||||
int ath9k_uses_beacons(int type);
|
||||
|
||||
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
|
||||
|
||||
void ath_start_rfkill_poll(struct ath_softc *sc);
|
||||
extern void ath9k_rfkill_poll_state(struct net80211_device *dev);
|
||||
|
||||
#endif /* ATH9K_H */
|
||||
733
src/drivers/net/ath/ath9k/ath9k_ani.c
Normal file
733
src/drivers/net/ath/ath9k/ath9k_ani.c
Normal file
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
|
||||
struct ani_ofdm_level_entry {
|
||||
int spur_immunity_level;
|
||||
int fir_step_level;
|
||||
int ofdm_weak_signal_on;
|
||||
};
|
||||
|
||||
/* values here are relative to the INI */
|
||||
|
||||
/*
|
||||
* Legend:
|
||||
*
|
||||
* SI: Spur immunity
|
||||
* FS: FIR Step
|
||||
* WS: OFDM / CCK Weak Signal detection
|
||||
* MRC-CCK: Maximal Ratio Combining for CCK
|
||||
*/
|
||||
|
||||
static const struct ani_ofdm_level_entry ofdm_level_table[] = {
|
||||
/* SI FS WS */
|
||||
{ 0, 0, 1 }, /* lvl 0 */
|
||||
{ 1, 1, 1 }, /* lvl 1 */
|
||||
{ 2, 2, 1 }, /* lvl 2 */
|
||||
{ 3, 2, 1 }, /* lvl 3 (default) */
|
||||
{ 4, 3, 1 }, /* lvl 4 */
|
||||
{ 5, 4, 1 }, /* lvl 5 */
|
||||
{ 6, 5, 1 }, /* lvl 6 */
|
||||
{ 7, 6, 1 }, /* lvl 7 */
|
||||
{ 7, 7, 1 }, /* lvl 8 */
|
||||
{ 7, 8, 0 } /* lvl 9 */
|
||||
};
|
||||
#define ATH9K_ANI_OFDM_NUM_LEVEL \
|
||||
ARRAY_SIZE(ofdm_level_table)
|
||||
#define ATH9K_ANI_OFDM_MAX_LEVEL \
|
||||
(ATH9K_ANI_OFDM_NUM_LEVEL-1)
|
||||
#define ATH9K_ANI_OFDM_DEF_LEVEL \
|
||||
3 /* default level - matches the INI settings */
|
||||
|
||||
/*
|
||||
* MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
|
||||
* With OFDM for single stream you just add up all antenna inputs, you're
|
||||
* only interested in what you get after FFT. Signal aligment is also not
|
||||
* required for OFDM because any phase difference adds up in the frequency
|
||||
* domain.
|
||||
*
|
||||
* MRC requires extra work for use with CCK. You need to align the antenna
|
||||
* signals from the different antenna before you can add the signals together.
|
||||
* You need aligment of signals as CCK is in time domain, so addition can cancel
|
||||
* your signal completely if phase is 180 degrees (think of adding sine waves).
|
||||
* You also need to remove noise before the addition and this is where ANI
|
||||
* MRC CCK comes into play. One of the antenna inputs may be stronger but
|
||||
* lower SNR, so just adding after alignment can be dangerous.
|
||||
*
|
||||
* Regardless of alignment in time, the antenna signals add constructively after
|
||||
* FFT and improve your reception. For more information:
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Maximal-ratio_combining
|
||||
*/
|
||||
|
||||
struct ani_cck_level_entry {
|
||||
int fir_step_level;
|
||||
int mrc_cck_on;
|
||||
};
|
||||
|
||||
static const struct ani_cck_level_entry cck_level_table[] = {
|
||||
/* FS MRC-CCK */
|
||||
{ 0, 1 }, /* lvl 0 */
|
||||
{ 1, 1 }, /* lvl 1 */
|
||||
{ 2, 1 }, /* lvl 2 (default) */
|
||||
{ 3, 1 }, /* lvl 3 */
|
||||
{ 4, 0 }, /* lvl 4 */
|
||||
{ 5, 0 }, /* lvl 5 */
|
||||
{ 6, 0 }, /* lvl 6 */
|
||||
{ 7, 0 }, /* lvl 7 (only for high rssi) */
|
||||
{ 8, 0 } /* lvl 8 (only for high rssi) */
|
||||
};
|
||||
|
||||
#define ATH9K_ANI_CCK_NUM_LEVEL \
|
||||
ARRAY_SIZE(cck_level_table)
|
||||
#define ATH9K_ANI_CCK_MAX_LEVEL \
|
||||
(ATH9K_ANI_CCK_NUM_LEVEL-1)
|
||||
#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
|
||||
(ATH9K_ANI_CCK_NUM_LEVEL-3)
|
||||
#define ATH9K_ANI_CCK_DEF_LEVEL \
|
||||
2 /* default level - matches the INI settings */
|
||||
|
||||
static int use_new_ani(struct ath_hw *ah)
|
||||
{
|
||||
return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
|
||||
}
|
||||
|
||||
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
|
||||
struct ath9k_mib_stats *stats)
|
||||
{
|
||||
stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
|
||||
stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
|
||||
stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
|
||||
stats->rts_good += REG_READ(ah, AR_RTS_OK);
|
||||
stats->beacons += REG_READ(ah, AR_BEACON_CNT);
|
||||
}
|
||||
|
||||
static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
u32 ofdm_base = 0, cck_base = 0;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
aniState->listenTime = 0;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
|
||||
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
|
||||
}
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Writing ofdmbase=%d cckbase=%d\n", ofdm_base, cck_base);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
|
||||
aniState->ofdmPhyErrCount = 0;
|
||||
aniState->cckPhyErrCount = 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
if (!aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
0)) {
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
}
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
1);
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
} else {
|
||||
if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
|
||||
if (!aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
0);
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
} else {
|
||||
if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the OFDM Noise Immunity Level */
|
||||
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
|
||||
{
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
const struct ani_ofdm_level_entry *entry_ofdm;
|
||||
const struct ani_cck_level_entry *entry_cck;
|
||||
|
||||
aniState->noiseFloor = BEACON_RSSI(ah);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
immunityLevel, aniState->noiseFloor,
|
||||
aniState->rssiThrLow, aniState->rssiThrHigh);
|
||||
|
||||
aniState->ofdmNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
|
||||
if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
entry_ofdm->spur_immunity_level);
|
||||
|
||||
if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
|
||||
entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
entry_ofdm->fir_step_level);
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_ofdm_err_trigger_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
|
||||
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the ANI settings to match an CCK level.
|
||||
*/
|
||||
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, uint8_t immunityLevel)
|
||||
{
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
const struct ani_ofdm_level_entry *entry_ofdm;
|
||||
const struct ani_cck_level_entry *entry_cck;
|
||||
|
||||
aniState->noiseFloor = BEACON_RSSI(ah);
|
||||
DBG2("ath9k: "
|
||||
"**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->cckNoiseImmunityLevel, immunityLevel,
|
||||
aniState->noiseFloor, aniState->rssiThrLow,
|
||||
aniState->rssiThrHigh);
|
||||
|
||||
if (aniState->noiseFloor <= (unsigned int)aniState->rssiThrLow &&
|
||||
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
|
||||
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
|
||||
|
||||
aniState->cckNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
|
||||
if (aniState->firstepLevel != entry_cck->fir_step_level &&
|
||||
entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
entry_cck->fir_step_level);
|
||||
|
||||
/* Skip MRC CCK for pre AR9003 families */
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
|
||||
return;
|
||||
|
||||
if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_MRC_CCK,
|
||||
entry_cck->mrc_cck_on);
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_cck_err_trigger_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
|
||||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
/* XXX: Handle me */
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
1) == 1)
|
||||
return;
|
||||
}
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1) == 1)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1) == 1)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel - 1))
|
||||
return;
|
||||
}
|
||||
|
||||
if (aniState->noiseImmunityLevel > 0) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only lower either OFDM or CCK errors per turn
|
||||
* we lower the other one next time
|
||||
*/
|
||||
static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_lower_immunity_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
/* lower OFDM noise immunity */
|
||||
if (aniState->ofdmNoiseImmunityLevel > 0 &&
|
||||
(aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
|
||||
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* lower CCK noise immunity */
|
||||
if (aniState->cckNoiseImmunityLevel > 0)
|
||||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
|
||||
}
|
||||
|
||||
static void ath9k_ani_reset_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->noiseImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel);
|
||||
if (aniState->spurImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel);
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
if (aniState->cckWeakSigThreshold)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
|
||||
aniState->cckWeakSigThreshold);
|
||||
if (aniState->firstepLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel);
|
||||
|
||||
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
|
||||
~ATH9K_RX_FILTER_PHYERR);
|
||||
ath9k_ani_restart(ah);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the ANI parameters in the HAL and reset the statistics.
|
||||
* This routine should be called for every hardware reset and for
|
||||
* every channel change.
|
||||
*/
|
||||
void ath9k_ani_reset(struct ath_hw *ah, int is_scanning)
|
||||
{
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah))
|
||||
return ath9k_ani_reset_old(ah);
|
||||
|
||||
ah->stats.ast_ani_reset++;
|
||||
|
||||
/* always allow mode (on/off) to be controlled */
|
||||
ah->ani_function |= ATH9K_ANI_MODE;
|
||||
|
||||
if (is_scanning) {
|
||||
/*
|
||||
* If we're scanning or in AP mode, the defaults (ini)
|
||||
* should be in place. For an AP we assume the historical
|
||||
* levels for this channel are probably outdated so start
|
||||
* from defaults instead.
|
||||
*/
|
||||
if (aniState->ofdmNoiseImmunityLevel !=
|
||||
ATH9K_ANI_OFDM_DEF_LEVEL ||
|
||||
aniState->cckNoiseImmunityLevel !=
|
||||
ATH9K_ANI_CCK_DEF_LEVEL) {
|
||||
DBG("ath9k: "
|
||||
"Restore defaults: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
|
||||
chan->channel,
|
||||
chan->channelFlags,
|
||||
is_scanning,
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
|
||||
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* restore historical levels for this channel
|
||||
*/
|
||||
DBG2("ath9k: "
|
||||
"Restore history: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
|
||||
chan->channel,
|
||||
chan->channelFlags,
|
||||
is_scanning,
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
ath9k_hw_set_ofdm_nil(ah,
|
||||
aniState->ofdmNoiseImmunityLevel);
|
||||
ath9k_hw_set_cck_nil(ah,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
}
|
||||
|
||||
/*
|
||||
* enable phy counters if hw supports or if not, enable phy
|
||||
* interrupts (so we can count each one)
|
||||
*/
|
||||
ath9k_ani_restart(ah);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
static int ath9k_hw_ani_read_counters(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
u32 ofdm_base = 0;
|
||||
u32 cck_base = 0;
|
||||
u32 ofdmPhyErrCnt, cckPhyErrCnt;
|
||||
u32 phyCnt1, phyCnt2;
|
||||
int32_t listenTime;
|
||||
|
||||
ath_hw_cycle_counters_update(common);
|
||||
listenTime = ath_hw_get_listen_time(common);
|
||||
|
||||
if (listenTime <= 0) {
|
||||
ah->stats.ast_ani_lneg++;
|
||||
ath9k_ani_restart(ah);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
|
||||
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
|
||||
}
|
||||
|
||||
aniState->listenTime += listenTime;
|
||||
|
||||
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
|
||||
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
|
||||
|
||||
if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
|
||||
if (phyCnt1 < ofdm_base) {
|
||||
DBG2("ath9k: "
|
||||
"phyCnt1 0x%x, resetting counter value to 0x%x\n",
|
||||
phyCnt1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
|
||||
AR_PHY_ERR_OFDM_TIMING);
|
||||
}
|
||||
if (phyCnt2 < cck_base) {
|
||||
DBG2("ath9k: "
|
||||
"phyCnt2 0x%x, resetting counter value to 0x%x\n",
|
||||
phyCnt2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
|
||||
AR_PHY_ERR_CCK_TIMING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ofdmPhyErrCnt = phyCnt1 - ofdm_base;
|
||||
ah->stats.ast_ani_ofdmerrs +=
|
||||
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
|
||||
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
|
||||
|
||||
cckPhyErrCnt = phyCnt2 - cck_base;
|
||||
ah->stats.ast_ani_cckerrs +=
|
||||
cckPhyErrCnt - aniState->cckPhyErrCount;
|
||||
aniState->cckPhyErrCount = cckPhyErrCnt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan __unused)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
u32 ofdmPhyErrRate, cckPhyErrRate;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
if (!aniState)
|
||||
return;
|
||||
|
||||
if (!ath9k_hw_ani_read_counters(ah))
|
||||
return;
|
||||
|
||||
ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
|
||||
aniState->listenTime;
|
||||
cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
|
||||
aniState->listenTime;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
|
||||
aniState->listenTime,
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
|
||||
cckPhyErrRate, aniState->ofdmsTurn);
|
||||
|
||||
if (aniState->listenTime > 5 * ah->aniperiod) {
|
||||
if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
|
||||
cckPhyErrRate <= ah->config.cck_trig_low) {
|
||||
ath9k_hw_ani_lower_immunity(ah);
|
||||
aniState->ofdmsTurn = !aniState->ofdmsTurn;
|
||||
}
|
||||
ath9k_ani_restart(ah);
|
||||
} else if (aniState->listenTime > ah->aniperiod) {
|
||||
/* check to see if need to raise immunity */
|
||||
if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
|
||||
(cckPhyErrRate <= ah->config.cck_trig_high ||
|
||||
aniState->ofdmsTurn)) {
|
||||
ath9k_hw_ani_ofdm_err_trigger(ah);
|
||||
ath9k_ani_restart(ah);
|
||||
aniState->ofdmsTurn = 0;
|
||||
} else if (cckPhyErrRate > ah->config.cck_trig_high) {
|
||||
ath9k_hw_ani_cck_err_trigger(ah);
|
||||
ath9k_ani_restart(ah);
|
||||
aniState->ofdmsTurn = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
|
||||
static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
|
||||
static const int coarseLow[] = { -64, -64, -64, -64, -70 };
|
||||
static const int firpwr[] = { -78, -78, -78, -78, -80 };
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ah->totalSizeDesired[i] = totalSizeDesired[i];
|
||||
ah->coarse_high[i] = coarseHigh[i];
|
||||
ah->coarse_low[i] = coarseLow[i];
|
||||
ah->firpwr[i] = firpwr[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
DBG2("ath9k: Initialize ANI\n");
|
||||
|
||||
if (use_new_ani(ah)) {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
|
||||
|
||||
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
|
||||
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
|
||||
} else {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
|
||||
|
||||
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
|
||||
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
|
||||
struct ath9k_channel *chan = &ah->channels[i];
|
||||
struct ar5416AniState *ani = &chan->ani;
|
||||
|
||||
if (use_new_ani(ah)) {
|
||||
ani->spurImmunityLevel =
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
|
||||
|
||||
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ani->mrcCCKOff =
|
||||
!ATH9K_ANI_ENABLE_MRC_CCK;
|
||||
else
|
||||
ani->mrcCCKOff = 1;
|
||||
|
||||
ani->ofdmsTurn = 1;
|
||||
} else {
|
||||
ani->spurImmunityLevel =
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
|
||||
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
|
||||
|
||||
ani->cckWeakSigThreshold =
|
||||
ATH9K_ANI_CCK_WEAK_SIG_THR;
|
||||
}
|
||||
|
||||
ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
|
||||
ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
|
||||
ani->ofdmWeakSigDetectOff =
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
}
|
||||
|
||||
/*
|
||||
* since we expect some ongoing maintenance on the tables, let's sanity
|
||||
* check here default level should not modify INI setting.
|
||||
*/
|
||||
if (use_new_ani(ah)) {
|
||||
ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
|
||||
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
|
||||
} else {
|
||||
ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
|
||||
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
|
||||
}
|
||||
|
||||
if (ah->config.enable_ani)
|
||||
ah->proc_phyerr |= HAL_PROCESS_ANI;
|
||||
|
||||
ath9k_ani_restart(ah);
|
||||
}
|
||||
1663
src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c
Normal file
1663
src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
997
src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c
Normal file
997
src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c
Normal file
@@ -0,0 +1,997 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
#include "ar9002_phy.h"
|
||||
|
||||
#define AR9285_CLCAL_REDO_THRESH 1
|
||||
|
||||
enum ar9002_cal_types {
|
||||
ADC_GAIN_CAL = BIT(0),
|
||||
ADC_DC_CAL = BIT(1),
|
||||
IQ_MISMATCH_CAL = BIT(2),
|
||||
};
|
||||
|
||||
static int ar9002_hw_is_cal_supported(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ar9002_cal_types cal_type)
|
||||
{
|
||||
int supported = 0;
|
||||
switch (ah->supp_cals & cal_type) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
/* Run IQ Mismatch for non-CCK only */
|
||||
if (!IS_CHAN_B(chan))
|
||||
supported = 1;
|
||||
break;
|
||||
case ADC_GAIN_CAL:
|
||||
case ADC_DC_CAL:
|
||||
/* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
|
||||
if (!IS_CHAN_B(chan) &&
|
||||
!(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
|
||||
supported = 1;
|
||||
break;
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
static void ar9002_hw_setup_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
|
||||
currCal->calData->calCountMax);
|
||||
|
||||
switch (currCal->calData->calType) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
|
||||
DBG2("ath9k: "
|
||||
"starting IQ Mismatch Calibration\n");
|
||||
break;
|
||||
case ADC_GAIN_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
|
||||
DBG2("ath9k: "
|
||||
"starting ADC Gain Calibration\n");
|
||||
break;
|
||||
case ADC_DC_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
|
||||
DBG2("ath9k: "
|
||||
"starting ADC DC Calibration\n");
|
||||
break;
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_DO_CAL);
|
||||
}
|
||||
|
||||
static int ar9002_hw_per_calibration(struct ath_hw *ah,
|
||||
struct ath9k_channel *ichan __unused,
|
||||
u8 rxchainmask,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
int iscaldone = 0;
|
||||
|
||||
if (currCal->calState == CAL_RUNNING) {
|
||||
if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
|
||||
AR_PHY_TIMING_CTRL4_DO_CAL)) {
|
||||
|
||||
currCal->calData->calCollect(ah);
|
||||
ah->cal_samples++;
|
||||
|
||||
if (ah->cal_samples >=
|
||||
currCal->calData->calNumSamples) {
|
||||
int i, numChains = 0;
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (rxchainmask & (1 << i))
|
||||
numChains++;
|
||||
}
|
||||
|
||||
currCal->calData->calPostProc(ah, numChains);
|
||||
caldata->CalValid |= currCal->calData->calType;
|
||||
currCal->calState = CAL_DONE;
|
||||
iscaldone = 1;
|
||||
} else {
|
||||
ar9002_hw_setup_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
} else if (!(caldata->CalValid & currCal->calData->calType)) {
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ah->totalPowerMeasI[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ah->totalPowerMeasQ[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ah->totalIqCorrMeas[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
DBG2("ath9k: "
|
||||
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
|
||||
ah->cal_samples, i, ah->totalPowerMeasI[i],
|
||||
ah->totalPowerMeasQ[i],
|
||||
ah->totalIqCorrMeas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ah->totalAdcIOddPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ah->totalAdcIEvenPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ah->totalAdcQOddPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
ah->totalAdcQEvenPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DBG2("ath9k: "
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcIOddPhase[i],
|
||||
ah->totalAdcIEvenPhase[i],
|
||||
ah->totalAdcQOddPhase[i],
|
||||
ah->totalAdcQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ah->totalAdcDcOffsetIOddPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ah->totalAdcDcOffsetIEvenPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ah->totalAdcDcOffsetQOddPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
ah->totalAdcDcOffsetQEvenPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DBG2("ath9k: "
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcDcOffsetIOddPhase[i],
|
||||
ah->totalAdcDcOffsetIEvenPhase[i],
|
||||
ah->totalAdcDcOffsetQOddPhase[i],
|
||||
ah->totalAdcDcOffsetQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
u32 powerMeasQ, powerMeasI, iqCorrMeas;
|
||||
u32 qCoffDenom, iCoffDenom;
|
||||
int32_t qCoff, iCoff;
|
||||
int iqCorrNeg, i;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
powerMeasI = ah->totalPowerMeasI[i];
|
||||
powerMeasQ = ah->totalPowerMeasQ[i];
|
||||
iqCorrMeas = ah->totalIqCorrMeas[i];
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Starting IQ Cal and Correction for Chain %d\n",
|
||||
i);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
|
||||
i, ah->totalIqCorrMeas[i]);
|
||||
|
||||
iqCorrNeg = 0;
|
||||
|
||||
if (iqCorrMeas > 0x80000000) {
|
||||
iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
|
||||
iqCorrNeg = 1;
|
||||
}
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
|
||||
DBG2("ath9k: iqCorrNeg is 0x%08x\n",
|
||||
iqCorrNeg);
|
||||
|
||||
iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
|
||||
qCoffDenom = powerMeasQ / 64;
|
||||
|
||||
if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
|
||||
(qCoffDenom != 0)) {
|
||||
iCoff = iqCorrMeas / iCoffDenom;
|
||||
qCoff = powerMeasI / qCoffDenom - 64;
|
||||
DBG2("ath9k: "
|
||||
"Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d qCoff = 0x%08x\n", i, qCoff);
|
||||
|
||||
iCoff = iCoff & 0x3f;
|
||||
DBG2("ath9k: "
|
||||
"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
if (iqCorrNeg == 0x0)
|
||||
iCoff = 0x40 - iCoff;
|
||||
|
||||
if (qCoff > 15)
|
||||
qCoff = 15;
|
||||
else if (qCoff <= -16)
|
||||
qCoff = -16;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
|
||||
i, iCoff, qCoff);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
iCoff);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
qCoff);
|
||||
DBG2("ath9k: "
|
||||
"IQ Cal and Correction done for Chain %d\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
|
||||
}
|
||||
|
||||
static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
|
||||
u32 qGainMismatch, iGainMismatch, val, i;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
iOddMeasOffset = ah->totalAdcIOddPhase[i];
|
||||
iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
|
||||
qOddMeasOffset = ah->totalAdcQOddPhase[i];
|
||||
qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Starting ADC Gain Cal for Chain %d\n", i);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
|
||||
iOddMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_even_i = 0x%08x\n", i,
|
||||
iEvenMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
|
||||
qOddMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_even_q = 0x%08x\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
|
||||
iGainMismatch =
|
||||
((iEvenMeasOffset * 32) /
|
||||
iOddMeasOffset) & 0x3f;
|
||||
qGainMismatch =
|
||||
((qOddMeasOffset * 32) /
|
||||
qEvenMeasOffset) & 0x3f;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d gain_mismatch_i = 0x%08x\n", i,
|
||||
iGainMismatch);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d gain_mismatch_q = 0x%08x\n", i,
|
||||
qGainMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xfffff000;
|
||||
val |= (qGainMismatch) | (iGainMismatch << 6);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"ADC Gain Cal done for Chain %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
|
||||
REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
|
||||
AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
|
||||
}
|
||||
|
||||
static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, val, i;
|
||||
int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
|
||||
const struct ath9k_percal_data *calData =
|
||||
ah->cal_list_curr->calData;
|
||||
u32 numSamples =
|
||||
(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
|
||||
iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
|
||||
qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
|
||||
qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Starting ADC DC Offset Cal for Chain %d\n", i);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_odd_i = %d\n", i,
|
||||
iOddMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_even_i = %d\n", i,
|
||||
iEvenMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_odd_q = %d\n", i,
|
||||
qOddMeasOffset);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_even_q = %d\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
|
||||
iDcMismatch);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
|
||||
qDcMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xc0000fff;
|
||||
val |= (qDcMismatch << 12) | (iDcMismatch << 21);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"ADC DC Offset Cal done for Chain %d\n", i);
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
|
||||
REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
|
||||
AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
|
||||
}
|
||||
|
||||
static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
|
||||
{
|
||||
u32 rddata;
|
||||
int32_t delta, currPDADC, slope;
|
||||
|
||||
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
|
||||
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
|
||||
if (ah->initPDADC == 0 || currPDADC == 0) {
|
||||
/*
|
||||
* Zero value indicates that no frames have been transmitted
|
||||
* yet, can't do temperature compensation until frames are
|
||||
* transmitted.
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
|
||||
|
||||
if (slope == 0) { /* to avoid divide by zero case */
|
||||
delta = 0;
|
||||
} else {
|
||||
delta = ((currPDADC - ah->initPDADC)*4) / slope;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
|
||||
{
|
||||
u32 rddata, i;
|
||||
int delta, currPDADC, regval;
|
||||
|
||||
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
|
||||
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
|
||||
if (ah->initPDADC == 0 || currPDADC == 0)
|
||||
return;
|
||||
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
|
||||
delta = (currPDADC - ah->initPDADC + 4) / 8;
|
||||
else
|
||||
delta = (currPDADC - ah->initPDADC + 5) / 10;
|
||||
|
||||
if (delta != ah->PDADCdelta) {
|
||||
ah->PDADCdelta = delta;
|
||||
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
regval = ah->originalGain[i] - delta;
|
||||
if (regval < 0)
|
||||
regval = 0;
|
||||
|
||||
REG_RMW_FIELD(ah,
|
||||
AR_PHY_TX_GAIN_TBL1 + i * 4,
|
||||
AR_PHY_TX_GAIN, regval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
|
||||
{
|
||||
u32 regVal;
|
||||
unsigned int i;
|
||||
u32 regList[][2] = {
|
||||
{ 0x786c, 0 },
|
||||
{ 0x7854, 0 },
|
||||
{ 0x7820, 0 },
|
||||
{ 0x7824, 0 },
|
||||
{ 0x7868, 0 },
|
||||
{ 0x783c, 0 },
|
||||
{ 0x7838, 0 } ,
|
||||
{ 0x7828, 0 } ,
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
regList[i][1] = REG_READ(ah, regList[i][0]);
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal |= (0x1 << 27);
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
/* 786c,b23,1, pwddac=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
|
||||
/* 7854, b5,1, pdrxtxbb=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
|
||||
/* 7854, b7,1, pdv2i=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
|
||||
/* 7854, b8,1, pddacinterface=1 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
|
||||
/* 7824,b12,0, offcal=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
|
||||
/* 7838, b1,0, pwddb=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
|
||||
/* 7820,b11,0, enpacal=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
|
||||
/* 7820,b25,1, pdpadrv1=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
|
||||
/* 7820,b24,0, pdpadrv2=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
|
||||
/* 7820,b23,0, pdpaout=0 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
|
||||
/* 783c,b14-16,7, padrvgn2tab_0=7 */
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
/*
|
||||
* 7838,b29-31,0, padrvgn1tab_0=0
|
||||
* does not matter since we turn it off
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
|
||||
|
||||
/* Set:
|
||||
* localmode=1,bmode=1,bmoderxtx=1,synthon=1,
|
||||
* txon=1,paon=1,oscon=1,synthon_force=1
|
||||
*/
|
||||
REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
|
||||
udelay(30);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
|
||||
|
||||
/* find off_6_1; */
|
||||
for (i = 6; i > 0; i--) {
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= (1 << (20 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
udelay(1);
|
||||
/* regVal = REG_READ(ah, 0x7834); */
|
||||
regVal &= (~(0x1 << (20 + i)));
|
||||
regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
|
||||
<< (20 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
}
|
||||
|
||||
regVal = (regVal >> 20) & 0x7f;
|
||||
|
||||
/* Update PA cal info */
|
||||
if ((!is_reset) && ((unsigned int)ah->pacal_info.prev_offset == regVal)) {
|
||||
if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
|
||||
ah->pacal_info.max_skipcount =
|
||||
2 * ah->pacal_info.max_skipcount;
|
||||
ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
|
||||
} else {
|
||||
ah->pacal_info.max_skipcount = 1;
|
||||
ah->pacal_info.skipcount = 0;
|
||||
ah->pacal_info.prev_offset = regVal;
|
||||
}
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= 0x1;
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal &= (~(0x1 << 27));
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
REG_WRITE(ah, regList[i][0], regList[i][1]);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
static inline void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
|
||||
{
|
||||
u32 regVal;
|
||||
unsigned int i;
|
||||
int offset, offs_6_1, offs_0;
|
||||
u32 ccomp_org, reg_field;
|
||||
u32 regList[][2] = {
|
||||
{ 0x786c, 0 },
|
||||
{ 0x7854, 0 },
|
||||
{ 0x7820, 0 },
|
||||
{ 0x7824, 0 },
|
||||
{ 0x7868, 0 },
|
||||
{ 0x783c, 0 },
|
||||
{ 0x7838, 0 },
|
||||
};
|
||||
|
||||
DBG2("ath9k: Running PA Calibration\n");
|
||||
|
||||
/* PA CAL is not needed for high power solution */
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
|
||||
AR5416_EEP_TXGAIN_HIGH_POWER)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
regList[i][1] = REG_READ(ah, regList[i][0]);
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal |= (0x1 << 27);
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
|
||||
ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
|
||||
|
||||
REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
|
||||
udelay(30);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
|
||||
|
||||
for (i = 6; i > 0; i--) {
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= (1 << (19 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
udelay(1);
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1 << (19 + i)));
|
||||
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
|
||||
regVal |= (reg_field << (19 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
|
||||
udelay(1);
|
||||
reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
|
||||
offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
|
||||
offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
|
||||
|
||||
offset = (offs_6_1<<1) | offs_0;
|
||||
offset = offset - 0;
|
||||
offs_6_1 = offset>>1;
|
||||
offs_0 = offset & 1;
|
||||
|
||||
if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
|
||||
if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
|
||||
ah->pacal_info.max_skipcount =
|
||||
2 * ah->pacal_info.max_skipcount;
|
||||
ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
|
||||
} else {
|
||||
ah->pacal_info.max_skipcount = 1;
|
||||
ah->pacal_info.skipcount = 0;
|
||||
ah->pacal_info.prev_offset = offset;
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= 0x1;
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
regVal = REG_READ(ah, 0x9808);
|
||||
regVal &= (~(0x1 << 27));
|
||||
REG_WRITE(ah, 0x9808, regVal);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regList); i++)
|
||||
REG_WRITE(ah, regList[i][0], regList[i][1]);
|
||||
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
|
||||
}
|
||||
|
||||
static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
|
||||
{
|
||||
if (AR_SREV_9271(ah)) {
|
||||
if (is_reset || !ah->pacal_info.skipcount)
|
||||
ar9271_hw_pa_cal(ah, is_reset);
|
||||
else
|
||||
ah->pacal_info.skipcount--;
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (is_reset || !ah->pacal_info.skipcount)
|
||||
ar9285_hw_pa_cal(ah, is_reset);
|
||||
else
|
||||
ah->pacal_info.skipcount--;
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
|
||||
{
|
||||
if (OLC_FOR_AR9287_10_LATER)
|
||||
ar9287_hw_olc_temp_compensation(ah);
|
||||
else if (OLC_FOR_AR9280_20_LATER)
|
||||
ar9280_hw_olc_temp_compensation(ah);
|
||||
}
|
||||
|
||||
static int ar9002_hw_calibrate(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 rxchainmask,
|
||||
int longcal)
|
||||
{
|
||||
int iscaldone = 1;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
int nfcal, nfcal_pending = 0;
|
||||
|
||||
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
|
||||
if (ah->caldata)
|
||||
nfcal_pending = ah->caldata->nfcal_pending;
|
||||
|
||||
if (currCal && !nfcal &&
|
||||
(currCal->calState == CAL_RUNNING ||
|
||||
currCal->calState == CAL_WAITING)) {
|
||||
iscaldone = ar9002_hw_per_calibration(ah, chan,
|
||||
rxchainmask, currCal);
|
||||
if (iscaldone) {
|
||||
ah->cal_list_curr = currCal = currCal->calNext;
|
||||
|
||||
if (currCal->calState == CAL_WAITING) {
|
||||
iscaldone = 0;
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do NF cal only at longer intervals */
|
||||
if (longcal || nfcal_pending) {
|
||||
/*
|
||||
* Get the value from the previous NF cal and update
|
||||
* history buffer.
|
||||
*/
|
||||
if (ath9k_hw_getnf(ah, chan)) {
|
||||
/*
|
||||
* Load the NF from history buffer of the current
|
||||
* channel.
|
||||
* NF is slow time-variant, so it is OK to use a
|
||||
* historical value.
|
||||
*/
|
||||
ath9k_hw_loadnf(ah, ah->curchan);
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
ath9k_hw_start_nfcal(ah, 0);
|
||||
/* Do periodic PAOffset Cal */
|
||||
ar9002_hw_pa_cal(ah, 0);
|
||||
ar9002_hw_olc_temp_compensation(ah);
|
||||
}
|
||||
}
|
||||
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
/* Carrier leakage Calibration fix */
|
||||
static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
if (IS_CHAN_HT20(chan)) {
|
||||
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
|
||||
REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
|
||||
DBG("ath9k: "
|
||||
"offset calibration failed to complete in 1ms; noisy environment?\n");
|
||||
return 0;
|
||||
}
|
||||
REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
||||
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
|
||||
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
}
|
||||
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
DBG("ath9k: "
|
||||
"offset calibration failed to complete in 1ms; noisy environment?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t txgain_max;
|
||||
uint32_t clc_gain, gain_mask = 0, clc_num = 0;
|
||||
uint32_t reg_clc_I0, reg_clc_Q0;
|
||||
uint32_t i0_num = 0;
|
||||
uint32_t q0_num = 0;
|
||||
uint32_t total_num = 0;
|
||||
uint32_t reg_rf2g5_org;
|
||||
int retv = 1;
|
||||
|
||||
if (!(ar9285_hw_cl_cal(ah, chan)))
|
||||
return 0;
|
||||
|
||||
txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
|
||||
AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
|
||||
|
||||
for (i = 0; i < (txgain_max+1); i++) {
|
||||
clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
|
||||
AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
|
||||
if (!(gain_mask & (1 << clc_gain))) {
|
||||
gain_mask |= (1 << clc_gain);
|
||||
clc_num++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < clc_num; i++) {
|
||||
reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
|
||||
& AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
|
||||
reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
|
||||
& AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
|
||||
if (reg_clc_I0 == 0)
|
||||
i0_num++;
|
||||
|
||||
if (reg_clc_Q0 == 0)
|
||||
q0_num++;
|
||||
}
|
||||
total_num = i0_num + q0_num;
|
||||
if (total_num > AR9285_CLCAL_REDO_THRESH) {
|
||||
reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
|
||||
if (AR_SREV_9285E_20(ah)) {
|
||||
REG_WRITE(ah, AR9285_RF2G5,
|
||||
(reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
|
||||
AR9285_RF2G5_IC50TX_XE_SET);
|
||||
} else {
|
||||
REG_WRITE(ah, AR9285_RF2G5,
|
||||
(reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
|
||||
AR9285_RF2G5_IC50TX_SET);
|
||||
}
|
||||
retv = ar9285_hw_cl_cal(ah, chan);
|
||||
REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
|
||||
}
|
||||
return retv;
|
||||
}
|
||||
|
||||
static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
if (AR_SREV_9271(ah)) {
|
||||
if (!ar9285_hw_cl_cal(ah, chan))
|
||||
return 0;
|
||||
} else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (!ar9285_hw_clc(ah, chan))
|
||||
return 0;
|
||||
} else {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
|
||||
AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
}
|
||||
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
|
||||
/* Poll for offset calibration complete */
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
DBG("ath9k: "
|
||||
"offset calibration failed to complete in 1ms; noisy environment?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (!AR_SREV_9287_11_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_PHY_ADC_CTL,
|
||||
AR_PHY_ADC_CTL_OFF_PWDADC);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do PA Calibration */
|
||||
ar9002_hw_pa_cal(ah, 1);
|
||||
|
||||
/* Do NF Calibration after DC offset and other calibrations */
|
||||
ath9k_hw_start_nfcal(ah, 1);
|
||||
|
||||
if (ah->caldata)
|
||||
ah->caldata->nfcal_pending = 1;
|
||||
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
|
||||
/* Enable IQ, ADC Gain and ADC DC offset CALs */
|
||||
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
|
||||
if (AR_SREV_9160_10_OR_LATER(ah))
|
||||
ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
|
||||
|
||||
if (AR_SREV_9287(ah))
|
||||
ah->supp_cals &= ~ADC_GAIN_CAL;
|
||||
|
||||
if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
|
||||
INIT_CAL(&ah->adcgain_caldata);
|
||||
INSERT_CAL(ah, &ah->adcgain_caldata);
|
||||
DBG2("ath9k: "
|
||||
"enabling ADC Gain Calibration.\n");
|
||||
}
|
||||
|
||||
if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
|
||||
INIT_CAL(&ah->adcdc_caldata);
|
||||
INSERT_CAL(ah, &ah->adcdc_caldata);
|
||||
DBG2("ath9k: "
|
||||
"enabling ADC DC Calibration.\n");
|
||||
}
|
||||
|
||||
if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
DBG2("ath9k: "
|
||||
"enabling IQ Calibration.\n");
|
||||
}
|
||||
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
if (ah->cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
|
||||
}
|
||||
|
||||
if (ah->caldata)
|
||||
ah->caldata->CalValid = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct ath9k_percal_data iq_cal_multi_sample = {
|
||||
IQ_MISMATCH_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ar9002_hw_iqcal_collect,
|
||||
ar9002_hw_iqcalibrate
|
||||
};
|
||||
static const struct ath9k_percal_data iq_cal_single_sample = {
|
||||
IQ_MISMATCH_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ar9002_hw_iqcal_collect,
|
||||
ar9002_hw_iqcalibrate
|
||||
};
|
||||
static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
|
||||
ADC_GAIN_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ar9002_hw_adc_gaincal_collect,
|
||||
ar9002_hw_adc_gaincal_calibrate
|
||||
};
|
||||
static const struct ath9k_percal_data adc_gain_cal_single_sample = {
|
||||
ADC_GAIN_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ar9002_hw_adc_gaincal_collect,
|
||||
ar9002_hw_adc_gaincal_calibrate
|
||||
};
|
||||
static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
|
||||
ADC_DC_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ar9002_hw_adc_dccal_collect,
|
||||
ar9002_hw_adc_dccal_calibrate
|
||||
};
|
||||
static const struct ath9k_percal_data adc_dc_cal_single_sample = {
|
||||
ADC_DC_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ar9002_hw_adc_dccal_collect,
|
||||
ar9002_hw_adc_dccal_calibrate
|
||||
};
|
||||
|
||||
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9100(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_multi_sample;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
ah->adcgain_caldata.calData =
|
||||
&adc_gain_cal_single_sample;
|
||||
ah->adcdc_caldata.calData =
|
||||
&adc_dc_cal_single_sample;
|
||||
} else {
|
||||
ah->iq_caldata.calData = &iq_cal_multi_sample;
|
||||
ah->adcgain_caldata.calData =
|
||||
&adc_gain_cal_multi_sample;
|
||||
ah->adcdc_caldata.calData =
|
||||
&adc_dc_cal_multi_sample;
|
||||
}
|
||||
ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
|
||||
|
||||
if (AR_SREV_9287(ah))
|
||||
ah->supp_cals &= ~ADC_GAIN_CAL;
|
||||
}
|
||||
}
|
||||
|
||||
void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
|
||||
priv_ops->init_cal = ar9002_hw_init_cal;
|
||||
priv_ops->setup_calibration = ar9002_hw_setup_calibration;
|
||||
|
||||
ops->calibrate = ar9002_hw_calibrate;
|
||||
}
|
||||
607
src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c
Normal file
607
src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c
Normal file
@@ -0,0 +1,607 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "ar5008_initvals.h"
|
||||
#include "ar9001_initvals.h"
|
||||
#include "ar9002_initvals.h"
|
||||
#include "ar9002_phy.h"
|
||||
|
||||
int modparam_force_new_ani;
|
||||
|
||||
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
|
||||
|
||||
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9271(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
|
||||
ARRAY_SIZE(ar9271Modes_9271), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
|
||||
ARRAY_SIZE(ar9271Common_9271), 2);
|
||||
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
|
||||
ar9271Common_normal_cck_fir_coeff_9271,
|
||||
ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
|
||||
INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
|
||||
ar9271Common_japan_2484_cck_fir_coeff_9271,
|
||||
ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
|
||||
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
|
||||
ar9271Modes_9271_1_0_only,
|
||||
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
|
||||
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
|
||||
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
|
||||
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
|
||||
ar9271Modes_high_power_tx_gain_9271,
|
||||
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
|
||||
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
|
||||
ar9271Modes_normal_power_tx_gain_9271,
|
||||
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
|
||||
if (ah->config.pcie_clock_req)
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9287PciePhy_clkreq_off_L1_9287_1_1,
|
||||
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
|
||||
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
|
||||
2);
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
|
||||
ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
|
||||
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
|
||||
|
||||
if (ah->config.pcie_clock_req) {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9285PciePhy_clkreq_off_L1_9285_1_2,
|
||||
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
|
||||
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
|
||||
2);
|
||||
}
|
||||
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_9280_2), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
|
||||
ARRAY_SIZE(ar9280Common_9280_2), 2);
|
||||
|
||||
if (ah->config.pcie_clock_req) {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9280PciePhy_clkreq_off_L1_9280,
|
||||
ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9280PciePhy_clkreq_always_on_L1_9280,
|
||||
ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
|
||||
}
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional,
|
||||
ar9280Modes_fast_clock_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
|
||||
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
|
||||
ARRAY_SIZE(ar5416Modes_9160), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
|
||||
ARRAY_SIZE(ar5416Common_9160), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
|
||||
ARRAY_SIZE(ar5416Bank0_9160), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
|
||||
ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
|
||||
ARRAY_SIZE(ar5416Bank1_9160), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
|
||||
ARRAY_SIZE(ar5416Bank2_9160), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
|
||||
ARRAY_SIZE(ar5416Bank3_9160), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
|
||||
ARRAY_SIZE(ar5416Bank6_9160), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
|
||||
ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
|
||||
ARRAY_SIZE(ar5416Bank7_9160), 2);
|
||||
if (AR_SREV_9160_11(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniAddac,
|
||||
ar5416Addac_9160_1_1,
|
||||
ARRAY_SIZE(ar5416Addac_9160_1_1), 2);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
|
||||
ARRAY_SIZE(ar5416Addac_9160), 2);
|
||||
}
|
||||
} else if (AR_SREV_9100_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
|
||||
ARRAY_SIZE(ar5416Modes_9100), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
|
||||
ARRAY_SIZE(ar5416Common_9100), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
|
||||
ARRAY_SIZE(ar5416Bank0_9100), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
|
||||
ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
|
||||
ARRAY_SIZE(ar5416Bank1_9100), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
|
||||
ARRAY_SIZE(ar5416Bank2_9100), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
|
||||
ARRAY_SIZE(ar5416Bank3_9100), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
|
||||
ARRAY_SIZE(ar5416Bank6_9100), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
|
||||
ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
|
||||
ARRAY_SIZE(ar5416Bank7_9100), 2);
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
|
||||
ARRAY_SIZE(ar5416Addac_9100), 2);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
|
||||
ARRAY_SIZE(ar5416Modes), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
|
||||
ARRAY_SIZE(ar5416Common), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
|
||||
ARRAY_SIZE(ar5416Bank0), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
|
||||
ARRAY_SIZE(ar5416BB_RfGain), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
|
||||
ARRAY_SIZE(ar5416Bank1), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
|
||||
ARRAY_SIZE(ar5416Bank2), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
|
||||
ARRAY_SIZE(ar5416Bank3), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
|
||||
ARRAY_SIZE(ar5416Bank6), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
|
||||
ARRAY_SIZE(ar5416Bank6TPC), 3);
|
||||
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
|
||||
ARRAY_SIZE(ar5416Bank7), 2);
|
||||
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
|
||||
ARRAY_SIZE(ar5416Addac), 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Support for Japan ch.14 (2484) spread */
|
||||
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniCckfirNormal,
|
||||
ar9287Common_normal_cck_fir_coeff_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1),
|
||||
2);
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1),
|
||||
2);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
|
||||
{
|
||||
u32 rxgain_type;
|
||||
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
|
||||
AR5416_EEP_MINOR_VER_17) {
|
||||
rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
|
||||
|
||||
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9280Modes_backoff_13db_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
|
||||
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9280Modes_backoff_23db_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9280Modes_original_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9280Modes_original_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
|
||||
{
|
||||
u32 txgain_type;
|
||||
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
|
||||
AR5416_EEP_MINOR_VER_19) {
|
||||
txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
|
||||
|
||||
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9280Modes_high_power_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9280Modes_original_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9280Modes_original_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_11_OR_LATER(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9287Modes_rx_gain_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
|
||||
else if (AR_SREV_9280_20(ah))
|
||||
ar9280_20_hw_init_rxgain_ini(ah);
|
||||
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9287Modes_tx_gain_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
|
||||
} else if (AR_SREV_9280_20(ah)) {
|
||||
ar9280_20_hw_init_txgain_ini(ah);
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
|
||||
|
||||
/* txgain table */
|
||||
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
|
||||
if (AR_SREV_9285E_20(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9285Modes_XE2_0_high_power,
|
||||
ARRAY_SIZE(
|
||||
ar9285Modes_XE2_0_high_power), 6);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9285Modes_high_power_tx_gain_9285_1_2,
|
||||
ARRAY_SIZE(
|
||||
ar9285Modes_high_power_tx_gain_9285_1_2), 6);
|
||||
}
|
||||
} else {
|
||||
if (AR_SREV_9285E_20(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9285Modes_XE2_0_normal_power,
|
||||
ARRAY_SIZE(
|
||||
ar9285Modes_XE2_0_normal_power), 6);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9285Modes_original_tx_gain_9285_1_2,
|
||||
ARRAY_SIZE(
|
||||
ar9285Modes_original_tx_gain_9285_1_2), 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for ASPM support.
|
||||
*
|
||||
* Disable PLL when in L0s as well as receiver clock when in L1.
|
||||
* This power saving option must be enabled through the SerDes.
|
||||
*
|
||||
* Programming the SerDes must go through the same 288 bit serial shift
|
||||
* register as the other analog registers. Hence the 9 writes.
|
||||
*/
|
||||
static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
||||
int restore,
|
||||
int power_off)
|
||||
{
|
||||
u8 i;
|
||||
u32 val;
|
||||
|
||||
if (ah->is_pciexpress != 1)
|
||||
return;
|
||||
|
||||
/* Do not touch SerDes registers */
|
||||
if (ah->config.pcie_powersave_enable == 2)
|
||||
return;
|
||||
|
||||
/* Nothing to do on restore for 11N */
|
||||
if (!restore) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
/*
|
||||
* AR9280 2.0 or later chips use SerDes values from the
|
||||
* initvals.h initialized depending on chipset during
|
||||
* __ath9k_hw_init()
|
||||
*/
|
||||
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
|
||||
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
|
||||
INI_RA(&ah->iniPcieSerdes, i, 1));
|
||||
}
|
||||
} else {
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
||||
|
||||
/* RX shut off when elecidle is asserted */
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
|
||||
|
||||
/*
|
||||
* Ignore ah->ah_config.pcie_clock_req setting for
|
||||
* pre-AR9280 11n
|
||||
*/
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
|
||||
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
|
||||
|
||||
/* Load the new settings */
|
||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
if (power_off) {
|
||||
/* clear bit 19 to disable L1 */
|
||||
REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
|
||||
val = REG_READ(ah, AR_WA);
|
||||
|
||||
/*
|
||||
* Set PCIe workaround bits
|
||||
* In AR9280 and AR9285, bit 14 in WA register (disable L1)
|
||||
* should only be set when device enters D3 and be
|
||||
* cleared when device comes back to D0.
|
||||
*/
|
||||
if (ah->config.pcie_waen) {
|
||||
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
||||
val |= AR_WA_D3_L1_DISABLE;
|
||||
} else {
|
||||
if (((AR_SREV_9285(ah) ||
|
||||
AR_SREV_9271(ah) ||
|
||||
AR_SREV_9287(ah)) &&
|
||||
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
||||
(AR_SREV_9280(ah) &&
|
||||
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
||||
val |= AR_WA_D3_L1_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
|
||||
/*
|
||||
* Disable bit 6 and 7 before entering D3 to
|
||||
* prevent system hang.
|
||||
*/
|
||||
val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
|
||||
}
|
||||
|
||||
if (AR_SREV_9280(ah))
|
||||
val |= AR_WA_BIT22;
|
||||
|
||||
if (AR_SREV_9285E_20(ah))
|
||||
val |= AR_WA_BIT23;
|
||||
|
||||
REG_WRITE(ah, AR_WA, val);
|
||||
} else {
|
||||
if (ah->config.pcie_waen) {
|
||||
val = ah->config.pcie_waen;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
} else {
|
||||
if (AR_SREV_9285(ah) ||
|
||||
AR_SREV_9271(ah) ||
|
||||
AR_SREV_9287(ah)) {
|
||||
val = AR9285_WA_DEFAULT;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
}
|
||||
else if (AR_SREV_9280(ah)) {
|
||||
/*
|
||||
* For AR9280 chips, bit 22 of 0x4004
|
||||
* needs to be set.
|
||||
*/
|
||||
val = AR9280_WA_DEFAULT;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
} else {
|
||||
val = AR_WA_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/* WAR for ASPM system hang */
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
|
||||
val |= (AR_WA_BIT6 | AR_WA_BIT7);
|
||||
|
||||
if (AR_SREV_9285E_20(ah))
|
||||
val |= AR_WA_BIT23;
|
||||
|
||||
REG_WRITE(ah, AR_WA, val);
|
||||
|
||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
}
|
||||
}
|
||||
|
||||
static int ar9002_hw_get_radiorev(struct ath_hw *ah)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
|
||||
for (i = 0; i < 8; i++)
|
||||
REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
||||
val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
|
||||
val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
|
||||
|
||||
return ath9k_hw_reverse_bits(val, 8);
|
||||
}
|
||||
|
||||
int ar9002_hw_rf_claim(struct ath_hw *ah)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
REG_WRITE(ah, AR_PHY(0), 0x00000007);
|
||||
|
||||
val = ar9002_hw_get_radiorev(ah);
|
||||
switch (val & AR_RADIO_SREV_MAJOR) {
|
||||
case 0:
|
||||
val = AR_RAD5133_SREV_MAJOR;
|
||||
break;
|
||||
case AR_RAD5133_SREV_MAJOR:
|
||||
case AR_RAD5122_SREV_MAJOR:
|
||||
case AR_RAD2133_SREV_MAJOR:
|
||||
case AR_RAD2122_SREV_MAJOR:
|
||||
break;
|
||||
default:
|
||||
DBG("ath9k: "
|
||||
"Radio Chip Rev 0x%02X not supported\n",
|
||||
val & AR_RADIO_SREV_MAJOR);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ah->hw_version.analog5GhzRev = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
|
||||
REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
|
||||
REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If Async FIFO is enabled, the following counters change as MAC now runs
|
||||
* at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
|
||||
*
|
||||
* The values below tested for ht40 2 chain.
|
||||
* Overwrite the delay/timeouts initialized in process ini.
|
||||
*/
|
||||
void ar9002_hw_update_async_fifo(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
|
||||
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
|
||||
AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
|
||||
AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
|
||||
|
||||
REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
|
||||
REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
|
||||
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
|
||||
AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
|
||||
REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
|
||||
AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't enable WEP aggregation on mac80211 but we keep this
|
||||
* around for HAL unification purposes.
|
||||
*/
|
||||
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
|
||||
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
|
||||
void ar9002_hw_attach_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
|
||||
priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
|
||||
|
||||
ops->config_pci_powersave = ar9002_hw_configpcipowersave;
|
||||
|
||||
ar5008_hw_attach_phy_ops(ah);
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ar9002_hw_attach_phy_ops(ah);
|
||||
|
||||
ar9002_hw_attach_calib_ops(ah);
|
||||
ar9002_hw_attach_mac_ops(ah);
|
||||
}
|
||||
|
||||
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
u32 modesIndex;
|
||||
unsigned int i;
|
||||
|
||||
switch (chan->chanmode) {
|
||||
case CHANNEL_A:
|
||||
case CHANNEL_A_HT20:
|
||||
modesIndex = 1;
|
||||
break;
|
||||
case CHANNEL_A_HT40PLUS:
|
||||
case CHANNEL_A_HT40MINUS:
|
||||
modesIndex = 2;
|
||||
break;
|
||||
case CHANNEL_G:
|
||||
case CHANNEL_G_HT20:
|
||||
case CHANNEL_B:
|
||||
modesIndex = 4;
|
||||
break;
|
||||
case CHANNEL_G_HT40PLUS:
|
||||
case CHANNEL_G_HT40MINUS:
|
||||
modesIndex = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
|
||||
u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
|
||||
u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
|
||||
u32 val_orig;
|
||||
|
||||
if (reg == AR_PHY_CCK_DETECT) {
|
||||
val_orig = REG_READ(ah, reg);
|
||||
val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
|
||||
val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
|
||||
|
||||
REG_WRITE(ah, reg, val|val_orig);
|
||||
} else
|
||||
REG_WRITE(ah, reg, val);
|
||||
}
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
454
src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c
Normal file
454
src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
#define AR_BufLen 0x00000fff
|
||||
|
||||
static void ar9002_hw_rx_enable(struct ath_hw *ah)
|
||||
{
|
||||
REG_WRITE(ah, AR_CR, AR_CR_RXE);
|
||||
}
|
||||
|
||||
static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
|
||||
{
|
||||
((struct ath_desc*) ds)->ds_link = ds_link;
|
||||
}
|
||||
|
||||
static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
|
||||
{
|
||||
*ds_link = &((struct ath_desc *)ds)->ds_link;
|
||||
}
|
||||
|
||||
static int ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
{
|
||||
u32 isr = 0;
|
||||
u32 mask2 = 0;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
u32 sync_cause = 0;
|
||||
int fatal_int = 0;
|
||||
|
||||
if (!AR_SREV_9100(ah) && (ah->ah_ier & AR_IER_ENABLE)) {
|
||||
if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
|
||||
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
|
||||
== AR_RTC_STATUS_ON) {
|
||||
isr = REG_READ(ah, AR_ISR);
|
||||
}
|
||||
}
|
||||
|
||||
sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
|
||||
AR_INTR_SYNC_DEFAULT;
|
||||
|
||||
*masked = 0;
|
||||
|
||||
if (!isr && !sync_cause)
|
||||
return 0;
|
||||
} else {
|
||||
*masked = 0;
|
||||
isr = REG_READ(ah, AR_ISR);
|
||||
}
|
||||
|
||||
if (isr) {
|
||||
if (isr & AR_ISR_BCNMISC) {
|
||||
u32 isr2;
|
||||
isr2 = REG_READ(ah, AR_ISR_S2);
|
||||
if (isr2 & AR_ISR_S2_TIM)
|
||||
mask2 |= ATH9K_INT_TIM;
|
||||
if (isr2 & AR_ISR_S2_DTIM)
|
||||
mask2 |= ATH9K_INT_DTIM;
|
||||
if (isr2 & AR_ISR_S2_DTIMSYNC)
|
||||
mask2 |= ATH9K_INT_DTIMSYNC;
|
||||
if (isr2 & (AR_ISR_S2_CABEND))
|
||||
mask2 |= ATH9K_INT_CABEND;
|
||||
if (isr2 & AR_ISR_S2_GTT)
|
||||
mask2 |= ATH9K_INT_GTT;
|
||||
if (isr2 & AR_ISR_S2_CST)
|
||||
mask2 |= ATH9K_INT_CST;
|
||||
if (isr2 & AR_ISR_S2_TSFOOR)
|
||||
mask2 |= ATH9K_INT_TSFOOR;
|
||||
}
|
||||
|
||||
isr = REG_READ(ah, AR_ISR_RAC);
|
||||
if (isr == 0xffffffff) {
|
||||
*masked = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*masked = isr & ATH9K_INT_COMMON;
|
||||
|
||||
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
|
||||
AR_ISR_RXOK | AR_ISR_RXERR))
|
||||
*masked |= ATH9K_INT_RX;
|
||||
|
||||
if (isr &
|
||||
(AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
|
||||
AR_ISR_TXEOL)) {
|
||||
u32 s0_s, s1_s;
|
||||
|
||||
*masked |= ATH9K_INT_TX;
|
||||
|
||||
s0_s = REG_READ(ah, AR_ISR_S0_S);
|
||||
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
|
||||
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
|
||||
|
||||
s1_s = REG_READ(ah, AR_ISR_S1_S);
|
||||
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
|
||||
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
|
||||
}
|
||||
|
||||
if (isr & AR_ISR_RXORN) {
|
||||
DBG("ath9k: "
|
||||
"receive FIFO overrun interrupt\n");
|
||||
}
|
||||
|
||||
*masked |= mask2;
|
||||
}
|
||||
|
||||
if (AR_SREV_9100(ah))
|
||||
return 1;
|
||||
|
||||
if (isr & AR_ISR_GENTMR) {
|
||||
u32 s5_s;
|
||||
|
||||
s5_s = REG_READ(ah, AR_ISR_S5_S);
|
||||
ah->intr_gen_timer_trigger =
|
||||
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
|
||||
|
||||
ah->intr_gen_timer_thresh =
|
||||
MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
|
||||
|
||||
if (ah->intr_gen_timer_trigger)
|
||||
*masked |= ATH9K_INT_GENTIMER;
|
||||
|
||||
if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
|
||||
!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
*masked |= ATH9K_INT_TIM_TIMER;
|
||||
}
|
||||
|
||||
if (sync_cause) {
|
||||
fatal_int =
|
||||
(sync_cause &
|
||||
(AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
|
||||
? 1 : 0;
|
||||
|
||||
if (fatal_int) {
|
||||
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
|
||||
DBG("ath9k: "
|
||||
"received PCI FATAL interrupt\n");
|
||||
}
|
||||
if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
|
||||
DBG("ath9k: "
|
||||
"received PCI PERR interrupt\n");
|
||||
}
|
||||
*masked |= ATH9K_INT_FATAL;
|
||||
}
|
||||
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
|
||||
DBG("ath9k: "
|
||||
"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
|
||||
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
|
||||
REG_WRITE(ah, AR_RC, 0);
|
||||
*masked |= ATH9K_INT_FATAL;
|
||||
}
|
||||
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
|
||||
DBG("ath9k: "
|
||||
"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
|
||||
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ar9002_hw_fill_txdesc(struct ath_hw *ah __unused, void *ds, u32 seglen,
|
||||
int is_firstseg, int is_lastseg,
|
||||
const void *ds0, u32 buf_addr,
|
||||
unsigned int qcu __unused)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
ads->ds_data = buf_addr;
|
||||
|
||||
if (is_firstseg) {
|
||||
ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
|
||||
} else if (is_lastseg) {
|
||||
ads->ds_ctl0 = 0;
|
||||
ads->ds_ctl1 = seglen;
|
||||
ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
|
||||
ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
|
||||
} else {
|
||||
ads->ds_ctl0 = 0;
|
||||
ads->ds_ctl1 = seglen | AR_TxMore;
|
||||
ads->ds_ctl2 = 0;
|
||||
ads->ds_ctl3 = 0;
|
||||
}
|
||||
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
|
||||
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
|
||||
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
|
||||
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
|
||||
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
|
||||
}
|
||||
|
||||
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
u32 status;
|
||||
|
||||
status = *(volatile typeof(ads->ds_txstatus9) *)&(ads->ds_txstatus9);
|
||||
if ((status & AR_TxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ts->ts_tstamp = ads->AR_SendTimestamp;
|
||||
ts->ts_status = 0;
|
||||
ts->ts_flags = 0;
|
||||
|
||||
if (status & AR_TxOpExceeded)
|
||||
ts->ts_status |= ATH9K_TXERR_XTXOP;
|
||||
ts->tid = MS(status, AR_TxTid);
|
||||
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
|
||||
ts->ts_seqnum = MS(status, AR_SeqNum);
|
||||
|
||||
status = *(volatile typeof(ads->ds_txstatus0) *)&(ads->ds_txstatus0);
|
||||
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
|
||||
if (status & AR_TxBaStatus) {
|
||||
ts->ts_flags |= ATH9K_TX_BA;
|
||||
ts->ba_low = ads->AR_BaBitmapLow;
|
||||
ts->ba_high = ads->AR_BaBitmapHigh;
|
||||
}
|
||||
|
||||
status = *(volatile typeof(ads->ds_txstatus1) *)&(ads->ds_txstatus1);
|
||||
if (status & AR_FrmXmitOK)
|
||||
ts->ts_status |= ATH9K_TX_ACKED;
|
||||
else {
|
||||
if (status & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (status & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (status & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
}
|
||||
if (status & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
if (status & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (status & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
if (status & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
ts->ts_shortretry = MS(status, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(status, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
|
||||
|
||||
status = *(volatile typeof(ads->ds_txstatus5) *)&(ads->ds_txstatus5);
|
||||
ts->ts_rssi = MS(status, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
||||
|
||||
ts->evm0 = ads->AR_TxEVM0;
|
||||
ts->evm1 = ads->AR_TxEVM1;
|
||||
ts->evm2 = ads->AR_TxEVM2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type,
|
||||
u32 txPower, u32 keyIx,
|
||||
enum ath9k_key_type keyType, u32 flags)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
if (txPower > 63)
|
||||
txPower = 63;
|
||||
|
||||
ads->ds_ctl0 = (pktLen & AR_FrameLen)
|
||||
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
||||
| SM(txPower, AR_XmitPower)
|
||||
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
||||
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
|
||||
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
|
||||
|
||||
ads->ds_ctl1 =
|
||||
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
|
||||
| SM(type, AR_FrameType)
|
||||
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
|
||||
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
|
||||
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
|
||||
|
||||
ads->ds_ctl6 = SM(keyType, AR_EncrType);
|
||||
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
|
||||
ads->ds_ctl8 = 0;
|
||||
ads->ds_ctl9 = 0;
|
||||
ads->ds_ctl10 = 0;
|
||||
ads->ds_ctl11 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_set_clrdmask(struct ath_hw *ah __unused, void *ds, int val)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
if (val)
|
||||
ads->ds_ctl0 |= AR_ClrDestMask;
|
||||
else
|
||||
ads->ds_ctl0 &= ~AR_ClrDestMask;
|
||||
}
|
||||
|
||||
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah __unused, void *ds,
|
||||
void *lastds,
|
||||
u32 durUpdateEn, u32 rtsctsRate,
|
||||
u32 rtsctsDuration __unused,
|
||||
struct ath9k_11n_rate_series series[],
|
||||
u32 nseries __unused, u32 flags)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
struct ar5416_desc *last_ads = AR5416DESC(lastds);
|
||||
u32 ds_ctl0;
|
||||
|
||||
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
|
||||
ds_ctl0 = ads->ds_ctl0;
|
||||
|
||||
if (flags & ATH9K_TXDESC_RTSENA) {
|
||||
ds_ctl0 &= ~AR_CTSEnable;
|
||||
ds_ctl0 |= AR_RTSEnable;
|
||||
} else {
|
||||
ds_ctl0 &= ~AR_RTSEnable;
|
||||
ds_ctl0 |= AR_CTSEnable;
|
||||
}
|
||||
|
||||
ads->ds_ctl0 = ds_ctl0;
|
||||
} else {
|
||||
ads->ds_ctl0 =
|
||||
(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
|
||||
}
|
||||
|
||||
ads->ds_ctl2 = set11nTries(series, 0)
|
||||
| set11nTries(series, 1)
|
||||
| set11nTries(series, 2)
|
||||
| set11nTries(series, 3)
|
||||
| (durUpdateEn ? AR_DurUpdateEna : 0)
|
||||
| SM(0, AR_BurstDur);
|
||||
|
||||
ads->ds_ctl3 = set11nRate(series, 0)
|
||||
| set11nRate(series, 1)
|
||||
| set11nRate(series, 2)
|
||||
| set11nRate(series, 3);
|
||||
|
||||
ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
|
||||
| set11nPktDurRTSCTS(series, 1);
|
||||
|
||||
ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
|
||||
| set11nPktDurRTSCTS(series, 3);
|
||||
|
||||
ads->ds_ctl7 = set11nRateFlags(series, 0)
|
||||
| set11nRateFlags(series, 1)
|
||||
| set11nRateFlags(series, 2)
|
||||
| set11nRateFlags(series, 3)
|
||||
| SM(rtsctsRate, AR_RTSCTSRate);
|
||||
last_ads->ds_ctl2 = ads->ds_ctl2;
|
||||
last_ads->ds_ctl3 = ads->ds_ctl3;
|
||||
}
|
||||
|
||||
static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah __unused, void *ds,
|
||||
u32 aggrLen)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
|
||||
ads->ds_ctl6 &= ~AR_AggrLen;
|
||||
ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
|
||||
}
|
||||
|
||||
static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah __unused, void *ds,
|
||||
u32 numDelims)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
unsigned int ctl6;
|
||||
|
||||
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
|
||||
|
||||
ctl6 = ads->ds_ctl6;
|
||||
ctl6 &= ~AR_PadDelim;
|
||||
ctl6 |= SM(numDelims, AR_PadDelim);
|
||||
ads->ds_ctl6 = ctl6;
|
||||
}
|
||||
|
||||
static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah __unused, void *ds)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
ads->ds_ctl1 |= AR_IsAggr;
|
||||
ads->ds_ctl1 &= ~AR_MoreAggr;
|
||||
ads->ds_ctl6 &= ~AR_PadDelim;
|
||||
}
|
||||
|
||||
static void ar9002_hw_clr11n_aggr(struct ath_hw *ah __unused, void *ds)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
|
||||
ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
|
||||
}
|
||||
|
||||
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 size, u32 flags)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
|
||||
ads->ds_ctl1 = size & AR_BufLen;
|
||||
if (flags & ATH9K_RXDESC_INTREQ)
|
||||
ads->ds_ctl1 |= AR_RxIntrReq;
|
||||
|
||||
ads->ds_rxstatus8 &= ~AR_RxDone;
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
memset(&(ads->u), 0, sizeof(ads->u));
|
||||
}
|
||||
|
||||
void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
ops->rx_enable = ar9002_hw_rx_enable;
|
||||
ops->set_desc_link = ar9002_hw_set_desc_link;
|
||||
ops->get_desc_link = ar9002_hw_get_desc_link;
|
||||
ops->get_isr = ar9002_hw_get_isr;
|
||||
ops->fill_txdesc = ar9002_hw_fill_txdesc;
|
||||
ops->proc_txdesc = ar9002_hw_proc_txdesc;
|
||||
ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
|
||||
ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
|
||||
ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
|
||||
ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
|
||||
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
|
||||
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
|
||||
ops->set_clrdmask = ar9002_hw_set_clrdmask;
|
||||
}
|
||||
578
src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c
Normal file
578
src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c
Normal file
@@ -0,0 +1,578 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: Programming Atheros 802.11n analog front end radios
|
||||
*
|
||||
* AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
|
||||
* devices have either an external AR2133 analog front end radio for single
|
||||
* band 2.4 GHz communication or an AR5133 analog front end radio for dual
|
||||
* band 2.4 GHz / 5 GHz communication.
|
||||
*
|
||||
* All devices after the AR5416 and AR5418 family starting with the AR9280
|
||||
* have their analog front radios, MAC/BB and host PCIe/USB interface embedded
|
||||
* into a single-chip and require less programming.
|
||||
*
|
||||
* The following single-chips exist with a respective embedded radio:
|
||||
*
|
||||
* AR9280 - 11n dual-band 2x2 MIMO for PCIe
|
||||
* AR9281 - 11n single-band 1x2 MIMO for PCIe
|
||||
* AR9285 - 11n single-band 1x1 for PCIe
|
||||
* AR9287 - 11n single-band 2x2 MIMO for PCIe
|
||||
*
|
||||
* AR9220 - 11n dual-band 2x2 MIMO for PCI
|
||||
* AR9223 - 11n single-band 2x2 MIMO for PCI
|
||||
*
|
||||
* AR9287 - 11n single-band 1x1 MIMO for USB
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
#include "ar9002_phy.h"
|
||||
|
||||
/**
|
||||
* ar9002_hw_set_channel - set channel on single-chip device
|
||||
* @ah: atheros hardware structure
|
||||
* @chan:
|
||||
*
|
||||
* This is the function to change channel on single-chip devices, that is
|
||||
* all devices after ar9280.
|
||||
*
|
||||
* This function takes the channel value in MHz and sets
|
||||
* hardware channel value. Assumes writes have been enabled to analog bus.
|
||||
*
|
||||
* Actual Expression,
|
||||
*
|
||||
* For 2GHz channel,
|
||||
* Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
|
||||
* (freq_ref = 40MHz)
|
||||
*
|
||||
* For 5GHz channel,
|
||||
* Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
|
||||
* (freq_ref = 40MHz/(24>>amodeRefSel))
|
||||
*/
|
||||
static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
u16 bMode, fracMode, aModeRefSel = 0;
|
||||
u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
|
||||
struct chan_centers centers;
|
||||
u32 refDivA = 24;
|
||||
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
freq = centers.synth_center;
|
||||
|
||||
reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
|
||||
reg32 &= 0xc0000000;
|
||||
|
||||
if (freq < 4800) { /* 2 GHz, fractional mode */
|
||||
u32 txctl;
|
||||
unsigned int regWrites = 0;
|
||||
|
||||
bMode = 1;
|
||||
fracMode = 1;
|
||||
aModeRefSel = 0;
|
||||
channelSel = CHANSEL_2G(freq);
|
||||
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
if (freq == 2484) {
|
||||
/* Enable channel spreading for channel 14 */
|
||||
REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
|
||||
1, regWrites);
|
||||
} else {
|
||||
REG_WRITE_ARRAY(&ah->iniCckfirNormal,
|
||||
1, regWrites);
|
||||
}
|
||||
} else {
|
||||
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
|
||||
if (freq == 2484) {
|
||||
/* Enable channel spreading for channel 14 */
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
} else {
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bMode = 0;
|
||||
fracMode = 0;
|
||||
|
||||
switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
|
||||
case 0:
|
||||
if ((freq % 20) == 0)
|
||||
aModeRefSel = 3;
|
||||
else if ((freq % 10) == 0)
|
||||
aModeRefSel = 2;
|
||||
if (aModeRefSel)
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
aModeRefSel = 0;
|
||||
/*
|
||||
* Enable 2G (fractional) mode for channels
|
||||
* which are 5MHz spaced.
|
||||
*/
|
||||
fracMode = 1;
|
||||
refDivA = 1;
|
||||
channelSel = CHANSEL_5G(freq);
|
||||
|
||||
/* RefDivA setting */
|
||||
REG_RMW_FIELD(ah, AR_AN_SYNTH9,
|
||||
AR_AN_SYNTH9_REFDIVA, refDivA);
|
||||
|
||||
}
|
||||
|
||||
if (!fracMode) {
|
||||
ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
|
||||
channelSel = ndiv & 0x1ff;
|
||||
channelFrac = (ndiv & 0xfffffe00) * 2;
|
||||
channelSel = (channelSel << 17) | channelFrac;
|
||||
}
|
||||
}
|
||||
|
||||
reg32 = reg32 |
|
||||
(bMode << 29) |
|
||||
(fracMode << 28) | (aModeRefSel << 26) | (channelSel);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
|
||||
|
||||
ah->curchan = chan;
|
||||
ah->curchan_rad_index = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ar9002_hw_spur_mitigate - convert baseband spur frequency
|
||||
* @ah: atheros hardware structure
|
||||
* @chan:
|
||||
*
|
||||
* For single-chip solutions. Converts to baseband spur frequency given the
|
||||
* input channel frequency and compute register settings below.
|
||||
*/
|
||||
static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
int bb_spur = AR_NO_SPUR;
|
||||
int freq;
|
||||
int bin, cur_bin;
|
||||
int bb_spur_off, spur_subchannel_sd;
|
||||
int spur_freq_sd;
|
||||
int spur_delta_phase;
|
||||
int denominator;
|
||||
int upper, lower, cur_vit_mask;
|
||||
int tmp, newVal;
|
||||
int i;
|
||||
static const int pilot_mask_reg[4] = {
|
||||
AR_PHY_TIMING7, AR_PHY_TIMING8,
|
||||
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
|
||||
};
|
||||
static const int chan_mask_reg[4] = {
|
||||
AR_PHY_TIMING9, AR_PHY_TIMING10,
|
||||
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
|
||||
};
|
||||
static const int inc[4] = { 0, 100, 0, 0 };
|
||||
struct chan_centers centers;
|
||||
|
||||
int8_t mask_m[123];
|
||||
int8_t mask_p[123];
|
||||
int8_t mask_amt;
|
||||
int tmp_mask;
|
||||
int cur_bb_spur;
|
||||
int is2GHz = IS_CHAN_2GHZ(chan);
|
||||
|
||||
memset(&mask_m, 0, sizeof(int8_t) * 123);
|
||||
memset(&mask_p, 0, sizeof(int8_t) * 123);
|
||||
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
freq = centers.synth_center;
|
||||
|
||||
ah->config.spurmode = SPUR_ENABLE_EEPROM;
|
||||
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
|
||||
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
|
||||
|
||||
if (AR_NO_SPUR == cur_bb_spur)
|
||||
break;
|
||||
|
||||
if (is2GHz)
|
||||
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
|
||||
else
|
||||
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
|
||||
|
||||
cur_bb_spur = cur_bb_spur - freq;
|
||||
|
||||
if (IS_CHAN_HT40(chan)) {
|
||||
if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
|
||||
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
|
||||
bb_spur = cur_bb_spur;
|
||||
break;
|
||||
}
|
||||
} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
|
||||
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
|
||||
bb_spur = cur_bb_spur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AR_NO_SPUR == bb_spur) {
|
||||
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
|
||||
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
|
||||
return;
|
||||
} else {
|
||||
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
|
||||
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
|
||||
}
|
||||
|
||||
bin = bb_spur * 320;
|
||||
|
||||
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
|
||||
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
|
||||
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
|
||||
|
||||
newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
|
||||
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
|
||||
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
|
||||
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
|
||||
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
|
||||
REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
|
||||
|
||||
if (IS_CHAN_HT40(chan)) {
|
||||
if (bb_spur < 0) {
|
||||
spur_subchannel_sd = 1;
|
||||
bb_spur_off = bb_spur + 10;
|
||||
} else {
|
||||
spur_subchannel_sd = 0;
|
||||
bb_spur_off = bb_spur - 10;
|
||||
}
|
||||
} else {
|
||||
spur_subchannel_sd = 0;
|
||||
bb_spur_off = bb_spur;
|
||||
}
|
||||
|
||||
if (IS_CHAN_HT40(chan))
|
||||
spur_delta_phase =
|
||||
((bb_spur * 262144) /
|
||||
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
|
||||
else
|
||||
spur_delta_phase =
|
||||
((bb_spur * 524288) /
|
||||
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
|
||||
|
||||
denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
|
||||
spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
|
||||
|
||||
newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
|
||||
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
|
||||
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
|
||||
REG_WRITE(ah, AR_PHY_TIMING11, newVal);
|
||||
|
||||
newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
|
||||
REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
|
||||
|
||||
cur_bin = -6000;
|
||||
upper = bin + 100;
|
||||
lower = bin - 100;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int pilot_mask = 0;
|
||||
int chan_mask = 0;
|
||||
int bp = 0;
|
||||
for (bp = 0; bp < 30; bp++) {
|
||||
if ((cur_bin > lower) && (cur_bin < upper)) {
|
||||
pilot_mask = pilot_mask | 0x1 << bp;
|
||||
chan_mask = chan_mask | 0x1 << bp;
|
||||
}
|
||||
cur_bin += 100;
|
||||
}
|
||||
cur_bin += inc[i];
|
||||
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
|
||||
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
|
||||
}
|
||||
|
||||
cur_vit_mask = 6100;
|
||||
upper = bin + 120;
|
||||
lower = bin - 120;
|
||||
|
||||
for (i = 0; i < 123; i++) {
|
||||
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
|
||||
|
||||
/* workaround for gcc bug #37014 */
|
||||
volatile int tmp_v = abs(cur_vit_mask - bin);
|
||||
|
||||
if (tmp_v < 75)
|
||||
mask_amt = 1;
|
||||
else
|
||||
mask_amt = 0;
|
||||
if (cur_vit_mask < 0)
|
||||
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
|
||||
else
|
||||
mask_p[cur_vit_mask / 100] = mask_amt;
|
||||
}
|
||||
cur_vit_mask -= 100;
|
||||
}
|
||||
|
||||
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
|
||||
| (mask_m[48] << 26) | (mask_m[49] << 24)
|
||||
| (mask_m[50] << 22) | (mask_m[51] << 20)
|
||||
| (mask_m[52] << 18) | (mask_m[53] << 16)
|
||||
| (mask_m[54] << 14) | (mask_m[55] << 12)
|
||||
| (mask_m[56] << 10) | (mask_m[57] << 8)
|
||||
| (mask_m[58] << 6) | (mask_m[59] << 4)
|
||||
| (mask_m[60] << 2) | (mask_m[61] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_m[31] << 28)
|
||||
| (mask_m[32] << 26) | (mask_m[33] << 24)
|
||||
| (mask_m[34] << 22) | (mask_m[35] << 20)
|
||||
| (mask_m[36] << 18) | (mask_m[37] << 16)
|
||||
| (mask_m[48] << 14) | (mask_m[39] << 12)
|
||||
| (mask_m[40] << 10) | (mask_m[41] << 8)
|
||||
| (mask_m[42] << 6) | (mask_m[43] << 4)
|
||||
| (mask_m[44] << 2) | (mask_m[45] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
|
||||
| (mask_m[18] << 26) | (mask_m[18] << 24)
|
||||
| (mask_m[20] << 22) | (mask_m[20] << 20)
|
||||
| (mask_m[22] << 18) | (mask_m[22] << 16)
|
||||
| (mask_m[24] << 14) | (mask_m[24] << 12)
|
||||
| (mask_m[25] << 10) | (mask_m[26] << 8)
|
||||
| (mask_m[27] << 6) | (mask_m[28] << 4)
|
||||
| (mask_m[29] << 2) | (mask_m[30] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
|
||||
| (mask_m[2] << 26) | (mask_m[3] << 24)
|
||||
| (mask_m[4] << 22) | (mask_m[5] << 20)
|
||||
| (mask_m[6] << 18) | (mask_m[7] << 16)
|
||||
| (mask_m[8] << 14) | (mask_m[9] << 12)
|
||||
| (mask_m[10] << 10) | (mask_m[11] << 8)
|
||||
| (mask_m[12] << 6) | (mask_m[13] << 4)
|
||||
| (mask_m[14] << 2) | (mask_m[15] << 0);
|
||||
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_p[15] << 28)
|
||||
| (mask_p[14] << 26) | (mask_p[13] << 24)
|
||||
| (mask_p[12] << 22) | (mask_p[11] << 20)
|
||||
| (mask_p[10] << 18) | (mask_p[9] << 16)
|
||||
| (mask_p[8] << 14) | (mask_p[7] << 12)
|
||||
| (mask_p[6] << 10) | (mask_p[5] << 8)
|
||||
| (mask_p[4] << 6) | (mask_p[3] << 4)
|
||||
| (mask_p[2] << 2) | (mask_p[1] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_p[30] << 28)
|
||||
| (mask_p[29] << 26) | (mask_p[28] << 24)
|
||||
| (mask_p[27] << 22) | (mask_p[26] << 20)
|
||||
| (mask_p[25] << 18) | (mask_p[24] << 16)
|
||||
| (mask_p[23] << 14) | (mask_p[22] << 12)
|
||||
| (mask_p[21] << 10) | (mask_p[20] << 8)
|
||||
| (mask_p[19] << 6) | (mask_p[18] << 4)
|
||||
| (mask_p[17] << 2) | (mask_p[16] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_p[45] << 28)
|
||||
| (mask_p[44] << 26) | (mask_p[43] << 24)
|
||||
| (mask_p[42] << 22) | (mask_p[41] << 20)
|
||||
| (mask_p[40] << 18) | (mask_p[39] << 16)
|
||||
| (mask_p[38] << 14) | (mask_p[37] << 12)
|
||||
| (mask_p[36] << 10) | (mask_p[35] << 8)
|
||||
| (mask_p[34] << 6) | (mask_p[33] << 4)
|
||||
| (mask_p[32] << 2) | (mask_p[31] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
|
||||
|
||||
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
|
||||
| (mask_p[59] << 26) | (mask_p[58] << 24)
|
||||
| (mask_p[57] << 22) | (mask_p[56] << 20)
|
||||
| (mask_p[55] << 18) | (mask_p[54] << 16)
|
||||
| (mask_p[53] << 14) | (mask_p[52] << 12)
|
||||
| (mask_p[51] << 10) | (mask_p[50] << 8)
|
||||
| (mask_p[49] << 6) | (mask_p[48] << 4)
|
||||
| (mask_p[47] << 2) | (mask_p[46] << 0);
|
||||
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
|
||||
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
static void ar9002_olc_init(struct ath_hw *ah)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (!OLC_FOR_AR9280_20_LATER)
|
||||
return;
|
||||
|
||||
if (OLC_FOR_AR9287_10_LATER) {
|
||||
REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
|
||||
AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
|
||||
ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
|
||||
AR9287_AN_TXPC0_TXPCMODE,
|
||||
AR9287_AN_TXPC0_TXPCMODE_S,
|
||||
AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
|
||||
udelay(100);
|
||||
} else {
|
||||
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
|
||||
ah->originalGain[i] =
|
||||
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
|
||||
AR_PHY_TX_GAIN);
|
||||
ah->PDADCdelta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
u32 pll;
|
||||
|
||||
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
|
||||
|
||||
if (chan && IS_CHAN_HALF_RATE(chan))
|
||||
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
|
||||
else if (chan && IS_CHAN_QUARTER_RATE(chan))
|
||||
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
|
||||
|
||||
if (chan && IS_CHAN_5GHZ(chan)) {
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
pll = 0x142c;
|
||||
else if (AR_SREV_9280_20(ah))
|
||||
pll = 0x2850;
|
||||
else
|
||||
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
|
||||
} else {
|
||||
pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
|
||||
}
|
||||
|
||||
return pll;
|
||||
}
|
||||
|
||||
static void ar9002_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nfarray[NUM_NF_READINGS])
|
||||
{
|
||||
int16_t nf;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
|
||||
nfarray[0] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
|
||||
if (IS_CHAN_HT40(ah->curchan))
|
||||
nfarray[3] = sign_extend32(nf, 8);
|
||||
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
|
||||
return;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
|
||||
nfarray[1] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
|
||||
if (IS_CHAN_HT40(ah->curchan))
|
||||
nfarray[4] = sign_extend32(nf, 8);
|
||||
}
|
||||
|
||||
static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9285(ah)) {
|
||||
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
|
||||
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
|
||||
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
|
||||
} else if (AR_SREV_9287(ah)) {
|
||||
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
|
||||
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
|
||||
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
|
||||
} else if (AR_SREV_9271(ah)) {
|
||||
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ;
|
||||
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ;
|
||||
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ;
|
||||
} else {
|
||||
ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
|
||||
ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
|
||||
ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
|
||||
ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
|
||||
ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
|
||||
ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
|
||||
antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
|
||||
AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
|
||||
antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
|
||||
AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
|
||||
antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
|
||||
AR_PHY_9285_FAST_DIV_BIAS_S;
|
||||
antconf->lna1_lna2_delta = -3;
|
||||
antconf->div_group = 0;
|
||||
}
|
||||
|
||||
static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
|
||||
regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
|
||||
AR_PHY_9285_ANT_DIV_ALT_LNACONF |
|
||||
AR_PHY_9285_FAST_DIV_BIAS);
|
||||
regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
|
||||
& AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
|
||||
regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
|
||||
& AR_PHY_9285_ANT_DIV_ALT_LNACONF);
|
||||
regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
|
||||
& AR_PHY_9285_FAST_DIV_BIAS);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
|
||||
}
|
||||
|
||||
void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->set_rf_regs = NULL;
|
||||
priv_ops->rf_alloc_ext_banks = NULL;
|
||||
priv_ops->rf_free_ext_banks = NULL;
|
||||
priv_ops->rf_set_freq = ar9002_hw_set_channel;
|
||||
priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
|
||||
priv_ops->olc_init = ar9002_olc_init;
|
||||
priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
|
||||
priv_ops->do_getnf = ar9002_hw_do_getnf;
|
||||
|
||||
ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
|
||||
ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
|
||||
|
||||
ar9002_hw_set_nf_limits(ah);
|
||||
}
|
||||
932
src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c
Normal file
932
src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c
Normal file
@@ -0,0 +1,932 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
#include "ar9003_phy.h"
|
||||
|
||||
#define MAX_MEASUREMENT 8
|
||||
#define MAX_MAG_DELTA 11
|
||||
#define MAX_PHS_DELTA 10
|
||||
|
||||
struct coeff {
|
||||
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
|
||||
int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
|
||||
int iqc_coeff[2];
|
||||
};
|
||||
|
||||
enum ar9003_cal_types {
|
||||
IQ_MISMATCH_CAL = BIT(0),
|
||||
TEMP_COMP_CAL = BIT(1),
|
||||
};
|
||||
|
||||
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
/* Select calibration to run */
|
||||
switch (currCal->calData->calType) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
/*
|
||||
* Start calibration with
|
||||
* 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING4,
|
||||
AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
|
||||
currCal->calData->calCountMax);
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"starting IQ Mismatch Calibration\n");
|
||||
|
||||
/* Kick-off cal */
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
|
||||
break;
|
||||
case TEMP_COMP_CAL:
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
|
||||
AR_PHY_65NM_CH0_THERM_LOCAL, 1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
|
||||
AR_PHY_65NM_CH0_THERM_START, 1);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"starting Temperature Compensation Calibration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic calibration routine.
|
||||
* Recalibrate the lower PHY chips to account for temperature/environment
|
||||
* changes.
|
||||
*/
|
||||
static int ar9003_hw_per_calibration(struct ath_hw *ah,
|
||||
struct ath9k_channel *ichan __unused,
|
||||
u8 rxchainmask,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
/* Cal is assumed not done until explicitly set below */
|
||||
int iscaldone = 0;
|
||||
|
||||
/* Calibration in progress. */
|
||||
if (currCal->calState == CAL_RUNNING) {
|
||||
/* Check to see if it has finished. */
|
||||
if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
|
||||
/*
|
||||
* Accumulate cal measures for active chains
|
||||
*/
|
||||
currCal->calData->calCollect(ah);
|
||||
ah->cal_samples++;
|
||||
|
||||
if (ah->cal_samples >=
|
||||
currCal->calData->calNumSamples) {
|
||||
unsigned int i, numChains = 0;
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (rxchainmask & (1 << i))
|
||||
numChains++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process accumulated data
|
||||
*/
|
||||
currCal->calData->calPostProc(ah, numChains);
|
||||
|
||||
/* Calibration has finished. */
|
||||
caldata->CalValid |= currCal->calData->calType;
|
||||
currCal->calState = CAL_DONE;
|
||||
iscaldone = 1;
|
||||
} else {
|
||||
/*
|
||||
* Set-up collection of another sub-sample until we
|
||||
* get desired number
|
||||
*/
|
||||
ar9003_hw_setup_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
} else if (!(caldata->CalValid & currCal->calData->calType)) {
|
||||
/* If current cal is marked invalid in channel, kick it off */
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
static int ar9003_hw_calibrate(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 rxchainmask,
|
||||
int longcal)
|
||||
{
|
||||
int iscaldone = 1;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
|
||||
/*
|
||||
* For given calibration:
|
||||
* 1. Call generic cal routine
|
||||
* 2. When this cal is done (isCalDone) if we have more cals waiting
|
||||
* (eg after reset), mask this to upper layers by not propagating
|
||||
* isCalDone if it is set to TRUE.
|
||||
* Instead, change isCalDone to FALSE and setup the waiting cal(s)
|
||||
* to be run.
|
||||
*/
|
||||
if (currCal &&
|
||||
(currCal->calState == CAL_RUNNING ||
|
||||
currCal->calState == CAL_WAITING)) {
|
||||
iscaldone = ar9003_hw_per_calibration(ah, chan,
|
||||
rxchainmask, currCal);
|
||||
if (iscaldone) {
|
||||
ah->cal_list_curr = currCal = currCal->calNext;
|
||||
|
||||
if (currCal->calState == CAL_WAITING) {
|
||||
iscaldone = 0;
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do NF cal only at longer intervals */
|
||||
if (longcal) {
|
||||
/*
|
||||
* Get the value from the previous NF cal and update
|
||||
* history buffer.
|
||||
*/
|
||||
ath9k_hw_getnf(ah, chan);
|
||||
|
||||
/*
|
||||
* Load the NF from history buffer of the current channel.
|
||||
* NF is slow time-variant, so it is OK to use a historical
|
||||
* value.
|
||||
*/
|
||||
ath9k_hw_loadnf(ah, ah->curchan);
|
||||
|
||||
/* start NF calibration, without updating BB NF register */
|
||||
ath9k_hw_start_nfcal(ah, 0);
|
||||
}
|
||||
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Accumulate IQ cal measures for active chains */
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (ah->txchainmask & BIT(i)) {
|
||||
ah->totalPowerMeasI[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ah->totalPowerMeasQ[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ah->totalIqCorrMeas[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
DBG2("ath9k: "
|
||||
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
|
||||
ah->cal_samples, i, ah->totalPowerMeasI[i],
|
||||
ah->totalPowerMeasQ[i],
|
||||
ah->totalIqCorrMeas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
u32 powerMeasQ, powerMeasI, iqCorrMeas;
|
||||
u32 qCoffDenom, iCoffDenom;
|
||||
int32_t qCoff, iCoff;
|
||||
int iqCorrNeg, i;
|
||||
static const uint32_t offset_array[3] = {
|
||||
AR_PHY_RX_IQCAL_CORR_B0,
|
||||
AR_PHY_RX_IQCAL_CORR_B1,
|
||||
AR_PHY_RX_IQCAL_CORR_B2,
|
||||
};
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
powerMeasI = ah->totalPowerMeasI[i];
|
||||
powerMeasQ = ah->totalPowerMeasQ[i];
|
||||
iqCorrMeas = ah->totalIqCorrMeas[i];
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Starting IQ Cal and Correction for Chain %d\n",
|
||||
i);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
|
||||
i, ah->totalIqCorrMeas[i]);
|
||||
|
||||
iqCorrNeg = 0;
|
||||
|
||||
if (iqCorrMeas > 0x80000000) {
|
||||
iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
|
||||
iqCorrNeg = 1;
|
||||
}
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
|
||||
DBG2("ath9k: iqCorrNeg is 0x%08x\n",
|
||||
iqCorrNeg);
|
||||
|
||||
iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
|
||||
qCoffDenom = powerMeasQ / 64;
|
||||
|
||||
if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
|
||||
iCoff = iqCorrMeas / iCoffDenom;
|
||||
qCoff = powerMeasI / qCoffDenom - 64;
|
||||
DBG2("ath9k: "
|
||||
"Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
DBG2("ath9k: "
|
||||
"Chn %d qCoff = 0x%08x\n", i, qCoff);
|
||||
|
||||
/* Force bounds on iCoff */
|
||||
if (iCoff >= 63)
|
||||
iCoff = 63;
|
||||
else if (iCoff <= -63)
|
||||
iCoff = -63;
|
||||
|
||||
/* Negate iCoff if iqCorrNeg == 0 */
|
||||
if (iqCorrNeg == 0x0)
|
||||
iCoff = -iCoff;
|
||||
|
||||
/* Force bounds on qCoff */
|
||||
if (qCoff >= 63)
|
||||
qCoff = 63;
|
||||
else if (qCoff <= -63)
|
||||
qCoff = -63;
|
||||
|
||||
iCoff = iCoff & 0x7f;
|
||||
qCoff = qCoff & 0x7f;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
|
||||
i, iCoff, qCoff);
|
||||
DBG2("ath9k: "
|
||||
"Register offset (0x%04x) before update = 0x%x\n",
|
||||
offset_array[i],
|
||||
REG_READ(ah, offset_array[i]));
|
||||
|
||||
REG_RMW_FIELD(ah, offset_array[i],
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
|
||||
iCoff);
|
||||
REG_RMW_FIELD(ah, offset_array[i],
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
|
||||
qCoff);
|
||||
DBG2("ath9k: "
|
||||
"Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
|
||||
offset_array[i],
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
|
||||
REG_READ(ah, offset_array[i]));
|
||||
DBG2("ath9k: "
|
||||
"Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
|
||||
offset_array[i],
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
|
||||
REG_READ(ah, offset_array[i]));
|
||||
|
||||
DBG2("ath9k: "
|
||||
"IQ Cal and Correction done for Chain %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
|
||||
DBG2("ath9k: "
|
||||
"IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
|
||||
(unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
|
||||
REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
|
||||
}
|
||||
|
||||
static const struct ath9k_percal_data iq_cal_single_sample = {
|
||||
IQ_MISMATCH_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ar9003_hw_iqcal_collect,
|
||||
ar9003_hw_iqcalibrate
|
||||
};
|
||||
|
||||
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
}
|
||||
|
||||
/*
|
||||
* solve 4x4 linear equation used in loopback iq cal.
|
||||
*/
|
||||
static int ar9003_hw_solve_iq_cal(struct ath_hw *ah __unused,
|
||||
s32 sin_2phi_1,
|
||||
s32 cos_2phi_1,
|
||||
s32 sin_2phi_2,
|
||||
s32 cos_2phi_2,
|
||||
s32 mag_a0_d0,
|
||||
s32 phs_a0_d0,
|
||||
s32 mag_a1_d0,
|
||||
s32 phs_a1_d0,
|
||||
s32 solved_eq[])
|
||||
{
|
||||
s32 f1 = cos_2phi_1 - cos_2phi_2,
|
||||
f3 = sin_2phi_1 - sin_2phi_2,
|
||||
f2;
|
||||
s32 mag_tx, phs_tx, mag_rx, phs_rx;
|
||||
const s32 result_shift = 1 << 15;
|
||||
|
||||
f2 = (f1 * f1 + f3 * f3) / result_shift;
|
||||
|
||||
if (!f2) {
|
||||
DBG("ath9k: Divide by 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mag mismatch, tx */
|
||||
mag_tx = f1 * (mag_a0_d0 - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
|
||||
/* phs mismatch, tx */
|
||||
phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
|
||||
|
||||
mag_tx = (mag_tx / f2);
|
||||
phs_tx = (phs_tx / f2);
|
||||
|
||||
/* mag mismatch, rx */
|
||||
mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
|
||||
result_shift;
|
||||
/* phs mismatch, rx */
|
||||
phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
|
||||
result_shift;
|
||||
|
||||
solved_eq[0] = mag_tx;
|
||||
solved_eq[1] = phs_tx;
|
||||
solved_eq[2] = mag_rx;
|
||||
solved_eq[3] = phs_rx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah __unused, s32 in_re, s32 in_im)
|
||||
{
|
||||
s32 abs_i = abs(in_re),
|
||||
abs_q = abs(in_im),
|
||||
max_abs, min_abs;
|
||||
|
||||
if (abs_i > abs_q) {
|
||||
max_abs = abs_i;
|
||||
min_abs = abs_q;
|
||||
} else {
|
||||
max_abs = abs_q;
|
||||
min_abs = abs_i;
|
||||
}
|
||||
|
||||
return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
|
||||
}
|
||||
|
||||
#define DELPT 32
|
||||
|
||||
static int ar9003_hw_calc_iq_corr(struct ath_hw *ah,
|
||||
s32 chain_idx,
|
||||
const s32 iq_res[],
|
||||
s32 iqc_coeff[])
|
||||
{
|
||||
s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
|
||||
i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
|
||||
i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
|
||||
i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
|
||||
s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
|
||||
phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
|
||||
sin_2phi_1, cos_2phi_1,
|
||||
sin_2phi_2, cos_2phi_2;
|
||||
s32 mag_tx, phs_tx, mag_rx, phs_rx;
|
||||
s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
|
||||
q_q_coff, q_i_coff;
|
||||
const s32 res_scale = 1 << 15;
|
||||
const s32 delpt_shift = 1 << 8;
|
||||
s32 mag1, mag2;
|
||||
|
||||
i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
|
||||
i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
|
||||
iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
|
||||
|
||||
if (i2_m_q2_a0_d0 > 0x800)
|
||||
i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
|
||||
|
||||
if (i2_p_q2_a0_d0 > 0x800)
|
||||
i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
|
||||
|
||||
if (iq_corr_a0_d0 > 0x800)
|
||||
iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
|
||||
|
||||
i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
|
||||
i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
|
||||
iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
|
||||
|
||||
if (i2_m_q2_a0_d1 > 0x800)
|
||||
i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
|
||||
|
||||
if (i2_p_q2_a0_d1 > 0x800)
|
||||
i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
|
||||
|
||||
if (iq_corr_a0_d1 > 0x800)
|
||||
iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
|
||||
|
||||
i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
|
||||
i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
|
||||
iq_corr_a1_d0 = iq_res[4] & 0xfff;
|
||||
|
||||
if (i2_m_q2_a1_d0 > 0x800)
|
||||
i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
|
||||
|
||||
if (i2_p_q2_a1_d0 > 0x800)
|
||||
i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
|
||||
|
||||
if (iq_corr_a1_d0 > 0x800)
|
||||
iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
|
||||
|
||||
i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
|
||||
i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
|
||||
iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
|
||||
|
||||
if (i2_m_q2_a1_d1 > 0x800)
|
||||
i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
|
||||
|
||||
if (i2_p_q2_a1_d1 > 0x800)
|
||||
i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
|
||||
|
||||
if (iq_corr_a1_d1 > 0x800)
|
||||
iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
|
||||
|
||||
if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
|
||||
(i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
|
||||
DBG("ath9k: "
|
||||
"Divide by 0:\n"
|
||||
"a0_d0=%d\n"
|
||||
"a0_d1=%d\n"
|
||||
"a2_d0=%d\n"
|
||||
"a1_d1=%d\n",
|
||||
i2_p_q2_a0_d0, i2_p_q2_a0_d1,
|
||||
i2_p_q2_a1_d0, i2_p_q2_a1_d1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
|
||||
phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
|
||||
|
||||
mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
|
||||
phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
|
||||
|
||||
mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
|
||||
phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
|
||||
|
||||
mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
|
||||
phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
|
||||
|
||||
/* w/o analog phase shift */
|
||||
sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
|
||||
/* w/o analog phase shift */
|
||||
cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
|
||||
/* w/ analog phase shift */
|
||||
sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
|
||||
/* w/ analog phase shift */
|
||||
cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
|
||||
|
||||
/*
|
||||
* force sin^2 + cos^2 = 1;
|
||||
* find magnitude by approximation
|
||||
*/
|
||||
mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
|
||||
mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
|
||||
|
||||
if ((mag1 == 0) || (mag2 == 0)) {
|
||||
DBG("ath9k: "
|
||||
"Divide by 0: mag1=%d, mag2=%d\n",
|
||||
mag1, mag2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* normalization sin and cos by mag */
|
||||
sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
|
||||
cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
|
||||
sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
|
||||
cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
|
||||
|
||||
/* calculate IQ mismatch */
|
||||
if (!ar9003_hw_solve_iq_cal(ah,
|
||||
sin_2phi_1, cos_2phi_1,
|
||||
sin_2phi_2, cos_2phi_2,
|
||||
mag_a0_d0, phs_a0_d0,
|
||||
mag_a1_d0,
|
||||
phs_a1_d0, solved_eq)) {
|
||||
DBG("ath9k: "
|
||||
"Call to ar9003_hw_solve_iq_cal() failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mag_tx = solved_eq[0];
|
||||
phs_tx = solved_eq[1];
|
||||
mag_rx = solved_eq[2];
|
||||
phs_rx = solved_eq[3];
|
||||
|
||||
DBG2("ath9k: "
|
||||
"chain %d: mag mismatch=%d phase mismatch=%d\n",
|
||||
chain_idx, mag_tx/res_scale, phs_tx/res_scale);
|
||||
|
||||
if (res_scale == mag_tx) {
|
||||
DBG("ath9k: "
|
||||
"Divide by 0: mag_tx=%d, res_scale=%d\n",
|
||||
mag_tx, res_scale);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate and quantize Tx IQ correction factor */
|
||||
mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
|
||||
phs_corr_tx = -phs_tx;
|
||||
|
||||
q_q_coff = (mag_corr_tx * 128 / res_scale);
|
||||
q_i_coff = (phs_corr_tx * 256 / res_scale);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"tx chain %d: mag corr=%d phase corr=%d\n",
|
||||
chain_idx, q_q_coff, q_i_coff);
|
||||
|
||||
if (q_i_coff < -63)
|
||||
q_i_coff = -63;
|
||||
if (q_i_coff > 63)
|
||||
q_i_coff = 63;
|
||||
if (q_q_coff < -63)
|
||||
q_q_coff = -63;
|
||||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"tx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[0]);
|
||||
|
||||
if (-mag_rx == res_scale) {
|
||||
DBG("ath9k: "
|
||||
"Divide by 0: mag_rx=%d, res_scale=%d\n",
|
||||
mag_rx, res_scale);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate and quantize Rx IQ correction factors */
|
||||
mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
|
||||
phs_corr_rx = -phs_rx;
|
||||
|
||||
q_q_coff = (mag_corr_rx * 128 / res_scale);
|
||||
q_i_coff = (phs_corr_rx * 256 / res_scale);
|
||||
|
||||
DBG("ath9k: "
|
||||
"rx chain %d: mag corr=%d phase corr=%d\n",
|
||||
chain_idx, q_q_coff, q_i_coff);
|
||||
|
||||
if (q_i_coff < -63)
|
||||
q_i_coff = -63;
|
||||
if (q_i_coff > 63)
|
||||
q_i_coff = 63;
|
||||
if (q_q_coff < -63)
|
||||
q_q_coff = -63;
|
||||
if (q_q_coff > 63)
|
||||
q_q_coff = 63;
|
||||
|
||||
iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"rx chain %d: iq corr coeff=%x\n",
|
||||
chain_idx, iqc_coeff[1]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
int max_delta)
|
||||
{
|
||||
int mp_max = -64, max_idx = 0;
|
||||
int mp_min = 63, min_idx = 0;
|
||||
int mp_avg = 0, i, outlier_idx = 0;
|
||||
|
||||
/* find min/max mismatch across all calibrated gains */
|
||||
for (i = 0; i < nmeasurement; i++) {
|
||||
mp_avg += mp_coeff[i];
|
||||
if (mp_coeff[i] > mp_max) {
|
||||
mp_max = mp_coeff[i];
|
||||
max_idx = i;
|
||||
} else if (mp_coeff[i] < mp_min) {
|
||||
mp_min = mp_coeff[i];
|
||||
min_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* find average (exclude max abs value) */
|
||||
for (i = 0; i < nmeasurement; i++) {
|
||||
if ((abs(mp_coeff[i]) < abs(mp_max)) ||
|
||||
(abs(mp_coeff[i]) < abs(mp_min)))
|
||||
mp_avg += mp_coeff[i];
|
||||
}
|
||||
mp_avg /= (nmeasurement - 1);
|
||||
|
||||
/* detect outlier */
|
||||
if (abs(mp_max - mp_min) > max_delta) {
|
||||
if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
|
||||
outlier_idx = max_idx;
|
||||
else
|
||||
outlier_idx = min_idx;
|
||||
}
|
||||
mp_coeff[outlier_idx] = mp_avg;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
|
||||
u8 num_chains,
|
||||
struct coeff *coeff)
|
||||
{
|
||||
int i, im, nmeasurement;
|
||||
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
|
||||
|
||||
memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
|
||||
for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
|
||||
tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
|
||||
AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
|
||||
if (!AR_SREV_9485(ah)) {
|
||||
tx_corr_coeff[i * 2][1] =
|
||||
tx_corr_coeff[(i * 2) + 1][1] =
|
||||
AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
|
||||
|
||||
tx_corr_coeff[i * 2][2] =
|
||||
tx_corr_coeff[(i * 2) + 1][2] =
|
||||
AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the average of 2 passes */
|
||||
for (i = 0; i < num_chains; i++) {
|
||||
nmeasurement = REG_READ_FIELD(ah,
|
||||
AR_PHY_TX_IQCAL_STATUS_B0,
|
||||
AR_PHY_CALIBRATED_GAINS_0);
|
||||
|
||||
if (nmeasurement > MAX_MEASUREMENT)
|
||||
nmeasurement = MAX_MEASUREMENT;
|
||||
|
||||
/* detect outlier only if nmeasurement > 1 */
|
||||
if (nmeasurement > 1) {
|
||||
/* Detect magnitude outlier */
|
||||
ar9003_hw_detect_outlier(coeff->mag_coeff[i],
|
||||
nmeasurement, MAX_MAG_DELTA);
|
||||
|
||||
/* Detect phase outlier */
|
||||
ar9003_hw_detect_outlier(coeff->phs_coeff[i],
|
||||
nmeasurement, MAX_PHS_DELTA);
|
||||
}
|
||||
|
||||
for (im = 0; im < nmeasurement; im++) {
|
||||
|
||||
coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
|
||||
((coeff->phs_coeff[i][im] & 0x7f) << 7);
|
||||
|
||||
if ((im % 2) == 0)
|
||||
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
|
||||
AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
|
||||
coeff->iqc_coeff[0]);
|
||||
else
|
||||
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
|
||||
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
|
||||
coeff->iqc_coeff[0]);
|
||||
}
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
|
||||
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
|
||||
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static int ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
|
||||
{
|
||||
u8 tx_gain_forced;
|
||||
|
||||
tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
|
||||
AR_PHY_TXGAIN_FORCE);
|
||||
if (tx_gain_forced)
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
|
||||
AR_PHY_TXGAIN_FORCE, 0);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
|
||||
AR_PHY_TX_IQCAL_START_DO_CAL, 1);
|
||||
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
|
||||
AR_PHY_TX_IQCAL_START_DO_CAL, 0,
|
||||
AH_WAIT_TIMEOUT)) {
|
||||
DBG2("ath9k: "
|
||||
"Tx IQ Cal is not completed.\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
|
||||
{
|
||||
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
|
||||
AR_PHY_TX_IQCAL_STATUS_B0,
|
||||
AR_PHY_TX_IQCAL_STATUS_B1,
|
||||
AR_PHY_TX_IQCAL_STATUS_B2,
|
||||
};
|
||||
const uint32_t chan_info_tab[] = {
|
||||
AR_PHY_CHAN_INFO_TAB_0,
|
||||
AR_PHY_CHAN_INFO_TAB_1,
|
||||
AR_PHY_CHAN_INFO_TAB_2,
|
||||
};
|
||||
struct coeff coeff;
|
||||
s32 iq_res[6];
|
||||
u8 num_chains = 0;
|
||||
int i, im, j;
|
||||
int nmeasurement;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (ah->txchainmask & (1 << i))
|
||||
num_chains++;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_chains; i++) {
|
||||
nmeasurement = REG_READ_FIELD(ah,
|
||||
AR_PHY_TX_IQCAL_STATUS_B0,
|
||||
AR_PHY_CALIBRATED_GAINS_0);
|
||||
if (nmeasurement > MAX_MEASUREMENT)
|
||||
nmeasurement = MAX_MEASUREMENT;
|
||||
|
||||
for (im = 0; im < nmeasurement; im++) {
|
||||
DBG2("ath9k: "
|
||||
"Doing Tx IQ Cal for chain %d.\n", i);
|
||||
|
||||
if (REG_READ(ah, txiqcal_status[i]) &
|
||||
AR_PHY_TX_IQCAL_STATUS_FAILED) {
|
||||
DBG("ath9k: "
|
||||
"Tx IQ Cal failed for chain %d.\n", i);
|
||||
goto tx_iqcal_fail;
|
||||
}
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
u32 idx = 2 * j, offset = 4 * (3 * im + j);
|
||||
|
||||
REG_RMW_FIELD(ah,
|
||||
AR_PHY_CHAN_INFO_MEMORY,
|
||||
AR_PHY_CHAN_INFO_TAB_S2_READ,
|
||||
0);
|
||||
|
||||
/* 32 bits */
|
||||
iq_res[idx] = REG_READ(ah,
|
||||
chan_info_tab[i] +
|
||||
offset);
|
||||
|
||||
REG_RMW_FIELD(ah,
|
||||
AR_PHY_CHAN_INFO_MEMORY,
|
||||
AR_PHY_CHAN_INFO_TAB_S2_READ,
|
||||
1);
|
||||
|
||||
/* 16 bits */
|
||||
iq_res[idx + 1] = 0xffff & REG_READ(ah,
|
||||
chan_info_tab[i] + offset);
|
||||
|
||||
DBG2("ath9k: "
|
||||
"IQ RES[%d]=0x%x"
|
||||
"IQ_RES[%d]=0x%x\n",
|
||||
idx, iq_res[idx], idx + 1,
|
||||
iq_res[idx + 1]);
|
||||
}
|
||||
|
||||
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
|
||||
coeff.iqc_coeff)) {
|
||||
DBG("ath9k: "
|
||||
"Failed in calculation of \
|
||||
IQ correction.\n");
|
||||
goto tx_iqcal_fail;
|
||||
}
|
||||
|
||||
coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
|
||||
coeff.phs_coeff[i][im] =
|
||||
(coeff.iqc_coeff[0] >> 7) & 0x7f;
|
||||
|
||||
if (coeff.mag_coeff[i][im] > 63)
|
||||
coeff.mag_coeff[i][im] -= 128;
|
||||
if (coeff.phs_coeff[i][im] > 63)
|
||||
coeff.phs_coeff[i][im] -= 128;
|
||||
}
|
||||
}
|
||||
ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
|
||||
|
||||
return;
|
||||
|
||||
tx_iqcal_fail:
|
||||
DBG("ath9k: Tx IQ Cal failed\n");
|
||||
return;
|
||||
}
|
||||
static int ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan __unused)
|
||||
{
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
int val;
|
||||
int txiqcal_done = 0;
|
||||
|
||||
val = REG_READ(ah, AR_ENT_OTP);
|
||||
DBG2("ath9k: ath9k: AR_ENT_OTP 0x%x\n", val);
|
||||
|
||||
/* Configure rx/tx chains before running AGC/TxiQ cals */
|
||||
if (val & AR_ENT_OTP_CHAIN2_DISABLE)
|
||||
ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
|
||||
else
|
||||
ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
|
||||
pCap->tx_chainmask);
|
||||
|
||||
/* Do Tx IQ Calibration */
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
|
||||
AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
|
||||
DELPT);
|
||||
|
||||
/*
|
||||
* For AR9485 or later chips, TxIQ cal runs as part of
|
||||
* AGC calibration
|
||||
*/
|
||||
if (AR_SREV_9485_OR_LATER(ah))
|
||||
txiqcal_done = 1;
|
||||
else {
|
||||
txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
|
||||
udelay(5);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
|
||||
}
|
||||
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
|
||||
/* Poll for offset calibration complete */
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
DBG("ath9k: "
|
||||
"offset calibration failed to complete in 1ms; noisy environment?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah);
|
||||
|
||||
/* Revert chainmasks to their original values before NF cal */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
ath9k_hw_start_nfcal(ah, 1);
|
||||
|
||||
/* Initialize list pointers */
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
|
||||
if (ah->supp_cals & IQ_MISMATCH_CAL) {
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
DBG2("ath9k: "
|
||||
"enabling IQ Calibration.\n");
|
||||
}
|
||||
|
||||
if (ah->supp_cals & TEMP_COMP_CAL) {
|
||||
INIT_CAL(&ah->tempCompCalData);
|
||||
INSERT_CAL(ah, &ah->tempCompCalData);
|
||||
DBG2("ath9k: "
|
||||
"enabling Temperature Compensation Calibration.\n");
|
||||
}
|
||||
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
if (ah->cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
|
||||
|
||||
if (ah->caldata)
|
||||
ah->caldata->CalValid = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
|
||||
priv_ops->init_cal = ar9003_hw_init_cal;
|
||||
priv_ops->setup_calibration = ar9003_hw_setup_calibration;
|
||||
|
||||
ops->calibrate = ar9003_hw_calibrate;
|
||||
}
|
||||
5005
src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c
Normal file
5005
src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c
Normal file
File diff suppressed because it is too large
Load Diff
409
src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c
Normal file
409
src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "ar9003_mac.h"
|
||||
#include "ar9003_2p2_initvals.h"
|
||||
#include "ar9485_initvals.h"
|
||||
#include "ar9340_initvals.h"
|
||||
|
||||
/* General hardware code for the AR9003 hadware family */
|
||||
|
||||
/*
|
||||
* The AR9003 family uses a new INI format (pre, core, post
|
||||
* arrays per subsystem). This provides support for the
|
||||
* AR9003 2.2 chipsets.
|
||||
*/
|
||||
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9340(ah)) {
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
ar9340_1p0_mac_core,
|
||||
ARRAY_SIZE(ar9340_1p0_mac_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
|
||||
ar9340_1p0_mac_postamble,
|
||||
ARRAY_SIZE(ar9340_1p0_mac_postamble), 5);
|
||||
|
||||
/* bb */
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
|
||||
ar9340_1p0_baseband_core,
|
||||
ARRAY_SIZE(ar9340_1p0_baseband_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
|
||||
ar9340_1p0_baseband_postamble,
|
||||
ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5);
|
||||
|
||||
/* radio */
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
|
||||
ar9340_1p0_radio_core,
|
||||
ARRAY_SIZE(ar9340_1p0_radio_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
|
||||
ar9340_1p0_radio_postamble,
|
||||
ARRAY_SIZE(ar9340_1p0_radio_postamble), 5);
|
||||
|
||||
/* soc */
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
|
||||
ar9340_1p0_soc_preamble,
|
||||
ARRAY_SIZE(ar9340_1p0_soc_preamble), 2);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
|
||||
ar9340_1p0_soc_postamble,
|
||||
ARRAY_SIZE(ar9340_1p0_soc_postamble), 5);
|
||||
|
||||
/* rx/tx gain */
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9340Common_wo_xlna_rx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
|
||||
5);
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_high_ob_db_tx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
|
||||
5);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional,
|
||||
ar9340Modes_fast_clock_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
|
||||
3);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional_40M,
|
||||
ar9340_1p0_radio_core_40M,
|
||||
ARRAY_SIZE(ar9340_1p0_radio_core_40M),
|
||||
2);
|
||||
} else if (AR_SREV_9485_11(ah)) {
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
ar9485_1_1_mac_core,
|
||||
ARRAY_SIZE(ar9485_1_1_mac_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
|
||||
ar9485_1_1_mac_postamble,
|
||||
ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
|
||||
|
||||
/* bb */
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
|
||||
ARRAY_SIZE(ar9485_1_1), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
|
||||
ar9485_1_1_baseband_core,
|
||||
ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
|
||||
ar9485_1_1_baseband_postamble,
|
||||
ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
|
||||
|
||||
/* radio */
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
|
||||
ar9485_1_1_radio_core,
|
||||
ARRAY_SIZE(ar9485_1_1_radio_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
|
||||
ar9485_1_1_radio_postamble,
|
||||
ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
|
||||
|
||||
/* soc */
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
|
||||
ar9485_1_1_soc_preamble,
|
||||
ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
|
||||
|
||||
/* rx/tx gain */
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9485Common_wo_xlna_rx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2);
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485_modes_lowest_ob_db_tx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
|
||||
5);
|
||||
|
||||
/* Load PCIE SERDES settings from INI */
|
||||
|
||||
/* Awake Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9485_1_1_pcie_phy_clkreq_disable_L1,
|
||||
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
|
||||
2);
|
||||
|
||||
/* Sleep Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||
ar9485_1_1_pcie_phy_clkreq_disable_L1,
|
||||
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
|
||||
2);
|
||||
} else {
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
ar9300_2p2_mac_core,
|
||||
ARRAY_SIZE(ar9300_2p2_mac_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
|
||||
ar9300_2p2_mac_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
|
||||
|
||||
/* bb */
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
|
||||
ar9300_2p2_baseband_core,
|
||||
ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
|
||||
ar9300_2p2_baseband_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
|
||||
|
||||
/* radio */
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
|
||||
ar9300_2p2_radio_core,
|
||||
ARRAY_SIZE(ar9300_2p2_radio_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
|
||||
ar9300_2p2_radio_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
|
||||
|
||||
/* soc */
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
|
||||
ar9300_2p2_soc_preamble,
|
||||
ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
|
||||
ar9300_2p2_soc_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
|
||||
|
||||
/* rx/tx gain */
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
|
||||
/* Load PCIE SERDES settings from INI */
|
||||
|
||||
/* Awake Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
|
||||
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
|
||||
2);
|
||||
|
||||
/* Sleep Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
|
||||
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
|
||||
2);
|
||||
|
||||
/* Fast clock modal settings */
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional,
|
||||
ar9300Modes_fast_clock_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
|
||||
3);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
|
||||
{
|
||||
switch (ar9003_hw_get_tx_gain_idx(ah)) {
|
||||
case 0:
|
||||
default:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
|
||||
5);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485_modes_lowest_ob_db_tx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
case 1:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
|
||||
5);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_high_ob_db_tx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_high_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
case 2:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
|
||||
5);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_low_ob_db_tx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_low_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
case 3:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
|
||||
5);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_high_power_tx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_high_power_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
|
||||
{
|
||||
switch (ar9003_hw_get_rx_gain_idx(ah)) {
|
||||
case 0:
|
||||
default:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9340Common_rx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
|
||||
2);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9485Common_wo_xlna_rx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
|
||||
2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
|
||||
2);
|
||||
break;
|
||||
case 1:
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9340Common_wo_xlna_rx_gain_table_1p0,
|
||||
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
|
||||
2);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9485Common_wo_xlna_rx_gain_1_1,
|
||||
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
|
||||
2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_wo_xlna_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
|
||||
2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* set gain table pointers according to values read from the eeprom */
|
||||
static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
{
|
||||
ar9003_tx_gain_table_apply(ah);
|
||||
ar9003_rx_gain_table_apply(ah);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for ASPM support.
|
||||
*
|
||||
* Disable PLL when in L0s as well as receiver clock when in L1.
|
||||
* This power saving option must be enabled through the SerDes.
|
||||
*
|
||||
* Programming the SerDes must go through the same 288 bit serial shift
|
||||
* register as the other analog registers. Hence the 9 writes.
|
||||
*/
|
||||
static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
|
||||
int restore,
|
||||
int power_off)
|
||||
{
|
||||
if (ah->is_pciexpress != 1)
|
||||
return;
|
||||
|
||||
/* Do not touch SerDes registers */
|
||||
if (ah->config.pcie_powersave_enable == 2)
|
||||
return;
|
||||
|
||||
/* Nothing to do on restore for 11N */
|
||||
if (!restore) {
|
||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
|
||||
/* Several PCIe massages to ensure proper behaviour */
|
||||
if (ah->config.pcie_waen)
|
||||
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
|
||||
else
|
||||
REG_WRITE(ah, AR_WA, ah->WARegVal);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configire PCIE after Ini init. SERDES values now come from ini file
|
||||
* This enables PCIe low power mode.
|
||||
*/
|
||||
if (ah->config.pcieSerDesWrite) {
|
||||
unsigned int i;
|
||||
struct ar5416IniArray *array;
|
||||
|
||||
array = power_off ? &ah->iniPcieSerdes :
|
||||
&ah->iniPcieSerdesLowPower;
|
||||
|
||||
for (i = 0; i < array->ia_rows; i++) {
|
||||
REG_WRITE(ah,
|
||||
INI_RA(array, i, 0),
|
||||
INI_RA(array, i, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets up the AR9003 hardware familiy callbacks */
|
||||
void ar9003_hw_attach_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
|
||||
priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
|
||||
|
||||
ops->config_pci_powersave = ar9003_hw_configpcipowersave;
|
||||
|
||||
ar9003_hw_attach_phy_ops(ah);
|
||||
ar9003_hw_attach_calib_ops(ah);
|
||||
ar9003_hw_attach_mac_ops(ah);
|
||||
}
|
||||
669
src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c
Normal file
669
src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c
Normal file
@@ -0,0 +1,669 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
#include "ar9003_mac.h"
|
||||
|
||||
static void ar9003_hw_rx_enable(struct ath_hw *hw)
|
||||
{
|
||||
REG_WRITE(hw, AR_CR, 0);
|
||||
}
|
||||
|
||||
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
|
||||
{
|
||||
int checksum;
|
||||
|
||||
checksum = ads->info + ads->link
|
||||
+ ads->data0 + ads->ctl3
|
||||
+ ads->data1 + ads->ctl5
|
||||
+ ads->data2 + ads->ctl7
|
||||
+ ads->data3 + ads->ctl9;
|
||||
|
||||
return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
|
||||
{
|
||||
struct ar9003_txc *ads = ds;
|
||||
|
||||
ads->link = ds_link;
|
||||
ads->ctl10 &= ~AR_TxPtrChkSum;
|
||||
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
|
||||
}
|
||||
|
||||
static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
|
||||
{
|
||||
struct ar9003_txc *ads = ds;
|
||||
|
||||
*ds_link = &ads->link;
|
||||
}
|
||||
|
||||
static int ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
{
|
||||
u32 isr = 0;
|
||||
u32 mask2 = 0;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
u32 sync_cause = 0;
|
||||
|
||||
if (ah->ah_ier & AR_IER_ENABLE) {
|
||||
if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
|
||||
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
|
||||
== AR_RTC_STATUS_ON)
|
||||
isr = REG_READ(ah, AR_ISR);
|
||||
}
|
||||
|
||||
sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
|
||||
|
||||
*masked = 0;
|
||||
|
||||
if (!isr && !sync_cause)
|
||||
return 0;
|
||||
} else {
|
||||
*masked = 0;
|
||||
isr = REG_READ(ah, AR_ISR);
|
||||
}
|
||||
|
||||
if (isr) {
|
||||
if (isr & AR_ISR_BCNMISC) {
|
||||
u32 isr2;
|
||||
isr2 = REG_READ(ah, AR_ISR_S2);
|
||||
|
||||
mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
|
||||
MAP_ISR_S2_TIM);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
|
||||
MAP_ISR_S2_DTIM);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
|
||||
MAP_ISR_S2_DTIMSYNC);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
|
||||
MAP_ISR_S2_CABEND);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
|
||||
MAP_ISR_S2_GTT);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_CST) <<
|
||||
MAP_ISR_S2_CST);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
|
||||
MAP_ISR_S2_TSFOOR);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
|
||||
MAP_ISR_S2_BB_WATCHDOG);
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
||||
REG_WRITE(ah, AR_ISR_S2, isr2);
|
||||
isr &= ~AR_ISR_BCNMISC;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
|
||||
isr = REG_READ(ah, AR_ISR_RAC);
|
||||
|
||||
if (isr == 0xffffffff) {
|
||||
*masked = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*masked = isr & ATH9K_INT_COMMON;
|
||||
|
||||
if (ah->config.rx_intr_mitigation)
|
||||
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
|
||||
*masked |= ATH9K_INT_RXLP;
|
||||
|
||||
if (ah->config.tx_intr_mitigation)
|
||||
if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
|
||||
*masked |= ATH9K_INT_TX;
|
||||
|
||||
if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
|
||||
*masked |= ATH9K_INT_RXLP;
|
||||
|
||||
if (isr & AR_ISR_HP_RXOK)
|
||||
*masked |= ATH9K_INT_RXHP;
|
||||
|
||||
if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
|
||||
*masked |= ATH9K_INT_TX;
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
||||
u32 s0, s1;
|
||||
s0 = REG_READ(ah, AR_ISR_S0);
|
||||
REG_WRITE(ah, AR_ISR_S0, s0);
|
||||
s1 = REG_READ(ah, AR_ISR_S1);
|
||||
REG_WRITE(ah, AR_ISR_S1, s1);
|
||||
|
||||
isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
|
||||
AR_ISR_TXEOL);
|
||||
}
|
||||
}
|
||||
|
||||
if (isr & AR_ISR_GENTMR) {
|
||||
u32 s5;
|
||||
|
||||
if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
|
||||
s5 = REG_READ(ah, AR_ISR_S5_S);
|
||||
else
|
||||
s5 = REG_READ(ah, AR_ISR_S5);
|
||||
|
||||
ah->intr_gen_timer_trigger =
|
||||
MS(s5, AR_ISR_S5_GENTIMER_TRIG);
|
||||
|
||||
ah->intr_gen_timer_thresh =
|
||||
MS(s5, AR_ISR_S5_GENTIMER_THRESH);
|
||||
|
||||
if (ah->intr_gen_timer_trigger)
|
||||
*masked |= ATH9K_INT_GENTIMER;
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
||||
REG_WRITE(ah, AR_ISR_S5, s5);
|
||||
isr &= ~AR_ISR_GENTMR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*masked |= mask2;
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
||||
REG_WRITE(ah, AR_ISR, isr);
|
||||
|
||||
(void) REG_READ(ah, AR_ISR);
|
||||
}
|
||||
}
|
||||
|
||||
if (sync_cause) {
|
||||
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
|
||||
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
|
||||
REG_WRITE(ah, AR_RC, 0);
|
||||
*masked |= ATH9K_INT_FATAL;
|
||||
}
|
||||
|
||||
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
|
||||
DBG("ath9k: "
|
||||
"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
|
||||
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ar9003_hw_fill_txdesc(struct ath_hw *ah __unused, void *ds, u32 seglen,
|
||||
int is_firstseg, int is_lastseg,
|
||||
const void *ds0, u32 buf_addr,
|
||||
unsigned int qcu)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
unsigned int descid = 0;
|
||||
|
||||
ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
|
||||
(1 << AR_TxRxDesc_S) |
|
||||
(1 << AR_CtrlStat_S) |
|
||||
(qcu << AR_TxQcuNum_S) | 0x17;
|
||||
|
||||
ads->data0 = buf_addr;
|
||||
ads->data1 = 0;
|
||||
ads->data2 = 0;
|
||||
ads->data3 = 0;
|
||||
|
||||
ads->ctl3 = (seglen << AR_BufLen_S);
|
||||
ads->ctl3 &= AR_BufLen;
|
||||
|
||||
/* Fill in pointer checksum and descriptor id */
|
||||
ads->ctl10 = ar9003_calc_ptr_chksum(ads);
|
||||
ads->ctl10 |= (descid << AR_TxDescId_S);
|
||||
|
||||
if (is_firstseg) {
|
||||
ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
|
||||
} else if (is_lastseg) {
|
||||
ads->ctl11 = 0;
|
||||
ads->ctl12 = 0;
|
||||
ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
|
||||
ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
|
||||
} else {
|
||||
/* XXX Intermediate descriptor in a multi-descriptor frame.*/
|
||||
ads->ctl11 = 0;
|
||||
ads->ctl12 = AR_TxMore;
|
||||
ads->ctl13 = 0;
|
||||
ads->ctl14 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds __unused,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
struct ar9003_txs *ads;
|
||||
u32 status;
|
||||
|
||||
ads = &ah->ts_ring[ah->ts_tail];
|
||||
|
||||
status = *(volatile typeof(ads->status8) *)&(ads->status8);
|
||||
if ((status & AR_TxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
|
||||
|
||||
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
|
||||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
|
||||
DBG("ath9k: "
|
||||
"Tx Descriptor error %x\n", ads->ds_info);
|
||||
memset(ads, 0, sizeof(*ads));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (status & AR_TxOpExceeded)
|
||||
ts->ts_status |= ATH9K_TXERR_XTXOP;
|
||||
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
|
||||
ts->ts_seqnum = MS(status, AR_SeqNum);
|
||||
ts->tid = MS(status, AR_TxTid);
|
||||
|
||||
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
|
||||
ts->desc_id = MS(ads->status1, AR_TxDescId);
|
||||
ts->ts_tstamp = ads->status4;
|
||||
ts->ts_status = 0;
|
||||
ts->ts_flags = 0;
|
||||
|
||||
status = *(volatile typeof(ads->status2) *)&(ads->status2);
|
||||
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
|
||||
if (status & AR_TxBaStatus) {
|
||||
ts->ts_flags |= ATH9K_TX_BA;
|
||||
ts->ba_low = ads->status5;
|
||||
ts->ba_high = ads->status6;
|
||||
}
|
||||
|
||||
status = *(volatile typeof(ads->status3) *)&(ads->status3);
|
||||
if (status & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (status & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (status & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
if (status & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
if (status & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (status & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
if (status & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
}
|
||||
ts->ts_shortretry = MS(status, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(status, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
|
||||
|
||||
status = *(volatile typeof(ads->status7) *)&(ads->status7);
|
||||
ts->ts_rssi = MS(status, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
||||
|
||||
memset(ads, 0, sizeof(*ads));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||
u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
|
||||
u32 keyIx, enum ath9k_key_type keyType, u32 flags)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
if (txpower > ah->txpower_limit)
|
||||
txpower = ah->txpower_limit;
|
||||
|
||||
if (txpower > 63)
|
||||
txpower = 63;
|
||||
|
||||
ads->ctl11 = (pktlen & AR_FrameLen)
|
||||
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
||||
| SM(txpower, AR_XmitPower)
|
||||
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
||||
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
|
||||
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
|
||||
|
||||
ads->ctl12 =
|
||||
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
|
||||
| SM(type, AR_FrameType)
|
||||
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
|
||||
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
|
||||
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
|
||||
|
||||
ads->ctl17 = SM(keyType, AR_EncrType) |
|
||||
(flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
|
||||
ads->ctl18 = 0;
|
||||
ads->ctl19 = AR_Not_Sounding;
|
||||
|
||||
ads->ctl20 = 0;
|
||||
ads->ctl21 = 0;
|
||||
ads->ctl22 = 0;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_clrdmask(struct ath_hw *ah __unused, void *ds, int val)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
if (val)
|
||||
ads->ctl11 |= AR_ClrDestMask;
|
||||
else
|
||||
ads->ctl11 &= ~AR_ClrDestMask;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah __unused, void *ds,
|
||||
void *lastds,
|
||||
u32 durUpdateEn, u32 rtsctsRate,
|
||||
u32 rtsctsDuration __unused,
|
||||
struct ath9k_11n_rate_series series[],
|
||||
u32 nseries __unused, u32 flags)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
|
||||
uint32_t ctl11;
|
||||
|
||||
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
|
||||
ctl11 = ads->ctl11;
|
||||
|
||||
if (flags & ATH9K_TXDESC_RTSENA) {
|
||||
ctl11 &= ~AR_CTSEnable;
|
||||
ctl11 |= AR_RTSEnable;
|
||||
} else {
|
||||
ctl11 &= ~AR_RTSEnable;
|
||||
ctl11 |= AR_CTSEnable;
|
||||
}
|
||||
|
||||
ads->ctl11 = ctl11;
|
||||
} else {
|
||||
ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
|
||||
}
|
||||
|
||||
ads->ctl13 = set11nTries(series, 0)
|
||||
| set11nTries(series, 1)
|
||||
| set11nTries(series, 2)
|
||||
| set11nTries(series, 3)
|
||||
| (durUpdateEn ? AR_DurUpdateEna : 0)
|
||||
| SM(0, AR_BurstDur);
|
||||
|
||||
ads->ctl14 = set11nRate(series, 0)
|
||||
| set11nRate(series, 1)
|
||||
| set11nRate(series, 2)
|
||||
| set11nRate(series, 3);
|
||||
|
||||
ads->ctl15 = set11nPktDurRTSCTS(series, 0)
|
||||
| set11nPktDurRTSCTS(series, 1);
|
||||
|
||||
ads->ctl16 = set11nPktDurRTSCTS(series, 2)
|
||||
| set11nPktDurRTSCTS(series, 3);
|
||||
|
||||
ads->ctl18 = set11nRateFlags(series, 0)
|
||||
| set11nRateFlags(series, 1)
|
||||
| set11nRateFlags(series, 2)
|
||||
| set11nRateFlags(series, 3)
|
||||
| SM(rtsctsRate, AR_RTSCTSRate);
|
||||
ads->ctl19 = AR_Not_Sounding;
|
||||
|
||||
last_ads->ctl13 = ads->ctl13;
|
||||
last_ads->ctl14 = ads->ctl14;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
|
||||
u32 aggrLen)
|
||||
{
|
||||
#define FIRST_DESC_NDELIMS 60
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
|
||||
|
||||
if (ah->ent_mode & AR_ENT_OTP_MPSD) {
|
||||
u32 ctl17, ndelim;
|
||||
/*
|
||||
* Add delimiter when using RTS/CTS with aggregation
|
||||
* and non enterprise AR9003 card
|
||||
*/
|
||||
ctl17 = ads->ctl17;
|
||||
ndelim = MS(ctl17, AR_PadDelim);
|
||||
|
||||
if (ndelim < FIRST_DESC_NDELIMS) {
|
||||
aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
|
||||
ndelim = FIRST_DESC_NDELIMS;
|
||||
}
|
||||
|
||||
ctl17 &= ~AR_AggrLen;
|
||||
ctl17 |= SM(aggrLen, AR_AggrLen);
|
||||
|
||||
ctl17 &= ~AR_PadDelim;
|
||||
ctl17 |= SM(ndelim, AR_PadDelim);
|
||||
|
||||
ads->ctl17 = ctl17;
|
||||
} else {
|
||||
ads->ctl17 &= ~AR_AggrLen;
|
||||
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah __unused, void *ds,
|
||||
u32 numDelims)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
unsigned int ctl17;
|
||||
|
||||
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
|
||||
|
||||
/*
|
||||
* We use a stack variable to manipulate ctl6 to reduce uncached
|
||||
* read modify, modfiy, write.
|
||||
*/
|
||||
ctl17 = ads->ctl17;
|
||||
ctl17 &= ~AR_PadDelim;
|
||||
ctl17 |= SM(numDelims, AR_PadDelim);
|
||||
ads->ctl17 = ctl17;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah __unused, void *ds)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
ads->ctl12 |= AR_IsAggr;
|
||||
ads->ctl12 &= ~AR_MoreAggr;
|
||||
ads->ctl17 &= ~AR_PadDelim;
|
||||
}
|
||||
|
||||
static void ar9003_hw_clr11n_aggr(struct ath_hw *ah __unused, void *ds)
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
|
||||
}
|
||||
|
||||
void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah __unused, void *ds, u8 chains)
|
||||
{
|
||||
struct ar9003_txc *ads = ds;
|
||||
|
||||
ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
|
||||
}
|
||||
|
||||
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
|
||||
{
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
|
||||
|
||||
ops->rx_enable = ar9003_hw_rx_enable;
|
||||
ops->set_desc_link = ar9003_hw_set_desc_link;
|
||||
ops->get_desc_link = ar9003_hw_get_desc_link;
|
||||
ops->get_isr = ar9003_hw_get_isr;
|
||||
ops->fill_txdesc = ar9003_hw_fill_txdesc;
|
||||
ops->proc_txdesc = ar9003_hw_proc_txdesc;
|
||||
ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
|
||||
ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
|
||||
ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
|
||||
ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
|
||||
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
|
||||
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
|
||||
ops->set_clrdmask = ar9003_hw_set_clrdmask;
|
||||
}
|
||||
|
||||
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
|
||||
{
|
||||
REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK);
|
||||
}
|
||||
|
||||
void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
|
||||
enum ath9k_rx_qtype qtype)
|
||||
{
|
||||
if (qtype == ATH9K_RX_QUEUE_HP)
|
||||
REG_WRITE(ah, AR_HP_RXDP, rxdp);
|
||||
else
|
||||
REG_WRITE(ah, AR_LP_RXDP, rxdp);
|
||||
}
|
||||
|
||||
int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah __unused, struct ath_rx_status *rxs,
|
||||
void *buf_addr)
|
||||
{
|
||||
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
|
||||
unsigned int phyerr;
|
||||
|
||||
/* TODO: byte swap on big endian for ar9300_10 */
|
||||
|
||||
if ((rxsp->status11 & AR_RxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
|
||||
return -EINVAL;
|
||||
|
||||
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
if (!rxs)
|
||||
return 0;
|
||||
|
||||
rxs->rs_status = 0;
|
||||
rxs->rs_flags = 0;
|
||||
|
||||
rxs->rs_datalen = rxsp->status2 & AR_DataLen;
|
||||
rxs->rs_tstamp = rxsp->status3;
|
||||
|
||||
/* XXX: Keycache */
|
||||
rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
|
||||
rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
|
||||
rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
|
||||
rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
|
||||
rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
|
||||
rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
|
||||
rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
|
||||
|
||||
if (rxsp->status11 & AR_RxKeyIdxValid)
|
||||
rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
|
||||
else
|
||||
rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
|
||||
|
||||
rxs->rs_rate = MS(rxsp->status1, AR_RxRate);
|
||||
rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0;
|
||||
|
||||
rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0;
|
||||
rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
|
||||
rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
|
||||
rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0;
|
||||
rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0;
|
||||
|
||||
rxs->evm0 = rxsp->status6;
|
||||
rxs->evm1 = rxsp->status7;
|
||||
rxs->evm2 = rxsp->status8;
|
||||
rxs->evm3 = rxsp->status9;
|
||||
rxs->evm4 = (rxsp->status10 & 0xffff);
|
||||
|
||||
if (rxsp->status11 & AR_PreDelimCRCErr)
|
||||
rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
|
||||
|
||||
if (rxsp->status11 & AR_PostDelimCRCErr)
|
||||
rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
|
||||
|
||||
if (rxsp->status11 & AR_DecryptBusyErr)
|
||||
rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
|
||||
|
||||
if ((rxsp->status11 & AR_RxFrameOK) == 0) {
|
||||
/*
|
||||
* AR_CRCErr will bet set to true if we're on the last
|
||||
* subframe and the AR_PostDelimCRCErr is caught.
|
||||
* In a way this also gives us a guarantee that when
|
||||
* (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
|
||||
* possibly be reviewing the last subframe. AR_CRCErr
|
||||
* is the CRC of the actual data.
|
||||
*/
|
||||
if (rxsp->status11 & AR_CRCErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (rxsp->status11 & AR_PHYErr) {
|
||||
phyerr = MS(rxsp->status11, AR_PHYErrCode);
|
||||
/*
|
||||
* If we reach a point here where AR_PostDelimCRCErr is
|
||||
* true it implies we're *not* on the last subframe. In
|
||||
* in that case that we know already that the CRC of
|
||||
* the frame was OK, and MAC would send an ACK for that
|
||||
* subframe, even if we did get a phy error of type
|
||||
* ATH9K_PHYERR_OFDM_RESTART. This is only applicable
|
||||
* to frame that are prior to the last subframe.
|
||||
* The AR_PostDelimCRCErr is the CRC for the MPDU
|
||||
* delimiter, which contains the 4 reserved bits,
|
||||
* the MPDU length (12 bits), and follows the MPDU
|
||||
* delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
|
||||
*/
|
||||
if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
|
||||
(rxsp->status11 & AR_PostDelimCRCErr)) {
|
||||
rxs->rs_phyerr = 0;
|
||||
} else {
|
||||
rxs->rs_status |= ATH9K_RXERR_PHY;
|
||||
rxs->rs_phyerr = phyerr;
|
||||
}
|
||||
|
||||
} else if (rxsp->status11 & AR_DecryptCRCErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
else if (rxsp->status11 & AR_MichaelErr)
|
||||
rxs->rs_status |= ATH9K_RXERR_MIC;
|
||||
else if (rxsp->status11 & AR_KeyMiss)
|
||||
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
|
||||
{
|
||||
ah->ts_tail = 0;
|
||||
|
||||
memset((void *) ah->ts_ring, 0,
|
||||
ah->ts_size * sizeof(struct ar9003_txs));
|
||||
|
||||
DBG2("ath9k: "
|
||||
"TS Start 0x%x End 0x%x Virt %p, Size %d\n",
|
||||
ah->ts_paddr_start, ah->ts_paddr_end,
|
||||
ah->ts_ring, ah->ts_size);
|
||||
|
||||
REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
|
||||
REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
|
||||
}
|
||||
|
||||
void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
|
||||
u32 ts_paddr_start,
|
||||
u8 size)
|
||||
{
|
||||
|
||||
ah->ts_paddr_start = ts_paddr_start;
|
||||
ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs));
|
||||
ah->ts_size = size;
|
||||
ah->ts_ring = (struct ar9003_txs *) ts_start;
|
||||
|
||||
ath9k_hw_reset_txstatus_ring(ah);
|
||||
}
|
||||
1277
src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c
Normal file
1277
src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
403
src/drivers/net/ath/ath9k/ath9k_calib.c
Normal file
403
src/drivers/net/ath/ath9k/ath9k_calib.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
|
||||
/* Common calibration code */
|
||||
|
||||
#define ATH9K_NF_TOO_HIGH -60
|
||||
|
||||
static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
|
||||
{
|
||||
int16_t nfval;
|
||||
int16_t sort[ATH9K_NF_CAL_HIST_MAX];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
|
||||
sort[i] = nfCalBuffer[i];
|
||||
|
||||
for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
|
||||
for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
|
||||
if (sort[j] > sort[j - 1]) {
|
||||
nfval = sort[j];
|
||||
sort[j] = sort[j - 1];
|
||||
sort[j - 1] = nfval;
|
||||
}
|
||||
}
|
||||
}
|
||||
nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
|
||||
|
||||
return nfval;
|
||||
}
|
||||
|
||||
static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_nf_limits *limit;
|
||||
|
||||
if (!chan || IS_CHAN_2GHZ(chan))
|
||||
limit = &ah->nf_2g;
|
||||
else
|
||||
limit = &ah->nf_5g;
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_get_nf_limits(ah, chan)->nominal;
|
||||
}
|
||||
|
||||
|
||||
static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
|
||||
struct ath9k_hw_cal_data *cal,
|
||||
int16_t *nfarray)
|
||||
{
|
||||
struct ath_nf_limits *limit;
|
||||
struct ath9k_nfcal_hist *h;
|
||||
int high_nf_mid = 0;
|
||||
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
|
||||
int i;
|
||||
|
||||
h = cal->nfCalHist;
|
||||
limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (!(chainmask & (1 << i)) ||
|
||||
(i >= AR5416_MAX_CHAINS))
|
||||
continue;
|
||||
|
||||
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
|
||||
|
||||
if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
|
||||
h[i].currIndex = 0;
|
||||
|
||||
if (h[i].invalidNFcount > 0) {
|
||||
h[i].invalidNFcount--;
|
||||
h[i].privNF = nfarray[i];
|
||||
} else {
|
||||
h[i].privNF =
|
||||
ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
|
||||
}
|
||||
|
||||
if (!h[i].privNF)
|
||||
continue;
|
||||
|
||||
if (h[i].privNF > limit->max) {
|
||||
high_nf_mid = 1;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"NFmid[%d] (%d) > MAX (%d), %s\n",
|
||||
i, h[i].privNF, limit->max,
|
||||
(cal->nfcal_interference ?
|
||||
"not corrected (due to interference)" :
|
||||
"correcting to MAX"));
|
||||
|
||||
/*
|
||||
* Normally we limit the average noise floor by the
|
||||
* hardware specific maximum here. However if we have
|
||||
* encountered stuck beacons because of interference,
|
||||
* we bypass this limit here in order to better deal
|
||||
* with our environment.
|
||||
*/
|
||||
if (!cal->nfcal_interference)
|
||||
h[i].privNF = limit->max;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the noise floor seems normal for all chains, assume that
|
||||
* there is no significant interference in the environment anymore.
|
||||
* Re-enable the enforcement of the NF maximum again.
|
||||
*/
|
||||
if (!high_nf_mid)
|
||||
cal->nfcal_interference = 0;
|
||||
}
|
||||
|
||||
static int ath9k_hw_get_nf_thresh(struct ath_hw *ah,
|
||||
int band,
|
||||
int16_t *nft)
|
||||
{
|
||||
switch (band) {
|
||||
case NET80211_BAND_5GHZ:
|
||||
*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
|
||||
break;
|
||||
case NET80211_BAND_2GHZ:
|
||||
*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ath9k_hw_reset_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
int i;
|
||||
|
||||
ath9k_hw_setup_calibration(ah, currCal);
|
||||
|
||||
currCal->calState = CAL_RUNNING;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ah->meas0.sign[i] = 0;
|
||||
ah->meas1.sign[i] = 0;
|
||||
ah->meas2.sign[i] = 0;
|
||||
ah->meas3.sign[i] = 0;
|
||||
}
|
||||
|
||||
ah->cal_samples = 0;
|
||||
}
|
||||
|
||||
/* This is done for the currently configured channel */
|
||||
int ath9k_hw_reset_calvalid(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
|
||||
if (!ah->caldata)
|
||||
return 1;
|
||||
|
||||
if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
|
||||
return 1;
|
||||
|
||||
if (currCal == NULL)
|
||||
return 1;
|
||||
|
||||
if (currCal->calState != CAL_DONE) {
|
||||
DBG("ath9k: "
|
||||
"Calibration state incorrect, %d\n",
|
||||
currCal->calState);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(ah->supp_cals & currCal->calData->calType))
|
||||
return 1;
|
||||
|
||||
DBG("ath9k: "
|
||||
"Resetting Cal %d state for channel %d\n",
|
||||
currCal->calData->calType, (ah->dev->channels + ah->dev->channel)->center_freq);
|
||||
|
||||
ah->caldata->CalValid &= ~currCal->calData->calType;
|
||||
currCal->calState = CAL_WAITING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
|
||||
{
|
||||
if (ah->caldata)
|
||||
ah->caldata->nfcal_pending = 1;
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_ENABLE_NF);
|
||||
|
||||
if (update)
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
else
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
}
|
||||
|
||||
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_nfcal_hist *h = NULL;
|
||||
unsigned i, j;
|
||||
int32_t val;
|
||||
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
|
||||
s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
|
||||
if (ah->caldata)
|
||||
h = ah->caldata->nfCalHist;
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
s16 nfval;
|
||||
|
||||
if (i >= AR5416_MAX_CHAINS)
|
||||
continue;
|
||||
|
||||
if (h)
|
||||
nfval = h[i].privNF;
|
||||
else
|
||||
nfval = default_nf;
|
||||
|
||||
val = REG_READ(ah, ah->nf_regs[i]);
|
||||
val &= 0xFFFFFE00;
|
||||
val |= (((u32) nfval << 1) & 0x1ff);
|
||||
REG_WRITE(ah, ah->nf_regs[i], val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Load software filtered NF value into baseband internal minCCApwr
|
||||
* variable.
|
||||
*/
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_ENABLE_NF);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
|
||||
/*
|
||||
* Wait for load to complete, should be fast, a few 10s of us.
|
||||
* The max delay was changed from an original 250us to 10000us
|
||||
* since 250us often results in NF load timeout and causes deaf
|
||||
* condition during stress testing 12/12/2009
|
||||
*/
|
||||
for (j = 0; j < 10000; j++) {
|
||||
if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_NF) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* We timed out waiting for the noisefloor to load, probably due to an
|
||||
* in-progress rx. Simply return here and allow the load plenty of time
|
||||
* to complete before the next calibration interval. We need to avoid
|
||||
* trying to load -50 (which happens below) while the previous load is
|
||||
* still in progress as this can cause rx deafness. Instead by returning
|
||||
* here, the baseband nf cal will just be capped by our present
|
||||
* noisefloor until the next calibration timer.
|
||||
*/
|
||||
if (j == 10000) {
|
||||
DBG("ath9k: "
|
||||
"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore maxCCAPower register parameter again so that we're not capped
|
||||
* by the median we just loaded. This will be initial (and max) value
|
||||
* of next noise floor calibration the baseband does.
|
||||
*/
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
if (i >= AR5416_MAX_CHAINS)
|
||||
continue;
|
||||
|
||||
val = REG_READ(ah, ah->nf_regs[i]);
|
||||
val &= 0xFFFFFE00;
|
||||
val |= (((u32) (-50) << 1) & 0x1ff);
|
||||
REG_WRITE(ah, ah->nf_regs[i], val);
|
||||
}
|
||||
}
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
|
||||
static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
|
||||
{
|
||||
struct ath_nf_limits *limit;
|
||||
int i;
|
||||
|
||||
if (IS_CHAN_2GHZ(ah->curchan))
|
||||
limit = &ah->nf_2g;
|
||||
else
|
||||
limit = &ah->nf_5g;
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (!nf[i])
|
||||
continue;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"NF calibrated [%s] [chain %d] is %d\n",
|
||||
(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
|
||||
|
||||
if (nf[i] > ATH9K_NF_TOO_HIGH) {
|
||||
DBG("ath9k: "
|
||||
"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
|
||||
i, nf[i], ATH9K_NF_TOO_HIGH);
|
||||
nf[i] = limit->max;
|
||||
} else if (nf[i] < limit->min) {
|
||||
DBG("ath9k: "
|
||||
"NF[%d] (%d) < MIN (%d), correcting to NOM\n",
|
||||
i, nf[i], limit->min);
|
||||
nf[i] = limit->nominal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
int16_t nf, nfThresh;
|
||||
int16_t nfarray[NUM_NF_READINGS] = { 0 };
|
||||
struct ath9k_nfcal_hist *h;
|
||||
struct net80211_channel *c = chan->chan;
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
|
||||
chan->channelFlags &= (~CHANNEL_CW_INT);
|
||||
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
|
||||
DBG("ath9k: "
|
||||
"NF did not complete in calibration window\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath9k_hw_do_getnf(ah, nfarray);
|
||||
ath9k_hw_nf_sanitize(ah, nfarray);
|
||||
nf = nfarray[0];
|
||||
if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
|
||||
&& nf > nfThresh) {
|
||||
DBG2("ath9k: "
|
||||
"noise floor failed detected; detected %d, threshold %d\n",
|
||||
nf, nfThresh);
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
}
|
||||
|
||||
if (!caldata) {
|
||||
chan->noisefloor = nf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
h = caldata->nfCalHist;
|
||||
caldata->nfcal_pending = 0;
|
||||
ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
|
||||
chan->noisefloor = h[0].privNF;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_nfcal_hist *h;
|
||||
s16 default_nf;
|
||||
int i, j;
|
||||
|
||||
ah->caldata->channel = chan->channel;
|
||||
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
|
||||
h = ah->caldata->nfCalHist;
|
||||
default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
h[i].currIndex = 0;
|
||||
h[i].privNF = default_nf;
|
||||
h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
|
||||
for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
|
||||
h[i].nfCalBuffer[j] = default_nf;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/drivers/net/ath/ath9k/ath9k_common.c
Normal file
69
src/drivers/net/ath/ath9k/ath9k_common.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module for common driver code between ath9k and ath9k_htc
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Update internal channel flags.
|
||||
*/
|
||||
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
|
||||
struct net80211_channel *chan)
|
||||
{
|
||||
ichan->channel = chan->center_freq;
|
||||
ichan->chan = chan;
|
||||
|
||||
if (chan->band == NET80211_BAND_2GHZ) {
|
||||
ichan->chanmode = CHANNEL_G;
|
||||
ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
|
||||
} else {
|
||||
ichan->chanmode = CHANNEL_A;
|
||||
ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the internal channel reference.
|
||||
*/
|
||||
struct ath9k_channel *ath9k_cmn_get_curchannel(struct net80211_device *dev,
|
||||
struct ath_hw *ah)
|
||||
{
|
||||
struct net80211_channel *curchan = dev->channels + dev->channel;
|
||||
struct ath9k_channel *channel;
|
||||
u8 chan_idx;
|
||||
|
||||
chan_idx = curchan->hw_value;
|
||||
channel = &ah->channels[chan_idx];
|
||||
ath9k_cmn_update_ichannel(channel, curchan);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
|
||||
u16 new_txpow, u16 *txpower)
|
||||
{
|
||||
if (cur_txpow != new_txpow) {
|
||||
ath9k_hw_set_txpowerlimit(ah, new_txpow, 0);
|
||||
/* read back in case value is clamped */
|
||||
*txpower = ath9k_hw_regulatory(ah)->power_limit;
|
||||
}
|
||||
}
|
||||
551
src/drivers/net/ath/ath9k/ath9k_eeprom.c
Normal file
551
src/drivers/net/ath/ath9k/ath9k_eeprom.c
Normal file
@@ -0,0 +1,551 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
static inline u16 ath9k_hw_fbin2freq(u8 fbin, int is2GHz)
|
||||
{
|
||||
if (fbin == AR5416_BCHAN_UNUSED)
|
||||
return fbin;
|
||||
|
||||
return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
|
||||
}
|
||||
|
||||
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
|
||||
{
|
||||
REG_WRITE(ah, reg, val);
|
||||
|
||||
if (ah->config.analog_shiftreg)
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
|
||||
u32 shift, u32 val)
|
||||
{
|
||||
u32 regVal;
|
||||
|
||||
regVal = REG_READ(ah, reg) & ~mask;
|
||||
regVal |= (val << shift) & mask;
|
||||
|
||||
REG_WRITE(ah, reg, regVal);
|
||||
|
||||
if (ah->config.analog_shiftreg)
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
|
||||
int16_t targetLeft, int16_t targetRight)
|
||||
{
|
||||
int16_t rv;
|
||||
|
||||
if (srcRight == srcLeft) {
|
||||
rv = targetLeft;
|
||||
} else {
|
||||
rv = (int16_t) (((target - srcLeft) * targetRight +
|
||||
(srcRight - target) * targetLeft) /
|
||||
(srcRight - srcLeft));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
||||
u16 *indexL, u16 *indexR)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
if (target <= pList[0]) {
|
||||
*indexL = *indexR = 0;
|
||||
return 1;
|
||||
}
|
||||
if (target >= pList[listSize - 1]) {
|
||||
*indexL = *indexR = (u16) (listSize - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < listSize - 1; i++) {
|
||||
if (pList[i] == target) {
|
||||
*indexL = *indexR = i;
|
||||
return 1;
|
||||
}
|
||||
if (target < pList[i + 1]) {
|
||||
*indexL = i;
|
||||
*indexR = (u16) (i + 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
|
||||
int eep_start_loc, int size)
|
||||
{
|
||||
int i = 0, j, addr;
|
||||
u32 addrdata[8];
|
||||
u32 data[8];
|
||||
|
||||
for (addr = 0; addr < size; addr++) {
|
||||
addrdata[i] = AR5416_EEPROM_OFFSET +
|
||||
((addr + eep_start_loc) << AR5416_EEPROM_S);
|
||||
i++;
|
||||
if (i == 8) {
|
||||
REG_READ_MULTI(ah, addrdata, data, i);
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
*eep_data = data[j];
|
||||
eep_data++;
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
REG_READ_MULTI(ah, addrdata, data, i);
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
*eep_data = data[j];
|
||||
eep_data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
return common->bus_ops->eeprom_read(common, off, data);
|
||||
}
|
||||
|
||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||
u8 *pVpdList, u16 numIntercepts,
|
||||
u8 *pRetVpdList)
|
||||
{
|
||||
u16 i, k;
|
||||
u8 currPwr = pwrMin;
|
||||
u16 idxL = 0, idxR = 0;
|
||||
|
||||
for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
|
||||
ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
|
||||
numIntercepts, &(idxL),
|
||||
&(idxR));
|
||||
if (idxR < 1)
|
||||
idxR = 1;
|
||||
if (idxL == numIntercepts - 1)
|
||||
idxL = (u16) (numIntercepts - 2);
|
||||
if (pPwrList[idxL] == pPwrList[idxR])
|
||||
k = pVpdList[idxL];
|
||||
else
|
||||
k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
|
||||
(pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
|
||||
(pPwrList[idxR] - pPwrList[idxL]));
|
||||
pRetVpdList[i] = (u8) k;
|
||||
currPwr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_leg *powInfo,
|
||||
u16 numChannels,
|
||||
struct cal_target_power_leg *pNewPower,
|
||||
u16 numRates, int isExtTarget)
|
||||
{
|
||||
struct chan_centers centers;
|
||||
u16 clo, chi;
|
||||
int i;
|
||||
int matchIndex = -1, lowIndex = -1;
|
||||
u16 freq;
|
||||
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
|
||||
|
||||
if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
matchIndex = 0;
|
||||
} else {
|
||||
for (i = 0; (i < numChannels) &&
|
||||
(powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
|
||||
if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
matchIndex = i;
|
||||
break;
|
||||
} else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan)) && i > 0 &&
|
||||
freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
lowIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((matchIndex == -1) && (lowIndex == -1))
|
||||
matchIndex = i - 1;
|
||||
}
|
||||
|
||||
if (matchIndex != -1) {
|
||||
*pNewPower = powInfo[matchIndex];
|
||||
} else {
|
||||
clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
|
||||
for (i = 0; i < numRates; i++) {
|
||||
pNewPower->tPow2x[i] =
|
||||
(u8)ath9k_hw_interpolate(freq, clo, chi,
|
||||
powInfo[lowIndex].tPow2x[i],
|
||||
powInfo[lowIndex + 1].tPow2x[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_get_target_powers(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_ht *powInfo,
|
||||
u16 numChannels,
|
||||
struct cal_target_power_ht *pNewPower,
|
||||
u16 numRates, int isHt40Target)
|
||||
{
|
||||
struct chan_centers centers;
|
||||
u16 clo, chi;
|
||||
int i;
|
||||
int matchIndex = -1, lowIndex = -1;
|
||||
u16 freq;
|
||||
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
freq = isHt40Target ? centers.synth_center : centers.ctl_center;
|
||||
|
||||
if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
|
||||
matchIndex = 0;
|
||||
} else {
|
||||
for (i = 0; (i < numChannels) &&
|
||||
(powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
|
||||
if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
matchIndex = i;
|
||||
break;
|
||||
} else
|
||||
if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan)) && i > 0 &&
|
||||
freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
lowIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((matchIndex == -1) && (lowIndex == -1))
|
||||
matchIndex = i - 1;
|
||||
}
|
||||
|
||||
if (matchIndex != -1) {
|
||||
*pNewPower = powInfo[matchIndex];
|
||||
} else {
|
||||
clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
|
||||
for (i = 0; i < numRates; i++) {
|
||||
pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
|
||||
clo, chi,
|
||||
powInfo[lowIndex].tPow2x[i],
|
||||
powInfo[lowIndex + 1].tPow2x[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
|
||||
int is2GHz, int num_band_edges)
|
||||
{
|
||||
u16 twiceMaxEdgePower = MAX_RATE_POWER;
|
||||
int i;
|
||||
|
||||
for (i = 0; (i < num_band_edges) &&
|
||||
(pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
|
||||
if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
|
||||
twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
|
||||
break;
|
||||
} else if ((i > 0) &&
|
||||
(freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
|
||||
is2GHz))) {
|
||||
if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
|
||||
is2GHz) < freq &&
|
||||
CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
|
||||
twiceMaxEdgePower =
|
||||
CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return twiceMaxEdgePower;
|
||||
}
|
||||
|
||||
void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
|
||||
switch (ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
DBG2("ath9k: "
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
void *pRawDataSet,
|
||||
u8 *bChans, u16 availPiers,
|
||||
u16 tPdGainOverlap,
|
||||
u16 *pPdGainBoundaries, u8 *pPDADCValues,
|
||||
u16 numXpdGains)
|
||||
{
|
||||
int i, j, k;
|
||||
int16_t ss;
|
||||
u16 idxL = 0, idxR = 0, numPiers;
|
||||
static u8 vpdTableL[AR5416_NUM_PD_GAINS]
|
||||
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
|
||||
static u8 vpdTableR[AR5416_NUM_PD_GAINS]
|
||||
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
|
||||
static u8 vpdTableI[AR5416_NUM_PD_GAINS]
|
||||
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
|
||||
|
||||
u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
|
||||
u8 minPwrT4[AR5416_NUM_PD_GAINS];
|
||||
u8 maxPwrT4[AR5416_NUM_PD_GAINS];
|
||||
int16_t vpdStep;
|
||||
int16_t tmpVal;
|
||||
u16 sizeCurrVpdTable, maxIndex, tgtIndex;
|
||||
int match;
|
||||
int16_t minDelta = 0;
|
||||
struct chan_centers centers;
|
||||
int pdgain_boundary_default;
|
||||
struct cal_data_per_freq *data_def = pRawDataSet;
|
||||
struct cal_data_per_freq_4k *data_4k = pRawDataSet;
|
||||
struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
|
||||
int eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
|
||||
int intercepts;
|
||||
|
||||
if (AR_SREV_9287(ah))
|
||||
intercepts = AR9287_PD_GAIN_ICEPTS;
|
||||
else
|
||||
intercepts = AR5416_PD_GAIN_ICEPTS;
|
||||
|
||||
memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
|
||||
for (numPiers = 0; numPiers < availPiers; numPiers++) {
|
||||
if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
|
||||
break;
|
||||
}
|
||||
|
||||
match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
|
||||
IS_CHAN_2GHZ(chan)),
|
||||
bChans, numPiers, &idxL, &idxR);
|
||||
|
||||
if (match) {
|
||||
if (AR_SREV_9287(ah)) {
|
||||
/* FIXME: array overrun? */
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
|
||||
maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
|
||||
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
|
||||
data_9287[idxL].pwrPdg[i],
|
||||
data_9287[idxL].vpdPdg[i],
|
||||
intercepts,
|
||||
vpdTableI[i]);
|
||||
}
|
||||
} else if (eeprom_4k) {
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
|
||||
maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
|
||||
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
|
||||
data_4k[idxL].pwrPdg[i],
|
||||
data_4k[idxL].vpdPdg[i],
|
||||
intercepts,
|
||||
vpdTableI[i]);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
|
||||
maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
|
||||
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
|
||||
data_def[idxL].pwrPdg[i],
|
||||
data_def[idxL].vpdPdg[i],
|
||||
intercepts,
|
||||
vpdTableI[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
if (AR_SREV_9287(ah)) {
|
||||
pVpdL = data_9287[idxL].vpdPdg[i];
|
||||
pPwrL = data_9287[idxL].pwrPdg[i];
|
||||
pVpdR = data_9287[idxR].vpdPdg[i];
|
||||
pPwrR = data_9287[idxR].pwrPdg[i];
|
||||
} else if (eeprom_4k) {
|
||||
pVpdL = data_4k[idxL].vpdPdg[i];
|
||||
pPwrL = data_4k[idxL].pwrPdg[i];
|
||||
pVpdR = data_4k[idxR].vpdPdg[i];
|
||||
pPwrR = data_4k[idxR].pwrPdg[i];
|
||||
} else {
|
||||
pVpdL = data_def[idxL].vpdPdg[i];
|
||||
pPwrL = data_def[idxL].pwrPdg[i];
|
||||
pVpdR = data_def[idxR].vpdPdg[i];
|
||||
pPwrR = data_def[idxR].pwrPdg[i];
|
||||
}
|
||||
|
||||
minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
|
||||
|
||||
maxPwrT4[i] =
|
||||
min(pPwrL[intercepts - 1],
|
||||
pPwrR[intercepts - 1]);
|
||||
|
||||
|
||||
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
|
||||
pPwrL, pVpdL,
|
||||
intercepts,
|
||||
vpdTableL[i]);
|
||||
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
|
||||
pPwrR, pVpdR,
|
||||
intercepts,
|
||||
vpdTableR[i]);
|
||||
|
||||
for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
|
||||
vpdTableI[i][j] =
|
||||
(u8)(ath9k_hw_interpolate((u16)
|
||||
FREQ2FBIN(centers.
|
||||
synth_center,
|
||||
IS_CHAN_2GHZ
|
||||
(chan)),
|
||||
bChans[idxL], bChans[idxR],
|
||||
vpdTableL[i][j], vpdTableR[i][j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
if (i == (numXpdGains - 1))
|
||||
pPdGainBoundaries[i] =
|
||||
(u16)(maxPwrT4[i] / 2);
|
||||
else
|
||||
pPdGainBoundaries[i] =
|
||||
(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
|
||||
|
||||
pPdGainBoundaries[i] =
|
||||
min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
|
||||
|
||||
if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
|
||||
minDelta = pPdGainBoundaries[0] - 23;
|
||||
pPdGainBoundaries[0] = 23;
|
||||
} else {
|
||||
minDelta = 0;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ss = (int16_t)(0 - (minPwrT4[i] / 2));
|
||||
else
|
||||
ss = 0;
|
||||
} else {
|
||||
ss = (int16_t)((pPdGainBoundaries[i - 1] -
|
||||
(minPwrT4[i] / 2)) -
|
||||
tPdGainOverlap + 1 + minDelta);
|
||||
}
|
||||
vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
|
||||
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
|
||||
|
||||
while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
|
||||
tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
|
||||
pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
|
||||
ss++;
|
||||
}
|
||||
|
||||
sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
|
||||
tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
|
||||
(minPwrT4[i] / 2));
|
||||
maxIndex = (tgtIndex < sizeCurrVpdTable) ?
|
||||
tgtIndex : sizeCurrVpdTable;
|
||||
|
||||
while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
|
||||
pPDADCValues[k++] = vpdTableI[i][ss++];
|
||||
}
|
||||
|
||||
vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
|
||||
vpdTableI[i][sizeCurrVpdTable - 2]);
|
||||
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
|
||||
|
||||
if (tgtIndex >= maxIndex) {
|
||||
while ((ss <= tgtIndex) &&
|
||||
(k < (AR5416_NUM_PDADC_VALUES - 1))) {
|
||||
tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
|
||||
(ss - maxIndex + 1) * vpdStep));
|
||||
pPDADCValues[k++] = (u8)((tmpVal > 255) ?
|
||||
255 : tmpVal);
|
||||
ss++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eeprom_4k)
|
||||
pdgain_boundary_default = 58;
|
||||
else
|
||||
pdgain_boundary_default = pPdGainBoundaries[i - 1];
|
||||
|
||||
while (i < AR5416_PD_GAINS_IN_MASK) {
|
||||
pPdGainBoundaries[i] = pdgain_boundary_default;
|
||||
i++;
|
||||
}
|
||||
|
||||
while (k < AR5416_NUM_PDADC_VALUES) {
|
||||
pPDADCValues[k] = pPDADCValues[k - 1];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ah->eep_ops = &eep_ar9300_ops;
|
||||
else if (AR_SREV_9287(ah)) {
|
||||
ah->eep_ops = &eep_ar9287_ops;
|
||||
} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
|
||||
ah->eep_ops = &eep_4k_ops;
|
||||
} else {
|
||||
ah->eep_ops = &eep_def_ops;
|
||||
}
|
||||
|
||||
if (!ah->eep_ops->fill_eeprom(ah))
|
||||
return -EIO;
|
||||
|
||||
status = ah->eep_ops->check_eeprom(ah);
|
||||
|
||||
return status;
|
||||
}
|
||||
1078
src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c
Normal file
1078
src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c
Normal file
File diff suppressed because it is too large
Load Diff
1019
src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c
Normal file
1019
src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c
Normal file
File diff suppressed because it is too large
Load Diff
1351
src/drivers/net/ath/ath9k/ath9k_eeprom_def.c
Normal file
1351
src/drivers/net/ath/ath9k/ath9k_eeprom_def.c
Normal file
File diff suppressed because it is too large
Load Diff
2067
src/drivers/net/ath/ath9k/ath9k_hw.c
Normal file
2067
src/drivers/net/ath/ath9k/ath9k_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
593
src/drivers/net/ath/ath9k/ath9k_init.c
Normal file
593
src/drivers/net/ath/ath9k/ath9k_init.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/malloc.h>
|
||||
#include <ipxe/pci_io.h>
|
||||
#include <ipxe/pci.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
int is_ath9k_unloaded;
|
||||
/* We use the hw_value as an index into our private channel structure */
|
||||
|
||||
#define CHAN2G(_freq, _idx) { \
|
||||
.band = NET80211_BAND_2GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
.maxpower = 20, \
|
||||
}
|
||||
|
||||
#define CHAN5G(_freq, _idx) { \
|
||||
.band = NET80211_BAND_5GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
.maxpower = 20, \
|
||||
}
|
||||
|
||||
/* Some 2 GHz radios are actually tunable on 2312-2732
|
||||
* on 5 MHz steps, we support the channels which we know
|
||||
* we have calibration data for all cards though to make
|
||||
* this static */
|
||||
static const struct net80211_channel ath9k_2ghz_chantable[] = {
|
||||
CHAN2G(2412, 0), /* Channel 1 */
|
||||
CHAN2G(2417, 1), /* Channel 2 */
|
||||
CHAN2G(2422, 2), /* Channel 3 */
|
||||
CHAN2G(2427, 3), /* Channel 4 */
|
||||
CHAN2G(2432, 4), /* Channel 5 */
|
||||
CHAN2G(2437, 5), /* Channel 6 */
|
||||
CHAN2G(2442, 6), /* Channel 7 */
|
||||
CHAN2G(2447, 7), /* Channel 8 */
|
||||
CHAN2G(2452, 8), /* Channel 9 */
|
||||
CHAN2G(2457, 9), /* Channel 10 */
|
||||
CHAN2G(2462, 10), /* Channel 11 */
|
||||
CHAN2G(2467, 11), /* Channel 12 */
|
||||
CHAN2G(2472, 12), /* Channel 13 */
|
||||
CHAN2G(2484, 13), /* Channel 14 */
|
||||
};
|
||||
|
||||
/* Some 5 GHz radios are actually tunable on XXXX-YYYY
|
||||
* on 5 MHz steps, we support the channels which we know
|
||||
* we have calibration data for all cards though to make
|
||||
* this static */
|
||||
static const struct net80211_channel ath9k_5ghz_chantable[] = {
|
||||
/* _We_ call this UNII 1 */
|
||||
CHAN5G(5180, 14), /* Channel 36 */
|
||||
CHAN5G(5200, 15), /* Channel 40 */
|
||||
CHAN5G(5220, 16), /* Channel 44 */
|
||||
CHAN5G(5240, 17), /* Channel 48 */
|
||||
/* _We_ call this UNII 2 */
|
||||
CHAN5G(5260, 18), /* Channel 52 */
|
||||
CHAN5G(5280, 19), /* Channel 56 */
|
||||
CHAN5G(5300, 20), /* Channel 60 */
|
||||
CHAN5G(5320, 21), /* Channel 64 */
|
||||
/* _We_ call this "Middle band" */
|
||||
CHAN5G(5500, 22), /* Channel 100 */
|
||||
CHAN5G(5520, 23), /* Channel 104 */
|
||||
CHAN5G(5540, 24), /* Channel 108 */
|
||||
CHAN5G(5560, 25), /* Channel 112 */
|
||||
CHAN5G(5580, 26), /* Channel 116 */
|
||||
CHAN5G(5600, 27), /* Channel 120 */
|
||||
CHAN5G(5620, 28), /* Channel 124 */
|
||||
CHAN5G(5640, 29), /* Channel 128 */
|
||||
CHAN5G(5660, 30), /* Channel 132 */
|
||||
CHAN5G(5680, 31), /* Channel 136 */
|
||||
CHAN5G(5700, 32), /* Channel 140 */
|
||||
/* _We_ call this UNII 3 */
|
||||
CHAN5G(5745, 33), /* Channel 149 */
|
||||
CHAN5G(5765, 34), /* Channel 153 */
|
||||
CHAN5G(5785, 35), /* Channel 157 */
|
||||
CHAN5G(5805, 36), /* Channel 161 */
|
||||
CHAN5G(5825, 37), /* Channel 165 */
|
||||
};
|
||||
|
||||
/* Atheros hardware rate code addition for short premble */
|
||||
#define SHPCHECK(__hw_rate, __flags) \
|
||||
((__flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
|
||||
|
||||
#define RATE(_bitrate, _hw_rate, _flags) { \
|
||||
.bitrate = (_bitrate), \
|
||||
.flags = (_flags), \
|
||||
.hw_value = (_hw_rate), \
|
||||
.hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
|
||||
}
|
||||
|
||||
static struct ath9k_legacy_rate ath9k_legacy_rates[] = {
|
||||
RATE(10, 0x1b, 0),
|
||||
RATE(20, 0x1a, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
|
||||
RATE(55, 0x19, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
|
||||
RATE(110, 0x18, IEEE80211_TX_RC_USE_SHORT_PREAMBLE),
|
||||
RATE(60, 0x0b, 0),
|
||||
RATE(90, 0x0f, 0),
|
||||
RATE(120, 0x0a, 0),
|
||||
RATE(180, 0x0e, 0),
|
||||
RATE(240, 0x09, 0),
|
||||
RATE(360, 0x0d, 0),
|
||||
RATE(480, 0x08, 0),
|
||||
RATE(540, 0x0c, 0),
|
||||
};
|
||||
|
||||
static void ath9k_deinit_softc(struct ath_softc *sc);
|
||||
|
||||
/*
|
||||
* Read and write, they both share the same lock. We do this to serialize
|
||||
* reads and writes on Atheros 802.11n PCI devices only. This is required
|
||||
* as the FIFO on these devices can only accept sanely 2 requests.
|
||||
*/
|
||||
|
||||
static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) hw_priv;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
|
||||
writel(val, sc->mem + reg_offset);
|
||||
}
|
||||
|
||||
static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) hw_priv;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
u32 val;
|
||||
|
||||
val = readl(sc->mem + reg_offset);
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) hw_priv;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
u32 val;
|
||||
|
||||
val = readl(sc->mem + reg_offset);
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
writel(val, sc->mem + reg_offset);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Initialization */
|
||||
/**************************/
|
||||
|
||||
/*
|
||||
* This function will allocate both the DMA descriptor structure, and the
|
||||
* buffers it contains. These are used to contain the descriptors used
|
||||
* by the system.
|
||||
*/
|
||||
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head, const char *name,
|
||||
int nbuf, int ndesc, int is_tx)
|
||||
{
|
||||
#define DS2PHYS(_dd, _ds) \
|
||||
((_dd)->dd_desc_paddr + ((char *)(_ds) - (char *)(_dd)->dd_desc))
|
||||
#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF9F) ? 1 : 0)
|
||||
u8 *ds;
|
||||
struct ath_buf *bf;
|
||||
int i, bsize, error, desc_len;
|
||||
|
||||
DBG2("ath9k: %s DMA: %d buffers %d desc/buf\n",
|
||||
name, nbuf, ndesc);
|
||||
|
||||
INIT_LIST_HEAD(head);
|
||||
|
||||
if (is_tx)
|
||||
desc_len = sc->sc_ah->caps.tx_desc_len;
|
||||
else
|
||||
desc_len = sizeof(struct ath_desc);
|
||||
|
||||
/* ath_desc must be a multiple of DWORDs */
|
||||
if ((desc_len % 4) != 0) {
|
||||
DBG("ath9k: ath_desc not DWORD aligned\n");
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dd->dd_desc_len = desc_len * nbuf * ndesc;
|
||||
|
||||
/*
|
||||
* Need additional DMA memory because we can't use
|
||||
* descriptors that cross the 4K page boundary.
|
||||
* However, iPXE only utilizes 16 buffers, which
|
||||
* will never make up more than half of one page,
|
||||
* so we will only ever skip 1 descriptor, if that.
|
||||
*/
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
|
||||
u32 ndesc_skipped = 1;
|
||||
u32 dma_len;
|
||||
|
||||
dma_len = ndesc_skipped * desc_len;
|
||||
dd->dd_desc_len += dma_len;
|
||||
}
|
||||
|
||||
/* allocate descriptors */
|
||||
dd->dd_desc = malloc_dma(dd->dd_desc_len, 16);
|
||||
if (dd->dd_desc == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
dd->dd_desc_paddr = virt_to_bus(dd->dd_desc);
|
||||
ds = (u8 *) dd->dd_desc;
|
||||
DBG2("ath9k: %s DMA map: %p (%d) -> %llx (%d)\n",
|
||||
name, ds, (u32) dd->dd_desc_len,
|
||||
ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
|
||||
|
||||
/* allocate buffers */
|
||||
bsize = sizeof(struct ath_buf) * nbuf;
|
||||
bf = zalloc(bsize);
|
||||
if (bf == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto fail2;
|
||||
}
|
||||
dd->dd_bufptr = bf;
|
||||
|
||||
for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
|
||||
bf->bf_desc = ds;
|
||||
bf->bf_daddr = DS2PHYS(dd, ds);
|
||||
|
||||
if (!(sc->sc_ah->caps.hw_caps &
|
||||
ATH9K_HW_CAP_4KB_SPLITTRANS)) {
|
||||
/*
|
||||
* Skip descriptor addresses which can cause 4KB
|
||||
* boundary crossing (addr + length) with a 32 dword
|
||||
* descriptor fetch.
|
||||
*/
|
||||
while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
|
||||
ds += (desc_len * ndesc);
|
||||
bf->bf_desc = ds;
|
||||
bf->bf_daddr = DS2PHYS(dd, ds);
|
||||
}
|
||||
}
|
||||
list_add_tail(&bf->list, head);
|
||||
}
|
||||
return 0;
|
||||
fail2:
|
||||
free_dma(dd->dd_desc, dd->dd_desc_len);
|
||||
fail:
|
||||
memset(dd, 0, sizeof(*dd));
|
||||
return error;
|
||||
#undef ATH_DESC_4KB_BOUND_CHECK
|
||||
#undef DS2PHYS
|
||||
}
|
||||
|
||||
void ath9k_init_crypto(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
unsigned int i = 0;
|
||||
|
||||
/* Get the hardware key cache size. */
|
||||
common->keymax = AR_KEYTABLE_SIZE;
|
||||
|
||||
/*
|
||||
* Reset the key cache since some parts do not
|
||||
* reset the contents on initial power up.
|
||||
*/
|
||||
for (i = 0; i < common->keymax; i++)
|
||||
ath_hw_keyreset(common, (u16) i);
|
||||
|
||||
/*
|
||||
* Check whether the separate key cache entries
|
||||
* are required to handle both tx+rx MIC keys.
|
||||
* With split mic keys the number of stations is limited
|
||||
* to 27 otherwise 59.
|
||||
*/
|
||||
if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
|
||||
common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
|
||||
}
|
||||
|
||||
static int ath9k_init_queues(struct ath_softc *sc)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < WME_NUM_AC; i++) {
|
||||
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
|
||||
sc->tx.txq_map[i]->mac80211_qnum = i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_init_channels_rates(struct ath_softc *sc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
memcpy(&sc->rates, ath9k_legacy_rates, sizeof(ath9k_legacy_rates));
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
|
||||
memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable));
|
||||
|
||||
sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_2ghz_chantable);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
|
||||
sc->hwinfo->rates[NET80211_BAND_2GHZ][i] = ath9k_legacy_rates[i].bitrate;
|
||||
sc->hwinfo->nr_rates[NET80211_BAND_2GHZ] = ARRAY_SIZE(ath9k_legacy_rates);
|
||||
}
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
|
||||
memcpy(&sc->hwinfo->channels[sc->hwinfo->nr_channels], ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable));
|
||||
|
||||
sc->hwinfo->nr_channels += ARRAY_SIZE(ath9k_5ghz_chantable);
|
||||
|
||||
for (i = 4; i < ARRAY_SIZE(ath9k_legacy_rates); i++)
|
||||
sc->hwinfo->rates[NET80211_BAND_5GHZ][i - 4] = ath9k_legacy_rates[i].bitrate;
|
||||
sc->hwinfo->nr_rates[NET80211_BAND_5GHZ] = ARRAY_SIZE(ath9k_legacy_rates) - 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_init_misc(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
common->ani.timer = 0;
|
||||
|
||||
sc->config.txpowlimit = ATH_TXPOWER_MAX;
|
||||
|
||||
common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
|
||||
common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
|
||||
|
||||
ath9k_hw_set_diversity(sc->sc_ah, 1);
|
||||
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
|
||||
|
||||
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
|
||||
}
|
||||
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
struct ath_hw *ah = NULL;
|
||||
struct ath_common *common;
|
||||
int ret = 0, i;
|
||||
int csz = 0;
|
||||
|
||||
ah = zalloc(sizeof(struct ath_hw));
|
||||
if (!ah)
|
||||
return -ENOMEM;
|
||||
|
||||
ah->dev = sc->dev;
|
||||
ah->hw_version.devid = devid;
|
||||
ah->hw_version.subsysid = subsysid;
|
||||
ah->reg_ops.read = ath9k_ioread32;
|
||||
ah->reg_ops.write = ath9k_iowrite32;
|
||||
ah->reg_ops.rmw = ath9k_reg_rmw;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
|
||||
if (!sc->hwinfo) {
|
||||
DBG("ath9k: cannot allocate 802.11 hardware info structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
sc->sc_ah->led_pin = -1;
|
||||
|
||||
common = ath9k_hw_common(ah);
|
||||
common->ops = &ah->reg_ops;
|
||||
common->bus_ops = bus_ops;
|
||||
common->ah = ah;
|
||||
common->dev = sc->dev;
|
||||
common->priv = sc;
|
||||
|
||||
sc->intr_tq = ath9k_tasklet;
|
||||
|
||||
/*
|
||||
* Cache line size is used to size and align various
|
||||
* structures used to communicate with the hardware.
|
||||
*/
|
||||
ath_read_cachesize(common, &csz);
|
||||
common->cachelsz = csz << 2; /* convert to bytes */
|
||||
|
||||
/* Initializes the hardware for all supported chipsets */
|
||||
ret = ath9k_hw_init(ah);
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
memcpy(sc->hwinfo->hwaddr, common->macaddr, ETH_ALEN);
|
||||
|
||||
ret = ath9k_init_queues(sc);
|
||||
if (ret)
|
||||
goto err_queues;
|
||||
|
||||
ret = ath9k_init_channels_rates(sc);
|
||||
if (ret)
|
||||
goto err_btcoex;
|
||||
|
||||
ath9k_init_crypto(sc);
|
||||
ath9k_init_misc(sc);
|
||||
|
||||
return 0;
|
||||
|
||||
err_btcoex:
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i))
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
err_queues:
|
||||
ath9k_hw_deinit(ah);
|
||||
err_hw:
|
||||
free(sc->hwinfo);
|
||||
sc->hwinfo = NULL;
|
||||
|
||||
free(ah);
|
||||
sc->sc_ah = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
|
||||
{
|
||||
struct net80211_channel *chan;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->hwinfo->nr_channels; i++) {
|
||||
chan = &sc->hwinfo->channels[i];
|
||||
if(chan->band != band)
|
||||
continue;
|
||||
ah->curchan = &ah->channels[chan->hw_value];
|
||||
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, 1);
|
||||
chan->maxpower = reg->max_power_level / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_init_txpower_limits(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_channel *curchan = ah->curchan;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
|
||||
ath9k_init_band_txpower(sc, NET80211_BAND_2GHZ);
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||
ath9k_init_band_txpower(sc, NET80211_BAND_5GHZ);
|
||||
|
||||
ah->curchan = curchan;
|
||||
}
|
||||
|
||||
void ath9k_set_hw_capab(struct ath_softc *sc, struct net80211_device *dev __unused)
|
||||
{
|
||||
sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
|
||||
sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
|
||||
sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
|
||||
sc->hwinfo->channel_change_time = 5000;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
|
||||
{
|
||||
sc->hwinfo->bands |= NET80211_BAND_BIT_2GHZ;
|
||||
sc->hwinfo->modes |= NET80211_MODE_B | NET80211_MODE_G;
|
||||
}
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||
{
|
||||
sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
|
||||
sc->hwinfo->modes |= NET80211_MODE_A;
|
||||
}
|
||||
}
|
||||
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
struct net80211_device *dev = sc->dev;
|
||||
/*struct ath_common *common;
|
||||
struct ath_hw *ah;*/
|
||||
int error = 0;
|
||||
/*struct ath_regulatory *reg;*/
|
||||
|
||||
/* Bring up device */
|
||||
error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
|
||||
if (error != 0)
|
||||
goto error_init;
|
||||
|
||||
/*ah = sc->sc_ah;
|
||||
common = ath9k_hw_common(ah);*/
|
||||
ath9k_set_hw_capab(sc, dev);
|
||||
/* TODO Cottsay: reg */
|
||||
/* Initialize regulatory */
|
||||
/*error = ath_regd_init(&common->regulatory, sc->dev->wiphy,
|
||||
ath9k_reg_notifier);
|
||||
if (error)
|
||||
goto error_regd;
|
||||
|
||||
reg = &common->regulatory;*/
|
||||
|
||||
/* Setup TX DMA */
|
||||
error = ath_tx_init(sc, ATH_TXBUF);
|
||||
if (error != 0)
|
||||
goto error_tx;
|
||||
|
||||
/* Setup RX DMA */
|
||||
error = ath_rx_init(sc, ATH_RXBUF);
|
||||
if (error != 0)
|
||||
goto error_rx;
|
||||
|
||||
ath9k_init_txpower_limits(sc);
|
||||
|
||||
/* Register with mac80211 */
|
||||
error = net80211_register(dev, &ath9k_ops, sc->hwinfo);
|
||||
if (error)
|
||||
goto error_register;
|
||||
|
||||
/* TODO Cottsay: reg */
|
||||
/* Handle world regulatory */
|
||||
/*if (!ath_is_world_regd(reg)) {
|
||||
error = regulatory_hint(hw->wiphy, reg->alpha2);
|
||||
if (error)
|
||||
goto error_world;
|
||||
}*/
|
||||
|
||||
sc->hw_pll_work = ath_hw_pll_work;
|
||||
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
/* TODO Cottsay: rfkill */
|
||||
/*ath_start_rfkill_poll(sc);*/
|
||||
|
||||
return 0;
|
||||
|
||||
//error_world:
|
||||
// net80211_unregister(dev);
|
||||
error_register:
|
||||
ath_rx_cleanup(sc);
|
||||
error_rx:
|
||||
ath_tx_cleanup(sc);
|
||||
error_tx:
|
||||
ath9k_deinit_softc(sc);
|
||||
error_init:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* De-Initialization */
|
||||
/*****************************/
|
||||
|
||||
static void ath9k_deinit_softc(struct ath_softc *sc)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i))
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
|
||||
ath9k_hw_deinit(sc->sc_ah);
|
||||
|
||||
free(sc->hwinfo);
|
||||
sc->hwinfo = NULL;
|
||||
free(sc->sc_ah);
|
||||
sc->sc_ah = NULL;
|
||||
}
|
||||
|
||||
void ath9k_deinit_device(struct ath_softc *sc)
|
||||
{
|
||||
struct net80211_device *dev = sc->dev;
|
||||
|
||||
net80211_unregister(dev);
|
||||
ath_rx_cleanup(sc);
|
||||
ath_tx_cleanup(sc);
|
||||
ath9k_deinit_softc(sc);
|
||||
}
|
||||
|
||||
void ath_descdma_cleanup(struct ath_softc *sc __unused,
|
||||
struct ath_descdma *dd,
|
||||
struct list_head *head)
|
||||
{
|
||||
free_dma(dd->dd_desc, dd->dd_desc_len);
|
||||
|
||||
INIT_LIST_HEAD(head);
|
||||
free(dd->dd_bufptr);
|
||||
memset(dd, 0, sizeof(*dd));
|
||||
}
|
||||
733
src/drivers/net/ath/ath9k/ath9k_mac.c
Normal file
733
src/drivers/net/ath/ath9k/ath9k_mac.c
Normal file
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
|
||||
static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
|
||||
struct ath9k_tx_queue_info *qi __unused)
|
||||
{
|
||||
DBG2("ath9k: "
|
||||
"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
|
||||
ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
|
||||
ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
|
||||
ah->txurn_interrupt_mask);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_IMR_S0,
|
||||
SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
|
||||
| SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
|
||||
REG_WRITE(ah, AR_IMR_S1,
|
||||
SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
|
||||
| SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
|
||||
|
||||
ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
|
||||
ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
|
||||
{
|
||||
REG_WRITE(ah, AR_QTXDP(q), txdp);
|
||||
}
|
||||
|
||||
void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
DBG2("ath9k: "
|
||||
"Enable TXE on queue: %d\n", q);
|
||||
REG_WRITE(ah, AR_Q_TXE, 1 << q);
|
||||
}
|
||||
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
u32 npend;
|
||||
|
||||
npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
|
||||
if (npend == 0) {
|
||||
|
||||
if (REG_READ(ah, AR_Q_TXE) & (1 << q))
|
||||
npend = 1;
|
||||
}
|
||||
|
||||
return npend;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
|
||||
*
|
||||
* @ah: atheros hardware struct
|
||||
* @bIncTrigLevel: whether or not the frame trigger level should be updated
|
||||
*
|
||||
* The frame trigger level specifies the minimum number of bytes,
|
||||
* in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
|
||||
* before the PCU will initiate sending the frame on the air. This can
|
||||
* mean we initiate transmit before a full frame is on the PCU TX FIFO.
|
||||
* Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
|
||||
* first)
|
||||
*
|
||||
* Caution must be taken to ensure to set the frame trigger level based
|
||||
* on the DMA request size. For example if the DMA request size is set to
|
||||
* 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
|
||||
* there need to be enough space in the tx FIFO for the requested transfer
|
||||
* size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
|
||||
* the threshold to a value beyond 6, then the transmit will hang.
|
||||
*
|
||||
* Current dual stream devices have a PCU TX FIFO size of 8 KB.
|
||||
* Current single stream devices have a PCU TX FIFO size of 4 KB, however,
|
||||
* there is a hardware issue which forces us to use 2 KB instead so the
|
||||
* frame trigger level must not exceed 2 KB for these chipsets.
|
||||
*/
|
||||
int ath9k_hw_updatetxtriglevel(struct ath_hw *ah, int bIncTrigLevel)
|
||||
{
|
||||
u32 txcfg, curLevel, newLevel;
|
||||
|
||||
if (ah->tx_trig_level >= ah->config.max_txtrig_level)
|
||||
return 0;
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
txcfg = REG_READ(ah, AR_TXCFG);
|
||||
curLevel = MS(txcfg, AR_FTRIG);
|
||||
newLevel = curLevel;
|
||||
if (bIncTrigLevel) {
|
||||
if (curLevel < ah->config.max_txtrig_level)
|
||||
newLevel++;
|
||||
} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
|
||||
newLevel--;
|
||||
if (newLevel != curLevel)
|
||||
REG_WRITE(ah, AR_TXCFG,
|
||||
(txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
|
||||
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
ah->tx_trig_level = newLevel;
|
||||
|
||||
return newLevel != curLevel;
|
||||
}
|
||||
|
||||
void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
|
||||
{
|
||||
int i, q;
|
||||
|
||||
REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
|
||||
|
||||
REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
|
||||
for (q = 0; q < AR_NUM_QCU; q++) {
|
||||
for (i = 0; i < 1000; i++) {
|
||||
if (i)
|
||||
udelay(5);
|
||||
|
||||
if (!ath9k_hw_numtxpending(ah, q))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
|
||||
REG_WRITE(ah, AR_Q_TXD, 0);
|
||||
}
|
||||
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
|
||||
{
|
||||
*txqs &= ah->intr_txqs;
|
||||
ah->intr_txqs &= ~(*txqs);
|
||||
}
|
||||
|
||||
int ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
u32 cw;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DBG("ath9k: "
|
||||
"Set TXQ properties, inactive queue: %d\n", q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBG2("ath9k: Set queue properties for: %d\n", q);
|
||||
|
||||
qi->tqi_ver = qinfo->tqi_ver;
|
||||
qi->tqi_subtype = qinfo->tqi_subtype;
|
||||
qi->tqi_qflags = qinfo->tqi_qflags;
|
||||
qi->tqi_priority = qinfo->tqi_priority;
|
||||
if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
|
||||
qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
|
||||
else
|
||||
qi->tqi_aifs = INIT_AIFS;
|
||||
if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
|
||||
cw = min(qinfo->tqi_cwmin, 1024U);
|
||||
qi->tqi_cwmin = 1;
|
||||
while (qi->tqi_cwmin < cw)
|
||||
qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
|
||||
} else
|
||||
qi->tqi_cwmin = qinfo->tqi_cwmin;
|
||||
if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
|
||||
cw = min(qinfo->tqi_cwmax, 1024U);
|
||||
qi->tqi_cwmax = 1;
|
||||
while (qi->tqi_cwmax < cw)
|
||||
qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
|
||||
} else
|
||||
qi->tqi_cwmax = INIT_CWMAX;
|
||||
|
||||
if (qinfo->tqi_shretry != 0)
|
||||
qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
|
||||
else
|
||||
qi->tqi_shretry = INIT_SH_RETRY;
|
||||
if (qinfo->tqi_lgretry != 0)
|
||||
qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
|
||||
else
|
||||
qi->tqi_lgretry = INIT_LG_RETRY;
|
||||
qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
|
||||
qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
|
||||
qi->tqi_burstTime = qinfo->tqi_burstTime;
|
||||
qi->tqi_readyTime = qinfo->tqi_readyTime;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
||||
const struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
int q;
|
||||
|
||||
for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
|
||||
if (ah->txq[q].tqi_type ==
|
||||
ATH9K_TX_QUEUE_INACTIVE)
|
||||
break;
|
||||
if (q == ATH9K_NUM_TX_QUEUES) {
|
||||
DBG("No available TX queue\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG2("ath9K: Setup TX queue: %d\n", q);
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DBG("ath9k: TX queue: %d already active\n", q);
|
||||
return -1;
|
||||
}
|
||||
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
qi->tqi_type = type;
|
||||
if (qinfo == NULL) {
|
||||
qi->tqi_qflags =
|
||||
TXQ_FLAG_TXOKINT_ENABLE
|
||||
| TXQ_FLAG_TXERRINT_ENABLE
|
||||
| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
|
||||
qi->tqi_aifs = INIT_AIFS;
|
||||
qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
|
||||
qi->tqi_cwmax = INIT_CWMAX;
|
||||
qi->tqi_shretry = INIT_SH_RETRY;
|
||||
qi->tqi_lgretry = INIT_LG_RETRY;
|
||||
qi->tqi_physCompBuf = 0;
|
||||
} else {
|
||||
qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
|
||||
(void) ath9k_hw_set_txq_props(ah, q, qinfo);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
int ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DBG("ath9k: "
|
||||
"Release TXQ, inactive queue: %d\n", q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBG2("ath9k: Release TX queue: %d\n", q);
|
||||
|
||||
qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
|
||||
ah->txok_interrupt_mask &= ~(1 << q);
|
||||
ah->txerr_interrupt_mask &= ~(1 << q);
|
||||
ah->txdesc_interrupt_mask &= ~(1 << q);
|
||||
ah->txeol_interrupt_mask &= ~(1 << q);
|
||||
ah->txurn_interrupt_mask &= ~(1 << q);
|
||||
ath9k_hw_set_txq_interrupts(ah, qi);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
u32 cwMin, chanCwMin, value __unused;
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DBG("ath9k: "
|
||||
"Reset TXQ, inactive queue: %d\n", q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DBG2("ath9k: Reset TX queue: %d\n", q);
|
||||
|
||||
if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
|
||||
if (chan && IS_CHAN_B(chan))
|
||||
chanCwMin = INIT_CWMIN_11B;
|
||||
else
|
||||
chanCwMin = INIT_CWMIN;
|
||||
|
||||
for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
|
||||
} else
|
||||
cwMin = qi->tqi_cwmin;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_DLCL_IFS(q),
|
||||
SM(cwMin, AR_D_LCL_IFS_CWMIN) |
|
||||
SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
|
||||
SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
|
||||
|
||||
REG_WRITE(ah, AR_DRETRY_LIMIT(q),
|
||||
SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
|
||||
SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
|
||||
SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
|
||||
|
||||
REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
|
||||
|
||||
if (AR_SREV_9340(ah))
|
||||
REG_WRITE(ah, AR_DMISC(q),
|
||||
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
||||
else
|
||||
REG_WRITE(ah, AR_DMISC(q),
|
||||
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
|
||||
|
||||
if (qi->tqi_cbrPeriod) {
|
||||
REG_WRITE(ah, AR_QCBRCFG(q),
|
||||
SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
|
||||
SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
|
||||
REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
|
||||
(qi->tqi_cbrOverflowLimit ?
|
||||
AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
|
||||
}
|
||||
if (qi->tqi_readyTime) {
|
||||
REG_WRITE(ah, AR_QRDYTIMECFG(q),
|
||||
SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
|
||||
AR_Q_RDYTIMECFG_EN);
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_DCHNTIME(q),
|
||||
SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
|
||||
(qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
|
||||
|
||||
if (qi->tqi_burstTime
|
||||
&& (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
|
||||
REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
|
||||
|
||||
if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
|
||||
REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
||||
if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
|
||||
REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);
|
||||
|
||||
if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
|
||||
REG_SET_BIT(ah, AR_DMISC(q),
|
||||
SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
|
||||
AR_D_MISC_ARB_LOCKOUT_CNTRL) |
|
||||
AR_D_MISC_POST_FR_BKOFF_DIS);
|
||||
}
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
|
||||
|
||||
if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
|
||||
ah->txok_interrupt_mask |= 1 << q;
|
||||
else
|
||||
ah->txok_interrupt_mask &= ~(1 << q);
|
||||
if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
|
||||
ah->txerr_interrupt_mask |= 1 << q;
|
||||
else
|
||||
ah->txerr_interrupt_mask &= ~(1 << q);
|
||||
if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
|
||||
ah->txdesc_interrupt_mask |= 1 << q;
|
||||
else
|
||||
ah->txdesc_interrupt_mask &= ~(1 << q);
|
||||
if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
|
||||
ah->txeol_interrupt_mask |= 1 << q;
|
||||
else
|
||||
ah->txeol_interrupt_mask &= ~(1 << q);
|
||||
if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
|
||||
ah->txurn_interrupt_mask |= 1 << q;
|
||||
else
|
||||
ah->txurn_interrupt_mask &= ~(1 << q);
|
||||
ath9k_hw_set_txq_interrupts(ah, qi);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
struct ath_rx_status *rs, u64 tsf __unused)
|
||||
{
|
||||
struct ar5416_desc ads;
|
||||
struct ar5416_desc *adsp = AR5416DESC(ds);
|
||||
u32 phyerr;
|
||||
|
||||
if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ads.u.rx = adsp->u.rx;
|
||||
|
||||
rs->rs_status = 0;
|
||||
rs->rs_flags = 0;
|
||||
|
||||
rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
|
||||
rs->rs_tstamp = ads.AR_RcvTimestamp;
|
||||
|
||||
if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
|
||||
rs->rs_rssi = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
|
||||
rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
|
||||
} else {
|
||||
rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
|
||||
rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
|
||||
AR_RxRSSIAnt00);
|
||||
rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
|
||||
AR_RxRSSIAnt01);
|
||||
rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
|
||||
AR_RxRSSIAnt02);
|
||||
rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
|
||||
AR_RxRSSIAnt10);
|
||||
rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
|
||||
AR_RxRSSIAnt11);
|
||||
rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
|
||||
AR_RxRSSIAnt12);
|
||||
}
|
||||
if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
|
||||
rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
|
||||
else
|
||||
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
|
||||
|
||||
rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
|
||||
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
|
||||
|
||||
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
|
||||
rs->rs_moreaggr =
|
||||
(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
|
||||
rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
|
||||
rs->rs_flags =
|
||||
(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
|
||||
rs->rs_flags |=
|
||||
(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
|
||||
|
||||
if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
|
||||
rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
|
||||
if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
|
||||
rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
|
||||
if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
|
||||
rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
|
||||
|
||||
if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
|
||||
/*
|
||||
* Treat these errors as mutually exclusive to avoid spurious
|
||||
* extra error reports from the hardware. If a CRC error is
|
||||
* reported, then decryption and MIC errors are irrelevant,
|
||||
* the frame is going to be dropped either way
|
||||
*/
|
||||
if (ads.ds_rxstatus8 & AR_CRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_CRC;
|
||||
else if (ads.ds_rxstatus8 & AR_PHYErr) {
|
||||
rs->rs_status |= ATH9K_RXERR_PHY;
|
||||
phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
|
||||
rs->rs_phyerr = phyerr;
|
||||
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
else if (ads.ds_rxstatus8 & AR_MichaelErr)
|
||||
rs->rs_status |= ATH9K_RXERR_MIC;
|
||||
else if (ads.ds_rxstatus8 & AR_KeyMiss)
|
||||
rs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can stop or re-enables RX.
|
||||
*
|
||||
* If bool is set this will kill any frame which is currently being
|
||||
* transferred between the MAC and baseband and also prevent any new
|
||||
* frames from getting started.
|
||||
*/
|
||||
int ath9k_hw_setrxabort(struct ath_hw *ah, int set)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (set) {
|
||||
REG_SET_BIT(ah, AR_DIAG_SW,
|
||||
(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
|
||||
if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
REG_CLR_BIT(ah, AR_DIAG_SW,
|
||||
(AR_DIAG_RX_DIS |
|
||||
AR_DIAG_RX_ABORT));
|
||||
|
||||
reg = REG_READ(ah, AR_OBS_BUS_1);
|
||||
DBG("ath9k: "
|
||||
"RX failed to go idle in 10 ms RXSM=0x%x\n",
|
||||
reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
REG_CLR_BIT(ah, AR_DIAG_SW,
|
||||
(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
|
||||
{
|
||||
REG_WRITE(ah, AR_RXDP, rxdp);
|
||||
}
|
||||
|
||||
void ath9k_hw_startpcureceive(struct ath_hw *ah, int is_scanning)
|
||||
{
|
||||
ath9k_ani_reset(ah, is_scanning);
|
||||
|
||||
REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
}
|
||||
|
||||
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
|
||||
}
|
||||
|
||||
int ath9k_hw_stopdmarecv(struct ath_hw *ah, int *reset)
|
||||
{
|
||||
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
|
||||
u32 mac_status, last_mac_status = 0;
|
||||
int i;
|
||||
|
||||
/* Enable access to the DMA observation bus */
|
||||
REG_WRITE(ah, AR_MACMISC,
|
||||
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
|
||||
(AR_MACMISC_MISC_OBS_BUS_1 <<
|
||||
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
|
||||
|
||||
REG_WRITE(ah, AR_CR, AR_CR_RXD);
|
||||
|
||||
/* Wait for rx enable bit to go low */
|
||||
for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
|
||||
if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
|
||||
break;
|
||||
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
|
||||
if (mac_status == 0x1c0 && mac_status == last_mac_status) {
|
||||
*reset = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
last_mac_status = mac_status;
|
||||
}
|
||||
|
||||
udelay(AH_TIME_QUANTUM);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
DBG("ath9k: "
|
||||
"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
|
||||
AH_RX_STOP_DMA_TIMEOUT / 1000,
|
||||
REG_READ(ah, AR_CR),
|
||||
REG_READ(ah, AR_DIAG_SW),
|
||||
REG_READ(ah, AR_DMADBG_7));
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef AH_RX_STOP_DMA_TIMEOUT
|
||||
}
|
||||
|
||||
int ath9k_hw_intrpend(struct ath_hw *ah)
|
||||
{
|
||||
u32 host_isr;
|
||||
|
||||
if (AR_SREV_9100(ah) || !(ah->ah_ier & AR_IER_ENABLE))
|
||||
return 1;
|
||||
|
||||
host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
|
||||
if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
|
||||
return 1;
|
||||
|
||||
host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
|
||||
if ((host_isr & AR_INTR_SYNC_DEFAULT)
|
||||
&& (host_isr != AR_INTR_SPURIOUS))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath9k_hw_disable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
DBG2("ath9k: disable IER\n");
|
||||
REG_WRITE(ah, AR_IER, ah->ah_ier);
|
||||
(void) REG_READ(ah, AR_IER);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
u32 sync_default = AR_INTR_SYNC_DEFAULT;
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_GLOBAL))
|
||||
return;
|
||||
|
||||
if (AR_SREV_9340(ah))
|
||||
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
|
||||
|
||||
DBG2("ath9k: enable IER\n");
|
||||
REG_WRITE(ah, AR_IER, ah->ah_ier);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
|
||||
AR_INTR_MAC_IRQ);
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
|
||||
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
|
||||
REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default);
|
||||
}
|
||||
DBG2("ath9k: AR_IMR 0x%x IER 0x%x\n",
|
||||
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
|
||||
}
|
||||
|
||||
void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
|
||||
{
|
||||
enum ath9k_int omask = ah->imask;
|
||||
u32 mask, mask2;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
|
||||
if (!(ints & ATH9K_INT_GLOBAL))
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
DBG2("ath9k: 0x%x => 0x%x\n", omask, ints);
|
||||
|
||||
/* TODO: global int Ref count */
|
||||
mask = ints & ATH9K_INT_COMMON;
|
||||
mask2 = 0;
|
||||
|
||||
if (ints & ATH9K_INT_TX) {
|
||||
if (ah->config.tx_intr_mitigation)
|
||||
mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
|
||||
else {
|
||||
if (ah->txok_interrupt_mask)
|
||||
mask |= AR_IMR_TXOK;
|
||||
if (ah->txdesc_interrupt_mask)
|
||||
mask |= AR_IMR_TXDESC;
|
||||
}
|
||||
if (ah->txerr_interrupt_mask)
|
||||
mask |= AR_IMR_TXERR;
|
||||
if (ah->txeol_interrupt_mask)
|
||||
mask |= AR_IMR_TXEOL;
|
||||
}
|
||||
if (ints & ATH9K_INT_RX) {
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
|
||||
if (ah->config.rx_intr_mitigation) {
|
||||
mask &= ~AR_IMR_RXOK_LP;
|
||||
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
|
||||
} else {
|
||||
mask |= AR_IMR_RXOK_LP;
|
||||
}
|
||||
} else {
|
||||
if (ah->config.rx_intr_mitigation)
|
||||
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
|
||||
else
|
||||
mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
|
||||
}
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
mask |= AR_IMR_GENTMR;
|
||||
}
|
||||
|
||||
if (ints & ATH9K_INT_GENTIMER)
|
||||
mask |= AR_IMR_GENTMR;
|
||||
|
||||
if (ints & (ATH9K_INT_BMISC)) {
|
||||
mask |= AR_IMR_BCNMISC;
|
||||
if (ints & ATH9K_INT_TIM)
|
||||
mask2 |= AR_IMR_S2_TIM;
|
||||
if (ints & ATH9K_INT_DTIM)
|
||||
mask2 |= AR_IMR_S2_DTIM;
|
||||
if (ints & ATH9K_INT_DTIMSYNC)
|
||||
mask2 |= AR_IMR_S2_DTIMSYNC;
|
||||
if (ints & ATH9K_INT_CABEND)
|
||||
mask2 |= AR_IMR_S2_CABEND;
|
||||
if (ints & ATH9K_INT_TSFOOR)
|
||||
mask2 |= AR_IMR_S2_TSFOOR;
|
||||
}
|
||||
|
||||
if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
|
||||
mask |= AR_IMR_BCNMISC;
|
||||
if (ints & ATH9K_INT_GTT)
|
||||
mask2 |= AR_IMR_S2_GTT;
|
||||
if (ints & ATH9K_INT_CST)
|
||||
mask2 |= AR_IMR_S2_CST;
|
||||
}
|
||||
|
||||
DBG2("ath9k: new IMR 0x%x\n", mask);
|
||||
REG_WRITE(ah, AR_IMR, mask);
|
||||
ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
|
||||
AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
|
||||
AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
|
||||
ah->imrs2_reg |= mask2;
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
|
||||
if (ints & ATH9K_INT_TIM_TIMER)
|
||||
REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
|
||||
}
|
||||
|
||||
if (ints & ATH9K_INT_GLOBAL)
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
return;
|
||||
}
|
||||
916
src/drivers/net/ath/ath9k/ath9k_main.c
Normal file
916
src/drivers/net/ath/ath9k/ath9k_main.c
Normal file
@@ -0,0 +1,916 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
static void ath9k_bss_info_changed(struct net80211_device *dev, u32 changed);
|
||||
|
||||
int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath9k_hw_setpower(sc->sc_ah, mode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath_start_ani(struct ath_common *common)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
unsigned long timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC;
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
|
||||
if (!(sc->sc_flags & SC_OP_ANI_RUN))
|
||||
return;
|
||||
|
||||
if (sc->sc_flags & SC_OP_OFFCHANNEL)
|
||||
return;
|
||||
|
||||
common->ani.longcal_timer = timestamp;
|
||||
common->ani.shortcal_timer = timestamp;
|
||||
common->ani.checkani_timer = timestamp;
|
||||
|
||||
common->ani.timer = timestamp + ah->config.ani_poll_interval;
|
||||
}
|
||||
|
||||
static void ath_update_survey_nf(struct ath_softc *sc, int channel)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_channel *chan = &ah->channels[channel];
|
||||
struct survey_info *survey = &sc->survey[channel];
|
||||
|
||||
if (chan->noisefloor) {
|
||||
survey->filled |= SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = chan->noisefloor;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the survey statistics and returns the busy time since last
|
||||
* update in %, if the measurement duration was long enough for the
|
||||
* result to be useful, -1 otherwise.
|
||||
*/
|
||||
static int ath_update_survey_stats(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int pos = ah->curchan - &ah->channels[0];
|
||||
struct survey_info *survey = &sc->survey[pos];
|
||||
struct ath_cycle_counters *cc = &common->cc_survey;
|
||||
unsigned int div = common->clockrate * 1000;
|
||||
int ret = 0;
|
||||
|
||||
if (!ah->curchan)
|
||||
return -1;
|
||||
|
||||
if (ah->power_mode == ATH9K_PM_AWAKE)
|
||||
ath_hw_cycle_counters_update(common);
|
||||
|
||||
if (cc->cycles > 0) {
|
||||
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
survey->channel_time += cc->cycles / div;
|
||||
survey->channel_time_busy += cc->rx_busy / div;
|
||||
survey->channel_time_rx += cc->rx_frame / div;
|
||||
survey->channel_time_tx += cc->tx_frame / div;
|
||||
}
|
||||
|
||||
if (cc->cycles < div)
|
||||
return -1;
|
||||
|
||||
if (cc->cycles > 0)
|
||||
ret = cc->rx_busy * 100 / cc->cycles;
|
||||
|
||||
memset(cc, 0, sizeof(*cc));
|
||||
|
||||
ath_update_survey_nf(sc, pos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set/change channels. If the channel is really being changed, it's done
|
||||
* by reseting the chip. To accomplish this we must first cleanup any pending
|
||||
* DMA, then restart stuff.
|
||||
*/
|
||||
int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev,
|
||||
struct ath9k_channel *hchan)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int fastcc __unused = 1, stopped __unused;
|
||||
struct net80211_channel *channel = dev->channels + dev->channel;
|
||||
struct ath9k_hw_cal_data *caldata = NULL;
|
||||
int r;
|
||||
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return -EIO;
|
||||
|
||||
sc->hw_busy_count = 0;
|
||||
|
||||
common->ani.timer = 0;
|
||||
sc->tx_complete_work_timer = 0;
|
||||
sc->hw_pll_work_timer = 0;
|
||||
|
||||
/*
|
||||
* This is only performed if the channel settings have
|
||||
* actually changed.
|
||||
*
|
||||
* To switch channels clear any pending DMA operations;
|
||||
* wait long enough for the RX fifo to drain, reset the
|
||||
* hardware at the new frequency, and then re-enable
|
||||
* the relevant bits of the h/w.
|
||||
*/
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
stopped = ath_drain_all_txq(sc, 0);
|
||||
|
||||
if (!ath_stoprecv(sc))
|
||||
stopped = 0;
|
||||
|
||||
if (!ath9k_hw_check_alive(ah))
|
||||
stopped = 0;
|
||||
|
||||
/* XXX: do not flush receive queue here. We don't want
|
||||
* to flush data frames already in queue because of
|
||||
* changing channel. */
|
||||
|
||||
if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
|
||||
caldata = &sc->caldata;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"(%d MHz) -> (%d MHz)\n",
|
||||
sc->sc_ah->curchan->channel,
|
||||
channel->center_freq);
|
||||
|
||||
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
||||
if (r) {
|
||||
DBG("ath9k: "
|
||||
"Unable to reset channel (%d MHz), reset status %d\n",
|
||||
channel->center_freq, r);
|
||||
goto ps_restore;
|
||||
}
|
||||
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
DBG("ath9k: Unable to restart recv logic\n");
|
||||
r = -EIO;
|
||||
goto ps_restore;
|
||||
}
|
||||
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->config.txpowlimit, &sc->curtxpow);
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
|
||||
if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
|
||||
sc->tx_complete_work(sc);
|
||||
sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 500;
|
||||
ath_start_ani(common);
|
||||
}
|
||||
|
||||
ps_restore:
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine performs the periodic noise floor calibration function
|
||||
* that is used to adjust and optimize the chip performance. This
|
||||
* takes environmental changes (location, temperature) into account.
|
||||
* When the task is complete, it reschedules itself depending on the
|
||||
* appropriate interval that was calculated.
|
||||
*/
|
||||
void ath_ani_calibrate(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int longcal = 0;
|
||||
int shortcal = 0;
|
||||
int aniflag = 0;
|
||||
unsigned int timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
|
||||
u32 cal_interval, short_cal_interval, long_cal_interval;
|
||||
|
||||
if (ah->caldata && ah->caldata->nfcal_interference)
|
||||
long_cal_interval = ATH_LONG_CALINTERVAL_INT;
|
||||
else
|
||||
long_cal_interval = ATH_LONG_CALINTERVAL;
|
||||
|
||||
short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
|
||||
|
||||
/* Only calibrate if awake */
|
||||
if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
|
||||
goto set_timer;
|
||||
|
||||
/* Long calibration runs independently of short calibration. */
|
||||
if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
|
||||
longcal = 1;
|
||||
DBG2("ath9k: longcal @%d\n", timestamp);
|
||||
common->ani.longcal_timer = timestamp;
|
||||
}
|
||||
|
||||
/* Short calibration applies only while caldone is false */
|
||||
if (!common->ani.caldone) {
|
||||
if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
|
||||
shortcal = 1;
|
||||
DBG2("ath9k: "
|
||||
"shortcal @%d\n", timestamp);
|
||||
common->ani.shortcal_timer = timestamp;
|
||||
common->ani.resetcal_timer = timestamp;
|
||||
}
|
||||
} else {
|
||||
if ((timestamp - common->ani.resetcal_timer) >=
|
||||
ATH_RESTART_CALINTERVAL) {
|
||||
common->ani.caldone = ath9k_hw_reset_calvalid(ah);
|
||||
if (common->ani.caldone)
|
||||
common->ani.resetcal_timer = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify whether we must check ANI */
|
||||
if ((timestamp - common->ani.checkani_timer) >=
|
||||
ah->config.ani_poll_interval) {
|
||||
aniflag = 1;
|
||||
common->ani.checkani_timer = timestamp;
|
||||
}
|
||||
|
||||
/* Skip all processing if there's nothing to do. */
|
||||
if (longcal || shortcal || aniflag) {
|
||||
/* Call ANI routine if necessary */
|
||||
if (aniflag) {
|
||||
ath9k_hw_ani_monitor(ah, ah->curchan);
|
||||
ath_update_survey_stats(sc);
|
||||
}
|
||||
|
||||
/* Perform calibration if necessary */
|
||||
if (longcal || shortcal) {
|
||||
common->ani.caldone =
|
||||
ath9k_hw_calibrate(ah,
|
||||
ah->curchan,
|
||||
common->rx_chainmask,
|
||||
longcal);
|
||||
}
|
||||
}
|
||||
|
||||
set_timer:
|
||||
/*
|
||||
* Set timer interval based on previous results.
|
||||
* The interval must be the shortest necessary to satisfy ANI,
|
||||
* short calibration and long calibration.
|
||||
*/
|
||||
cal_interval = ATH_LONG_CALINTERVAL;
|
||||
if (sc->sc_ah->config.enable_ani)
|
||||
cal_interval = min(cal_interval,
|
||||
(u32)ah->config.ani_poll_interval);
|
||||
if (!common->ani.caldone)
|
||||
cal_interval = min(cal_interval, (u32)short_cal_interval);
|
||||
|
||||
common->ani.timer = timestamp + cal_interval;
|
||||
}
|
||||
|
||||
void ath_hw_check(struct ath_softc *sc)
|
||||
{
|
||||
int busy;
|
||||
|
||||
if (ath9k_hw_check_alive(sc->sc_ah))
|
||||
goto out;
|
||||
|
||||
busy = ath_update_survey_stats(sc);
|
||||
|
||||
DBG("ath9k: Possible baseband hang, "
|
||||
"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
|
||||
if (busy >= 99) {
|
||||
if (++sc->hw_busy_count >= 3)
|
||||
ath_reset(sc, 1);
|
||||
} else if (busy >= 0)
|
||||
sc->hw_busy_count = 0;
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
|
||||
{
|
||||
static int count;
|
||||
|
||||
if (pll_sqsum >= 0x40000) {
|
||||
count++;
|
||||
if (count == 3) {
|
||||
/* Rx is hung for more than 500ms. Reset it */
|
||||
DBG("ath9k: "
|
||||
"Possible RX hang, resetting");
|
||||
ath_reset(sc, 1);
|
||||
count = 0;
|
||||
}
|
||||
} else
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void ath_hw_pll_work(struct ath_softc *sc)
|
||||
{
|
||||
u32 pll_sqsum;
|
||||
|
||||
if (AR_SREV_9485(sc->sc_ah)) {
|
||||
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
|
||||
|
||||
ath_hw_pll_rx_hang_check(sc, pll_sqsum);
|
||||
|
||||
sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 200;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ath9k_tasklet(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
u32 status = sc->intrstatus;
|
||||
u32 rxmask;
|
||||
|
||||
if ((status & ATH9K_INT_FATAL) ||
|
||||
(status & ATH9K_INT_BB_WATCHDOG)) {
|
||||
ath_reset(sc, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
|
||||
|
||||
if (status & rxmask) {
|
||||
ath_rx_tasklet(sc, 0, 0);
|
||||
}
|
||||
|
||||
if (status & ATH9K_INT_TX) {
|
||||
ath_tx_tasklet(sc);
|
||||
}
|
||||
|
||||
/* re-enable hardware interrupt */
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
|
||||
void ath_isr(struct net80211_device *dev)
|
||||
{
|
||||
#define SCHED_INTR ( \
|
||||
ATH9K_INT_FATAL | \
|
||||
ATH9K_INT_BB_WATCHDOG | \
|
||||
ATH9K_INT_RXORN | \
|
||||
ATH9K_INT_RXEOL | \
|
||||
ATH9K_INT_RX | \
|
||||
ATH9K_INT_RXLP | \
|
||||
ATH9K_INT_RXHP | \
|
||||
ATH9K_INT_TX | \
|
||||
ATH9K_INT_BMISS | \
|
||||
ATH9K_INT_CST | \
|
||||
ATH9K_INT_TSFOOR | \
|
||||
ATH9K_INT_GENTIMER)
|
||||
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
enum ath9k_int status;
|
||||
unsigned long timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
|
||||
int sched = 0;
|
||||
|
||||
/*
|
||||
* The hardware is not ready/present, don't
|
||||
* touch anything. Note this can happen early
|
||||
* on if the IRQ is shared.
|
||||
*/
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return;
|
||||
|
||||
|
||||
/* Check calibration */
|
||||
if(timestamp >= (unsigned int)common->ani.timer && common->ani.timer)
|
||||
ath_ani_calibrate(sc);
|
||||
|
||||
/* Check tx_complete_work */
|
||||
if(timestamp >= (unsigned int)sc->tx_complete_work_timer && sc->tx_complete_work_timer)
|
||||
sc->tx_complete_work(sc);
|
||||
|
||||
/* Check hw_pll_work */
|
||||
if(timestamp >= (unsigned int)sc->hw_pll_work_timer && sc->hw_pll_work_timer)
|
||||
sc->hw_pll_work(sc);
|
||||
|
||||
/* shared irq, not for us */
|
||||
|
||||
if (!ath9k_hw_intrpend(ah))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Figure out the reason(s) for the interrupt. Note
|
||||
* that the hal returns a pseudo-ISR that may include
|
||||
* bits we haven't explicitly enabled so we mask the
|
||||
* value to insure we only process bits we requested.
|
||||
*/
|
||||
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
|
||||
status &= ah->imask; /* discard unasked-for bits */
|
||||
|
||||
/*
|
||||
* If there are no status bits set, then this interrupt was not
|
||||
* for me (should have been caught above).
|
||||
*/
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
/* Cache the status */
|
||||
sc->intrstatus = status;
|
||||
|
||||
if (status & SCHED_INTR)
|
||||
sched = 1;
|
||||
|
||||
/*
|
||||
* If a FATAL or RXORN interrupt is received, we have to reset the
|
||||
* chip immediately.
|
||||
*/
|
||||
if ((status & ATH9K_INT_FATAL) || (status & ATH9K_INT_RXORN))
|
||||
goto chip_reset;
|
||||
|
||||
if (status & ATH9K_INT_TXURN)
|
||||
ath9k_hw_updatetxtriglevel(ah, 1);
|
||||
|
||||
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
if (status & ATH9K_INT_TIM_TIMER) {
|
||||
if (sc->ps_idle)
|
||||
goto chip_reset;
|
||||
/* Clear RxAbort bit so that we can
|
||||
* receive frames */
|
||||
ath9k_setpower(sc, ATH9K_PM_AWAKE);
|
||||
ath9k_hw_setrxabort(sc->sc_ah, 0);
|
||||
sc->ps_flags |= PS_WAIT_FOR_BEACON;
|
||||
}
|
||||
|
||||
chip_reset:
|
||||
|
||||
if (sched) {
|
||||
/* turn off every interrupt */
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
sc->intr_tq(sc);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
#undef SCHED_INTR
|
||||
}
|
||||
|
||||
void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct net80211_channel *channel = dev->channels + dev->channel;
|
||||
int r;
|
||||
|
||||
sc->hw_pll_work_timer = 0;
|
||||
|
||||
/*
|
||||
* Keep the LED on when the radio is disabled
|
||||
* during idle unassociated state.
|
||||
*/
|
||||
if (!sc->ps_idle) {
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
ath_drain_all_txq(sc, 0); /* clear pending tx frames */
|
||||
|
||||
ath_stoprecv(sc); /* turn off frame recv */
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath9k_cmn_get_curchannel(dev, ah);
|
||||
|
||||
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, 0);
|
||||
if (r) {
|
||||
DBG("ath9k: "
|
||||
"Unable to reset channel (%d MHz), reset status %d\n",
|
||||
channel->center_freq, r);
|
||||
}
|
||||
|
||||
ath9k_hw_phy_disable(ah);
|
||||
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
}
|
||||
|
||||
int ath_reset(struct ath_softc *sc, int retry_tx)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int r;
|
||||
|
||||
sc->hw_busy_count = 0;
|
||||
|
||||
/* Stop ANI */
|
||||
common->ani.timer = 0;
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath_drain_all_txq(sc, retry_tx);
|
||||
|
||||
ath_stoprecv(sc);
|
||||
ath_flushrecv(sc);
|
||||
|
||||
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, 0);
|
||||
if (r)
|
||||
DBG("ath9k: "
|
||||
"Unable to reset hardware; reset status %d\n", r);
|
||||
|
||||
if (ath_startrecv(sc) != 0)
|
||||
DBG("ath9k: Unable to start recv logic\n");
|
||||
|
||||
/*
|
||||
* We may be doing a reset in response to a request
|
||||
* that changes the channel so update any state that
|
||||
* might change as a result.
|
||||
*/
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->config.txpowlimit, &sc->curtxpow);
|
||||
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
|
||||
if (retry_tx) {
|
||||
int i;
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (ATH_TXQ_SETUP(sc, i)) {
|
||||
ath_txq_schedule(sc, &sc->tx.txq[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start ANI */
|
||||
ath_start_ani(common);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* mac80211 callbacks */
|
||||
/**********************/
|
||||
|
||||
static int ath9k_start(struct net80211_device *dev)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct net80211_channel *curchan = dev->channels + dev->channel;
|
||||
struct ath9k_channel *init_channel;
|
||||
int r;
|
||||
|
||||
DBG("ath9k: "
|
||||
"Starting driver with initial channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
/* setup initial channel */
|
||||
sc->chan_idx = curchan->hw_value;
|
||||
|
||||
init_channel = ath9k_cmn_get_curchannel(dev, ah);
|
||||
|
||||
/* Reset SERDES registers */
|
||||
ath9k_hw_configpcipowersave(ah, 0, 0);
|
||||
|
||||
/*
|
||||
* The basic interface to setting the hardware in a good
|
||||
* state is ``reset''. On return the hardware is known to
|
||||
* be powered up and with interrupts disabled. This must
|
||||
* be followed by initialization of the appropriate bits
|
||||
* and then setup of the interrupt mask.
|
||||
*/
|
||||
r = ath9k_hw_reset(ah, init_channel, ah->caldata, 0);
|
||||
if (r) {
|
||||
DBG("ath9k: "
|
||||
"Unable to reset hardware; reset status %d (freq %d MHz)\n",
|
||||
r, curchan->center_freq);
|
||||
goto mutex_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is needed only to setup initial state
|
||||
* but it's best done after a reset.
|
||||
*/
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->config.txpowlimit, &sc->curtxpow);
|
||||
|
||||
/*
|
||||
* Setup the hardware after reset:
|
||||
* The receive engine is set going.
|
||||
* Frame transmit is handled entirely
|
||||
* in the frame output path; there's nothing to do
|
||||
* here except setup the interrupt mask.
|
||||
*/
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
DBG("ath9k: Unable to start recv logic\n");
|
||||
r = -EIO;
|
||||
goto mutex_unlock;
|
||||
}
|
||||
|
||||
/* Setup our intr mask. */
|
||||
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
|
||||
ATH9K_INT_RXORN | ATH9K_INT_FATAL |
|
||||
ATH9K_INT_GLOBAL;
|
||||
|
||||
ah->imask |= ATH9K_INT_RX;
|
||||
|
||||
sc->sc_flags &= ~SC_OP_INVALID;
|
||||
sc->sc_ah->is_monitoring = 0;
|
||||
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
|
||||
sc->tx_complete_work(sc);
|
||||
|
||||
if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
|
||||
common->bus_ops->extn_synch_en(common);
|
||||
|
||||
mutex_unlock:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ath9k_tx(struct net80211_device *dev, struct io_buffer *iob)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_tx_control txctl;
|
||||
int ret = 0;
|
||||
|
||||
memset(&txctl, 0, sizeof(struct ath_tx_control));
|
||||
txctl.txq = sc->tx.txq_map[0];
|
||||
|
||||
DBGIO("ath9k: transmitting packet, iob: %p\n", iob);
|
||||
|
||||
ret = ath_tx_start(dev, iob, &txctl);
|
||||
if (ret) {
|
||||
DBG("ath9k: TX failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return ret;
|
||||
exit:
|
||||
free_iob(iob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_stop(struct net80211_device *dev)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
sc->tx_complete_work_timer = 0;
|
||||
sc->hw_pll_work_timer = 0;
|
||||
|
||||
if (sc->sc_flags & SC_OP_INVALID) {
|
||||
DBG("ath9k: Device not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* prevent tasklets to enable interrupts once we disable them */
|
||||
ah->imask &= ~ATH9K_INT_GLOBAL;
|
||||
|
||||
/* make sure h/w will not generate any interrupt
|
||||
* before setting the invalid flag. */
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
if (!(sc->sc_flags & SC_OP_INVALID)) {
|
||||
ath_drain_all_txq(sc, 0);
|
||||
ath_stoprecv(sc);
|
||||
ath9k_hw_phy_disable(ah);
|
||||
} else
|
||||
sc->rx.rxlink = NULL;
|
||||
|
||||
if (sc->rx.frag) {
|
||||
free_iob(sc->rx.frag);
|
||||
sc->rx.frag = NULL;
|
||||
}
|
||||
|
||||
/* disable HAL and put h/w to sleep */
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
|
||||
ath_radio_disable(sc, dev);
|
||||
|
||||
sc->sc_flags |= SC_OP_INVALID;
|
||||
|
||||
DBG("ath9k: Driver halt\n");
|
||||
}
|
||||
|
||||
static int ath9k_config(struct net80211_device *dev, int changed)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
if ((changed & NET80211_CFG_RATE) ||
|
||||
(changed & NET80211_CFG_PHY_PARAMS)) {
|
||||
int spmbl = (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? IEEE80211_TX_RC_USE_SHORT_PREAMBLE : 0;
|
||||
u16 rate = dev->rates[dev->rate];
|
||||
u16 slowrate = dev->rates[dev->rtscts_rate];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NET80211_MAX_RATES; i++) {
|
||||
if (sc->rates[i].bitrate == rate &&
|
||||
(sc->rates[i].flags & spmbl))
|
||||
sc->hw_rix = i;
|
||||
|
||||
if (sc->rates[i].bitrate == slowrate &&
|
||||
(sc->rates[i].flags & spmbl))
|
||||
sc->hw_rix = i;
|
||||
}
|
||||
}
|
||||
|
||||
ath9k_bss_info_changed(dev, changed);
|
||||
|
||||
if (changed & NET80211_CFG_CHANNEL) {
|
||||
struct net80211_channel *curchan = dev->channels + dev->channel;
|
||||
int pos = curchan->hw_value;
|
||||
int old_pos = -1;
|
||||
|
||||
if (ah->curchan)
|
||||
old_pos = ah->curchan - &ah->channels[0];
|
||||
|
||||
sc->sc_flags &= ~SC_OP_OFFCHANNEL;
|
||||
|
||||
DBG2("ath9k: "
|
||||
"Set channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
|
||||
curchan);
|
||||
|
||||
/* update survey stats for the old channel before switching */
|
||||
ath_update_survey_stats(sc);
|
||||
|
||||
/*
|
||||
* If the operating channel changes, change the survey in-use flags
|
||||
* along with it.
|
||||
* Reset the survey data for the new channel, unless we're switching
|
||||
* back to the operating channel from an off-channel operation.
|
||||
*/
|
||||
if (sc->cur_survey != &sc->survey[pos]) {
|
||||
|
||||
if (sc->cur_survey)
|
||||
sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
|
||||
|
||||
sc->cur_survey = &sc->survey[pos];
|
||||
|
||||
memset(sc->cur_survey, 0, sizeof(struct survey_info));
|
||||
sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
|
||||
} else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
|
||||
memset(&sc->survey[pos], 0, sizeof(struct survey_info));
|
||||
}
|
||||
|
||||
if (ath_set_channel(sc, dev, &sc->sc_ah->channels[pos]) < 0) {
|
||||
DBG("ath9k: Unable to set channel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The most recent snapshot of channel->noisefloor for the old
|
||||
* channel is only available after the hardware reset. Copy it to
|
||||
* the survey stats now.
|
||||
*/
|
||||
if (old_pos >= 0)
|
||||
ath_update_survey_nf(sc, old_pos);
|
||||
}
|
||||
|
||||
if (changed & NET80211_CFG_CHANNEL) {
|
||||
DBG2("ath9k: "
|
||||
"Set power: %d\n", (dev->channels + dev->channel)->maxpower);
|
||||
sc->config.txpowlimit = 2 * (dev->channels + dev->channel)->maxpower;
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->config.txpowlimit, &sc->curtxpow);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_bss_iter(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
if (common->dev->state & NET80211_ASSOCIATED) {
|
||||
sc->sc_flags |= SC_OP_PRIM_STA_VIF;
|
||||
memcpy(common->curbssid, common->dev->bssid, ETH_ALEN);
|
||||
common->curaid = common->dev->aid;
|
||||
ath9k_hw_write_associd(sc->sc_ah);
|
||||
DBG("ath9k: "
|
||||
"Bss Info ASSOC %d, bssid: %pM\n",
|
||||
common->dev->aid, common->curbssid);
|
||||
|
||||
/*
|
||||
* Request a re-configuration of Beacon related timers
|
||||
* on the receipt of the first Beacon frame (i.e.,
|
||||
* after time sync with the AP).
|
||||
*/
|
||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||
/* Reset rssi stats */
|
||||
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
sc->sc_flags |= SC_OP_ANI_RUN;
|
||||
ath_start_ani(common);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_config_bss(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct net80211_device *dev = common->dev;
|
||||
|
||||
/* Reconfigure bss info */
|
||||
if (!(dev->state & NET80211_ASSOCIATED)) {
|
||||
DBG2("ath9k: "
|
||||
"ath9k: Bss Info DISASSOC %d, bssid %pM\n",
|
||||
common->curaid, common->curbssid);
|
||||
sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
|
||||
memset(common->curbssid, 0, ETH_ALEN);
|
||||
common->curaid = 0;
|
||||
}
|
||||
|
||||
ath9k_bss_iter(sc);
|
||||
|
||||
/*
|
||||
* None of station vifs are associated.
|
||||
* Clear bssid & aid
|
||||
*/
|
||||
if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
|
||||
ath9k_hw_write_associd(sc->sc_ah);
|
||||
/* Stop ANI */
|
||||
sc->sc_flags &= ~SC_OP_ANI_RUN;
|
||||
common->ani.timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_bss_info_changed(struct net80211_device *dev,
|
||||
u32 changed)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int slottime;
|
||||
|
||||
if (changed & NET80211_CFG_ASSOC) {
|
||||
ath9k_config_bss(sc);
|
||||
|
||||
DBG2("ath9k: BSSID: %pM aid: 0x%x\n",
|
||||
common->curbssid, common->curaid);
|
||||
}
|
||||
|
||||
if (changed & NET80211_CFG_PHY_PARAMS) {
|
||||
if (dev->phy_flags & NET80211_PHY_USE_PROTECTION)
|
||||
slottime = 9;
|
||||
else
|
||||
slottime = 20;
|
||||
ah->slottime = slottime;
|
||||
ath9k_hw_init_global_settings(ah);
|
||||
|
||||
DBG2("ath9k: BSS Changed PREAMBLE %d\n",
|
||||
!!(dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE));
|
||||
if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
|
||||
sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
|
||||
else
|
||||
sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
|
||||
|
||||
DBG2("ath9k: BSS Changed CTS PROT %d\n",
|
||||
!!(dev->phy_flags & NET80211_PHY_USE_PROTECTION));
|
||||
if ((dev->phy_flags & NET80211_PHY_USE_PROTECTION) &&
|
||||
(dev->channels + dev->channel)->band != NET80211_BAND_5GHZ)
|
||||
sc->sc_flags |= SC_OP_PROTECT_ENABLE;
|
||||
else
|
||||
sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_poll(struct net80211_device *dev)
|
||||
{
|
||||
ath_isr(dev);
|
||||
}
|
||||
|
||||
static void ath9k_irq(struct net80211_device *dev, int enable)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
ah->ah_ier = enable ? AR_IER_ENABLE : AR_IER_DISABLE;
|
||||
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
}
|
||||
|
||||
struct net80211_device_operations ath9k_ops = {
|
||||
.transmit = ath9k_tx,
|
||||
.open = ath9k_start,
|
||||
.close = ath9k_stop,
|
||||
.config = ath9k_config,
|
||||
.poll = ath9k_poll,
|
||||
.irq = ath9k_irq,
|
||||
};
|
||||
521
src/drivers/net/ath/ath9k/ath9k_recv.c
Normal file
521
src/drivers/net/ath/ath9k/ath9k_recv.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "ar9003_mac.h"
|
||||
|
||||
/*
|
||||
* Setup and link descriptors.
|
||||
*
|
||||
* 11N: we can no longer afford to self link the last descriptor.
|
||||
* MAC acknowledges BA status as long as it copies frames to host
|
||||
* buffer (or rx fifo). This can incorrectly acknowledge packets
|
||||
* to a sender if last desc is self-linked.
|
||||
*/
|
||||
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_desc *ds;
|
||||
// struct io_buffer *iob;
|
||||
|
||||
ATH_RXBUF_RESET(bf);
|
||||
|
||||
ds = bf->bf_desc;
|
||||
ds->ds_link = 0; /* link to null */
|
||||
ds->ds_data = bf->bf_buf_addr;
|
||||
|
||||
// /* virtual addr of the beginning of the buffer. */
|
||||
// iob = bf->bf_mpdu;
|
||||
// ds->ds_vdata = iob->data;
|
||||
|
||||
/*
|
||||
* setup rx descriptors. The rx_bufsize here tells the hardware
|
||||
* how much data it can DMA to us and that we are prepared
|
||||
* to process
|
||||
*/
|
||||
ath9k_hw_setuprxdesc(ah, ds,
|
||||
common->rx_bufsize,
|
||||
0);
|
||||
|
||||
if (sc->rx.rxlink == NULL)
|
||||
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
|
||||
else
|
||||
*sc->rx.rxlink = bf->bf_daddr;
|
||||
|
||||
sc->rx.rxlink = &ds->ds_link;
|
||||
}
|
||||
|
||||
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
|
||||
{
|
||||
/* XXX block beacon interrupts */
|
||||
ath9k_hw_setantenna(sc->sc_ah, antenna);
|
||||
sc->rx.defant = antenna;
|
||||
sc->rx.rxotherant = 0;
|
||||
}
|
||||
|
||||
static void ath_opmode_init(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
u32 rfilt, mfilt[2];
|
||||
|
||||
/* configure rx filter */
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(ah, rfilt);
|
||||
|
||||
/* configure bssid mask */
|
||||
ath_hw_setbssidmask(common);
|
||||
|
||||
/* configure operational mode */
|
||||
ath9k_hw_setopmode(ah);
|
||||
|
||||
/* calculate and install multicast filter */
|
||||
mfilt[0] = mfilt[1] = ~0;
|
||||
ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
|
||||
}
|
||||
|
||||
int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct io_buffer *iob;
|
||||
u32 *iob_addr = NULL;
|
||||
struct ath_buf *bf;
|
||||
int error = 0;
|
||||
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
|
||||
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
|
||||
sc->sc_ah->caps.rx_status_len;
|
||||
|
||||
DBG2("ath9k: cachelsz %d rxbufsize %d\n",
|
||||
common->cachelsz, common->rx_bufsize);
|
||||
|
||||
/* Initialize rx descriptors */
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
|
||||
"rx", nbufs, 1, 0);
|
||||
if (error != 0) {
|
||||
DBG("ath9k: "
|
||||
"failed to allocate rx descriptors: %d\n",
|
||||
error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
iob = ath_rxbuf_alloc(common, common->rx_bufsize,
|
||||
iob_addr);
|
||||
if (iob == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bf->bf_mpdu = iob;
|
||||
bf->bf_buf_addr = *iob_addr;
|
||||
}
|
||||
sc->rx.rxlink = NULL;
|
||||
|
||||
err:
|
||||
if (error)
|
||||
ath_rx_cleanup(sc);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void ath_rx_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct io_buffer *iob;
|
||||
struct ath_buf *bf;
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
iob = bf->bf_mpdu;
|
||||
if (iob) {
|
||||
free_iob(iob);
|
||||
bf->bf_buf_addr = 0;
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->rx.rxdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the receive filter according to the
|
||||
* operating mode and state:
|
||||
*
|
||||
* o always accept unicast, broadcast, and multicast traffic
|
||||
* o maintain current state of phy error reception (the hal
|
||||
* may enable phy error frames for noise immunity work)
|
||||
* o probe request frames are accepted only when operating in
|
||||
* hostap, adhoc, or monitor modes
|
||||
* o enable promiscuous mode according to the interface state
|
||||
* o accept beacons:
|
||||
* - when operating in adhoc mode so the 802.11 layer creates
|
||||
* node table entries for peers,
|
||||
* - when operating in station mode for collecting rssi data when
|
||||
* the station is otherwise quiet, or
|
||||
* - when operating as a repeater so we see repeater-sta beacons
|
||||
* - when scanning
|
||||
*/
|
||||
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||
{
|
||||
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
|
||||
|
||||
u32 rfilt;
|
||||
|
||||
rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
|
||||
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
|
||||
| ATH9K_RX_FILTER_MCAST | ATH9K_RX_FILTER_BEACON;
|
||||
|
||||
return rfilt;
|
||||
|
||||
#undef RX_FILTER_PRESERVE
|
||||
}
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_buf *bf, *tbf;
|
||||
|
||||
if (list_empty(&sc->rx.rxbuf))
|
||||
goto start_recv;
|
||||
|
||||
sc->rx.rxlink = NULL;
|
||||
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
|
||||
ath_rx_buf_link(sc, bf);
|
||||
}
|
||||
|
||||
/* We could have deleted elements so the list may be empty now */
|
||||
if (list_empty(&sc->rx.rxbuf))
|
||||
goto start_recv;
|
||||
|
||||
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
|
||||
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
|
||||
ath9k_hw_rxena(ah);
|
||||
|
||||
start_recv:
|
||||
ath_opmode_init(sc);
|
||||
ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_stoprecv(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
int stopped, reset = 0;
|
||||
|
||||
ath9k_hw_abortpcurecv(ah);
|
||||
ath9k_hw_setrxfilter(ah, 0);
|
||||
stopped = ath9k_hw_stopdmarecv(ah, &reset);
|
||||
|
||||
sc->rx.rxlink = NULL;
|
||||
|
||||
if (!(ah->ah_flags & AH_UNPLUGGED) &&
|
||||
!stopped) {
|
||||
DBG("ath9k: "
|
||||
"Could not stop RX, we could be "
|
||||
"confusing the DMA engine when we start RX up\n");
|
||||
}
|
||||
return stopped && !reset;
|
||||
}
|
||||
|
||||
void ath_flushrecv(struct ath_softc *sc)
|
||||
{
|
||||
sc->sc_flags |= SC_OP_RXFLUSH;
|
||||
ath_rx_tasklet(sc, 1, 0);
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
}
|
||||
|
||||
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_desc *ds;
|
||||
struct ath_buf *bf;
|
||||
int ret;
|
||||
|
||||
if (list_empty(&sc->rx.rxbuf)) {
|
||||
sc->rx.rxlink = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
|
||||
ds = bf->bf_desc;
|
||||
|
||||
/*
|
||||
* Must provide the virtual address of the current
|
||||
* descriptor, the physical address, and the virtual
|
||||
* address of the next descriptor in the h/w chain.
|
||||
* This allows the HAL to look ahead to see if the
|
||||
* hardware is done with a descriptor by checking the
|
||||
* done bit in the following descriptor and the address
|
||||
* of the current descriptor the DMA engine is working
|
||||
* on. All this is necessary because of our use of
|
||||
* a self-linked list to avoid rx overruns.
|
||||
*/
|
||||
ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
|
||||
if (ret == -EINPROGRESS) {
|
||||
struct ath_rx_status trs;
|
||||
struct ath_buf *tbf;
|
||||
struct ath_desc *tds;
|
||||
|
||||
memset(&trs, 0, sizeof(trs));
|
||||
if ((&bf->list)->next == &sc->rx.rxbuf) {
|
||||
sc->rx.rxlink = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tbf = list_entry(bf->list.next, struct ath_buf, list);
|
||||
|
||||
/*
|
||||
* On some hardware the descriptor status words could
|
||||
* get corrupted, including the done bit. Because of
|
||||
* this, check if the next descriptor's done bit is
|
||||
* set or not.
|
||||
*
|
||||
* If the next descriptor's done bit is set, the current
|
||||
* descriptor has been corrupted. Force s/w to discard
|
||||
* this descriptor and continue...
|
||||
*/
|
||||
|
||||
tds = tbf->bf_desc;
|
||||
ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
|
||||
if (ret == -EINPROGRESS)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!bf->bf_mpdu)
|
||||
return bf;
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
/* Assumes you've already done the endian to CPU conversion */
|
||||
static int ath9k_rx_accept(struct ath_common *common,
|
||||
struct ath_rx_status *rx_stats,
|
||||
int *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
u8 rx_status_len = ah->caps.rx_status_len;
|
||||
|
||||
|
||||
if (!rx_stats->rs_datalen)
|
||||
return 0;
|
||||
/*
|
||||
* rs_status follows rs_datalen so if rs_datalen is too large
|
||||
* we can take a hint that hardware corrupted it, so ignore
|
||||
* those frames.
|
||||
*/
|
||||
if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
|
||||
return 0;
|
||||
|
||||
/* Only use error bits from the last fragment */
|
||||
if (rx_stats->rs_more)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
* chained descriptors so it can be ignored if rs_more is set. The
|
||||
* rs_more will be false at the last element of the chained
|
||||
* descriptors.
|
||||
*/
|
||||
if (rx_stats->rs_status != 0) {
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
|
||||
return 0;
|
||||
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = 1;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (ah->is_monitoring) {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
return 0;
|
||||
} else {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ath9k_process_rate(struct ath_common *common __unused,
|
||||
struct net80211_device *dev,
|
||||
struct ath_rx_status *rx_stats,
|
||||
int *rix)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)dev->priv;
|
||||
int band;
|
||||
int i = 0;
|
||||
|
||||
band = (dev->channels + sc->dev->channel)->band;
|
||||
|
||||
for (i = 0; i < sc->hwinfo->nr_rates[band]; i++) {
|
||||
if (sc->rates[i].hw_value == rx_stats->rs_rate) {
|
||||
*rix = i;
|
||||
return 0;
|
||||
}
|
||||
if (sc->rates[i].hw_value_short == rx_stats->rs_rate) {
|
||||
*rix = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No valid hardware bitrate found -- we should not get here
|
||||
* because hardware has already validated this frame as OK.
|
||||
*/
|
||||
DBG("ath9k: "
|
||||
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
|
||||
rx_stats->rs_rate);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* up the frame up to let mac80211 handle the actual error case, be it no
|
||||
* decryption key or real decryption error. This let us keep statistics there.
|
||||
*/
|
||||
static int ath9k_rx_iob_preprocess(struct ath_common *common,
|
||||
struct net80211_device *dev,
|
||||
struct ath_rx_status *rx_stats,
|
||||
int *rix,
|
||||
int *decrypt_error)
|
||||
{
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
* separately to avoid doing two lookups for a rate for each frame.
|
||||
*/
|
||||
if (!ath9k_rx_accept(common, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
/* Only use status info from the last fragment */
|
||||
if (rx_stats->rs_more)
|
||||
return 0;
|
||||
|
||||
if (ath9k_process_rate(common, dev, rx_stats, rix))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp __unused)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct io_buffer *iob = NULL, *requeue_iob;
|
||||
u32 *requeue_iob_addr = NULL;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
/*
|
||||
* The hw can technically differ from common->hw when using ath9k
|
||||
* virtual wiphy so to account for that we iterate over the active
|
||||
* wiphys and find the appropriate wiphy and therefore hw.
|
||||
*/
|
||||
struct net80211_device *dev = sc->dev;
|
||||
int retval;
|
||||
int decrypt_error = 0;
|
||||
struct ath_rx_status rs;
|
||||
int rix = 0;
|
||||
|
||||
do {
|
||||
/* If handling rx interrupt and flush is in progress => exit */
|
||||
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
|
||||
break;
|
||||
|
||||
memset(&rs, 0, sizeof(rs));
|
||||
bf = ath_get_next_rx_buf(sc, &rs);
|
||||
|
||||
if (!bf)
|
||||
break;
|
||||
|
||||
iob = bf->bf_mpdu;
|
||||
if (!iob)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we're asked to flush receive queue, directly
|
||||
* chain it back at the queue without processing it.
|
||||
*/
|
||||
if (flush)
|
||||
goto requeue_drop_frag;
|
||||
|
||||
retval = ath9k_rx_iob_preprocess(common, dev, &rs,
|
||||
&rix, &decrypt_error);
|
||||
if (retval)
|
||||
goto requeue_drop_frag;
|
||||
|
||||
/* Ensure we always have an iob to requeue once we are done
|
||||
* processing the current buffer's iob */
|
||||
requeue_iob = ath_rxbuf_alloc(common, common->rx_bufsize, requeue_iob_addr);
|
||||
|
||||
/* If there is no memory we ignore the current RX'd frame,
|
||||
* tell hardware it can give us a new frame using the old
|
||||
* iob and put it at the tail of the sc->rx.rxbuf list for
|
||||
* processing. */
|
||||
if (!requeue_iob)
|
||||
goto requeue_drop_frag;
|
||||
|
||||
iob_put(iob, rs.rs_datalen + ah->caps.rx_status_len);
|
||||
if (ah->caps.rx_status_len)
|
||||
iob_pull(iob, ah->caps.rx_status_len);
|
||||
|
||||
/* We will now give hardware our shiny new allocated iob */
|
||||
bf->bf_mpdu = requeue_iob;
|
||||
bf->bf_buf_addr = *requeue_iob_addr;
|
||||
|
||||
/*
|
||||
* change the default rx antenna if rx diversity chooses the
|
||||
* other antenna 3 times in a row.
|
||||
*/
|
||||
if (sc->rx.defant != rs.rs_antenna) {
|
||||
if (++sc->rx.rxotherant >= 3)
|
||||
ath_setdefantenna(sc, rs.rs_antenna);
|
||||
} else {
|
||||
sc->rx.rxotherant = 0;
|
||||
}
|
||||
|
||||
DBGIO("ath9k: rx %d bytes, signal %d, bitrate %d, hw_value %d\n", rs.rs_datalen,
|
||||
rs.rs_rssi, sc->rates[rix].bitrate, rs.rs_rate);
|
||||
|
||||
net80211_rx(dev, iob, rs.rs_rssi,
|
||||
sc->rates[rix].bitrate);
|
||||
|
||||
requeue_drop_frag:
|
||||
list_del(&bf->list);
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_buf_link(sc, bf);
|
||||
ath9k_hw_rxena(ah);
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
813
src/drivers/net/ath/ath9k/ath9k_xmit.c
Normal file
813
src/drivers/net/ath/ath9k/ath9k_xmit.c
Normal file
@@ -0,0 +1,813 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "ar9003_mac.h"
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
#define OFDM_PLCP_BITS 22
|
||||
#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
|
||||
#define L_STF 8
|
||||
#define L_LTF 8
|
||||
#define L_SIG 4
|
||||
#define HT_SIG 8
|
||||
#define HT_STF 4
|
||||
#define HT_LTF(_ns) (4 * (_ns))
|
||||
#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
|
||||
#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
|
||||
#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
|
||||
#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
|
||||
|
||||
|
||||
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
|
||||
|
||||
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
struct list_head *bf_head);
|
||||
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_txq *txq, struct list_head *bf_q,
|
||||
struct ath_tx_status *ts, int txok, int sendbar);
|
||||
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct list_head *head);
|
||||
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
|
||||
|
||||
enum {
|
||||
MCS_HT20,
|
||||
MCS_HT20_SGI,
|
||||
MCS_HT40,
|
||||
MCS_HT40_SGI,
|
||||
};
|
||||
|
||||
/*********************/
|
||||
/* Aggregation logic */
|
||||
/*********************/
|
||||
|
||||
static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_atx_ac *ac = tid->ac;
|
||||
|
||||
if (tid->paused)
|
||||
return;
|
||||
|
||||
if (tid->sched)
|
||||
return;
|
||||
|
||||
tid->sched = 1;
|
||||
list_add_tail(&tid->list, &ac->tid_q);
|
||||
|
||||
if (ac->sched)
|
||||
return;
|
||||
|
||||
ac->sched = 1;
|
||||
list_add_tail(&ac->list, &txq->axq_acq);
|
||||
}
|
||||
|
||||
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_buf *bf = NULL;
|
||||
|
||||
if (list_empty(&sc->tx.txbuf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
|
||||
list_del(&bf->list);
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
|
||||
{
|
||||
list_add_tail(&bf->list, &sc->tx.txbuf);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* Queue Management */
|
||||
/********************/
|
||||
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_tx_queue_info qi;
|
||||
static const int subtype_txq_to_hwq[] = {
|
||||
[WME_AC_BE] = ATH_TXQ_AC_BE,
|
||||
};
|
||||
int axq_qnum, i;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
qi.tqi_subtype = subtype_txq_to_hwq[subtype];
|
||||
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_physCompBuf = 0;
|
||||
|
||||
/*
|
||||
* Enable interrupts only for EOL and DESC conditions.
|
||||
* We mark tx descriptors to receive a DESC interrupt
|
||||
* when a tx queue gets deep; otherwise waiting for the
|
||||
* EOL to reap descriptors. Note that this is done to
|
||||
* reduce interrupt load and this only defers reaping
|
||||
* descriptors, never transmitting frames. Aside from
|
||||
* reducing interrupts this also permits more concurrency.
|
||||
* The only potential downside is if the tx queue backs
|
||||
* up in which case the top half of the kernel may backup
|
||||
* due to a lack of tx descriptors.
|
||||
*
|
||||
* The UAPSD queue is an exception, since we take a desc-
|
||||
* based intr on the EOSP frames.
|
||||
*/
|
||||
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
|
||||
TXQ_FLAG_TXDESCINT_ENABLE;
|
||||
|
||||
axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
|
||||
if (axq_qnum == -1) {
|
||||
/*
|
||||
* NB: don't print a message, this happens
|
||||
* normally on parts with too few tx queues
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
if ((unsigned int)axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
|
||||
DBG("ath9k: qnum %d out of range, max %zd!\n",
|
||||
axq_qnum, ARRAY_SIZE(sc->tx.txq));
|
||||
ath9k_hw_releasetxqueue(ah, axq_qnum);
|
||||
return NULL;
|
||||
}
|
||||
if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
|
||||
struct ath_txq *txq = &sc->tx.txq[axq_qnum];
|
||||
|
||||
txq->axq_qnum = axq_qnum;
|
||||
txq->mac80211_qnum = -1;
|
||||
txq->axq_link = NULL;
|
||||
INIT_LIST_HEAD(&txq->axq_q);
|
||||
INIT_LIST_HEAD(&txq->axq_acq);
|
||||
txq->axq_depth = 0;
|
||||
txq->axq_ampdu_depth = 0;
|
||||
txq->axq_tx_inprogress = 0;
|
||||
sc->tx.txqsetup |= 1<<axq_qnum;
|
||||
|
||||
txq->txq_headidx = txq->txq_tailidx = 0;
|
||||
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
|
||||
INIT_LIST_HEAD(&txq->txq_fifo[i]);
|
||||
INIT_LIST_HEAD(&txq->txq_fifo_pending);
|
||||
}
|
||||
return &sc->tx.txq[axq_qnum];
|
||||
}
|
||||
|
||||
/*
|
||||
* Drain a given TX queue (could be Beacon or Data)
|
||||
*
|
||||
* This assumes output has been stopped and
|
||||
* we do not need to block ath_tx_tasklet.
|
||||
*/
|
||||
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, int retry_tx __unused)
|
||||
{
|
||||
struct ath_buf *bf, *lastbf __unused;
|
||||
struct list_head bf_head;
|
||||
struct ath_tx_status ts;
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
||||
for (;;) {
|
||||
if (list_empty(&txq->axq_q)) {
|
||||
txq->axq_link = NULL;
|
||||
break;
|
||||
}
|
||||
bf = list_first_entry(&txq->axq_q, struct ath_buf,
|
||||
list);
|
||||
|
||||
if (bf->bf_stale) {
|
||||
list_del(&bf->list);
|
||||
|
||||
ath_tx_return_buffer(sc, bf);
|
||||
continue;
|
||||
}
|
||||
|
||||
lastbf = bf->bf_lastbf;
|
||||
|
||||
list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
|
||||
|
||||
txq->axq_depth--;
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
|
||||
}
|
||||
|
||||
txq->axq_tx_inprogress = 0;
|
||||
}
|
||||
|
||||
int ath_drain_all_txq(struct ath_softc *sc, int retry_tx)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_txq *txq;
|
||||
int i, npend = 0;
|
||||
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return 1;
|
||||
|
||||
ath9k_hw_abort_tx_dma(ah);
|
||||
|
||||
/* Check if any queue remains active */
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
|
||||
}
|
||||
|
||||
if (npend)
|
||||
DBG("ath9k: Failed to stop TX DMA!\n");
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The caller will resume queues with ieee80211_wake_queues.
|
||||
* Mark the queue as not stopped to prevent ath_tx_complete
|
||||
* from waking the queue too early.
|
||||
*/
|
||||
txq = &sc->tx.txq[i];
|
||||
txq->stopped = 0;
|
||||
ath_draintxq(sc, txq, retry_tx);
|
||||
}
|
||||
|
||||
return !npend;
|
||||
}
|
||||
|
||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
|
||||
sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
|
||||
}
|
||||
|
||||
/* For each axq_acq entry, for each tid, try to schedule packets
|
||||
* for transmit until ampdu_depth has reached min Q depth.
|
||||
*/
|
||||
void ath_txq_schedule(struct ath_softc *sc __unused, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_atx_ac *ac, *ac_tmp, *last_ac;
|
||||
struct ath_atx_tid *tid, *last_tid;
|
||||
|
||||
if (list_empty(&txq->axq_acq) ||
|
||||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
|
||||
return;
|
||||
|
||||
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
|
||||
last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
|
||||
|
||||
list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
|
||||
last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
|
||||
list_del(&ac->list);
|
||||
ac->sched = 0;
|
||||
|
||||
while (!list_empty(&ac->tid_q)) {
|
||||
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
||||
list);
|
||||
list_del(&tid->list);
|
||||
tid->sched = 0;
|
||||
|
||||
if (tid->paused)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* add tid to round-robin queue if more frames
|
||||
* are pending for the tid
|
||||
*/
|
||||
if (!list_empty(&tid->buf_q))
|
||||
ath_tx_queue_tid(txq, tid);
|
||||
|
||||
if (tid == last_tid ||
|
||||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!list_empty(&ac->tid_q)) {
|
||||
if (!ac->sched) {
|
||||
ac->sched = 1;
|
||||
list_add_tail(&ac->list, &txq->axq_acq);
|
||||
}
|
||||
}
|
||||
|
||||
if (ac == last_ac ||
|
||||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* TX, DMA */
|
||||
/***********/
|
||||
|
||||
/*
|
||||
* Insert a chain of ath_buf (descriptors) on a txq and
|
||||
* assume the descriptors are already chained together by caller.
|
||||
*/
|
||||
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_buf *bf;
|
||||
|
||||
/*
|
||||
* Insert the frame on the outbound list and
|
||||
* pass it on to the hardware.
|
||||
*/
|
||||
|
||||
if (list_empty(head))
|
||||
return;
|
||||
|
||||
bf = list_first_entry(head, struct ath_buf, list);
|
||||
|
||||
DBGIO("ath9k: "
|
||||
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
|
||||
|
||||
list_splice_tail_init(head, &txq->axq_q);
|
||||
|
||||
if (txq->axq_link == NULL) {
|
||||
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
|
||||
DBGIO("ath9k: TXDP[%d] = %llx (%p)\n",
|
||||
txq->axq_qnum, ito64(bf->bf_daddr),
|
||||
bf->bf_desc);
|
||||
} else {
|
||||
*txq->axq_link = bf->bf_daddr;
|
||||
DBGIO("ath9k: "
|
||||
"link[%d] (%p)=%llx (%p)\n",
|
||||
txq->axq_qnum, txq->axq_link,
|
||||
ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
|
||||
&txq->axq_link);
|
||||
ath9k_hw_txstart(ah, txq->axq_qnum);
|
||||
|
||||
txq->axq_depth++;
|
||||
}
|
||||
|
||||
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
struct list_head *bf_head)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
|
||||
bf = list_first_entry(bf_head, struct ath_buf, list);
|
||||
bf->bf_state.bf_type &= ~BUF_AMPDU;
|
||||
|
||||
/* update starting sequence number for subsequent ADDBA request */
|
||||
if (tid)
|
||||
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
|
||||
|
||||
bf->bf_lastbf = bf;
|
||||
ath_buf_set_rate(sc, bf, iob_len(bf->bf_mpdu) + FCS_LEN);
|
||||
ath_tx_txqaddbuf(sc, txq, bf_head);
|
||||
}
|
||||
|
||||
static enum ath9k_pkt_type get_hw_packet_type(struct io_buffer *iob)
|
||||
{
|
||||
struct ieee80211_frame *hdr;
|
||||
enum ath9k_pkt_type htype;
|
||||
u16 fc;
|
||||
|
||||
hdr = (struct ieee80211_frame *)iob->data;
|
||||
fc = hdr->fc;
|
||||
|
||||
if ((fc & (IEEE80211_FC_TYPE | IEEE80211_FC_SUBTYPE)) == (IEEE80211_TYPE_MGMT | IEEE80211_STYPE_BEACON))
|
||||
htype = ATH9K_PKT_TYPE_BEACON;
|
||||
else if ((fc & (IEEE80211_FC_TYPE | IEEE80211_FC_SUBTYPE)) == (IEEE80211_TYPE_MGMT | IEEE80211_STYPE_PROBE_RESP))
|
||||
htype = ATH9K_PKT_TYPE_PROBE_RESP;
|
||||
else
|
||||
htype = ATH9K_PKT_TYPE_NORMAL;
|
||||
|
||||
return htype;
|
||||
}
|
||||
|
||||
static int setup_tx_flags(struct io_buffer *iob __unused)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
flags |= ATH9K_TXDESC_INTREQ;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_channel *curchan = ah->curchan;
|
||||
if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
|
||||
(curchan->channelFlags & CHANNEL_5GHZ) &&
|
||||
(chainmask == 0x7) && (rate < 0x90))
|
||||
return 0x3;
|
||||
else
|
||||
return chainmask;
|
||||
}
|
||||
|
||||
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath9k_11n_rate_series series[4];
|
||||
const struct ath9k_legacy_rate *rate;
|
||||
int i, flags = 0;
|
||||
u8 rix = 0, ctsrate = 0;
|
||||
int is_pspoll;
|
||||
|
||||
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
|
||||
|
||||
is_pspoll = 0;
|
||||
|
||||
/*
|
||||
* We check if Short Preamble is needed for the CTS rate by
|
||||
* checking the BSS's global flag.
|
||||
* But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
|
||||
*/
|
||||
rate = &sc->rates[sc->hw_rix];
|
||||
ctsrate = rate->hw_value;
|
||||
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
|
||||
ctsrate |= rate->hw_value_short;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int is_40 __unused, is_sgi __unused, is_sp;
|
||||
int phy;
|
||||
|
||||
rix = sc->hw_rix;
|
||||
series[i].Tries = ATH_TXMAXTRY;
|
||||
|
||||
if (sc->sc_flags & SC_OP_PROTECT_ENABLE) {
|
||||
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
|
||||
flags |= ATH9K_TXDESC_CTSENA;
|
||||
}
|
||||
|
||||
is_sp = !!(rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
|
||||
|
||||
/* legacy rates */
|
||||
if ((sc->dev->channels + sc->dev->channel)->band == NET80211_BAND_2GHZ)
|
||||
phy = CHANNEL_CCK;
|
||||
else
|
||||
phy = CHANNEL_OFDM;
|
||||
|
||||
series[i].Rate = rate->hw_value;
|
||||
if (rate->hw_value_short && (sc->sc_flags & SC_OP_PREAMBLE_SHORT)) {
|
||||
if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
|
||||
series[i].Rate |= rate->hw_value_short;
|
||||
} else {
|
||||
is_sp = 0;
|
||||
}
|
||||
|
||||
if (bf->bf_state.bfs_paprd)
|
||||
series[i].ChSel = common->tx_chainmask;
|
||||
else
|
||||
series[i].ChSel = ath_txchainmask_reduction(sc,
|
||||
common->tx_chainmask, series[i].Rate);
|
||||
|
||||
series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
|
||||
phy, rate->bitrate * 100, len, rix, is_sp);
|
||||
}
|
||||
|
||||
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
|
||||
if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
|
||||
flags &= ~ATH9K_TXDESC_RTSENA;
|
||||
|
||||
/* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
|
||||
if (flags & ATH9K_TXDESC_RTSENA)
|
||||
flags &= ~ATH9K_TXDESC_CTSENA;
|
||||
|
||||
/* set dur_update_en for l-sig computation except for PS-Poll frames */
|
||||
ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
|
||||
bf->bf_lastbf->bf_desc,
|
||||
!is_pspoll, ctsrate,
|
||||
0, series, 4, flags);
|
||||
|
||||
}
|
||||
|
||||
static struct ath_buf *ath_tx_setup_buffer(struct net80211_device *dev,
|
||||
struct ath_txq *txq,
|
||||
struct io_buffer *iob)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_buf *bf;
|
||||
struct ath_desc *ds;
|
||||
int frm_type;
|
||||
static const enum ath9k_key_type net80211_keytype_to_ath[] = {
|
||||
[NET80211_CRYPT_NONE] = ATH9K_KEY_TYPE_CLEAR,
|
||||
[NET80211_CRYPT_WEP] = ATH9K_KEY_TYPE_WEP,
|
||||
[NET80211_CRYPT_TKIP] = ATH9K_KEY_TYPE_TKIP,
|
||||
[NET80211_CRYPT_CCMP] = ATH9K_KEY_TYPE_AES,
|
||||
[NET80211_CRYPT_UNKNOWN] = ATH9K_KEY_TYPE_CLEAR,
|
||||
};
|
||||
|
||||
bf = ath_tx_get_buffer(sc);
|
||||
if (!bf) {
|
||||
DBG("ath9k: TX buffers are full\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATH_TXBUF_RESET(bf);
|
||||
|
||||
bf->bf_flags = setup_tx_flags(iob);
|
||||
bf->bf_mpdu = iob;
|
||||
|
||||
bf->bf_buf_addr = virt_to_bus(iob->data);
|
||||
|
||||
frm_type = get_hw_packet_type(iob);
|
||||
|
||||
ds = bf->bf_desc;
|
||||
ath9k_hw_set_desc_link(ah, ds, 0);
|
||||
|
||||
ath9k_hw_set11n_txdesc(ah, ds, iob_len(iob) + FCS_LEN, frm_type, MAX_RATE_POWER,
|
||||
ATH9K_TXKEYIX_INVALID, net80211_keytype_to_ath[dev->crypto->algorithm], bf->bf_flags);
|
||||
|
||||
ath9k_hw_filltxdesc(ah, ds,
|
||||
iob_len(iob), /* segment length */
|
||||
1, /* first segment */
|
||||
1, /* last segment */
|
||||
ds, /* first descriptor */
|
||||
bf->bf_buf_addr,
|
||||
txq->axq_qnum);
|
||||
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
/* FIXME: tx power */
|
||||
static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct list_head bf_head;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_add_tail(&bf->list, &bf_head);
|
||||
|
||||
bf->bf_state.bfs_paprd = txctl->paprd;
|
||||
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC;
|
||||
|
||||
ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, 1);
|
||||
|
||||
ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
|
||||
}
|
||||
|
||||
/* Upon failure caller should free iob */
|
||||
int ath_tx_start(struct net80211_device *dev, struct io_buffer *iob,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ath_softc *sc = dev->priv;
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_buf *bf;
|
||||
int q;
|
||||
|
||||
/*
|
||||
* At this point, the vif, hw_key and sta pointers in the tx control
|
||||
* info are no longer valid (overwritten by the ath_frame_info data.
|
||||
*/
|
||||
|
||||
bf = ath_tx_setup_buffer(dev, txctl->txq, iob);
|
||||
if (!bf)
|
||||
return -ENOMEM;
|
||||
|
||||
q = 0;
|
||||
if (txq == sc->tx.txq_map[q] &&
|
||||
++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
|
||||
txq->stopped = 1;
|
||||
}
|
||||
|
||||
ath_tx_start_dma(sc, bf, txctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/* TX Completion */
|
||||
/*****************/
|
||||
|
||||
static void ath_tx_complete(struct ath_softc *sc, struct io_buffer *iob,
|
||||
int tx_flags __unused, struct ath_tx_status *ts, struct ath_txq *txq)
|
||||
{
|
||||
struct net80211_device *dev = sc->dev;
|
||||
int q, padpos __unused, padsize __unused;
|
||||
|
||||
DBGIO("ath9k: TX complete: iob: %p\n", iob);
|
||||
|
||||
q = 0;
|
||||
if (txq == sc->tx.txq_map[q]) {
|
||||
if (--txq->pending_frames < 0)
|
||||
txq->pending_frames = 0;
|
||||
|
||||
if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
|
||||
txq->stopped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
net80211_tx_complete(dev, iob, ts->ts_longretry,
|
||||
(ts->ts_status & ATH9K_TXERR_MASK) ? EIO : 0);
|
||||
}
|
||||
|
||||
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_txq *txq, struct list_head *bf_q,
|
||||
struct ath_tx_status *ts, int txok, int sendbar)
|
||||
{
|
||||
struct io_buffer *iob = bf->bf_mpdu;
|
||||
int tx_flags = 0;
|
||||
|
||||
if (sendbar)
|
||||
tx_flags = ATH_TX_BAR;
|
||||
|
||||
if (!txok) {
|
||||
tx_flags |= ATH_TX_ERROR;
|
||||
|
||||
if (bf_isxretried(bf))
|
||||
tx_flags |= ATH_TX_XRETRY;
|
||||
}
|
||||
|
||||
bf->bf_buf_addr = 0;
|
||||
|
||||
ath_tx_complete(sc, iob, tx_flags,
|
||||
ts, txq);
|
||||
|
||||
/* At this point, iob (bf->bf_mpdu) is consumed...make sure we don't
|
||||
* accidentally reference it later.
|
||||
*/
|
||||
bf->bf_mpdu = NULL;
|
||||
|
||||
/*
|
||||
* Return the list of ath_buf of this mpdu to free queue
|
||||
*/
|
||||
list_splice_tail_init(bf_q, &sc->tx.txbuf);
|
||||
}
|
||||
|
||||
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_buf *bf, *lastbf, *bf_held = NULL;
|
||||
struct list_head bf_head;
|
||||
struct ath_desc *ds;
|
||||
struct ath_tx_status ts;
|
||||
int txok;
|
||||
int status;
|
||||
|
||||
DBGIO("ath9k: tx queue %d (%x), link %p\n",
|
||||
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||
txq->axq_link);
|
||||
|
||||
for (;;) {
|
||||
if (list_empty(&txq->axq_q)) {
|
||||
txq->axq_link = NULL;
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
break;
|
||||
}
|
||||
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
|
||||
|
||||
/*
|
||||
* There is a race condition that a BH gets scheduled
|
||||
* after sw writes TxE and before hw re-load the last
|
||||
* descriptor to get the newly chained one.
|
||||
* Software must keep the last DONE descriptor as a
|
||||
* holding descriptor - software does so by marking
|
||||
* it with the STALE flag.
|
||||
*/
|
||||
bf_held = NULL;
|
||||
if (bf->bf_stale) {
|
||||
bf_held = bf;
|
||||
if (list_is_last(&bf_held->list, &txq->axq_q)) {
|
||||
break;
|
||||
} else {
|
||||
bf = list_entry(bf_held->list.next,
|
||||
struct ath_buf, list);
|
||||
}
|
||||
}
|
||||
|
||||
lastbf = bf->bf_lastbf;
|
||||
ds = lastbf->bf_desc;
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
status = ath9k_hw_txprocdesc(ah, ds, &ts);
|
||||
if (status == -EINPROGRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove ath_buf's of the same transmit unit from txq,
|
||||
* however leave the last descriptor back as the holding
|
||||
* descriptor for hw.
|
||||
*/
|
||||
lastbf->bf_stale = 1;
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
if (!list_is_singular(&lastbf->list))
|
||||
list_cut_position(&bf_head,
|
||||
&txq->axq_q, lastbf->list.prev);
|
||||
|
||||
txq->axq_depth--;
|
||||
txok = !(ts.ts_status & ATH9K_TXERR_MASK);
|
||||
txq->axq_tx_inprogress = 0;
|
||||
if (bf_held)
|
||||
list_del(&bf_held->list);
|
||||
|
||||
if (bf_held)
|
||||
ath_tx_return_buffer(sc, bf_held);
|
||||
|
||||
/*
|
||||
* This frame is sent out as a single frame.
|
||||
* Use hardware retry status for this frame.
|
||||
*/
|
||||
if (ts.ts_status & ATH9K_TXERR_XRETRY)
|
||||
bf->bf_state.bf_type |= BUF_XRETRY;
|
||||
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
|
||||
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_tx_complete_poll_work(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_txq *txq;
|
||||
int i;
|
||||
int needreset = 0;
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i)) {
|
||||
txq = &sc->tx.txq[i];
|
||||
if (txq->axq_depth) {
|
||||
if (txq->axq_tx_inprogress) {
|
||||
needreset = 1;
|
||||
break;
|
||||
} else {
|
||||
txq->axq_tx_inprogress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needreset) {
|
||||
DBG("ath9k: "
|
||||
"tx hung, resetting the chip\n");
|
||||
ath_reset(sc, 1);
|
||||
}
|
||||
|
||||
sc->tx_complete_work_timer = ( currticks() * 1000 ) / TICKS_PER_SEC + ATH_TX_COMPLETE_POLL_INT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ath_tx_tasklet(struct ath_softc *sc)
|
||||
{
|
||||
int i;
|
||||
u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
|
||||
|
||||
ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
|
||||
ath_tx_processq(sc, &sc->tx.txq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/* Init, Cleanup */
|
||||
/*****************/
|
||||
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
|
||||
"tx", nbufs, 1, 1);
|
||||
if (error != 0) {
|
||||
DBG("ath9k: "
|
||||
"Failed to allocate tx descriptors: %d\n", error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
sc->tx_complete_work = ath_tx_complete_poll_work;
|
||||
|
||||
err:
|
||||
if (error != 0)
|
||||
ath_tx_cleanup(sc);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void ath_tx_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
if (sc->tx.txdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
|
||||
}
|
||||
115
src/drivers/net/ath/ath9k/calib.h
Normal file
115
src/drivers/net/ath/ath9k/calib.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CALIB_H
|
||||
#define CALIB_H
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
|
||||
#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
|
||||
|
||||
#define NUM_NF_READINGS 6
|
||||
#define ATH9K_NF_CAL_HIST_MAX 5
|
||||
|
||||
struct ar5416IniArray {
|
||||
u32 *ia_array;
|
||||
u32 ia_rows;
|
||||
u32 ia_columns;
|
||||
};
|
||||
|
||||
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
|
||||
(iniarray)->ia_array = (u32 *)(array); \
|
||||
(iniarray)->ia_rows = (rows); \
|
||||
(iniarray)->ia_columns = (columns); \
|
||||
} while (0)
|
||||
|
||||
#define INI_RA(iniarray, row, column) \
|
||||
(((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
|
||||
|
||||
#define INIT_CAL(_perCal) do { \
|
||||
(_perCal)->calState = CAL_WAITING; \
|
||||
(_perCal)->calNext = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define INSERT_CAL(_ahp, _perCal) \
|
||||
do { \
|
||||
if ((_ahp)->cal_list_last == NULL) { \
|
||||
(_ahp)->cal_list = \
|
||||
(_ahp)->cal_list_last = (_perCal); \
|
||||
((_ahp)->cal_list_last)->calNext = (_perCal); \
|
||||
} else { \
|
||||
((_ahp)->cal_list_last)->calNext = (_perCal); \
|
||||
(_ahp)->cal_list_last = (_perCal); \
|
||||
(_perCal)->calNext = (_ahp)->cal_list; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
enum ath9k_cal_state {
|
||||
CAL_INACTIVE,
|
||||
CAL_WAITING,
|
||||
CAL_RUNNING,
|
||||
CAL_DONE
|
||||
};
|
||||
|
||||
#define MIN_CAL_SAMPLES 1
|
||||
#define MAX_CAL_SAMPLES 64
|
||||
#define INIT_LOG_COUNT 5
|
||||
#define PER_MIN_LOG_COUNT 2
|
||||
#define PER_MAX_LOG_COUNT 10
|
||||
|
||||
struct ath9k_percal_data {
|
||||
u32 calType;
|
||||
u32 calNumSamples;
|
||||
u32 calCountMax;
|
||||
void (*calCollect) (struct ath_hw *);
|
||||
void (*calPostProc) (struct ath_hw *, u8);
|
||||
};
|
||||
|
||||
struct ath9k_cal_list {
|
||||
const struct ath9k_percal_data *calData;
|
||||
enum ath9k_cal_state calState;
|
||||
struct ath9k_cal_list *calNext;
|
||||
};
|
||||
|
||||
struct ath9k_nfcal_hist {
|
||||
int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
|
||||
u8 currIndex;
|
||||
int16_t privNF;
|
||||
u8 invalidNFcount;
|
||||
};
|
||||
|
||||
#define MAX_PACAL_SKIPCOUNT 8
|
||||
struct ath9k_pacal_info{
|
||||
int32_t prev_offset; /* Previous value of PA offset value */
|
||||
int8_t max_skipcount; /* Max No. of times PACAL can be skipped */
|
||||
int8_t skipcount; /* No. of times the PACAL to be skipped */
|
||||
};
|
||||
|
||||
int ath9k_hw_reset_calvalid(struct ath_hw *ah);
|
||||
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update);
|
||||
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
void ath9k_hw_reset_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal);
|
||||
|
||||
|
||||
#endif /* CALIB_H */
|
||||
56
src/drivers/net/ath/ath9k/common.h
Normal file
56
src/drivers/net/ath/ath9k/common.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../ath.h"
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw-ops.h"
|
||||
|
||||
/* Common header for Atheros 802.11n base driver cores */
|
||||
|
||||
#define WME_NUM_TID 16
|
||||
#define WME_BA_BMP_SIZE 64
|
||||
#define WME_MAX_BA WME_BA_BMP_SIZE
|
||||
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
|
||||
|
||||
#define WME_AC_BE 2
|
||||
#define WME_NUM_AC 1
|
||||
|
||||
#define ATH_RSSI_DUMMY_MARKER 0x127
|
||||
#define ATH_RSSI_LPF_LEN 10
|
||||
#define RSSI_LPF_THRESHOLD -20
|
||||
#define ATH_RSSI_EP_MULTIPLIER (1<<7)
|
||||
#define ATH_EP_MUL(x, mul) ((x) * (mul))
|
||||
#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
|
||||
#define ATH_LPF_RSSI(x, y, len) \
|
||||
((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
|
||||
#define ATH_RSSI_LPF(x, y) do { \
|
||||
if ((y) >= RSSI_LPF_THRESHOLD) \
|
||||
x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
|
||||
} while (0)
|
||||
#define ATH_EP_RND(x, mul) \
|
||||
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
|
||||
|
||||
|
||||
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
|
||||
struct net80211_channel *chan);
|
||||
struct ath9k_channel *ath9k_cmn_get_curchannel(struct net80211_device *dev,
|
||||
struct ath_hw *ah);
|
||||
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
|
||||
u16 new_txpow, u16 *txpower);
|
||||
714
src/drivers/net/ath/ath9k/eeprom.h
Normal file
714
src/drivers/net/ath/ath9k/eeprom.h
Normal file
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EEPROM_H
|
||||
#define EEPROM_H
|
||||
|
||||
#define AR_EEPROM_MODAL_SPURS 5
|
||||
|
||||
#include "../ath.h"
|
||||
#include "ar9003_eeprom.h"
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define AR5416_EEPROM_MAGIC 0x5aa5
|
||||
#else
|
||||
#define AR5416_EEPROM_MAGIC 0xa55a
|
||||
#endif
|
||||
|
||||
#define CTRY_DEBUG 0x1ff
|
||||
#define CTRY_DEFAULT 0
|
||||
|
||||
#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001
|
||||
#define AR_EEPROM_EEPCAP_AES_DIS 0x0002
|
||||
#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004
|
||||
#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008
|
||||
#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0
|
||||
#define AR_EEPROM_EEPCAP_MAXQCU_S 4
|
||||
#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200
|
||||
#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000
|
||||
#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12
|
||||
|
||||
#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800
|
||||
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000
|
||||
#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
|
||||
|
||||
#define AR5416_EEPROM_MAGIC_OFFSET 0x0
|
||||
#define AR5416_EEPROM_S 2
|
||||
#define AR5416_EEPROM_OFFSET 0x2000
|
||||
#define AR5416_EEPROM_MAX 0xae0
|
||||
|
||||
#define AR5416_EEPROM_START_ADDR \
|
||||
(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
|
||||
|
||||
#define SD_NO_CTL 0xE0
|
||||
#define NO_CTL 0xff
|
||||
#define CTL_MODE_M 0xf
|
||||
#define CTL_11A 0
|
||||
#define CTL_11B 1
|
||||
#define CTL_11G 2
|
||||
#define CTL_2GHT20 5
|
||||
#define CTL_5GHT20 6
|
||||
#define CTL_2GHT40 7
|
||||
#define CTL_5GHT40 8
|
||||
|
||||
#define EXT_ADDITIVE (0x8000)
|
||||
#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
|
||||
#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
|
||||
#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
|
||||
|
||||
#define SUB_NUM_CTL_MODES_AT_5G_40 2
|
||||
#define SUB_NUM_CTL_MODES_AT_2G_40 3
|
||||
|
||||
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
|
||||
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
|
||||
|
||||
/*
|
||||
* For AR9285 and later chipsets, the following bits are not being programmed
|
||||
* in EEPROM and so need to be enabled always.
|
||||
*
|
||||
* Bit 0: en_fcc_mid
|
||||
* Bit 1: en_jap_mid
|
||||
* Bit 2: en_fcc_dfs_ht40
|
||||
* Bit 3: en_jap_ht40
|
||||
* Bit 4: en_jap_dfs_ht40
|
||||
*/
|
||||
#define AR9285_RDEXT_DEFAULT 0x1F
|
||||
|
||||
#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
|
||||
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
|
||||
#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
|
||||
|
||||
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
|
||||
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
|
||||
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
|
||||
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||
|
||||
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
|
||||
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
|
||||
#define AR_EEPROM_RFSILENT_POLARITY 0x0002
|
||||
#define AR_EEPROM_RFSILENT_POLARITY_S 1
|
||||
|
||||
#define EEP_RFSILENT_ENABLED 0x0001
|
||||
#define EEP_RFSILENT_ENABLED_S 0
|
||||
#define EEP_RFSILENT_POLARITY 0x0002
|
||||
#define EEP_RFSILENT_POLARITY_S 1
|
||||
#define EEP_RFSILENT_GPIO_SEL 0x001c
|
||||
#define EEP_RFSILENT_GPIO_SEL_S 2
|
||||
|
||||
#define AR5416_OPFLAGS_11A 0x01
|
||||
#define AR5416_OPFLAGS_11G 0x02
|
||||
#define AR5416_OPFLAGS_N_5G_HT40 0x04
|
||||
#define AR5416_OPFLAGS_N_2G_HT40 0x08
|
||||
#define AR5416_OPFLAGS_N_5G_HT20 0x10
|
||||
#define AR5416_OPFLAGS_N_2G_HT20 0x20
|
||||
|
||||
#define AR5416_EEP_NO_BACK_VER 0x1
|
||||
#define AR5416_EEP_VER 0xE
|
||||
#define AR5416_EEP_VER_MINOR_MASK 0x0FFF
|
||||
#define AR5416_EEP_MINOR_VER_2 0x2
|
||||
#define AR5416_EEP_MINOR_VER_3 0x3
|
||||
#define AR5416_EEP_MINOR_VER_7 0x7
|
||||
#define AR5416_EEP_MINOR_VER_9 0x9
|
||||
#define AR5416_EEP_MINOR_VER_16 0x10
|
||||
#define AR5416_EEP_MINOR_VER_17 0x11
|
||||
#define AR5416_EEP_MINOR_VER_19 0x13
|
||||
#define AR5416_EEP_MINOR_VER_20 0x14
|
||||
#define AR5416_EEP_MINOR_VER_21 0x15
|
||||
#define AR5416_EEP_MINOR_VER_22 0x16
|
||||
|
||||
#define AR5416_NUM_5G_CAL_PIERS 8
|
||||
#define AR5416_NUM_2G_CAL_PIERS 4
|
||||
#define AR5416_NUM_5G_20_TARGET_POWERS 8
|
||||
#define AR5416_NUM_5G_40_TARGET_POWERS 8
|
||||
#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
|
||||
#define AR5416_NUM_2G_20_TARGET_POWERS 4
|
||||
#define AR5416_NUM_2G_40_TARGET_POWERS 4
|
||||
#define AR5416_NUM_CTLS 24
|
||||
#define AR5416_NUM_BAND_EDGES 8
|
||||
#define AR5416_NUM_PD_GAINS 4
|
||||
#define AR5416_PD_GAINS_IN_MASK 4
|
||||
#define AR5416_PD_GAIN_ICEPTS 5
|
||||
#define AR5416_NUM_PDADC_VALUES 128
|
||||
#define AR5416_BCHAN_UNUSED 0xFF
|
||||
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
|
||||
#define AR5416_MAX_CHAINS 3
|
||||
#define AR9300_MAX_CHAINS 3
|
||||
#define AR5416_PWR_TABLE_OFFSET_DB -5
|
||||
|
||||
/* Rx gain type values */
|
||||
#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
|
||||
#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
|
||||
#define AR5416_EEP_RXGAIN_ORIG 2
|
||||
|
||||
/* Tx gain type values */
|
||||
#define AR5416_EEP_TXGAIN_ORIGINAL 0
|
||||
#define AR5416_EEP_TXGAIN_HIGH_POWER 1
|
||||
|
||||
#define AR5416_EEP4K_START_LOC 64
|
||||
#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
|
||||
#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
|
||||
#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
|
||||
#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
|
||||
#define AR5416_EEP4K_NUM_CTLS 12
|
||||
#define AR5416_EEP4K_NUM_BAND_EDGES 4
|
||||
#define AR5416_EEP4K_NUM_PD_GAINS 2
|
||||
#define AR5416_EEP4K_MAX_CHAINS 1
|
||||
|
||||
#define AR9280_TX_GAIN_TABLE_SIZE 22
|
||||
|
||||
#define AR9287_EEP_VER 0xE
|
||||
#define AR9287_EEP_VER_MINOR_MASK 0xFFF
|
||||
#define AR9287_EEP_MINOR_VER_1 0x1
|
||||
#define AR9287_EEP_MINOR_VER_2 0x2
|
||||
#define AR9287_EEP_MINOR_VER_3 0x3
|
||||
#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3
|
||||
#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER
|
||||
#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1
|
||||
|
||||
#define AR9287_EEP_START_LOC 128
|
||||
#define AR9287_HTC_EEP_START_LOC 256
|
||||
#define AR9287_NUM_2G_CAL_PIERS 3
|
||||
#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
|
||||
#define AR9287_NUM_2G_20_TARGET_POWERS 3
|
||||
#define AR9287_NUM_2G_40_TARGET_POWERS 3
|
||||
#define AR9287_NUM_CTLS 12
|
||||
#define AR9287_NUM_BAND_EDGES 4
|
||||
#define AR9287_PD_GAIN_ICEPTS 1
|
||||
#define AR9287_EEPMISC_BIG_ENDIAN 0x01
|
||||
#define AR9287_EEPMISC_WOW 0x02
|
||||
#define AR9287_MAX_CHAINS 2
|
||||
#define AR9287_ANT_16S 32
|
||||
|
||||
#define AR9287_DATA_SZ 32
|
||||
|
||||
#define AR9287_PWR_TABLE_OFFSET_DB -5
|
||||
|
||||
#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
|
||||
|
||||
#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
|
||||
#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
|
||||
|
||||
#define LNA_CTL_BUF_MODE BIT(0)
|
||||
#define LNA_CTL_ISEL_LO BIT(1)
|
||||
#define LNA_CTL_ISEL_HI BIT(2)
|
||||
#define LNA_CTL_BUF_IN BIT(3)
|
||||
#define LNA_CTL_FEM_BAND BIT(4)
|
||||
#define LNA_CTL_LOCAL_BIAS BIT(5)
|
||||
#define LNA_CTL_FORCE_XPA BIT(6)
|
||||
#define LNA_CTL_USE_ANT1 BIT(7)
|
||||
|
||||
enum eeprom_param {
|
||||
EEP_NFTHRESH_5,
|
||||
EEP_NFTHRESH_2,
|
||||
EEP_MAC_MSW,
|
||||
EEP_MAC_MID,
|
||||
EEP_MAC_LSW,
|
||||
EEP_REG_0,
|
||||
EEP_REG_1,
|
||||
EEP_OP_CAP,
|
||||
EEP_OP_MODE,
|
||||
EEP_RF_SILENT,
|
||||
EEP_OB_5,
|
||||
EEP_DB_5,
|
||||
EEP_OB_2,
|
||||
EEP_DB_2,
|
||||
EEP_MINOR_REV,
|
||||
EEP_TX_MASK,
|
||||
EEP_RX_MASK,
|
||||
EEP_FSTCLK_5G,
|
||||
EEP_RXGAIN_TYPE,
|
||||
EEP_OL_PWRCTRL,
|
||||
EEP_TXGAIN_TYPE,
|
||||
EEP_RC_CHAIN_MASK,
|
||||
EEP_DAC_HPWR_5G,
|
||||
EEP_FRAC_N_5G,
|
||||
EEP_DEV_TYPE,
|
||||
EEP_TEMPSENSE_SLOPE,
|
||||
EEP_TEMPSENSE_SLOPE_PAL_ON,
|
||||
EEP_PWR_TABLE_OFFSET,
|
||||
EEP_DRIVE_STRENGTH,
|
||||
EEP_INTERNAL_REGULATOR,
|
||||
EEP_SWREG,
|
||||
EEP_PAPRD,
|
||||
EEP_MODAL_VER,
|
||||
EEP_ANT_DIV_CTL1,
|
||||
EEP_CHAIN_MASK_REDUCE
|
||||
};
|
||||
|
||||
enum ar5416_rates {
|
||||
rate6mb, rate9mb, rate12mb, rate18mb,
|
||||
rate24mb, rate36mb, rate48mb, rate54mb,
|
||||
rate1l, rate2l, rate2s, rate5_5l,
|
||||
rate5_5s, rate11l, rate11s, rateXr,
|
||||
rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
|
||||
rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
|
||||
rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
|
||||
rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
|
||||
rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
|
||||
Ar5416RateSize
|
||||
};
|
||||
|
||||
enum ath9k_hal_freq_band {
|
||||
ATH9K_HAL_FREQ_BAND_5GHZ = 0,
|
||||
ATH9K_HAL_FREQ_BAND_2GHZ = 1
|
||||
};
|
||||
|
||||
struct base_eep_header {
|
||||
u16 length;
|
||||
u16 checksum;
|
||||
u16 version;
|
||||
u8 opCapFlags;
|
||||
u8 eepMisc;
|
||||
u16 regDmn[2];
|
||||
u8 macAddr[6];
|
||||
u8 rxMask;
|
||||
u8 txMask;
|
||||
u16 rfSilent;
|
||||
u16 blueToothOptions;
|
||||
u16 deviceCap;
|
||||
u32 binBuildNumber;
|
||||
u8 deviceType;
|
||||
u8 pwdclkind;
|
||||
u8 fastClk5g;
|
||||
u8 divChain;
|
||||
u8 rxGainType;
|
||||
u8 dacHiPwrMode_5G;
|
||||
u8 openLoopPwrCntl;
|
||||
u8 dacLpMode;
|
||||
u8 txGainType;
|
||||
u8 rcChainMask;
|
||||
u8 desiredScaleCCK;
|
||||
u8 pwr_table_offset;
|
||||
u8 frac_n_5g;
|
||||
u8 futureBase_3[21];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct base_eep_header_4k {
|
||||
u16 length;
|
||||
u16 checksum;
|
||||
u16 version;
|
||||
u8 opCapFlags;
|
||||
u8 eepMisc;
|
||||
u16 regDmn[2];
|
||||
u8 macAddr[6];
|
||||
u8 rxMask;
|
||||
u8 txMask;
|
||||
u16 rfSilent;
|
||||
u16 blueToothOptions;
|
||||
u16 deviceCap;
|
||||
u32 binBuildNumber;
|
||||
u8 deviceType;
|
||||
u8 txGainType;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct spur_chan {
|
||||
u16 spurChan;
|
||||
u8 spurRangeLow;
|
||||
u8 spurRangeHigh;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct modal_eep_header {
|
||||
u32 antCtrlChain[AR5416_MAX_CHAINS];
|
||||
u32 antCtrlCommon;
|
||||
u8 antennaGainCh[AR5416_MAX_CHAINS];
|
||||
u8 switchSettling;
|
||||
u8 txRxAttenCh[AR5416_MAX_CHAINS];
|
||||
u8 rxTxMarginCh[AR5416_MAX_CHAINS];
|
||||
u8 adcDesiredSize;
|
||||
u8 pgaDesiredSize;
|
||||
u8 xlnaGainCh[AR5416_MAX_CHAINS];
|
||||
u8 txEndToXpaOff;
|
||||
u8 txEndToRxOn;
|
||||
u8 txFrameToXpaOn;
|
||||
u8 thresh62;
|
||||
u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
|
||||
u8 xpdGain;
|
||||
u8 xpd;
|
||||
u8 iqCalICh[AR5416_MAX_CHAINS];
|
||||
u8 iqCalQCh[AR5416_MAX_CHAINS];
|
||||
u8 pdGainOverlap;
|
||||
u8 ob;
|
||||
u8 db;
|
||||
u8 xpaBiasLvl;
|
||||
u8 pwrDecreaseFor2Chain;
|
||||
u8 pwrDecreaseFor3Chain;
|
||||
u8 txFrameToDataStart;
|
||||
u8 txFrameToPaOn;
|
||||
u8 ht40PowerIncForPdadc;
|
||||
u8 bswAtten[AR5416_MAX_CHAINS];
|
||||
u8 bswMargin[AR5416_MAX_CHAINS];
|
||||
u8 swSettleHt40;
|
||||
u8 xatten2Db[AR5416_MAX_CHAINS];
|
||||
u8 xatten2Margin[AR5416_MAX_CHAINS];
|
||||
u8 ob_ch1;
|
||||
u8 db_ch1;
|
||||
u8 lna_ctl;
|
||||
u8 miscBits;
|
||||
u16 xpaBiasLvlFreq[3];
|
||||
u8 futureModal[6];
|
||||
|
||||
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct calDataPerFreqOpLoop {
|
||||
u8 pwrPdg[2][5];
|
||||
u8 vpdPdg[2][5];
|
||||
u8 pcdac[2][5];
|
||||
u8 empty[2][5];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct modal_eep_4k_header {
|
||||
u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
|
||||
u32 antCtrlCommon;
|
||||
u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 switchSettling;
|
||||
u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 adcDesiredSize;
|
||||
u8 pgaDesiredSize;
|
||||
u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 txEndToXpaOff;
|
||||
u8 txEndToRxOn;
|
||||
u8 txFrameToXpaOn;
|
||||
u8 thresh62;
|
||||
u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 xpdGain;
|
||||
u8 xpd;
|
||||
u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 pdGainOverlap;
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
u8 ob_1:4, ob_0:4;
|
||||
u8 db1_1:4, db1_0:4;
|
||||
#else
|
||||
u8 ob_0:4, ob_1:4;
|
||||
u8 db1_0:4, db1_1:4;
|
||||
#endif
|
||||
u8 xpaBiasLvl;
|
||||
u8 txFrameToDataStart;
|
||||
u8 txFrameToPaOn;
|
||||
u8 ht40PowerIncForPdadc;
|
||||
u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 swSettleHt40;
|
||||
u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
|
||||
u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
u8 db2_1:4, db2_0:4;
|
||||
#else
|
||||
u8 db2_0:4, db2_1:4;
|
||||
#endif
|
||||
u8 version;
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
u8 ob_3:4, ob_2:4;
|
||||
u8 antdiv_ctl1:4, ob_4:4;
|
||||
u8 db1_3:4, db1_2:4;
|
||||
u8 antdiv_ctl2:4, db1_4:4;
|
||||
u8 db2_2:4, db2_3:4;
|
||||
u8 reserved:4, db2_4:4;
|
||||
#else
|
||||
u8 ob_2:4, ob_3:4;
|
||||
u8 ob_4:4, antdiv_ctl1:4;
|
||||
u8 db1_2:4, db1_3:4;
|
||||
u8 db1_4:4, antdiv_ctl2:4;
|
||||
u8 db2_2:4, db2_3:4;
|
||||
u8 db2_4:4, reserved:4;
|
||||
#endif
|
||||
u8 tx_diversity;
|
||||
u8 flc_pwr_thresh;
|
||||
u8 bb_scale_smrt_antenna;
|
||||
#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f
|
||||
u8 futureModal[1];
|
||||
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct base_eep_ar9287_header {
|
||||
u16 length;
|
||||
u16 checksum;
|
||||
u16 version;
|
||||
u8 opCapFlags;
|
||||
u8 eepMisc;
|
||||
u16 regDmn[2];
|
||||
u8 macAddr[6];
|
||||
u8 rxMask;
|
||||
u8 txMask;
|
||||
u16 rfSilent;
|
||||
u16 blueToothOptions;
|
||||
u16 deviceCap;
|
||||
u32 binBuildNumber;
|
||||
u8 deviceType;
|
||||
u8 openLoopPwrCntl;
|
||||
int8_t pwrTableOffset;
|
||||
int8_t tempSensSlope;
|
||||
int8_t tempSensSlopePalOn;
|
||||
u8 futureBase[29];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct modal_eep_ar9287_header {
|
||||
u32 antCtrlChain[AR9287_MAX_CHAINS];
|
||||
u32 antCtrlCommon;
|
||||
int8_t antennaGainCh[AR9287_MAX_CHAINS];
|
||||
u8 switchSettling;
|
||||
u8 txRxAttenCh[AR9287_MAX_CHAINS];
|
||||
u8 rxTxMarginCh[AR9287_MAX_CHAINS];
|
||||
int8_t adcDesiredSize;
|
||||
u8 txEndToXpaOff;
|
||||
u8 txEndToRxOn;
|
||||
u8 txFrameToXpaOn;
|
||||
u8 thresh62;
|
||||
int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
|
||||
u8 xpdGain;
|
||||
u8 xpd;
|
||||
int8_t iqCalICh[AR9287_MAX_CHAINS];
|
||||
int8_t iqCalQCh[AR9287_MAX_CHAINS];
|
||||
u8 pdGainOverlap;
|
||||
u8 xpaBiasLvl;
|
||||
u8 txFrameToDataStart;
|
||||
u8 txFrameToPaOn;
|
||||
u8 ht40PowerIncForPdadc;
|
||||
u8 bswAtten[AR9287_MAX_CHAINS];
|
||||
u8 bswMargin[AR9287_MAX_CHAINS];
|
||||
u8 swSettleHt40;
|
||||
u8 version;
|
||||
u8 db1;
|
||||
u8 db2;
|
||||
u8 ob_cck;
|
||||
u8 ob_psk;
|
||||
u8 ob_qam;
|
||||
u8 ob_pal_off;
|
||||
u8 futureModal[30];
|
||||
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_data_per_freq {
|
||||
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_data_per_freq_4k {
|
||||
u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_target_power_leg {
|
||||
u8 bChannel;
|
||||
u8 tPow2x[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_target_power_ht {
|
||||
u8 bChannel;
|
||||
u8 tPow2x[8];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_edges {
|
||||
u8 bChannel;
|
||||
u8 ctl;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_data_op_loop_ar9287 {
|
||||
u8 pwrPdg[2][5];
|
||||
u8 vpdPdg[2][5];
|
||||
u8 pcdac[2][5];
|
||||
u8 empty[2][5];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_data_per_freq_ar9287 {
|
||||
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
|
||||
u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
|
||||
} __attribute__((packed));
|
||||
|
||||
union cal_data_per_freq_ar9287_u {
|
||||
struct cal_data_op_loop_ar9287 calDataOpen;
|
||||
struct cal_data_per_freq_ar9287 calDataClose;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_data_ar9287 {
|
||||
struct cal_ctl_edges
|
||||
ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_data {
|
||||
struct cal_ctl_edges
|
||||
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cal_ctl_data_4k {
|
||||
struct cal_ctl_edges
|
||||
ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar5416_eeprom_def {
|
||||
struct base_eep_header baseEepHeader;
|
||||
u8 custData[64];
|
||||
struct modal_eep_header modalHeader[2];
|
||||
u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
|
||||
u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
|
||||
struct cal_data_per_freq
|
||||
calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
|
||||
struct cal_data_per_freq
|
||||
calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
|
||||
u8 ctlIndex[AR5416_NUM_CTLS];
|
||||
struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
|
||||
u8 padding;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar5416_eeprom_4k {
|
||||
struct base_eep_header_4k baseEepHeader;
|
||||
u8 custData[20];
|
||||
struct modal_eep_4k_header modalHeader;
|
||||
u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
|
||||
struct cal_data_per_freq_4k
|
||||
calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
|
||||
u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
|
||||
struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
|
||||
u8 padding;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ar9287_eeprom {
|
||||
struct base_eep_ar9287_header baseEepHeader;
|
||||
u8 custData[AR9287_DATA_SZ];
|
||||
struct modal_eep_ar9287_header modalHeader;
|
||||
u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
|
||||
union cal_data_per_freq_ar9287_u
|
||||
calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
|
||||
struct cal_target_power_leg
|
||||
calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
|
||||
struct cal_target_power_ht
|
||||
calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
|
||||
u8 ctlIndex[AR9287_NUM_CTLS];
|
||||
struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
|
||||
u8 padding;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum reg_ext_bitmap {
|
||||
REG_EXT_FCC_MIDBAND = 0,
|
||||
REG_EXT_JAPAN_MIDBAND = 1,
|
||||
REG_EXT_FCC_DFS_HT40 = 2,
|
||||
REG_EXT_JAPAN_NONDFS_HT40 = 3,
|
||||
REG_EXT_JAPAN_DFS_HT40 = 4
|
||||
};
|
||||
|
||||
struct ath9k_country_entry {
|
||||
u16 countryCode;
|
||||
u16 regDmnEnum;
|
||||
u16 regDmn5G;
|
||||
u16 regDmn2G;
|
||||
u8 isMultidomain;
|
||||
u8 iso[3];
|
||||
};
|
||||
|
||||
struct eeprom_ops {
|
||||
int (*check_eeprom)(struct ath_hw *hw);
|
||||
u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
|
||||
int (*fill_eeprom)(struct ath_hw *hw);
|
||||
int (*get_eeprom_ver)(struct ath_hw *hw);
|
||||
int (*get_eeprom_rev)(struct ath_hw *hw);
|
||||
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
|
||||
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
|
||||
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
|
||||
u16 cfgCtl, u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower, u8 powerLimit,
|
||||
int test);
|
||||
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, int is2GHz);
|
||||
};
|
||||
|
||||
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
|
||||
void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
|
||||
u32 shift, u32 val);
|
||||
int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
|
||||
int16_t targetLeft,
|
||||
int16_t targetRight);
|
||||
int ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
||||
u16 *indexL, u16 *indexR);
|
||||
int ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
|
||||
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
|
||||
int eep_start_loc, int size);
|
||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||
u8 *pVpdList, u16 numIntercepts,
|
||||
u8 *pRetVpdList);
|
||||
void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_leg *powInfo,
|
||||
u16 numChannels,
|
||||
struct cal_target_power_leg *pNewPower,
|
||||
u16 numRates, int isExtTarget);
|
||||
void ath9k_hw_get_target_powers(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_ht *powInfo,
|
||||
u16 numChannels,
|
||||
struct cal_target_power_ht *pNewPower,
|
||||
u16 numRates, int isHt40Target);
|
||||
u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
|
||||
int is2GHz, int num_band_edges);
|
||||
void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah);
|
||||
|
||||
void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
void *pRawDataSet,
|
||||
u8 *bChans, u16 availPiers,
|
||||
u16 tPdGainOverlap,
|
||||
u16 *pPdGainBoundaries, u8 *pPDADCValues,
|
||||
u16 numXpdGains);
|
||||
|
||||
#define ar5416_get_ntxchains(_txchainmask) \
|
||||
(((_txchainmask >> 2) & 1) + \
|
||||
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
|
||||
|
||||
extern const struct eeprom_ops eep_def_ops;
|
||||
extern const struct eeprom_ops eep_4k_ops;
|
||||
extern const struct eeprom_ops eep_ar9287_ops;
|
||||
extern const struct eeprom_ops eep_ar9287_ops;
|
||||
extern const struct eeprom_ops eep_ar9300_ops;
|
||||
|
||||
#endif /* EEPROM_H */
|
||||
268
src/drivers/net/ath/ath9k/hw-ops.h
Normal file
268
src/drivers/net/ath/ath9k/hw-ops.h
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH9K_HW_OPS_H
|
||||
#define ATH9K_HW_OPS_H
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
/* Hardware core and driver accessible callbacks */
|
||||
|
||||
static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
|
||||
int restore,
|
||||
int power_off)
|
||||
{
|
||||
ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_rxena(struct ath_hw *ah)
|
||||
{
|
||||
ath9k_hw_ops(ah)->rx_enable(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
|
||||
u32 link)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set_desc_link(ds, link);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
|
||||
u32 **link)
|
||||
{
|
||||
ath9k_hw_ops(ah)->get_desc_link(ds, link);
|
||||
}
|
||||
static inline int ath9k_hw_calibrate(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 rxchainmask,
|
||||
int longcal)
|
||||
{
|
||||
return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
{
|
||||
return ath9k_hw_ops(ah)->get_isr(ah, masked);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
|
||||
int is_firstseg, int is_lastseg,
|
||||
const void *ds0, u32 buf_addr,
|
||||
unsigned int qcu)
|
||||
{
|
||||
ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
|
||||
ds0, buf_addr, qcu);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type,
|
||||
u32 txPower, u32 keyIx,
|
||||
enum ath9k_key_type keyType,
|
||||
u32 flags)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
|
||||
keyType, flags);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
|
||||
void *lastds,
|
||||
u32 durUpdateEn, u32 rtsctsRate,
|
||||
u32 rtsctsDuration,
|
||||
struct ath9k_11n_rate_series series[],
|
||||
u32 nseries, u32 flags)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
|
||||
rtsctsRate, rtsctsDuration, series,
|
||||
nseries, flags);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
|
||||
u32 aggrLen)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
|
||||
u32 numDelims)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
|
||||
{
|
||||
ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, int val)
|
||||
{
|
||||
ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf)
|
||||
{
|
||||
ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf)
|
||||
{
|
||||
ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf);
|
||||
}
|
||||
|
||||
/* Private hardware call ops */
|
||||
|
||||
/* PHY ops */
|
||||
|
||||
static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks)
|
||||
return 0;
|
||||
|
||||
return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks)
|
||||
return;
|
||||
|
||||
ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_set_rf_regs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u16 modesIndex)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->set_rf_regs)
|
||||
return 1;
|
||||
|
||||
return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_bb(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->init_bb(ah, chan);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_process_ini(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->process_ini(ah, chan);
|
||||
}
|
||||
|
||||
static inline void ath9k_olc_init(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->olc_init)
|
||||
return;
|
||||
|
||||
return ath9k_hw_private_ops(ah)->olc_init(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_rfmode(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_rfbus_req(struct ath_hw *ah)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->rfbus_req(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_rfbus_done(struct ath_hw *ah)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->rfbus_done(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->restore_chainmask)
|
||||
return;
|
||||
|
||||
return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_set_diversity(struct ath_hw *ah, int value)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_ani_control(struct ath_hw *ah,
|
||||
enum ath9k_ani_cmd cmd, int param)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nfarray[NUM_NF_READINGS])
|
||||
{
|
||||
ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_init_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
return ath9k_hw_private_ops(ah)->init_cal(ah, chan);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
|
||||
}
|
||||
|
||||
#endif /* ATH9K_HW_OPS_H */
|
||||
995
src/drivers/net/ath/ath9k/hw.h
Normal file
995
src/drivers/net/ath/ath9k/hw.h
Normal file
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HW_H
|
||||
#define HW_H
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "mac.h"
|
||||
#include "ani.h"
|
||||
#include "eeprom.h"
|
||||
#include "calib.h"
|
||||
#include "reg.h"
|
||||
#include "phy.h"
|
||||
|
||||
#include "../regd.h"
|
||||
|
||||
/* Keep all ath9k files under one errfile ID */
|
||||
#undef ERRFILE
|
||||
#define ERRFILE ERRFILE_ath9k
|
||||
|
||||
#define ATHEROS_VENDOR_ID 0x168c
|
||||
|
||||
#define AR5416_DEVID_PCI 0x0023
|
||||
#define AR5416_DEVID_PCIE 0x0024
|
||||
#define AR9160_DEVID_PCI 0x0027
|
||||
#define AR9280_DEVID_PCI 0x0029
|
||||
#define AR9280_DEVID_PCIE 0x002a
|
||||
#define AR9285_DEVID_PCIE 0x002b
|
||||
#define AR2427_DEVID_PCIE 0x002c
|
||||
#define AR9287_DEVID_PCI 0x002d
|
||||
#define AR9287_DEVID_PCIE 0x002e
|
||||
#define AR9300_DEVID_PCIE 0x0030
|
||||
#define AR9300_DEVID_AR9340 0x0031
|
||||
#define AR9300_DEVID_AR9485_PCIE 0x0032
|
||||
|
||||
#define AR5416_AR9100_DEVID 0x000b
|
||||
|
||||
#define AR_SUBVENDOR_ID_NOG 0x0e11
|
||||
#define AR_SUBVENDOR_ID_NEW_A 0x7065
|
||||
#define AR5416_MAGIC 0x19641014
|
||||
|
||||
#define AR9280_COEX2WIRE_SUBSYSID 0x309b
|
||||
#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
|
||||
#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
|
||||
|
||||
#define AR9300_NUM_BT_WEIGHTS 4
|
||||
#define AR9300_NUM_WLAN_WEIGHTS 4
|
||||
|
||||
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
|
||||
|
||||
#define ATH_DEFAULT_NOISE_FLOOR -95
|
||||
|
||||
#define ATH9K_RSSI_BAD -128
|
||||
|
||||
#define ATH9K_NUM_CHANNELS 38
|
||||
|
||||
/* Register read/write primitives */
|
||||
#define REG_WRITE(_ah, _reg, _val) \
|
||||
(_ah)->reg_ops.write((_ah), (_val), (_reg))
|
||||
|
||||
#define REG_READ(_ah, _reg) \
|
||||
(_ah)->reg_ops.read((_ah), (_reg))
|
||||
|
||||
#define REG_READ_MULTI(_ah, _addr, _val, _cnt) \
|
||||
(_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt))
|
||||
|
||||
#define REG_RMW(_ah, _reg, _set, _clr) \
|
||||
(_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr))
|
||||
|
||||
#define ENABLE_REGWRITE_BUFFER(_ah) \
|
||||
do { \
|
||||
if ((_ah)->reg_ops.enable_write_buffer) \
|
||||
(_ah)->reg_ops.enable_write_buffer((_ah)); \
|
||||
} while (0)
|
||||
|
||||
#define REGWRITE_BUFFER_FLUSH(_ah) \
|
||||
do { \
|
||||
if ((_ah)->reg_ops.write_flush) \
|
||||
(_ah)->reg_ops.write_flush((_ah)); \
|
||||
} while (0)
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_S) & _f)
|
||||
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
|
||||
#define REG_RMW_FIELD(_a, _r, _f, _v) \
|
||||
REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f))
|
||||
#define REG_READ_FIELD(_a, _r, _f) \
|
||||
(((REG_READ(_a, _r) & _f) >> _f##_S))
|
||||
#define REG_SET_BIT(_a, _r, _f) \
|
||||
REG_RMW(_a, _r, (_f), 0)
|
||||
#define REG_CLR_BIT(_a, _r, _f) \
|
||||
REG_RMW(_a, _r, 0, (_f))
|
||||
|
||||
#define DO_DELAY(x) do { \
|
||||
if (((++(x) % 64) == 0) && \
|
||||
(ath9k_hw_common(ah)->bus_ops->ath_bus_type \
|
||||
!= ATH_USB)) \
|
||||
udelay(1); \
|
||||
} while (0)
|
||||
|
||||
#define REG_WRITE_ARRAY(iniarray, column, regWr) \
|
||||
ath9k_hw_write_array(ah, iniarray, column, &(regWr))
|
||||
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
||||
|
||||
#define AR_GPIOD_MASK 0x00001FFF
|
||||
#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
|
||||
|
||||
#define BASE_ACTIVATE_DELAY 100
|
||||
#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100)
|
||||
#define COEF_SCALE_S 24
|
||||
#define HT40_CHANNEL_CENTER_SHIFT 10
|
||||
|
||||
#define ATH9K_ANTENNA0_CHAINMASK 0x1
|
||||
#define ATH9K_ANTENNA1_CHAINMASK 0x2
|
||||
|
||||
#define ATH9K_NUM_DMA_DEBUG_REGS 8
|
||||
#define ATH9K_NUM_QUEUES 10
|
||||
|
||||
#define MAX_RATE_POWER 63
|
||||
#define AH_WAIT_TIMEOUT 100000 /* (us) */
|
||||
#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
|
||||
#define AH_TIME_QUANTUM 10
|
||||
#define AR_KEYTABLE_SIZE 128
|
||||
#define POWER_UP_TIME 10000
|
||||
#define SPUR_RSSI_THRESH 40
|
||||
|
||||
#define CAB_TIMEOUT_VAL 10
|
||||
#define BEACON_TIMEOUT_VAL 10
|
||||
#define MIN_BEACON_TIMEOUT_VAL 1
|
||||
#define SLEEP_SLOP 3
|
||||
|
||||
#define INIT_CONFIG_STATUS 0x00000000
|
||||
#define INIT_RSSI_THR 0x00000700
|
||||
#define INIT_BCON_CNTRL_REG 0x00000000
|
||||
|
||||
#define TU_TO_USEC(_tu) ((_tu) << 10)
|
||||
|
||||
#define ATH9K_HW_RX_HP_QDEPTH 16
|
||||
#define ATH9K_HW_RX_LP_QDEPTH 128
|
||||
|
||||
#define PAPRD_GAIN_TABLE_ENTRIES 32
|
||||
#define PAPRD_TABLE_SZ 24
|
||||
|
||||
enum ath_hw_txq_subtype {
|
||||
ATH_TXQ_AC_BE = 0,
|
||||
};
|
||||
|
||||
enum ath_ini_subsys {
|
||||
ATH_INI_PRE = 0,
|
||||
ATH_INI_CORE,
|
||||
ATH_INI_POST,
|
||||
ATH_INI_NUM_SPLIT,
|
||||
};
|
||||
|
||||
enum ath9k_hw_caps {
|
||||
ATH9K_HW_CAP_HT = BIT(0),
|
||||
ATH9K_HW_CAP_RFSILENT = BIT(1),
|
||||
ATH9K_HW_CAP_CST = BIT(2),
|
||||
ATH9K_HW_CAP_AUTOSLEEP = BIT(4),
|
||||
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5),
|
||||
ATH9K_HW_CAP_EDMA = BIT(6),
|
||||
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7),
|
||||
ATH9K_HW_CAP_LDPC = BIT(8),
|
||||
ATH9K_HW_CAP_FASTCLOCK = BIT(9),
|
||||
ATH9K_HW_CAP_SGI_20 = BIT(10),
|
||||
ATH9K_HW_CAP_PAPRD = BIT(11),
|
||||
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
|
||||
ATH9K_HW_CAP_2GHZ = BIT(13),
|
||||
ATH9K_HW_CAP_5GHZ = BIT(14),
|
||||
ATH9K_HW_CAP_APM = BIT(15),
|
||||
};
|
||||
|
||||
struct ath9k_hw_capabilities {
|
||||
u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
|
||||
u16 rts_aggr_limit;
|
||||
u8 tx_chainmask;
|
||||
u8 rx_chainmask;
|
||||
u8 max_txchains;
|
||||
u8 max_rxchains;
|
||||
u8 num_gpio_pins;
|
||||
u8 rx_hp_qdepth;
|
||||
u8 rx_lp_qdepth;
|
||||
u8 rx_status_len;
|
||||
u8 tx_desc_len;
|
||||
u8 txs_len;
|
||||
u16 pcie_lcr_offset;
|
||||
int pcie_lcr_extsync_en;
|
||||
};
|
||||
|
||||
struct ath9k_ops_config {
|
||||
int dma_beacon_response_time;
|
||||
int sw_beacon_response_time;
|
||||
int additional_swba_backoff;
|
||||
int ack_6mb;
|
||||
u32 cwm_ignore_extcca;
|
||||
u8 pcie_powersave_enable;
|
||||
int pcieSerDesWrite;
|
||||
u8 pcie_clock_req;
|
||||
u32 pcie_waen;
|
||||
u8 analog_shiftreg;
|
||||
u8 paprd_disable;
|
||||
u32 ofdm_trig_low;
|
||||
u32 ofdm_trig_high;
|
||||
u32 cck_trig_high;
|
||||
u32 cck_trig_low;
|
||||
u32 enable_ani;
|
||||
int serialize_regmode;
|
||||
int rx_intr_mitigation;
|
||||
int tx_intr_mitigation;
|
||||
#define SPUR_DISABLE 0
|
||||
#define SPUR_ENABLE_IOCTL 1
|
||||
#define SPUR_ENABLE_EEPROM 2
|
||||
#define AR_SPUR_5413_1 1640
|
||||
#define AR_SPUR_5413_2 1200
|
||||
#define AR_NO_SPUR 0x8000
|
||||
#define AR_BASE_FREQ_2GHZ 2300
|
||||
#define AR_BASE_FREQ_5GHZ 4900
|
||||
#define AR_SPUR_FEEQ_BOUND_HT40 19
|
||||
#define AR_SPUR_FEEQ_BOUND_HT20 10
|
||||
int spurmode;
|
||||
u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
|
||||
u8 max_txtrig_level;
|
||||
u16 ani_poll_interval; /* ANI poll interval in ms */
|
||||
};
|
||||
|
||||
enum ath9k_int {
|
||||
ATH9K_INT_RX = 0x00000001,
|
||||
ATH9K_INT_RXDESC = 0x00000002,
|
||||
ATH9K_INT_RXHP = 0x00000001,
|
||||
ATH9K_INT_RXLP = 0x00000002,
|
||||
ATH9K_INT_RXNOFRM = 0x00000008,
|
||||
ATH9K_INT_RXEOL = 0x00000010,
|
||||
ATH9K_INT_RXORN = 0x00000020,
|
||||
ATH9K_INT_TX = 0x00000040,
|
||||
ATH9K_INT_TXDESC = 0x00000080,
|
||||
ATH9K_INT_TIM_TIMER = 0x00000100,
|
||||
ATH9K_INT_BB_WATCHDOG = 0x00000400,
|
||||
ATH9K_INT_TXURN = 0x00000800,
|
||||
ATH9K_INT_MIB = 0x00001000,
|
||||
ATH9K_INT_RXPHY = 0x00004000,
|
||||
ATH9K_INT_RXKCM = 0x00008000,
|
||||
ATH9K_INT_SWBA = 0x00010000,
|
||||
ATH9K_INT_BMISS = 0x00040000,
|
||||
ATH9K_INT_BNR = 0x00100000,
|
||||
ATH9K_INT_TIM = 0x00200000,
|
||||
ATH9K_INT_DTIM = 0x00400000,
|
||||
ATH9K_INT_DTIMSYNC = 0x00800000,
|
||||
ATH9K_INT_GPIO = 0x01000000,
|
||||
ATH9K_INT_CABEND = 0x02000000,
|
||||
ATH9K_INT_TSFOOR = 0x04000000,
|
||||
ATH9K_INT_GENTIMER = 0x08000000,
|
||||
ATH9K_INT_CST = 0x10000000,
|
||||
ATH9K_INT_GTT = 0x20000000,
|
||||
ATH9K_INT_FATAL = 0x40000000,
|
||||
ATH9K_INT_GLOBAL = 0x80000000,
|
||||
ATH9K_INT_BMISC = ATH9K_INT_TIM |
|
||||
ATH9K_INT_DTIM |
|
||||
ATH9K_INT_DTIMSYNC |
|
||||
ATH9K_INT_TSFOOR |
|
||||
ATH9K_INT_CABEND,
|
||||
ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
|
||||
ATH9K_INT_RXDESC |
|
||||
ATH9K_INT_RXEOL |
|
||||
ATH9K_INT_RXORN |
|
||||
ATH9K_INT_TXURN |
|
||||
ATH9K_INT_TXDESC |
|
||||
ATH9K_INT_MIB |
|
||||
ATH9K_INT_RXPHY |
|
||||
ATH9K_INT_RXKCM |
|
||||
ATH9K_INT_SWBA |
|
||||
ATH9K_INT_BMISS |
|
||||
ATH9K_INT_GPIO,
|
||||
ATH9K_INT_NOCARD = 0xffffffff
|
||||
};
|
||||
|
||||
#define CHANNEL_CW_INT 0x00002
|
||||
#define CHANNEL_CCK 0x00020
|
||||
#define CHANNEL_OFDM 0x00040
|
||||
#define CHANNEL_2GHZ 0x00080
|
||||
#define CHANNEL_5GHZ 0x00100
|
||||
#define CHANNEL_PASSIVE 0x00200
|
||||
#define CHANNEL_DYN 0x00400
|
||||
#define CHANNEL_HALF 0x04000
|
||||
#define CHANNEL_QUARTER 0x08000
|
||||
#define CHANNEL_HT20 0x10000
|
||||
#define CHANNEL_HT40PLUS 0x20000
|
||||
#define CHANNEL_HT40MINUS 0x40000
|
||||
|
||||
#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
|
||||
#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
|
||||
#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
|
||||
#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20)
|
||||
#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20)
|
||||
#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
|
||||
#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
|
||||
#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
|
||||
#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
|
||||
#define CHANNEL_ALL \
|
||||
(CHANNEL_OFDM| \
|
||||
CHANNEL_CCK| \
|
||||
CHANNEL_2GHZ | \
|
||||
CHANNEL_5GHZ | \
|
||||
CHANNEL_HT20 | \
|
||||
CHANNEL_HT40PLUS | \
|
||||
CHANNEL_HT40MINUS)
|
||||
|
||||
struct ath9k_hw_cal_data {
|
||||
u16 channel;
|
||||
u32 channelFlags;
|
||||
int32_t CalValid;
|
||||
int8_t iCoff;
|
||||
int8_t qCoff;
|
||||
int paprd_done;
|
||||
int nfcal_pending;
|
||||
int nfcal_interference;
|
||||
u16 small_signal_gain[AR9300_MAX_CHAINS];
|
||||
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
};
|
||||
|
||||
struct ath9k_channel {
|
||||
struct net80211_channel *chan;
|
||||
struct ar5416AniState ani;
|
||||
u16 channel;
|
||||
u32 channelFlags;
|
||||
u32 chanmode;
|
||||
s16 noisefloor;
|
||||
};
|
||||
|
||||
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
|
||||
#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
|
||||
#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
|
||||
#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
|
||||
#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
|
||||
#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
|
||||
#define IS_CHAN_A_FAST_CLOCK(_ah, _c) \
|
||||
((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
|
||||
((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))
|
||||
|
||||
/* These macros check chanmode and not channelFlags */
|
||||
#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
|
||||
#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
|
||||
((_c)->chanmode == CHANNEL_G_HT20))
|
||||
#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
|
||||
((_c)->chanmode == CHANNEL_A_HT40MINUS) || \
|
||||
((_c)->chanmode == CHANNEL_G_HT40PLUS) || \
|
||||
((_c)->chanmode == CHANNEL_G_HT40MINUS))
|
||||
#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
|
||||
|
||||
enum ath9k_power_mode {
|
||||
ATH9K_PM_AWAKE = 0,
|
||||
ATH9K_PM_FULL_SLEEP,
|
||||
ATH9K_PM_NETWORK_SLEEP,
|
||||
ATH9K_PM_UNDEFINED
|
||||
};
|
||||
|
||||
enum ath9k_tp_scale {
|
||||
ATH9K_TP_SCALE_MAX = 0,
|
||||
ATH9K_TP_SCALE_50,
|
||||
ATH9K_TP_SCALE_25,
|
||||
ATH9K_TP_SCALE_12,
|
||||
ATH9K_TP_SCALE_MIN
|
||||
};
|
||||
|
||||
enum ser_reg_mode {
|
||||
SER_REG_MODE_OFF = 0,
|
||||
SER_REG_MODE_ON = 1,
|
||||
SER_REG_MODE_AUTO = 2,
|
||||
};
|
||||
|
||||
enum ath9k_rx_qtype {
|
||||
ATH9K_RX_QUEUE_HP,
|
||||
ATH9K_RX_QUEUE_LP,
|
||||
ATH9K_RX_QUEUE_MAX,
|
||||
};
|
||||
|
||||
struct ath9k_beacon_state {
|
||||
u32 bs_nexttbtt;
|
||||
u32 bs_nextdtim;
|
||||
u32 bs_intval;
|
||||
#define ATH9K_BEACON_PERIOD 0x0000ffff
|
||||
#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */
|
||||
u32 bs_dtimperiod;
|
||||
u16 bs_cfpperiod;
|
||||
u16 bs_cfpmaxduration;
|
||||
u32 bs_cfpnext;
|
||||
u16 bs_timoffset;
|
||||
u16 bs_bmissthreshold;
|
||||
u32 bs_sleepduration;
|
||||
u32 bs_tsfoor_threshold;
|
||||
};
|
||||
|
||||
struct chan_centers {
|
||||
u16 synth_center;
|
||||
u16 ctl_center;
|
||||
u16 ext_center;
|
||||
};
|
||||
|
||||
enum {
|
||||
ATH9K_RESET_POWER_ON,
|
||||
ATH9K_RESET_WARM,
|
||||
ATH9K_RESET_COLD,
|
||||
};
|
||||
|
||||
struct ath9k_hw_version {
|
||||
u32 magic;
|
||||
u16 devid;
|
||||
u16 subvendorid;
|
||||
u32 macVersion;
|
||||
u16 macRev;
|
||||
u16 phyRev;
|
||||
u16 analog5GhzRev;
|
||||
u16 analog2GhzRev;
|
||||
u16 subsysid;
|
||||
enum ath_usb_dev usbdev;
|
||||
};
|
||||
|
||||
/* Generic TSF timer definitions */
|
||||
|
||||
#define ATH_MAX_GEN_TIMER 16
|
||||
|
||||
#define AR_GENTMR_BIT(_index) (1 << (_index))
|
||||
|
||||
/*
|
||||
* Using de Bruijin sequence to look up 1's index in a 32 bit number
|
||||
* debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
|
||||
*/
|
||||
#define debruijn32 0x077CB531U
|
||||
|
||||
struct ath_gen_timer_configuration {
|
||||
u32 next_addr;
|
||||
u32 period_addr;
|
||||
u32 mode_addr;
|
||||
u32 mode_mask;
|
||||
};
|
||||
|
||||
struct ath_gen_timer {
|
||||
void (*trigger)(void *arg);
|
||||
void (*overflow)(void *arg);
|
||||
void *arg;
|
||||
u8 index;
|
||||
};
|
||||
|
||||
struct ath_gen_timer_table {
|
||||
u32 gen_timer_index[32];
|
||||
struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
|
||||
union {
|
||||
unsigned long timer_bits;
|
||||
u16 val;
|
||||
} timer_mask;
|
||||
};
|
||||
|
||||
struct ath_hw_antcomb_conf {
|
||||
u8 main_lna_conf;
|
||||
u8 alt_lna_conf;
|
||||
u8 fast_div_bias;
|
||||
u8 main_gaintb;
|
||||
u8 alt_gaintb;
|
||||
int lna1_lna2_delta;
|
||||
u8 div_group;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_hw_radar_conf - radar detection initialization parameters
|
||||
*
|
||||
* @pulse_inband: threshold for checking the ratio of in-band power
|
||||
* to total power for short radar pulses (half dB steps)
|
||||
* @pulse_inband_step: threshold for checking an in-band power to total
|
||||
* power ratio increase for short radar pulses (half dB steps)
|
||||
* @pulse_height: threshold for detecting the beginning of a short
|
||||
* radar pulse (dB step)
|
||||
* @pulse_rssi: threshold for detecting if a short radar pulse is
|
||||
* gone (dB step)
|
||||
* @pulse_maxlen: maximum pulse length (0.8 us steps)
|
||||
*
|
||||
* @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
|
||||
* @radar_inband: threshold for checking the ratio of in-band power
|
||||
* to total power for long radar pulses (half dB steps)
|
||||
* @fir_power: threshold for detecting the end of a long radar pulse (dB)
|
||||
*
|
||||
* @ext_channel: enable extension channel radar detection
|
||||
*/
|
||||
struct ath_hw_radar_conf {
|
||||
unsigned int pulse_inband;
|
||||
unsigned int pulse_inband_step;
|
||||
unsigned int pulse_height;
|
||||
unsigned int pulse_rssi;
|
||||
unsigned int pulse_maxlen;
|
||||
|
||||
unsigned int radar_rssi;
|
||||
unsigned int radar_inband;
|
||||
int fir_power;
|
||||
|
||||
int ext_channel;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_hw_private_ops - callbacks used internally by hardware code
|
||||
*
|
||||
* This structure contains private callbacks designed to only be used internally
|
||||
* by the hardware core.
|
||||
*
|
||||
* @init_cal_settings: setup types of calibrations supported
|
||||
* @init_cal: starts actual calibration
|
||||
*
|
||||
* @init_mode_regs: Initializes mode registers
|
||||
* @init_mode_gain_regs: Initialize TX/RX gain registers
|
||||
*
|
||||
* @rf_set_freq: change frequency
|
||||
* @spur_mitigate_freq: spur mitigation
|
||||
* @rf_alloc_ext_banks:
|
||||
* @rf_free_ext_banks:
|
||||
* @set_rf_regs:
|
||||
* @compute_pll_control: compute the PLL control value to use for
|
||||
* AR_RTC_PLL_CONTROL for a given channel
|
||||
* @setup_calibration: set up calibration
|
||||
* @iscal_supported: used to query if a type of calibration is supported
|
||||
*
|
||||
* @ani_cache_ini_regs: cache the values for ANI from the initial
|
||||
* register settings through the register initialization.
|
||||
*/
|
||||
struct ath_hw_private_ops {
|
||||
/* Calibration ops */
|
||||
void (*init_cal_settings)(struct ath_hw *ah);
|
||||
int (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
||||
void (*init_mode_regs)(struct ath_hw *ah);
|
||||
void (*init_mode_gain_regs)(struct ath_hw *ah);
|
||||
void (*setup_calibration)(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal);
|
||||
|
||||
/* PHY ops */
|
||||
int (*rf_set_freq)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
void (*spur_mitigate_freq)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int (*rf_alloc_ext_banks)(struct ath_hw *ah);
|
||||
void (*rf_free_ext_banks)(struct ath_hw *ah);
|
||||
int (*set_rf_regs)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u16 modesIndex);
|
||||
void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
void (*init_bb)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
void (*olc_init)(struct ath_hw *ah);
|
||||
void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
void (*mark_phy_inactive)(struct ath_hw *ah);
|
||||
void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
int (*rfbus_req)(struct ath_hw *ah);
|
||||
void (*rfbus_done)(struct ath_hw *ah);
|
||||
void (*restore_chainmask)(struct ath_hw *ah);
|
||||
void (*set_diversity)(struct ath_hw *ah, int value);
|
||||
u32 (*compute_pll_control)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
|
||||
int param);
|
||||
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
|
||||
void (*set_radar_params)(struct ath_hw *ah,
|
||||
struct ath_hw_radar_conf *conf);
|
||||
|
||||
/* ANI */
|
||||
void (*ani_cache_ini_regs)(struct ath_hw *ah);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_hw_ops - callbacks used by hardware code and driver code
|
||||
*
|
||||
* This structure contains callbacks designed to to be used internally by
|
||||
* hardware code and also by the lower level driver.
|
||||
*
|
||||
* @config_pci_powersave:
|
||||
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
|
||||
*/
|
||||
struct ath_hw_ops {
|
||||
void (*config_pci_powersave)(struct ath_hw *ah,
|
||||
int restore,
|
||||
int power_off);
|
||||
void (*rx_enable)(struct ath_hw *ah);
|
||||
void (*set_desc_link)(void *ds, u32 link);
|
||||
void (*get_desc_link)(void *ds, u32 **link);
|
||||
int (*calibrate)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 rxchainmask,
|
||||
int longcal);
|
||||
int (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
|
||||
void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
|
||||
int is_firstseg, int is_is_lastseg,
|
||||
const void *ds0, u32 buf_addr,
|
||||
unsigned int qcu);
|
||||
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts);
|
||||
void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type,
|
||||
u32 txPower, u32 keyIx,
|
||||
enum ath9k_key_type keyType,
|
||||
u32 flags);
|
||||
void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
|
||||
void *lastds,
|
||||
u32 durUpdateEn, u32 rtsctsRate,
|
||||
u32 rtsctsDuration,
|
||||
struct ath9k_11n_rate_series series[],
|
||||
u32 nseries, u32 flags);
|
||||
void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
|
||||
u32 aggrLen);
|
||||
void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
|
||||
u32 numDelims);
|
||||
void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
|
||||
void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
|
||||
void (*set_clrdmask)(struct ath_hw *ah, void *ds, int val);
|
||||
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf);
|
||||
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf);
|
||||
|
||||
};
|
||||
|
||||
struct ath_nf_limits {
|
||||
s16 max;
|
||||
s16 min;
|
||||
s16 nominal;
|
||||
};
|
||||
|
||||
/* ah_flags */
|
||||
#define AH_USE_EEPROM 0x1
|
||||
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
|
||||
|
||||
struct ath_hw {
|
||||
struct ath_ops reg_ops;
|
||||
|
||||
struct net80211_device *dev;
|
||||
struct ath_common common;
|
||||
struct ath9k_hw_version hw_version;
|
||||
struct ath9k_ops_config config;
|
||||
struct ath9k_hw_capabilities caps;
|
||||
struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
|
||||
struct ath9k_channel *curchan;
|
||||
|
||||
union {
|
||||
struct ar5416_eeprom_def def;
|
||||
struct ar5416_eeprom_4k map4k;
|
||||
struct ar9287_eeprom map9287;
|
||||
struct ar9300_eeprom ar9300_eep;
|
||||
} eeprom;
|
||||
const struct eeprom_ops *eep_ops;
|
||||
|
||||
int sw_mgmt_crypto;
|
||||
int is_pciexpress;
|
||||
int is_monitoring;
|
||||
int need_an_top2_fixup;
|
||||
u16 tx_trig_level;
|
||||
|
||||
u32 nf_regs[6];
|
||||
struct ath_nf_limits nf_2g;
|
||||
struct ath_nf_limits nf_5g;
|
||||
u16 rfsilent;
|
||||
u32 rfkill_gpio;
|
||||
u32 rfkill_polarity;
|
||||
u32 ah_flags;
|
||||
|
||||
int htc_reset_init;
|
||||
|
||||
enum ath9k_power_mode power_mode;
|
||||
|
||||
struct ath9k_hw_cal_data *caldata;
|
||||
struct ath9k_pacal_info pacal_info;
|
||||
struct ar5416Stats stats;
|
||||
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
|
||||
|
||||
int16_t curchan_rad_index;
|
||||
int ah_ier;
|
||||
enum ath9k_int imask;
|
||||
u32 imrs2_reg;
|
||||
u32 txok_interrupt_mask;
|
||||
u32 txerr_interrupt_mask;
|
||||
u32 txdesc_interrupt_mask;
|
||||
u32 txeol_interrupt_mask;
|
||||
u32 txurn_interrupt_mask;
|
||||
int chip_fullsleep;
|
||||
u32 atim_window;
|
||||
|
||||
/* Calibration */
|
||||
u32 supp_cals;
|
||||
struct ath9k_cal_list iq_caldata;
|
||||
struct ath9k_cal_list adcgain_caldata;
|
||||
struct ath9k_cal_list adcdc_caldata;
|
||||
struct ath9k_cal_list tempCompCalData;
|
||||
struct ath9k_cal_list *cal_list;
|
||||
struct ath9k_cal_list *cal_list_last;
|
||||
struct ath9k_cal_list *cal_list_curr;
|
||||
#define totalPowerMeasI meas0.unsign
|
||||
#define totalPowerMeasQ meas1.unsign
|
||||
#define totalIqCorrMeas meas2.sign
|
||||
#define totalAdcIOddPhase meas0.unsign
|
||||
#define totalAdcIEvenPhase meas1.unsign
|
||||
#define totalAdcQOddPhase meas2.unsign
|
||||
#define totalAdcQEvenPhase meas3.unsign
|
||||
#define totalAdcDcOffsetIOddPhase meas0.sign
|
||||
#define totalAdcDcOffsetIEvenPhase meas1.sign
|
||||
#define totalAdcDcOffsetQOddPhase meas2.sign
|
||||
#define totalAdcDcOffsetQEvenPhase meas3.sign
|
||||
union {
|
||||
u32 unsign[AR5416_MAX_CHAINS];
|
||||
int32_t sign[AR5416_MAX_CHAINS];
|
||||
} meas0;
|
||||
union {
|
||||
u32 unsign[AR5416_MAX_CHAINS];
|
||||
int32_t sign[AR5416_MAX_CHAINS];
|
||||
} meas1;
|
||||
union {
|
||||
u32 unsign[AR5416_MAX_CHAINS];
|
||||
int32_t sign[AR5416_MAX_CHAINS];
|
||||
} meas2;
|
||||
union {
|
||||
u32 unsign[AR5416_MAX_CHAINS];
|
||||
int32_t sign[AR5416_MAX_CHAINS];
|
||||
} meas3;
|
||||
u16 cal_samples;
|
||||
|
||||
u32 sta_id1_defaults;
|
||||
u32 misc_mode;
|
||||
enum {
|
||||
AUTO_32KHZ,
|
||||
USE_32KHZ,
|
||||
DONT_USE_32KHZ,
|
||||
} enable_32kHz_clock;
|
||||
|
||||
/* Private to hardware code */
|
||||
struct ath_hw_private_ops private_ops;
|
||||
/* Accessed by the lower level driver */
|
||||
struct ath_hw_ops ops;
|
||||
|
||||
/* Used to program the radio on non single-chip devices */
|
||||
u32 *analogBank0Data;
|
||||
u32 *analogBank1Data;
|
||||
u32 *analogBank2Data;
|
||||
u32 *analogBank3Data;
|
||||
u32 *analogBank6Data;
|
||||
u32 *analogBank6TPCData;
|
||||
u32 *analogBank7Data;
|
||||
u32 *addac5416_21;
|
||||
u32 *bank6Temp;
|
||||
|
||||
u8 txpower_limit;
|
||||
int coverage_class;
|
||||
u32 slottime;
|
||||
u32 globaltxtimeout;
|
||||
|
||||
/* ANI */
|
||||
u32 proc_phyerr;
|
||||
u32 aniperiod;
|
||||
int totalSizeDesired[5];
|
||||
int coarse_high[5];
|
||||
int coarse_low[5];
|
||||
int firpwr[5];
|
||||
enum ath9k_ani_cmd ani_function;
|
||||
|
||||
u32 intr_txqs;
|
||||
u8 txchainmask;
|
||||
u8 rxchainmask;
|
||||
|
||||
struct ath_hw_radar_conf radar_conf;
|
||||
|
||||
u32 originalGain[22];
|
||||
int initPDADC;
|
||||
int PDADCdelta;
|
||||
int led_pin;
|
||||
u32 gpio_mask;
|
||||
u32 gpio_val;
|
||||
|
||||
struct ar5416IniArray iniModes;
|
||||
struct ar5416IniArray iniCommon;
|
||||
struct ar5416IniArray iniBank0;
|
||||
struct ar5416IniArray iniBB_RfGain;
|
||||
struct ar5416IniArray iniBank1;
|
||||
struct ar5416IniArray iniBank2;
|
||||
struct ar5416IniArray iniBank3;
|
||||
struct ar5416IniArray iniBank6;
|
||||
struct ar5416IniArray iniBank6TPC;
|
||||
struct ar5416IniArray iniBank7;
|
||||
struct ar5416IniArray iniAddac;
|
||||
struct ar5416IniArray iniPcieSerdes;
|
||||
struct ar5416IniArray iniPcieSerdesLowPower;
|
||||
struct ar5416IniArray iniModesAdditional;
|
||||
struct ar5416IniArray iniModesAdditional_40M;
|
||||
struct ar5416IniArray iniModesRxGain;
|
||||
struct ar5416IniArray iniModesTxGain;
|
||||
struct ar5416IniArray iniModes_9271_1_0_only;
|
||||
struct ar5416IniArray iniCckfirNormal;
|
||||
struct ar5416IniArray iniCckfirJapan2484;
|
||||
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
|
||||
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
|
||||
struct ar5416IniArray iniModes_9271_ANI_reg;
|
||||
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
|
||||
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
|
||||
|
||||
struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
|
||||
struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
|
||||
struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT];
|
||||
struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT];
|
||||
|
||||
u32 intr_gen_timer_trigger;
|
||||
u32 intr_gen_timer_thresh;
|
||||
struct ath_gen_timer_table hw_gen_timers;
|
||||
|
||||
struct ar9003_txs *ts_ring;
|
||||
void *ts_start;
|
||||
u32 ts_paddr_start;
|
||||
u32 ts_paddr_end;
|
||||
u16 ts_tail;
|
||||
u8 ts_size;
|
||||
|
||||
unsigned int paprd_target_power;
|
||||
unsigned int paprd_training_power;
|
||||
unsigned int paprd_ratemask;
|
||||
unsigned int paprd_ratemask_ht40;
|
||||
int paprd_table_write_done;
|
||||
u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
|
||||
u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
|
||||
/*
|
||||
* Store the permanent value of Reg 0x4004in WARegVal
|
||||
* so we dont have to R/M/W. We should not be reading
|
||||
* this register when in sleep states.
|
||||
*/
|
||||
u32 WARegVal;
|
||||
|
||||
/* Enterprise mode cap */
|
||||
u32 ent_mode;
|
||||
|
||||
int is_clk_25mhz;
|
||||
};
|
||||
|
||||
struct ath_bus_ops {
|
||||
enum ath_bus_type ath_bus_type;
|
||||
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||
int (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||
void (*bt_coex_prep)(struct ath_common *common);
|
||||
void (*extn_synch_en)(struct ath_common *common);
|
||||
};
|
||||
|
||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||
{
|
||||
return &ah->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
|
||||
{
|
||||
return &(ath9k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah)
|
||||
{
|
||||
return &ah->private_ops;
|
||||
}
|
||||
|
||||
static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
|
||||
{
|
||||
return &ah->ops;
|
||||
}
|
||||
|
||||
static inline u8 get_streams(int mask)
|
||||
{
|
||||
return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
|
||||
}
|
||||
|
||||
/* Initialization, Detach, Reset */
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
void ath9k_hw_deinit(struct ath_hw *ah);
|
||||
int ath9k_hw_init(struct ath_hw *ah);
|
||||
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
struct ath9k_hw_cal_data *caldata, int bChannelChange);
|
||||
int ath9k_hw_fill_cap_info(struct ath_hw *ah);
|
||||
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
|
||||
|
||||
/* GPIO / RFKILL / Antennae */
|
||||
void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
|
||||
u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
|
||||
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
|
||||
u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
|
||||
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
|
||||
|
||||
/* General Operation */
|
||||
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
|
||||
void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
|
||||
int column, unsigned int *writecnt);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
u16 ath9k_hw_computetxtime(struct ath_hw *ah,
|
||||
u8 phy, int kbps,
|
||||
u32 frameLen, u16 rateix, int shortPreamble);
|
||||
void ath9k_hw_get_channel_centers(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers);
|
||||
u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
|
||||
void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
|
||||
int ath9k_hw_phy_disable(struct ath_hw *ah);
|
||||
int ath9k_hw_disable(struct ath_hw *ah);
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, int test);
|
||||
void ath9k_hw_setopmode(struct ath_hw *ah);
|
||||
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
|
||||
void ath9k_hw_setbssidmask(struct ath_hw *ah);
|
||||
void ath9k_hw_write_associd(struct ath_hw *ah);
|
||||
void ath9k_hw_init_global_settings(struct ath_hw *ah);
|
||||
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hw *ah);
|
||||
int ath9k_hw_check_alive(struct ath_hw *ah);
|
||||
|
||||
int ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
|
||||
|
||||
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
|
||||
|
||||
/* HTC */
|
||||
void ath9k_hw_htc_resetinit(struct ath_hw *ah);
|
||||
|
||||
/* PHY */
|
||||
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
|
||||
u32 *coef_mantissa, u32 *coef_exponent);
|
||||
|
||||
/*
|
||||
* Code Specific to AR5008, AR9001 or AR9002,
|
||||
* we stuff these here to avoid callbacks for AR9003.
|
||||
*/
|
||||
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
|
||||
int ar9002_hw_rf_claim(struct ath_hw *ah);
|
||||
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
|
||||
void ar9002_hw_update_async_fifo(struct ath_hw *ah);
|
||||
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
|
||||
|
||||
/*
|
||||
* Code specific to AR9003, we stuff these here to avoid callbacks
|
||||
* for older families
|
||||
*/
|
||||
void ar9003_hw_disable_phy_restart(struct ath_hw *ah);
|
||||
|
||||
/* Hardware family op attach helpers */
|
||||
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
/*
|
||||
* ANI work can be shared between all families but a next
|
||||
* generation implementation of ANI will be used only for AR9003 only
|
||||
* for now as the other families still need to be tested with the same
|
||||
* next generation ANI. Feel free to start testing it though for the
|
||||
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
|
||||
*/
|
||||
extern int modparam_force_new_ani;
|
||||
void ath9k_ani_reset(struct ath_hw *ah, int is_scanning);
|
||||
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
||||
#define ATH_PCIE_CAP_LINK_CTRL 0x70
|
||||
#define ATH_PCIE_CAP_LINK_L0S 1
|
||||
#define ATH_PCIE_CAP_LINK_L1 2
|
||||
|
||||
#define ATH9K_CLOCK_RATE_CCK 22
|
||||
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
|
||||
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
|
||||
#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
|
||||
|
||||
#endif
|
||||
708
src/drivers/net/ath/ath9k/mac.h
Normal file
708
src/drivers/net/ath/ath9k/mac.h
Normal file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MAC_H
|
||||
#define MAC_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
|
||||
MS(ads->ds_rxstatus0, AR_RxRate) : \
|
||||
(ads->ds_rxstatus3 >> 2) & 0xFF)
|
||||
|
||||
#define set11nTries(_series, _index) \
|
||||
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
|
||||
|
||||
#define set11nRate(_series, _index) \
|
||||
(SM((_series)[_index].Rate, AR_XmitRate##_index))
|
||||
|
||||
#define set11nPktDurRTSCTS(_series, _index) \
|
||||
(SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \
|
||||
((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \
|
||||
AR_RTSCTSQual##_index : 0))
|
||||
|
||||
#define set11nRateFlags(_series, _index) \
|
||||
(((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \
|
||||
AR_2040_##_index : 0) \
|
||||
|((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
|
||||
AR_GI##_index : 0) \
|
||||
|((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ? \
|
||||
AR_STBC##_index : 0) \
|
||||
|SM((_series)[_index].ChSel, AR_ChainSel##_index))
|
||||
|
||||
#define CCK_SIFS_TIME 10
|
||||
#define CCK_PREAMBLE_BITS 144
|
||||
#define CCK_PLCP_BITS 48
|
||||
|
||||
#define OFDM_SIFS_TIME 16
|
||||
#define OFDM_PREAMBLE_TIME 20
|
||||
#define OFDM_PLCP_BITS 22
|
||||
#define OFDM_SYMBOL_TIME 4
|
||||
|
||||
#define OFDM_SIFS_TIME_HALF 32
|
||||
#define OFDM_PREAMBLE_TIME_HALF 40
|
||||
#define OFDM_PLCP_BITS_HALF 22
|
||||
#define OFDM_SYMBOL_TIME_HALF 8
|
||||
|
||||
#define OFDM_SIFS_TIME_QUARTER 64
|
||||
#define OFDM_PREAMBLE_TIME_QUARTER 80
|
||||
#define OFDM_PLCP_BITS_QUARTER 22
|
||||
#define OFDM_SYMBOL_TIME_QUARTER 16
|
||||
|
||||
#define INIT_AIFS 2
|
||||
#define INIT_CWMIN 15
|
||||
#define INIT_CWMIN_11B 31
|
||||
#define INIT_CWMAX 1023
|
||||
#define INIT_SH_RETRY 10
|
||||
#define INIT_LG_RETRY 10
|
||||
#define INIT_SSH_RETRY 32
|
||||
#define INIT_SLG_RETRY 32
|
||||
|
||||
#define ATH9K_SLOT_TIME_6 6
|
||||
#define ATH9K_SLOT_TIME_9 9
|
||||
#define ATH9K_SLOT_TIME_20 20
|
||||
|
||||
#define ATH9K_TXERR_XRETRY 0x01
|
||||
#define ATH9K_TXERR_FILT 0x02
|
||||
#define ATH9K_TXERR_FIFO 0x04
|
||||
#define ATH9K_TXERR_XTXOP 0x08
|
||||
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
|
||||
#define ATH9K_TX_ACKED 0x20
|
||||
#define ATH9K_TXERR_MASK \
|
||||
(ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
|
||||
ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
|
||||
|
||||
#define ATH9K_TX_BA 0x01
|
||||
#define ATH9K_TX_PWRMGMT 0x02
|
||||
#define ATH9K_TX_DESC_CFG_ERR 0x04
|
||||
#define ATH9K_TX_DATA_UNDERRUN 0x08
|
||||
#define ATH9K_TX_DELIM_UNDERRUN 0x10
|
||||
#define ATH9K_TX_SW_FILTERED 0x80
|
||||
|
||||
/* 64 bytes */
|
||||
#define MIN_TX_FIFO_THRESHOLD 0x1
|
||||
|
||||
/*
|
||||
* Single stream device AR9285 and AR9271 require 2 KB
|
||||
* to work around a hardware issue, all other devices
|
||||
* have can use the max 4 KB limit.
|
||||
*/
|
||||
#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
|
||||
|
||||
struct ath_tx_status {
|
||||
u32 ts_tstamp;
|
||||
u16 ts_seqnum;
|
||||
u8 ts_status;
|
||||
u8 ts_rateindex;
|
||||
int8_t ts_rssi;
|
||||
u8 ts_shortretry;
|
||||
u8 ts_longretry;
|
||||
u8 ts_virtcol;
|
||||
u8 ts_flags;
|
||||
int8_t ts_rssi_ctl0;
|
||||
int8_t ts_rssi_ctl1;
|
||||
int8_t ts_rssi_ctl2;
|
||||
int8_t ts_rssi_ext0;
|
||||
int8_t ts_rssi_ext1;
|
||||
int8_t ts_rssi_ext2;
|
||||
u8 qid;
|
||||
u16 desc_id;
|
||||
u8 tid;
|
||||
u32 ba_low;
|
||||
u32 ba_high;
|
||||
u32 evm0;
|
||||
u32 evm1;
|
||||
u32 evm2;
|
||||
};
|
||||
|
||||
struct ath_rx_status {
|
||||
u32 rs_tstamp;
|
||||
u16 rs_datalen;
|
||||
u8 rs_status;
|
||||
u8 rs_phyerr;
|
||||
int8_t rs_rssi;
|
||||
u8 rs_keyix;
|
||||
u8 rs_rate;
|
||||
u8 rs_antenna;
|
||||
u8 rs_more;
|
||||
int8_t rs_rssi_ctl0;
|
||||
int8_t rs_rssi_ctl1;
|
||||
int8_t rs_rssi_ctl2;
|
||||
int8_t rs_rssi_ext0;
|
||||
int8_t rs_rssi_ext1;
|
||||
int8_t rs_rssi_ext2;
|
||||
u8 rs_isaggr;
|
||||
u8 rs_moreaggr;
|
||||
u8 rs_num_delims;
|
||||
u8 rs_flags;
|
||||
u32 evm0;
|
||||
u32 evm1;
|
||||
u32 evm2;
|
||||
u32 evm3;
|
||||
u32 evm4;
|
||||
};
|
||||
|
||||
struct ath_htc_rx_status {
|
||||
uint64_t rs_tstamp;
|
||||
uint16_t rs_datalen;
|
||||
u8 rs_status;
|
||||
u8 rs_phyerr;
|
||||
int8_t rs_rssi;
|
||||
int8_t rs_rssi_ctl0;
|
||||
int8_t rs_rssi_ctl1;
|
||||
int8_t rs_rssi_ctl2;
|
||||
int8_t rs_rssi_ext0;
|
||||
int8_t rs_rssi_ext1;
|
||||
int8_t rs_rssi_ext2;
|
||||
u8 rs_keyix;
|
||||
u8 rs_rate;
|
||||
u8 rs_antenna;
|
||||
u8 rs_more;
|
||||
u8 rs_isaggr;
|
||||
u8 rs_moreaggr;
|
||||
u8 rs_num_delims;
|
||||
u8 rs_flags;
|
||||
u8 rs_dummy;
|
||||
uint32_t evm0;
|
||||
uint32_t evm1;
|
||||
uint32_t evm2;
|
||||
};
|
||||
|
||||
#define ATH9K_RXERR_CRC 0x01
|
||||
#define ATH9K_RXERR_PHY 0x02
|
||||
#define ATH9K_RXERR_FIFO 0x04
|
||||
#define ATH9K_RXERR_DECRYPT 0x08
|
||||
#define ATH9K_RXERR_MIC 0x10
|
||||
|
||||
#define ATH9K_RX_MORE 0x01
|
||||
#define ATH9K_RX_MORE_AGGR 0x02
|
||||
#define ATH9K_RX_GI 0x04
|
||||
#define ATH9K_RX_2040 0x08
|
||||
#define ATH9K_RX_DELIM_CRC_PRE 0x10
|
||||
#define ATH9K_RX_DELIM_CRC_POST 0x20
|
||||
#define ATH9K_RX_DECRYPT_BUSY 0x40
|
||||
|
||||
#define ATH9K_RXKEYIX_INVALID ((u8)-1)
|
||||
#define ATH9K_TXKEYIX_INVALID ((u32)-1)
|
||||
|
||||
enum ath9k_phyerr {
|
||||
ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
|
||||
ATH9K_PHYERR_TIMING = 1, /* Timing error */
|
||||
ATH9K_PHYERR_PARITY = 2, /* Illegal parity */
|
||||
ATH9K_PHYERR_RATE = 3, /* Illegal rate */
|
||||
ATH9K_PHYERR_LENGTH = 4, /* Illegal length */
|
||||
ATH9K_PHYERR_RADAR = 5, /* Radar detect */
|
||||
ATH9K_PHYERR_SERVICE = 6, /* Illegal service */
|
||||
ATH9K_PHYERR_TOR = 7, /* Transmit override receive */
|
||||
|
||||
ATH9K_PHYERR_OFDM_TIMING = 17,
|
||||
ATH9K_PHYERR_OFDM_SIGNAL_PARITY = 18,
|
||||
ATH9K_PHYERR_OFDM_RATE_ILLEGAL = 19,
|
||||
ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL = 20,
|
||||
ATH9K_PHYERR_OFDM_POWER_DROP = 21,
|
||||
ATH9K_PHYERR_OFDM_SERVICE = 22,
|
||||
ATH9K_PHYERR_OFDM_RESTART = 23,
|
||||
ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
|
||||
|
||||
ATH9K_PHYERR_CCK_TIMING = 25,
|
||||
ATH9K_PHYERR_CCK_HEADER_CRC = 26,
|
||||
ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
|
||||
ATH9K_PHYERR_CCK_SERVICE = 30,
|
||||
ATH9K_PHYERR_CCK_RESTART = 31,
|
||||
ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
|
||||
ATH9K_PHYERR_CCK_POWER_DROP = 33,
|
||||
|
||||
ATH9K_PHYERR_HT_CRC_ERROR = 34,
|
||||
ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
|
||||
ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
|
||||
|
||||
ATH9K_PHYERR_MAX = 37,
|
||||
};
|
||||
|
||||
struct ath_desc {
|
||||
u32 ds_link;
|
||||
u32 ds_data;
|
||||
u32 ds_ctl0;
|
||||
u32 ds_ctl1;
|
||||
u32 ds_hw[20];
|
||||
// void *ds_vdata;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
#define ATH9K_TXDESC_NOACK 0x0002
|
||||
#define ATH9K_TXDESC_RTSENA 0x0004
|
||||
#define ATH9K_TXDESC_CTSENA 0x0008
|
||||
/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
|
||||
* the descriptor its marked on. We take a tx interrupt to reap
|
||||
* descriptors when the h/w hits an EOL condition or
|
||||
* when the descriptor is specifically marked to generate
|
||||
* an interrupt with this flag. Descriptors should be
|
||||
* marked periodically to insure timely replenishing of the
|
||||
* supply needed for sending frames. Defering interrupts
|
||||
* reduces system load and potentially allows more concurrent
|
||||
* work to be done but if done to aggressively can cause
|
||||
* senders to backup. When the hardware queue is left too
|
||||
* large rate control information may also be too out of
|
||||
* date. An Alternative for this is TX interrupt mitigation
|
||||
* but this needs more testing. */
|
||||
#define ATH9K_TXDESC_INTREQ 0x0010
|
||||
#define ATH9K_TXDESC_VEOL 0x0020
|
||||
#define ATH9K_TXDESC_EXT_ONLY 0x0040
|
||||
#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
|
||||
#define ATH9K_TXDESC_VMF 0x0100
|
||||
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
|
||||
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
|
||||
#define ATH9K_TXDESC_LDPC 0x00010000
|
||||
|
||||
#define ATH9K_RXDESC_INTREQ 0x0020
|
||||
|
||||
struct ar5416_desc {
|
||||
u32 ds_link;
|
||||
u32 ds_data;
|
||||
u32 ds_ctl0;
|
||||
u32 ds_ctl1;
|
||||
union {
|
||||
struct {
|
||||
u32 ctl2;
|
||||
u32 ctl3;
|
||||
u32 ctl4;
|
||||
u32 ctl5;
|
||||
u32 ctl6;
|
||||
u32 ctl7;
|
||||
u32 ctl8;
|
||||
u32 ctl9;
|
||||
u32 ctl10;
|
||||
u32 ctl11;
|
||||
u32 status0;
|
||||
u32 status1;
|
||||
u32 status2;
|
||||
u32 status3;
|
||||
u32 status4;
|
||||
u32 status5;
|
||||
u32 status6;
|
||||
u32 status7;
|
||||
u32 status8;
|
||||
u32 status9;
|
||||
} tx;
|
||||
struct {
|
||||
u32 status0;
|
||||
u32 status1;
|
||||
u32 status2;
|
||||
u32 status3;
|
||||
u32 status4;
|
||||
u32 status5;
|
||||
u32 status6;
|
||||
u32 status7;
|
||||
u32 status8;
|
||||
} rx;
|
||||
} u;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
|
||||
#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
|
||||
|
||||
#define ds_ctl2 u.tx.ctl2
|
||||
#define ds_ctl3 u.tx.ctl3
|
||||
#define ds_ctl4 u.tx.ctl4
|
||||
#define ds_ctl5 u.tx.ctl5
|
||||
#define ds_ctl6 u.tx.ctl6
|
||||
#define ds_ctl7 u.tx.ctl7
|
||||
#define ds_ctl8 u.tx.ctl8
|
||||
#define ds_ctl9 u.tx.ctl9
|
||||
#define ds_ctl10 u.tx.ctl10
|
||||
#define ds_ctl11 u.tx.ctl11
|
||||
|
||||
#define ds_txstatus0 u.tx.status0
|
||||
#define ds_txstatus1 u.tx.status1
|
||||
#define ds_txstatus2 u.tx.status2
|
||||
#define ds_txstatus3 u.tx.status3
|
||||
#define ds_txstatus4 u.tx.status4
|
||||
#define ds_txstatus5 u.tx.status5
|
||||
#define ds_txstatus6 u.tx.status6
|
||||
#define ds_txstatus7 u.tx.status7
|
||||
#define ds_txstatus8 u.tx.status8
|
||||
#define ds_txstatus9 u.tx.status9
|
||||
|
||||
#define ds_rxstatus0 u.rx.status0
|
||||
#define ds_rxstatus1 u.rx.status1
|
||||
#define ds_rxstatus2 u.rx.status2
|
||||
#define ds_rxstatus3 u.rx.status3
|
||||
#define ds_rxstatus4 u.rx.status4
|
||||
#define ds_rxstatus5 u.rx.status5
|
||||
#define ds_rxstatus6 u.rx.status6
|
||||
#define ds_rxstatus7 u.rx.status7
|
||||
#define ds_rxstatus8 u.rx.status8
|
||||
|
||||
#define AR_FrameLen 0x00000fff
|
||||
#define AR_VirtMoreFrag 0x00001000
|
||||
#define AR_TxCtlRsvd00 0x0000e000
|
||||
#define AR_XmitPower 0x003f0000
|
||||
#define AR_XmitPower_S 16
|
||||
#define AR_RTSEnable 0x00400000
|
||||
#define AR_VEOL 0x00800000
|
||||
#define AR_ClrDestMask 0x01000000
|
||||
#define AR_TxCtlRsvd01 0x1e000000
|
||||
#define AR_TxIntrReq 0x20000000
|
||||
#define AR_DestIdxValid 0x40000000
|
||||
#define AR_CTSEnable 0x80000000
|
||||
|
||||
#define AR_TxMore 0x00001000
|
||||
#define AR_DestIdx 0x000fe000
|
||||
#define AR_DestIdx_S 13
|
||||
#define AR_FrameType 0x00f00000
|
||||
#define AR_FrameType_S 20
|
||||
#define AR_NoAck 0x01000000
|
||||
#define AR_InsertTS 0x02000000
|
||||
#define AR_CorruptFCS 0x04000000
|
||||
#define AR_ExtOnly 0x08000000
|
||||
#define AR_ExtAndCtl 0x10000000
|
||||
#define AR_MoreAggr 0x20000000
|
||||
#define AR_IsAggr 0x40000000
|
||||
|
||||
#define AR_BurstDur 0x00007fff
|
||||
#define AR_BurstDur_S 0
|
||||
#define AR_DurUpdateEna 0x00008000
|
||||
#define AR_XmitDataTries0 0x000f0000
|
||||
#define AR_XmitDataTries0_S 16
|
||||
#define AR_XmitDataTries1 0x00f00000
|
||||
#define AR_XmitDataTries1_S 20
|
||||
#define AR_XmitDataTries2 0x0f000000
|
||||
#define AR_XmitDataTries2_S 24
|
||||
#define AR_XmitDataTries3 0xf0000000
|
||||
#define AR_XmitDataTries3_S 28
|
||||
|
||||
#define AR_XmitRate0 0x000000ff
|
||||
#define AR_XmitRate0_S 0
|
||||
#define AR_XmitRate1 0x0000ff00
|
||||
#define AR_XmitRate1_S 8
|
||||
#define AR_XmitRate2 0x00ff0000
|
||||
#define AR_XmitRate2_S 16
|
||||
#define AR_XmitRate3 0xff000000
|
||||
#define AR_XmitRate3_S 24
|
||||
|
||||
#define AR_PacketDur0 0x00007fff
|
||||
#define AR_PacketDur0_S 0
|
||||
#define AR_RTSCTSQual0 0x00008000
|
||||
#define AR_PacketDur1 0x7fff0000
|
||||
#define AR_PacketDur1_S 16
|
||||
#define AR_RTSCTSQual1 0x80000000
|
||||
|
||||
#define AR_PacketDur2 0x00007fff
|
||||
#define AR_PacketDur2_S 0
|
||||
#define AR_RTSCTSQual2 0x00008000
|
||||
#define AR_PacketDur3 0x7fff0000
|
||||
#define AR_PacketDur3_S 16
|
||||
#define AR_RTSCTSQual3 0x80000000
|
||||
|
||||
#define AR_AggrLen 0x0000ffff
|
||||
#define AR_AggrLen_S 0
|
||||
#define AR_TxCtlRsvd60 0x00030000
|
||||
#define AR_PadDelim 0x03fc0000
|
||||
#define AR_PadDelim_S 18
|
||||
#define AR_EncrType 0x0c000000
|
||||
#define AR_EncrType_S 26
|
||||
#define AR_TxCtlRsvd61 0xf0000000
|
||||
#define AR_LDPC 0x80000000
|
||||
|
||||
#define AR_2040_0 0x00000001
|
||||
#define AR_GI0 0x00000002
|
||||
#define AR_ChainSel0 0x0000001c
|
||||
#define AR_ChainSel0_S 2
|
||||
#define AR_2040_1 0x00000020
|
||||
#define AR_GI1 0x00000040
|
||||
#define AR_ChainSel1 0x00000380
|
||||
#define AR_ChainSel1_S 7
|
||||
#define AR_2040_2 0x00000400
|
||||
#define AR_GI2 0x00000800
|
||||
#define AR_ChainSel2 0x00007000
|
||||
#define AR_ChainSel2_S 12
|
||||
#define AR_2040_3 0x00008000
|
||||
#define AR_GI3 0x00010000
|
||||
#define AR_ChainSel3 0x000e0000
|
||||
#define AR_ChainSel3_S 17
|
||||
#define AR_RTSCTSRate 0x0ff00000
|
||||
#define AR_RTSCTSRate_S 20
|
||||
#define AR_STBC0 0x10000000
|
||||
#define AR_STBC1 0x20000000
|
||||
#define AR_STBC2 0x40000000
|
||||
#define AR_STBC3 0x80000000
|
||||
|
||||
#define AR_TxRSSIAnt00 0x000000ff
|
||||
#define AR_TxRSSIAnt00_S 0
|
||||
#define AR_TxRSSIAnt01 0x0000ff00
|
||||
#define AR_TxRSSIAnt01_S 8
|
||||
#define AR_TxRSSIAnt02 0x00ff0000
|
||||
#define AR_TxRSSIAnt02_S 16
|
||||
#define AR_TxStatusRsvd00 0x3f000000
|
||||
#define AR_TxBaStatus 0x40000000
|
||||
#define AR_TxStatusRsvd01 0x80000000
|
||||
|
||||
/*
|
||||
* AR_FrmXmitOK - Frame transmission success flag. If set, the frame was
|
||||
* transmitted successfully. If clear, no ACK or BA was received to indicate
|
||||
* successful transmission when we were expecting an ACK or BA.
|
||||
*/
|
||||
#define AR_FrmXmitOK 0x00000001
|
||||
#define AR_ExcessiveRetries 0x00000002
|
||||
#define AR_FIFOUnderrun 0x00000004
|
||||
#define AR_Filtered 0x00000008
|
||||
#define AR_RTSFailCnt 0x000000f0
|
||||
#define AR_RTSFailCnt_S 4
|
||||
#define AR_DataFailCnt 0x00000f00
|
||||
#define AR_DataFailCnt_S 8
|
||||
#define AR_VirtRetryCnt 0x0000f000
|
||||
#define AR_VirtRetryCnt_S 12
|
||||
#define AR_TxDelimUnderrun 0x00010000
|
||||
#define AR_TxDataUnderrun 0x00020000
|
||||
#define AR_DescCfgErr 0x00040000
|
||||
#define AR_TxTimerExpired 0x00080000
|
||||
#define AR_TxStatusRsvd10 0xfff00000
|
||||
|
||||
#define AR_SendTimestamp ds_txstatus2
|
||||
#define AR_BaBitmapLow ds_txstatus3
|
||||
#define AR_BaBitmapHigh ds_txstatus4
|
||||
|
||||
#define AR_TxRSSIAnt10 0x000000ff
|
||||
#define AR_TxRSSIAnt10_S 0
|
||||
#define AR_TxRSSIAnt11 0x0000ff00
|
||||
#define AR_TxRSSIAnt11_S 8
|
||||
#define AR_TxRSSIAnt12 0x00ff0000
|
||||
#define AR_TxRSSIAnt12_S 16
|
||||
#define AR_TxRSSICombined 0xff000000
|
||||
#define AR_TxRSSICombined_S 24
|
||||
|
||||
#define AR_TxTid 0xf0000000
|
||||
#define AR_TxTid_S 28
|
||||
|
||||
#define AR_TxEVM0 ds_txstatus5
|
||||
#define AR_TxEVM1 ds_txstatus6
|
||||
#define AR_TxEVM2 ds_txstatus7
|
||||
|
||||
#define AR_TxDone 0x00000001
|
||||
#define AR_SeqNum 0x00001ffe
|
||||
#define AR_SeqNum_S 1
|
||||
#define AR_TxStatusRsvd80 0x0001e000
|
||||
#define AR_TxOpExceeded 0x00020000
|
||||
#define AR_TxStatusRsvd81 0x001c0000
|
||||
#define AR_FinalTxIdx 0x00600000
|
||||
#define AR_FinalTxIdx_S 21
|
||||
#define AR_TxStatusRsvd82 0x01800000
|
||||
#define AR_PowerMgmt 0x02000000
|
||||
#define AR_TxStatusRsvd83 0xfc000000
|
||||
|
||||
#define AR_RxCTLRsvd00 0xffffffff
|
||||
|
||||
#define AR_RxCtlRsvd00 0x00001000
|
||||
#define AR_RxIntrReq 0x00002000
|
||||
#define AR_RxCtlRsvd01 0xffffc000
|
||||
|
||||
#define AR_RxRSSIAnt00 0x000000ff
|
||||
#define AR_RxRSSIAnt00_S 0
|
||||
#define AR_RxRSSIAnt01 0x0000ff00
|
||||
#define AR_RxRSSIAnt01_S 8
|
||||
#define AR_RxRSSIAnt02 0x00ff0000
|
||||
#define AR_RxRSSIAnt02_S 16
|
||||
#define AR_RxRate 0xff000000
|
||||
#define AR_RxRate_S 24
|
||||
#define AR_RxStatusRsvd00 0xff000000
|
||||
|
||||
#define AR_DataLen 0x00000fff
|
||||
#define AR_RxMore 0x00001000
|
||||
#define AR_NumDelim 0x003fc000
|
||||
#define AR_NumDelim_S 14
|
||||
#define AR_RxStatusRsvd10 0xff800000
|
||||
|
||||
#define AR_RcvTimestamp ds_rxstatus2
|
||||
|
||||
#define AR_GI 0x00000001
|
||||
#define AR_2040 0x00000002
|
||||
#define AR_Parallel40 0x00000004
|
||||
#define AR_Parallel40_S 2
|
||||
#define AR_RxStatusRsvd30 0x000000f8
|
||||
#define AR_RxAntenna 0xffffff00
|
||||
#define AR_RxAntenna_S 8
|
||||
|
||||
#define AR_RxRSSIAnt10 0x000000ff
|
||||
#define AR_RxRSSIAnt10_S 0
|
||||
#define AR_RxRSSIAnt11 0x0000ff00
|
||||
#define AR_RxRSSIAnt11_S 8
|
||||
#define AR_RxRSSIAnt12 0x00ff0000
|
||||
#define AR_RxRSSIAnt12_S 16
|
||||
#define AR_RxRSSICombined 0xff000000
|
||||
#define AR_RxRSSICombined_S 24
|
||||
|
||||
#define AR_RxEVM0 ds_rxstatus4
|
||||
#define AR_RxEVM1 ds_rxstatus5
|
||||
#define AR_RxEVM2 ds_rxstatus6
|
||||
|
||||
#define AR_RxDone 0x00000001
|
||||
#define AR_RxFrameOK 0x00000002
|
||||
#define AR_CRCErr 0x00000004
|
||||
#define AR_DecryptCRCErr 0x00000008
|
||||
#define AR_PHYErr 0x00000010
|
||||
#define AR_MichaelErr 0x00000020
|
||||
#define AR_PreDelimCRCErr 0x00000040
|
||||
#define AR_RxStatusRsvd70 0x00000080
|
||||
#define AR_RxKeyIdxValid 0x00000100
|
||||
#define AR_KeyIdx 0x0000fe00
|
||||
#define AR_KeyIdx_S 9
|
||||
#define AR_PHYErrCode 0x0000ff00
|
||||
#define AR_PHYErrCode_S 8
|
||||
#define AR_RxMoreAggr 0x00010000
|
||||
#define AR_RxAggr 0x00020000
|
||||
#define AR_PostDelimCRCErr 0x00040000
|
||||
#define AR_RxStatusRsvd71 0x3ff80000
|
||||
#define AR_DecryptBusyErr 0x40000000
|
||||
#define AR_KeyMiss 0x80000000
|
||||
|
||||
enum ath9k_tx_queue {
|
||||
ATH9K_TX_QUEUE_INACTIVE = 0,
|
||||
ATH9K_TX_QUEUE_DATA,
|
||||
};
|
||||
|
||||
#define ATH9K_NUM_TX_QUEUES 1
|
||||
|
||||
/* Used as a queue subtype instead of a WMM AC */
|
||||
#define ATH9K_WME_UPSD 4
|
||||
|
||||
enum ath9k_tx_queue_flags {
|
||||
TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
|
||||
TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
|
||||
TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
|
||||
TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
|
||||
TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
|
||||
TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
|
||||
TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
|
||||
TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
|
||||
TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
|
||||
};
|
||||
|
||||
#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
|
||||
#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
|
||||
|
||||
#define ATH9K_DECOMP_MASK_SIZE 128
|
||||
#define ATH9K_READY_TIME_LO_BOUND 50
|
||||
#define ATH9K_READY_TIME_HI_BOUND 96
|
||||
|
||||
enum ath9k_pkt_type {
|
||||
ATH9K_PKT_TYPE_NORMAL = 0,
|
||||
ATH9K_PKT_TYPE_ATIM,
|
||||
ATH9K_PKT_TYPE_PSPOLL,
|
||||
ATH9K_PKT_TYPE_BEACON,
|
||||
ATH9K_PKT_TYPE_PROBE_RESP,
|
||||
ATH9K_PKT_TYPE_CHIRP,
|
||||
ATH9K_PKT_TYPE_GRP_POLL,
|
||||
};
|
||||
|
||||
struct ath9k_tx_queue_info {
|
||||
u32 tqi_ver;
|
||||
enum ath9k_tx_queue tqi_type;
|
||||
int tqi_subtype;
|
||||
enum ath9k_tx_queue_flags tqi_qflags;
|
||||
u32 tqi_priority;
|
||||
u32 tqi_aifs;
|
||||
u32 tqi_cwmin;
|
||||
u32 tqi_cwmax;
|
||||
u16 tqi_shretry;
|
||||
u16 tqi_lgretry;
|
||||
u32 tqi_cbrPeriod;
|
||||
u32 tqi_cbrOverflowLimit;
|
||||
u32 tqi_burstTime;
|
||||
u32 tqi_readyTime;
|
||||
u32 tqi_physCompBuf;
|
||||
u32 tqi_intFlags;
|
||||
};
|
||||
|
||||
enum ath9k_rx_filter {
|
||||
ATH9K_RX_FILTER_UCAST = 0x00000001,
|
||||
ATH9K_RX_FILTER_MCAST = 0x00000002,
|
||||
ATH9K_RX_FILTER_BCAST = 0x00000004,
|
||||
ATH9K_RX_FILTER_CONTROL = 0x00000008,
|
||||
ATH9K_RX_FILTER_BEACON = 0x00000010,
|
||||
ATH9K_RX_FILTER_PROM = 0x00000020,
|
||||
ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
|
||||
ATH9K_RX_FILTER_PHYERR = 0x00000100,
|
||||
ATH9K_RX_FILTER_MYBEACON = 0x00000200,
|
||||
ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
|
||||
ATH9K_RX_FILTER_COMP_BA = 0x00000800,
|
||||
ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000,
|
||||
ATH9K_RX_FILTER_PSPOLL = 0x00004000,
|
||||
ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
|
||||
ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
|
||||
};
|
||||
|
||||
#define ATH9K_RATESERIES_RTS_CTS 0x0001
|
||||
#define ATH9K_RATESERIES_2040 0x0002
|
||||
#define ATH9K_RATESERIES_HALFGI 0x0004
|
||||
#define ATH9K_RATESERIES_STBC 0x0008
|
||||
|
||||
struct ath9k_11n_rate_series {
|
||||
u32 Tries;
|
||||
u32 Rate;
|
||||
u32 PktDuration;
|
||||
u32 ChSel;
|
||||
u32 RateFlags;
|
||||
};
|
||||
|
||||
enum ath9k_key_type {
|
||||
ATH9K_KEY_TYPE_CLEAR,
|
||||
ATH9K_KEY_TYPE_WEP,
|
||||
ATH9K_KEY_TYPE_AES,
|
||||
ATH9K_KEY_TYPE_TKIP,
|
||||
};
|
||||
|
||||
struct ath_hw;
|
||||
struct ath9k_channel;
|
||||
enum ath9k_int;
|
||||
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
|
||||
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
|
||||
void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
|
||||
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
|
||||
int ath9k_hw_updatetxtriglevel(struct ath_hw *ah, int bIncTrigLevel);
|
||||
int ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
|
||||
void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
|
||||
int ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
int ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
|
||||
struct ath9k_tx_queue_info *qinfo);
|
||||
int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
int ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
|
||||
int ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
|
||||
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
struct ath_rx_status *rs, u64 tsf);
|
||||
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 size, u32 flags);
|
||||
int ath9k_hw_setrxabort(struct ath_hw *ah, int set);
|
||||
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
|
||||
void ath9k_hw_startpcureceive(struct ath_hw *ah, int is_scanning);
|
||||
void ath9k_hw_abortpcurecv(struct ath_hw *ah);
|
||||
int ath9k_hw_stopdmarecv(struct ath_hw *ah, int *reset);
|
||||
|
||||
/* Interrupt Handling */
|
||||
int ath9k_hw_intrpend(struct ath_hw *ah);
|
||||
void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
|
||||
|
||||
#endif /* MAC_H */
|
||||
51
src/drivers/net/ath/ath9k/phy.h
Normal file
51
src/drivers/net/ath/ath9k/phy.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PHY_H
|
||||
#define PHY_H
|
||||
|
||||
#define CHANSEL_DIV 15
|
||||
#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
|
||||
#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)
|
||||
|
||||
#define AR_PHY_BASE 0x9800
|
||||
#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
|
||||
|
||||
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000
|
||||
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13
|
||||
#define AR_PHY_TX_GAIN_CLC 0x0000001E
|
||||
#define AR_PHY_TX_GAIN_CLC_S 1
|
||||
#define AR_PHY_TX_GAIN 0x0007F000
|
||||
#define AR_PHY_TX_GAIN_S 12
|
||||
|
||||
#define AR_PHY_CLC_TBL1 0xa35c
|
||||
#define AR_PHY_CLC_I0 0x07ff0000
|
||||
#define AR_PHY_CLC_I0_S 16
|
||||
#define AR_PHY_CLC_Q0 0x0000ffd0
|
||||
#define AR_PHY_CLC_Q0_S 5
|
||||
|
||||
#define ANTSWAP_AB 0x0001
|
||||
#define REDUCE_CHAIN_0 0x00000050
|
||||
#define REDUCE_CHAIN_1 0x00000051
|
||||
#define AR_PHY_CHIP_ID 0x9818
|
||||
|
||||
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
|
||||
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
|
||||
|
||||
#define AR_PHY_PLL_CONTROL 0x16180
|
||||
#define AR_PHY_PLL_MODE 0x16184
|
||||
|
||||
#endif
|
||||
1919
src/drivers/net/ath/ath9k/reg.h
Normal file
1919
src/drivers/net/ath/ath9k/reg.h
Normal file
File diff suppressed because it is too large
Load Diff
183
src/drivers/net/ath/ath_hw.c
Normal file
183
src/drivers/net/ath/ath_hw.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "ath.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define REG_READ (common->ops->read)
|
||||
#define REG_WRITE (common->ops->write)
|
||||
|
||||
/**
|
||||
* ath_hw_set_bssid_mask - filter out bssids we listen
|
||||
*
|
||||
* @common: the ath_common struct for the device.
|
||||
*
|
||||
* BSSID masking is a method used by AR5212 and newer hardware to inform PCU
|
||||
* which bits of the interface's MAC address should be looked at when trying
|
||||
* to decide which packets to ACK. In station mode and AP mode with a single
|
||||
* BSS every bit matters since we lock to only one BSS. In AP mode with
|
||||
* multiple BSSes (virtual interfaces) not every bit matters because hw must
|
||||
* accept frames for all BSSes and so we tweak some bits of our mac address
|
||||
* in order to have multiple BSSes.
|
||||
*
|
||||
* NOTE: This is a simple filter and does *not* filter out all
|
||||
* relevant frames. Some frames that are not for us might get ACKed from us
|
||||
* by PCU because they just match the mask.
|
||||
*
|
||||
* When handling multiple BSSes you can get the BSSID mask by computing the
|
||||
* set of ~ ( MAC XOR BSSID ) for all bssids we handle.
|
||||
*
|
||||
* When you do this you are essentially computing the common bits of all your
|
||||
* BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with
|
||||
* the MAC address to obtain the relevant bits and compare the result with
|
||||
* (frame's BSSID & mask) to see if they match.
|
||||
*
|
||||
* Simple example: on your card you have have two BSSes you have created with
|
||||
* BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
|
||||
* There is another BSSID-03 but you are not part of it. For simplicity's sake,
|
||||
* assuming only 4 bits for a mac address and for BSSIDs you can then have:
|
||||
*
|
||||
* \
|
||||
* MAC: 0001 |
|
||||
* BSSID-01: 0100 | --> Belongs to us
|
||||
* BSSID-02: 1001 |
|
||||
* /
|
||||
* -------------------
|
||||
* BSSID-03: 0110 | --> External
|
||||
* -------------------
|
||||
*
|
||||
* Our bssid_mask would then be:
|
||||
*
|
||||
* On loop iteration for BSSID-01:
|
||||
* ~(0001 ^ 0100) -> ~(0101)
|
||||
* -> 1010
|
||||
* bssid_mask = 1010
|
||||
*
|
||||
* On loop iteration for BSSID-02:
|
||||
* bssid_mask &= ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(1000)
|
||||
* bssid_mask = (1010) & (0111)
|
||||
* bssid_mask = 0010
|
||||
*
|
||||
* A bssid_mask of 0010 means "only pay attention to the second least
|
||||
* significant bit". This is because its the only bit common
|
||||
* amongst the MAC and all BSSIDs we support. To findout what the real
|
||||
* common bit is we can simply "&" the bssid_mask now with any BSSID we have
|
||||
* or our MAC address (we assume the hardware uses the MAC address).
|
||||
*
|
||||
* Now, suppose there's an incoming frame for BSSID-03:
|
||||
*
|
||||
* IFRAME-01: 0110
|
||||
*
|
||||
* An easy eye-inspeciton of this already should tell you that this frame
|
||||
* will not pass our check. This is because the bssid_mask tells the
|
||||
* hardware to only look at the second least significant bit and the
|
||||
* common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
|
||||
* as 1, which does not match 0.
|
||||
*
|
||||
* So with IFRAME-01 we *assume* the hardware will do:
|
||||
*
|
||||
* allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
|
||||
* --> allow = (0010) == 0000 ? 1 : 0;
|
||||
* --> allow = 0
|
||||
*
|
||||
* Lets now test a frame that should work:
|
||||
*
|
||||
* IFRAME-02: 0001 (we should allow)
|
||||
*
|
||||
* allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
|
||||
* --> allow = (0000) == (0000)
|
||||
* --> allow = 1
|
||||
*
|
||||
* Other examples:
|
||||
*
|
||||
* IFRAME-03: 0100 --> allowed
|
||||
* IFRAME-04: 1001 --> allowed
|
||||
* IFRAME-05: 1101 --> allowed but its not for us!!!
|
||||
*
|
||||
*/
|
||||
void ath_hw_setbssidmask(struct ath_common *common)
|
||||
{
|
||||
void *ah = common->ah;
|
||||
|
||||
REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
|
||||
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ath_hw_cycle_counters_update - common function to update cycle counters
|
||||
*
|
||||
* @common: the ath_common struct for the device.
|
||||
*
|
||||
* This function is used to update all cycle counters in one place.
|
||||
* It has to be called while holding common->cc_lock!
|
||||
*/
|
||||
void ath_hw_cycle_counters_update(struct ath_common *common)
|
||||
{
|
||||
u32 cycles, busy, rx, tx;
|
||||
void *ah = common->ah;
|
||||
|
||||
/* freeze */
|
||||
REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
|
||||
|
||||
/* read */
|
||||
cycles = REG_READ(ah, AR_CCCNT);
|
||||
busy = REG_READ(ah, AR_RCCNT);
|
||||
rx = REG_READ(ah, AR_RFCNT);
|
||||
tx = REG_READ(ah, AR_TFCNT);
|
||||
|
||||
/* clear */
|
||||
REG_WRITE(ah, 0, AR_CCCNT);
|
||||
REG_WRITE(ah, 0, AR_RFCNT);
|
||||
REG_WRITE(ah, 0, AR_RCCNT);
|
||||
REG_WRITE(ah, 0, AR_TFCNT);
|
||||
|
||||
/* unfreeze */
|
||||
REG_WRITE(ah, 0, AR_MIBC);
|
||||
|
||||
/* update all cycle counters here */
|
||||
common->cc_ani.cycles += cycles;
|
||||
common->cc_ani.rx_busy += busy;
|
||||
common->cc_ani.rx_frame += rx;
|
||||
common->cc_ani.tx_frame += tx;
|
||||
|
||||
common->cc_survey.cycles += cycles;
|
||||
common->cc_survey.rx_busy += busy;
|
||||
common->cc_survey.rx_frame += rx;
|
||||
common->cc_survey.tx_frame += tx;
|
||||
}
|
||||
|
||||
int32_t ath_hw_get_listen_time(struct ath_common *common)
|
||||
{
|
||||
struct ath_cycle_counters *cc = &common->cc_ani;
|
||||
int32_t listen_time;
|
||||
|
||||
listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
|
||||
(common->clockrate * 1000);
|
||||
|
||||
memset(cc, 0, sizeof(*cc));
|
||||
|
||||
return listen_time;
|
||||
}
|
||||
82
src/drivers/net/ath/ath_key.c
Normal file
82
src/drivers/net/ath/ath_key.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Atheros Communications Inc.
|
||||
* Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define REG_READ (common->ops->read)
|
||||
#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
|
||||
#define ENABLE_REGWRITE_BUFFER(_ah) \
|
||||
if (common->ops->enable_write_buffer) \
|
||||
common->ops->enable_write_buffer((_ah));
|
||||
|
||||
#define REGWRITE_BUFFER_FLUSH(_ah) \
|
||||
if (common->ops->write_flush) \
|
||||
common->ops->write_flush((_ah));
|
||||
|
||||
|
||||
#define IEEE80211_WEP_NKID 4 /* number of key ids */
|
||||
|
||||
/************************/
|
||||
/* Key Cache Management */
|
||||
/************************/
|
||||
|
||||
int ath_hw_keyreset(struct ath_common *common, u16 entry)
|
||||
{
|
||||
u32 keyType;
|
||||
void *ah = common->ah;
|
||||
|
||||
if (entry >= common->keymax) {
|
||||
DBG("ath: keycache entry %d out of range\n", entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
|
||||
REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
|
||||
|
||||
if (keyType == AR_KEYTABLE_TYPE_TKIP) {
|
||||
u16 micentry = entry + 64;
|
||||
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
|
||||
if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
|
||||
REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
|
||||
REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
|
||||
AR_KEYTABLE_TYPE_CLR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
||||
return 1;
|
||||
}
|
||||
59
src/drivers/net/ath/ath_main.c
Normal file
59
src/drivers/net/ath/ath_main.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ipxe/io.h>
|
||||
|
||||
#include "ath.h"
|
||||
|
||||
struct io_buffer *ath_rxbuf_alloc(struct ath_common *common,
|
||||
u32 len,
|
||||
u32 *iob_addr)
|
||||
{
|
||||
struct io_buffer *iob;
|
||||
u32 off;
|
||||
|
||||
/*
|
||||
* Cache-line-align. This is important (for the
|
||||
* 5210 at least) as not doing so causes bogus data
|
||||
* in rx'd frames.
|
||||
*/
|
||||
|
||||
/* Note: the kernel can allocate a value greater than
|
||||
* what we ask it to give us. We really only need 4 KB as that
|
||||
* is this hardware supports and in fact we need at least 3849
|
||||
* as that is the MAX AMSDU size this hardware supports.
|
||||
* Unfortunately this means we may get 8 KB here from the
|
||||
* kernel... and that is actually what is observed on some
|
||||
* systems :( */
|
||||
iob = alloc_iob(len + common->cachelsz - 1);
|
||||
if (iob != NULL) {
|
||||
*iob_addr = virt_to_bus(iob->data);
|
||||
off = ((unsigned long) iob->data) % common->cachelsz;
|
||||
if (off != 0)
|
||||
{
|
||||
iob_reserve(iob, common->cachelsz - off);
|
||||
*iob_addr += common->cachelsz - off;
|
||||
}
|
||||
} else {
|
||||
DBG("ath: iobuffer alloc of size %d failed\n", len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return iob;
|
||||
}
|
||||
602
src/drivers/net/ath/ath_regd.c
Normal file
602
src/drivers/net/ath/ath_regd.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "regd.h"
|
||||
#include "regd_common.h"
|
||||
|
||||
/*
|
||||
* This is a set of common rules used by our world regulatory domains.
|
||||
* We have 12 world regulatory domains. To save space we consolidate
|
||||
* the regulatory domains in 5 structures by frequency and change
|
||||
* the flags on our reg_notifier() on a case by case basis.
|
||||
*/
|
||||
|
||||
/* Only these channels all allow active scan on all world regulatory domains */
|
||||
#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
|
||||
|
||||
/* We enable active scan on these a case by case basis by regulatory domain */
|
||||
#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
|
||||
NL80211_RRF_PASSIVE_SCAN)
|
||||
#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
|
||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
|
||||
|
||||
/* We allow IBSS on these on a case by case basis by regulatory domain */
|
||||
#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\
|
||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
||||
#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\
|
||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
||||
#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\
|
||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
||||
|
||||
#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
|
||||
ATH9K_2GHZ_CH12_13, \
|
||||
ATH9K_2GHZ_CH14
|
||||
|
||||
#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \
|
||||
ATH9K_5GHZ_5470_5850
|
||||
|
||||
/* This one skips what we call "mid band" */
|
||||
#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
|
||||
ATH9K_5GHZ_5725_5850
|
||||
|
||||
///* Can be used for:
|
||||
// * 0x60, 0x61, 0x62 */
|
||||
//static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
|
||||
// .n_reg_rules = 5,
|
||||
// .alpha2 = "99",
|
||||
// .reg_rules = {
|
||||
// ATH9K_2GHZ_ALL,
|
||||
// ATH9K_5GHZ_ALL,
|
||||
// }
|
||||
//};
|
||||
//
|
||||
///* Can be used by 0x63 and 0x65 */
|
||||
//static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
|
||||
// .n_reg_rules = 4,
|
||||
// .alpha2 = "99",
|
||||
// .reg_rules = {
|
||||
// ATH9K_2GHZ_CH01_11,
|
||||
// ATH9K_2GHZ_CH12_13,
|
||||
// ATH9K_5GHZ_NO_MIDBAND,
|
||||
// }
|
||||
//};
|
||||
//
|
||||
///* Can be used by 0x64 only */
|
||||
//static const struct ieee80211_regdomain ath_world_regdom_64 = {
|
||||
// .n_reg_rules = 3,
|
||||
// .alpha2 = "99",
|
||||
// .reg_rules = {
|
||||
// ATH9K_2GHZ_CH01_11,
|
||||
// ATH9K_5GHZ_NO_MIDBAND,
|
||||
// }
|
||||
//};
|
||||
//
|
||||
///* Can be used by 0x66 and 0x69 */
|
||||
//static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
|
||||
// .n_reg_rules = 3,
|
||||
// .alpha2 = "99",
|
||||
// .reg_rules = {
|
||||
// ATH9K_2GHZ_CH01_11,
|
||||
// ATH9K_5GHZ_ALL,
|
||||
// }
|
||||
//};
|
||||
//
|
||||
///* Can be used by 0x67, 0x68, 0x6A and 0x6C */
|
||||
//static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
|
||||
// .n_reg_rules = 4,
|
||||
// .alpha2 = "99",
|
||||
// .reg_rules = {
|
||||
// ATH9K_2GHZ_CH01_11,
|
||||
// ATH9K_2GHZ_CH12_13,
|
||||
// ATH9K_5GHZ_ALL,
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//static inline int is_wwr_sku(u16 regd)
|
||||
//{
|
||||
// return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
|
||||
// (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
|
||||
// (regd == WORLD));
|
||||
//}
|
||||
//
|
||||
//static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
|
||||
//{
|
||||
// return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
|
||||
//}
|
||||
//
|
||||
//int ath_is_world_regd(struct ath_regulatory *reg)
|
||||
//{
|
||||
// return is_wwr_sku(ath_regd_get_eepromRD(reg));
|
||||
//}
|
||||
//
|
||||
//static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
|
||||
//{
|
||||
// /* this is the most restrictive */
|
||||
// return &ath_world_regdom_64;
|
||||
//}
|
||||
//
|
||||
//static const struct
|
||||
//ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
|
||||
//{
|
||||
// switch (reg->regpair->regDmnEnum) {
|
||||
// case 0x60:
|
||||
// case 0x61:
|
||||
// case 0x62:
|
||||
// return &ath_world_regdom_60_61_62;
|
||||
// case 0x63:
|
||||
// case 0x65:
|
||||
// return &ath_world_regdom_63_65;
|
||||
// case 0x64:
|
||||
// return &ath_world_regdom_64;
|
||||
// case 0x66:
|
||||
// case 0x69:
|
||||
// return &ath_world_regdom_66_69;
|
||||
// case 0x67:
|
||||
// case 0x68:
|
||||
// case 0x6A:
|
||||
// case 0x6C:
|
||||
// return &ath_world_regdom_67_68_6A_6C;
|
||||
// default:
|
||||
// WARN_ON(1);
|
||||
// return ath_default_world_regdomain();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//int ath_is_49ghz_allowed(u16 regdomain)
|
||||
//{
|
||||
// /* possibly more */
|
||||
// return regdomain == MKK9_MKKC;
|
||||
//}
|
||||
//
|
||||
///* Frequency is one where radar detection is required */
|
||||
//static int ath_is_radar_freq(u16 center_freq)
|
||||
//{
|
||||
// return (center_freq >= 5260 && center_freq <= 5700);
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * N.B: These exception rules do not apply radar freqs.
|
||||
// *
|
||||
// * - We enable adhoc (or beaconing) if allowed by 11d
|
||||
// * - We enable active scan if the channel is allowed by 11d
|
||||
// * - If no country IE has been processed and a we determine we have
|
||||
// * received a beacon on a channel we can enable active scan and
|
||||
// * adhoc (or beaconing).
|
||||
// */
|
||||
//static void
|
||||
//ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
// enum nl80211_reg_initiator initiator)
|
||||
//{
|
||||
// int band;
|
||||
// struct ieee80211_supported_band *sband;
|
||||
// const struct ieee80211_reg_rule *reg_rule;
|
||||
// struct net80211_channel *ch;
|
||||
// unsigned int i;
|
||||
// u32 bandwidth = 0;
|
||||
// int r;
|
||||
//
|
||||
// for (band = 0; band < NET80211_NR_BANDS; band++) {
|
||||
//
|
||||
// if (!wiphy->bands[band])
|
||||
// continue;
|
||||
//
|
||||
// sband = wiphy->bands[band];
|
||||
//
|
||||
// for (i = 0; i < sband->n_channels; i++) {
|
||||
//
|
||||
// ch = &sband->channels[i];
|
||||
//
|
||||
// if (ath_is_radar_freq(ch->center_freq) ||
|
||||
// (ch->flags & IEEE80211_CHAN_RADAR))
|
||||
// continue;
|
||||
//
|
||||
// if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||
// r = freq_reg_info(wiphy,
|
||||
// ch->center_freq,
|
||||
// bandwidth,
|
||||
// ®_rule);
|
||||
// if (r)
|
||||
// continue;
|
||||
// /*
|
||||
// * If 11d had a rule for this channel ensure
|
||||
// * we enable adhoc/beaconing if it allows us to
|
||||
// * use it. Note that we would have disabled it
|
||||
// * by applying our static world regdomain by
|
||||
// * default during init, prior to calling our
|
||||
// * regulatory_hint().
|
||||
// */
|
||||
// if (!(reg_rule->flags &
|
||||
// NL80211_RRF_NO_IBSS))
|
||||
// ch->flags &=
|
||||
// ~IEEE80211_CHAN_NO_IBSS;
|
||||
// if (!(reg_rule->flags &
|
||||
// NL80211_RRF_PASSIVE_SCAN))
|
||||
// ch->flags &=
|
||||
// ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// } else {
|
||||
// if (ch->beacon_found)
|
||||
// ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
|
||||
// IEEE80211_CHAN_PASSIVE_SCAN);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
///* Allows active scan scan on Ch 12 and 13 */
|
||||
//static void
|
||||
//ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||
// enum nl80211_reg_initiator initiator)
|
||||
//{
|
||||
// struct ieee80211_supported_band *sband;
|
||||
// struct net80211_channel *ch;
|
||||
// const struct ieee80211_reg_rule *reg_rule;
|
||||
// u32 bandwidth = 0;
|
||||
// int r;
|
||||
//
|
||||
// sband = wiphy->bands[NET80211_BAND_2GHZ];
|
||||
//
|
||||
// /*
|
||||
// * If no country IE has been received always enable active scan
|
||||
// * on these channels. This is only done for specific regulatory SKUs
|
||||
// */
|
||||
// if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||
// ch = &sband->channels[11]; /* CH 12 */
|
||||
// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// ch = &sband->channels[12]; /* CH 13 */
|
||||
// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * If a country IE has been received check its rule for this
|
||||
// * channel first before enabling active scan. The passive scan
|
||||
// * would have been enforced by the initial processing of our
|
||||
// * custom regulatory domain.
|
||||
// */
|
||||
//
|
||||
// ch = &sband->channels[11]; /* CH 12 */
|
||||
// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule);
|
||||
// if (!r) {
|
||||
// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
||||
// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// }
|
||||
//
|
||||
// ch = &sband->channels[12]; /* CH 13 */
|
||||
// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule);
|
||||
// if (!r) {
|
||||
// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
||||
// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
|
||||
//static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
|
||||
//{
|
||||
// struct ieee80211_supported_band *sband;
|
||||
// struct net80211_channel *ch;
|
||||
// unsigned int i;
|
||||
//
|
||||
// if (!wiphy->bands[NET80211_BAND_5GHZ])
|
||||
// return;
|
||||
//
|
||||
// sband = wiphy->bands[NET80211_BAND_5GHZ];
|
||||
//
|
||||
// for (i = 0; i < sband->n_channels; i++) {
|
||||
// ch = &sband->channels[i];
|
||||
// if (!ath_is_radar_freq(ch->center_freq))
|
||||
// continue;
|
||||
// /* We always enable radar detection/DFS on this
|
||||
// * frequency range. Additionally we also apply on
|
||||
// * this frequency range:
|
||||
// * - If STA mode does not yet have DFS supports disable
|
||||
// * active scanning
|
||||
// * - If adhoc mode does not support DFS yet then
|
||||
// * disable adhoc in the frequency.
|
||||
// * - If AP mode does not yet support radar detection/DFS
|
||||
// * do not allow AP mode
|
||||
// */
|
||||
// if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
||||
// ch->flags |= IEEE80211_CHAN_RADAR |
|
||||
// IEEE80211_CHAN_NO_IBSS |
|
||||
// IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//static void ath_reg_apply_world_flags(struct wiphy *wiphy,
|
||||
// enum nl80211_reg_initiator initiator,
|
||||
// struct ath_regulatory *reg)
|
||||
//{
|
||||
// switch (reg->regpair->regDmnEnum) {
|
||||
// case 0x60:
|
||||
// case 0x63:
|
||||
// case 0x66:
|
||||
// case 0x67:
|
||||
// case 0x6C:
|
||||
// ath_reg_apply_beaconing_flags(wiphy, initiator);
|
||||
// break;
|
||||
// case 0x68:
|
||||
// ath_reg_apply_beaconing_flags(wiphy, initiator);
|
||||
// ath_reg_apply_active_scan_flags(wiphy, initiator);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
// struct regulatory_request *request,
|
||||
// struct ath_regulatory *reg)
|
||||
//{
|
||||
// /* We always apply this */
|
||||
// ath_reg_apply_radar_flags(wiphy);
|
||||
//
|
||||
// /*
|
||||
// * This would happen when we have sent a custom regulatory request
|
||||
// * a world regulatory domain and the scheduler hasn't yet processed
|
||||
// * any pending requests in the queue.
|
||||
// */
|
||||
// if (!request)
|
||||
// return 0;
|
||||
//
|
||||
// switch (request->initiator) {
|
||||
// case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
// case NL80211_REGDOM_SET_BY_CORE:
|
||||
// case NL80211_REGDOM_SET_BY_USER:
|
||||
// break;
|
||||
// case NL80211_REGDOM_SET_BY_COUNTRY_IE:
|
||||
// if (ath_is_world_regd(reg))
|
||||
// ath_reg_apply_world_flags(wiphy, request->initiator,
|
||||
// reg);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
//static int ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
|
||||
//{
|
||||
// u16 rd = ath_regd_get_eepromRD(reg);
|
||||
// int i;
|
||||
//
|
||||
// if (rd & COUNTRY_ERD_FLAG) {
|
||||
// /* EEPROM value is a country code */
|
||||
// u16 cc = rd & ~COUNTRY_ERD_FLAG;
|
||||
// DBG2(
|
||||
// "ath: EEPROM indicates we should expect "
|
||||
// "a country code\n");
|
||||
// for (i = 0; i < ARRAY_SIZE(allCountries); i++)
|
||||
// if (allCountries[i].countryCode == cc)
|
||||
// return 1;
|
||||
// } else {
|
||||
// /* EEPROM value is a regpair value */
|
||||
// if (rd != CTRY_DEFAULT)
|
||||
// DBG2("ath: EEPROM indicates we "
|
||||
// "should expect a direct regpair map\n");
|
||||
// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
|
||||
// if (regDomainPairs[i].regDmnEnum == rd)
|
||||
// return 1;
|
||||
// }
|
||||
// DBG(
|
||||
// "ath: invalid regulatory domain/country code 0x%x\n", rd);
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
///* EEPROM country code to regpair mapping */
|
||||
//static struct country_code_to_enum_rd*
|
||||
//ath_regd_find_country(u16 countryCode)
|
||||
//{
|
||||
// int i;
|
||||
//
|
||||
// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
|
||||
// if (allCountries[i].countryCode == countryCode)
|
||||
// return &allCountries[i];
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
///* EEPROM rd code to regpair mapping */
|
||||
//static struct country_code_to_enum_rd*
|
||||
//ath_regd_find_country_by_rd(int regdmn)
|
||||
//{
|
||||
// int i;
|
||||
//
|
||||
// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
|
||||
// if (allCountries[i].regDmnEnum == regdmn)
|
||||
// return &allCountries[i];
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
///* Returns the map of the EEPROM set RD to a country code */
|
||||
//static u16 ath_regd_get_default_country(u16 rd)
|
||||
//{
|
||||
// if (rd & COUNTRY_ERD_FLAG) {
|
||||
// struct country_code_to_enum_rd *country = NULL;
|
||||
// u16 cc = rd & ~COUNTRY_ERD_FLAG;
|
||||
//
|
||||
// country = ath_regd_find_country(cc);
|
||||
// if (country != NULL)
|
||||
// return cc;
|
||||
// }
|
||||
//
|
||||
// return CTRY_DEFAULT;
|
||||
//}
|
||||
//
|
||||
//static struct reg_dmn_pair_mapping*
|
||||
//ath_get_regpair(int regdmn)
|
||||
//{
|
||||
// int i;
|
||||
//
|
||||
// if (regdmn == NO_ENUMRD)
|
||||
// return NULL;
|
||||
// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
|
||||
// if (regDomainPairs[i].regDmnEnum == regdmn)
|
||||
// return ®DomainPairs[i];
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
//static int
|
||||
//ath_regd_init_wiphy(struct ath_regulatory *reg,
|
||||
// struct wiphy *wiphy,
|
||||
// int (*reg_notifier)(struct wiphy *wiphy,
|
||||
// struct regulatory_request *request))
|
||||
//{
|
||||
// const struct ieee80211_regdomain *regd;
|
||||
//
|
||||
// wiphy->reg_notifier = reg_notifier;
|
||||
// wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
|
||||
//
|
||||
// if (ath_is_world_regd(reg)) {
|
||||
// /*
|
||||
// * Anything applied here (prior to wiphy registration) gets
|
||||
// * saved on the wiphy orig_* parameters
|
||||
// */
|
||||
// regd = ath_world_regdomain(reg);
|
||||
// wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
||||
// } else {
|
||||
// /*
|
||||
// * This gets applied in the case of the absence of CRDA,
|
||||
// * it's our own custom world regulatory domain, similar to
|
||||
// * cfg80211's but we enable passive scanning.
|
||||
// */
|
||||
// regd = ath_default_world_regdomain();
|
||||
// }
|
||||
// wiphy_apply_custom_regulatory(wiphy, regd);
|
||||
// ath_reg_apply_radar_flags(wiphy);
|
||||
// ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Some users have reported their EEPROM programmed with
|
||||
// * 0x8000 set, this is not a supported regulatory domain
|
||||
// * but since we have more than one user with it we need
|
||||
// * a solution for them. We default to 0x64, which is the
|
||||
// * default Atheros world regulatory domain.
|
||||
// */
|
||||
//static void ath_regd_sanitize(struct ath_regulatory *reg)
|
||||
//{
|
||||
// if (reg->current_rd != COUNTRY_ERD_FLAG)
|
||||
// return;
|
||||
// DBG2("ath: EEPROM regdomain sanitized\n");
|
||||
// reg->current_rd = 0x64;
|
||||
//}
|
||||
//
|
||||
//int
|
||||
//ath_regd_init(struct ath_regulatory *reg,
|
||||
// struct wiphy *wiphy,
|
||||
// int (*reg_notifier)(struct wiphy *wiphy,
|
||||
// struct regulatory_request *request))
|
||||
//{
|
||||
// struct country_code_to_enum_rd *country = NULL;
|
||||
// u16 regdmn;
|
||||
//
|
||||
// if (!reg)
|
||||
// return -EINVAL;
|
||||
//
|
||||
// ath_regd_sanitize(reg);
|
||||
//
|
||||
// DBG2("ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
|
||||
//
|
||||
// if (!ath_regd_is_eeprom_valid(reg)) {
|
||||
// DBG("ath: Invalid EEPROM contents\n");
|
||||
// return -EINVAL;
|
||||
// }
|
||||
//
|
||||
// regdmn = ath_regd_get_eepromRD(reg);
|
||||
// reg->country_code = ath_regd_get_default_country(regdmn);
|
||||
//
|
||||
// if (reg->country_code == CTRY_DEFAULT &&
|
||||
// regdmn == CTRY_DEFAULT) {
|
||||
// DBG2("ath: EEPROM indicates default "
|
||||
// "country code should be used\n");
|
||||
// reg->country_code = CTRY_UNITED_STATES;
|
||||
// }
|
||||
//
|
||||
// if (reg->country_code == CTRY_DEFAULT) {
|
||||
// country = NULL;
|
||||
// } else {
|
||||
// DBG2("ath: doing EEPROM country->regdmn "
|
||||
// "map search\n");
|
||||
// country = ath_regd_find_country(reg->country_code);
|
||||
// if (country == NULL) {
|
||||
// DBG(
|
||||
// "ath: no valid country maps found for "
|
||||
// "country code: 0x%0x\n",
|
||||
// reg->country_code);
|
||||
// return -EINVAL;
|
||||
// } else {
|
||||
// regdmn = country->regDmnEnum;
|
||||
// DBG2("ath: country maps to "
|
||||
// "regdmn code: 0x%0x\n",
|
||||
// regdmn);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// reg->regpair = ath_get_regpair(regdmn);
|
||||
//
|
||||
// if (!reg->regpair) {
|
||||
// DBG("ath: "
|
||||
// "No regulatory domain pair found, cannot continue\n");
|
||||
// return -EINVAL;
|
||||
// }
|
||||
//
|
||||
// if (!country)
|
||||
// country = ath_regd_find_country_by_rd(regdmn);
|
||||
//
|
||||
// if (country) {
|
||||
// reg->alpha2[0] = country->isoName[0];
|
||||
// reg->alpha2[1] = country->isoName[1];
|
||||
// } else {
|
||||
// reg->alpha2[0] = '0';
|
||||
// reg->alpha2[1] = '0';
|
||||
// }
|
||||
//
|
||||
// DBG2("ath: Country alpha2 being used: %c%c\n",
|
||||
// reg->alpha2[0], reg->alpha2[1]);
|
||||
// DBG2("ath: Regpair used: 0x%0x\n",
|
||||
// reg->regpair->regDmnEnum);
|
||||
//
|
||||
// ath_regd_init_wiphy(reg, wiphy, reg_notifier);
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
|
||||
int band)
|
||||
{
|
||||
/* TODO Cottsay: reg */
|
||||
// if (!reg->regpair ||
|
||||
// (reg->country_code == CTRY_DEFAULT &&
|
||||
// is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
|
||||
// return SD_NO_CTL;
|
||||
// }
|
||||
|
||||
switch (band) {
|
||||
case NET80211_BAND_2GHZ:
|
||||
return reg->regpair->reg_2ghz_ctl;
|
||||
case NET80211_BAND_5GHZ:
|
||||
return reg->regpair->reg_5ghz_ctl;
|
||||
default:
|
||||
return NO_CTL;
|
||||
}
|
||||
}
|
||||
64
src/drivers/net/ath/reg.h
Normal file
64
src/drivers/net/ath/reg.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH_REGISTERS_H
|
||||
#define ATH_REGISTERS_H
|
||||
|
||||
#define AR_MIBC 0x0040
|
||||
#define AR_MIBC_COW 0x00000001
|
||||
#define AR_MIBC_FMC 0x00000002
|
||||
#define AR_MIBC_CMC 0x00000004
|
||||
#define AR_MIBC_MCS 0x00000008
|
||||
|
||||
/*
|
||||
* BSSID mask registers. See ath_hw_set_bssid_mask()
|
||||
* for detailed documentation about these registers.
|
||||
*/
|
||||
#define AR_BSSMSKL 0x80e0
|
||||
#define AR_BSSMSKU 0x80e4
|
||||
|
||||
#define AR_TFCNT 0x80ec
|
||||
#define AR_RFCNT 0x80f0
|
||||
#define AR_RCCNT 0x80f4
|
||||
#define AR_CCCNT 0x80f8
|
||||
|
||||
#define AR_KEYTABLE_0 0x8800
|
||||
#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
|
||||
#define AR_KEY_CACHE_SIZE 128
|
||||
#define AR_RSVD_KEYTABLE_ENTRIES 4
|
||||
#define AR_KEY_TYPE 0x00000007
|
||||
#define AR_KEYTABLE_TYPE_40 0x00000000
|
||||
#define AR_KEYTABLE_TYPE_104 0x00000001
|
||||
#define AR_KEYTABLE_TYPE_128 0x00000003
|
||||
#define AR_KEYTABLE_TYPE_TKIP 0x00000004
|
||||
#define AR_KEYTABLE_TYPE_AES 0x00000005
|
||||
#define AR_KEYTABLE_TYPE_CCM 0x00000006
|
||||
#define AR_KEYTABLE_TYPE_CLR 0x00000007
|
||||
#define AR_KEYTABLE_ANT 0x00000008
|
||||
#define AR_KEYTABLE_VALID 0x00008000
|
||||
#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
|
||||
#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
|
||||
#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
|
||||
#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
|
||||
#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
|
||||
#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
|
||||
#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
|
||||
#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
|
||||
|
||||
#endif /* ATH_REGISTERS_H */
|
||||
263
src/drivers/net/ath/regd.h
Normal file
263
src/drivers/net/ath/regd.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef REGD_H
|
||||
#define REGD_H
|
||||
|
||||
#include "ath.h"
|
||||
|
||||
enum ctl_group {
|
||||
CTL_FCC = 0x10,
|
||||
CTL_MKK = 0x40,
|
||||
CTL_ETSI = 0x30,
|
||||
};
|
||||
|
||||
#define NO_CTL 0xff
|
||||
#define SD_NO_CTL 0xE0
|
||||
#define NO_CTL 0xff
|
||||
#define CTL_11A 0
|
||||
#define CTL_11B 1
|
||||
#define CTL_11G 2
|
||||
#define CTL_2GHT20 5
|
||||
#define CTL_5GHT20 6
|
||||
#define CTL_2GHT40 7
|
||||
#define CTL_5GHT40 8
|
||||
|
||||
#define CTRY_DEBUG 0x1ff
|
||||
#define CTRY_DEFAULT 0
|
||||
|
||||
#define COUNTRY_ERD_FLAG 0x8000
|
||||
#define WORLDWIDE_ROAMING_FLAG 0x4000
|
||||
|
||||
#define MULTI_DOMAIN_MASK 0xFF00
|
||||
|
||||
#define WORLD_SKU_MASK 0x00F0
|
||||
#define WORLD_SKU_PREFIX 0x0060
|
||||
|
||||
#define CHANNEL_HALF_BW 10
|
||||
#define CHANNEL_QUARTER_BW 5
|
||||
|
||||
struct country_code_to_enum_rd {
|
||||
u16 countryCode;
|
||||
u16 regDmnEnum;
|
||||
const char *isoName;
|
||||
};
|
||||
|
||||
enum CountryCode {
|
||||
CTRY_ALBANIA = 8,
|
||||
CTRY_ALGERIA = 12,
|
||||
CTRY_ARGENTINA = 32,
|
||||
CTRY_ARMENIA = 51,
|
||||
CTRY_ARUBA = 533,
|
||||
CTRY_AUSTRALIA = 36,
|
||||
CTRY_AUSTRIA = 40,
|
||||
CTRY_AZERBAIJAN = 31,
|
||||
CTRY_BAHRAIN = 48,
|
||||
CTRY_BANGLADESH = 50,
|
||||
CTRY_BARBADOS = 52,
|
||||
CTRY_BELARUS = 112,
|
||||
CTRY_BELGIUM = 56,
|
||||
CTRY_BELIZE = 84,
|
||||
CTRY_BOLIVIA = 68,
|
||||
CTRY_BOSNIA_HERZ = 70,
|
||||
CTRY_BRAZIL = 76,
|
||||
CTRY_BRUNEI_DARUSSALAM = 96,
|
||||
CTRY_BULGARIA = 100,
|
||||
CTRY_CAMBODIA = 116,
|
||||
CTRY_CANADA = 124,
|
||||
CTRY_CHILE = 152,
|
||||
CTRY_CHINA = 156,
|
||||
CTRY_COLOMBIA = 170,
|
||||
CTRY_COSTA_RICA = 188,
|
||||
CTRY_CROATIA = 191,
|
||||
CTRY_CYPRUS = 196,
|
||||
CTRY_CZECH = 203,
|
||||
CTRY_DENMARK = 208,
|
||||
CTRY_DOMINICAN_REPUBLIC = 214,
|
||||
CTRY_ECUADOR = 218,
|
||||
CTRY_EGYPT = 818,
|
||||
CTRY_EL_SALVADOR = 222,
|
||||
CTRY_ESTONIA = 233,
|
||||
CTRY_FAEROE_ISLANDS = 234,
|
||||
CTRY_FINLAND = 246,
|
||||
CTRY_FRANCE = 250,
|
||||
CTRY_GEORGIA = 268,
|
||||
CTRY_GERMANY = 276,
|
||||
CTRY_GREECE = 300,
|
||||
CTRY_GREENLAND = 304,
|
||||
CTRY_GRENEDA = 308,
|
||||
CTRY_GUAM = 316,
|
||||
CTRY_GUATEMALA = 320,
|
||||
CTRY_HAITI = 332,
|
||||
CTRY_HONDURAS = 340,
|
||||
CTRY_HONG_KONG = 344,
|
||||
CTRY_HUNGARY = 348,
|
||||
CTRY_ICELAND = 352,
|
||||
CTRY_INDIA = 356,
|
||||
CTRY_INDONESIA = 360,
|
||||
CTRY_IRAN = 364,
|
||||
CTRY_IRAQ = 368,
|
||||
CTRY_IRELAND = 372,
|
||||
CTRY_ISRAEL = 376,
|
||||
CTRY_ITALY = 380,
|
||||
CTRY_JAMAICA = 388,
|
||||
CTRY_JAPAN = 392,
|
||||
CTRY_JORDAN = 400,
|
||||
CTRY_KAZAKHSTAN = 398,
|
||||
CTRY_KENYA = 404,
|
||||
CTRY_KOREA_NORTH = 408,
|
||||
CTRY_KOREA_ROC = 410,
|
||||
CTRY_KOREA_ROC2 = 411,
|
||||
CTRY_KOREA_ROC3 = 412,
|
||||
CTRY_KUWAIT = 414,
|
||||
CTRY_LATVIA = 428,
|
||||
CTRY_LEBANON = 422,
|
||||
CTRY_LIBYA = 434,
|
||||
CTRY_LIECHTENSTEIN = 438,
|
||||
CTRY_LITHUANIA = 440,
|
||||
CTRY_LUXEMBOURG = 442,
|
||||
CTRY_MACAU = 446,
|
||||
CTRY_MACEDONIA = 807,
|
||||
CTRY_MALAYSIA = 458,
|
||||
CTRY_MALTA = 470,
|
||||
CTRY_MEXICO = 484,
|
||||
CTRY_MONACO = 492,
|
||||
CTRY_MOROCCO = 504,
|
||||
CTRY_NEPAL = 524,
|
||||
CTRY_NETHERLANDS = 528,
|
||||
CTRY_NETHERLANDS_ANTILLES = 530,
|
||||
CTRY_NEW_ZEALAND = 554,
|
||||
CTRY_NICARAGUA = 558,
|
||||
CTRY_NORWAY = 578,
|
||||
CTRY_OMAN = 512,
|
||||
CTRY_PAKISTAN = 586,
|
||||
CTRY_PANAMA = 591,
|
||||
CTRY_PAPUA_NEW_GUINEA = 598,
|
||||
CTRY_PARAGUAY = 600,
|
||||
CTRY_PERU = 604,
|
||||
CTRY_PHILIPPINES = 608,
|
||||
CTRY_POLAND = 616,
|
||||
CTRY_PORTUGAL = 620,
|
||||
CTRY_PUERTO_RICO = 630,
|
||||
CTRY_QATAR = 634,
|
||||
CTRY_ROMANIA = 642,
|
||||
CTRY_RUSSIA = 643,
|
||||
CTRY_SAUDI_ARABIA = 682,
|
||||
CTRY_SERBIA_MONTENEGRO = 891,
|
||||
CTRY_SINGAPORE = 702,
|
||||
CTRY_SLOVAKIA = 703,
|
||||
CTRY_SLOVENIA = 705,
|
||||
CTRY_SOUTH_AFRICA = 710,
|
||||
CTRY_SPAIN = 724,
|
||||
CTRY_SRI_LANKA = 144,
|
||||
CTRY_SWEDEN = 752,
|
||||
CTRY_SWITZERLAND = 756,
|
||||
CTRY_SYRIA = 760,
|
||||
CTRY_TAIWAN = 158,
|
||||
CTRY_THAILAND = 764,
|
||||
CTRY_TRINIDAD_Y_TOBAGO = 780,
|
||||
CTRY_TUNISIA = 788,
|
||||
CTRY_TURKEY = 792,
|
||||
CTRY_UAE = 784,
|
||||
CTRY_UKRAINE = 804,
|
||||
CTRY_UNITED_KINGDOM = 826,
|
||||
CTRY_UNITED_STATES = 840,
|
||||
CTRY_UNITED_STATES_FCC49 = 842,
|
||||
CTRY_URUGUAY = 858,
|
||||
CTRY_UZBEKISTAN = 860,
|
||||
CTRY_VENEZUELA = 862,
|
||||
CTRY_VIET_NAM = 704,
|
||||
CTRY_YEMEN = 887,
|
||||
CTRY_ZIMBABWE = 716,
|
||||
CTRY_JAPAN1 = 393,
|
||||
CTRY_JAPAN2 = 394,
|
||||
CTRY_JAPAN3 = 395,
|
||||
CTRY_JAPAN4 = 396,
|
||||
CTRY_JAPAN5 = 397,
|
||||
CTRY_JAPAN6 = 4006,
|
||||
CTRY_JAPAN7 = 4007,
|
||||
CTRY_JAPAN8 = 4008,
|
||||
CTRY_JAPAN9 = 4009,
|
||||
CTRY_JAPAN10 = 4010,
|
||||
CTRY_JAPAN11 = 4011,
|
||||
CTRY_JAPAN12 = 4012,
|
||||
CTRY_JAPAN13 = 4013,
|
||||
CTRY_JAPAN14 = 4014,
|
||||
CTRY_JAPAN15 = 4015,
|
||||
CTRY_JAPAN16 = 4016,
|
||||
CTRY_JAPAN17 = 4017,
|
||||
CTRY_JAPAN18 = 4018,
|
||||
CTRY_JAPAN19 = 4019,
|
||||
CTRY_JAPAN20 = 4020,
|
||||
CTRY_JAPAN21 = 4021,
|
||||
CTRY_JAPAN22 = 4022,
|
||||
CTRY_JAPAN23 = 4023,
|
||||
CTRY_JAPAN24 = 4024,
|
||||
CTRY_JAPAN25 = 4025,
|
||||
CTRY_JAPAN26 = 4026,
|
||||
CTRY_JAPAN27 = 4027,
|
||||
CTRY_JAPAN28 = 4028,
|
||||
CTRY_JAPAN29 = 4029,
|
||||
CTRY_JAPAN30 = 4030,
|
||||
CTRY_JAPAN31 = 4031,
|
||||
CTRY_JAPAN32 = 4032,
|
||||
CTRY_JAPAN33 = 4033,
|
||||
CTRY_JAPAN34 = 4034,
|
||||
CTRY_JAPAN35 = 4035,
|
||||
CTRY_JAPAN36 = 4036,
|
||||
CTRY_JAPAN37 = 4037,
|
||||
CTRY_JAPAN38 = 4038,
|
||||
CTRY_JAPAN39 = 4039,
|
||||
CTRY_JAPAN40 = 4040,
|
||||
CTRY_JAPAN41 = 4041,
|
||||
CTRY_JAPAN42 = 4042,
|
||||
CTRY_JAPAN43 = 4043,
|
||||
CTRY_JAPAN44 = 4044,
|
||||
CTRY_JAPAN45 = 4045,
|
||||
CTRY_JAPAN46 = 4046,
|
||||
CTRY_JAPAN47 = 4047,
|
||||
CTRY_JAPAN48 = 4048,
|
||||
CTRY_JAPAN49 = 4049,
|
||||
CTRY_JAPAN50 = 4050,
|
||||
CTRY_JAPAN51 = 4051,
|
||||
CTRY_JAPAN52 = 4052,
|
||||
CTRY_JAPAN53 = 4053,
|
||||
CTRY_JAPAN54 = 4054,
|
||||
CTRY_JAPAN55 = 4055,
|
||||
CTRY_JAPAN56 = 4056,
|
||||
CTRY_JAPAN57 = 4057,
|
||||
CTRY_JAPAN58 = 4058,
|
||||
CTRY_JAPAN59 = 4059,
|
||||
CTRY_AUSTRALIA2 = 5000,
|
||||
CTRY_CANADA2 = 5001,
|
||||
CTRY_BELGIUM2 = 5002
|
||||
};
|
||||
|
||||
int ath_is_world_regd(struct ath_regulatory *reg);
|
||||
int ath_is_49ghz_allowed(u16 redomain);
|
||||
//int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
|
||||
// int (*reg_notifier)(struct wiphy *wiphy,
|
||||
// struct regulatory_request *request));
|
||||
u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
|
||||
int band);
|
||||
//int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
// struct regulatory_request *request,
|
||||
// struct ath_regulatory *reg);
|
||||
|
||||
#endif
|
||||
481
src/drivers/net/ath/regd_common.h
Normal file
481
src/drivers/net/ath/regd_common.h
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
|
||||
* Original from Linux kernel 3.0.1
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef REGD_COMMON_H
|
||||
#define REGD_COMMON_H
|
||||
|
||||
enum EnumRd {
|
||||
NO_ENUMRD = 0x00,
|
||||
NULL1_WORLD = 0x03,
|
||||
NULL1_ETSIB = 0x07,
|
||||
NULL1_ETSIC = 0x08,
|
||||
FCC1_FCCA = 0x10,
|
||||
FCC1_WORLD = 0x11,
|
||||
FCC4_FCCA = 0x12,
|
||||
FCC5_FCCA = 0x13,
|
||||
FCC6_FCCA = 0x14,
|
||||
|
||||
FCC2_FCCA = 0x20,
|
||||
FCC2_WORLD = 0x21,
|
||||
FCC2_ETSIC = 0x22,
|
||||
FCC6_WORLD = 0x23,
|
||||
FRANCE_RES = 0x31,
|
||||
FCC3_FCCA = 0x3A,
|
||||
FCC3_WORLD = 0x3B,
|
||||
|
||||
ETSI1_WORLD = 0x37,
|
||||
ETSI3_ETSIA = 0x32,
|
||||
ETSI2_WORLD = 0x35,
|
||||
ETSI3_WORLD = 0x36,
|
||||
ETSI4_WORLD = 0x30,
|
||||
ETSI4_ETSIC = 0x38,
|
||||
ETSI5_WORLD = 0x39,
|
||||
ETSI6_WORLD = 0x34,
|
||||
ETSI_RESERVED = 0x33,
|
||||
|
||||
MKK1_MKKA = 0x40,
|
||||
MKK1_MKKB = 0x41,
|
||||
APL4_WORLD = 0x42,
|
||||
MKK2_MKKA = 0x43,
|
||||
APL_RESERVED = 0x44,
|
||||
APL2_WORLD = 0x45,
|
||||
APL2_APLC = 0x46,
|
||||
APL3_WORLD = 0x47,
|
||||
MKK1_FCCA = 0x48,
|
||||
APL2_APLD = 0x49,
|
||||
MKK1_MKKA1 = 0x4A,
|
||||
MKK1_MKKA2 = 0x4B,
|
||||
MKK1_MKKC = 0x4C,
|
||||
|
||||
APL3_FCCA = 0x50,
|
||||
APL1_WORLD = 0x52,
|
||||
APL1_FCCA = 0x53,
|
||||
APL1_APLA = 0x54,
|
||||
APL1_ETSIC = 0x55,
|
||||
APL2_ETSIC = 0x56,
|
||||
APL5_WORLD = 0x58,
|
||||
APL6_WORLD = 0x5B,
|
||||
APL7_FCCA = 0x5C,
|
||||
APL8_WORLD = 0x5D,
|
||||
APL9_WORLD = 0x5E,
|
||||
|
||||
WOR0_WORLD = 0x60,
|
||||
WOR1_WORLD = 0x61,
|
||||
WOR2_WORLD = 0x62,
|
||||
WOR3_WORLD = 0x63,
|
||||
WOR4_WORLD = 0x64,
|
||||
WOR5_ETSIC = 0x65,
|
||||
|
||||
WOR01_WORLD = 0x66,
|
||||
WOR02_WORLD = 0x67,
|
||||
EU1_WORLD = 0x68,
|
||||
|
||||
WOR9_WORLD = 0x69,
|
||||
WORA_WORLD = 0x6A,
|
||||
WORB_WORLD = 0x6B,
|
||||
WORC_WORLD = 0x6C,
|
||||
|
||||
MKK3_MKKB = 0x80,
|
||||
MKK3_MKKA2 = 0x81,
|
||||
MKK3_MKKC = 0x82,
|
||||
|
||||
MKK4_MKKB = 0x83,
|
||||
MKK4_MKKA2 = 0x84,
|
||||
MKK4_MKKC = 0x85,
|
||||
|
||||
MKK5_MKKB = 0x86,
|
||||
MKK5_MKKA2 = 0x87,
|
||||
MKK5_MKKC = 0x88,
|
||||
|
||||
MKK6_MKKB = 0x89,
|
||||
MKK6_MKKA2 = 0x8A,
|
||||
MKK6_MKKC = 0x8B,
|
||||
|
||||
MKK7_MKKB = 0x8C,
|
||||
MKK7_MKKA2 = 0x8D,
|
||||
MKK7_MKKC = 0x8E,
|
||||
|
||||
MKK8_MKKB = 0x8F,
|
||||
MKK8_MKKA2 = 0x90,
|
||||
MKK8_MKKC = 0x91,
|
||||
|
||||
MKK14_MKKA1 = 0x92,
|
||||
MKK15_MKKA1 = 0x93,
|
||||
|
||||
MKK10_FCCA = 0xD0,
|
||||
MKK10_MKKA1 = 0xD1,
|
||||
MKK10_MKKC = 0xD2,
|
||||
MKK10_MKKA2 = 0xD3,
|
||||
|
||||
MKK11_MKKA = 0xD4,
|
||||
MKK11_FCCA = 0xD5,
|
||||
MKK11_MKKA1 = 0xD6,
|
||||
MKK11_MKKC = 0xD7,
|
||||
MKK11_MKKA2 = 0xD8,
|
||||
|
||||
MKK12_MKKA = 0xD9,
|
||||
MKK12_FCCA = 0xDA,
|
||||
MKK12_MKKA1 = 0xDB,
|
||||
MKK12_MKKC = 0xDC,
|
||||
MKK12_MKKA2 = 0xDD,
|
||||
|
||||
MKK13_MKKB = 0xDE,
|
||||
|
||||
MKK3_MKKA = 0xF0,
|
||||
MKK3_MKKA1 = 0xF1,
|
||||
MKK3_FCCA = 0xF2,
|
||||
MKK4_MKKA = 0xF3,
|
||||
MKK4_MKKA1 = 0xF4,
|
||||
MKK4_FCCA = 0xF5,
|
||||
MKK9_MKKA = 0xF6,
|
||||
MKK10_MKKA = 0xF7,
|
||||
MKK6_MKKA1 = 0xF8,
|
||||
MKK6_FCCA = 0xF9,
|
||||
MKK7_MKKA1 = 0xFA,
|
||||
MKK7_FCCA = 0xFB,
|
||||
MKK9_FCCA = 0xFC,
|
||||
MKK9_MKKA1 = 0xFD,
|
||||
MKK9_MKKC = 0xFE,
|
||||
MKK9_MKKA2 = 0xFF,
|
||||
|
||||
WORLD = 0x0199,
|
||||
DEBUG_REG_DMN = 0x01ff,
|
||||
};
|
||||
|
||||
///* Regpair to CTL band mapping */
|
||||
//static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
||||
// /* regpair, 5 GHz CTL, 2 GHz CTL */
|
||||
// {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
|
||||
// {NULL1_WORLD, NO_CTL, CTL_ETSI},
|
||||
// {NULL1_ETSIB, NO_CTL, CTL_ETSI},
|
||||
// {NULL1_ETSIC, NO_CTL, CTL_ETSI},
|
||||
//
|
||||
// {FCC2_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {FCC2_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
// {FCC3_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {FCC3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {FCC4_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {FCC5_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {FCC6_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {FCC6_WORLD, CTL_FCC, CTL_ETSI},
|
||||
//
|
||||
// {ETSI1_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {ETSI2_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {ETSI3_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
//
|
||||
// /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
|
||||
// {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
|
||||
// {FRANCE_RES, CTL_ETSI, CTL_ETSI},
|
||||
//
|
||||
// {FCC1_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {FCC1_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {APL1_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {APL2_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {APL3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {APL4_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {APL5_WORLD, CTL_FCC, CTL_ETSI},
|
||||
// {APL6_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {APL8_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
// {APL9_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
//
|
||||
// {APL3_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {APL7_FCCA, CTL_FCC, CTL_FCC},
|
||||
// {APL1_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
// {APL2_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
// {APL2_APLD, CTL_FCC, NO_CTL},
|
||||
//
|
||||
// {MKK1_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK1_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK1_FCCA, CTL_MKK, CTL_FCC},
|
||||
// {MKK1_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK1_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK1_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK2_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_MKKC, CTL_MKK, CTL_MKK},
|
||||
// {MKK3_FCCA, CTL_MKK, CTL_FCC},
|
||||
//
|
||||
// {MKK4_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK4_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK4_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK4_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK4_MKKC, CTL_MKK, CTL_MKK},
|
||||
// {MKK4_FCCA, CTL_MKK, CTL_FCC},
|
||||
//
|
||||
// {MKK5_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK5_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK5_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK6_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK6_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK6_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK6_MKKC, CTL_MKK, CTL_MKK},
|
||||
// {MKK6_FCCA, CTL_MKK, CTL_FCC},
|
||||
//
|
||||
// {MKK7_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK7_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK7_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK7_MKKC, CTL_MKK, CTL_MKK},
|
||||
// {MKK7_FCCA, CTL_MKK, CTL_FCC},
|
||||
//
|
||||
// {MKK8_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK8_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK8_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK9_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK9_FCCA, CTL_MKK, CTL_FCC},
|
||||
// {MKK9_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK9_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK9_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK10_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK10_FCCA, CTL_MKK, CTL_FCC},
|
||||
// {MKK10_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK10_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK10_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK11_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK11_FCCA, CTL_MKK, CTL_FCC},
|
||||
// {MKK11_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK11_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK11_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK12_MKKA, CTL_MKK, CTL_MKK},
|
||||
// {MKK12_FCCA, CTL_MKK, CTL_FCC},
|
||||
// {MKK12_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK12_MKKA2, CTL_MKK, CTL_MKK},
|
||||
// {MKK12_MKKC, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {MKK13_MKKB, CTL_MKK, CTL_MKK},
|
||||
// {MKK14_MKKA1, CTL_MKK, CTL_MKK},
|
||||
// {MKK15_MKKA1, CTL_MKK, CTL_MKK},
|
||||
//
|
||||
// {WOR0_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR1_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR2_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR3_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR4_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR5_ETSIC, NO_CTL, NO_CTL},
|
||||
// {WOR01_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR02_WORLD, NO_CTL, NO_CTL},
|
||||
// {EU1_WORLD, NO_CTL, NO_CTL},
|
||||
// {WOR9_WORLD, NO_CTL, NO_CTL},
|
||||
// {WORA_WORLD, NO_CTL, NO_CTL},
|
||||
// {WORB_WORLD, NO_CTL, NO_CTL},
|
||||
// {WORC_WORLD, NO_CTL, NO_CTL},
|
||||
//};
|
||||
//
|
||||
//static struct country_code_to_enum_rd allCountries[] = {
|
||||
// {CTRY_DEBUG, NO_ENUMRD, "DB"},
|
||||
// {CTRY_DEFAULT, FCC1_FCCA, "CO"},
|
||||
// {CTRY_ALBANIA, NULL1_WORLD, "AL"},
|
||||
// {CTRY_ALGERIA, NULL1_WORLD, "DZ"},
|
||||
// {CTRY_ARGENTINA, FCC3_WORLD, "AR"},
|
||||
// {CTRY_ARMENIA, ETSI4_WORLD, "AM"},
|
||||
// {CTRY_ARUBA, ETSI1_WORLD, "AW"},
|
||||
// {CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
|
||||
// {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
|
||||
// {CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
|
||||
// {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
|
||||
// {CTRY_BAHRAIN, APL6_WORLD, "BH"},
|
||||
// {CTRY_BANGLADESH, NULL1_WORLD, "BD"},
|
||||
// {CTRY_BARBADOS, FCC2_WORLD, "BB"},
|
||||
// {CTRY_BELARUS, ETSI1_WORLD, "BY"},
|
||||
// {CTRY_BELGIUM, ETSI1_WORLD, "BE"},
|
||||
// {CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
|
||||
// {CTRY_BELIZE, APL1_ETSIC, "BZ"},
|
||||
// {CTRY_BOLIVIA, APL1_ETSIC, "BO"},
|
||||
// {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
|
||||
// {CTRY_BRAZIL, FCC3_WORLD, "BR"},
|
||||
// {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
|
||||
// {CTRY_BULGARIA, ETSI6_WORLD, "BG"},
|
||||
// {CTRY_CAMBODIA, ETSI1_WORLD, "KH"},
|
||||
// {CTRY_CANADA, FCC3_FCCA, "CA"},
|
||||
// {CTRY_CANADA2, FCC6_FCCA, "CA"},
|
||||
// {CTRY_CHILE, APL6_WORLD, "CL"},
|
||||
// {CTRY_CHINA, APL1_WORLD, "CN"},
|
||||
// {CTRY_COLOMBIA, FCC1_FCCA, "CO"},
|
||||
// {CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
|
||||
// {CTRY_CROATIA, ETSI1_WORLD, "HR"},
|
||||
// {CTRY_CYPRUS, ETSI1_WORLD, "CY"},
|
||||
// {CTRY_CZECH, ETSI3_WORLD, "CZ"},
|
||||
// {CTRY_DENMARK, ETSI1_WORLD, "DK"},
|
||||
// {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
|
||||
// {CTRY_ECUADOR, FCC1_WORLD, "EC"},
|
||||
// {CTRY_EGYPT, ETSI3_WORLD, "EG"},
|
||||
// {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"},
|
||||
// {CTRY_ESTONIA, ETSI1_WORLD, "EE"},
|
||||
// {CTRY_FINLAND, ETSI1_WORLD, "FI"},
|
||||
// {CTRY_FRANCE, ETSI1_WORLD, "FR"},
|
||||
// {CTRY_GEORGIA, ETSI4_WORLD, "GE"},
|
||||
// {CTRY_GERMANY, ETSI1_WORLD, "DE"},
|
||||
// {CTRY_GREECE, ETSI1_WORLD, "GR"},
|
||||
// {CTRY_GREENLAND, ETSI1_WORLD, "GL"},
|
||||
// {CTRY_GRENEDA, FCC3_FCCA, "GD"},
|
||||
// {CTRY_GUAM, FCC1_FCCA, "GU"},
|
||||
// {CTRY_GUATEMALA, FCC1_FCCA, "GT"},
|
||||
// {CTRY_HAITI, ETSI1_WORLD, "HT"},
|
||||
// {CTRY_HONDURAS, NULL1_WORLD, "HN"},
|
||||
// {CTRY_HONG_KONG, FCC3_WORLD, "HK"},
|
||||
// {CTRY_HUNGARY, ETSI1_WORLD, "HU"},
|
||||
// {CTRY_ICELAND, ETSI1_WORLD, "IS"},
|
||||
// {CTRY_INDIA, APL6_WORLD, "IN"},
|
||||
// {CTRY_INDONESIA, NULL1_WORLD, "ID"},
|
||||
// {CTRY_IRAN, APL1_WORLD, "IR"},
|
||||
// {CTRY_IRELAND, ETSI1_WORLD, "IE"},
|
||||
// {CTRY_ISRAEL, NULL1_WORLD, "IL"},
|
||||
// {CTRY_ITALY, ETSI1_WORLD, "IT"},
|
||||
// {CTRY_JAMAICA, FCC3_WORLD, "JM"},
|
||||
//
|
||||
// {CTRY_JAPAN, MKK1_MKKA, "JP"},
|
||||
// {CTRY_JAPAN1, MKK1_MKKB, "JP"},
|
||||
// {CTRY_JAPAN2, MKK1_FCCA, "JP"},
|
||||
// {CTRY_JAPAN3, MKK2_MKKA, "JP"},
|
||||
// {CTRY_JAPAN4, MKK1_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN5, MKK1_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN6, MKK1_MKKC, "JP"},
|
||||
// {CTRY_JAPAN7, MKK3_MKKB, "JP"},
|
||||
// {CTRY_JAPAN8, MKK3_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN9, MKK3_MKKC, "JP"},
|
||||
// {CTRY_JAPAN10, MKK4_MKKB, "JP"},
|
||||
// {CTRY_JAPAN11, MKK4_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN12, MKK4_MKKC, "JP"},
|
||||
// {CTRY_JAPAN13, MKK5_MKKB, "JP"},
|
||||
// {CTRY_JAPAN14, MKK5_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN15, MKK5_MKKC, "JP"},
|
||||
// {CTRY_JAPAN16, MKK6_MKKB, "JP"},
|
||||
// {CTRY_JAPAN17, MKK6_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN18, MKK6_MKKC, "JP"},
|
||||
// {CTRY_JAPAN19, MKK7_MKKB, "JP"},
|
||||
// {CTRY_JAPAN20, MKK7_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN21, MKK7_MKKC, "JP"},
|
||||
// {CTRY_JAPAN22, MKK8_MKKB, "JP"},
|
||||
// {CTRY_JAPAN23, MKK8_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN24, MKK8_MKKC, "JP"},
|
||||
// {CTRY_JAPAN25, MKK3_MKKA, "JP"},
|
||||
// {CTRY_JAPAN26, MKK3_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN27, MKK3_FCCA, "JP"},
|
||||
// {CTRY_JAPAN28, MKK4_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN29, MKK4_FCCA, "JP"},
|
||||
// {CTRY_JAPAN30, MKK6_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN31, MKK6_FCCA, "JP"},
|
||||
// {CTRY_JAPAN32, MKK7_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN33, MKK7_FCCA, "JP"},
|
||||
// {CTRY_JAPAN34, MKK9_MKKA, "JP"},
|
||||
// {CTRY_JAPAN35, MKK10_MKKA, "JP"},
|
||||
// {CTRY_JAPAN36, MKK4_MKKA, "JP"},
|
||||
// {CTRY_JAPAN37, MKK9_FCCA, "JP"},
|
||||
// {CTRY_JAPAN38, MKK9_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN39, MKK9_MKKC, "JP"},
|
||||
// {CTRY_JAPAN40, MKK9_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN41, MKK10_FCCA, "JP"},
|
||||
// {CTRY_JAPAN42, MKK10_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN43, MKK10_MKKC, "JP"},
|
||||
// {CTRY_JAPAN44, MKK10_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN45, MKK11_MKKA, "JP"},
|
||||
// {CTRY_JAPAN46, MKK11_FCCA, "JP"},
|
||||
// {CTRY_JAPAN47, MKK11_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN48, MKK11_MKKC, "JP"},
|
||||
// {CTRY_JAPAN49, MKK11_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN50, MKK12_MKKA, "JP"},
|
||||
// {CTRY_JAPAN51, MKK12_FCCA, "JP"},
|
||||
// {CTRY_JAPAN52, MKK12_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN53, MKK12_MKKC, "JP"},
|
||||
// {CTRY_JAPAN54, MKK12_MKKA2, "JP"},
|
||||
// {CTRY_JAPAN57, MKK13_MKKB, "JP"},
|
||||
// {CTRY_JAPAN58, MKK14_MKKA1, "JP"},
|
||||
// {CTRY_JAPAN59, MKK15_MKKA1, "JP"},
|
||||
//
|
||||
// {CTRY_JORDAN, ETSI2_WORLD, "JO"},
|
||||
// {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
|
||||
// {CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
|
||||
// {CTRY_KOREA_ROC, APL9_WORLD, "KR"},
|
||||
// {CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
|
||||
// {CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
|
||||
// {CTRY_KUWAIT, ETSI3_WORLD, "KW"},
|
||||
// {CTRY_LATVIA, ETSI1_WORLD, "LV"},
|
||||
// {CTRY_LEBANON, NULL1_WORLD, "LB"},
|
||||
// {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
|
||||
// {CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
|
||||
// {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
|
||||
// {CTRY_MACAU, FCC2_WORLD, "MO"},
|
||||
// {CTRY_MACEDONIA, NULL1_WORLD, "MK"},
|
||||
// {CTRY_MALAYSIA, APL8_WORLD, "MY"},
|
||||
// {CTRY_MALTA, ETSI1_WORLD, "MT"},
|
||||
// {CTRY_MEXICO, FCC1_FCCA, "MX"},
|
||||
// {CTRY_MONACO, ETSI4_WORLD, "MC"},
|
||||
// {CTRY_MOROCCO, APL4_WORLD, "MA"},
|
||||
// {CTRY_NEPAL, APL1_WORLD, "NP"},
|
||||
// {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
|
||||
// {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
|
||||
// {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
|
||||
// {CTRY_NORWAY, ETSI1_WORLD, "NO"},
|
||||
// {CTRY_OMAN, FCC3_WORLD, "OM"},
|
||||
// {CTRY_PAKISTAN, NULL1_WORLD, "PK"},
|
||||
// {CTRY_PANAMA, FCC1_FCCA, "PA"},
|
||||
// {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
|
||||
// {CTRY_PERU, APL1_WORLD, "PE"},
|
||||
// {CTRY_PHILIPPINES, APL1_WORLD, "PH"},
|
||||
// {CTRY_POLAND, ETSI1_WORLD, "PL"},
|
||||
// {CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
|
||||
// {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
|
||||
// {CTRY_QATAR, APL1_WORLD, "QA"},
|
||||
// {CTRY_ROMANIA, NULL1_WORLD, "RO"},
|
||||
// {CTRY_RUSSIA, NULL1_WORLD, "RU"},
|
||||
// {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
|
||||
// {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
|
||||
// {CTRY_SINGAPORE, APL6_WORLD, "SG"},
|
||||
// {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
|
||||
// {CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
|
||||
// {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
|
||||
// {CTRY_SPAIN, ETSI1_WORLD, "ES"},
|
||||
// {CTRY_SRI_LANKA, FCC3_WORLD, "LK"},
|
||||
// {CTRY_SWEDEN, ETSI1_WORLD, "SE"},
|
||||
// {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
|
||||
// {CTRY_SYRIA, NULL1_WORLD, "SY"},
|
||||
// {CTRY_TAIWAN, APL3_FCCA, "TW"},
|
||||
// {CTRY_THAILAND, FCC3_WORLD, "TH"},
|
||||
// {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"},
|
||||
// {CTRY_TUNISIA, ETSI3_WORLD, "TN"},
|
||||
// {CTRY_TURKEY, ETSI3_WORLD, "TR"},
|
||||
// {CTRY_UKRAINE, NULL1_WORLD, "UA"},
|
||||
// {CTRY_UAE, NULL1_WORLD, "AE"},
|
||||
// {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
|
||||
// {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
|
||||
// /* This "PS" is for US public safety actually... to support this we
|
||||
// * would need to assign new special alpha2 to CRDA db as with the world
|
||||
// * regdomain and use another alpha2 */
|
||||
// {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
|
||||
// {CTRY_URUGUAY, FCC3_WORLD, "UY"},
|
||||
// {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
|
||||
// {CTRY_VENEZUELA, APL2_ETSIC, "VE"},
|
||||
// {CTRY_VIET_NAM, NULL1_WORLD, "VN"},
|
||||
// {CTRY_YEMEN, NULL1_WORLD, "YE"},
|
||||
// {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
|
||||
//};
|
||||
|
||||
#endif
|
||||
@@ -137,6 +137,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#define ERRFILE_virtio_net ( ERRFILE_DRIVER | 0x005c0000 )
|
||||
#define ERRFILE_tap ( ERRFILE_DRIVER | 0x005d0000 )
|
||||
#define ERRFILE_igbvf_main ( ERRFILE_DRIVER | 0x005e0000 )
|
||||
#define ERRFILE_ath9k ( ERRFILE_DRIVER | 0x005f0000 )
|
||||
#define ERRFILE_ath ( ERRFILE_DRIVER | 0x00600000 )
|
||||
|
||||
#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
|
||||
#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
|
||||
|
||||
@@ -272,7 +272,7 @@ enum net80211_crypto_alg {
|
||||
#define NET80211_MAX_RATES 16
|
||||
|
||||
/** The maximum number of channels we allow to be configured simultaneously */
|
||||
#define NET80211_MAX_CHANNELS 32
|
||||
#define NET80211_MAX_CHANNELS 40
|
||||
|
||||
/** Seconds we'll wait to get all fragments of a packet */
|
||||
#define NET80211_FRAG_TIMEOUT 2
|
||||
|
||||
Reference in New Issue
Block a user