cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ar9002_hw.c (12856B)


      1/*
      2 * Copyright (c) 2008-2011 Atheros Communications Inc.
      3 *
      4 * Permission to use, copy, modify, and/or distribute this software for any
      5 * purpose with or without fee is hereby granted, provided that the above
      6 * copyright notice and this permission notice appear in all copies.
      7 *
      8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15 */
     16
     17#include <linux/moduleparam.h>
     18#include "hw.h"
     19#include "ar5008_initvals.h"
     20#include "ar9001_initvals.h"
     21#include "ar9002_initvals.h"
     22#include "ar9002_phy.h"
     23
     24/* General hardware code for the A5008/AR9001/AR9002 hadware families */
     25
     26static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
     27{
     28	if (AR_SREV_9271(ah)) {
     29		INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271);
     30		INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271);
     31		INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg);
     32		return 0;
     33	}
     34
     35	INIT_INI_ARRAY(&ah->iniPcieSerdes,
     36		       ar9280PciePhy_clkreq_always_on_L1_9280);
     37
     38	if (AR_SREV_9287_11_OR_LATER(ah)) {
     39		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
     40		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
     41	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
     42		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
     43		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
     44	} else if (AR_SREV_9280_20_OR_LATER(ah)) {
     45		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
     46		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
     47
     48		INIT_INI_ARRAY(&ah->iniModesFastClock,
     49			       ar9280Modes_fast_clock_9280_2);
     50	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
     51		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
     52		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
     53		if (AR_SREV_9160_11(ah)) {
     54			INIT_INI_ARRAY(&ah->iniAddac,
     55				       ar5416Addac_9160_1_1);
     56		} else {
     57			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
     58		}
     59	} else if (AR_SREV_9100_OR_LATER(ah)) {
     60		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
     61		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
     62		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
     63	} else {
     64		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
     65		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
     66		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
     67	}
     68
     69	if (!AR_SREV_9280_20_OR_LATER(ah)) {
     70		/* Common for AR5416, AR913x, AR9160 */
     71		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
     72
     73		/* Common for AR913x, AR9160 */
     74		if (!AR_SREV_5416(ah))
     75			INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
     76		else
     77			INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
     78	}
     79
     80	/* iniAddac needs to be modified for these chips */
     81	if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
     82		struct ar5416IniArray *addac = &ah->iniAddac;
     83		u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
     84		u32 *data;
     85
     86		data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
     87		if (!data)
     88			return -ENOMEM;
     89
     90		memcpy(data, addac->ia_array, size);
     91		addac->ia_array = data;
     92
     93		if (!AR_SREV_5416_22_OR_LATER(ah)) {
     94			/* override CLKDRV value */
     95			INI_RA(addac, 31,1) = 0;
     96		}
     97	}
     98	if (AR_SREV_9287_11_OR_LATER(ah)) {
     99		INIT_INI_ARRAY(&ah->iniCckfirNormal,
    100		       ar9287Common_normal_cck_fir_coeff_9287_1_1);
    101		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
    102		       ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
    103	}
    104	return 0;
    105}
    106
    107static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
    108{
    109	u32 rxgain_type;
    110
    111	if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) {
    112		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
    113
    114		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
    115			INIT_INI_ARRAY(&ah->iniModesRxGain,
    116				       ar9280Modes_backoff_13db_rxgain_9280_2);
    117		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
    118			INIT_INI_ARRAY(&ah->iniModesRxGain,
    119				       ar9280Modes_backoff_23db_rxgain_9280_2);
    120		else
    121			INIT_INI_ARRAY(&ah->iniModesRxGain,
    122				       ar9280Modes_original_rxgain_9280_2);
    123	} else {
    124		INIT_INI_ARRAY(&ah->iniModesRxGain,
    125			       ar9280Modes_original_rxgain_9280_2);
    126	}
    127}
    128
    129static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
    130{
    131	if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) {
    132		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
    133			INIT_INI_ARRAY(&ah->iniModesTxGain,
    134				       ar9280Modes_high_power_tx_gain_9280_2);
    135		else
    136			INIT_INI_ARRAY(&ah->iniModesTxGain,
    137				       ar9280Modes_original_tx_gain_9280_2);
    138	} else {
    139		INIT_INI_ARRAY(&ah->iniModesTxGain,
    140			       ar9280Modes_original_tx_gain_9280_2);
    141	}
    142}
    143
    144static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
    145{
    146	if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
    147		INIT_INI_ARRAY(&ah->iniModesTxGain,
    148			       ar9271Modes_high_power_tx_gain_9271);
    149	else
    150		INIT_INI_ARRAY(&ah->iniModesTxGain,
    151			       ar9271Modes_normal_power_tx_gain_9271);
    152}
    153
    154static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
    155{
    156	u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
    157
    158	if (AR_SREV_9287_11_OR_LATER(ah))
    159		INIT_INI_ARRAY(&ah->iniModesRxGain,
    160			       ar9287Modes_rx_gain_9287_1_1);
    161	else if (AR_SREV_9280_20(ah))
    162		ar9280_20_hw_init_rxgain_ini(ah);
    163
    164	if (AR_SREV_9271(ah)) {
    165		ar9271_hw_init_txgain_ini(ah, txgain_type);
    166	} else if (AR_SREV_9287_11_OR_LATER(ah)) {
    167		INIT_INI_ARRAY(&ah->iniModesTxGain,
    168			       ar9287Modes_tx_gain_9287_1_1);
    169	} else if (AR_SREV_9280_20(ah)) {
    170		ar9280_20_hw_init_txgain_ini(ah, txgain_type);
    171	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
    172		/* txgain table */
    173		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
    174			if (AR_SREV_9285E_20(ah)) {
    175				INIT_INI_ARRAY(&ah->iniModesTxGain,
    176					       ar9285Modes_XE2_0_high_power);
    177			} else {
    178				INIT_INI_ARRAY(&ah->iniModesTxGain,
    179					ar9285Modes_high_power_tx_gain_9285_1_2);
    180			}
    181		} else {
    182			if (AR_SREV_9285E_20(ah)) {
    183				INIT_INI_ARRAY(&ah->iniModesTxGain,
    184					       ar9285Modes_XE2_0_normal_power);
    185			} else {
    186				INIT_INI_ARRAY(&ah->iniModesTxGain,
    187					ar9285Modes_original_tx_gain_9285_1_2);
    188			}
    189		}
    190	}
    191}
    192
    193/*
    194 * Helper for ASPM support.
    195 *
    196 * Disable PLL when in L0s as well as receiver clock when in L1.
    197 * This power saving option must be enabled through the SerDes.
    198 *
    199 * Programming the SerDes must go through the same 288 bit serial shift
    200 * register as the other analog registers.  Hence the 9 writes.
    201 */
    202static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
    203					 bool power_off)
    204{
    205	u8 i;
    206	u32 val;
    207
    208	/* Nothing to do on restore for 11N */
    209	if (!power_off /* !restore */) {
    210		if (AR_SREV_9280_20_OR_LATER(ah)) {
    211			/*
    212			 * AR9280 2.0 or later chips use SerDes values from the
    213			 * initvals.h initialized depending on chipset during
    214			 * __ath9k_hw_init()
    215			 */
    216			for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
    217				REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
    218					  INI_RA(&ah->iniPcieSerdes, i, 1));
    219			}
    220		} else {
    221			ENABLE_REGWRITE_BUFFER(ah);
    222
    223			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
    224			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
    225
    226			/* RX shut off when elecidle is asserted */
    227			REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
    228			REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
    229			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
    230
    231			/*
    232			 * Ignore ah->ah_config.pcie_clock_req setting for
    233			 * pre-AR9280 11n
    234			 */
    235			REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
    236
    237			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
    238			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
    239			REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
    240
    241			/* Load the new settings */
    242			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
    243
    244			REGWRITE_BUFFER_FLUSH(ah);
    245		}
    246
    247		udelay(1000);
    248	}
    249
    250	if (power_off) {
    251		/* clear bit 19 to disable L1 */
    252		REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
    253
    254		val = REG_READ(ah, AR_WA);
    255
    256		/*
    257		 * Set PCIe workaround bits
    258		 * In AR9280 and AR9285, bit 14 in WA register (disable L1)
    259		 * should only  be set when device enters D3 and be
    260		 * cleared when device comes back to D0.
    261		 */
    262		if (ah->config.pcie_waen) {
    263			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
    264				val |= AR_WA_D3_L1_DISABLE;
    265		} else {
    266			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
    267				if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
    268					val |= AR_WA_D3_L1_DISABLE;
    269			} else if (AR_SREV_9280(ah)) {
    270				if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
    271					val |= AR_WA_D3_L1_DISABLE;
    272			}
    273		}
    274
    275		if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
    276			/*
    277			 * Disable bit 6 and 7 before entering D3 to
    278			 * prevent system hang.
    279			 */
    280			val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
    281		}
    282
    283		if (AR_SREV_9280(ah))
    284			val |= AR_WA_BIT22;
    285
    286		if (AR_SREV_9285E_20(ah))
    287			val |= AR_WA_BIT23;
    288
    289		REG_WRITE(ah, AR_WA, val);
    290	} else {
    291		if (ah->config.pcie_waen) {
    292			val = ah->config.pcie_waen;
    293			val &= (~AR_WA_D3_L1_DISABLE);
    294		} else {
    295			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
    296				val = AR9285_WA_DEFAULT;
    297				val &= (~AR_WA_D3_L1_DISABLE);
    298			} else if (AR_SREV_9280(ah)) {
    299				/*
    300				 * For AR9280 chips, bit 22 of 0x4004
    301				 * needs to be set.
    302				 */
    303				val = AR9280_WA_DEFAULT;
    304				val &= (~AR_WA_D3_L1_DISABLE);
    305			} else {
    306				val = AR_WA_DEFAULT;
    307			}
    308		}
    309
    310		/* WAR for ASPM system hang */
    311		if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
    312			val |= (AR_WA_BIT6 | AR_WA_BIT7);
    313
    314		if (AR_SREV_9285E_20(ah))
    315			val |= AR_WA_BIT23;
    316
    317		REG_WRITE(ah, AR_WA, val);
    318
    319		/* set bit 19 to allow forcing of pcie core into L1 state */
    320		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
    321	}
    322}
    323
    324static int ar9002_hw_get_radiorev(struct ath_hw *ah)
    325{
    326	u32 val;
    327	int i;
    328
    329	ENABLE_REGWRITE_BUFFER(ah);
    330
    331	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
    332	for (i = 0; i < 8; i++)
    333		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
    334
    335	REGWRITE_BUFFER_FLUSH(ah);
    336
    337	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
    338	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
    339
    340	return ath9k_hw_reverse_bits(val, 8);
    341}
    342
    343int ar9002_hw_rf_claim(struct ath_hw *ah)
    344{
    345	u32 val;
    346
    347	REG_WRITE(ah, AR_PHY(0), 0x00000007);
    348
    349	val = ar9002_hw_get_radiorev(ah);
    350	switch (val & AR_RADIO_SREV_MAJOR) {
    351	case 0:
    352		val = AR_RAD5133_SREV_MAJOR;
    353		break;
    354	case AR_RAD5133_SREV_MAJOR:
    355	case AR_RAD5122_SREV_MAJOR:
    356	case AR_RAD2133_SREV_MAJOR:
    357	case AR_RAD2122_SREV_MAJOR:
    358		break;
    359	default:
    360		ath_err(ath9k_hw_common(ah),
    361			"Radio Chip Rev 0x%02X not supported\n",
    362			val & AR_RADIO_SREV_MAJOR);
    363		return -EOPNOTSUPP;
    364	}
    365
    366	ah->hw_version.analog5GhzRev = val;
    367
    368	return 0;
    369}
    370
    371void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
    372{
    373	if (AR_SREV_9287_13_OR_LATER(ah)) {
    374		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
    375				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
    376		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
    377		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
    378				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
    379		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
    380				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
    381	}
    382}
    383
    384static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
    385{
    386	if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
    387		ah->config.hw_hang_checks |= HW_BB_RIFS_HANG;
    388		ah->config.hw_hang_checks |= HW_BB_DFS_HANG;
    389	}
    390
    391	if (AR_SREV_9280(ah))
    392		ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG;
    393
    394	if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah))
    395		ah->config.hw_hang_checks |= HW_MAC_HANG;
    396}
    397
    398/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
    399int ar9002_hw_attach_ops(struct ath_hw *ah)
    400{
    401	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
    402	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
    403	int ret;
    404
    405	ret = ar9002_hw_init_mode_regs(ah);
    406	if (ret)
    407		return ret;
    408
    409	priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
    410	priv_ops->init_hang_checks = ar9002_hw_init_hang_checks;
    411
    412	ops->config_pci_powersave = ar9002_hw_configpcipowersave;
    413
    414	ret = ar5008_hw_attach_phy_ops(ah);
    415	if (ret)
    416		return ret;
    417
    418	if (AR_SREV_9280_20_OR_LATER(ah))
    419		ar9002_hw_attach_phy_ops(ah);
    420
    421	ar9002_hw_attach_calib_ops(ah);
    422	ar9002_hw_attach_mac_ops(ah);
    423	return 0;
    424}
    425
    426void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
    427{
    428	u32 modesIndex;
    429	int i;
    430
    431	if (IS_CHAN_5GHZ(chan))
    432		modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
    433	else
    434		modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
    435
    436	ENABLE_REGWRITE_BUFFER(ah);
    437
    438	for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
    439		u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
    440		u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
    441		u32 val_orig;
    442
    443		if (reg == AR_PHY_CCK_DETECT) {
    444			val_orig = REG_READ(ah, reg);
    445			val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
    446			val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
    447
    448			REG_WRITE(ah, reg, val|val_orig);
    449		} else
    450			REG_WRITE(ah, reg, val);
    451	}
    452
    453	REGWRITE_BUFFER_FLUSH(ah);
    454}