2009-01-31 02:31:53

by Nick Kossifidis

[permalink] [raw]
Subject: [PATCH 5/5] ath5k: Update reset code

* Update reset and sync with HALs
* Clean up eeprom settings and tweaking of initvals and put them on separate functions
* Set/Restore 32KHz ref clk operation
* Add some more documentation
TODO: Spur mitigation, tpc, half/quarter rate, compression etc


Signed-Off-by: Nick Kossifidis <[email protected]>

---
drivers/net/wireless/ath5k/ath5k.h | 12 +-
drivers/net/wireless/ath5k/attach.c | 16 +-
drivers/net/wireless/ath5k/eeprom.c | 12 +
drivers/net/wireless/ath5k/eeprom.h | 1 +
drivers/net/wireless/ath5k/reg.h | 41 +-
drivers/net/wireless/ath5k/reset.c | 901 ++++++++++++++++++++++++++---------
6 files changed, 711 insertions(+), 272 deletions(-)

diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 5b2e0da..a3313be 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -222,6 +222,8 @@
#endif

/* Initial values */
+#define AR5K_INIT_RSSI_THR 0x00000781
+#define AR5K_INIT_CYCRSSI_THR1 2
#define AR5K_INIT_TX_LATENCY 502
#define AR5K_INIT_USEC 39
#define AR5K_INIT_USEC_TURBO 79
@@ -313,7 +315,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_AR5424 0x90 /* Condor */
#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
#define AR5K_SREV_AR5414 0xa0 /* Eagle */
-#define AR5K_SREV_AR2415 0xb0 /* Cobra */
+#define AR5K_SREV_AR2415 0xb0 /* Talon */
#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
#define AR5K_SREV_AR5418 0xca /* PCI-E */
#define AR5K_SREV_AR2425 0xe0 /* Swan */
@@ -331,7 +333,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_2112B 0x46
#define AR5K_SREV_RAD_2413 0x50
#define AR5K_SREV_RAD_5413 0x60
-#define AR5K_SREV_RAD_2316 0x70
+#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */
#define AR5K_SREV_RAD_2317 0x80
#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
#define AR5K_SREV_RAD_2425 0xa2
@@ -340,7 +342,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_PHY_5211 0x30
#define AR5K_SREV_PHY_5212 0x41
#define AR5K_SREV_PHY_5212A 0x42
-#define AR5K_SREV_PHY_2112B 0x43
+#define AR5K_SREV_PHY_5212B 0x43
#define AR5K_SREV_PHY_2413 0x45
#define AR5K_SREV_PHY_5413 0x61
#define AR5K_SREV_PHY_2425 0x70
@@ -1030,7 +1032,6 @@ struct ath5k_hw {
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
- u32 ah_phy_spending;

enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
@@ -1156,6 +1157,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
/* EEPROM access functions */
extern int ath5k_eeprom_init(struct ath5k_hw *ah);
extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);

/* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
@@ -1258,6 +1260,7 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);

/*
* Translate usec to hw clock units
+ * TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
{
@@ -1266,6 +1269,7 @@ static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)

/*
* Translate hw clock units to usec
+ * TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c
index a3f07a4..05bc5cb 100644
--- a/drivers/net/wireless/ath5k/attach.c
+++ b/drivers/net/wireless/ath5k/attach.c
@@ -169,7 +169,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ);
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
break;
case AR5K_SREV_RAD_5112:
case AR5K_SREV_RAD_2112:
@@ -177,38 +176,31 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ);
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
break;
case AR5K_SREV_RAD_2413:
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
break;
case AR5K_SREV_RAD_5413:
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
break;
case AR5K_SREV_RAD_2316:
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
break;
case AR5K_SREV_RAD_2317:
ah->ah_radio = AR5K_RF2317;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2317;
break;
case AR5K_SREV_RAD_5424:
if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
ah->ah_mac_version == AR5K_SREV_AR2417){
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
}
break;
default:
@@ -227,29 +219,25 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else if (srev == AR5K_SREV_AR5213A &&
- ah->ah_phy_revision == AR5K_SREV_PHY_2112B) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
- ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2112B;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
} else {
ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
ret = -ENODEV;
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
index b4ec539..5f16fea 100644
--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -1412,6 +1412,7 @@ ath5k_eeprom_init(struct ath5k_hw *ah)

return 0;
}
+
/*
* Read the MAC address from eeprom
*/
@@ -1448,3 +1449,14 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
return 0;
}

+bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
+{
+ u16 data;
+
+ ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) && data))
+ return true;
+ else
+ return false;
+}
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h
index 09eb7d0..1deebc0 100644
--- a/drivers/net/wireless/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath5k/eeprom.h
@@ -25,6 +25,7 @@
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */

+#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index 84f4669..d023eb5 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -187,6 +187,7 @@
#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */
#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */
+#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable doulbe buffering on DCU */
#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */

/*
@@ -753,7 +754,7 @@
*/
#define AR5K_DCU_SEQNUM_BASE 0x1140
#define AR5K_DCU_SEQNUM_M 0x00000fff
-#define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)

/*
* DCU global IFS SIFS register
@@ -1679,7 +1680,7 @@
* TSF parameter register
*/
#define AR5K_TSF_PARM 0x8104 /* Register Address */
-#define AR5K_TSF_PARM_INC_M 0x000000ff /* Mask for TSF increment */
+#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */
#define AR5K_TSF_PARM_INC_S 0

/*
@@ -1928,8 +1929,8 @@
#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0

#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* TX end to XLNA on */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 0
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8

#define AR5K_PHY_ADC_CTL 0x982c
#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
@@ -1963,7 +1964,7 @@
#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
#define AR5K_PHY_SETTLING_AGC_S 0
#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
-#define AR5K_PHY_SETTLINK_SWITCH_S 7
+#define AR5K_PHY_SETTLING_SWITCH_S 7

/*
* PHY Gain registers
@@ -2069,14 +2070,14 @@
* PHY sleep registers [5112+]
*/
#define AR5K_PHY_SCR 0x9870
-#define AR5K_PHY_SCR_32MHZ 0x0000001f

#define AR5K_PHY_SLMT 0x9874
#define AR5K_PHY_SLMT_32MHZ 0x0000007f

#define AR5K_PHY_SCAL 0x9878
#define AR5K_PHY_SCAL_32MHZ 0x0000000e
-
+#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
+#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032

/*
* PHY PLL (Phase Locked Loop) control register
@@ -2156,7 +2157,8 @@
#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
-#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f9 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4

/*
* PHY receiver delay register [5111+]
@@ -2196,7 +2198,7 @@
#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
-#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
@@ -2279,6 +2281,15 @@
AR5K_PHY_FRAME_CTL_TIMING_ERR

/*
+ * PHY Tx Power adjustment register [5212A+]
+ */
+#define AR5K_PHY_TX_PWR_ADJ 0x994c
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18
+
+/*
* PHY radar detection register [5111+]
*/
#define AR5K_PHY_RADAR 0x9954
@@ -2459,17 +2470,7 @@
#define AR5K_PHY_SDELAY 0x99f4
#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
#define AR5K_PHY_SPENDING 0x99f8
-#define AR5K_PHY_SPENDING_14 0x00000014
-#define AR5K_PHY_SPENDING_18 0x00000018
-#define AR5K_PHY_SPENDING_RF5111 0x00000018
-#define AR5K_PHY_SPENDING_RF5112 0x00000014
-/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */
-/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */
-#define AR5K_PHY_SPENDING_RF5413 0x00000018
-#define AR5K_PHY_SPENDING_RF2413 0x00000018
-#define AR5K_PHY_SPENDING_RF2316 0x00000018
-#define AR5K_PHY_SPENDING_RF2317 0x00000018
-#define AR5K_PHY_SPENDING_RF2425 0x00000014
+

/*
* PHY PAPD I (power?) table (?)
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
index 579c64c..34dc2d5 100644
--- a/drivers/net/wireless/ath5k/reset.c
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -37,10 +37,14 @@
* @ah: the &struct ath5k_hw
* @channel: the currently set channel upon reset
*
- * Write the OFDM timings for the AR5212 upon reset. This is a helper for
- * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
- * depending on the bandwidth of the channel.
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operration on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
*
+ * Since delta slope is floating point we split it on it's exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this pattent is related
+ * http://www.freepatentsonline.com/7184495.html
*/
static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
struct ieee80211_channel *channel)
@@ -53,13 +57,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM))
BUG();

- /* Seems there are two PLLs, one for baseband sampling and one
- * for tuning. Tuning basebands are 40 MHz or 80MHz when in
- * turbo. */
- clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
+ /* Get coefficient
+ * ALGO: coef = (5 * clock * carrier_freq) / 2)
+ * we scale coef by shifting clock value by 24 for
+ * better precision since we use integers */
+ /* TODO: Half/quarter rate */
+ clock = channel->hw_value & CHANNEL_TURBO ?
+ ath5k_hw_htoclock(1, true) :
+ ath5k_hw_htoclock(1, false);
+
coef_scaled = ((5 * (clock << 24)) / 2) /
channel->center_freq;

+ /* Get exponent
+ * ALGO: coe_exp = 14 - highest set bit position */
for (coef_exp = 31; coef_exp > 0; coef_exp--)
if ((coef_scaled >> coef_exp) & 0x1)
break;
@@ -68,8 +79,14 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
return -EINVAL;

coef_exp = 14 - (coef_exp - 24);
+
+ /* Get mantissa (significant digits)
+ * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
coef_man = coef_scaled +
(1 << (24 - coef_exp - 1));
+
+ /* Calculate delta slope coefficient exponent
+ * and mantissa (remove scaling) and set them on hw */
ds_coef_man = coef_man >> (24 - coef_exp);
ds_coef_exp = coef_exp - 16;

@@ -90,16 +107,22 @@ static int control_rates[] =
{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };

/**
- * ath5k_hw_write_rate_duration - set rate duration during hw resets
+ * ath5k_hw_write_rate_duration - set rate code to duration table during hw resets
*
* @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode
*
- * Write the rate duration table upon hw reset. This is a helper for
- * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for
- * the hardware for the current mode for each rate. The rates which are capable
- * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another
- * register for the short preamble ACK timeout calculation.
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are capable
+ * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have different
+ * rate code so we write their value twice (one for long preample and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates. If we operate in turbo or xr/half/quarter
+ * rate mode, we need to use another set of bitrates (that's why we need the mode
+ * parameter) but we don't handle these proprietary modes yet.
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int mode)
@@ -275,7 +298,8 @@ commit:
}

/*
- * Bring up MAC + PHY Chips
+ * Bring up MAC + PHY Chips and program PLL
+ * TODO: Half/Quarter rate support
*/
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{
@@ -333,7 +357,11 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}
} else if (flags & CHANNEL_5GHZ) {
mode |= AR5K_PHY_MODE_FREQ_5GHZ;
- clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (ah->ah_radio == AR5K_RF5413)
+ clock |= AR5K_PHY_PLL_40MHZ_5413;
+ else
+ clock |= AR5K_PHY_PLL_40MHZ;

if (flags & CHANNEL_OFDM)
mode |= AR5K_PHY_MODE_MOD_OFDM;
@@ -391,10 +419,14 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}

if (ah->ah_version != AR5K_AR5210) {
- /* ...set the PHY operating mode */
- ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
- udelay(300);

+ /* ...program PLL if it needs change */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+ }
+
+ /* ...set the PHY operating mode */
ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
}
@@ -403,22 +435,397 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}

/*
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power durring sleep or restore normal 32/40MHz
+ * operation.
+ *
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ * 123 - 127) require delay on access.
+ */
+void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 scal, spending, usec32;
+
+ /* No 32KHz clock available, stick to the default
+ * settings we got from initvals */
+ if (!(AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+ AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)))
+ return;
+
+ if (enable) {
+
+ /* 1 usec/cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
+ /* Set up tsf increment on each cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
+
+ /* Set baseband sleep control registers
+ * and sleep control rate */
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
+ } else {
+ ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
+ }
+
+ /* Enable sleep clock operation */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+ } else {
+
+ /* Disable sleep clock operation and
+ * restore default parameters */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413))
+ usec32 = 39;
+ else
+ usec32 = 31;
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+ }
+ return;
+}
+
+static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u8 refclk_freq;
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ refclk_freq = 40;
+ else
+ refclk_freq = 32;
+
+ if ((channel->center_freq % refclk_freq != 0) &&
+ ((channel->center_freq % refclk_freq < 10) ||
+ (channel->center_freq % refclk_freq > 22)))
+ return true;
+ else
+ return false;
+}
+
+/* TODO: Half/Quarter rate */
+static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u32 data;
+
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_phy_revision > AR5K_SREV_PHY_5212A) {
+
+ /* Setup ADC control */
+ ath5k_hw_reg_write(ah,
+ (AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
+ AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
+ AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
+ AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
+ AR5K_PHY_ADC_CTL);
+
+
+
+ /* Disable barker RSSI threshold */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
+
+ /* Set the mute mask */
+ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+ }
+
+ /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
+
+ /* Enable DCU double buffering */
+ if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_DCU_DBL_BUF_DIS);
+
+ /* Set DAC/ADC delays */
+ if (ah->ah_version == AR5K_AR5212) {
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ data = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ data = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ data = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_SCAL);
+ data = 0;
+ }
+
+ /* Set fast ADC */
+ if ((ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ data = 1;
+
+ if (channel->center_freq == 2462 ||
+ channel->center_freq == 2467)
+ data = 0;
+
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != data)
+ ath5k_hw_reg_write(ah, data,
+ AR5K_PHY_FAST_ADC);
+ data = 0;
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio >= AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ data = 0;
+ }
+
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ /* 5311 has different tx/rx latency masks
+ * from 5211, since we deal 5311 the same
+ * as 5211 when setting initvals, shift
+ * values here to their proper locations */
+ data = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+ ath5k_hw_reg_write(ah, data & (AR5K_USEC_1 |
+ AR5K_USEC_32 |
+ AR5K_USEC_TX_LATENCY_5211 |
+ AR5K_REG_SM(29,
+ AR5K_USEC_RX_LATENCY_5210)),
+ AR5K_USEC_5211);
+ /* Clear QCU/DCU clock gating register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
+ /* Set DAC/ADC delays */
+ ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+ /* Enable PCU FIFO corruption ECO */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_ECO_ENABLE);
+ data = 0;
+ }
+
+ return;
+}
+
+static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int16_t cck_ofdm_pwr_delta = 0;
+
+ /* Set CCK to OFDM power delta */
+ if (ah->ah_phy_revision > AR5K_SREV_PHY_5212A) {
+ /* Adjust power delta for channel 14 */
+ if (channel->center_freq == 2484)
+ cck_ofdm_pwr_delta =
+ ((ee->ee_cck_ofdm_power_delta -
+ ee->ee_scaled_cck_delta) * 2) / 10;
+ else
+ cck_ofdm_pwr_delta =
+ ee->ee_cck_ofdm_power_delta;
+
+ if (channel->hw_value == CHANNEL_G)
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
+ AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
+ AR5K_PHY_TX_PWR_ADJ);
+ else
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
+ }
+
+ /* Set antenna idle switch table */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+ AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+ ah->ah_antenna[ee_mode][0]);
+
+ /* Set antenna switch table */
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Noise floor threshold */
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY_NFTHRES);
+
+ if ((channel->hw_value & CHANNEL_TURBO) &&
+ (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
+ /* Switch settling time (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling_turbo[ee_mode]);
+
+ /* Tx/Rx attenuation (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx_turbo[ee_mode]);
+
+ /* ADC/PGA dezired size (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size_turbo[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size_turbo[ee_mode]);
+
+ /* Tx/Rx margin (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx_turbo[ee_mode]);
+
+ } else {
+ /* Switch settling time */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling[ee_mode]);
+
+ /* Tx/Rx attenuation */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx[ee_mode]);
+
+ /* ADC/PGA dezired size */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size[ee_mode]);
+
+ /* Tx/Rx margin */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+ }
+
+ /* XPA delays */
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+ /* XLNA delay */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
+ AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
+ ee->ee_tx_end2xlna_enable[ee_mode]);
+
+ /* Thres64 (ANI) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
+ AR5K_PHY_NF_THRESH62,
+ ee->ee_thr_62[ee_mode]);
+
+
+ /* False detect backoff for channels
+ * that have spur noise. Write the new
+ * cyclic power RSSI threshold. */
+ if (ath5k_hw_chan_has_spur_noise(ah, channel))
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1 +
+ ee->ee_false_detect[ee_mode]);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1);
+
+ /* I/Q correction
+ * TODO: Per channel i/q infos ? */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ /* Heavy clipping -disable for now */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
+
+ return;
+}
+
+/*
* Main reset function
*/
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool change_channel)
{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- struct pci_dev *pdev = ah->ah_sc->pdev;
- u32 data, s_seq, s_ant, s_led[3], dma_size;
- unsigned int i, mode, freq, ee_mode, ant[2];
- int ret;
+ u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
+ u32 data, rssi_thr;
+ u8 mode, freq, ee_mode, ant[2];
+ int i, ret;

ATH5K_TRACE(ah->ah_sc);

- s_seq = 0;
s_ant = 0;
ee_mode = 0;
+ staid1_flags = 0;
+ tsf_up = 0;
+ tsf_lo = 0;
freq = 0;
mode = 0;

@@ -427,36 +834,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*/
/*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) {
- if (change_channel) {
- /* Seq number for queue 0 -do this for all queues ? */
- s_seq = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DFS_SEQNUM(0));
- /*Default antenna*/
- s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
- }
- }
-
- /*GPIOs*/
- s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
- s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
- s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
-
- /*Wakeup the device*/
- ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
- if (ret)
- return ret;
-
- /*
- * Initialize operating mode
- */
- ah->ah_op_mode = op_mode;
-
- /*
- * 5111/5112 Settings
- * 5210 only comes with RF5110
- */
- if (ah->ah_version != AR5K_AR5210) {

switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
@@ -479,8 +856,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
break;
- /*Is this ok on 5211 too ?*/
case CHANNEL_TG:
+ if (ah->ah_version == AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "TurboG mode not available on 5211");
+ return -EINVAL;
+ }
mode = AR5K_MODE_11G_TURBO;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
@@ -501,11 +882,100 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
return -EINVAL;
}

+ if (change_channel) {
+ /*
+ * Save frame sequence count
+ * For revs. after Oahu, only save
+ * seq num for DCU 0 (Global seq num)
+ */
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+ for (i = 0; i < 10; i++)
+ s_seq[i] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(i));
+
+ } else {
+ s_seq[0] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+
+ /* TSF accelerates on AR5211 durring reset
+ * As a workaround save it here and restore
+ * it later so that it's back in time after
+ * reset. This way it'll get re-synced on the
+ * next beacon without breaking ad-hoc.
+ *
+ * On AR5212 TSF is almost preserved across a
+ * reset so it stays back in time anyway and
+ * we don't have to save/restore it.
+ *
+ * XXX: Since this breaks power saving we have
+ * to disable power saving until we receive the
+ * next beacon, so we can resync beacon timers */
+ if (ah->ah_version == AR5K_AR5211) {
+ tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+ }
+ }
+
+ /* Save default antenna */
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ /* AR5K_STA_ID1 flags, only preserve antenna and
+ * ack/cts rate mode */
+ staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
+ (AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_DESC_ANTENNA |
+ AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ AR5K_STA_ID1_ACKCTS_6MB |
+ AR5K_STA_ID1_BASE_RATE_11B |
+ AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ /* Restore normal 32/40MHz clock operation
+ * to avoid register access delay on certain
+ * PHY registers */
+ ath5k_hw_set_sleep_clock(ah, false);
+
+ /* Since we are going to write rf buffer
+ * check if we have any pending gain_F
+ * optimization settings */
+ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_gainf_calibrate(ah);
+ }
}

+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ /* Save RSSI thresholds (they 'll get zeroed from initvals) */
+ rssi_thr = ath5k_hw_reg_read(ah, AR5K_RSSI_THR);
+ /* If they are not set, set the default value */
+ if (!rssi_thr)
+ rssi_thr = AR5K_INIT_RSSI_THR;
+
+
+ /* Wakeup the device */
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Initialize operating mode
+ */
+ ah->ah_op_mode = op_mode;
+
/* PHY access enable */
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ else
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
+ AR5K_PHY(0));

+ /* Write initial settings */
ret = ath5k_hw_write_initvals(ah, mode, change_channel);
if (ret)
return ret;
@@ -514,6 +984,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* 5211/5212 Specific
*/
if (ah->ah_version != AR5K_AR5210) {
+
/*
* Write initial RF gain settings
* This should work for both 5111/5112
@@ -525,53 +996,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
mdelay(1);

/*
- * Write some more initial register settings for revised chips
+ * Tweak initval settings for revised
+ * chipsets and add some more config
+ * bits
*/
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_phy_revision > 0x41) {
- ath5k_hw_reg_write(ah, 0x0002a002, 0x982c);
-
- if (channel->hw_value == CHANNEL_G)
- if (ah->ah_mac_srev < AR5K_SREV_AR2413)
- ath5k_hw_reg_write(ah, 0x00f80d80,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_AR5424)
- ath5k_hw_reg_write(ah, 0x00380140,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_AR2425)
- ath5k_hw_reg_write(ah, 0x00fc0ec0,
- 0x994c);
- else /* 2425 */
- ath5k_hw_reg_write(ah, 0x00fc0fc0,
- 0x994c);
- else
- ath5k_hw_reg_write(ah, 0x00000000, 0x994c);
-
- /* Got this from legacy-hal */
- AR5K_REG_DISABLE_BITS(ah, 0xa228, 0x200);
-
- AR5K_REG_MASKED_BITS(ah, 0xa228, 0x800, 0xfffe03ff);
-
- /* Just write 0x9b5 ? */
- /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */
- ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
- ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
- ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
- }
-
- /* Fix for first revision of the RF5112 RF chipset */
- if (ah->ah_radio >= AR5K_RF5112 &&
- ah->ah_radio_5ghz_revision <
- AR5K_SREV_RAD_5112A) {
- ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
- AR5K_PHY_CCKTXCTL);
- if (channel->hw_value & CHANNEL_5GHZ)
- data = 0xffb81020;
- else
- data = 0xffb80d20;
- ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
- data = 0;
- }
+ ath5k_hw_tweak_initval_settings(ah, channel);

/*
* Set TX power (FIXME)
@@ -589,15 +1018,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_write_rate_duration(ah, mode);

/*
- * Write RF registers
+ * Write RF buffer
*/
ret = ath5k_hw_rfregs_init(ah, channel, mode);
if (ret)
return ret;

- /*
- * Configure additional registers
- */

/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
@@ -619,17 +1045,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}

/*
- * Set channel and calibrate the PHY
- */
- ret = ath5k_hw_channel(ah, channel);
- if (ret)
- return ret;
-
- /* Set antenna mode */
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL,
- ah->ah_antenna[ee_mode][0], 0xfffffc06);
-
- /*
* In case a fixed antenna was set as default
* write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
* registers.
@@ -644,54 +1059,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ant[1] = AR5K_ANT_FIXED_B;
}

- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
- AR5K_PHY_ANT_SWITCH_TABLE_0);
- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
- AR5K_PHY_ANT_SWITCH_TABLE_1);
-
/* Commit values from EEPROM */
- if (ah->ah_radio == AR5K_RF5111)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
- AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
-
- ath5k_hw_reg_write(ah,
- AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
- AR5K_PHY_NFTHRES);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING,
- (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
- 0xffffc07f);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
- (ee->ee_atn_tx_rx[ee_mode] << 12) & 0x3f000,
- 0xfffc0fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
- (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
- ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
- 0xffff0000);
-
- ath5k_hw_reg_write(ah,
- (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
- (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
- (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
- (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3,
- ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF,
- (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01);
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CORR_ENABLE |
- (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
- ee->ee_q_cal[ee_mode]);
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
- AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
- ee->ee_margin_tx_rx[ee_mode]);
+ ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);

} else {
+ /*
+ * For 5210 we do all initialization using
+ * initvals, so we don't have to modify
+ * any settings (5210 also only supports
+ * a/aturbo modes)
+ */
mdelay(1);
/* Disable phy and wait */
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
@@ -701,61 +1078,99 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/*
* Restore saved values
*/
+
/*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) {
- ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
+
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ for (i = 0; i < 10; i++)
+ ath5k_hw_reg_write(ah, s_seq[i],
+ AR5K_QUEUE_DCU_SEQNUM(i));
+ } else {
+ ath5k_hw_reg_write(ah, s_seq[0],
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+
+
+ if (ah->ah_version == AR5K_AR5211) {
+ ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
+ ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
+ }
+
ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
}
+
+ /* Ledstate */
AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+
+ /* Gpio settings */
ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);

+ /* RSSI thresholds */
+ ath5k_hw_reg_write(ah, rssi_thr, AR5K_RSSI_THR);
+
+ /* Restore sta_id flags and preserve our mac address*/
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
+ AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
+ AR5K_STA_ID1);
+
+
/*
- * Misc
+ * Configure PCU
*/
+
+ /* Restore bssid and bssid mask */
/* XXX: add ah->aid once mac80211 gives this to us */
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);

+ /* Set PCU config */
ath5k_hw_set_opmode(ah);
- /*PISR/SISR Not available on 5210*/
+
+ /* Clear any pending interrupts
+ * PISR/SISR Not available on 5210 */
if (ah->ah_version != AR5K_AR5210) {
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
- /* If we later allow tuning for this, store into sc structure */
- data = AR5K_TUNE_RSSI_THRES |
- AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
- ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
}

+ /* MIC QoS support */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+ ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+ ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+ }
+
+ /* QoS NOACK Policy */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+ AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
+ AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+ AR5K_QOS_NOACK);
+ }
+
+
/*
- * Set Rx/Tx DMA Configuration
- *
- * Set maximum DMA size (512) except for PCI-E cards since
- * it causes rx overruns and tx errors (tested on 5424 but since
- * rx overruns also occur on 5416/5418 with madwifi we set 128
- * for all PCI-E cards to be safe).
- *
- * In dumps this is 128 for allchips.
- *
- * XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
- * guess we can tweak it and see how it goes ;-)
+ * Configure PHY
*/
- dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
- if (ah->ah_version != AR5K_AR5210) {
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_SDMAMR, dma_size);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
- AR5K_RXCFG_SDMAMW, dma_size);
- }
+
+ /* Set channel on PHY */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;

/*
* Enable the PHY and wait until completion
+ * This includes BaseBand and Synthesizer
+ * activation.
*/
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);

/*
* On 5211+ read activation -> rx delay
* and use it.
+ *
+ * TODO: Half/quarter rate support
*/
if (ah->ah_version != AR5K_AR5210) {
data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
@@ -770,7 +1185,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}

/*
- * Perform ADC test (?)
+ * Perform ADC test to see if baseband is ready
+ * Set tx hold and check adc test register
*/
data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
@@ -783,18 +1199,23 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
data = 0;

/*
- * Start automatic gain calibration
+ * Start automatic gain control calibration
*
* During AGC calibration RX path is re-routed to
- * a signal detector so we don't receive anything.
+ * a power detector so we don't receive anything.
*
* This method is used to calibrate some static offsets
* used together with on-the fly I/Q calibration (the
* one performed via ath5k_hw_phy_calibrate), that doesn't
* interrupt rx path.
*
+ * While rx path is re-routed to the power detector we also
+ * start a noise floor calibration, to measure the
+ * card's noise floor (the noise we measure when we are not
+ * transmiting or receiving anything).
+ *
* If we are in a noisy environment AGC calibration may time
- * out.
+ * out and/or noise floor calibration might timeout.
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL);
@@ -816,30 +1237,37 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
channel->center_freq);
- return -EAGAIN;
}

/*
- * Start noise floor calibration
- *
* If we run NF calibration before AGC, it always times out.
* Binary HAL starts NF and AGC calibration at the same time
- * and only waits for AGC to finish. I believe that's wrong because
- * during NF calibration, rx path is also routed to a detector, so if
- * it doesn't finish we won't have RX.
- *
- * XXX: Find an interval that's OK for all cards...
+ * and only waits for AGC to finish. Also if AGC or NF cal.
+ * times out, reset doesn't fail on binary HAL. I believe
+ * that's wrong because since rx path is routed to a detector,
+ * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
+ * enables noise floor calibration after offset calibration and if noise
+ * floor calibration fails, reset fails. I believe that's
+ * a better approach, we just need to find a polling interval
+ * that suits best, even if reset continues we need to make
+ * sure that rx path is ready.
*/
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);

+
+ /*
+ * Configure QCUs/DCUs
+ */
+
+ /* TODO: HW Compression support for data queues */
+ /* TODO: Burst prefetch for data queues */
+
/*
* Reset queues and start beacon timers at the end of the reset routine
+ * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+ * Note: If we want we can assign multiple qcus on one dcu.
*/
for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
- /*No QCU on 5210*/
- if (ah->ah_version != AR5K_AR5210)
- AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
-
ret = ath5k_hw_reset_tx_queue(ah, i);
if (ret) {
ATH5K_ERR(ah->ah_sc,
@@ -848,14 +1276,40 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
}

+
+ /*
+ * Configure DMA/Interrupts
+ */
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set standard DMA size (128). Note that
+ * a DMA size of 512 causes rx overruns and tx errors
+ * on pci-e cards (tested on 5424 but since rx overruns
+ * also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+ }
+
/* Pre-enable interrupts on 5211/5212*/
if (ah->ah_version != AR5K_AR5210)
ath5k_hw_set_imr(ah, ah->ah_imr);

/*
- * Set RF kill flags if supported by the device (read from the EEPROM)
- * Disable gpio_intr for now since it results system hang.
- * TODO: Handle this in ath5k_intr
+ * Setup RFKill interrupt if rfkill flag is set on eeprom.
+ * TODO: Use gpio pin and polarity infos from eeprom
+ * TODO: Handle this in ath5k_intr because it'll result
+ * a nasty interrupt storm.
*/
#if 0
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
@@ -868,33 +1322,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
#endif

- /*
- * Set the 32MHz reference clock on 5212 phy clock sleep register
- *
- * TODO: Find out how to switch to external 32Khz clock to save power
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
- ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
- ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
-
- data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ;
- data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ?
- 0x00000f80 : 0x00001380 ;
- ath5k_hw_reg_write(ah, data, AR5K_USEC_5211);
- data = 0;
- }
-
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
- ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
- ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
- if (ah->ah_mac_srev >= AR5K_SREV_AR2413)
- ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
- }
+ /* Enable 32KHz clock function for AR5212+ chips
+ * Set clocks to 32KHz operation and use an
+ * external 32KHz crystal when sleeping if one
+ * exists */
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_set_sleep_clock(ah, true);

/*
* Disable beacons and reset the register


2009-01-31 22:58:15

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/1 Bob Copeland <[email protected]>:
> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>> > Heh, we should write a little tool to check the shifts and masks :)
>> >
>>
>> Yup :P
>
> I just wrote one, I can post it later :) It also found:
>
> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>
> Should be 12 or a different mask...
>

ACK

>> Thanks a lot for your comments, i'll address them asap and come up
>> with a new version of this patch ;-)
>
> My computer also hangs with the whole series... reverting the reset
> part makes it work. I'll try and narrow that down later when I
> get some time.
>

O.K. i'll work on the other issues and when you find the problem let
me know so i can resend reset patch.

Are you all ok on the rest 4 patches ?



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-01-31 18:48:04

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/1/31 Bob Copeland <[email protected]>:
> On Sat, Jan 31, 2009 at 04:31:47AM +0200, Nick Kossifidis wrote:
>> * Update reset and sync with HALs
>> * Clean up eeprom settings and tweaking of initvals and put them on separate functions
>> * Set/Restore 32KHz ref clk operation
>> * Add some more documentation
>> TODO: Spur mitigation, tpc, half/quarter rate, compression etc
>
> Awesome work! I just double checked it, I have some minor comments,
> on the whole looks very good.
>

Thanks a lot for the review ! ;-)

>> Signed-Off-by: Nick Kossifidis <[email protected]>
>
> Should be "Signed-off-by:" (lowercase O) according to checkpatch.
>

ACK, i just c/p it from my previous patches and it seems i got it
wrong on all of them :P

>> [...]
>> +bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
>> +{
>> + u16 data;
>> +
>> + ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
>> +
>> + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) && data))
>
> Don't think it makes a difference, but judging from the double parens,
> I think you meant:
>
>> + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)

You are right, i'll change that...

>
> Do we need to check for eeprom version 5.4 or better? HAL does.
>

Well ath5k_eeprom_is_hb63 is a temporary solution, i'll make a
ath5k_hw_get_eeprom_info for all eeprom flags (rf kill, antenna gain
etc) and use that instead.

>> [...]
>> @@ -2156,7 +2157,8 @@
>> #define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
>> #define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
>> #define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
>> -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f9 /* Switch table idle (?) */
>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
>
> That doesn't look right.. should be 3f0? (still probably works, I guess).
>

I know, but HAL does this...
AR_PHY_BIS(ah, 68, 0xFFFFFC06,
(ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);

~0xFFFFFC06 = 3F9

>> -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0
>> +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
>
> Heh, we should write a little tool to check the shifts and masks :)
>

Yup :P

>> - * Write the OFDM timings for the AR5212 upon reset. This is a helper for
>> - * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
>> - * depending on the bandwidth of the channel.
>> + * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
>> + * operration on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
>
> operation
>
>> *
>> + * Since delta slope is floating point we split it on it's exponent and
>
> its
>
>> + * mantissa and provide these values on hw.
>> + *
>> + * For more infos i think this pattent is related
>
> patent
>

ACK

>> @@ -53,13 +57,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
>> !(channel->hw_value & CHANNEL_OFDM))
>> BUG();
>>
>> - /* Seems there are two PLLs, one for baseband sampling and one
>> - * for tuning. Tuning basebands are 40 MHz or 80MHz when in
>> - * turbo. */
>> - clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
>> + /* Get coefficient
>> + * ALGO: coef = (5 * clock * carrier_freq) / 2)
>> + * we scale coef by shifting clock value by 24 for
>> + * better precision since we use integers */
>> + /* TODO: Half/quarter rate */
>> + clock = channel->hw_value & CHANNEL_TURBO ?
>> + ath5k_hw_htoclock(1, true) :
>> + ath5k_hw_htoclock(1, false);
>> +
>
>
> Could be:
>
> clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
>

My intention is to reimplement hw_htoclock to account for half/quarter
rate so it'll soon be
clock = ath5k_hw_htoclock(1, channel->hw_value);

>> coef_scaled = ((5 * (clock << 24)) / 2) /
>> channel->center_freq;
>>
>> + /* Get exponent
>> + * ALGO: coe_exp = 14 - highest set bit position */
>> for (coef_exp = 31; coef_exp > 0; coef_exp--)
>> if ((coef_scaled >> coef_exp) & 0x1)
>> break;
>
> I know this is existing code, but we could use something like
> get_bitmask_order() here or fls() instead of the open-coded loop.
> For some other patch.
>

Sure thing, i was also looking for some fast bit operation but i
didn't put it in

>> /*
>> + * If there is an external 32KHz crystal available, use it
>> + * as ref. clock instead of 32/40MHz clock and baseband clocks
>> + * to save power durring sleep or restore normal 32/40MHz
>
> during
>

>> + /* Set DAC/ADC delays */
>> + if (ah->ah_version == AR5K_AR5212) {
>> + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
>> + data = AR5K_PHY_SCAL_32MHZ_2417;
>> + else if (ath5k_eeprom_is_hb63(ah))
>> + data = AR5K_PHY_SCAL_32MHZ_HB63;
>> + else
>> + data = AR5K_PHY_SCAL_32MHZ;
>> + ath5k_hw_reg_write(ah, data, AR5K_PHY_SCAL);
>> + data = 0;
>
> why data = 0; ?
>

Instead of having multiple temporary variables, i use only "data". To
be sure that "data" is ok for use i always zero it each time i use it
so that we don't write any weird stuff by mistake.

>
>> + }
>> +
>> + return;
>
> No need for return.
>

It's for my eyes mostly

>> +}
>> +
>> +static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
>> + struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
>> +{
>> + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
>> + int16_t cck_ofdm_pwr_delta = 0;
>
> I don't think you need to assign it, unless gcc is particularly dumb.
>

I agree but it's a good practice to initialize vars and it's free

>> +
>> + /* Set CCK to OFDM power delta */
>> + if (ah->ah_phy_revision > AR5K_SREV_PHY_5212A) {
>> + /* Adjust power delta for channel 14 */
>> + if (channel->center_freq == 2484)
>> + cck_ofdm_pwr_delta =
>> + ((ee->ee_cck_ofdm_power_delta -
>> + ee->ee_scaled_cck_delta) * 2) / 10;
>> + else
>> + cck_ofdm_pwr_delta =
>> + ee->ee_cck_ofdm_power_delta;
>
> missing * 2 / 10 here?
>

Ouch ! Nice catch ;-)

>> +
>> + if (channel->hw_value == CHANNEL_G)
>> + ath5k_hw_reg_write(ah,
>> + AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1),
>> [...]
>> + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
>> + AR5K_PHY_GAIN_TXRX_ATTEN,
>> + ee->ee_atn_tx_rx[ee_mode]);
>> +
>> + /* ADC/PGA dezired size */
>
> desired
>
>> [...]
>> +
>> + /* Thres64 (ANI) */
>
> Thresh62 ?
>

Yup, I mispelled it

>> +
>> + /* QoS NOACK Policy */
>> + if (ah->ah_version == AR5K_AR5212) {
>> + ath5k_hw_reg_write(ah,
>> + AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
>> + AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
>> + AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
>
> AR5K_QOS_NOACK_BYTE_OFFSET_S is also wrong, should be 7.
>

ACK


Thanks a lot for your comments, i'll address them asap and come up
with a new version of this patch ;-)



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-01-31 18:56:44

by Felix Fietkau

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

Nick Kossifidis wrote:
>>> [...]
>>> @@ -2156,7 +2157,8 @@
>>> #define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
>>> #define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
>>> #define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
>>> -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
>>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f9 /* Switch table idle (?) */
>>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
>>
>> That doesn't look right.. should be 3f0? (still probably works, I guess).
>>
>
> I know, but HAL does this...
> AR_PHY_BIS(ah, 68, 0xFFFFFC06,
> (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
>
> ~0xFFFFFC06 = 3F9
How about splitting it up and making the 0x1 a separate flag?

> My intention is to reimplement hw_htoclock to account for half/quarter
> rate so it'll soon be
> clock = ath5k_hw_htoclock(1, channel->hw_value);
AFAIK Sam's HAL might have a bug there. If I remember correctly, the MAC
runs at the same clock speed with Half/Quarter rate.
It's done that way in the legacy HAL. Though there is a possibility of
it being hardware dependent, I'm pretty sure that it is that way at least
on 5413.

>>> + /* Set DAC/ADC delays */
>>> + if (ah->ah_version == AR5K_AR5212) {
>>> + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
>>> + data = AR5K_PHY_SCAL_32MHZ_2417;
>>> + else if (ath5k_eeprom_is_hb63(ah))
>>> + data = AR5K_PHY_SCAL_32MHZ_HB63;
>>> + else
>>> + data = AR5K_PHY_SCAL_32MHZ;
>>> + ath5k_hw_reg_write(ah, data, AR5K_PHY_SCAL);
>>> + data = 0;
>>
>> why data = 0; ?
>>
> Instead of having multiple temporary variables, i use only "data". To
> be sure that "data" is ok for use i always zero it each time i use it
> so that we don't write any weird stuff by mistake.
Wouldn't multiple temporary values be preferable, since the compiler
optimizes that stuff anyway?

- Felix

2009-01-31 21:46:02

by Felix Fietkau

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

Nick Kossifidis wrote:
>>> My intention is to reimplement hw_htoclock to account for half/quarter
>>> rate so it'll soon be
>>> clock = ath5k_hw_htoclock(1, channel->hw_value);
>> AFAIK Sam's HAL might have a bug there. If I remember correctly, the MAC
>> runs at the same clock speed with Half/Quarter rate.
>> It's done that way in the legacy HAL. Though there is a possibility of
>> it being hardware dependent, I'm pretty sure that it is that way at least
>> on 5413.
>>
>
> Both HALs tweak clock this way on ar5212SetDeltaSlope on all chips. If
> clock depends on channel bandwidth for turbo it makes sense to also
> change on half/quarter rate operation.
Yeah, for the delta slope it may be the same, but not for the MAC, IMHO.
Check out ath_hal_mac_clks in the legacy HAL and Sam's HAL. I believe
the legacy HAL variant is correct in this case.

- Felix

2009-01-31 17:08:26

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Sat, Jan 31, 2009 at 04:31:47AM +0200, Nick Kossifidis wrote:
> * Update reset and sync with HALs
> * Clean up eeprom settings and tweaking of initvals and put them on separate functions
> * Set/Restore 32KHz ref clk operation
> * Add some more documentation
> TODO: Spur mitigation, tpc, half/quarter rate, compression etc

Awesome work! I just double checked it, I have some minor comments,
on the whole looks very good.

> Signed-Off-by: Nick Kossifidis <[email protected]>

Should be "Signed-off-by:" (lowercase O) according to checkpatch.

> [...]
> +bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
> +{
> + u16 data;
> +
> + ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
> +
> + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) && data))

Don't think it makes a difference, but judging from the double parens,
I think you meant:

> + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)

Do we need to check for eeprom version 5.4 or better? HAL does.

> [...]
> @@ -2156,7 +2157,8 @@
> #define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
> #define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
> #define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
> -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f9 /* Switch table idle (?) */
> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4

That doesn't look right.. should be 3f0? (still probably works, I guess).

> -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0
> +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1

Heh, we should write a little tool to check the shifts and masks :)

> - * Write the OFDM timings for the AR5212 upon reset. This is a helper for
> - * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
> - * depending on the bandwidth of the channel.
> + * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
> + * operration on the AR5212 upon reset. This is a helper for ath5k_hw_reset().

operation

> *
> + * Since delta slope is floating point we split it on it's exponent and

its

> + * mantissa and provide these values on hw.
> + *
> + * For more infos i think this pattent is related

patent

> @@ -53,13 +57,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
> !(channel->hw_value & CHANNEL_OFDM))
> BUG();
>
> - /* Seems there are two PLLs, one for baseband sampling and one
> - * for tuning. Tuning basebands are 40 MHz or 80MHz when in
> - * turbo. */
> - clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
> + /* Get coefficient
> + * ALGO: coef = (5 * clock * carrier_freq) / 2)
> + * we scale coef by shifting clock value by 24 for
> + * better precision since we use integers */
> + /* TODO: Half/quarter rate */
> + clock = channel->hw_value & CHANNEL_TURBO ?
> + ath5k_hw_htoclock(1, true) :
> + ath5k_hw_htoclock(1, false);
> +


Could be:

clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);

> coef_scaled = ((5 * (clock << 24)) / 2) /
> channel->center_freq;
>
> + /* Get exponent
> + * ALGO: coe_exp = 14 - highest set bit position */
> for (coef_exp = 31; coef_exp > 0; coef_exp--)
> if ((coef_scaled >> coef_exp) & 0x1)
> break;

I know this is existing code, but we could use something like
get_bitmask_order() here or fls() instead of the open-coded loop.
For some other patch.

> /*
> + * If there is an external 32KHz crystal available, use it
> + * as ref. clock instead of 32/40MHz clock and baseband clocks
> + * to save power durring sleep or restore normal 32/40MHz

during

> + * operation.
> + *
> + * XXX: When operating on 32KHz certain PHY registers (27 - 31,
> + * 123 - 127) require delay on access.
> + */
> +void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)

ACK

> +static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
> + struct ieee80211_channel *channel)
> +{

ACK

> + /* Set DAC/ADC delays */
> + if (ah->ah_version == AR5K_AR5212) {
> + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
> + data = AR5K_PHY_SCAL_32MHZ_2417;
> + else if (ath5k_eeprom_is_hb63(ah))
> + data = AR5K_PHY_SCAL_32MHZ_HB63;
> + else
> + data = AR5K_PHY_SCAL_32MHZ;
> + ath5k_hw_reg_write(ah, data, AR5K_PHY_SCAL);
> + data = 0;

why data = 0; ?

> + }
> +
> + /* Set fast ADC */
> + if ((ah->ah_radio == AR5K_RF5413) ||
> + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
> + data = 1;
> +
> + if (channel->center_freq == 2462 ||
> + channel->center_freq == 2467)
> + data = 0;
> +
> + if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != data)
> + ath5k_hw_reg_write(ah, data,
> + AR5K_PHY_FAST_ADC);
> + data = 0;

ditto

> + }
> +
> + /* Fix for first revision of the RF5112 RF chipset */
> + if (ah->ah_radio >= AR5K_RF5112 &&
> + ah->ah_radio_5ghz_revision <
> + AR5K_SREV_RAD_5112A) {
> + ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
> + AR5K_PHY_CCKTXCTL);
> + if (channel->hw_value & CHANNEL_5GHZ)
> + data = 0xffb81020;
> + else
> + data = 0xffb80d20;
> + ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
> + data = 0;

ditto

> + }
> +
> + if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
> + /* 5311 has different tx/rx latency masks
> + * from 5211, since we deal 5311 the same
> + * as 5211 when setting initvals, shift
> + * values here to their proper locations */
> + data = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
> + ath5k_hw_reg_write(ah, data & (AR5K_USEC_1 |
> + AR5K_USEC_32 |
> + AR5K_USEC_TX_LATENCY_5211 |
> + AR5K_REG_SM(29,
> + AR5K_USEC_RX_LATENCY_5210)),
> + AR5K_USEC_5211);
> + /* Clear QCU/DCU clock gating register */
> + ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
> + /* Set DAC/ADC delays */
> + ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
> + /* Enable PCU FIFO corruption ECO */
> + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
> + AR5K_DIAG_SW_ECO_ENABLE);
> + data = 0;

ditto

> + }
> +
> + return;

No need for return.

> +}
> +
> +static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
> + struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
> +{
> + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
> + int16_t cck_ofdm_pwr_delta = 0;

I don't think you need to assign it, unless gcc is particularly dumb.

> +
> + /* Set CCK to OFDM power delta */
> + if (ah->ah_phy_revision > AR5K_SREV_PHY_5212A) {
> + /* Adjust power delta for channel 14 */
> + if (channel->center_freq == 2484)
> + cck_ofdm_pwr_delta =
> + ((ee->ee_cck_ofdm_power_delta -
> + ee->ee_scaled_cck_delta) * 2) / 10;
> + else
> + cck_ofdm_pwr_delta =
> + ee->ee_cck_ofdm_power_delta;

missing * 2 / 10 here?

> +
> + if (channel->hw_value == CHANNEL_G)
> + ath5k_hw_reg_write(ah,
> + AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1),
> [...]
> + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
> + AR5K_PHY_GAIN_TXRX_ATTEN,
> + ee->ee_atn_tx_rx[ee_mode]);
> +
> + /* ADC/PGA dezired size */

desired

> [...]
> +
> + /* Thres64 (ANI) */

Thresh62 ?

> + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
> + AR5K_PHY_NF_THRESH62,
> + ee->ee_thr_62[ee_mode]);
> +

> + /* I/Q correction
> + * TODO: Per channel i/q infos ? */
> + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
> + AR5K_PHY_IQ_CORR_ENABLE |
> + (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
> + ee->ee_q_cal[ee_mode]);
> +
> + /* Heavy clipping -disable for now */
> + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
> + ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
> +
> + return;

No need for return.

> +}

My eyes got tired, so I skipped a lot :)

> +
> + /* QoS NOACK Policy */
> + if (ah->ah_version == AR5K_AR5212) {
> + ath5k_hw_reg_write(ah,
> + AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
> + AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
> + AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),

AR5K_QOS_NOACK_BYTE_OFFSET_S is also wrong, should be 7.

> + AR5K_QOS_NOACK);
> + }
> +

Thanks!
--
Bob Copeland %% http://www.bobcopeland.com


2009-01-31 22:38:25

by Bob Copeland

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
> > Heh, we should write a little tool to check the shifts and masks :)
> >
>
> Yup :P

I just wrote one, I can post it later :) It also found:

AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13

Should be 12 or a different mask...

> Thanks a lot for your comments, i'll address them asap and come up
> with a new version of this patch ;-)

My computer also hangs with the whole series... reverting the reset
part makes it work. I'll try and narrow that down later when I
get some time.

--
Bob Copeland %% http://www.bobcopeland.com


2009-01-31 20:50:13

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/1/31 Felix Fietkau <[email protected]>:
> Nick Kossifidis wrote:
>>>> [...]
>>>> @@ -2156,7 +2157,8 @@
>>>> #define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
>>>> #define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
>>>> #define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
>>>> -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
>>>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f9 /* Switch table idle (?) */
>>>> +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
>>>
>>> That doesn't look right.. should be 3f0? (still probably works, I guess).
>>>
>>
>> I know, but HAL does this...
>> AR_PHY_BIS(ah, 68, 0xFFFFFC06,
>> (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
>>
>> ~0xFFFFFC06 = 3F9
> How about splitting it up and making the 0x1 a separate flag?
>

Agree, i'll change eeprom.c too...

/* Get antenna modes */
ah->ah_antenna[mode][0] =
(ee->ee_ant_control[mode][0] << 4) | 0x1;

>> My intention is to reimplement hw_htoclock to account for half/quarter
>> rate so it'll soon be
>> clock = ath5k_hw_htoclock(1, channel->hw_value);
> AFAIK Sam's HAL might have a bug there. If I remember correctly, the MAC
> runs at the same clock speed with Half/Quarter rate.
> It's done that way in the legacy HAL. Though there is a possibility of
> it being hardware dependent, I'm pretty sure that it is that way at least
> on 5413.
>

Both HALs tweak clock this way on ar5212SetDeltaSlope on all chips. If
clock depends on channel bandwidth for turbo it makes sense to also
change on half/quarter rate operation.

>>>> + /* Set DAC/ADC delays */
>>>> + if (ah->ah_version == AR5K_AR5212) {
>>>> + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
>>>> + data = AR5K_PHY_SCAL_32MHZ_2417;
>>>> + else if (ath5k_eeprom_is_hb63(ah))
>>>> + data = AR5K_PHY_SCAL_32MHZ_HB63;
>>>> + else
>>>> + data = AR5K_PHY_SCAL_32MHZ;
>>>> + ath5k_hw_reg_write(ah, data, AR5K_PHY_SCAL);
>>>> + data = 0;
>>>
>>> why data = 0; ?
>>>
>> Instead of having multiple temporary variables, i use only "data". To
>> be sure that "data" is ok for use i always zero it each time i use it
>> so that we don't write any weird stuff by mistake.
> Wouldn't multiple temporary values be preferable, since the compiler
> optimizes that stuff anyway?
>

Hmm, you are right, i just opened ath5k.o with IDA and it seems
hw_reset has too many ints so what i'm doing is probably confusing for
gcc.



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-01 04:42:00

by Bob Copeland

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

On Sun, Feb 01, 2009 at 12:58:14AM +0200, Nick Kossifidis wrote:
> Are you all ok on the rest 4 patches ?

I skimmed the rest of the patches, all look good to me.

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-07 05:20:54

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

2009/2/7 Bob Copeland <[email protected]>:
> On Thu, Feb 05, 2009 at 11:06:59PM +0200, Nick Kossifidis wrote:
>> I think this is because we call reset too many times. Try removing
>> call to reset from config_interface, after some tests i did it seems
>> wrong (we don't need to reset pcu and if we do, we don't need to reset
>> the whole chip and re run phy initialization etc). I don't get any
>> problems with ar2425 but i didn't get any before anyway (i never got a
>> hang, just a few bmiss interrupts, not a storm).
>
> Yep, with BMISS interrupts turned off and config_interface no longer
> calling reset, it's quite stable now. Maybe there was some timing
> thing at play. If we add a patch to remove those then I'm satisfied :)
>

O.K. do you want me to put these fixes on this patch or post a separate ?



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-08 18:01:57

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

2009/2/8 John W. Linville <[email protected]>:
> On Sat, Feb 07, 2009 at 06:13:55PM +0200, Nick Kossifidis wrote:
>> 2009/2/7 Bob Copeland <[email protected]>:
>> > On Sat, Feb 07, 2009 at 07:20:52AM +0200, Nick Kossifidis wrote:
>> >> O.K. do you want me to put these fixes on this patch or post a separate ?
>> >
>> > I think a separate patch is fine, it's a valid change by itself.
>> >
>> > --
>> > Bob Copeland %% http://www.bobcopeland.com
>> >
>> >
>>
>> O.K. i'm sending a separate patch for this ;-)
>>
>> John is it ok to push these 5 patches on wireless-testing or should i
>> re-send the whole series along with the next one ?
>
> There has been a ton of discussion in this thread. It would make
> things more clear in my inbox if you reposted the whole revised series.
>
> Thanks!
>

ACK ;-)



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-05 21:06:59

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

2009/2/5 Bob Copeland <[email protected]>:
> On Wed, 4 Feb 2009 23:57:06 +0200, Nick Kossifidis wrote
>> * Update reset and sync with HALs
>> * Clean up eeprom settings and tweaking of initvals and put them on
> separate functions
>> * Set/Restore 32KHz ref clk operation
>> * Add some more documentation
>> TODO: Spur mitigation, tpc, half/quarter rate, compression etc
>>
>> v2: Address comments from Bob and Felix and fix RSSI threshold bug
>> introduced on the first version of the patch
>>
>> Signed-Off-by: Nick Kossifidis <[email protected]>
>
> This works much better, except I still get some hard hangs
> occasionally. Doesn't appear to be bmiss storm this time. I did it
> with a VT up and didn't get an oops; I guess I'll try a serial console
> or some printks.
>
> I could trigger it via a few suspend-resume cycles, so I guess it's the
> reset from ath5k_init(). Did you still have any problems with the 2425?
>

I think this is because we call reset too many times. Try removing
call to reset from config_interface, after some tests i did it seems
wrong (we don't need to reset pcu and if we do, we don't need to reset
the whole chip and re run phy initialization etc). I don't get any
problems with ar2425 but i didn't get any before anyway (i never got a
hang, just a few bmiss interrupts, not a storm).



--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-05 23:28:08

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

2009/2/5 Bob Copeland <[email protected]>:
> On Wed, 4 Feb 2009 23:57:06 +0200, Nick Kossifidis wrote
>> * Update reset and sync with HALs
>> * Clean up eeprom settings and tweaking of initvals and put them on
> separate functions
>> * Set/Restore 32KHz ref clk operation
>> * Add some more documentation
>> TODO: Spur mitigation, tpc, half/quarter rate, compression etc
>>
>> v2: Address comments from Bob and Felix and fix RSSI threshold bug
>> introduced on the first version of the patch
>>
>> Signed-Off-by: Nick Kossifidis <[email protected]>
>
> This works much better, except I still get some hard hangs
> occasionally. Doesn't appear to be bmiss storm this time. I did it
> with a VT up and didn't get an oops; I guess I'll try a serial console
> or some printks.
>

Did you disable BMISS interrupts on base.c ?





--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-07 16:13:56

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

2009/2/7 Bob Copeland <[email protected]>:
> On Sat, Feb 07, 2009 at 07:20:52AM +0200, Nick Kossifidis wrote:
>> O.K. do you want me to put these fixes on this patch or post a separate ?
>
> I think a separate patch is fine, it's a valid change by itself.
>
> --
> Bob Copeland %% http://www.bobcopeland.com
>
>

O.K. i'm sending a separate patch for this ;-)

John is it ok to push these 5 patches on wireless-testing or should i
re-send the whole series along with the next one ?


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-01 04:05:28

by Felix Fietkau

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

Nick Kossifidis wrote:
> 2009/2/1 Bob Copeland <[email protected]>:
>> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>>> > Heh, we should write a little tool to check the shifts and masks :)
>>> >
>>>
>>> Yup :P
>>
>> I just wrote one, I can post it later :) It also found:
>>
>> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>>
>> Should be 12 or a different mask...
>>
>
> 13 is correct
>
> 0x01ff3000 -> 1111111111110000000000000
I think it's 1111111110011000000000000? :)

This mask makes 12 seem more likely.

- Felix

2009-02-05 15:59:16

by Maxim Levitsky

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

On Thu, 2009-02-05 at 10:51 -0500, Bob Copeland wrote:
> On Wed, 4 Feb 2009 23:57:06 +0200, Nick Kossifidis wrote
> > * Update reset and sync with HALs
> > * Clean up eeprom settings and tweaking of initvals and put them on
> separate functions
> > * Set/Restore 32KHz ref clk operation
> > * Add some more documentation
> > TODO: Spur mitigation, tpc, half/quarter rate, compression etc
> >
> > v2: Address comments from Bob and Felix and fix RSSI threshold bug
> > introduced on the first version of the patch
> >
> > Signed-Off-by: Nick Kossifidis <[email protected]>
>
> This works much better, except I still get some hard hangs
> occasionally. Doesn't appear to be bmiss storm this time. I did it
> with a VT up and didn't get an oops; I guess I'll try a serial console
> or some printks.
>
> I could trigger it via a few suspend-resume cycles, so I guess it's the
> reset from ath5k_init(). Did you still have any problems with the 2425?
>

It also work better here, I didn't yet see these hangs, but nether I did
many suspend/resume cycles, so I'll take an another look.

But what I did see is that gain/noise timeouts still happen.
in exactly same way.

Best regards,
Maxim Levitsky


2009-02-01 04:50:21

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/1 Felix Fietkau <[email protected]>:
> Nick Kossifidis wrote:
>> 2009/2/1 Bob Copeland <[email protected]>:
>>> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>>>> > Heh, we should write a little tool to check the shifts and masks :)
>>>> >
>>>>
>>>> Yup :P
>>>
>>> I just wrote one, I can post it later :) It also found:
>>>
>>> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>>>
>>> Should be 12 or a different mask...
>>>
>>
>> 13 is correct
>>
>> 0x01ff3000 -> 1111111111110000000000000
> I think it's 1111111110011000000000000? :)
>
> This mask makes 12 seem more likely.
>
> - Felix
>

Maybe it's in big endian format (we don't know anything about this reg
anyway :P), both HALs have 13 plus it doesn't make sense to have a
field split.


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-06 03:52:38

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Thu, Feb 05, 2009 at 11:06:59PM +0200, Nick Kossifidis wrote:
> I think this is because we call reset too many times. Try removing
> call to reset from config_interface, after some tests i did it seems

Ok I'll try it, let you know ASAP.

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-07 14:40:01

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Sat, Feb 07, 2009 at 07:20:52AM +0200, Nick Kossifidis wrote:
> O.K. do you want me to put these fixes on this patch or post a separate ?

I think a separate patch is fine, it's a valid change by itself.

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-04 21:57:16

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

* Update reset and sync with HALs
* Clean up eeprom settings and tweaking of initvals and put them on separate functions
* Set/Restore 32KHz ref clk operation
* Add some more documentation
TODO: Spur mitigation, tpc, half/quarter rate, compression etc

v2: Address comments from Bob and Felix and fix RSSI threshold bug
introduced on the first version of the patch

Signed-Off-by: Nick Kossifidis <[email protected]>

---
drivers/net/wireless/ath5k/ath5k.h | 11 +-
drivers/net/wireless/ath5k/attach.c | 16 +-
drivers/net/wireless/ath5k/eeprom.c | 14 +-
drivers/net/wireless/ath5k/eeprom.h | 1 +
drivers/net/wireless/ath5k/reg.h | 56 +-
drivers/net/wireless/ath5k/reset.c | 930 +++++++++++++++++++++++++----------
6 files changed, 732 insertions(+), 296 deletions(-)

diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 5b2e0da..b9af2b8 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -222,6 +222,7 @@
#endif

/* Initial values */
+#define AR5K_INIT_CYCRSSI_THR1 2
#define AR5K_INIT_TX_LATENCY 502
#define AR5K_INIT_USEC 39
#define AR5K_INIT_USEC_TURBO 79
@@ -313,7 +314,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_AR5424 0x90 /* Condor */
#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
#define AR5K_SREV_AR5414 0xa0 /* Eagle */
-#define AR5K_SREV_AR2415 0xb0 /* Cobra */
+#define AR5K_SREV_AR2415 0xb0 /* Talon */
#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
#define AR5K_SREV_AR5418 0xca /* PCI-E */
#define AR5K_SREV_AR2425 0xe0 /* Swan */
@@ -331,7 +332,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_2112B 0x46
#define AR5K_SREV_RAD_2413 0x50
#define AR5K_SREV_RAD_5413 0x60
-#define AR5K_SREV_RAD_2316 0x70
+#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */
#define AR5K_SREV_RAD_2317 0x80
#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
#define AR5K_SREV_RAD_2425 0xa2
@@ -340,7 +341,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_PHY_5211 0x30
#define AR5K_SREV_PHY_5212 0x41
#define AR5K_SREV_PHY_5212A 0x42
-#define AR5K_SREV_PHY_2112B 0x43
+#define AR5K_SREV_PHY_5212B 0x43
#define AR5K_SREV_PHY_2413 0x45
#define AR5K_SREV_PHY_5413 0x61
#define AR5K_SREV_PHY_2425 0x70
@@ -1030,7 +1031,6 @@ struct ath5k_hw {
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
- u32 ah_phy_spending;

enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
@@ -1156,6 +1156,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
/* EEPROM access functions */
extern int ath5k_eeprom_init(struct ath5k_hw *ah);
extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);

/* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
@@ -1258,6 +1259,7 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);

/*
* Translate usec to hw clock units
+ * TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
{
@@ -1266,6 +1268,7 @@ static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)

/*
* Translate hw clock units to usec
+ * TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c
index a3f07a4..05bc5cb 100644
--- a/drivers/net/wireless/ath5k/attach.c
+++ b/drivers/net/wireless/ath5k/attach.c
@@ -169,7 +169,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ);
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
break;
case AR5K_SREV_RAD_5112:
case AR5K_SREV_RAD_2112:
@@ -177,38 +176,31 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ);
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
break;
case AR5K_SREV_RAD_2413:
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
break;
case AR5K_SREV_RAD_5413:
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
break;
case AR5K_SREV_RAD_2316:
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
break;
case AR5K_SREV_RAD_2317:
ah->ah_radio = AR5K_RF2317;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2317;
break;
case AR5K_SREV_RAD_5424:
if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
ah->ah_mac_version == AR5K_SREV_AR2417){
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
}
break;
default:
@@ -227,29 +219,25 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else if (srev == AR5K_SREV_AR5213A &&
- ah->ah_phy_revision == AR5K_SREV_PHY_2112B) {
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
- ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2112B;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
- ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
} else {
ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
ret = -ENODEV;
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
index b4ec539..21b9334 100644
--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -204,7 +204,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,

/* Get antenna modes */
ah->ah_antenna[mode][0] =
- (ee->ee_ant_control[mode][0] << 4) | 0x1;
+ (ee->ee_ant_control[mode][0] << 4);
ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
ee->ee_ant_control[mode][1] |
(ee->ee_ant_control[mode][2] << 6) |
@@ -1412,6 +1412,7 @@ ath5k_eeprom_init(struct ath5k_hw *ah)

return 0;
}
+
/*
* Read the MAC address from eeprom
*/
@@ -1448,3 +1449,14 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
return 0;
}

+bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
+{
+ u16 data;
+
+ ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
+ return true;
+ else
+ return false;
+}
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h
index 09eb7d0..1deebc0 100644
--- a/drivers/net/wireless/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath5k/eeprom.h
@@ -25,6 +25,7 @@
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */

+#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index 84f4669..2dc008e 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -187,6 +187,7 @@
#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */
#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */
+#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */
#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */

/*
@@ -753,7 +754,7 @@
*/
#define AR5K_DCU_SEQNUM_BASE 0x1140
#define AR5K_DCU_SEQNUM_M 0x00000fff
-#define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)

/*
* DCU global IFS SIFS register
@@ -1467,7 +1468,7 @@
#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */
#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */
#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */
-#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* Test ARM (Adaptive Radio Mode ?) */
+#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */

/*
* Default antenna register [5211+]
@@ -1679,7 +1680,7 @@
* TSF parameter register
*/
#define AR5K_TSF_PARM 0x8104 /* Register Address */
-#define AR5K_TSF_PARM_INC_M 0x000000ff /* Mask for TSF increment */
+#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */
#define AR5K_TSF_PARM_INC_S 0

/*
@@ -1691,7 +1692,7 @@
#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
#define AR5K_QOS_NOACK_BIT_OFFSET_S 4
#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */
-#define AR5K_QOS_NOACK_BYTE_OFFSET_S 8
+#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7

/*
* PHY error filter register
@@ -1850,15 +1851,14 @@
* TST_2 (Misc config parameters)
*/
#define AR5K_PHY_TST2 0x9800 /* Register Address */
-#define AR5K_PHY_TST2_TRIG_SEL 0x00000001 /* Trigger select (?) (field ?) */
-#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) (field ?) */
-#define AR5K_PHY_TST2_CBUS_MODE 0x00000100 /* Cardbus mode (?) */
-/* bit reserved */
+#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
+#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
+#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
-#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch) */
+#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */
#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */
#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */
#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */
@@ -1928,8 +1928,8 @@
#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0

#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* TX end to XLNA on */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 0
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8

#define AR5K_PHY_ADC_CTL 0x982c
#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
@@ -1963,7 +1963,7 @@
#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
#define AR5K_PHY_SETTLING_AGC_S 0
#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
-#define AR5K_PHY_SETTLINK_SWITCH_S 7
+#define AR5K_PHY_SETTLING_SWITCH_S 7

/*
* PHY Gain registers
@@ -2069,14 +2069,14 @@
* PHY sleep registers [5112+]
*/
#define AR5K_PHY_SCR 0x9870
-#define AR5K_PHY_SCR_32MHZ 0x0000001f

#define AR5K_PHY_SLMT 0x9874
#define AR5K_PHY_SLMT_32MHZ 0x0000007f

#define AR5K_PHY_SCAL 0x9878
#define AR5K_PHY_SCAL_32MHZ 0x0000000e
-
+#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
+#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032

/*
* PHY PLL (Phase Locked Loop) control register
@@ -2156,7 +2156,8 @@
#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
-#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4

/*
* PHY receiver delay register [5111+]
@@ -2196,7 +2197,7 @@
#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
-#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
@@ -2279,6 +2280,15 @@
AR5K_PHY_FRAME_CTL_TIMING_ERR

/*
+ * PHY Tx Power adjustment register [5212A+]
+ */
+#define AR5K_PHY_TX_PWR_ADJ 0x994c
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18
+
+/*
* PHY radar detection register [5111+]
*/
#define AR5K_PHY_RADAR 0x9954
@@ -2331,7 +2341,7 @@
#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8
-#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13

/*
@@ -2459,17 +2469,7 @@
#define AR5K_PHY_SDELAY 0x99f4
#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
#define AR5K_PHY_SPENDING 0x99f8
-#define AR5K_PHY_SPENDING_14 0x00000014
-#define AR5K_PHY_SPENDING_18 0x00000018
-#define AR5K_PHY_SPENDING_RF5111 0x00000018
-#define AR5K_PHY_SPENDING_RF5112 0x00000014
-/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */
-/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */
-#define AR5K_PHY_SPENDING_RF5413 0x00000018
-#define AR5K_PHY_SPENDING_RF2413 0x00000018
-#define AR5K_PHY_SPENDING_RF2316 0x00000018
-#define AR5K_PHY_SPENDING_RF2317 0x00000018
-#define AR5K_PHY_SPENDING_RF2425 0x00000014
+

/*
* PHY PAPD I (power?) table (?)
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
index 579c64c..1531ccd 100644
--- a/drivers/net/wireless/ath5k/reset.c
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -25,7 +25,8 @@
Reset functions and helpers
\*****************************/

-#include <linux/pci.h>
+#include <linux/pci.h> /* To determine if a card is pci-e */
+#include <linux/bitops.h> /* For get_bitmask_order */
#include "ath5k.h"
#include "reg.h"
#include "base.h"
@@ -37,10 +38,14 @@
* @ah: the &struct ath5k_hw
* @channel: the currently set channel upon reset
*
- * Write the OFDM timings for the AR5212 upon reset. This is a helper for
- * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
- * depending on the bandwidth of the channel.
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
*
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
*/
static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
struct ieee80211_channel *channel)
@@ -53,23 +58,34 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM))
BUG();

- /* Seems there are two PLLs, one for baseband sampling and one
- * for tuning. Tuning basebands are 40 MHz or 80MHz when in
- * turbo. */
- clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
- coef_scaled = ((5 * (clock << 24)) / 2) /
- channel->center_freq;
+ /* Get coefficient
+ * ALGO: coef = (5 * clock * carrier_freq) / 2)
+ * we scale coef by shifting clock value by 24 for
+ * better precision since we use integers */
+ /* TODO: Half/quarter rate */
+ clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);

- for (coef_exp = 31; coef_exp > 0; coef_exp--)
- if ((coef_scaled >> coef_exp) & 0x1)
- break;
+ coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+ /* Get exponent
+ * ALGO: coef_exp = 14 - highest set bit position */
+ coef_exp = get_bitmask_order(coef_scaled);

+ /* Doesn't make sense if it's zero*/
if (!coef_exp)
return -EINVAL;

+ /* Note: we've shifted coef_scaled by 24 */
coef_exp = 14 - (coef_exp - 24);
+
+
+ /* Get mantissa (significant digits)
+ * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
coef_man = coef_scaled +
(1 << (24 - coef_exp - 1));
+
+ /* Calculate delta slope coefficient exponent
+ * and mantissa (remove scaling) and set them on hw */
ds_coef_man = coef_man >> (24 - coef_exp);
ds_coef_exp = coef_exp - 16;

@@ -90,16 +106,23 @@ static int control_rates[] =
{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };

/**
- * ath5k_hw_write_rate_duration - set rate duration during hw resets
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
*
* @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode
*
- * Write the rate duration table upon hw reset. This is a helper for
- * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout for
- * the hardware for the current mode for each rate. The rates which are capable
- * of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another
- * register for the short preamble ACK timeout calculation.
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preample
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
+ * quarter rate mode, we need to use another set of bitrates (that's why we
+ * need the mode parameter) but we don't handle these proprietary modes yet.
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int mode)
@@ -275,7 +298,8 @@ commit:
}

/*
- * Bring up MAC + PHY Chips
+ * Bring up MAC + PHY Chips and program PLL
+ * TODO: Half/Quarter rate support
*/
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{
@@ -333,7 +357,11 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}
} else if (flags & CHANNEL_5GHZ) {
mode |= AR5K_PHY_MODE_FREQ_5GHZ;
- clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (ah->ah_radio == AR5K_RF5413)
+ clock |= AR5K_PHY_PLL_40MHZ_5413;
+ else
+ clock |= AR5K_PHY_PLL_40MHZ;

if (flags & CHANNEL_OFDM)
mode |= AR5K_PHY_MODE_MOD_OFDM;
@@ -391,10 +419,14 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}

if (ah->ah_version != AR5K_AR5210) {
- /* ...set the PHY operating mode */
- ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
- udelay(300);

+ /* ...update PLL if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+ }
+
+ /* ...set the PHY operating mode */
ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
}
@@ -403,22 +435,393 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
}

/*
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power during sleep or restore normal 32/40MHz
+ * operation.
+ *
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ * 123 - 127) require delay on access.
+ */
+static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 scal, spending, usec32;
+
+ /* Only set 32KHz settings if we have an external
+ * 32KHz crystal present */
+ if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+ AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+ enable) {
+
+ /* 1 usec/cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
+ /* Set up tsf increment on each cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
+
+ /* Set baseband sleep control registers
+ * and sleep control rate */
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
+ } else {
+ ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
+ }
+
+ /* Enable sleep clock operation */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+ } else {
+
+ /* Disable sleep clock operation and
+ * restore default parameters */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413))
+ usec32 = 39;
+ else
+ usec32 = 31;
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+ }
+ return;
+}
+
+static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u8 refclk_freq;
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ refclk_freq = 40;
+ else
+ refclk_freq = 32;
+
+ if ((channel->center_freq % refclk_freq != 0) &&
+ ((channel->center_freq % refclk_freq < 10) ||
+ (channel->center_freq % refclk_freq > 22)))
+ return true;
+ else
+ return false;
+}
+
+/* TODO: Half/Quarter rate */
+static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+
+ /* Setup ADC control */
+ ath5k_hw_reg_write(ah,
+ (AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
+ AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
+ AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
+ AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
+ AR5K_PHY_ADC_CTL);
+
+
+
+ /* Disable barker RSSI threshold */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
+
+ /* Set the mute mask */
+ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+ }
+
+ /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
+
+ /* Enable DCU double buffering */
+ if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_DCU_DBL_BUF_DIS);
+
+ /* Set DAC/ADC delays */
+ if (ah->ah_version == AR5K_AR5212) {
+ u32 scal;
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+ }
+
+ /* Set fast ADC */
+ if ((ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ u32 fast_adc = true;
+
+ if (channel->center_freq == 2462 ||
+ channel->center_freq == 2467)
+ fast_adc = 0;
+
+ /* Only update if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
+ ath5k_hw_reg_write(ah, fast_adc,
+ AR5K_PHY_FAST_ADC);
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio == AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ u32 data;
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ }
+
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ u32 usec_reg;
+ /* 5311 has different tx/rx latency masks
+ * from 5211, since we deal 5311 the same
+ * as 5211 when setting initvals, shift
+ * values here to their proper locations */
+ usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+ ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
+ AR5K_USEC_32 |
+ AR5K_USEC_TX_LATENCY_5211 |
+ AR5K_REG_SM(29,
+ AR5K_USEC_RX_LATENCY_5210)),
+ AR5K_USEC_5211);
+ /* Clear QCU/DCU clock gating register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
+ /* Set DAC/ADC delays */
+ ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+ /* Enable PCU FIFO corruption ECO */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_ECO_ENABLE);
+ }
+}
+
+static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+
+ /* Set CCK to OFDM power delta */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+ int16_t cck_ofdm_pwr_delta;
+
+ /* Adjust power delta for channel 14 */
+ if (channel->center_freq == 2484)
+ cck_ofdm_pwr_delta =
+ ((ee->ee_cck_ofdm_power_delta -
+ ee->ee_scaled_cck_delta) * 2) / 10;
+ else
+ cck_ofdm_pwr_delta =
+ (ee->ee_cck_ofdm_power_delta * 2) / 10;
+
+ if (channel->hw_value == CHANNEL_G)
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
+ AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
+ AR5K_PHY_TX_PWR_ADJ);
+ else
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
+ }
+
+ /* Set antenna idle switch table */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+ AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+ (ah->ah_antenna[ee_mode][0] |
+ AR5K_PHY_ANT_CTL_TXRX_EN));
+
+ /* Set antenna switch table */
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Noise floor threshold */
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY_NFTHRES);
+
+ if ((channel->hw_value & CHANNEL_TURBO) &&
+ (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
+ /* Switch settling time (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling_turbo[ee_mode]);
+
+ /* Tx/Rx attenuation (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx_turbo[ee_mode]);
+
+ /* ADC/PGA desired size (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size_turbo[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size_turbo[ee_mode]);
+
+ /* Tx/Rx margin (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx_turbo[ee_mode]);
+
+ } else {
+ /* Switch settling time */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling[ee_mode]);
+
+ /* Tx/Rx attenuation */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx[ee_mode]);
+
+ /* ADC/PGA desired size */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size[ee_mode]);
+
+ /* Tx/Rx margin */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+ }
+
+ /* XPA delays */
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+ /* XLNA delay */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
+ AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
+ ee->ee_tx_end2xlna_enable[ee_mode]);
+
+ /* Thresh64 (ANI) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
+ AR5K_PHY_NF_THRESH62,
+ ee->ee_thr_62[ee_mode]);
+
+
+ /* False detect backoff for channels
+ * that have spur noise. Write the new
+ * cyclic power RSSI threshold. */
+ if (ath5k_hw_chan_has_spur_noise(ah, channel))
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1 +
+ ee->ee_false_detect[ee_mode]);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1);
+
+ /* I/Q correction
+ * TODO: Per channel i/q infos ? */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ /* Heavy clipping -disable for now */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
+
+ return;
+}
+
+/*
* Main reset function
*/
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool change_channel)
{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- struct pci_dev *pdev = ah->ah_sc->pdev;
- u32 data, s_seq, s_ant, s_led[3], dma_size;
- unsigned int i, mode, freq, ee_mode, ant[2];
- int ret;
+ u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
+ u32 phy_tst1;
+ u8 mode, freq, ee_mode, ant[2];
+ int i, ret;

ATH5K_TRACE(ah->ah_sc);

- s_seq = 0;
s_ant = 0;
ee_mode = 0;
+ staid1_flags = 0;
+ tsf_up = 0;
+ tsf_lo = 0;
freq = 0;
mode = 0;

@@ -427,36 +830,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*/
/*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) {
- if (change_channel) {
- /* Seq number for queue 0 -do this for all queues ? */
- s_seq = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DFS_SEQNUM(0));
- /*Default antenna*/
- s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
- }
- }
-
- /*GPIOs*/
- s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
- s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
- s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
-
- /*Wakeup the device*/
- ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
- if (ret)
- return ret;
-
- /*
- * Initialize operating mode
- */
- ah->ah_op_mode = op_mode;
-
- /*
- * 5111/5112 Settings
- * 5210 only comes with RF5110
- */
- if (ah->ah_version != AR5K_AR5210) {

switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
@@ -479,8 +852,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
break;
- /*Is this ok on 5211 too ?*/
case CHANNEL_TG:
+ if (ah->ah_version == AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "TurboG mode not available on 5211");
+ return -EINVAL;
+ }
mode = AR5K_MODE_11G_TURBO;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
@@ -501,11 +878,93 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
return -EINVAL;
}

+ if (change_channel) {
+ /*
+ * Save frame sequence count
+ * For revs. after Oahu, only save
+ * seq num for DCU 0 (Global seq num)
+ */
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+ for (i = 0; i < 10; i++)
+ s_seq[i] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(i));
+
+ } else {
+ s_seq[0] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+
+ /* TSF accelerates on AR5211 durring reset
+ * As a workaround save it here and restore
+ * it later so that it's back in time after
+ * reset. This way it'll get re-synced on the
+ * next beacon without breaking ad-hoc.
+ *
+ * On AR5212 TSF is almost preserved across a
+ * reset so it stays back in time anyway and
+ * we don't have to save/restore it.
+ *
+ * XXX: Since this breaks power saving we have
+ * to disable power saving until we receive the
+ * next beacon, so we can resync beacon timers */
+ if (ah->ah_version == AR5K_AR5211) {
+ tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+ }
+ }
+
+ /* Save default antenna */
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ /* Restore normal 32/40MHz clock operation
+ * to avoid register access delay on certain
+ * PHY registers */
+ ath5k_hw_set_sleep_clock(ah, false);
+
+ /* Since we are going to write rf buffer
+ * check if we have any pending gain_F
+ * optimization settings */
+ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_gainf_calibrate(ah);
+ }
}

+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ /* AR5K_STA_ID1 flags, only preserve antenna
+ * settings and ack/cts rate mode */
+ staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
+ (AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_DESC_ANTENNA |
+ AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ AR5K_STA_ID1_ACKCTS_6MB |
+ AR5K_STA_ID1_BASE_RATE_11B |
+ AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+ /* Wakeup the device */
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Initialize operating mode
+ */
+ ah->ah_op_mode = op_mode;
+
/* PHY access enable */
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ else
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
+ AR5K_PHY(0));

+ /* Write initial settings */
ret = ath5k_hw_write_initvals(ah, mode, change_channel);
if (ret)
return ret;
@@ -514,6 +973,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* 5211/5212 Specific
*/
if (ah->ah_version != AR5K_AR5210) {
+
/*
* Write initial RF gain settings
* This should work for both 5111/5112
@@ -525,53 +985,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
mdelay(1);

/*
- * Write some more initial register settings for revised chips
+ * Tweak initval settings for revised
+ * chipsets and add some more config
+ * bits
*/
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_phy_revision > 0x41) {
- ath5k_hw_reg_write(ah, 0x0002a002, 0x982c);
-
- if (channel->hw_value == CHANNEL_G)
- if (ah->ah_mac_srev < AR5K_SREV_AR2413)
- ath5k_hw_reg_write(ah, 0x00f80d80,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_AR5424)
- ath5k_hw_reg_write(ah, 0x00380140,
- 0x994c);
- else if (ah->ah_mac_srev < AR5K_SREV_AR2425)
- ath5k_hw_reg_write(ah, 0x00fc0ec0,
- 0x994c);
- else /* 2425 */
- ath5k_hw_reg_write(ah, 0x00fc0fc0,
- 0x994c);
- else
- ath5k_hw_reg_write(ah, 0x00000000, 0x994c);
-
- /* Got this from legacy-hal */
- AR5K_REG_DISABLE_BITS(ah, 0xa228, 0x200);
-
- AR5K_REG_MASKED_BITS(ah, 0xa228, 0x800, 0xfffe03ff);
-
- /* Just write 0x9b5 ? */
- /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */
- ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
- ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
- ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
- }
-
- /* Fix for first revision of the RF5112 RF chipset */
- if (ah->ah_radio >= AR5K_RF5112 &&
- ah->ah_radio_5ghz_revision <
- AR5K_SREV_RAD_5112A) {
- ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
- AR5K_PHY_CCKTXCTL);
- if (channel->hw_value & CHANNEL_5GHZ)
- data = 0xffb81020;
- else
- data = 0xffb80d20;
- ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
- data = 0;
- }
+ ath5k_hw_tweak_initval_settings(ah, channel);

/*
* Set TX power (FIXME)
@@ -589,15 +1007,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_write_rate_duration(ah, mode);

/*
- * Write RF registers
+ * Write RF buffer
*/
ret = ath5k_hw_rfregs_init(ah, channel, mode);
if (ret)
return ret;

- /*
- * Configure additional registers
- */

/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
@@ -619,17 +1034,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}

/*
- * Set channel and calibrate the PHY
- */
- ret = ath5k_hw_channel(ah, channel);
- if (ret)
- return ret;
-
- /* Set antenna mode */
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL,
- ah->ah_antenna[ee_mode][0], 0xfffffc06);
-
- /*
* In case a fixed antenna was set as default
* write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
* registers.
@@ -644,54 +1048,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ant[1] = AR5K_ANT_FIXED_B;
}

- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
- AR5K_PHY_ANT_SWITCH_TABLE_0);
- ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
- AR5K_PHY_ANT_SWITCH_TABLE_1);
-
/* Commit values from EEPROM */
- if (ah->ah_radio == AR5K_RF5111)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
- AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
-
- ath5k_hw_reg_write(ah,
- AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
- AR5K_PHY_NFTHRES);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING,
- (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
- 0xffffc07f);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
- (ee->ee_atn_tx_rx[ee_mode] << 12) & 0x3f000,
- 0xfffc0fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
- (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
- ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
- 0xffff0000);
-
- ath5k_hw_reg_write(ah,
- (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
- (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
- (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
- (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
-
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3,
- ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF,
- (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
- AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01);
-
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CORR_ENABLE |
- (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
- ee->ee_q_cal[ee_mode]);
-
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
- AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
- ee->ee_margin_tx_rx[ee_mode]);
+ ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);

} else {
+ /*
+ * For 5210 we do all initialization using
+ * initvals, so we don't have to modify
+ * any settings (5210 also only supports
+ * a/aturbo modes)
+ */
mdelay(1);
/* Disable phy and wait */
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
@@ -701,100 +1067,154 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/*
* Restore saved values
*/
+
/*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) {
- ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
+
+ if (change_channel) {
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ for (i = 0; i < 10; i++)
+ ath5k_hw_reg_write(ah, s_seq[i],
+ AR5K_QUEUE_DCU_SEQNUM(i));
+ } else {
+ ath5k_hw_reg_write(ah, s_seq[0],
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+
+
+ if (ah->ah_version == AR5K_AR5211) {
+ ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
+ ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
+ }
+ }
+
ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
}
+
+ /* Ledstate */
AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+
+ /* Gpio settings */
ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);

+ /* Restore sta_id flags and preserve our mac address*/
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
+ AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
+ AR5K_STA_ID1);
+
+
/*
- * Misc
+ * Configure PCU
*/
+
+ /* Restore bssid and bssid mask */
/* XXX: add ah->aid once mac80211 gives this to us */
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);

+ /* Set PCU config */
ath5k_hw_set_opmode(ah);
- /*PISR/SISR Not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
+
+ /* Clear any pending interrupts
+ * PISR/SISR Not available on 5210 */
+ if (ah->ah_version != AR5K_AR5210)
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
- /* If we later allow tuning for this, store into sc structure */
- data = AR5K_TUNE_RSSI_THRES |
- AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
- ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
+
+ /* Set RSSI/BRSSI thresholds
+ *
+ * Note: If we decide to set this value
+ * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * register is read it might return 0x40 if we haven't
+ * wrote anything to it plus BMISS RSSI threshold is zeroed.
+ * So doing a save/restore procedure here isn't the right
+ * choice. Instead store it on ath5k_hw */
+ ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES <<
+ AR5K_RSSI_THR_BMISS_S),
+ AR5K_RSSI_THR);
+
+ /* MIC QoS support */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+ ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+ ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+ }
+
+ /* QoS NOACK Policy */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+ AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
+ AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+ AR5K_QOS_NOACK);
}

+
/*
- * Set Rx/Tx DMA Configuration
- *
- * Set maximum DMA size (512) except for PCI-E cards since
- * it causes rx overruns and tx errors (tested on 5424 but since
- * rx overruns also occur on 5416/5418 with madwifi we set 128
- * for all PCI-E cards to be safe).
- *
- * In dumps this is 128 for allchips.
- *
- * XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
- * guess we can tweak it and see how it goes ;-)
+ * Configure PHY
*/
- dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
- if (ah->ah_version != AR5K_AR5210) {
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_SDMAMR, dma_size);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
- AR5K_RXCFG_SDMAMW, dma_size);
- }
+
+ /* Set channel on PHY */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;

/*
* Enable the PHY and wait until completion
+ * This includes BaseBand and Synthesizer
+ * activation.
*/
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);

/*
* On 5211+ read activation -> rx delay
* and use it.
+ *
+ * TODO: Half/quarter rate support
*/
if (ah->ah_version != AR5K_AR5210) {
- data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ u32 delay;
+ delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
AR5K_PHY_RX_DELAY_M;
- data = (channel->hw_value & CHANNEL_CCK) ?
- ((data << 2) / 22) : (data / 10);
+ delay = (channel->hw_value & CHANNEL_CCK) ?
+ ((delay << 2) / 22) : (delay / 10);

- udelay(100 + (2 * data));
- data = 0;
+ udelay(100 + (2 * delay));
} else {
mdelay(1);
}

/*
- * Perform ADC test (?)
+ * Perform ADC test to see if baseband is ready
+ * Set tx hold and check adc test register
*/
- data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+ phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
for (i = 0; i <= 20; i++) {
if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
break;
udelay(200);
}
- ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1);
- data = 0;
+ ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);

/*
- * Start automatic gain calibration
+ * Start automatic gain control calibration
*
* During AGC calibration RX path is re-routed to
- * a signal detector so we don't receive anything.
+ * a power detector so we don't receive anything.
*
* This method is used to calibrate some static offsets
* used together with on-the fly I/Q calibration (the
* one performed via ath5k_hw_phy_calibrate), that doesn't
* interrupt rx path.
*
+ * While rx path is re-routed to the power detector we also
+ * start a noise floor calibration, to measure the
+ * card's noise floor (the noise we measure when we are not
+ * transmiting or receiving anything).
+ *
* If we are in a noisy environment AGC calibration may time
- * out.
+ * out and/or noise floor calibration might timeout.
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL);
@@ -816,30 +1236,37 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
channel->center_freq);
- return -EAGAIN;
}

/*
- * Start noise floor calibration
- *
* If we run NF calibration before AGC, it always times out.
* Binary HAL starts NF and AGC calibration at the same time
- * and only waits for AGC to finish. I believe that's wrong because
- * during NF calibration, rx path is also routed to a detector, so if
- * it doesn't finish we won't have RX.
- *
- * XXX: Find an interval that's OK for all cards...
+ * and only waits for AGC to finish. Also if AGC or NF cal.
+ * times out, reset doesn't fail on binary HAL. I believe
+ * that's wrong because since rx path is routed to a detector,
+ * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
+ * enables noise floor calibration after offset calibration and if noise
+ * floor calibration fails, reset fails. I believe that's
+ * a better approach, we just need to find a polling interval
+ * that suits best, even if reset continues we need to make
+ * sure that rx path is ready.
*/
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);

+
+ /*
+ * Configure QCUs/DCUs
+ */
+
+ /* TODO: HW Compression support for data queues */
+ /* TODO: Burst prefetch for data queues */
+
/*
* Reset queues and start beacon timers at the end of the reset routine
+ * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+ * Note: If we want we can assign multiple qcus on one dcu.
*/
for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
- /*No QCU on 5210*/
- if (ah->ah_version != AR5K_AR5210)
- AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
-
ret = ath5k_hw_reset_tx_queue(ah, i);
if (ret) {
ATH5K_ERR(ah->ah_sc,
@@ -848,14 +1275,40 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
}

+
+ /*
+ * Configure DMA/Interrupts
+ */
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set standard DMA size (128). Note that
+ * a DMA size of 512 causes rx overruns and tx errors
+ * on pci-e cards (tested on 5424 but since rx overruns
+ * also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+ }
+
/* Pre-enable interrupts on 5211/5212*/
if (ah->ah_version != AR5K_AR5210)
ath5k_hw_set_imr(ah, ah->ah_imr);

/*
- * Set RF kill flags if supported by the device (read from the EEPROM)
- * Disable gpio_intr for now since it results system hang.
- * TODO: Handle this in ath5k_intr
+ * Setup RFKill interrupt if rfkill flag is set on eeprom.
+ * TODO: Use gpio pin and polarity infos from eeprom
+ * TODO: Handle this in ath5k_intr because it'll result
+ * a nasty interrupt storm.
*/
#if 0
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
@@ -868,33 +1321,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
#endif

- /*
- * Set the 32MHz reference clock on 5212 phy clock sleep register
- *
- * TODO: Find out how to switch to external 32Khz clock to save power
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
- ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
- ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
-
- data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ;
- data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ?
- 0x00000f80 : 0x00001380 ;
- ath5k_hw_reg_write(ah, data, AR5K_USEC_5211);
- data = 0;
- }
-
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
- ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
- ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
- if (ah->ah_mac_srev >= AR5K_SREV_AR2413)
- ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
- }
+ /* Enable 32KHz clock function for AR5212+ chips
+ * Set clocks to 32KHz operation and use an
+ * external 32KHz crystal when sleeping if one
+ * exists */
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_set_sleep_clock(ah, true);

/*
* Disable beacons and reset the register


2009-02-01 05:14:31

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/1 Felix Fietkau <[email protected]>:
> Nick Kossifidis wrote:
>> 2009/2/1 Felix Fietkau <[email protected]>:
>>> Nick Kossifidis wrote:
>>>> 2009/2/1 Bob Copeland <[email protected]>:
>>>>> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>>>>>> > Heh, we should write a little tool to check the shifts and masks :)
>>>>>> >
>>>>>>
>>>>>> Yup :P
>>>>>
>>>>> I just wrote one, I can post it later :) It also found:
>>>>>
>>>>> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>>>>>
>>>>> Should be 12 or a different mask...
>>>>>
>>>>
>>>> 13 is correct
>>>>
>>>> 0x01ff3000 -> 1111111111110000000000000
>>> I think it's 1111111110011000000000000? :)
>>>
>>> This mask makes 12 seem more likely.
>>>
>>> - Felix
>>>
>>
>> Maybe it's in big endian format (we don't know anything about this reg
>> anyway :P), both HALs have 13 plus it doesn't make sense to have a
>> field split.
> Ah, figured it out. It's a typo :)
> Here are the settings from Sam's HAL:
>
> #define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
> #define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
>
> Which does make a lot more sense than 0x01FF3000 :)
>
> - Felix
>

/me has to get a new pair of glasses :P


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-04 05:14:20

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/4 Bob Copeland <[email protected]>:
> On Tue, Feb 03, 2009 at 06:28:47PM +0200, Nick Kossifidis wrote:
>> Nice catch ;-)
>>
>> Another difference i remembered is that we now don't set the TPC
>> register to 3f (until we fix the whole tx power stuff). I'll try to
>> reproduce this with my ar2425 as it turns it also has problems.
>
> And the winning hunk is:
>
> if (ah->ah_version != AR5K_AR5210) {
> ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
> - /* If we later allow tuning for this, store into sc structure */
> - data = AR5K_TUNE_RSSI_THRES |
> - AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
> - ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
> }
>
> (hmm, bmiss threshold, should've seen that before...)
>
> With that reverted from the rest of the patchset, I no longer get the
> interrupt storm. I do seem to get an occasional lockup at association
> time, but I haven't caught an oops for that yet. It could be unrelated.
>

O.K. i got that from legacy HAL. It first reads the register and if
it's zeroed it sets to the default value of 0x781 (which is the same
really, it's AR5K_TUNE_RSSI_THRES | AR5K_TUNE_BMISS_THRES <<
AR5K_RSSI_THR_BMISS_S), if not it saves it and restores it after reset
is done.

So can you see why this

/* Save RSSI thresholds (they 'll get zeroed from initvals) */
rssi_thr = ath5k_hw_reg_read(ah, AR5K_RSSI_THR);
/* If they are not set, set the default value */
if (!rssi_thr)
rssi_thr = AR5K_INIT_RSSI_THR;

doesn't work ? What is the value of rssi_trh if not zero ?

--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-03 16:28:48

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/3 Bob Copeland <[email protected]>:
> On Sat, 31 Jan 2009 04:31:47 +0200, Nick Kossifidis wrote
>> int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
>> struct ieee80211_channel *channel, bool change_channel)
>
> Here's another thing I just noticed:
>
>> {
>> + u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
>
> s_seq is now an array (we used to initialize s_seq to 0)
>
> [...]
>> + if (change_channel) {
>> + /*
>> + * Save frame sequence count
>> + * For revs. after Oahu, only save
>> + * seq num for DCU 0 (Global seq num)
>> + */
>> + if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
>> +
>> + for (i = 0; i < 10; i++)
>> + s_seq[i] = ath5k_hw_reg_read(ah,
>> + AR5K_QUEUE_DCU_SEQNUM(i));
>> +
>> + } else {
>> + s_seq[0] = ath5k_hw_reg_read(ah,
>> + AR5K_QUEUE_DCU_SEQNUM(0));
>> + }
>
> We only save the DCU sequence values if changing a channel
>
> [...]
>
>> if (ah->ah_version != AR5K_AR5210) {
>> - ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
>> +
>> + if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
>> + for (i = 0; i < 10; i++)
>> + ath5k_hw_reg_write(ah, s_seq[i],
>> + AR5K_QUEUE_DCU_SEQNUM(i));
>> + } else {
>> + ath5k_hw_reg_write(ah, s_seq[0],
>> + AR5K_QUEUE_DCU_SEQNUM(0));
>> + }
>
> But always write it. The old code did this too, the only difference
> was we explicitly initialized the s_seq[0] to 0. Since it's an array,
> gcc won't warn about it but s_seq[] probably has random crap in it.
>

Nice catch ;-)

Another difference i remembered is that we now don't set the TPC
register to 3f (until we fix the whole tx power stuff). I'll try to
reproduce this with my ar2425 as it turns it also has problems.


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-05 15:52:11

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Wed, 4 Feb 2009 23:57:06 +0200, Nick Kossifidis wrote
> * Update reset and sync with HALs
> * Clean up eeprom settings and tweaking of initvals and put them on
separate functions
> * Set/Restore 32KHz ref clk operation
> * Add some more documentation
> TODO: Spur mitigation, tpc, half/quarter rate, compression etc
>
> v2: Address comments from Bob and Felix and fix RSSI threshold bug
> introduced on the first version of the patch
>
> Signed-Off-by: Nick Kossifidis <[email protected]>

This works much better, except I still get some hard hangs
occasionally. Doesn't appear to be bmiss storm this time. I did it
with a VT up and didn't get an oops; I guess I'll try a serial console
or some printks.

I could trigger it via a few suspend-resume cycles, so I guess it's the
reset from ath5k_init(). Did you still have any problems with the 2425?

--
Bob Copeland %% http://www.bobcopeland.com



2009-02-08 18:01:03

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Sat, Feb 07, 2009 at 06:13:55PM +0200, Nick Kossifidis wrote:
> 2009/2/7 Bob Copeland <[email protected]>:
> > On Sat, Feb 07, 2009 at 07:20:52AM +0200, Nick Kossifidis wrote:
> >> O.K. do you want me to put these fixes on this patch or post a separate ?
> >
> > I think a separate patch is fine, it's a valid change by itself.
> >
> > --
> > Bob Copeland %% http://www.bobcopeland.com
> >
> >
>
> O.K. i'm sending a separate patch for this ;-)
>
> John is it ok to push these 5 patches on wireless-testing or should i
> re-send the whole series along with the next one ?

There has been a ton of discussion in this thread. It would make
things more clear in my inbox if you reposted the whole revised series.

Thanks!

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2009-02-01 05:07:28

by Felix Fietkau

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

Nick Kossifidis wrote:
> 2009/2/1 Felix Fietkau <[email protected]>:
>> Nick Kossifidis wrote:
>>> 2009/2/1 Bob Copeland <[email protected]>:
>>>> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>>>>> > Heh, we should write a little tool to check the shifts and masks :)
>>>>> >
>>>>>
>>>>> Yup :P
>>>>
>>>> I just wrote one, I can post it later :) It also found:
>>>>
>>>> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>>>>
>>>> Should be 12 or a different mask...
>>>>
>>>
>>> 13 is correct
>>>
>>> 0x01ff3000 -> 1111111111110000000000000
>> I think it's 1111111110011000000000000? :)
>>
>> This mask makes 12 seem more likely.
>>
>> - Felix
>>
>
> Maybe it's in big endian format (we don't know anything about this reg
> anyway :P), both HALs have 13 plus it doesn't make sense to have a
> field split.
Ah, figured it out. It's a typo :)
Here are the settings from Sam's HAL:

#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13

Which does make a lot more sense than 0x01FF3000 :)

- Felix

2009-02-06 03:51:00

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Fri, Feb 06, 2009 at 01:28:07AM +0200, Nick Kossifidis wrote:
> > This works much better, except I still get some hard hangs
> > occasionally. Doesn't appear to be bmiss storm this time. I did it
> > with a VT up and didn't get an oops; I guess I'll try a serial console
> > or some printks.
>
> Did you disable BMISS interrupts on base.c ?

Nope this is just vanilla wireless testing + your patchset.

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-03 16:24:24

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Sat, 31 Jan 2009 04:31:47 +0200, Nick Kossifidis wrote
> int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
> struct ieee80211_channel *channel, bool change_channel)

Here's another thing I just noticed:

> {
> + u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;

s_seq is now an array (we used to initialize s_seq to 0)

[...]
> + if (change_channel) {
> + /*
> + * Save frame sequence count
> + * For revs. after Oahu, only save
> + * seq num for DCU 0 (Global seq num)
> + */
> + if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
> +
> + for (i = 0; i < 10; i++)
> + s_seq[i] = ath5k_hw_reg_read(ah,
> + AR5K_QUEUE_DCU_SEQNUM(i));
> +
> + } else {
> + s_seq[0] = ath5k_hw_reg_read(ah,
> + AR5K_QUEUE_DCU_SEQNUM(0));
> + }

We only save the DCU sequence values if changing a channel

[...]

> if (ah->ah_version != AR5K_AR5210) {
> - ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
> +
> + if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
> + for (i = 0; i < 10; i++)
> + ath5k_hw_reg_write(ah, s_seq[i],
> + AR5K_QUEUE_DCU_SEQNUM(i));
> + } else {
> + ath5k_hw_reg_write(ah, s_seq[0],
> + AR5K_QUEUE_DCU_SEQNUM(0));
> + }

But always write it. The old code did this too, the only difference
was we explicitly initialized the s_seq[0] to 0. Since it's an array,
gcc won't warn about it but s_seq[] probably has random crap in it.

--
Bob Copeland %% http://www.bobcopeland.com



2009-02-04 04:52:33

by Bob Copeland

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

On Tue, Feb 03, 2009 at 06:28:47PM +0200, Nick Kossifidis wrote:
> Nice catch ;-)
>
> Another difference i remembered is that we now don't set the TPC
> register to 3f (until we fix the whole tx power stuff). I'll try to
> reproduce this with my ar2425 as it turns it also has problems.

And the winning hunk is:

if (ah->ah_version != AR5K_AR5210) {
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
- /* If we later allow tuning for this, store into sc structure */
- data = AR5K_TUNE_RSSI_THRES |
- AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
- ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
}

(hmm, bmiss threshold, should've seen that before...)

With that reverted from the rest of the patchset, I no longer get the
interrupt storm. I do seem to get an occasional lockup at association
time, but I haven't caught an oops for that yet. It could be unrelated.

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-04 06:58:42

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/4 Nick Kossifidis <[email protected]>:
> 2009/2/4 Bob Copeland <[email protected]>:
>> On Tue, Feb 03, 2009 at 06:28:47PM +0200, Nick Kossifidis wrote:
>>> Nice catch ;-)
>>>
>>> Another difference i remembered is that we now don't set the TPC
>>> register to 3f (until we fix the whole tx power stuff). I'll try to
>>> reproduce this with my ar2425 as it turns it also has problems.
>>
>> And the winning hunk is:
>>
>> if (ah->ah_version != AR5K_AR5210) {
>> ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
>> - /* If we later allow tuning for this, store into sc structure */
>> - data = AR5K_TUNE_RSSI_THRES |
>> - AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
>> - ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
>> }
>>
>> (hmm, bmiss threshold, should've seen that before...)
>>
>> With that reverted from the rest of the patchset, I no longer get the
>> interrupt storm. I do seem to get an occasional lockup at association
>> time, but I haven't caught an oops for that yet. It could be unrelated.
>>
>
> O.K. i got that from legacy HAL. It first reads the register and if
> it's zeroed it sets to the default value of 0x781 (which is the same
> really, it's AR5K_TUNE_RSSI_THRES | AR5K_TUNE_BMISS_THRES <<
> AR5K_RSSI_THR_BMISS_S), if not it saves it and restores it after reset
> is done.
>
> So can you see why this
>
> /* Save RSSI thresholds (they 'll get zeroed from initvals) */
> rssi_thr = ath5k_hw_reg_read(ah, AR5K_RSSI_THR);
> /* If they are not set, set the default value */
> if (!rssi_thr)
> rssi_thr = AR5K_INIT_RSSI_THR;
>
> doesn't work ? What is the value of rssi_trh if not zero ?
>

Gotcha ;-)
rssi_thr: 0x40

I checked the docs and it seems this register is not changed by the
hw, so somewhere we write 0x40 on this register or something else
happens. I'll do some more research on that...


--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick

2009-02-07 05:04:16

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 5/5] ath5k: Update reset code

On Thu, Feb 05, 2009 at 11:06:59PM +0200, Nick Kossifidis wrote:
> I think this is because we call reset too many times. Try removing
> call to reset from config_interface, after some tests i did it seems
> wrong (we don't need to reset pcu and if we do, we don't need to reset
> the whole chip and re run phy initialization etc). I don't get any
> problems with ar2425 but i didn't get any before anyway (i never got a
> hang, just a few bmiss interrupts, not a storm).

Yep, with BMISS interrupts turned off and config_interface no longer
calling reset, it's quite stable now. Maybe there was some timing
thing at play. If we add a patch to remove those then I'm satisfied :)

--
Bob Copeland %% http://www.bobcopeland.com


2009-02-01 03:50:42

by Nick Kossifidis

[permalink] [raw]
Subject: Re: [ath5k-devel] [PATCH 5/5] ath5k: Update reset code

2009/2/1 Bob Copeland <[email protected]>:
> On Sat, Jan 31, 2009 at 08:48:02PM +0200, Nick Kossifidis wrote:
>> > Heh, we should write a little tool to check the shifts and masks :)
>> >
>>
>> Yup :P
>
> I just wrote one, I can post it later :) It also found:
>
> AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 13
>
> Should be 12 or a different mask...
>

13 is correct

0x01ff3000 -> 1111111111110000000000000

12 only counts the 3 zeros (3 * 4)

I've fixed all things mentioned so far, as soon as you find out why it
hangs on your pc we can move on ;-)

Again thanks a lot for the review ;-)

--
GPG ID: 0xD21DB2DB
As you read this post global entropy rises. Have Fun ;-)
Nick