Commit e8f055f0 authored by Nick Kossifidis's avatar Nick Kossifidis Committed by John W. Linville

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: default avatarNick Kossifidis <mickflemm@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a406c139
...@@ -222,6 +222,7 @@ ...@@ -222,6 +222,7 @@
#endif #endif
/* Initial values */ /* Initial values */
#define AR5K_INIT_CYCRSSI_THR1 2
#define AR5K_INIT_TX_LATENCY 502 #define AR5K_INIT_TX_LATENCY 502
#define AR5K_INIT_USEC 39 #define AR5K_INIT_USEC 39
#define AR5K_INIT_USEC_TURBO 79 #define AR5K_INIT_USEC_TURBO 79
...@@ -313,7 +314,7 @@ struct ath5k_srev_name { ...@@ -313,7 +314,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_AR5424 0x90 /* Condor */ #define AR5K_SREV_AR5424 0x90 /* Condor */
#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
#define AR5K_SREV_AR5414 0xa0 /* Eagle */ #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_AR5416 0xc0 /* PCI-E */
#define AR5K_SREV_AR5418 0xca /* PCI-E */ #define AR5K_SREV_AR5418 0xca /* PCI-E */
#define AR5K_SREV_AR2425 0xe0 /* Swan */ #define AR5K_SREV_AR2425 0xe0 /* Swan */
...@@ -331,7 +332,7 @@ struct ath5k_srev_name { ...@@ -331,7 +332,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_2112B 0x46 #define AR5K_SREV_RAD_2112B 0x46
#define AR5K_SREV_RAD_2413 0x50 #define AR5K_SREV_RAD_2413 0x50
#define AR5K_SREV_RAD_5413 0x60 #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_2317 0x80
#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */ #define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
#define AR5K_SREV_RAD_2425 0xa2 #define AR5K_SREV_RAD_2425 0xa2
...@@ -340,7 +341,7 @@ struct ath5k_srev_name { ...@@ -340,7 +341,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_PHY_5211 0x30 #define AR5K_SREV_PHY_5211 0x30
#define AR5K_SREV_PHY_5212 0x41 #define AR5K_SREV_PHY_5212 0x41
#define AR5K_SREV_PHY_5212A 0x42 #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_2413 0x45
#define AR5K_SREV_PHY_5413 0x61 #define AR5K_SREV_PHY_5413 0x61
#define AR5K_SREV_PHY_2425 0x70 #define AR5K_SREV_PHY_2425 0x70
...@@ -1030,7 +1031,6 @@ struct ath5k_hw { ...@@ -1030,7 +1031,6 @@ struct ath5k_hw {
u16 ah_phy_revision; u16 ah_phy_revision;
u16 ah_radio_5ghz_revision; u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision; u16 ah_radio_2ghz_revision;
u32 ah_phy_spending;
enum ath5k_version ah_version; enum ath5k_version ah_version;
enum ath5k_radio ah_radio; enum ath5k_radio ah_radio;
...@@ -1156,6 +1156,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l ...@@ -1156,6 +1156,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l
/* EEPROM access functions */ /* EEPROM access functions */
extern int ath5k_eeprom_init(struct ath5k_hw *ah); extern int ath5k_eeprom_init(struct ath5k_hw *ah);
extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); 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 */ /* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); 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); ...@@ -1258,6 +1259,7 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
/* /*
* Translate usec to hw clock units * Translate usec to hw clock units
* TODO: Half/quarter rate
*/ */
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) 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) ...@@ -1266,6 +1268,7 @@ static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
/* /*
* Translate hw clock units to usec * Translate hw clock units to usec
* TODO: Half/quarter rate
*/ */
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{ {
......
...@@ -169,7 +169,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -169,7 +169,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false; ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ); CHANNEL_2GHZ);
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
break; break;
case AR5K_SREV_RAD_5112: case AR5K_SREV_RAD_5112:
case AR5K_SREV_RAD_2112: case AR5K_SREV_RAD_2112:
...@@ -177,38 +176,31 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -177,38 +176,31 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_single_chip = false; ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
CHANNEL_2GHZ); CHANNEL_2GHZ);
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
break; break;
case AR5K_SREV_RAD_2413: case AR5K_SREV_RAD_2413:
ah->ah_radio = AR5K_RF2413; ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
break; break;
case AR5K_SREV_RAD_5413: case AR5K_SREV_RAD_5413:
ah->ah_radio = AR5K_RF5413; ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
break; break;
case AR5K_SREV_RAD_2316: case AR5K_SREV_RAD_2316:
ah->ah_radio = AR5K_RF2316; ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316;
break; break;
case AR5K_SREV_RAD_2317: case AR5K_SREV_RAD_2317:
ah->ah_radio = AR5K_RF2317; ah->ah_radio = AR5K_RF2317;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2317;
break; break;
case AR5K_SREV_RAD_5424: case AR5K_SREV_RAD_5424:
if (ah->ah_mac_version == AR5K_SREV_AR2425 || if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
ah->ah_mac_version == AR5K_SREV_AR2417){ ah->ah_mac_version == AR5K_SREV_AR2417){
ah->ah_radio = AR5K_RF2425; ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else { } else {
ah->ah_radio = AR5K_RF5413; ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
} }
break; break;
default: default:
...@@ -227,29 +219,25 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -227,29 +219,25 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_radio = AR5K_RF2425; ah->ah_radio = AR5K_RF2425;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
} else if (srev == AR5K_SREV_AR5213A && } 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_radio = AR5K_RF5112;
ah->ah_single_chip = false; 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)) { } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
ah->ah_radio = AR5K_RF2316; ah->ah_radio = AR5K_RF2316;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; 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) || } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_5413) { ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
ah->ah_radio = AR5K_RF5413; ah->ah_radio = AR5K_RF5413;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; 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) || } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_2413) { ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
ah->ah_radio = AR5K_RF2413; ah->ah_radio = AR5K_RF2413;
ah->ah_single_chip = true; ah->ah_single_chip = true;
ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
} else { } else {
ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
ret = -ENODEV; ret = -ENODEV;
......
...@@ -204,7 +204,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, ...@@ -204,7 +204,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
/* Get antenna modes */ /* Get antenna modes */
ah->ah_antenna[mode][0] = 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] = ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
ee->ee_ant_control[mode][1] | ee->ee_ant_control[mode][1] |
(ee->ee_ant_control[mode][2] << 6) | (ee->ee_ant_control[mode][2] << 6) |
...@@ -1412,6 +1412,7 @@ ath5k_eeprom_init(struct ath5k_hw *ah) ...@@ -1412,6 +1412,7 @@ ath5k_eeprom_init(struct ath5k_hw *ah)
return 0; return 0;
} }
/* /*
* Read the MAC address from eeprom * Read the MAC address from eeprom
*/ */
...@@ -1448,3 +1449,14 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) ...@@ -1448,3 +1449,14 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
return 0; 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;
}
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ #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_REG_DOMAIN 0x00bf /* EEPROM regdom */
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
......
...@@ -187,6 +187,7 @@ ...@@ -187,6 +187,7 @@
#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ #define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [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_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 */ #define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */
/* /*
...@@ -753,7 +754,7 @@ ...@@ -753,7 +754,7 @@
*/ */
#define AR5K_DCU_SEQNUM_BASE 0x1140 #define AR5K_DCU_SEQNUM_BASE 0x1140
#define AR5K_DCU_SEQNUM_M 0x00000fff #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 * DCU global IFS SIFS register
...@@ -1467,7 +1468,7 @@ ...@@ -1467,7 +1468,7 @@
#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */ #define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */
#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */ #define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */
#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin 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+] * Default antenna register [5211+]
...@@ -1679,7 +1680,7 @@ ...@@ -1679,7 +1680,7 @@
* TSF parameter register * TSF parameter register
*/ */
#define AR5K_TSF_PARM 0x8104 /* Register Address */ #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 #define AR5K_TSF_PARM_INC_S 0
/* /*
...@@ -1691,7 +1692,7 @@ ...@@ -1691,7 +1692,7 @@
#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */ #define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
#define AR5K_QOS_NOACK_BIT_OFFSET_S 4 #define AR5K_QOS_NOACK_BIT_OFFSET_S 4
#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */ #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 * PHY error filter register
...@@ -1850,15 +1851,14 @@ ...@@ -1850,15 +1851,14 @@
* TST_2 (Misc config parameters) * TST_2 (Misc config parameters)
*/ */
#define AR5K_PHY_TST2 0x9800 /* Register Address */ #define AR5K_PHY_TST2 0x9800 /* Register Address */
#define AR5K_PHY_TST2_TRIG_SEL 0x00000001 /* Trigger select (?) (field ?) */ #define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) (field ?) */ #define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
#define AR5K_PHY_TST2_CBUS_MODE 0x00000100 /* Cardbus mode (?) */ #define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
/* bit reserved */
#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */ #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_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even 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_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_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_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */
#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */ #define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */
...@@ -1928,8 +1928,8 @@ ...@@ -1928,8 +1928,8 @@
#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0 #define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0
#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ #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 0x0000ff00 /* TX end to XLNA on */
#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 0 #define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8
#define AR5K_PHY_ADC_CTL 0x982c #define AR5K_PHY_ADC_CTL 0x982c
#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003 #define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
...@@ -1963,7 +1963,7 @@ ...@@ -1963,7 +1963,7 @@
#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
#define AR5K_PHY_SETTLING_AGC_S 0 #define AR5K_PHY_SETTLING_AGC_S 0
#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ #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 * PHY Gain registers
...@@ -2069,14 +2069,14 @@ ...@@ -2069,14 +2069,14 @@
* PHY sleep registers [5112+] * PHY sleep registers [5112+]
*/ */
#define AR5K_PHY_SCR 0x9870 #define AR5K_PHY_SCR 0x9870
#define AR5K_PHY_SCR_32MHZ 0x0000001f
#define AR5K_PHY_SLMT 0x9874 #define AR5K_PHY_SLMT 0x9874
#define AR5K_PHY_SLMT_32MHZ 0x0000007f #define AR5K_PHY_SLMT_32MHZ 0x0000007f
#define AR5K_PHY_SCAL 0x9878 #define AR5K_PHY_SCAL 0x9878
#define AR5K_PHY_SCAL_32MHZ 0x0000000e #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 * PHY PLL (Phase Locked Loop) control register
...@@ -2156,7 +2156,8 @@ ...@@ -2156,7 +2156,8 @@
#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */ #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_SECTORED_ANT 0x00000004 /* Sectored Antenna */
#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */ #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+] * PHY receiver delay register [5111+]
...@@ -2196,7 +2197,7 @@ ...@@ -2196,7 +2197,7 @@
#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ #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_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 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_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_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ #define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
...@@ -2278,6 +2279,15 @@ ...@@ -2278,6 +2279,15 @@
AR5K_PHY_FRAME_CTL_PARITY_ERR | \ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
AR5K_PHY_FRAME_CTL_TIMING_ERR 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+] * PHY radar detection register [5111+]
*/ */
...@@ -2331,7 +2341,7 @@ ...@@ -2331,7 +2341,7 @@
#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3 #define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00 #define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8 #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 #define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13
/* /*
...@@ -2459,17 +2469,7 @@ ...@@ -2459,17 +2469,7 @@
#define AR5K_PHY_SDELAY 0x99f4 #define AR5K_PHY_SDELAY 0x99f4
#define AR5K_PHY_SDELAY_32MHZ 0x000000ff #define AR5K_PHY_SDELAY_32MHZ 0x000000ff
#define AR5K_PHY_SPENDING 0x99f8 #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 (?) * PHY PAPD I (power?) table (?)
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
Reset functions and helpers 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 "ath5k.h"
#include "reg.h" #include "reg.h"
#include "base.h" #include "base.h"
...@@ -37,10 +38,14 @@ ...@@ -37,10 +38,14 @@
* @ah: the &struct ath5k_hw * @ah: the &struct ath5k_hw
* @channel: the currently set channel upon reset * @channel: the currently set channel upon reset
* *
* Write the OFDM timings for the AR5212 upon reset. This is a helper for * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
* ath5k_hw_reset(). This seems to tune the PLL a specified frequency * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
* depending on the bandwidth of the channel.
* *
* 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, static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
...@@ -53,23 +58,34 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, ...@@ -53,23 +58,34 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM)) !(channel->hw_value & CHANNEL_OFDM))
BUG(); BUG();
/* Seems there are two PLLs, one for baseband sampling and one /* Get coefficient
* for tuning. Tuning basebands are 40 MHz or 80MHz when in * ALGO: coef = (5 * clock * carrier_freq) / 2)
* turbo. */ * we scale coef by shifting clock value by 24 for
clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40; * better precision since we use integers */
coef_scaled = ((5 * (clock << 24)) / 2) / /* TODO: Half/quarter rate */
channel->center_freq; clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
for (coef_exp = 31; coef_exp > 0; coef_exp--) coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
if ((coef_scaled >> coef_exp) & 0x1)
break; /* 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) if (!coef_exp)
return -EINVAL; return -EINVAL;
/* Note: we've shifted coef_scaled by 24 */
coef_exp = 14 - (coef_exp - 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 + coef_man = coef_scaled +
(1 << (24 - coef_exp - 1)); (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_man = coef_man >> (24 - coef_exp);
ds_coef_exp = coef_exp - 16; ds_coef_exp = coef_exp - 16;
...@@ -90,16 +106,23 @@ static int control_rates[] = ...@@ -90,16 +106,23 @@ static int control_rates[] =
{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; { 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 * @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode * @mode: one of enum ath5k_driver_mode
* *
* Write the rate duration table upon hw reset. This is a helper for * 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 for * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
* the hardware for the current mode for each rate. The rates which are capable * the hardware, based on current mode, for each rate. The rates which are
* of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have another * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
* register for the short preamble ACK timeout calculation. * 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, static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int mode) unsigned int mode)
...@@ -275,7 +298,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, ...@@ -275,7 +298,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
} }
/* /*
* 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) int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{ {
...@@ -333,6 +357,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ...@@ -333,6 +357,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
} }
} else if (flags & CHANNEL_5GHZ) { } else if (flags & CHANNEL_5GHZ) {
mode |= AR5K_PHY_MODE_FREQ_5GHZ; mode |= AR5K_PHY_MODE_FREQ_5GHZ;
if (ah->ah_radio == AR5K_RF5413)
clock |= AR5K_PHY_PLL_40MHZ_5413;
else
clock |= AR5K_PHY_PLL_40MHZ; clock |= AR5K_PHY_PLL_40MHZ;
if (flags & CHANNEL_OFDM) if (flags & CHANNEL_OFDM)
...@@ -391,10 +419,14 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ...@@ -391,10 +419,14 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
} }
if (ah->ah_version != AR5K_AR5210) { if (ah->ah_version != AR5K_AR5210) {
/* ...set the PHY operating mode */
/* ...update PLL if needed */
if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
udelay(300); udelay(300);
}
/* ...set the PHY operating mode */
ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
} }
...@@ -402,23 +434,394 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ...@@ -402,23 +434,394 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return 0; return 0;
} }
/*
* 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 * Main reset function
*/ */
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool change_channel) struct ieee80211_channel *channel, bool change_channel)
{ {
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
struct pci_dev *pdev = ah->ah_sc->pdev; u32 phy_tst1;
u32 data, s_seq, s_ant, s_led[3], dma_size; u8 mode, freq, ee_mode, ant[2];
unsigned int i, mode, freq, ee_mode, ant[2]; int i, ret;
int ret;
ATH5K_TRACE(ah->ah_sc); ATH5K_TRACE(ah->ah_sc);
s_seq = 0;
s_ant = 0; s_ant = 0;
ee_mode = 0; ee_mode = 0;
staid1_flags = 0;
tsf_up = 0;
tsf_lo = 0;
freq = 0; freq = 0;
mode = 0; mode = 0;
...@@ -426,36 +829,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -426,36 +829,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* Save some registers before a reset * Save some registers before a reset
*/ */
/*DCU/Antenna selection not available on 5210*/ /*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) { if (ah->ah_version != AR5K_AR5210) {
switch (channel->hw_value & CHANNEL_MODES) { switch (channel->hw_value & CHANNEL_MODES) {
...@@ -479,8 +852,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -479,8 +852,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
freq = AR5K_INI_RFGAIN_5GHZ; freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A; ee_mode = AR5K_EEPROM_MODE_11A;
break; break;
/*Is this ok on 5211 too ?*/
case CHANNEL_TG: 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; mode = AR5K_MODE_11G_TURBO;
freq = AR5K_INI_RFGAIN_2GHZ; freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G; ee_mode = AR5K_EEPROM_MODE_11G;
...@@ -501,11 +878,93 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -501,11 +878,93 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
return -EINVAL; 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 */ /* PHY access enable */
if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); 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); ret = ath5k_hw_write_initvals(ah, mode, change_channel);
if (ret) if (ret)
return ret; return ret;
...@@ -514,6 +973,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -514,6 +973,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* 5211/5212 Specific * 5211/5212 Specific
*/ */
if (ah->ah_version != AR5K_AR5210) { if (ah->ah_version != AR5K_AR5210) {
/* /*
* Write initial RF gain settings * Write initial RF gain settings
* This should work for both 5111/5112 * This should work for both 5111/5112
...@@ -525,53 +985,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -525,53 +985,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
mdelay(1); 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 && ath5k_hw_tweak_initval_settings(ah, channel);
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;
}
/* /*
* Set TX power (FIXME) * Set TX power (FIXME)
...@@ -589,15 +1007,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -589,15 +1007,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_write_rate_duration(ah, mode); ath5k_hw_write_rate_duration(ah, mode);
/* /*
* Write RF registers * Write RF buffer
*/ */
ret = ath5k_hw_rfregs_init(ah, channel, mode); ret = ath5k_hw_rfregs_init(ah, channel, mode);
if (ret) if (ret)
return ret; return ret;
/*
* Configure additional registers
*/
/* Write OFDM timings on 5212*/ /* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 && if (ah->ah_version == AR5K_AR5212 &&
...@@ -618,17 +1033,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -618,17 +1033,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_TXCFG_B_MODE); AR5K_TXCFG_B_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 * In case a fixed antenna was set as default
* write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
...@@ -644,54 +1048,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -644,54 +1048,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ant[1] = AR5K_ANT_FIXED_B; 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 */ /* Commit values from EEPROM */
if (ah->ah_radio == AR5K_RF5111) ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
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]);
} else { } 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); mdelay(1);
/* Disable phy and wait */ /* Disable phy and wait */
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); 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, ...@@ -701,100 +1067,154 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* /*
* Restore saved values * Restore saved values
*/ */
/*DCU/Antenna selection not available on 5210*/ /*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) { 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); ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
} }
/* Ledstate */
AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); 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[1], AR5K_GPIOCR);
ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); 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 */ /* XXX: add ah->aid once mac80211 gives this to us */
ath5k_hw_set_associd(ah, ah->ah_bssid, 0); ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
/* Set PCU config */
ath5k_hw_set_opmode(ah); 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); ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
/* If we later allow tuning for this, store into sc structure */
data = AR5K_TUNE_RSSI_THRES | /* Set RSSI/BRSSI thresholds
AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S; *
ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR); * 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 * Configure PHY
*
* 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 ;-)
*/ */
dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
if (ah->ah_version != AR5K_AR5210) { /* Set channel on PHY */
AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, ret = ath5k_hw_channel(ah, channel);
AR5K_TXCFG_SDMAMR, dma_size); if (ret)
AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, return ret;
AR5K_RXCFG_SDMAMW, dma_size);
}
/* /*
* Enable the PHY and wait until completion * 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); ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
/* /*
* On 5211+ read activation -> rx delay * On 5211+ read activation -> rx delay
* and use it. * and use it.
*
* TODO: Half/quarter rate support
*/ */
if (ah->ah_version != AR5K_AR5210) { 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; AR5K_PHY_RX_DELAY_M;
data = (channel->hw_value & CHANNEL_CCK) ? delay = (channel->hw_value & CHANNEL_CCK) ?
((data << 2) / 22) : (data / 10); ((delay << 2) / 22) : (delay / 10);
udelay(100 + (2 * data)); udelay(100 + (2 * delay));
data = 0;
} else { } else {
mdelay(1); 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); ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
for (i = 0; i <= 20; i++) { for (i = 0; i <= 20; i++) {
if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
break; break;
udelay(200); udelay(200);
} }
ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1); ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
data = 0;
/* /*
* Start automatic gain calibration * Start automatic gain control calibration
* *
* During AGC calibration RX path is re-routed to * 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 * This method is used to calibrate some static offsets
* used together with on-the fly I/Q calibration (the * used together with on-the fly I/Q calibration (the
* one performed via ath5k_hw_phy_calibrate), that doesn't * one performed via ath5k_hw_phy_calibrate), that doesn't
* interrupt rx path. * 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 * 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_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL); AR5K_PHY_AGCCTL_CAL);
...@@ -816,30 +1236,37 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -816,30 +1236,37 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_PHY_AGCCTL_CAL, 0, false)) { AR5K_PHY_AGCCTL_CAL, 0, false)) {
ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
channel->center_freq); channel->center_freq);
return -EAGAIN;
} }
/* /*
* Start noise floor calibration
*
* If we run NF calibration before AGC, it always times out. * If we run NF calibration before AGC, it always times out.
* Binary HAL starts NF and AGC calibration at the same time * Binary HAL starts NF and AGC calibration at the same time
* and only waits for AGC to finish. I believe that's wrong because * and only waits for AGC to finish. Also if AGC or NF cal.
* during NF calibration, rx path is also routed to a detector, so if * times out, reset doesn't fail on binary HAL. I believe
* it doesn't finish we won't have RX. * 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
* XXX: Find an interval that's OK for all cards... * 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); 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 * 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++) { 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); ret = ath5k_hw_reset_tx_queue(ah, i);
if (ret) { if (ret) {
ATH5K_ERR(ah->ah_sc, ATH5K_ERR(ah->ah_sc,
...@@ -848,14 +1275,40 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ...@@ -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*/ /* Pre-enable interrupts on 5211/5212*/
if (ah->ah_version != AR5K_AR5210) if (ah->ah_version != AR5K_AR5210)
ath5k_hw_set_imr(ah, ah->ah_imr); ath5k_hw_set_imr(ah, ah->ah_imr);
/* /*
* Set RF kill flags if supported by the device (read from the EEPROM) * Setup RFKill interrupt if rfkill flag is set on eeprom.
* Disable gpio_intr for now since it results system hang. * TODO: Use gpio pin and polarity infos from eeprom
* TODO: Handle this in ath5k_intr * TODO: Handle this in ath5k_intr because it'll result
* a nasty interrupt storm.
*/ */
#if 0 #if 0
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { 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, ...@@ -868,33 +1321,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
} }
#endif #endif
/* /* Enable 32KHz clock function for AR5212+ chips
* Set the 32MHz reference clock on 5212 phy clock sleep register * Set clocks to 32KHz operation and use an
* * external 32KHz crystal when sleeping if one
* TODO: Find out how to switch to external 32Khz clock to save power * exists */
*/ if (ah->ah_version == AR5K_AR5212)
if (ah->ah_version == AR5K_AR5212) { ath5k_hw_set_sleep_clock(ah, true);
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);
}
/* /*
* Disable beacons and reset the register * Disable beacons and reset the register
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment