#include <linux/pci.h> /* To determine if a card is pci-e */ #include <linux/log2.h> #include <linux/platform_device.h> #include"ath5k.h" #include"reg.h" #include"debug.h"
/* *Setcoreclockfrequency
*/ switch (channel->hw_value) { case AR5K_MODE_11A:
clock = 40; break; case AR5K_MODE_11B:
clock = 22; break; case AR5K_MODE_11G: default:
clock = 44; break;
}
/* Use clock multiplier for non-default
* bwmode */ switch (ah->ah_bwmode) { case AR5K_BWMODE_40MHZ:
clock *= 2; break; case AR5K_BWMODE_10MHZ:
clock /= 2; break; case AR5K_BWMODE_5MHZ:
clock /= 4; break; default: break;
}
common->clockrate = clock;
/* *SetUSECparameters
*/ /* Set USEC counter on PCU*/
usec = clock - 1;
usec = AR5K_REG_SM(usec, AR5K_USEC_1);
/* Set usec duration on DCU */ if (ah->ah_version != AR5K_AR5210)
AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
AR5K_DCU_GBL_IFS_MISC_USEC_DUR,
clock);
/* On 5112 set tx frame to tx data start delay */ if (ah->ah_radio == AR5K_RF5112) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
AR5K_PHY_RF_CTL2_TXF2TXD_START,
txf2txs);
}
}
/* 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);
/* ah->ah_mac_srev is not available at this point yet */ if (ah->devid >= AR5K_SREV_AR2315_R6) {
reg = (u32 __iomem *) AR5K_AR2315_RESET; if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR2315_RESET_WMAC; if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR2315_RESET_BB_WARM;
} else {
reg = (u32 __iomem *) AR5K_AR5312_RESET; if (to_platform_device(ah->dev)->id == 0) { if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR5312_RESET_WMAC0; if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR5312_RESET_BB0_COLD |
AR5K_AR5312_RESET_BB0_WARM;
} else { if (mask & AR5K_RESET_CTL_PCU)
val |= AR5K_AR5312_RESET_WMAC1; if (mask & AR5K_RESET_CTL_BASEBAND)
val |= AR5K_AR5312_RESET_BB1_COLD |
AR5K_AR5312_RESET_BB1_WARM;
}
}
/* Put BB/MAC into reset */
regval = ioread32(reg);
iowrite32(regval | val, reg);
regval = ioread32(reg);
udelay(100); /* NB: should be atomic */
/* Bring BB/MAC out of reset */
iowrite32(regval & ~val, reg);
regval = ioread32(reg);
switch (mode) { case AR5K_PM_AUTO:
staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
fallthrough; case AR5K_PM_NETWORK_SLEEP: if (set_chip)
ath5k_hw_reg_write(ah,
AR5K_SLEEP_CTL_SLE_ALLOW |
sleep_duration,
AR5K_SLEEP_CTL);
staid |= AR5K_STA_ID1_PWR_SV; break;
case AR5K_PM_FULL_SLEEP: if (set_chip)
ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
AR5K_SLEEP_CTL);
staid |= AR5K_STA_ID1_PWR_SV; break;
case AR5K_PM_AWAKE:
staid &= ~AR5K_STA_ID1_PWR_SV;
if (!set_chip) goto commit;
data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
/* If card is down we 'll get 0xffff... so we *needtocleanthisupbeforewewritetheregister
*/ if (data & 0xffc00000)
data = 0; else /* Preserve sleep duration etc */
data = data & ~AR5K_SLEEP_CTL_SLE;
ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
AR5K_SLEEP_CTL);
usleep_range(15, 20);
for (i = 200; i > 0; i--) { /* Check if the chip did wake up */ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
AR5K_PCICFG_SPWR_DN) == 0) break;
/* Wait a bit and retry */
usleep_range(50, 75);
ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
AR5K_SLEEP_CTL);
}
/* Fail if the chip didn't wake up */ if (i == 0) return -EIO;
/* Make sure device is awake */
ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); if (ret) {
ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret;
}
if (ret) {
ATH5K_ERR(ah, "failed to put device on warm reset\n"); return -EIO;
}
/* ...wakeup again!*/
ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); if (ret) {
ATH5K_ERR(ah, "failed to put device on hold\n"); return ret;
}
if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { /* Wakeup the device */
ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); if (ret) {
ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret;
}
}
if (ah->ah_version == AR5K_AR5210) {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
usleep_range(2000, 2500);
} else { if (ath5k_get_bus_type(ah) == ATH_AHB)
ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_BASEBAND); else
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_BASEBAND | bus_flags);
}
if (ret) {
ATH5K_ERR(ah, "failed to reset the MAC Chip\n"); return -EIO;
}
/* ...wakeup again!...*/
ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); if (ret) {
ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); return ret;
}
/* ...reset configuration register on Wisoc ... *...clearresetcontrolregisterandpulldeviceoutof
* warm reset on others */ if (ath5k_get_bus_type(ah) == ATH_AHB)
ret = ath5k_hw_wisoc_reset(ah, 0); else
ret = ath5k_hw_nic_reset(ah, 0);
if (ret) {
ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n"); return -EIO;
}
/* On initialization skip PLL programming since we don't have
* a channel / mode set yet */ if (!channel) return0;
if (ah->ah_version != AR5K_AR5210) { /* *Getchannelmodeflags
*/
/* 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->band == NL80211_BAND_5GHZ)
data = 0xffb81020; else
data = 0xffb80d20;
ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
}
if (ah->ah_bwmode) { /* Increase PHY switch and AGC settling time *onturbomode(ath5k_hw_commit_eeprom_settings
* will override settling time if available) */ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
/* XXX: Initvals indicate we only increase *switchtimeonAR5212,5211and5210
* only change agc time (bug?) */ if (ah->ah_version == AR5K_AR5212)
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
AR5K_PHY_SETTLING_SWITCH,
AR5K_SWITCH_SETTLING_TURBO);
if (ah->ah_version == AR5K_AR5210) { /* Set Frame Control Register */
ath5k_hw_reg_write(ah,
(AR5K_PHY_FRAME_CTL_INI |
AR5K_PHY_TURBO_MODE |
AR5K_PHY_TURBO_SHORT | 0x2020),
AR5K_PHY_FRAME_CTL_5210);
} /* On 5413 PHY force window length for half/quarter rate*/
} elseif ((ah->ah_mac_srev >= AR5K_SREV_AR5424) &&
(ah->ah_mac_srev <= AR5K_SREV_AR5414)) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211,
AR5K_PHY_FRAME_CTL_WIN_LEN, 3);
}
} elseif (ah->ah_version == AR5K_AR5210) { /* Set Frame Control Register for normal operation */
ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020),
AR5K_PHY_FRAME_CTL_5210);
}
}
/* 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;
/* Set CCK to OFDM power delta on tx power
* adjustment register */ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { if (channel->hw_value == AR5K_MODE_11G)
ath5k_hw_reg_write(ah,
AR5K_REG_SM((ee->ee_cck_ofdm_gain_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);
} else { /* For older revs we scale power on sw during tx power
* setup */
ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
ah->ah_txpower.txp_cck_ofdm_gainf_delta =
ee->ee_cck_ofdm_gain_delta;
}
/* XXX: necessary here? is called from ath5k_hw_set_antenna_mode()
* too */
ath5k_hw_set_antenna_switch(ah, ee_mode);
mode = channel->hw_value; switch (mode) { case AR5K_MODE_11A: break; case AR5K_MODE_11G: if (ah->ah_version <= AR5K_AR5211) {
ATH5K_ERR(ah, "G mode not available on 5210/5211"); return -EINVAL;
} break; case AR5K_MODE_11B: if (ah->ah_version < AR5K_AR5211) {
ATH5K_ERR(ah, "B mode not available on 5210"); return -EINVAL;
} break; default:
ATH5K_ERR(ah, "invalid channel: %d\n", channel->center_freq); return -EINVAL;
}
/* *IfdriverrequestedfastchannelchangeandDMAhasstopped *goon.Ifitfailscontinuewithanormalreset.
*/ if (fast) {
ret = ath5k_hw_phy_init(ah, channel, mode, true); if (ret) {
ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fast chan change failed, falling back to normal reset\n"); /* Non fatal, can happen eg.
* on mode change */
ret = 0;
} else {
ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fast chan change successful\n"); return0;
}
}
/* *Savesomeregistersbeforeareset
*/ if (ah->ah_version != AR5K_AR5210) { /* *Saveframesequencecount *Forrevs.afterOahu,onlysave *seqnumforDCU0(Globalseqnum)
*/ 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));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.