Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h (revision 278741) @@ -1,1690 +1,1713 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _ATH_AR9300_H_ #define _ATH_AR9300_H_ #include "ar9300_freebsd_inc.h" #define AH_BIG_ENDIAN 4321 #define AH_LITTLE_ENDIAN 1234 #if _BYTE_ORDER == _BIG_ENDIAN #define AH_BYTE_ORDER AH_BIG_ENDIAN #else #define AH_BYTE_ORDER AH_LITTLE_ENDIAN #endif /* XXX doesn't belong here */ #define AR_EEPROM_MODAL_SPURS 5 /* * (a) this should be N(a), * (b) FreeBSD does define nitems, * (c) it doesn't have an AH_ prefix, sigh. */ #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) #include "ah_internal.h" #include "ah_eeprom.h" #include "ah_devid.h" #include "ar9300eep.h" /* For Eeprom definitions */ #define AR9300_MAGIC 0x19741014 /* MAC register values */ #define INIT_CONFIG_STATUS 0x00000000 #define INIT_RSSI_THR 0x7 /* Missed beacon counter initialized to 0x7 (max is 0xff) */ #define INIT_RSSI_BEACON_WEIGHT 8 /* ave beacon rssi weight (0-16) */ /* * Various fifo fill before Tx start, in 64-byte units * i.e. put the frame in the air while still DMAing */ #define MIN_TX_FIFO_THRESHOLD 0x1 #define MAX_TX_FIFO_THRESHOLD (( 4096 / 64) - 1) #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD #define CHANSEL_DIV 15 #define FCLK 40 #define COEFF ((FCLK * 5) / 2) #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) #define CHANSEL_5G_DOT5MHZ 2188 /* * Receive Queue Fifo depth. */ enum RX_FIFO_DEPTH { HAL_HP_RXFIFO_DEPTH = 16, HAL_LP_RXFIFO_DEPTH = 128, }; /* * Gain support. */ #define NUM_CORNER_FIX_BITS_2133 7 #define CCK_OFDM_GAIN_DELTA 15 enum GAIN_PARAMS { GP_TXCLIP, GP_PD90, GP_PD84, GP_GSEL }; enum GAIN_PARAMS_2133 { GP_MIXGAIN_OVR, GP_PWD_138, GP_PWD_137, GP_PWD_136, GP_PWD_132, GP_PWD_131, GP_PWD_130, }; enum { HAL_RESET_POWER_ON, HAL_RESET_WARM, HAL_RESET_COLD, }; typedef struct _gain_opt_step { int16_t paramVal[NUM_CORNER_FIX_BITS_2133]; int32_t stepGain; int8_t stepName[16]; } GAIN_OPTIMIZATION_STEP; typedef struct { u_int32_t numStepsInLadder; u_int32_t defaultStepNum; GAIN_OPTIMIZATION_STEP optStep[10]; } GAIN_OPTIMIZATION_LADDER; typedef struct { u_int32_t currStepNum; u_int32_t currGain; u_int32_t targetGain; u_int32_t loTrig; u_int32_t hiTrig; u_int32_t gainFCorrection; u_int32_t active; GAIN_OPTIMIZATION_STEP *curr_step; } GAIN_VALUES; typedef struct { u_int16_t synth_center; u_int16_t ctl_center; u_int16_t ext_center; } CHAN_CENTERS; /* RF HAL structures */ typedef struct rf_hal_funcs { HAL_BOOL (*set_channel)(struct ath_hal *, struct ieee80211_channel *); HAL_BOOL (*get_chip_power_lim)(struct ath_hal *ah, struct ieee80211_channel *chan); } RF_HAL_FUNCS; struct ar9300_ani_default { u_int16_t m1_thresh_low; u_int16_t m2_thresh_low; u_int16_t m1_thresh; u_int16_t m2_thresh; u_int16_t m2_count_thr; u_int16_t m2_count_thr_low; u_int16_t m1_thresh_low_ext; u_int16_t m2_thresh_low_ext; u_int16_t m1_thresh_ext; u_int16_t m2_thresh_ext; u_int16_t firstep; u_int16_t firstep_low; u_int16_t cycpwr_thr1; u_int16_t cycpwr_thr1_ext; }; /* * Per-channel ANI state private to the driver. */ struct ar9300_ani_state { struct ieee80211_channel c; /* XXX ew? */ HAL_BOOL must_restore; HAL_BOOL ofdms_turn; u_int8_t ofdm_noise_immunity_level; u_int8_t cck_noise_immunity_level; u_int8_t spur_immunity_level; u_int8_t firstep_level; u_int8_t ofdm_weak_sig_detect_off; u_int8_t mrc_cck_off; /* Thresholds */ u_int32_t listen_time; u_int32_t ofdm_trig_high; u_int32_t ofdm_trig_low; int32_t cck_trig_high; int32_t cck_trig_low; int32_t rssi_thr_low; int32_t rssi_thr_high; int32_t rssi; /* The current RSSI */ u_int32_t tx_frame_count; /* Last tx_frame_count */ u_int32_t rx_frame_count; /* Last rx Frame count */ u_int32_t cycle_count; /* Last cycle_count (can detect wrap-around) */ u_int32_t ofdm_phy_err_count;/* OFDM err count since last reset */ u_int32_t cck_phy_err_count; /* CCK err count since last reset */ struct ar9300_ani_default ini_def; /* INI default values for ANI registers */ HAL_BOOL phy_noise_spur; /* based on OFDM/CCK Phy errors */ }; #define AR9300_ANI_POLLINTERVAL 1000 /* 1000 milliseconds between ANI poll */ #define AR9300_CHANNEL_SWITCH_TIME_USEC 1000 /* 1 millisecond needed to change channels */ #define HAL_PROCESS_ANI 0x00000001 /* ANI state setup */ #define HAL_RADAR_EN 0x80000000 /* Radar detect is capable */ #define HAL_AR_EN 0x40000000 /* AR detect is capable */ #define DO_ANI(ah) \ ((AH9300(ah)->ah_proc_phy_err & HAL_PROCESS_ANI)) struct ar9300_stats { u_int32_t ast_ani_niup; /* ANI increased noise immunity */ u_int32_t ast_ani_nidown; /* ANI decreased noise immunity */ u_int32_t ast_ani_spurup; /* ANI increased spur immunity */ u_int32_t ast_ani_spurdown;/* ANI descreased spur immunity */ u_int32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ u_int32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ u_int32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ u_int32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ u_int32_t ast_ani_stepup; /* ANI increased first step level */ u_int32_t ast_ani_stepdown;/* ANI decreased first step level */ u_int32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ u_int32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ u_int32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ u_int32_t ast_ani_lzero; /* ANI listen time forced to zero */ u_int32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ }; struct ar9300_rad_reader { u_int16_t rd_index; u_int16_t rd_expSeq; u_int32_t rd_resetVal; u_int8_t rd_start; }; struct ar9300_rad_writer { u_int16_t wr_index; u_int16_t wr_seq; }; struct ar9300_radar_event { u_int32_t re_ts; /* 32 bit time stamp */ u_int8_t re_rssi; /* rssi of radar event */ u_int8_t re_dur; /* duration of radar pulse */ u_int8_t re_chanIndex; /* Channel of event */ }; struct ar9300_radar_q_elem { u_int32_t rq_seqNum; u_int32_t rq_busy; /* 32 bit to insure atomic read/write */ struct ar9300_radar_event rq_event; /* Radar event */ }; struct ar9300_radar_q_info { u_int16_t ri_qsize; /* q size */ u_int16_t ri_seqSize; /* Size of sequence ring */ struct ar9300_rad_reader ri_reader; /* State for the q reader */ struct ar9300_rad_writer ri_writer; /* state for the q writer */ }; #define HAL_MAX_ACK_RADAR_DUR 511 #define HAL_MAX_NUM_PEAKS 3 #define HAL_ARQ_SIZE 4096 /* 8K AR events for buffer size */ #define HAL_ARQ_SEQSIZE 4097 /* Sequence counter wrap for AR */ #define HAL_RADARQ_SIZE 1024 /* 1K radar events for buffer size */ #define HAL_RADARQ_SEQSIZE 1025 /* Sequence counter wrap for radar */ #define HAL_NUMRADAR_STATES 64 /* Number of radar channels we keep state for */ struct ar9300_ar_state { u_int16_t ar_prev_time_stamp; u_int32_t ar_prev_width; u_int32_t ar_phy_err_count[HAL_MAX_ACK_RADAR_DUR]; u_int32_t ar_ack_sum; u_int16_t ar_peak_list[HAL_MAX_NUM_PEAKS]; u_int32_t ar_packet_threshold; /* Thresh to determine traffic load */ u_int32_t ar_par_threshold; /* Thresh to determine peak */ u_int32_t ar_radar_rssi; /* Rssi threshold for AR event */ }; struct ar9300_radar_state { struct ieee80211_channel *rs_chan; /* Channel info */ u_int8_t rs_chan_index; /* Channel index in radar structure */ u_int32_t rs_num_radar_events; /* Number of radar events */ int32_t rs_firpwr; /* Thresh to check radar sig is gone */ u_int32_t rs_radar_rssi; /* Thresh to start radar det (dB) */ u_int32_t rs_height; /* Thresh for pulse height (dB)*/ u_int32_t rs_pulse_rssi; /* Thresh to check if pulse is gone (dB) */ u_int32_t rs_inband; /* Thresh to check if pusle is inband (0.5 dB) */ }; typedef struct { u_int8_t uc_receiver_errors; u_int8_t uc_bad_tlp_errors; u_int8_t uc_bad_dllp_errors; u_int8_t uc_replay_timeout_errors; u_int8_t uc_replay_number_rollover_errors; } ar_pcie_error_moniter_counters; #define AR9300_OPFLAGS_11A 0x01 /* if set, allow 11a */ #define AR9300_OPFLAGS_11G 0x02 /* if set, allow 11g */ #define AR9300_OPFLAGS_N_5G_HT40 0x04 /* if set, disable 5G HT40 */ #define AR9300_OPFLAGS_N_2G_HT40 0x08 /* if set, disable 2G HT40 */ #define AR9300_OPFLAGS_N_5G_HT20 0x10 /* if set, disable 5G HT20 */ #define AR9300_OPFLAGS_N_2G_HT20 0x20 /* if set, disable 2G HT20 */ /* * For Kite and later chipsets, the following bits are not being programmed in EEPROM * and so need to be enabled always. * Bit 0: en_fcc_mid, Bit 1: en_jap_mid, Bit 2: en_fcc_dfs_ht40 * Bit 3: en_jap_ht40, Bit 4: en_jap_dfs_ht40 */ #define AR9300_RDEXT_DEFAULT 0x1F #define AR9300_MAX_CHAINS 3 #define AR9300_NUM_CHAINS(chainmask) \ (((chainmask >> 2) & 1) + ((chainmask >> 1) & 1) + (chainmask & 1)) #define AR9300_CHAIN0_MASK 0x1 #define AR9300_CHAIN1_MASK 0x2 #define AR9300_CHAIN2_MASK 0x4 /* Support for multiple INIs */ struct ar9300_ini_array { const u_int32_t *ia_array; u_int32_t ia_rows; u_int32_t ia_columns; }; #define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ (iniarray)->ia_array = (const u_int32_t *)(array); \ (iniarray)->ia_rows = (rows); \ (iniarray)->ia_columns = (columns); \ } while (0) #define INI_RA(iniarray, row, column) (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) #define INIT_CAL(_perCal) \ (_perCal)->cal_state = CAL_WAITING; \ (_perCal)->cal_next = AH_NULL; #define INSERT_CAL(_ahp, _perCal) \ do { \ if ((_ahp)->ah_cal_list_last == AH_NULL) { \ (_ahp)->ah_cal_list = (_ahp)->ah_cal_list_last = (_perCal); \ ((_ahp)->ah_cal_list_last)->cal_next = (_perCal); \ } else { \ ((_ahp)->ah_cal_list_last)->cal_next = (_perCal); \ (_ahp)->ah_cal_list_last = (_perCal); \ (_perCal)->cal_next = (_ahp)->ah_cal_list; \ } \ } while (0) typedef enum cal_types { IQ_MISMATCH_CAL = 0x1, TEMP_COMP_CAL = 0x2, } HAL_CAL_TYPES; typedef enum cal_state { CAL_INACTIVE, CAL_WAITING, CAL_RUNNING, CAL_DONE } HAL_CAL_STATE; /* Calibrate state */ #define MIN_CAL_SAMPLES 1 #define MAX_CAL_SAMPLES 64 #define INIT_LOG_COUNT 5 #define PER_MIN_LOG_COUNT 2 #define PER_MAX_LOG_COUNT 10 #define AR9300_NUM_BT_WEIGHTS 4 #define AR9300_NUM_WLAN_WEIGHTS 4 /* Per Calibration data structure */ typedef struct per_cal_data { HAL_CAL_TYPES cal_type; // Type of calibration u_int32_t cal_num_samples; // Number of SW samples to collect u_int32_t cal_count_max; // Number of HW samples to collect void (*cal_collect)(struct ath_hal *, u_int8_t); // Accumulator func void (*cal_post_proc)(struct ath_hal *, u_int8_t); // Post-processing func } HAL_PERCAL_DATA; /* List structure for calibration data */ typedef struct cal_list { const HAL_PERCAL_DATA *cal_data; HAL_CAL_STATE cal_state; struct cal_list *cal_next; } HAL_CAL_LIST; #define AR9300_NUM_CAL_TYPES 2 #define AR9300_PAPRD_TABLE_SZ 24 #define AR9300_PAPRD_GAIN_TABLE_SZ 32 #define AR9382_MAX_GPIO_PIN_NUM (16) #define AR9382_GPIO_PIN_8_RESERVED (8) #define AR9382_GPIO_9_INPUT_ONLY (9) #define AR9382_MAX_GPIO_INPUT_PIN_NUM (13) #define AR9382_GPIO_PIN_11_RESERVED (11) #define AR9382_MAX_JTAG_GPIO_PIN_NUM (3) /* Paprd tx power adjust data structure */ struct ar9300_paprd_pwr_adjust { u_int32_t target_rate; // rate index u_int32_t reg_addr; // register offset u_int32_t reg_mask; // mask of register u_int32_t reg_mask_offset; // mask offset of register u_int32_t sub_db; // offset value unit of dB }; struct ar9300NfLimits { int16_t max; int16_t min; int16_t nominal; }; #define AR9300_MAX_RATES 36 /* legacy(4) + ofdm(8) + HTSS(8) + HTDS(8) + HTTS(8)*/ struct ath_hal_9300 { struct ath_hal_private ah_priv; /* base class */ /* * Information retrieved from EEPROM. */ ar9300_eeprom_t ah_eeprom; GAIN_VALUES ah_gain_values; u_int8_t ah_macaddr[IEEE80211_ADDR_LEN]; u_int8_t ah_bssid[IEEE80211_ADDR_LEN]; u_int8_t ah_bssid_mask[IEEE80211_ADDR_LEN]; u_int16_t ah_assoc_id; /* * Runtime state. */ u_int32_t ah_mask_reg; /* copy of AR_IMR */ u_int32_t ah_mask2Reg; /* copy of AR_IMR_S2 */ u_int32_t ah_msi_reg; /* copy of AR_PCIE_MSI */ os_atomic_t ah_ier_ref_count; /* reference count for enabling interrupts */ struct ar9300_stats ah_stats; /* various statistics */ RF_HAL_FUNCS ah_rf_hal; u_int32_t ah_tx_desc_mask; /* mask for TXDESC */ u_int32_t ah_tx_ok_interrupt_mask; u_int32_t ah_tx_err_interrupt_mask; u_int32_t ah_tx_desc_interrupt_mask; u_int32_t ah_tx_eol_interrupt_mask; u_int32_t ah_tx_urn_interrupt_mask; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; HAL_SMPS_MODE ah_sm_power_mode; HAL_BOOL ah_chip_full_sleep; u_int32_t ah_atim_window; HAL_ANT_SETTING ah_diversity_control; /* antenna setting */ u_int16_t ah_antenna_switch_swap; /* Controls mapping of OID request */ u_int8_t ah_tx_chainmask_cfg; /* chain mask config */ u_int8_t ah_rx_chainmask_cfg; u_int32_t ah_beacon_rssi_threshold; /* cache beacon rssi threshold */ /* Calibration related fields */ HAL_CAL_TYPES ah_supp_cals; HAL_CAL_LIST ah_iq_cal_data; /* IQ Cal Data */ HAL_CAL_LIST ah_temp_comp_cal_data; /* Temperature Compensation Cal Data */ HAL_CAL_LIST *ah_cal_list; /* ptr to first cal in list */ HAL_CAL_LIST *ah_cal_list_last; /* ptr to last cal in list */ HAL_CAL_LIST *ah_cal_list_curr; /* ptr to current cal */ // IQ Cal aliases #define ah_total_power_meas_i ah_meas0.unsign #define ah_total_power_meas_q ah_meas1.unsign #define ah_total_iq_corr_meas ah_meas2.sign union { u_int32_t unsign[AR9300_MAX_CHAINS]; int32_t sign[AR9300_MAX_CHAINS]; } ah_meas0; union { u_int32_t unsign[AR9300_MAX_CHAINS]; int32_t sign[AR9300_MAX_CHAINS]; } ah_meas1; union { u_int32_t unsign[AR9300_MAX_CHAINS]; int32_t sign[AR9300_MAX_CHAINS]; } ah_meas2; union { u_int32_t unsign[AR9300_MAX_CHAINS]; int32_t sign[AR9300_MAX_CHAINS]; } ah_meas3; u_int16_t ah_cal_samples; /* end - Calibration related fields */ u_int32_t ah_tx6_power_in_half_dbm; /* power output for 6Mb tx */ u_int32_t ah_sta_id1_defaults; /* STA_ID1 default settings */ u_int32_t ah_misc_mode; /* MISC_MODE settings */ HAL_BOOL ah_get_plcp_hdr; /* setting about MISC_SEL_EVM */ enum { AUTO_32KHZ, /* use it if 32kHz crystal present */ USE_32KHZ, /* do it regardless */ DONT_USE_32KHZ, /* don't use it regardless */ } ah_enable32k_hz_clock; /* whether to sleep at 32kHz */ u_int32_t ah_ofdm_tx_power; int16_t ah_tx_power_index_offset; u_int ah_slot_time; /* user-specified slot time */ u_int ah_ack_timeout; /* user-specified ack timeout */ /* * XXX * 11g-specific stuff; belongs in the driver. */ u_int8_t ah_g_beacon_rate; /* fixed rate for G beacons */ u_int32_t ah_gpio_mask; /* copy of enabled GPIO mask */ u_int32_t ah_gpio_cause; /* copy of GPIO cause (sync and async) */ /* * RF Silent handling; setup according to the EEPROM. */ u_int32_t ah_gpio_select; /* GPIO pin to use */ u_int32_t ah_polarity; /* polarity to disable RF */ u_int32_t ah_gpio_bit; /* after init, prev value */ HAL_BOOL ah_eep_enabled; /* EEPROM bit for capability */ #ifdef ATH_BT_COEX /* * Bluetooth coexistence static setup according to the registry */ HAL_BT_MODULE ah_bt_module; /* Bluetooth module identifier */ u_int8_t ah_bt_coex_config_type; /* BT coex configuration */ u_int8_t ah_bt_active_gpio_select; /* GPIO pin for BT_ACTIVE */ u_int8_t ah_bt_priority_gpio_select; /* GPIO pin for BT_PRIORITY */ u_int8_t ah_wlan_active_gpio_select; /* GPIO pin for WLAN_ACTIVE */ u_int8_t ah_bt_active_polarity; /* Polarity of BT_ACTIVE */ HAL_BOOL ah_bt_coex_single_ant; /* Single or dual antenna configuration */ u_int8_t ah_bt_wlan_isolation; /* Isolation between BT and WLAN in dB */ /* * Bluetooth coexistence runtime settings */ HAL_BOOL ah_bt_coex_enabled; /* If Bluetooth coexistence is enabled */ u_int32_t ah_bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ u_int32_t ah_bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; /* Register setting for AR_BT_COEX_WEIGHT */ u_int32_t ah_bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; /* Register setting for AR_BT_COEX_WEIGHT */ u_int32_t ah_bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ u_int32_t ah_bt_coex_flag; /* Special tuning flags for BT coex */ #endif /* * Generic timer support */ u_int32_t ah_avail_gen_timers; /* mask of available timers */ u_int32_t ah_intr_gen_timer_trigger; /* generic timer trigger interrupt state */ u_int32_t ah_intr_gen_timer_thresh; /* generic timer trigger interrupt state */ HAL_BOOL ah_enable_tsf2; /* enable TSF2 for gen timer 8-15. */ /* * ANI & Radar support. */ u_int32_t ah_proc_phy_err; /* Process Phy errs */ u_int32_t ah_ani_period; /* ani update list period */ struct ar9300_ani_state *ah_curani; /* cached last reference */ struct ar9300_ani_state ah_ani[255]; /* per-channel state */ struct ar9300_radar_state ah_radar[HAL_NUMRADAR_STATES]; /* Per-Channel Radar detector state */ struct ar9300_radar_q_elem *ah_radarq; /* radar event queue */ struct ar9300_radar_q_info ah_radarq_info; /* radar event q read/write state */ struct ar9300_ar_state ah_ar; /* AR detector state */ struct ar9300_radar_q_elem *ah_arq; /* AR event queue */ struct ar9300_radar_q_info ah_arq_info; /* AR event q read/write state */ /* * Transmit power state. Note these are maintained * here so they can be retrieved by diagnostic tools. */ u_int16_t ah_rates_array[16]; /* * Tx queue interrupt state. */ u_int32_t ah_intr_txqs; HAL_BOOL ah_intr_mitigation_rx; /* rx Interrupt Mitigation Settings */ HAL_BOOL ah_intr_mitigation_tx; /* tx Interrupt Mitigation Settings */ /* * Extension Channel Rx Clear State */ u_int32_t ah_cycle_count; u_int32_t ah_ctl_busy; u_int32_t ah_ext_busy; /* HT CWM state */ HAL_HT_EXTPROTSPACING ah_ext_prot_spacing; u_int8_t ah_tx_chainmask; /* tx chain mask */ u_int8_t ah_rx_chainmask; /* rx chain mask */ + /* optional tx chainmask */ + u_int8_t ah_tx_chainmaskopt; + u_int8_t ah_tx_cal_chainmask; /* tx cal chain mask */ u_int8_t ah_rx_cal_chainmask; /* rx cal chain mask */ int ah_hwp; void *ah_cal_mem; HAL_BOOL ah_emu_eeprom; HAL_ANI_CMD ah_ani_function; HAL_BOOL ah_rifs_enabled; u_int32_t ah_rifs_reg[11]; u_int32_t ah_rifs_sec_cnt; /* open-loop power control */ u_int32_t original_gain[22]; int32_t init_pdadc; int32_t pdadc_delta; /* cycle counts for beacon stuck diagnostics */ u_int32_t ah_cycles; u_int32_t ah_rx_clear; u_int32_t ah_rx_frame; u_int32_t ah_tx_frame; #define BB_HANG_SIG1 0 #define BB_HANG_SIG2 1 #define BB_HANG_SIG3 2 #define BB_HANG_SIG4 3 #define MAC_HANG_SIG1 4 #define MAC_HANG_SIG2 5 /* bb hang detection */ int ah_hang[6]; hal_hw_hangs_t ah_hang_wars; /* * Keytable type table */ #define AR_KEYTABLE_SIZE 128 /* XXX! */ uint8_t ah_keytype[AR_KEYTABLE_SIZE]; #undef AR_KEYTABLE_SIZE /* * Support for ar9300 multiple INIs */ struct ar9300_ini_array ah_ini_pcie_serdes; struct ar9300_ini_array ah_ini_pcie_serdes_low_power; struct ar9300_ini_array ah_ini_modes_additional; struct ar9300_ini_array ah_ini_modes_additional_40mhz; struct ar9300_ini_array ah_ini_modes_rxgain; struct ar9300_ini_array ah_ini_modes_rxgain_bounds; struct ar9300_ini_array ah_ini_modes_txgain; struct ar9300_ini_array ah_ini_japan2484; struct ar9300_ini_array ah_ini_radio_post_sys2ant; struct ar9300_ini_array ah_ini_BTCOEX_MAX_TXPWR; /* * New INI format starting with Osprey 2.0 INI. * Pre, core, post arrays for each sub-system (mac, bb, radio, soc) */ #define ATH_INI_PRE 0 #define ATH_INI_CORE 1 #define ATH_INI_POST 2 #define ATH_INI_NUM_SPLIT (ATH_INI_POST + 1) struct ar9300_ini_array ah_ini_mac[ATH_INI_NUM_SPLIT]; /* New INI format */ struct ar9300_ini_array ah_ini_bb[ATH_INI_NUM_SPLIT]; /* New INI format */ struct ar9300_ini_array ah_ini_radio[ATH_INI_NUM_SPLIT]; /* New INI format */ struct ar9300_ini_array ah_ini_soc[ATH_INI_NUM_SPLIT]; /* New INI format */ /* * Added to support DFS postamble array in INI that we need to apply * in DFS channels */ struct ar9300_ini_array ah_ini_dfs; #if ATH_WOW struct ar9300_ini_array ah_ini_pcie_serdes_wow; /* SerDes values during WOW sleep */ #endif /* To indicate EEPROM mapping used */ u_int32_t ah_immunity_vals[6]; HAL_BOOL ah_immunity_on; /* * snap shot of counter register for debug purposes */ #ifdef AH_DEBUG u_int32_t last_tf; u_int32_t last_rf; u_int32_t last_rc; u_int32_t last_cc; #endif HAL_BOOL ah_dma_stuck; /* Set to AH_TRUE when RX/TX DMA failed to stop. */ u_int32_t nf_tsf32; /* timestamp for NF calibration duration */ u_int32_t reg_dmn; /* Regulatory Domain */ int16_t twice_antenna_gain; /* Antenna Gain */ u_int16_t twice_antenna_reduction; /* Antenna Gain Allowed */ /* * Upper limit after factoring in the regulatory max, antenna gain and * multichain factor. No TxBF, CDD or STBC gain factored */ int16_t upper_limit[AR9300_MAX_CHAINS]; /* adjusted power for descriptor-based TPC for 1, 2, or 3 chains */ int16_t txpower[AR9300_MAX_RATES][AR9300_MAX_CHAINS]; /* adjusted power for descriptor-based TPC for 1, 2, or 3 chains with STBC*/ int16_t txpower_stbc[AR9300_MAX_RATES][AR9300_MAX_CHAINS]; /* Transmit Status ring support */ struct ar9300_txs *ts_ring; u_int16_t ts_tail; u_int16_t ts_size; u_int32_t ts_paddr_start; u_int32_t ts_paddr_end; /* Receive Buffer size */ #define HAL_RXBUFSIZE_DEFAULT 0xfff u_int16_t rx_buf_size; u_int32_t ah_wa_reg_val; // Store the permanent value of Reg 0x4004 so we dont have to R/M/W. (We should not be reading this register when in sleep states). /* Indicate the PLL source clock rate is 25Mhz or not. * clk_25mhz = 0 by default. */ u_int8_t clk_25mhz; /* For PAPRD uses */ u_int16_t small_signal_gain[AH_MAX_CHAINS]; u_int32_t pa_table[AH_MAX_CHAINS][AR9300_PAPRD_TABLE_SZ]; u_int32_t paprd_gain_table_entries[AR9300_PAPRD_GAIN_TABLE_SZ]; u_int32_t paprd_gain_table_index[AR9300_PAPRD_GAIN_TABLE_SZ]; u_int32_t ah_2g_paprd_rate_mask_ht20; /* Copy of eep->modal_header_2g.paprd_rate_mask_ht20 */ u_int32_t ah_2g_paprd_rate_mask_ht40; /* Copy of eep->modal_header_2g.paprd_rate_mask_ht40 */ u_int32_t ah_5g_paprd_rate_mask_ht20; /* Copy of eep->modal_header_5g.paprd_rate_mask_ht20 */ u_int32_t ah_5g_paprd_rate_mask_ht40; /* Copy of eep->modal_header_5g.paprd_rate_mask_ht40 */ u_int32_t paprd_training_power; /* For GreenTx use to store the default tx power */ u_int8_t ah_default_tx_power[ar9300_rate_size]; HAL_BOOL ah_paprd_broken; /* To store offsets of host interface registers */ struct { u_int32_t AR_RC; u_int32_t AR_WA; u_int32_t AR_PM_STATE; u_int32_t AR_H_INFOL; u_int32_t AR_H_INFOH; u_int32_t AR_PCIE_PM_CTRL; u_int32_t AR_HOST_TIMEOUT; u_int32_t AR_EEPROM; u_int32_t AR_SREV; u_int32_t AR_INTR_SYNC_CAUSE; u_int32_t AR_INTR_SYNC_CAUSE_CLR; u_int32_t AR_INTR_SYNC_ENABLE; u_int32_t AR_INTR_ASYNC_MASK; u_int32_t AR_INTR_SYNC_MASK; u_int32_t AR_INTR_ASYNC_CAUSE_CLR; u_int32_t AR_INTR_ASYNC_CAUSE; u_int32_t AR_INTR_ASYNC_ENABLE; u_int32_t AR_PCIE_SERDES; u_int32_t AR_PCIE_SERDES2; u_int32_t AR_GPIO_OUT; u_int32_t AR_GPIO_IN; u_int32_t AR_GPIO_OE_OUT; u_int32_t AR_GPIO_OE1_OUT; u_int32_t AR_GPIO_INTR_POL; u_int32_t AR_GPIO_INPUT_EN_VAL; u_int32_t AR_GPIO_INPUT_MUX1; u_int32_t AR_GPIO_INPUT_MUX2; u_int32_t AR_GPIO_OUTPUT_MUX1; u_int32_t AR_GPIO_OUTPUT_MUX2; u_int32_t AR_GPIO_OUTPUT_MUX3; u_int32_t AR_INPUT_STATE; u_int32_t AR_SPARE; u_int32_t AR_PCIE_CORE_RESET_EN; u_int32_t AR_CLKRUN; u_int32_t AR_EEPROM_STATUS_DATA; u_int32_t AR_OBS; u_int32_t AR_RFSILENT; u_int32_t AR_GPIO_PDPU; u_int32_t AR_GPIO_DS; u_int32_t AR_MISC; u_int32_t AR_PCIE_MSI; u_int32_t AR_TSF_SNAPSHOT_BT_ACTIVE; u_int32_t AR_TSF_SNAPSHOT_BT_PRIORITY; u_int32_t AR_TSF_SNAPSHOT_BT_CNTL; u_int32_t AR_PCIE_PHY_LATENCY_NFTS_ADJ; u_int32_t AR_TDMA_CCA_CNTL; u_int32_t AR_TXAPSYNC; u_int32_t AR_TXSYNC_INIT_SYNC_TMR; u_int32_t AR_INTR_PRIO_SYNC_CAUSE; u_int32_t AR_INTR_PRIO_SYNC_ENABLE; u_int32_t AR_INTR_PRIO_ASYNC_MASK; u_int32_t AR_INTR_PRIO_SYNC_MASK; u_int32_t AR_INTR_PRIO_ASYNC_CAUSE; u_int32_t AR_INTR_PRIO_ASYNC_ENABLE; } ah_hostifregs; u_int32_t ah_enterprise_mode; u_int32_t ah_radar1; u_int32_t ah_dc_offset; HAL_BOOL ah_hw_green_tx_enable; /* 1:enalbe H/W Green Tx */ HAL_BOOL ah_smartantenna_enable; /* 1:enalbe H/W */ u_int32_t ah_disable_cck; HAL_BOOL ah_lna_div_use_bt_ant_enable; /* 1:enable Rx(LNA) Diversity */ /* * Different types of memory where the calibration data might be stored. * All types are searched in Ar9300EepromRestore() in the order flash, eeprom, otp. * To disable searching a type, set its parameter to 0. */ int try_dram; int try_flash; int try_eeprom; int try_otp; #ifdef ATH_CAL_NAND_FLASH int try_nand; #endif /* * This is where we found the calibration data. */ int calibration_data_source; int calibration_data_source_address; /* * This is where we look for the calibration data. must be set before ath_attach() is called */ int calibration_data_try; int calibration_data_try_address; u_int8_t tx_iq_cal_enable : 1, tx_iq_cal_during_agc_cal : 1, tx_cl_cal_enable : 1; #if ATH_SUPPORT_MCI /* For MCI */ HAL_BOOL ah_mci_ready; u_int32_t ah_mci_int_raw; u_int32_t ah_mci_int_rx_msg; u_int32_t ah_mci_rx_status; u_int32_t ah_mci_cont_status; u_int8_t ah_mci_bt_state; u_int32_t ah_mci_gpm_addr; u_int8_t *ah_mci_gpm_buf; u_int32_t ah_mci_gpm_len; u_int32_t ah_mci_gpm_idx; u_int32_t ah_mci_sched_addr; u_int8_t *ah_mci_sched_buf; u_int8_t ah_mci_coex_major_version_wlan; u_int8_t ah_mci_coex_minor_version_wlan; u_int8_t ah_mci_coex_major_version_bt; u_int8_t ah_mci_coex_minor_version_bt; HAL_BOOL ah_mci_coex_bt_version_known; HAL_BOOL ah_mci_coex_wlan_channels_update; u_int32_t ah_mci_coex_wlan_channels[4]; HAL_BOOL ah_mci_coex_2g5g_update; HAL_BOOL ah_mci_coex_is_2g; HAL_BOOL ah_mci_query_bt; HAL_BOOL ah_mci_unhalt_bt_gpm; /* need send UNHALT */ HAL_BOOL ah_mci_halted_bt_gpm; /* HALT sent */ HAL_BOOL ah_mci_need_flush_btinfo; HAL_BOOL ah_mci_concur_tx_en; u_int8_t ah_mci_stomp_low_tx_pri; u_int8_t ah_mci_stomp_all_tx_pri; u_int8_t ah_mci_stomp_none_tx_pri; u_int32_t ah_mci_wlan_cal_seq; u_int32_t ah_mci_wlan_cal_done; #if ATH_SUPPORT_AIC HAL_BOOL ah_aic_enabled; u_int32_t ah_aic_sram[ATH_AIC_MAX_BT_CHANNEL]; #endif + #endif /* ATH_SUPPORT_MCI */ u_int8_t ah_cac_quiet_enabled; #if ATH_WOW_OFFLOAD u_int32_t ah_mcast_filter_l32_set; u_int32_t ah_mcast_filter_u32_set; #endif HAL_BOOL ah_reduced_self_gen_mask; + HAL_BOOL ah_chip_reset_done; + HAL_BOOL ah_abort_txdma_norx; + /* store previous passive RX Cal info */ + HAL_BOOL ah_skip_rx_iq_cal; + HAL_BOOL ah_rx_cal_complete; /* previous rx cal completed or not */ + u_int32_t ah_rx_cal_chan; /* chan on which rx cal is done */ + u_int32_t ah_rx_cal_chan_flag; + u_int32_t ah_rx_cal_corr[AR9300_MAX_CHAINS]; /* Local additions for FreeBSD */ /* * These fields are in the top level HAL in the atheros * codebase; here we place them in the AR9300 HAL and * access them via accessor methods if the driver requires them. */ u_int32_t ah_ob_db1[3]; u_int32_t ah_db2[3]; u_int32_t ah_bb_panic_timeout_ms; u_int32_t ah_bb_panic_last_status; u_int32_t ah_tx_trig_level; u_int16_t ath_hal_spur_chans[AR_EEPROM_MODAL_SPURS][2]; int16_t nf_cw_int_delta; /* diff btwn nominal NF and CW interf threshold */ int ah_phyrestart_disabled; HAL_RSSI_TX_POWER green_tx_status; int green_ap_ps_on; int ah_enable_keysearch_always; int ah_fccaifs; int ah_reset_reason; int ah_dcs_enable; struct ar9300NfLimits nf_2GHz; struct ar9300NfLimits nf_5GHz; struct ar9300NfLimits *nfp; - }; #define AH9300(_ah) ((struct ath_hal_9300 *)(_ah)) #define IS_9300_EMU(ah) \ (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_EMU_PCIE) #define ar9300_eep_data_in_flash(_ah) \ (!(AH_PRIVATE(_ah)->ah_flags & AH_USE_EEPROM)) #ifdef notyet // Need these additional conditions for IS_5GHZ_FAST_CLOCK_EN when we have valid eeprom contents. && \ ((ar9300_eeprom_get(AH9300(_ah), EEP_MINOR_REV) <= AR9300_EEP_MINOR_VER_16) || \ (ar9300_eeprom_get(AH9300(_ah), EEP_FSTCLK_5G)))) #endif /* * WAR for bug 6773. OS_DELAY() does a PIO READ on the PCI bus which allows * other cards' DMA reads to complete in the middle of our reset. */ #define WAR_6773(x) do { \ if ((++(x) % 64) == 0) \ OS_DELAY(1); \ } while (0) #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ int r; \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ OS_REG_WRITE(ah, INI_RA((iniarray), (r), 0), INI_RA((iniarray), r, (column)));\ WAR_6773(regWr); \ } \ } while (0) #define UPPER_5G_SUB_BANDSTART 5700 #define MID_5G_SUB_BANDSTART 5400 #define TRAINPOWER_DB_OFFSET 6 #define AH_PAPRD_GET_SCALE_FACTOR(_scale, _eep, _is2G, _channel) do{ if(_is2G) { _scale = (_eep->modal_header_2g.paprd_rate_mask_ht20>>25)&0x7; \ } else { \ if(_channel >= UPPER_5G_SUB_BANDSTART){ _scale = (_eep->modal_header_5g.paprd_rate_mask_ht20>>25)&0x7;} \ else if((UPPER_5G_SUB_BANDSTART < _channel) && (_channel >= MID_5G_SUB_BANDSTART)) \ { _scale = (_eep->modal_header_5g.paprd_rate_mask_ht40>>28)&0x7;} \ else { _scale = (_eep->modal_header_5g.paprd_rate_mask_ht40>>25)&0x7;} } }while(0) #ifdef AH_ASSERT #define ar9300FeatureNotSupported(feature, ah, func) \ ath_hal_printf(ah, # feature \ " not supported but called from %s\n", (func)), \ hal_assert(0) #else #define ar9300FeatureNotSupported(feature, ah, func) \ ath_hal_printf(ah, # feature \ " not supported but called from %s\n", (func)) #endif /* AH_ASSERT */ /* * Green Tx, Based on different RSSI of Received Beacon thresholds, * using different tx power by modified register tx power related values. * The thresholds are decided by system team. */ #define WB225_SW_GREEN_TX_THRES1_DB 56 /* in dB */ #define WB225_SW_GREEN_TX_THRES2_DB 41 /* in dB */ #define WB225_OB_CALIBRATION_VALUE 5 /* For Green Tx OLPC Delta Calibration Offset */ #define WB225_OB_GREEN_TX_SHORT_VALUE 1 /* For Green Tx OB value in short distance*/ #define WB225_OB_GREEN_TX_MIDDLE_VALUE 3 /* For Green Tx OB value in middle distance */ #define WB225_OB_GREEN_TX_LONG_VALUE 5 /* For Green Tx OB value in long distance */ #define WB225_BBPWRTXRATE9_SW_GREEN_TX_SHORT_VALUE 0x06060606 /* For SwGreen Tx BB_powertx_rate9 reg value in short distance */ #define WB225_BBPWRTXRATE9_SW_GREEN_TX_MIDDLE_VALUE 0x0E0E0E0E /* For SwGreen Tx BB_powertx_rate9 reg value in middle distance */ /* Tx power for short distacnce in SwGreenTx.*/ static const u_int8_t wb225_sw_gtx_tp_distance_short[ar9300_rate_size] = { 6, /*ALL_TARGET_LEGACY_6_24*/ 6, /*ALL_TARGET_LEGACY_36*/ 6, /*ALL_TARGET_LEGACY_48*/ 4, /*ALL_TARGET_LEGACY_54*/ 6, /*ALL_TARGET_LEGACY_1L_5L*/ 6, /*ALL_TARGET_LEGACY_5S*/ 6, /*ALL_TARGET_LEGACY_11L*/ 6, /*ALL_TARGET_LEGACY_11S*/ 6, /*ALL_TARGET_HT20_0_8_16*/ 6, /*ALL_TARGET_HT20_1_3_9_11_17_19*/ 4, /*ALL_TARGET_HT20_4*/ 4, /*ALL_TARGET_HT20_5*/ 4, /*ALL_TARGET_HT20_6*/ 2, /*ALL_TARGET_HT20_7*/ 0, /*ALL_TARGET_HT20_12*/ 0, /*ALL_TARGET_HT20_13*/ 0, /*ALL_TARGET_HT20_14*/ 0, /*ALL_TARGET_HT20_15*/ 0, /*ALL_TARGET_HT20_20*/ 0, /*ALL_TARGET_HT20_21*/ 0, /*ALL_TARGET_HT20_22*/ 0, /*ALL_TARGET_HT20_23*/ 6, /*ALL_TARGET_HT40_0_8_16*/ 6, /*ALL_TARGET_HT40_1_3_9_11_17_19*/ 4, /*ALL_TARGET_HT40_4*/ 4, /*ALL_TARGET_HT40_5*/ 4, /*ALL_TARGET_HT40_6*/ 2, /*ALL_TARGET_HT40_7*/ 0, /*ALL_TARGET_HT40_12*/ 0, /*ALL_TARGET_HT40_13*/ 0, /*ALL_TARGET_HT40_14*/ 0, /*ALL_TARGET_HT40_15*/ 0, /*ALL_TARGET_HT40_20*/ 0, /*ALL_TARGET_HT40_21*/ 0, /*ALL_TARGET_HT40_22*/ 0 /*ALL_TARGET_HT40_23*/ }; /* Tx power for middle distacnce in SwGreenTx.*/ static const u_int8_t wb225_sw_gtx_tp_distance_middle[ar9300_rate_size] = { 14, /*ALL_TARGET_LEGACY_6_24*/ 14, /*ALL_TARGET_LEGACY_36*/ 14, /*ALL_TARGET_LEGACY_48*/ 12, /*ALL_TARGET_LEGACY_54*/ 14, /*ALL_TARGET_LEGACY_1L_5L*/ 14, /*ALL_TARGET_LEGACY_5S*/ 14, /*ALL_TARGET_LEGACY_11L*/ 14, /*ALL_TARGET_LEGACY_11S*/ 14, /*ALL_TARGET_HT20_0_8_16*/ 14, /*ALL_TARGET_HT20_1_3_9_11_17_19*/ 14, /*ALL_TARGET_HT20_4*/ 14, /*ALL_TARGET_HT20_5*/ 12, /*ALL_TARGET_HT20_6*/ 10, /*ALL_TARGET_HT20_7*/ 0, /*ALL_TARGET_HT20_12*/ 0, /*ALL_TARGET_HT20_13*/ 0, /*ALL_TARGET_HT20_14*/ 0, /*ALL_TARGET_HT20_15*/ 0, /*ALL_TARGET_HT20_20*/ 0, /*ALL_TARGET_HT20_21*/ 0, /*ALL_TARGET_HT20_22*/ 0, /*ALL_TARGET_HT20_23*/ 14, /*ALL_TARGET_HT40_0_8_16*/ 14, /*ALL_TARGET_HT40_1_3_9_11_17_19*/ 14, /*ALL_TARGET_HT40_4*/ 14, /*ALL_TARGET_HT40_5*/ 12, /*ALL_TARGET_HT40_6*/ 10, /*ALL_TARGET_HT40_7*/ 0, /*ALL_TARGET_HT40_12*/ 0, /*ALL_TARGET_HT40_13*/ 0, /*ALL_TARGET_HT40_14*/ 0, /*ALL_TARGET_HT40_15*/ 0, /*ALL_TARGET_HT40_20*/ 0, /*ALL_TARGET_HT40_21*/ 0, /*ALL_TARGET_HT40_22*/ 0 /*ALL_TARGET_HT40_23*/ }; /* OLPC DeltaCalibration Offset unit in half dB.*/ static const u_int8_t wb225_gtx_olpc_cal_offset[6] = { 0, /* OB0*/ 16, /* OB1*/ 9, /* OB2*/ 5, /* OB3*/ 2, /* OB4*/ 0, /* OB5*/ }; /* * Definitions for HwGreenTx */ #define AR9485_HW_GREEN_TX_THRES1_DB 56 /* in dB */ #define AR9485_HW_GREEN_TX_THRES2_DB 41 /* in dB */ #define AR9485_BBPWRTXRATE9_HW_GREEN_TX_SHORT_VALUE 0x0C0C0A0A /* For HwGreen Tx BB_powertx_rate9 reg value in short distance */ #define AR9485_BBPWRTXRATE9_HW_GREEN_TX_MIDDLE_VALUE 0x10100E0E /* For HwGreenTx BB_powertx_rate9 reg value in middle distance */ /* Tx power for short distacnce in HwGreenTx.*/ static const u_int8_t ar9485_hw_gtx_tp_distance_short[ar9300_rate_size] = { 14, /*ALL_TARGET_LEGACY_6_24*/ 14, /*ALL_TARGET_LEGACY_36*/ 8, /*ALL_TARGET_LEGACY_48*/ 2, /*ALL_TARGET_LEGACY_54*/ 14, /*ALL_TARGET_LEGACY_1L_5L*/ 14, /*ALL_TARGET_LEGACY_5S*/ 14, /*ALL_TARGET_LEGACY_11L*/ 14, /*ALL_TARGET_LEGACY_11S*/ 12, /*ALL_TARGET_HT20_0_8_16*/ 12, /*ALL_TARGET_HT20_1_3_9_11_17_19*/ 12, /*ALL_TARGET_HT20_4*/ 12, /*ALL_TARGET_HT20_5*/ 8, /*ALL_TARGET_HT20_6*/ 2, /*ALL_TARGET_HT20_7*/ 0, /*ALL_TARGET_HT20_12*/ 0, /*ALL_TARGET_HT20_13*/ 0, /*ALL_TARGET_HT20_14*/ 0, /*ALL_TARGET_HT20_15*/ 0, /*ALL_TARGET_HT20_20*/ 0, /*ALL_TARGET_HT20_21*/ 0, /*ALL_TARGET_HT20_22*/ 0, /*ALL_TARGET_HT20_23*/ 10, /*ALL_TARGET_HT40_0_8_16*/ 10, /*ALL_TARGET_HT40_1_3_9_11_17_19*/ 10, /*ALL_TARGET_HT40_4*/ 10, /*ALL_TARGET_HT40_5*/ 6, /*ALL_TARGET_HT40_6*/ 2, /*ALL_TARGET_HT40_7*/ 0, /*ALL_TARGET_HT40_12*/ 0, /*ALL_TARGET_HT40_13*/ 0, /*ALL_TARGET_HT40_14*/ 0, /*ALL_TARGET_HT40_15*/ 0, /*ALL_TARGET_HT40_20*/ 0, /*ALL_TARGET_HT40_21*/ 0, /*ALL_TARGET_HT40_22*/ 0 /*ALL_TARGET_HT40_23*/ }; /* Tx power for middle distacnce in HwGreenTx.*/ static const u_int8_t ar9485_hw_gtx_tp_distance_middle[ar9300_rate_size] = { 18, /*ALL_TARGET_LEGACY_6_24*/ 18, /*ALL_TARGET_LEGACY_36*/ 14, /*ALL_TARGET_LEGACY_48*/ 12, /*ALL_TARGET_LEGACY_54*/ 18, /*ALL_TARGET_LEGACY_1L_5L*/ 18, /*ALL_TARGET_LEGACY_5S*/ 18, /*ALL_TARGET_LEGACY_11L*/ 18, /*ALL_TARGET_LEGACY_11S*/ 16, /*ALL_TARGET_HT20_0_8_16*/ 16, /*ALL_TARGET_HT20_1_3_9_11_17_19*/ 16, /*ALL_TARGET_HT20_4*/ 16, /*ALL_TARGET_HT20_5*/ 14, /*ALL_TARGET_HT20_6*/ 12, /*ALL_TARGET_HT20_7*/ 0, /*ALL_TARGET_HT20_12*/ 0, /*ALL_TARGET_HT20_13*/ 0, /*ALL_TARGET_HT20_14*/ 0, /*ALL_TARGET_HT20_15*/ 0, /*ALL_TARGET_HT20_20*/ 0, /*ALL_TARGET_HT20_21*/ 0, /*ALL_TARGET_HT20_22*/ 0, /*ALL_TARGET_HT20_23*/ 14, /*ALL_TARGET_HT40_0_8_16*/ 14, /*ALL_TARGET_HT40_1_3_9_11_17_19*/ 14, /*ALL_TARGET_HT40_4*/ 14, /*ALL_TARGET_HT40_5*/ 14, /*ALL_TARGET_HT40_6*/ 12, /*ALL_TARGET_HT40_7*/ 0, /*ALL_TARGET_HT40_12*/ 0, /*ALL_TARGET_HT40_13*/ 0, /*ALL_TARGET_HT40_14*/ 0, /*ALL_TARGET_HT40_15*/ 0, /*ALL_TARGET_HT40_20*/ 0, /*ALL_TARGET_HT40_21*/ 0, /*ALL_TARGET_HT40_22*/ 0 /*ALL_TARGET_HT40_23*/ }; /* MIMO Modes used in TPC calculations */ typedef enum { AR9300_DEF_MODE = 0, /* Could be CDD or Direct */ AR9300_TXBF_MODE, AR9300_STBC_MODE } AR9300_TXMODES; typedef enum { POSEIDON_STORED_REG_OBDB = 0, /* default OB/DB setting from ini */ POSEIDON_STORED_REG_TPC = 1, /* default txpower value in TPC reg */ POSEIDON_STORED_REG_BB_PWRTX_RATE9 = 2, /* default txpower value in * BB_powertx_rate9 reg */ POSEIDON_STORED_REG_SZ /* Can not add anymore */ } POSEIDON_STORED_REGS; typedef enum { POSEIDON_STORED_REG_G2_OLPC_OFFSET = 0,/* default OB/DB setting from ini */ POSEIDON_STORED_REG_G2_SZ /* should not exceed 3 */ } POSEIDON_STORED_REGS_G2; #if AH_NEED_TX_DATA_SWAP #if AH_NEED_RX_DATA_SWAP #define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB | AR_CFG_SWRB,0) #else #define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB,0) #endif #elif AH_NEED_RX_DATA_SWAP #define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWRB,0) #else #define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD,0) #endif extern HAL_BOOL ar9300_rf_attach(struct ath_hal *, HAL_STATUS *); struct ath_hal; extern struct ath_hal_9300 * ar9300_new_state(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status); extern struct ath_hal * ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status); extern void ar9300_detach(struct ath_hal *ah); extern void ar9300_read_revisions(struct ath_hal *ah); extern HAL_BOOL ar9300_chip_test(struct ath_hal *ah); extern HAL_BOOL ar9300_get_channel_edges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high); extern HAL_BOOL ar9300_fill_capability_info(struct ath_hal *ah); extern void ar9300_beacon_init(struct ath_hal *ah, - u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode); + u_int32_t next_beacon, u_int32_t beacon_period, + u_int32_t beacon_period_fraction, HAL_OPMODE opmode); extern void ar9300_set_sta_beacon_timers(struct ath_hal *ah, const HAL_BEACON_STATE *); extern HAL_BOOL ar9300_is_interrupt_pending(struct ath_hal *ah); extern HAL_BOOL ar9300_get_pending_interrupts(struct ath_hal *ah, HAL_INT *, HAL_INT_TYPE, u_int8_t, HAL_BOOL); extern HAL_INT ar9300_get_interrupts(struct ath_hal *ah); extern HAL_INT ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL); extern void ar9300_set_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg, u_int32_t value); extern u_int32_t ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg); extern u_int32_t ar9300_get_key_cache_size(struct ath_hal *); extern HAL_BOOL ar9300_is_key_cache_entry_valid(struct ath_hal *, u_int16_t entry); extern HAL_BOOL ar9300_reset_key_cache_entry(struct ath_hal *ah, u_int16_t entry); extern HAL_CHANNEL_INTERNAL * ar9300_check_chan(struct ath_hal *ah, const struct ieee80211_channel *chan); extern HAL_BOOL ar9300_set_key_cache_entry_mac(struct ath_hal *, u_int16_t entry, const u_int8_t *mac); extern HAL_BOOL ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry, const HAL_KEYVAL *k, const u_int8_t *mac, int xor_key); extern HAL_BOOL ar9300_print_keycache(struct ath_hal *ah); +#if ATH_SUPPORT_KEYPLUMB_WAR +extern HAL_BOOL ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry, + const HAL_KEYVAL *k, int xorKey); +#endif extern void ar9300_get_mac_address(struct ath_hal *ah, u_int8_t *mac); extern HAL_BOOL ar9300_set_mac_address(struct ath_hal *ah, const u_int8_t *); extern void ar9300_get_bss_id_mask(struct ath_hal *ah, u_int8_t *mac); extern HAL_BOOL ar9300_set_bss_id_mask(struct ath_hal *, const u_int8_t *); extern HAL_STATUS ar9300_select_ant_config(struct ath_hal *ah, u_int32_t cfg); +extern u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz); +extern HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops, + u_int32_t *common_tbl1, u_int32_t *common_tbl2); extern HAL_BOOL ar9300_set_regulatory_domain(struct ath_hal *ah, u_int16_t reg_domain, HAL_STATUS *stats); extern u_int ar9300_get_wireless_modes(struct ath_hal *ah); extern void ar9300_enable_rf_kill(struct ath_hal *); extern HAL_BOOL ar9300_gpio_cfg_output(struct ath_hal *, u_int32_t gpio, HAL_GPIO_MUX_TYPE signalType); extern HAL_BOOL ar9300_gpio_cfg_output_led_off(struct ath_hal *, u_int32_t gpio, HAL_GPIO_MUX_TYPE signalType); extern HAL_BOOL ar9300_gpio_cfg_input(struct ath_hal *, u_int32_t gpio); extern HAL_BOOL ar9300_gpio_set(struct ath_hal *, u_int32_t gpio, u_int32_t val); extern u_int32_t ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio); extern u_int32_t ar9300_gpio_get_intr(struct ath_hal *ah); extern void ar9300_gpio_set_intr(struct ath_hal *ah, u_int, u_int32_t ilevel); extern u_int32_t ar9300_gpio_get_polarity(struct ath_hal *ah); extern void ar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t, u_int32_t); extern u_int32_t ar9300_gpio_get_mask(struct ath_hal *ah); extern int ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map); extern void ar9300_set_led_state(struct ath_hal *ah, HAL_LED_STATE state); extern void ar9300_set_power_led_state(struct ath_hal *ah, u_int8_t enable); extern void ar9300_set_network_led_state(struct ath_hal *ah, u_int8_t enable); extern void ar9300_write_associd(struct ath_hal *ah, const u_int8_t *bssid, u_int16_t assoc_id); extern u_int32_t ar9300_ppm_get_rssi_dump(struct ath_hal *); extern u_int32_t ar9300_ppm_arm_trigger(struct ath_hal *); extern int ar9300_ppm_get_trigger(struct ath_hal *); extern u_int32_t ar9300_ppm_force(struct ath_hal *); extern void ar9300_ppm_un_force(struct ath_hal *); extern u_int32_t ar9300_ppm_get_force_state(struct ath_hal *); extern void ar9300_set_dcs_mode(struct ath_hal *ah, u_int32_t); extern u_int32_t ar9300_get_dcs_mode(struct ath_hal *ah); extern u_int32_t ar9300_get_tsf32(struct ath_hal *ah); extern u_int64_t ar9300_get_tsf64(struct ath_hal *ah); extern u_int32_t ar9300_get_tsf2_32(struct ath_hal *ah); extern void ar9300_set_tsf64(struct ath_hal *ah, u_int64_t tsf); extern void ar9300_reset_tsf(struct ath_hal *ah); extern void ar9300_set_basic_rate(struct ath_hal *ah, HAL_RATE_SET *pSet); extern u_int32_t ar9300_get_random_seed(struct ath_hal *ah); extern HAL_BOOL ar9300_detect_card_present(struct ath_hal *ah); extern void ar9300_update_mib_mac_stats(struct ath_hal *ah); extern void ar9300_get_mib_mac_stats(struct ath_hal *ah, HAL_MIB_STATS* stats); extern HAL_BOOL ar9300_is_japan_channel_spread_supported(struct ath_hal *ah); extern u_int32_t ar9300_get_cur_rssi(struct ath_hal *ah); extern u_int32_t ar9300_get_rssi_chain0(struct ath_hal *ah); extern u_int ar9300_get_def_antenna(struct ath_hal *ah); extern void ar9300_set_def_antenna(struct ath_hal *ah, u_int antenna); extern HAL_BOOL ar9300_set_antenna_switch(struct ath_hal *ah, HAL_ANT_SETTING settings, const struct ieee80211_channel *chan, u_int8_t *, u_int8_t *, u_int8_t *); extern HAL_BOOL ar9300_is_sleep_after_beacon_broken(struct ath_hal *ah); extern HAL_BOOL ar9300_set_slot_time(struct ath_hal *, u_int); extern HAL_BOOL ar9300_set_ack_timeout(struct ath_hal *, u_int); extern u_int ar9300_get_ack_timeout(struct ath_hal *); extern HAL_STATUS ar9300_set_quiet(struct ath_hal *ah, u_int32_t period, u_int32_t duration, u_int32_t next_start, HAL_QUIET_FLAG flag); extern void ar9300_set_pcu_config(struct ath_hal *); extern HAL_STATUS ar9300_get_capability(struct ath_hal *, HAL_CAPABILITY_TYPE, u_int32_t, u_int32_t *); extern HAL_BOOL ar9300_set_capability(struct ath_hal *, HAL_CAPABILITY_TYPE, u_int32_t, u_int32_t, HAL_STATUS *); extern HAL_BOOL ar9300_get_diag_state(struct ath_hal *ah, int request, const void *args, u_int32_t argsize, void **result, u_int32_t *resultsize); extern void ar9300_get_desc_info(struct ath_hal *ah, HAL_DESC_INFO *desc_info); extern uint32_t ar9300_get_11n_ext_busy(struct ath_hal *ah); extern void ar9300_set_11n_mac2040(struct ath_hal *ah, HAL_HT_MACMODE mode); extern HAL_HT_RXCLEAR ar9300_get_11n_rx_clear(struct ath_hal *ah); extern void ar9300_set_11n_rx_clear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear); extern HAL_BOOL ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip); extern HAL_POWER_MODE ar9300_get_power_mode(struct ath_hal *ah); extern HAL_BOOL ar9300_set_power_mode_awake(struct ath_hal *ah, int set_chip); extern void ar9300_set_sm_power_mode(struct ath_hal *ah, HAL_SMPS_MODE mode); extern void ar9300_config_pci_power_save(struct ath_hal *ah, int restore, int power_off); extern void ar9300_force_tsf_sync(struct ath_hal *ah, const u_int8_t *bssid, u_int16_t assoc_id); #if ATH_WOW extern void ar9300_wow_apply_pattern(struct ath_hal *ah, u_int8_t *p_ath_pattern, u_int8_t *p_ath_mask, int32_t pattern_count, u_int32_t ath_pattern_len); //extern u_int32_t ar9300_wow_wake_up(struct ath_hal *ah,u_int8_t *chipPatternBytes); extern u_int32_t ar9300_wow_wake_up(struct ath_hal *ah, HAL_BOOL offloadEnable); extern bool ar9300_wow_enable(struct ath_hal *ah, u_int32_t pattern_enable, u_int32_t timeout_in_seconds, int clearbssid, HAL_BOOL offloadEnable); #if ATH_WOW_OFFLOAD /* ARP offload */ #define WOW_OFFLOAD_ARP_INFO_MAX 2 struct hal_wow_offload_arp_info { u_int32_t valid; u_int32_t id; u_int32_t Flags; union { u_int8_t u8[4]; u_int32_t u32; } RemoteIPv4Address; union { u_int8_t u8[4]; u_int32_t u32; } HostIPv4Address; union { u_int8_t u8[6]; u_int32_t u32[2]; } MacAddress; }; /* NS offload */ #define WOW_OFFLOAD_NS_INFO_MAX 2 struct hal_wow_offload_ns_info { u_int32_t valid; u_int32_t id; u_int32_t Flags; union { u_int8_t u8[16]; u_int32_t u32[4]; } RemoteIPv6Address; union { u_int8_t u8[16]; u_int32_t u32[4]; } SolicitedNodeIPv6Address; union { u_int8_t u8[6]; u_int32_t u32[2]; } MacAddress; union { u_int8_t u8[16]; u_int32_t u32[4]; } TargetIPv6Addresses[2]; }; extern void ar9300_wowoffload_prep(struct ath_hal *ah); extern void ar9300_wowoffload_post(struct ath_hal *ah); extern u_int32_t ar9300_wowoffload_download_rekey_data(struct ath_hal *ah, u_int32_t *data, u_int32_t size); extern void ar9300_wowoffload_retrieve_data(struct ath_hal *ah, void *buf, u_int32_t param); extern void ar9300_wowoffload_download_acer_magic(struct ath_hal *ah, HAL_BOOL valid, u_int8_t* datap, u_int32_t bytes); extern void ar9300_wowoffload_download_acer_swka(struct ath_hal *ah, u_int32_t id, HAL_BOOL valid, u_int32_t period, u_int32_t size, u_int32_t* datap); extern void ar9300_wowoffload_download_arp_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data); extern void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data); #endif /* ATH_WOW_OFFLOAD */ #endif extern HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, HAL_BOOL b_channel_change, HAL_STATUS *status, int is_scan); extern HAL_BOOL ar9300_lean_channel_change(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask); extern HAL_BOOL ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type); extern void ar9300_init_pll(struct ath_hal *ah, struct ieee80211_channel *chan); extern void ar9300_green_ap_ps_on_off( struct ath_hal *ah, u_int16_t rxMask); extern u_int16_t ar9300_is_single_ant_power_save_possible(struct ath_hal *ah); extern void ar9300_set_operating_mode(struct ath_hal *ah, int opmode); extern HAL_BOOL ar9300_phy_disable(struct ath_hal *ah); extern HAL_BOOL ar9300_disable(struct ath_hal *ah); extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *); extern HAL_BOOL ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isIQdone, int is_scan, u_int32_t *sched_cals); extern void ar9300_reset_cal_valid(struct ath_hal *ah, const struct ieee80211_channel *chan, HAL_BOOL *isIQdone, u_int32_t cal_type); extern void ar9300_iq_cal_collect(struct ath_hal *ah, u_int8_t num_chains); extern void ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains); extern void ar9300_temp_comp_cal_collect(struct ath_hal *ah); extern void ar9300_temp_comp_calibration(struct ath_hal *ah, u_int8_t num_chains); extern int16_t ar9300_get_min_cca_pwr(struct ath_hal *ah); extern void ar9300_upload_noise_floor(struct ath_hal *ah, int is2G, int16_t nfarray[]); extern HAL_BOOL ar9300_set_tx_power_limit(struct ath_hal *ah, u_int32_t limit, u_int16_t extra_txpow, u_int16_t tpc_in_db); extern void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf, struct ieee80211_channel *chan, int is_scan); +extern int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time); +extern int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal); extern HAL_BOOL ar9300_load_nf(struct ath_hal *ah, int16_t nf[]); extern HAL_RFGAIN ar9300_get_rfgain(struct ath_hal *ah); extern const HAL_RATE_TABLE *ar9300_get_rate_table(struct ath_hal *, u_int mode); extern int16_t ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index, u_int8_t chainmask, u_int8_t mimo_mode); extern void ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, const struct ieee80211_channel *chan, u_int8_t powerPerRate[], u_int8_t chainmask); extern void ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, u_int8_t powerPerRate[]); extern HAL_STATUS ath_hal_get_rate_power_limit_from_eeprom(struct ath_hal *ah, u_int16_t freq, int8_t *max_rate_power, int8_t *min_rate_power); extern void ar9300_reset_tx_status_ring(struct ath_hal *ah); extern void ar9300_enable_mib_counters(struct ath_hal *); extern void ar9300_disable_mib_counters(struct ath_hal *); extern void ar9300_ani_attach(struct ath_hal *); extern void ar9300_ani_detach(struct ath_hal *); extern struct ar9300_ani_state *ar9300_ani_get_current_state(struct ath_hal *); extern struct ar9300_stats *ar9300_ani_get_current_stats(struct ath_hal *); extern HAL_BOOL ar9300_ani_control(struct ath_hal *, HAL_ANI_CMD cmd, int param); struct ath_rx_status; extern void ar9300_process_mib_intr(struct ath_hal *, const HAL_NODE_STATS *); extern void ar9300_ani_ar_poll(struct ath_hal *, const HAL_NODE_STATS *, const struct ieee80211_channel *, HAL_ANISTATS *); extern void ar9300_ani_reset(struct ath_hal *, HAL_BOOL is_scanning); extern void ar9300_ani_init_defaults(struct ath_hal *ah, HAL_HT_MACMODE macmode); extern void ar9300_enable_tpc(struct ath_hal *); extern HAL_BOOL ar9300_rf_gain_cap_apply(struct ath_hal *ah, int is2GHz); extern void ar9300_rx_gain_table_apply(struct ath_hal *ah); extern void ar9300_tx_gain_table_apply(struct ath_hal *ah); extern void ar9300_mat_enable(struct ath_hal *ah, int enable); extern void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry); extern HAL_BOOL ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal * ah, HAL_BOOL enable, const struct ieee80211_channel * chan); /* BB Panic Watchdog declarations */ #define HAL_BB_PANIC_WD_TMO 25 /* in ms, 0 to disable */ #define HAL_BB_PANIC_WD_TMO_HORNET 85 extern void ar9300_config_bb_panic_watchdog(struct ath_hal *); extern void ar9300_handle_bb_panic(struct ath_hal *); extern int ar9300_get_bb_panic_info(struct ath_hal *ah, struct hal_bb_panic_info *bb_panic); extern HAL_BOOL ar9300_handle_radar_bb_panic(struct ath_hal *ah); extern void ar9300_set_hal_reset_reason(struct ath_hal *ah, u_int8_t resetreason); /* DFS declarations */ extern void ar9300_check_dfs(struct ath_hal *ah, struct ieee80211_channel *chan); extern void ar9300_dfs_found(struct ath_hal *ah, struct ieee80211_channel *chan, u_int64_t nolTime); extern void ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); extern void ar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe); extern HAL_BOOL ar9300_radar_wait(struct ath_hal *ah, struct ieee80211_channel *chan); extern struct dfs_pulse * ar9300_get_dfs_radars(struct ath_hal *ah, u_int32_t dfsdomain, int *numradars, struct dfs_bin5pulse **bin5pulses, int *numb5radars, HAL_PHYERR_PARAM *pe); extern void ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val); extern u_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable); extern void ar9300_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL enable); extern void ar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start); extern struct ieee80211_channel * ar9300_get_extension_channel(struct ath_hal *ah); extern HAL_BOOL ar9300_is_fast_clock_enabled(struct ath_hal *ah); extern void ar9300_mark_phy_inactive(struct ath_hal *ah); /* Spectral scan declarations */ extern void ar9300_configure_spectral_scan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss); extern void ar9300_set_cca_threshold(struct ath_hal *ah, u_int8_t thresh62); extern void ar9300_get_spectral_params(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss); extern HAL_BOOL ar9300_is_spectral_active(struct ath_hal *ah); extern HAL_BOOL ar9300_is_spectral_enabled(struct ath_hal *ah); extern void ar9300_start_spectral_scan(struct ath_hal *ah); extern void ar9300_stop_spectral_scan(struct ath_hal *ah); extern u_int32_t ar9300_get_spectral_config(struct ath_hal *ah); extern void ar9300_restore_spectral_config(struct ath_hal *ah, u_int32_t restoreval); int16_t ar9300_get_ctl_chan_nf(struct ath_hal *ah); int16_t ar9300_get_ext_chan_nf(struct ath_hal *ah); /* End spectral scan declarations */ /* Raw ADC capture functions */ extern void ar9300_enable_test_addac_mode(struct ath_hal *ah); extern void ar9300_disable_test_addac_mode(struct ath_hal *ah); extern void ar9300_begin_adc_capture(struct ath_hal *ah, int auto_agc_gain); extern HAL_STATUS ar9300_retrieve_capture_data(struct ath_hal *ah, u_int16_t chain_mask, int disable_dc_filter, void *sample_buf, u_int32_t *max_samples); extern HAL_STATUS ar9300_calc_adc_ref_powers(struct ath_hal *ah, int freq_mhz, int16_t *sample_min, int16_t *sample_max, int32_t *chain_ref_pwr, int num_chain_ref_pwr); extern HAL_STATUS ar9300_get_min_agc_gain(struct ath_hal *ah, int freq_mhz, int32_t *chain_gain, int num_chain_gain); extern HAL_BOOL ar9300_reset_11n(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_BOOL b_channel_change, HAL_STATUS *status); extern void ar9300_set_coverage_class(struct ath_hal *ah, u_int8_t coverageclass, int now); extern void ar9300_get_channel_centers(struct ath_hal *ah, const struct ieee80211_channel *chan, CHAN_CENTERS *centers); extern u_int16_t ar9300_get_ctl_center(struct ath_hal *ah, const struct ieee80211_channel *chan); extern u_int16_t ar9300_get_ext_center(struct ath_hal *ah, const struct ieee80211_channel *chan); extern u_int32_t ar9300_get_mib_cycle_counts_pct(struct ath_hal *, u_int32_t*, u_int32_t*, u_int32_t*); extern void ar9300_dma_reg_dump(struct ath_hal *); extern HAL_BOOL ar9300_set_11n_rx_rifs(struct ath_hal *ah, HAL_BOOL enable); extern HAL_BOOL ar9300_set_rifs_delay(struct ath_hal *ah, HAL_BOOL enable); extern HAL_BOOL ar9300_set_smart_antenna(struct ath_hal *ah, HAL_BOOL enable); extern HAL_BOOL ar9300_detect_bb_hang(struct ath_hal *ah); extern HAL_BOOL ar9300_detect_mac_hang(struct ath_hal *ah); #ifdef ATH_BT_COEX extern void ar9300_set_bt_coex_info(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo); extern void ar9300_bt_coex_config(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf); extern void ar9300_bt_coex_set_qcu_thresh(struct ath_hal *ah, int qnum); extern void ar9300_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type); extern void ar9300_bt_coex_setup_bmiss_thresh(struct ath_hal *ah, u_int32_t thresh); extern void ar9300_bt_coex_set_parameter(struct ath_hal *ah, u_int32_t type, u_int32_t value); extern void ar9300_bt_coex_disable(struct ath_hal *ah); extern int ar9300_bt_coex_enable(struct ath_hal *ah); extern void ar9300_init_bt_coex(struct ath_hal *ah); extern u_int32_t ar9300_get_bt_active_gpio(struct ath_hal *ah, u_int32_t reg); extern u_int32_t ar9300_get_wlan_active_gpio(struct ath_hal *ah, u_int32_t reg,u_int32_t bOn); #endif extern int ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf); extern void ar9300_free_generic_timer(struct ath_hal *ah, int index); extern void ar9300_start_generic_timer(struct ath_hal *ah, int index, u_int32_t timer_next, u_int32_t timer_period); extern void ar9300_stop_generic_timer(struct ath_hal *ah, int index); extern void ar9300_get_gen_timer_interrupts(struct ath_hal *ah, u_int32_t *trigger, u_int32_t *thresh); extern void ar9300_start_tsf2(struct ath_hal *ah); extern void ar9300_chk_rssi_update_tx_pwr(struct ath_hal *ah, int rssi); extern HAL_BOOL ar9300_is_skip_paprd_by_greentx(struct ath_hal *ah); extern void ar9300_control_signals_for_green_tx_mode(struct ath_hal *ah); extern void ar9300_hwgreentx_set_pal_spare(struct ath_hal *ah, int value); extern HAL_BOOL ar9300_is_ani_noise_spur(struct ath_hal *ah); extern void ar9300_reset_hw_beacon_proc_crc(struct ath_hal *ah); extern int32_t ar9300_get_hw_beacon_rssi(struct ath_hal *ah); extern void ar9300_set_hw_beacon_rssi_threshold(struct ath_hal *ah, u_int32_t rssi_threshold); extern void ar9300_reset_hw_beacon_rssi(struct ath_hal *ah); extern void ar9300_set_hw_beacon_proc(struct ath_hal *ah, HAL_BOOL on); extern void ar9300_get_vow_stats(struct ath_hal *ah, HAL_VOWSTATS *p_stats, u_int8_t); extern int ar9300_get_spur_info(struct ath_hal * ah, int *enable, int len, u_int16_t *freq); extern int ar9300_set_spur_info(struct ath_hal * ah, int enable, int len, u_int16_t *freq); extern void ar9300_wow_set_gpio_reset_low(struct ath_hal * ah); extern HAL_BOOL ar9300_get_mib_cycle_counts(struct ath_hal *, HAL_SURVEY_SAMPLE *); extern void ar9300_clear_mib_counters(struct ath_hal *ah); /* EEPROM interface functions */ /* Common Interface functions */ extern HAL_STATUS ar9300_eeprom_attach(struct ath_hal *); extern u_int32_t ar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param); extern u_int32_t ar9300_ini_fixup(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, u_int32_t reg, u_int32_t val); extern HAL_STATUS ar9300_eeprom_set_transmit_power(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, const struct ieee80211_channel *chan, u_int16_t cfg_ctl, u_int16_t twice_antenna_reduction, u_int16_t twice_max_regulatory_power, u_int16_t power_limit); extern void ar9300_eeprom_set_addac(struct ath_hal *, struct ieee80211_channel *); extern HAL_BOOL ar9300_eeprom_set_param(struct ath_hal *ah, EEPROM_PARAM param, u_int32_t value); extern HAL_BOOL ar9300_eeprom_set_board_values(struct ath_hal *, const struct ieee80211_channel *); extern HAL_BOOL ar9300_eeprom_read_word(struct ath_hal *, u_int off, u_int16_t *data); extern HAL_BOOL ar9300_eeprom_read(struct ath_hal *ah, long address, u_int8_t *buffer, int many); extern HAL_BOOL ar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi); extern HAL_BOOL ar9300_flash_read(struct ath_hal *, u_int off, u_int16_t *data); extern HAL_BOOL ar9300_flash_write(struct ath_hal *, u_int off, u_int16_t data); extern u_int ar9300_eeprom_dump_support(struct ath_hal *ah, void **pp_e); extern u_int8_t ar9300_eeprom_get_num_ant_config(struct ath_hal_9300 *ahp, HAL_FREQ_BAND freq_band); extern HAL_STATUS ar9300_eeprom_get_ant_cfg(struct ath_hal_9300 *ahp, const struct ieee80211_channel *chan, u_int8_t index, u_int16_t *config); extern u_int8_t* ar9300_eeprom_get_cust_data(struct ath_hal_9300 *ahp); extern u_int8_t *ar9300_eeprom_get_spur_chans_ptr(struct ath_hal *ah, HAL_BOOL is_2ghz); extern HAL_BOOL ar9300_interference_is_present(struct ath_hal *ah); extern HAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah); extern void ar9300_disp_tpc_tables(struct ath_hal *ah); extern u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah); extern u_int8_t ar9300_eeprom_set_tx_gain_cap(struct ath_hal *ah, int *tx_gain_max); extern u_int8_t ar9300_eeprom_tx_gain_table_index_max_apply(struct ath_hal *ah, u_int16_t channel); /* Common EEPROM Help function */ extern void ar9300_set_immunity(struct ath_hal *ah, HAL_BOOL enable); extern void ar9300_get_hw_hangs(struct ath_hal *ah, hal_hw_hangs_t *hangs); extern u_int ar9300_mac_to_clks(struct ath_hal *ah, u_int clks); /* tx_bf interface */ #define ar9300_init_txbf(ah) #define ar9300_set_11n_txbf_sounding(ah, ds, series, cec, opt) #define ar9300_set_11n_txbf_cal(ah, ds, cal_pos, code_rate, cec, opt) #define ar9300_txbf_save_cv_from_compress( \ ah, key_idx, mimo_control, compress_rpt) \ false #define ar9300_txbf_save_cv_from_non_compress( \ ah, key_idx, mimo_control, non_compress_rpt) \ false #define ar9300_txbf_rc_update( \ ah, rx_status, local_h, csi_frame, ness_a, ness_b, bw) \ false #define ar9300_fill_csi_frame( \ ah, rx_status, bandwidth, local_h, csi_frame_body) \ 0 #define ar9300_fill_txbf_capabilities(ah) #define ar9300_get_txbf_capabilities(ah) NULL #define ar9300_txbf_set_key( \ ah, entry, rx_staggered_sounding, channel_estimation_cap, mmss) #define ar9300_read_key_cache_mac(ah, entry, mac) false #define ar9300_txbf_get_cv_cache_nr(ah, key_idx, nr) #define ar9300_set_selfgenrate_limit(ah, ts_ratecode) #define ar9300_reset_lowest_txrate(ah) #define ar9300_txbf_set_basic_set(ah) extern void ar9300_crdc_rx_notify(struct ath_hal *ah, struct ath_rx_status *rxs); extern void ar9300_chain_rssi_diff_compensation(struct ath_hal *ah); #if ATH_SUPPORT_MCI extern void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type); extern void ar9300_mci_bt_coex_disable(struct ath_hal *ah); extern int ar9300_mci_bt_coex_enable(struct ath_hal *ah); extern void ar9300_mci_setup (struct ath_hal *ah, u_int32_t gpm_addr, void *gpm_buf, u_int16_t len, u_int32_t sched_addr); extern void ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done); extern void ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done); extern void ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done); extern HAL_BOOL ar9300_mci_send_message (struct ath_hal *ah, u_int8_t header, u_int32_t flag, u_int32_t *payload, u_int8_t len, HAL_BOOL wait_done, HAL_BOOL check_bt); extern u_int32_t ar9300_mci_get_interrupt (struct ath_hal *ah, u_int32_t *mci_int, u_int32_t *mci_int_rx_msg); extern u_int32_t ar9300_mci_state (struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data); extern void ar9300_mci_reset (struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g, HAL_BOOL is_full_sleep); extern void ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah, HAL_BOOL halt, HAL_BOOL wait_done); extern void ar9300_mci_mute_bt(struct ath_hal *ah); extern u_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type, u_int8_t gpm_opcode, int32_t time_out); extern void ar9300_mci_enable_interrupt(struct ath_hal *ah); extern void ar9300_mci_disable_interrupt(struct ath_hal *ah); extern void ar9300_mci_detach (struct ath_hal *ah); extern u_int32_t ar9300_mci_check_int (struct ath_hal *ah, u_int32_t ints); extern void ar9300_mci_sync_bt_state (struct ath_hal *ah); extern void ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g); extern void ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done); #if ATH_SUPPORT_AIC extern u_int32_t ar9300_aic_calibration (struct ath_hal *ah); extern u_int32_t ar9300_aic_start_normal (struct ath_hal *ah); #endif #endif extern HAL_STATUS ar9300_set_proxy_sta(struct ath_hal *ah, HAL_BOOL enable); extern HAL_BOOL ar9300_regulatory_domain_override( struct ath_hal *ah, u_int16_t regdmn); #if ATH_ANT_DIV_COMB extern void ar9300_ant_div_comb_get_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG* div_comb_conf); extern void ar9300_ant_div_comb_set_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG* div_comb_conf); #endif /* ATH_ANT_DIV_COMB */ extern void ar9300_disable_phy_restart(struct ath_hal *ah, int disable_phy_restart); extern void ar9300_enable_keysearch_always(struct ath_hal *ah, int enable); extern HAL_BOOL ar9300ForceVCS( struct ath_hal *ah); extern HAL_BOOL ar9300SetDfs3StreamFix(struct ath_hal *ah, u_int32_t val); extern HAL_BOOL ar9300Get3StreamSignature( struct ath_hal *ah); #ifdef ATH_TX99_DIAG #ifndef ATH_SUPPORT_HTC extern void ar9300_tx99_channel_pwr_update(struct ath_hal *ah, struct ieee80211_channel *c, u_int32_t txpower); extern void ar9300_tx99_chainmsk_setup(struct ath_hal *ah, int tx_chainmask); extern void ar9300_tx99_set_single_carrier(struct ath_hal *ah, int tx_chain_mask, int chtype); extern void ar9300_tx99_start(struct ath_hal *ah, u_int8_t *data); extern void ar9300_tx99_stop(struct ath_hal *ah); #endif /* ATH_SUPPORT_HTC */ #endif /* ATH_TX99_DIAG */ +extern HAL_BOOL ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array); +extern void ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask); enum { AR9300_COEFF_TX_TYPE = 0, AR9300_COEFF_RX_TYPE }; #endif /* _ATH_AR9300_H_ */ Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (revision 278741) @@ -1,4129 +1,4148 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ar9300/ar9300desc.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300phy.h" #include "ar9300/ar9300paprd.h" #include "ar9300/ar9300_stub.h" #include "ar9300/ar9300_stub_funcs.h" /* Add static register initialization vectors */ #include "ar9300/ar9300_osprey22.ini" #include "ar9300/ar9330_11.ini" #include "ar9300/ar9330_12.ini" #include "ar9300/ar9340.ini" #include "ar9300/ar9485.ini" #include "ar9300/ar9485_1_1.ini" #include "ar9300/ar9300_jupiter10.ini" #include "ar9300/ar9300_jupiter20.ini" #include "ar9300/ar9580.ini" #include "ar9300/ar955x.ini" #include "ar9300/ar9300_aphrodite10.ini" /* Include various freebsd specific HAL methods */ #include "ar9300/ar9300_freebsd.h" /* XXX duplicate in ar9300_radio.c ? */ static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah, struct ieee80211_channel *chan); static inline HAL_STATUS ar9300_init_mac_addr(struct ath_hal *ah); static inline HAL_STATUS ar9300_hw_attach(struct ath_hal *ah); static inline void ar9300_hw_detach(struct ath_hal *ah); static int16_t ar9300_get_nf_adjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); #if 0 int ar9300_get_cal_intervals(struct ath_hal *ah, HAL_CALIBRATION_TIMER **timerp, HAL_CAL_QUERY query); #endif #if ATH_TRAFFIC_FAST_RECOVER unsigned long ar9300_get_pll3_sqsum_dvc(struct ath_hal *ah); #endif static int ar9300_init_offsets(struct ath_hal *ah, u_int16_t devid); static void ar9300_disable_pcie_phy(struct ath_hal *ah); static const HAL_PERCAL_DATA iq_cal_single_sample = {IQ_MISMATCH_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ar9300_iq_cal_collect, ar9300_iq_calibration}; #if 0 static HAL_CALIBRATION_TIMER ar9300_cals[] = { {IQ_MISMATCH_CAL, /* Cal type */ 1200000, /* Cal interval */ 0 /* Cal timestamp */ }, {TEMP_COMP_CAL, 5000, 0 }, }; #endif #if ATH_PCIE_ERROR_MONITOR int ar9300_start_pcie_error_monitor(struct ath_hal *ah, int b_auto_stop) { u_int32_t val; /* Clear the counters */ OS_REG_WRITE(ah, PCIE_CO_ERR_CTR_CTR0, 0); OS_REG_WRITE(ah, PCIE_CO_ERR_CTR_CTR1, 0); /* Read the previous value */ val = OS_REG_READ(ah, PCIE_CO_ERR_CTR_CTRL); /* Set auto_stop */ if (b_auto_stop) { val |= RCVD_ERR_CTR_AUTO_STOP | BAD_TLP_ERR_CTR_AUTO_STOP | BAD_DLLP_ERR_CTR_AUTO_STOP | RPLY_TO_ERR_CTR_AUTO_STOP | RPLY_NUM_RO_ERR_CTR_AUTO_STOP; } else { val &= ~( RCVD_ERR_CTR_AUTO_STOP | BAD_TLP_ERR_CTR_AUTO_STOP | BAD_DLLP_ERR_CTR_AUTO_STOP | RPLY_TO_ERR_CTR_AUTO_STOP | RPLY_NUM_RO_ERR_CTR_AUTO_STOP); } OS_REG_WRITE(ah, PCIE_CO_ERR_CTR_CTRL, val ); /* * Start to run. * This has to be done separately from the above auto_stop flag setting, * to avoid a HW race condition. */ val |= RCVD_ERR_CTR_RUN | BAD_TLP_ERR_CTR_RUN | BAD_DLLP_ERR_CTR_RUN | RPLY_TO_ERR_CTR_RUN | RPLY_NUM_RO_ERR_CTR_RUN; OS_REG_WRITE(ah, PCIE_CO_ERR_CTR_CTRL, val); return 0; } int ar9300_read_pcie_error_monitor(struct ath_hal *ah, void* p_read_counters) { u_int32_t val; ar_pcie_error_moniter_counters *p_counters = (ar_pcie_error_moniter_counters*) p_read_counters; val = OS_REG_READ(ah, PCIE_CO_ERR_CTR_CTR0); p_counters->uc_receiver_errors = MS(val, RCVD_ERR_MASK); p_counters->uc_bad_tlp_errors = MS(val, BAD_TLP_ERR_MASK); p_counters->uc_bad_dllp_errors = MS(val, BAD_DLLP_ERR_MASK); val = OS_REG_READ(ah, PCIE_CO_ERR_CTR_CTR1); p_counters->uc_replay_timeout_errors = MS(val, RPLY_TO_ERR_MASK); p_counters->uc_replay_number_rollover_errors= MS(val, RPLY_NUM_RO_ERR_MASK); return 0; } int ar9300_stop_pcie_error_monitor(struct ath_hal *ah) { u_int32_t val; /* Read the previous value */ val = OS_REG_READ(ah, PCIE_CO_ERR_CTR_CTRL); val &= ~( RCVD_ERR_CTR_RUN | BAD_TLP_ERR_CTR_RUN | BAD_DLLP_ERR_CTR_RUN | RPLY_TO_ERR_CTR_RUN | RPLY_NUM_RO_ERR_CTR_RUN); /* Start to stop */ OS_REG_WRITE(ah, PCIE_CO_ERR_CTR_CTRL, val ); return 0; } #endif /* ATH_PCIE_ERROR_MONITOR */ #if 0 /* WIN32 does not support C99 */ static const struct ath_hal_private ar9300hal = { { ar9300_get_rate_table, /* ah_get_rate_table */ ar9300_detach, /* ah_detach */ /* Reset Functions */ ar9300_reset, /* ah_reset */ ar9300_phy_disable, /* ah_phy_disable */ ar9300_disable, /* ah_disable */ ar9300_config_pci_power_save, /* ah_config_pci_power_save */ ar9300_set_pcu_config, /* ah_set_pcu_config */ ar9300_calibration, /* ah_per_calibration */ ar9300_reset_cal_valid, /* ah_reset_cal_valid */ ar9300_set_tx_power_limit, /* ah_set_tx_power_limit */ #if ATH_ANT_DIV_COMB ar9300_ant_ctrl_set_lna_div_use_bt_ant, /* ah_ant_ctrl_set_lna_div_use_bt_ant */ #endif /* ATH_ANT_DIV_COMB */ #ifdef ATH_SUPPORT_DFS ar9300_radar_wait, /* ah_radar_wait */ /* New DFS functions */ ar9300_check_dfs, /* ah_ar_check_dfs */ ar9300_dfs_found, /* ah_ar_dfs_found */ ar9300_enable_dfs, /* ah_ar_enable_dfs */ ar9300_get_dfs_thresh, /* ah_ar_get_dfs_thresh */ ar9300_get_dfs_radars, /* ah_ar_get_dfs_radars */ ar9300_adjust_difs, /* ah_adjust_difs */ ar9300_dfs_config_fft, /* ah_dfs_config_fft */ ar9300_dfs_cac_war, /* ah_dfs_cac_war */ ar9300_cac_tx_quiet, /* ah_cac_tx_quiet */ #endif ar9300_get_extension_channel, /* ah_get_extension_channel */ ar9300_is_fast_clock_enabled, /* ah_is_fast_clock_enabled */ /* Transmit functions */ ar9300_update_tx_trig_level, /* ah_update_tx_trig_level */ ar9300_get_tx_trig_level, /* ah_get_tx_trig_level */ ar9300_setup_tx_queue, /* ah_setup_tx_queue */ ar9300_set_tx_queue_props, /* ah_set_tx_queue_props */ ar9300_get_tx_queue_props, /* ah_get_tx_queue_props */ ar9300_release_tx_queue, /* ah_release_tx_queue */ ar9300_reset_tx_queue, /* ah_reset_tx_queue */ ar9300_get_tx_dp, /* ah_get_tx_dp */ ar9300_set_tx_dp, /* ah_set_tx_dp */ ar9300_num_tx_pending, /* ah_num_tx_pending */ ar9300_start_tx_dma, /* ah_start_tx_dma */ ar9300_stop_tx_dma, /* ah_stop_tx_dma */ ar9300_stop_tx_dma_indv_que, /* ah_stop_tx_dma_indv_que */ ar9300_abort_tx_dma, /* ah_abort_tx_dma */ ar9300_fill_tx_desc, /* ah_fill_tx_desc */ ar9300_set_desc_link, /* ah_set_desc_link */ ar9300_get_desc_link_ptr, /* ah_get_desc_link_ptr */ ar9300_clear_tx_desc_status, /* ah_clear_tx_desc_status */ #ifdef ATH_SWRETRY ar9300_clear_dest_mask, /* ah_clear_dest_mask */ #endif ar9300_proc_tx_desc, /* ah_proc_tx_desc */ ar9300_get_raw_tx_desc, /* ah_get_raw_tx_desc */ ar9300_get_tx_rate_code, /* ah_get_tx_rate_code */ AH_NULL, /* ah_get_tx_intr_queue */ ar9300_tx_req_intr_desc, /* ah_req_tx_intr_desc */ ar9300_calc_tx_airtime, /* ah_calc_tx_airtime */ ar9300_setup_tx_status_ring, /* ah_setup_tx_status_ring */ /* RX Functions */ ar9300_get_rx_dp, /* ah_get_rx_dp */ ar9300_set_rx_dp, /* ah_set_rx_dp */ ar9300_enable_receive, /* ah_enable_receive */ ar9300_stop_dma_receive, /* ah_stop_dma_receive */ ar9300_start_pcu_receive, /* ah_start_pcu_receive */ ar9300_stop_pcu_receive, /* ah_stop_pcu_receive */ ar9300_set_multicast_filter, /* ah_set_multicast_filter */ ar9300_get_rx_filter, /* ah_get_rx_filter */ ar9300_set_rx_filter, /* ah_set_rx_filter */ ar9300_set_rx_sel_evm, /* ah_set_rx_sel_evm */ ar9300_set_rx_abort, /* ah_set_rx_abort */ AH_NULL, /* ah_setup_rx_desc */ ar9300_proc_rx_desc, /* ah_proc_rx_desc */ ar9300_get_rx_key_idx, /* ah_get_rx_key_idx */ ar9300_proc_rx_desc_fast, /* ah_proc_rx_desc_fast */ ar9300_ani_ar_poll, /* ah_rx_monitor */ ar9300_process_mib_intr, /* ah_proc_mib_event */ /* Misc Functions */ ar9300_get_capability, /* ah_get_capability */ ar9300_set_capability, /* ah_set_capability */ ar9300_get_diag_state, /* ah_get_diag_state */ ar9300_get_mac_address, /* ah_get_mac_address */ ar9300_set_mac_address, /* ah_set_mac_address */ ar9300_get_bss_id_mask, /* ah_get_bss_id_mask */ ar9300_set_bss_id_mask, /* ah_set_bss_id_mask */ ar9300_set_regulatory_domain, /* ah_set_regulatory_domain */ ar9300_set_led_state, /* ah_set_led_state */ ar9300_set_power_led_state, /* ah_setpowerledstate */ ar9300_set_network_led_state, /* ah_setnetworkledstate */ ar9300_write_associd, /* ah_write_associd */ ar9300_force_tsf_sync, /* ah_force_tsf_sync */ ar9300_gpio_cfg_input, /* ah_gpio_cfg_input */ ar9300_gpio_cfg_output, /* ah_gpio_cfg_output */ ar9300_gpio_cfg_output_led_off, /* ah_gpio_cfg_output_led_off */ ar9300_gpio_get, /* ah_gpio_get */ ar9300_gpio_set, /* ah_gpio_set */ ar9300_gpio_get_intr, /* ah_gpio_get_intr */ ar9300_gpio_set_intr, /* ah_gpio_set_intr */ ar9300_gpio_get_polarity, /* ah_gpio_get_polarity */ ar9300_gpio_set_polarity, /* ah_gpio_set_polarity */ ar9300_gpio_get_mask, /* ah_gpio_get_mask */ ar9300_gpio_set_mask, /* ah_gpio_set_mask */ ar9300_get_tsf32, /* ah_get_tsf32 */ ar9300_get_tsf64, /* ah_get_tsf64 */ ar9300_get_tsf2_32, /* ah_get_tsf2_32 */ ar9300_reset_tsf, /* ah_reset_tsf */ ar9300_detect_card_present, /* ah_detect_card_present */ ar9300_update_mib_mac_stats, /* ah_update_mib_mac_stats */ ar9300_get_mib_mac_stats, /* ah_get_mib_mac_stats */ ar9300_get_rfgain, /* ah_get_rf_gain */ ar9300_get_def_antenna, /* ah_get_def_antenna */ ar9300_set_def_antenna, /* ah_set_def_antenna */ ar9300_set_slot_time, /* ah_set_slot_time */ ar9300_set_ack_timeout, /* ah_set_ack_timeout */ ar9300_get_ack_timeout, /* ah_get_ack_timeout */ ar9300_set_coverage_class, /* ah_set_coverage_class */ ar9300_set_quiet, /* ah_set_quiet */ ar9300_set_antenna_switch, /* ah_set_antenna_switch */ ar9300_get_desc_info, /* ah_get_desc_info */ ar9300_select_ant_config, /* ah_select_ant_config */ ar9300_ant_ctrl_common_get, /* ah_ant_ctrl_common_get */ + ar9300_ant_swcom_sel, /* ah_ant_swcom_sel */ ar9300_enable_tpc, /* ah_enable_tpc */ AH_NULL, /* ah_olpc_temp_compensation */ #if ATH_SUPPORT_CRDC ar9300_chain_rssi_diff_compensation,/*ah_chain_rssi_diff_compensation*/ #endif ar9300_disable_phy_restart, /* ah_disable_phy_restart */ ar9300_enable_keysearch_always, ar9300_interference_is_present, /* ah_interference_is_present */ ar9300_disp_tpc_tables, /* ah_disp_tpc_tables */ ar9300_get_tpc_tables, /* ah_get_tpc_tables */ /* Key Cache Functions */ ar9300_get_key_cache_size, /* ah_get_key_cache_size */ ar9300_reset_key_cache_entry, /* ah_reset_key_cache_entry */ ar9300_is_key_cache_entry_valid, /* ah_is_key_cache_entry_valid */ ar9300_set_key_cache_entry, /* ah_set_key_cache_entry */ ar9300_set_key_cache_entry_mac, /* ah_set_key_cache_entry_mac */ ar9300_print_keycache, /* ah_print_key_cache */ - +#if ATH_SUPPORT_KEYPLUMB_WAR + ar9300_check_key_cache_entry, /* ah_check_key_cache_entry */ +#endif /* Power Management Functions */ ar9300_set_power_mode, /* ah_set_power_mode */ ar9300_set_sm_power_mode, /* ah_set_sm_ps_mode */ #if ATH_WOW ar9300_wow_apply_pattern, /* ah_wow_apply_pattern */ ar9300_wow_enable, /* ah_wow_enable */ ar9300_wow_wake_up, /* ah_wow_wake_up */ #if ATH_WOW_OFFLOAD ar9300_wowoffload_prep, /* ah_wow_offload_prep */ ar9300_wowoffload_post, /* ah_wow_offload_post */ ar9300_wowoffload_download_rekey_data, /* ah_wow_offload_download_rekey_data */ ar9300_wowoffload_retrieve_data, /* ah_wow_offload_retrieve_data */ ar9300_wowoffload_download_acer_magic, /* ah_wow_offload_download_acer_magic */ ar9300_wowoffload_download_acer_swka, /* ah_wow_offload_download_acer_swka */ ar9300_wowoffload_download_arp_info, /* ah_wow_offload_download_arp_info */ ar9300_wowoffload_download_ns_info, /* ah_wow_offload_download_ns_info */ #endif /* ATH_WOW_OFFLOAD */ #endif /* Get Channel Noise */ ath_hal_get_chan_noise, /* ah_get_chan_noise */ ar9300_chain_noise_floor, /* ah_get_chain_noise_floor */ + ar9300_get_nf_from_reg, /* ah_get_nf_from_reg */ + ar9300_get_rx_nf_offset, /* ah_get_rx_nf_offset */ /* Beacon Functions */ ar9300_beacon_init, /* ah_beacon_init */ ar9300_set_sta_beacon_timers, /* ah_set_station_beacon_timers */ /* Interrupt Functions */ ar9300_is_interrupt_pending, /* ah_is_interrupt_pending */ ar9300_get_pending_interrupts, /* ah_get_pending_interrupts */ ar9300_get_interrupts, /* ah_get_interrupts */ ar9300_set_interrupts, /* ah_set_interrupts */ ar9300_set_intr_mitigation_timer, /* ah_set_intr_mitigation_timer */ ar9300_get_intr_mitigation_timer, /* ah_get_intr_mitigation_timer */ ar9300ForceVCS, ar9300SetDfs3StreamFix, ar9300Get3StreamSignature, /* 11n specific functions (NOT applicable to ar9300) */ ar9300_set_11n_tx_desc, /* ah_set_11n_tx_desc */ /* Update rxchain */ ar9300_set_rx_chainmask, /*ah_set_rx_chainmask*/ /*Updating locationing register */ ar9300_update_loc_ctl_reg, /*ah_update_loc_ctl_reg*/ /* Start PAPRD functions */ ar9300_set_paprd_tx_desc, /* ah_set_paprd_tx_desc */ ar9300_paprd_init_table, /* ah_paprd_init_table */ ar9300_paprd_setup_gain_table, /* ah_paprd_setup_gain_table */ ar9300_paprd_create_curve, /* ah_paprd_create_curve */ ar9300_paprd_is_done, /* ah_paprd_is_done */ ar9300_enable_paprd, /* ah_PAPRDEnable */ ar9300_populate_paprd_single_table,/* ah_paprd_populate_table */ ar9300_is_tx_done, /* ah_is_tx_done */ ar9300_paprd_dec_tx_pwr, /* ah_paprd_dec_tx_pwr*/ ar9300_paprd_thermal_send, /* ah_paprd_thermal_send */ /* End PAPRD functions */ ar9300_set_11n_rate_scenario, /* ah_set_11n_rate_scenario */ ar9300_set_11n_aggr_first, /* ah_set_11n_aggr_first */ ar9300_set_11n_aggr_middle, /* ah_set_11n_aggr_middle */ ar9300_set_11n_aggr_last, /* ah_set_11n_aggr_last */ ar9300_clr_11n_aggr, /* ah_clr_11n_aggr */ ar9300_set_11n_rifs_burst_middle, /* ah_set_11n_rifs_burst_middle */ ar9300_set_11n_rifs_burst_last, /* ah_set_11n_rifs_burst_last */ ar9300_clr_11n_rifs_burst, /* ah_clr_11n_rifs_burst */ ar9300_set_11n_aggr_rifs_burst, /* ah_set_11n_aggr_rifs_burst */ ar9300_set_11n_rx_rifs, /* ah_set_11n_rx_rifs */ ar9300_set_smart_antenna, /* ah_setSmartAntenna */ ar9300_detect_bb_hang, /* ah_detect_bb_hang */ ar9300_detect_mac_hang, /* ah_detect_mac_hang */ ar9300_set_immunity, /* ah_immunity */ ar9300_get_hw_hangs, /* ah_get_hang_types */ ar9300_set_11n_burst_duration, /* ah_set_11n_burst_duration */ ar9300_set_11n_virtual_more_frag, /* ah_set_11n_virtual_more_frag */ ar9300_get_11n_ext_busy, /* ah_get_11n_ext_busy */ ar9300_set_11n_mac2040, /* ah_set_11n_mac2040 */ ar9300_get_11n_rx_clear, /* ah_get_11n_rx_clear */ ar9300_set_11n_rx_clear, /* ah_set_11n_rx_clear */ ar9300_get_mib_cycle_counts_pct, /* ah_get_mib_cycle_counts_pct */ ar9300_dma_reg_dump, /* ah_dma_reg_dump */ /* force_ppm specific functions */ ar9300_ppm_get_rssi_dump, /* ah_ppm_get_rssi_dump */ ar9300_ppm_arm_trigger, /* ah_ppm_arm_trigger */ ar9300_ppm_get_trigger, /* ah_ppm_get_trigger */ ar9300_ppm_force, /* ah_ppm_force */ ar9300_ppm_un_force, /* ah_ppm_un_force */ ar9300_ppm_get_force_state, /* ah_ppm_get_force_state */ ar9300_get_spur_info, /* ah_get_spur_info */ ar9300_set_spur_info, /* ah_get_spur_info */ ar9300_get_min_cca_pwr, /* ah_ar_get_noise_floor_val */ ar9300_green_ap_ps_on_off, /* ah_set_rx_green_ap_ps_on_off */ ar9300_is_single_ant_power_save_possible, /* ah_is_single_ant_power_save_possible */ /* radio measurement specific functions */ ar9300_get_mib_cycle_counts, /* ah_get_mib_cycle_counts */ ar9300_get_vow_stats, /* ah_get_vow_stats */ ar9300_clear_mib_counters, /* ah_clear_mib_counters */ #if ATH_GEN_RANDOMNESS ar9300_get_rssi_chain0, /* ah_get_rssi_chain0 */ #endif #ifdef ATH_BT_COEX /* Bluetooth Coexistence functions */ ar9300_set_bt_coex_info, /* ah_set_bt_coex_info */ ar9300_bt_coex_config, /* ah_bt_coex_config */ ar9300_bt_coex_set_qcu_thresh, /* ah_bt_coex_set_qcu_thresh */ ar9300_bt_coex_set_weights, /* ah_bt_coex_set_weights */ ar9300_bt_coex_setup_bmiss_thresh, /* ah_bt_coex_set_bmiss_thresh */ ar9300_bt_coex_set_parameter, /* ah_bt_coex_set_parameter */ ar9300_bt_coex_disable, /* ah_bt_coex_disable */ ar9300_bt_coex_enable, /* ah_bt_coex_enable */ ar9300_get_bt_active_gpio, /* ah_bt_coex_info*/ ar9300_get_wlan_active_gpio, /* ah__coex_wlan_info*/ #endif /* Generic Timer functions */ ar9300_alloc_generic_timer, /* ah_gentimer_alloc */ ar9300_free_generic_timer, /* ah_gentimer_free */ ar9300_start_generic_timer, /* ah_gentimer_start */ ar9300_stop_generic_timer, /* ah_gentimer_stop */ ar9300_get_gen_timer_interrupts, /* ah_gentimer_get_intr */ ar9300_set_dcs_mode, /* ah_set_dcs_mode */ ar9300_get_dcs_mode, /* ah_get_dcs_mode */ #if ATH_ANT_DIV_COMB ar9300_ant_div_comb_get_config, /* ah_get_ant_dvi_comb_conf */ ar9300_ant_div_comb_set_config, /* ah_set_ant_dvi_comb_conf */ #endif ar9300_get_bb_panic_info, /* ah_get_bb_panic_info */ ar9300_handle_radar_bb_panic, /* ah_handle_radar_bb_panic */ ar9300_set_hal_reset_reason, /* ah_set_hal_reset_reason */ #if ATH_PCIE_ERROR_MONITOR ar9300_start_pcie_error_monitor, /* ah_start_pcie_error_monitor */ ar9300_read_pcie_error_monitor, /* ah_read_pcie_error_monitor*/ ar9300_stop_pcie_error_monitor, /* ah_stop_pcie_error_monitor*/ #endif /* ATH_PCIE_ERROR_MONITOR */ #if ATH_SUPPORT_SPECTRAL /* Spectral scan */ ar9300_configure_spectral_scan, /* ah_ar_configure_spectral */ ar9300_get_spectral_params, /* ah_ar_get_spectral_config */ ar9300_start_spectral_scan, /* ah_ar_start_spectral_scan */ ar9300_stop_spectral_scan, /* ah_ar_stop_spectral_scan */ ar9300_is_spectral_enabled, /* ah_ar_is_spectral_enabled */ ar9300_is_spectral_active, /* ah_ar_is_spectral_active */ ar9300_get_ctl_chan_nf, /* ah_ar_get_ctl_nf */ ar9300_get_ext_chan_nf, /* ah_ar_get_ext_nf */ #endif /* ATH_SUPPORT_SPECTRAL */ ar9300_promisc_mode, /* ah_promisc_mode */ ar9300_read_pktlog_reg, /* ah_read_pktlog_reg */ ar9300_write_pktlog_reg, /* ah_write_pktlog_reg */ ar9300_set_proxy_sta, /* ah_set_proxy_sta */ ar9300_get_cal_intervals, /* ah_get_cal_intervals */ #if ATH_TRAFFIC_FAST_RECOVER ar9300_get_pll3_sqsum_dvc, /* ah_get_pll3_sqsum_dvc */ #endif #ifdef ATH_SUPPORT_HTC AH_NULL, #endif #ifdef ATH_TX99_DIAG /* Tx99 functions */ #ifdef ATH_SUPPORT_HTC AH_NULL, AH_NULL, AH_NULL, AH_NULL, AH_NULL, AH_NULL, AH_NULL, #else AH_NULL, AH_NULL, - ar9300TX99TgtChannelPwrUpdate, /* ah_tx99channelpwrupdate */ - ar9300TX99TgtStart, /* ah_tx99start */ - ar9300TX99TgtStop, /* ah_tx99stop */ - ar9300TX99TgtChainmskSetup, /* ah_tx99_chainmsk_setup */ - ar9300TX99SetSingleCarrier, /* ah_tx99_set_single_carrier */ + ar9300_tx99_channel_pwr_update, /* ah_tx99channelpwrupdate */ + ar9300_tx99_start, /* ah_tx99start */ + ar9300_tx99_stop, /* ah_tx99stop */ + ar9300_tx99_chainmsk_setup, /* ah_tx99_chainmsk_setup */ + ar9300_tx99_set_single_carrier, /* ah_tx99_set_single_carrier */ #endif #endif ar9300_chk_rssi_update_tx_pwr, ar9300_is_skip_paprd_by_greentx, /* ah_is_skip_paprd_by_greentx */ ar9300_hwgreentx_set_pal_spare, /* ah_hwgreentx_set_pal_spare */ #if ATH_SUPPORT_MCI /* MCI Coexistence Functions */ ar9300_mci_setup, /* ah_mci_setup */ ar9300_mci_send_message, /* ah_mci_send_message */ ar9300_mci_get_interrupt, /* ah_mci_get_interrupt */ ar9300_mci_state, /* ah_mci_state */ ar9300_mci_detach, /* ah_mci_detach */ #endif ar9300_reset_hw_beacon_proc_crc, /* ah_reset_hw_beacon_proc_crc */ ar9300_get_hw_beacon_rssi, /* ah_get_hw_beacon_rssi */ ar9300_set_hw_beacon_rssi_threshold,/*ah_set_hw_beacon_rssi_threshold*/ ar9300_reset_hw_beacon_rssi, /* ah_reset_hw_beacon_rssi */ ar9300_mat_enable, /* ah_mat_enable */ ar9300_dump_keycache, /* ah_dump_keycache */ ar9300_is_ani_noise_spur, /* ah_is_ani_noise_spur */ ar9300_set_hw_beacon_proc, /* ah_set_hw_beacon_proc */ + ar9300_set_ctl_pwr, /* ah_set_ctl_pwr */ + ar9300_set_txchainmaskopt, /* ah_set_txchainmaskopt */ }, ar9300_get_channel_edges, /* ah_get_channel_edges */ ar9300_get_wireless_modes, /* ah_get_wireless_modes */ ar9300_eeprom_read_word, /* ah_eeprom_read */ AH_NULL, ar9300_eeprom_dump_support, /* ah_eeprom_dump */ ar9300_get_chip_power_limits, /* ah_get_chip_power_limits */ ar9300_get_nf_adjust, /* ah_get_nf_adjust */ /* rest is zero'd by compiler */ }; #endif /* * Read MAC version/revision information from Chip registers and initialize * local data structures. */ void ar9300_read_revisions(struct ath_hal *ah) { u_int32_t val; /* XXX verify if this is the correct way to read revision on Osprey */ /* new SREV format for Sowl and later */ val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_SREV)); if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9340) { /* XXX: AR_SREV register in Wasp reads 0 */ AH_PRIVATE(ah)->ah_macVersion = AR_SREV_VERSION_WASP; } else if(AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_QCA955X) { /* XXX: AR_SREV register in Scorpion reads 0 */ AH_PRIVATE(ah)->ah_macVersion = AR_SREV_VERSION_SCORPION; } else { /* * Include 6-bit Chip Type (masked to 0) * to differentiate from pre-Sowl versions */ AH_PRIVATE(ah)->ah_macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; } #ifdef AH_SUPPORT_HORNET /* * EV74984, due to Hornet 1.1 didn't update WMAC revision, * so that have to read SoC's revision ID instead */ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_HORNET) { #define AR_SOC_RST_REVISION_ID 0xB8060090 #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) if ((REG_READ(AR_SOC_RST_REVISION_ID) & AR_SREV_REVISION_HORNET_11_MASK) == AR_SREV_REVISION_HORNET_11) { AH_PRIVATE(ah)->ah_macRev = AR_SREV_REVISION_HORNET_11; } else { AH_PRIVATE(ah)->ah_macRev = MS(val, AR_SREV_REVISION2); } #undef REG_READ #undef AR_SOC_RST_REVISION_ID } else #endif if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_WASP) { #define AR_SOC_RST_REVISION_ID 0xB8060090 #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) AH_PRIVATE(ah)->ah_macRev = REG_READ(AR_SOC_RST_REVISION_ID) & AR_SREV_REVISION_WASP_MASK; #undef REG_READ #undef AR_SOC_RST_REVISION_ID } else AH_PRIVATE(ah)->ah_macRev = MS(val, AR_SREV_REVISION2); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { AH_PRIVATE(ah)->ah_ispcie = AH_TRUE; } else { AH_PRIVATE(ah)->ah_ispcie = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; } } /* * Attach for an AR9300 part. */ struct ath_hal * ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { struct ath_hal_9300 *ahp; struct ath_hal *ah; struct ath_hal_private *ahpriv; HAL_STATUS ecode; HAL_NO_INTERSPERSED_READS; /* NB: memory is returned zero'd */ ahp = ar9300_new_state(devid, sc, st, sh, eepromdata, ah_config, status); if (ahp == AH_NULL) { return AH_NULL; } ah = &ahp->ah_priv.h; ar9300_init_offsets(ah, devid); ahpriv = AH_PRIVATE(ah); // AH_PRIVATE(ah)->ah_bustype = bustype; /* FreeBSD: to make OTP work for now, provide this.. */ AH9300(ah)->ah_cal_mem = ath_hal_malloc(HOST_CALDATA_SIZE); if (AH9300(ah)->ah_cal_mem == NULL) { ath_hal_printf(ah, "%s: caldata malloc failed!\n", __func__); ecode = HAL_EIO; goto bad; } /* * If eepromdata is not NULL, copy it it into ah_cal_mem. */ if (eepromdata != NULL) OS_MEMCPY(AH9300(ah)->ah_cal_mem, eepromdata, HOST_CALDATA_SIZE); /* XXX FreeBSD: enable RX mitigation */ ah->ah_config.ath_hal_intr_mitigation_rx = 1; /* interrupt mitigation */ #ifdef AR5416_INT_MITIGATION if (ah->ah_config.ath_hal_intr_mitigation_rx != 0) { ahp->ah_intr_mitigation_rx = AH_TRUE; } #else /* Enable Rx mitigation (default) */ ahp->ah_intr_mitigation_rx = AH_TRUE; ah->ah_config.ath_hal_intr_mitigation_rx = 1; #endif #ifdef HOST_OFFLOAD /* Reset default Rx mitigation values for Hornet */ if (AR_SREV_HORNET(ah)) { ahp->ah_intr_mitigation_rx = AH_FALSE; #ifdef AR5416_INT_MITIGATION ah->ah_config.ath_hal_intr_mitigation_rx = 0; #endif } #endif if (ah->ah_config.ath_hal_intr_mitigation_tx != 0) { ahp->ah_intr_mitigation_tx = AH_TRUE; } /* * Read back AR_WA into a permanent copy and set bits 14 and 17. * We need to do this to avoid RMW of this register. * Do this before calling ar9300_set_reset_reg. * If not, the AR_WA register which was inited via EEPROM * will get wiped out. */ ahp->ah_wa_reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_WA)); /* Set Bits 14 and 17 in the AR_WA register. */ ahp->ah_wa_reg_val |= AR_WA_D3_TO_L1_DISABLE | AR_WA_ASPM_TIMER_BASED_DISABLE; if (!ar9300_set_reset_reg(ah, HAL_RESET_POWER_ON)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: couldn't reset chip\n", __func__); ecode = HAL_EIO; goto bad; } if (AR_SREV_JUPITER(ah) #if ATH_WOW_OFFLOAD && !HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SET_4004_BIT14) #endif ) { /* Jupiter doesn't need bit 14 to be set. */ ahp->ah_wa_reg_val &= ~AR_WA_D3_TO_L1_DISABLE; OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val); } #if ATH_SUPPORT_MCI if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { #if 0 ah->ah_bt_coex_set_weights = ar9300_mci_bt_coex_set_weights; ah->ah_bt_coex_disable = ar9300_mci_bt_coex_disable; ah->ah_bt_coex_enable = ar9300_mci_bt_coex_enable; #endif ahp->ah_mci_ready = AH_FALSE; ahp->ah_mci_bt_state = MCI_BT_SLEEP; ahp->ah_mci_coex_major_version_wlan = MCI_GPM_COEX_MAJOR_VERSION_WLAN; ahp->ah_mci_coex_minor_version_wlan = MCI_GPM_COEX_MINOR_VERSION_WLAN; ahp->ah_mci_coex_major_version_bt = MCI_GPM_COEX_MAJOR_VERSION_DEFAULT; ahp->ah_mci_coex_minor_version_bt = MCI_GPM_COEX_MINOR_VERSION_DEFAULT; ahp->ah_mci_coex_bt_version_known = AH_FALSE; ahp->ah_mci_coex_2g5g_update = AH_TRUE; /* track if 2g5g status sent */ /* will be updated before boot up sequence */ ahp->ah_mci_coex_is_2g = AH_TRUE; ahp->ah_mci_coex_wlan_channels_update = AH_FALSE; ahp->ah_mci_coex_wlan_channels[0] = 0x00000000; ahp->ah_mci_coex_wlan_channels[1] = 0xffffffff; ahp->ah_mci_coex_wlan_channels[2] = 0xffffffff; ahp->ah_mci_coex_wlan_channels[3] = 0x7fffffff; ahp->ah_mci_query_bt = AH_TRUE; /* In case WLAN start after BT */ ahp->ah_mci_unhalt_bt_gpm = AH_TRUE; /* Send UNHALT at beginning */ ahp->ah_mci_halted_bt_gpm = AH_FALSE; /* Allow first HALT */ ahp->ah_mci_need_flush_btinfo = AH_FALSE; ahp->ah_mci_wlan_cal_seq = 0; ahp->ah_mci_wlan_cal_done = 0; } #endif /* ATH_SUPPORT_MCI */ #if ATH_WOW_OFFLOAD ahp->ah_mcast_filter_l32_set = 0; ahp->ah_mcast_filter_u32_set = 0; #endif if (AR_SREV_HORNET(ah)) { #ifdef AH_SUPPORT_HORNET if (!AR_SREV_HORNET_11(ah)) { /* * Do not check bootstrap register, which cannot be trusted * due to s26 switch issue on CUS164/AP121. */ ahp->clk_25mhz = 1; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 25MHz\n"); } else { /* check bootstrap clock setting */ #define AR_SOC_SEL_25M_40M 0xB80600AC #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val); #define REG_READ(_reg) (*((volatile u_int32_t *)(_reg))) if (REG_READ(AR_SOC_SEL_25M_40M) & 0x1) { ahp->clk_25mhz = 0; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 40MHz\n"); } else { ahp->clk_25mhz = 1; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 25MHz\n"); } #undef REG_READ #undef REG_WRITE #undef AR_SOC_SEL_25M_40M } #endif /* AH_SUPPORT_HORNET */ } if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { /* check bootstrap clock setting */ #define AR9340_SOC_SEL_25M_40M 0xB80600B0 #define AR9340_REF_CLK_40 (1 << 4) /* 0 - 25MHz 1 - 40 MHz */ #define REG_READ(_reg) (*((volatile u_int32_t *)(_reg))) if (REG_READ(AR9340_SOC_SEL_25M_40M) & AR9340_REF_CLK_40) { ahp->clk_25mhz = 0; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 40MHz\n"); } else { ahp->clk_25mhz = 1; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 25MHz\n"); } #undef REG_READ #undef AR9340_SOC_SEL_25M_40M #undef AR9340_REF_CLK_40 } ar9300_init_pll(ah, AH_NULL); if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: couldn't wakeup chip\n", __func__); ecode = HAL_EIO; goto bad; } /* No serialization of Register Accesses needed. */ ah->ah_config.ah_serialise_reg_war = SER_REG_MODE_OFF; HALDEBUG(ah, HAL_DEBUG_RESET, "%s: ah_serialise_reg_war is %d\n", __func__, ah->ah_config.ah_serialise_reg_war); /* * Add mac revision check when needed. * - Osprey 1.0 and 2.0 no longer supported. */ if (((ahpriv->ah_macVersion == AR_SREV_VERSION_OSPREY) && (ahpriv->ah_macRev <= AR_SREV_REVISION_OSPREY_20)) || (ahpriv->ah_macVersion != AR_SREV_VERSION_OSPREY && ahpriv->ah_macVersion != AR_SREV_VERSION_WASP && ahpriv->ah_macVersion != AR_SREV_VERSION_HORNET && ahpriv->ah_macVersion != AR_SREV_VERSION_POSEIDON && ahpriv->ah_macVersion != AR_SREV_VERSION_SCORPION && ahpriv->ah_macVersion != AR_SREV_VERSION_JUPITER && ahpriv->ah_macVersion != AR_SREV_VERSION_APHRODITE) ) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Mac Chip Rev 0x%02x.%x is not supported by this driver\n", __func__, ahpriv->ah_macVersion, ahpriv->ah_macRev); ecode = HAL_ENOTSUPP; goto bad; } AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); /* Setup supported calibrations */ ahp->ah_iq_cal_data.cal_data = &iq_cal_single_sample; ahp->ah_supp_cals = IQ_MISMATCH_CAL; /* Enable ANI */ ahp->ah_ani_function = HAL_ANI_ALL; /* Enable RIFS */ ahp->ah_rifs_enabled = AH_TRUE; + + /* by default, stop RX also in abort txdma, due to + "Unable to stop TxDMA" msg observed */ + ahp->ah_abort_txdma_norx = AH_TRUE; + + /* do not use optional tx chainmask by default */ + ahp->ah_tx_chainmaskopt = 0; + + ahp->ah_skip_rx_iq_cal = AH_FALSE; + ahp->ah_rx_cal_complete = AH_FALSE; + ahp->ah_rx_cal_chan = 0; + ahp->ah_rx_cal_chan_flag = 0; HALDEBUG(ah, HAL_DEBUG_RESET, "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__, ahpriv->ah_macVersion, ahpriv->ah_macRev); if (AR_SREV_HORNET_12(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9331_hornet1_2_mac_core, ARRAY_LENGTH(ar9331_hornet1_2_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9331_hornet1_2_mac_postamble, ARRAY_LENGTH(ar9331_hornet1_2_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9331_hornet1_2_baseband_core, ARRAY_LENGTH(ar9331_hornet1_2_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9331_hornet1_2_baseband_postamble, ARRAY_LENGTH(ar9331_hornet1_2_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9331_hornet1_2_radio_core, ARRAY_LENGTH(ar9331_hornet1_2_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], NULL, 0, 0); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9331_hornet1_2_soc_preamble, ARRAY_LENGTH(ar9331_hornet1_2_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9331_hornet1_2_soc_postamble, ARRAY_LENGTH(ar9331_hornet1_2_soc_postamble), 2); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_rx_gain_hornet1_2, ARRAY_LENGTH(ar9331_common_rx_gain_hornet1_2), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_lowest_ob_db_tx_gain_hornet1_2, ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_2), 5); ah->ah_config.ath_hal_pcie_power_save_enable = 0; /* Japan 2484Mhz CCK settings */ INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9331_hornet1_2_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9331_hornet1_2_baseband_core_txfir_coeff_japan_2484), 2); #if 0 /* ATH_WOW */ /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_awow, ARRAY_LENGTH(ar9300_pcie_phy_awow), 2); #endif /* additional clock settings */ if (AH9300(ah)->clk_25mhz) { INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9331_hornet1_2_xtal_25M, ARRAY_LENGTH(ar9331_hornet1_2_xtal_25M), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9331_hornet1_2_xtal_40M, ARRAY_LENGTH(ar9331_hornet1_2_xtal_40M), 2); } } else if (AR_SREV_HORNET_11(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9331_hornet1_1_mac_core, ARRAY_LENGTH(ar9331_hornet1_1_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9331_hornet1_1_mac_postamble, ARRAY_LENGTH(ar9331_hornet1_1_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9331_hornet1_1_baseband_core, ARRAY_LENGTH(ar9331_hornet1_1_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9331_hornet1_1_baseband_postamble, ARRAY_LENGTH(ar9331_hornet1_1_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9331_hornet1_1_radio_core, ARRAY_LENGTH(ar9331_hornet1_1_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], NULL, 0, 0); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9331_hornet1_1_soc_preamble, ARRAY_LENGTH(ar9331_hornet1_1_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9331_hornet1_1_soc_postamble, ARRAY_LENGTH(ar9331_hornet1_1_soc_postamble), 2); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_rx_gain_hornet1_1, ARRAY_LENGTH(ar9331_common_rx_gain_hornet1_1), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_lowest_ob_db_tx_gain_hornet1_1, ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_1), 5); ah->ah_config.ath_hal_pcie_power_save_enable = 0; /* Japan 2484Mhz CCK settings */ INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9331_hornet1_1_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9331_hornet1_1_baseband_core_txfir_coeff_japan_2484), 2); #if 0 /* ATH_WOW */ /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_awow, N(ar9300_pcie_phy_awow), 2); #endif /* additional clock settings */ if (AH9300(ah)->clk_25mhz) { INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9331_hornet1_1_xtal_25M, ARRAY_LENGTH(ar9331_hornet1_1_xtal_25M), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9331_hornet1_1_xtal_40M, ARRAY_LENGTH(ar9331_hornet1_1_xtal_40M), 2); } } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9485_poseidon1_1_mac_core, ARRAY_LENGTH( ar9485_poseidon1_1_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9485_poseidon1_1_mac_postamble, ARRAY_LENGTH(ar9485_poseidon1_1_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], ar9485_poseidon1_1, ARRAY_LENGTH(ar9485_poseidon1_1), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9485_poseidon1_1_baseband_core, ARRAY_LENGTH(ar9485_poseidon1_1_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9485_poseidon1_1_baseband_postamble, ARRAY_LENGTH(ar9485_poseidon1_1_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9485_poseidon1_1_radio_core, ARRAY_LENGTH(ar9485_poseidon1_1_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9485_poseidon1_1_radio_postamble, ARRAY_LENGTH(ar9485_poseidon1_1_radio_postamble), 2); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9485_poseidon1_1_soc_preamble, ARRAY_LENGTH(ar9485_poseidon1_1_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], NULL, 0, 0); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485_common_wo_xlna_rx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_common_wo_xlna_rx_gain_poseidon1_1), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1), 5); /* Japan 2484Mhz CCK settings */ INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9485_poseidon1_1_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9485_poseidon1_1_baseband_core_txfir_coeff_japan_2484), 2); /* Load PCIE SERDES settings from INI */ if (ah->ah_config.ath_hal_pcie_clock_req) { /* Pci-e Clock Request = 1 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_enable_L1), 2); } /* Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_enable_L1), 2); } } else { /*Use driver default setting*/ /* Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH(ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1), 2); /* Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH(ar9485_poseidon1_1_pcie_phy_clkreq_enable_L1), 2); } } else { /* Pci-e Clock Request = 0 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_disable_L1), 2); } /* Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_1_pcie_phy_pll_on_clkreq_disable_L1), 2); } } else { /*Use driver default setting*/ /* Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH(ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1), 2); /* Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH(ar9485_poseidon1_1_pcie_phy_clkreq_disable_L1), 2); } } /* pcie ps setting will honor registry setting, default is 0 */ //ah->ah_config.ath_hal_pciePowerSaveEnable = 0; } else if (AR_SREV_POSEIDON(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9485_poseidon1_0_mac_core, ARRAY_LENGTH(ar9485_poseidon1_0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9485_poseidon1_0_mac_postamble, ARRAY_LENGTH(ar9485_poseidon1_0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], ar9485_poseidon1_0, ARRAY_LENGTH(ar9485_poseidon1_0), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9485_poseidon1_0_baseband_core, ARRAY_LENGTH(ar9485_poseidon1_0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9485_poseidon1_0_baseband_postamble, ARRAY_LENGTH(ar9485_poseidon1_0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9485_poseidon1_0_radio_core, ARRAY_LENGTH(ar9485_poseidon1_0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9485_poseidon1_0_radio_postamble, ARRAY_LENGTH(ar9485_poseidon1_0_radio_postamble), 2); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9485_poseidon1_0_soc_preamble, ARRAY_LENGTH(ar9485_poseidon1_0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], NULL, 0, 0); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485Common_wo_xlna_rx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Common_wo_xlna_rx_gain_poseidon1_0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0), 5); /* Japan 2484Mhz CCK settings */ INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9485_poseidon1_0_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9485_poseidon1_0_baseband_core_txfir_coeff_japan_2484), 2); /* Load PCIE SERDES settings from INI */ if (ah->ah_config.ath_hal_pcie_clock_req) { /* Pci-e Clock Request = 1 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_clkreq_enable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1), 2); } /* Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_clkreq_enable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1), 2); } } else { /*Use driver default setting*/ /* Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1), 2); /* Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_enable_L1), 2); } } else { /* Pci-e Clock Request = 0 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_clkreq_disable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); } /* Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_clkreq_disable_L1), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); } } else { /*Use driver default setting*/ /* Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); /* Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1, ARRAY_LENGTH( ar9485_poseidon1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); } } /* pcie ps setting will honor registry setting, default is 0 */ /*ah->ah_config.ath_hal_pcie_power_save_enable = 0;*/ #if 0 /* ATH_WOW */ /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_awow, ARRAY_LENGTH(ar9300_pcie_phy_awow), 2); #endif } else if (AR_SREV_WASP(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9340_wasp_1p0_mac_core, ARRAY_LENGTH(ar9340_wasp_1p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9340_wasp_1p0_mac_postamble, ARRAY_LENGTH(ar9340_wasp_1p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9340_wasp_1p0_baseband_core, ARRAY_LENGTH(ar9340_wasp_1p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9340_wasp_1p0_baseband_postamble, ARRAY_LENGTH(ar9340_wasp_1p0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9340_wasp_1p0_radio_core, ARRAY_LENGTH(ar9340_wasp_1p0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9340_wasp_1p0_radio_postamble, ARRAY_LENGTH(ar9340_wasp_1p0_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9340_wasp_1p0_soc_preamble, ARRAY_LENGTH(ar9340_wasp_1p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9340_wasp_1p0_soc_postamble, ARRAY_LENGTH(ar9340_wasp_1p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9340Common_wo_xlna_rx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Common_wo_xlna_rx_gain_table_wasp_1p0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0), 5); ah->ah_config.ath_hal_pcie_power_save_enable = 0; /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9340Modes_fast_clock_wasp_1p0, ARRAY_LENGTH(ar9340Modes_fast_clock_wasp_1p0), 3); /* Additional setttings for 40Mhz */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional_40mhz, ar9340_wasp_1p0_radio_core_40M, ARRAY_LENGTH(ar9340_wasp_1p0_radio_core_40M), 2); /* DFS */ INIT_INI_ARRAY(&ahp->ah_ini_dfs, ar9340_wasp_1p0_baseband_postamble_dfs_channel, ARRAY_LENGTH(ar9340_wasp_1p0_baseband_postamble_dfs_channel), 3); } else if (AR_SREV_SCORPION(ah)) { /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar955x_scorpion_1p0_mac_core, ARRAY_LENGTH(ar955x_scorpion_1p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar955x_scorpion_1p0_mac_postamble, ARRAY_LENGTH(ar955x_scorpion_1p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar955x_scorpion_1p0_baseband_core, ARRAY_LENGTH(ar955x_scorpion_1p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar955x_scorpion_1p0_baseband_postamble, ARRAY_LENGTH(ar955x_scorpion_1p0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar955x_scorpion_1p0_radio_core, ARRAY_LENGTH(ar955x_scorpion_1p0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar955x_scorpion_1p0_radio_postamble, ARRAY_LENGTH(ar955x_scorpion_1p0_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar955x_scorpion_1p0_soc_preamble, ARRAY_LENGTH(ar955x_scorpion_1p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar955x_scorpion_1p0_soc_postamble, ARRAY_LENGTH(ar955x_scorpion_1p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0), 5); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar955xModes_no_xpa_tx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xModes_no_xpa_tx_gain_table_scorpion_1p0), 5); /*ath_hal_pciePowerSaveEnable should be 2 for OWL/Condor and 0 for merlin */ ah->ah_config.ath_hal_pcie_power_save_enable = 0; /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar955xModes_fast_clock_scorpion_1p0, ARRAY_LENGTH(ar955xModes_fast_clock_scorpion_1p0), 3); /* Additional setttings for 40Mhz */ //INIT_INI_ARRAY(&ahp->ah_ini_modes_additional_40M, // ar955x_scorpion_1p0_radio_core_40M, // ARRAY_LENGTH(ar955x_scorpion_1p0_radio_core_40M), 2); } else if (AR_SREV_JUPITER_10(ah)) { /* Jupiter: new INI format (pre, core, post arrays per subsystem) */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9300_jupiter_1p0_mac_core, ARRAY_LENGTH(ar9300_jupiter_1p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9300_jupiter_1p0_mac_postamble, ARRAY_LENGTH(ar9300_jupiter_1p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9300_jupiter_1p0_baseband_core, ARRAY_LENGTH(ar9300_jupiter_1p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9300_jupiter_1p0_baseband_postamble, ARRAY_LENGTH(ar9300_jupiter_1p0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9300_jupiter_1p0_radio_core, ARRAY_LENGTH(ar9300_jupiter_1p0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9300_jupiter_1p0_radio_postamble, ARRAY_LENGTH(ar9300_jupiter_1p0_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9300_jupiter_1p0_soc_preamble, ARRAY_LENGTH(ar9300_jupiter_1p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9300_jupiter_1p0_soc_postamble, ARRAY_LENGTH(ar9300_jupiter_1p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_jupiter_1p0, ARRAY_LENGTH(ar9300_common_rx_gain_table_jupiter_1p0), 2); /* Load PCIE SERDES settings from INI */ if (ah->ah_config.ath_hal_pcie_clock_req) { /* Pci-e Clock Request = 1 */ /* * PLL ON + clkreq enable is not a valid combination, * thus to ignore ath_hal_pll_pwr_save, use PLL OFF. */ { /*Use driver default setting*/ /* Awake -> Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_pcie_phy_clkreq_enable_L1_jupiter_1p0, ARRAY_LENGTH(ar9300_pcie_phy_clkreq_enable_L1_jupiter_1p0), 2); /* Sleep -> Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_pcie_phy_clkreq_enable_L1_jupiter_1p0, ARRAY_LENGTH(ar9300_pcie_phy_clkreq_enable_L1_jupiter_1p0), 2); } } else { /* * Since Jupiter 1.0 and 2.0 share the same device id and will be * installed with same INF, but Jupiter 1.0 has issue with PLL OFF. * * Force Jupiter 1.0 to use ON/ON setting. */ ah->ah_config.ath_hal_pll_pwr_save = 0; /* Pci-e Clock Request = 0 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Awake -> Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_pcie_phy_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_clkreq_disable_L1_jupiter_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0), 2); } /* Sleep -> Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_pcie_phy_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_clkreq_disable_L1_jupiter_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0), 2); } } else { /*Use driver default setting*/ /* Awake -> Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0), 2); /* Sleep -> Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0, ARRAY_LENGTH( ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0), 2); } } /* * ath_hal_pcie_power_save_enable should be 2 for OWL/Condor and * 0 for merlin */ ah->ah_config.ath_hal_pcie_power_save_enable = 0; #if 0 // ATH_WOW /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_AWOW, ARRAY_LENGTH(ar9300_pcie_phy_AWOW), 2); #endif /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9300_modes_fast_clock_jupiter_1p0, ARRAY_LENGTH(ar9300_modes_fast_clock_jupiter_1p0), 3); INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9300_jupiter_1p0_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9300_jupiter_1p0_baseband_core_txfir_coeff_japan_2484), 2); } else if (AR_SREV_JUPITER_20(ah)) { /* Jupiter: new INI format (pre, core, post arrays per subsystem) */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9300_jupiter_2p0_mac_core, ARRAY_LENGTH(ar9300_jupiter_2p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9300_jupiter_2p0_mac_postamble, ARRAY_LENGTH(ar9300_jupiter_2p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9300_jupiter_2p0_baseband_core, ARRAY_LENGTH(ar9300_jupiter_2p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9300_jupiter_2p0_baseband_postamble, ARRAY_LENGTH(ar9300_jupiter_2p0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9300_jupiter_2p0_radio_core, ARRAY_LENGTH(ar9300_jupiter_2p0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9300_jupiter_2p0_radio_postamble, ARRAY_LENGTH(ar9300_jupiter_2p0_radio_postamble), 5); INIT_INI_ARRAY(&ahp->ah_ini_radio_post_sys2ant, ar9300_jupiter_2p0_radio_postamble_sys2ant, ARRAY_LENGTH(ar9300_jupiter_2p0_radio_postamble_sys2ant), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9300_jupiter_2p0_soc_preamble, ARRAY_LENGTH(ar9300_jupiter_2p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9300_jupiter_2p0_soc_postamble, ARRAY_LENGTH(ar9300_jupiter_2p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300Common_rx_gain_table_jupiter_2p0, ARRAY_LENGTH(ar9300Common_rx_gain_table_jupiter_2p0), 2); /* BTCOEX */ INIT_INI_ARRAY(&ahp->ah_ini_BTCOEX_MAX_TXPWR, ar9300_jupiter_2p0_BTCOEX_MAX_TXPWR_table, ARRAY_LENGTH(ar9300_jupiter_2p0_BTCOEX_MAX_TXPWR_table), 2); /* Load PCIE SERDES settings from INI */ if (ah->ah_config.ath_hal_pcie_clock_req) { /* Pci-e Clock Request = 1 */ /* * PLL ON + clkreq enable is not a valid combination, * thus to ignore ath_hal_pll_pwr_save, use PLL OFF. */ { /*Use driver default setting*/ /* Awake -> Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_PciePhy_clkreq_enable_L1_jupiter_2p0, ARRAY_LENGTH(ar9300_PciePhy_clkreq_enable_L1_jupiter_2p0), 2); /* Sleep -> Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_PciePhy_clkreq_enable_L1_jupiter_2p0, ARRAY_LENGTH(ar9300_PciePhy_clkreq_enable_L1_jupiter_2p0), 2); } } else { /* Pci-e Clock Request = 0 */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { /* Awake -> Sleep Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_PciePhy_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_clkreq_disable_L1_jupiter_2p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0), 2); } /* Sleep -> Awake Setting */ if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_PciePhy_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_clkreq_disable_L1_jupiter_2p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0), 2); } } else { /*Use driver default setting*/ /* Awake -> Sleep Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0), 2); /* Sleep -> Awake Setting */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0, ARRAY_LENGTH( ar9300_PciePhy_pll_on_clkreq_disable_L1_jupiter_2p0), 2); } } /* * ath_hal_pcie_power_save_enable should be 2 for OWL/Condor and * 0 for merlin */ ah->ah_config.ath_hal_pcie_power_save_enable = 0; #if 0 // ATH_WOW /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_AWOW, ARRAY_LENGTH(ar9300_pcie_phy_AWOW), 2); #endif /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9300Modes_fast_clock_jupiter_2p0, ARRAY_LENGTH(ar9300Modes_fast_clock_jupiter_2p0), 3); INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9300_jupiter_2p0_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9300_jupiter_2p0_baseband_core_txfir_coeff_japan_2484), 2); } else if (AR_SREV_APHRODITE(ah)) { /* Aphrodite: new INI format (pre, core, post arrays per subsystem) */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar956X_aphrodite_1p0_mac_core, ARRAY_LENGTH(ar956X_aphrodite_1p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar956X_aphrodite_1p0_mac_postamble, ARRAY_LENGTH(ar956X_aphrodite_1p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar956X_aphrodite_1p0_baseband_core, ARRAY_LENGTH(ar956X_aphrodite_1p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar956X_aphrodite_1p0_baseband_postamble, ARRAY_LENGTH(ar956X_aphrodite_1p0_baseband_postamble), 5); //mark jupiter have but aphrodite don't have // /* radio */ // INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); // INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], // ar9300_aphrodite_1p0_radio_core, // ARRAY_LENGTH(ar9300_aphrodite_1p0_radio_core), 2); // INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], // ar9300_aphrodite_1p0_radio_postamble, // ARRAY_LENGTH(ar9300_aphrodite_1p0_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar956X_aphrodite_1p0_soc_preamble, ARRAY_LENGTH(ar956X_aphrodite_1p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar956X_aphrodite_1p0_soc_postamble, ARRAY_LENGTH(ar956X_aphrodite_1p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar956XCommon_rx_gain_table_aphrodite_1p0, ARRAY_LENGTH(ar956XCommon_rx_gain_table_aphrodite_1p0), 2); //INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, // ar956XModes_lowest_ob_db_tx_gain_table_aphrodite_1p0, // ARRAY_LENGTH(ar956XModes_lowest_ob_db_tx_gain_table_aphrodite_1p0), // 5); /* * ath_hal_pcie_power_save_enable should be 2 for OWL/Condor and * 0 for merlin */ ah->ah_config.ath_hal_pcie_power_save_enable = 0; #if 0 // ATH_WOW /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_AWOW, ARRAY_LENGTH(ar9300_pcie_phy_AWOW), 2); #endif /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar956XModes_fast_clock_aphrodite_1p0, ARRAY_LENGTH(ar956XModes_fast_clock_aphrodite_1p0), 3); } else if (AR_SREV_AR9580(ah)) { /* * AR9580/Peacock - * new INI format (pre, core, post arrays per subsystem) */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9300_ar9580_1p0_mac_core, ARRAY_LENGTH(ar9300_ar9580_1p0_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9300_ar9580_1p0_mac_postamble, ARRAY_LENGTH(ar9300_ar9580_1p0_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9300_ar9580_1p0_baseband_core, ARRAY_LENGTH(ar9300_ar9580_1p0_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9300_ar9580_1p0_baseband_postamble, ARRAY_LENGTH(ar9300_ar9580_1p0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9300_ar9580_1p0_radio_core, ARRAY_LENGTH(ar9300_ar9580_1p0_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9300_ar9580_1p0_radio_postamble, ARRAY_LENGTH(ar9300_ar9580_1p0_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9300_ar9580_1p0_soc_preamble, ARRAY_LENGTH(ar9300_ar9580_1p0_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9300_ar9580_1p0_soc_postamble, ARRAY_LENGTH(ar9300_ar9580_1p0_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300_common_rx_gain_table_ar9580_1p0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0), 5); /* DFS */ INIT_INI_ARRAY(&ahp->ah_ini_dfs, ar9300_ar9580_1p0_baseband_postamble_dfs_channel, ARRAY_LENGTH(ar9300_ar9580_1p0_baseband_postamble_dfs_channel), 3); /* Load PCIE SERDES settings from INI */ /*D3 Setting */ if (ah->ah_config.ath_hal_pcie_clock_req) { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { //bit1, in to D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_enable_L1_ar9580_1p0, ARRAY_LENGTH(ar9300PciePhy_clkreq_enable_L1_ar9580_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else {//no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { //bit1, in to D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_clkreq_disable_L1_ar9580_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else {//no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } /*D0 Setting */ if (ah->ah_config.ath_hal_pcie_clock_req) { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { //bit2, out of D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_clkreq_enable_L1_ar9580_1p0, ARRAY_LENGTH(ar9300PciePhy_clkreq_enable_L1_ar9580_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else { //no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) {//registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) {//bit2, out of D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH(ar9300PciePhy_clkreq_disable_L1_ar9580_1p0), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } else { //no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0), 2); } } ah->ah_config.ath_hal_pcie_power_save_enable = 0; #if 0 /* ATH_WOW */ /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_awow, ARRAY_LENGTH(ar9300_pcie_phy_awow), 2); #endif /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9300Modes_fast_clock_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_fast_clock_ar9580_1p0), 3); INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9300_ar9580_1p0_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9300_ar9580_1p0_baseband_core_txfir_coeff_japan_2484), 2); } else { /* * Osprey 2.2 - new INI format (pre, core, post arrays per subsystem) */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9300_osprey_2p2_mac_core, ARRAY_LENGTH(ar9300_osprey_2p2_mac_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], ar9300_osprey_2p2_mac_postamble, ARRAY_LENGTH(ar9300_osprey_2p2_mac_postamble), 5); /* bb */ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE], ar9300_osprey_2p2_baseband_core, ARRAY_LENGTH(ar9300_osprey_2p2_baseband_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9300_osprey_2p2_baseband_postamble, ARRAY_LENGTH(ar9300_osprey_2p2_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE], ar9300_osprey_2p2_radio_core, ARRAY_LENGTH(ar9300_osprey_2p2_radio_core), 2); INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], ar9300_osprey_2p2_radio_postamble, ARRAY_LENGTH(ar9300_osprey_2p2_radio_postamble), 5); /* soc */ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9300_osprey_2p2_soc_preamble, ARRAY_LENGTH(ar9300_osprey_2p2_soc_preamble), 2); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST], ar9300_osprey_2p2_soc_postamble, ARRAY_LENGTH(ar9300_osprey_2p2_soc_postamble), 5); /* rx/tx gain */ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300_common_rx_gain_table_osprey_2p2), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2), 5); /* DFS */ INIT_INI_ARRAY(&ahp->ah_ini_dfs, ar9300_osprey_2p2_baseband_postamble_dfs_channel, ARRAY_LENGTH(ar9300_osprey_2p2_baseband_postamble_dfs_channel), 3); /* Load PCIE SERDES settings from INI */ /*D3 Setting */ if (ah->ah_config.ath_hal_pcie_clock_req) { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { //bit1, in to D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_enable_L1_osprey_2p2, ARRAY_LENGTH(ar9300PciePhy_clkreq_enable_L1_osprey_2p2), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } else {//no registry control, default is pll on #ifndef ATH_BUS_PM INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); #else //no registry control, default is pll off INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_clkreq_disable_L1_osprey_2p2), 2); #endif } } else { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D3) { //bit1, in to D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_clkreq_disable_L1_osprey_2p2), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } else { #ifndef ATH_BUS_PM //no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); #else //no registry control, default is pll off INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes, ar9300PciePhy_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH(ar9300PciePhy_clkreq_disable_L1_osprey_2p2), 2); #endif } } /*D0 Setting */ if (ah->ah_config.ath_hal_pcie_clock_req) { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) { //registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) { //bit2, out of D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_clkreq_enable_L1_osprey_2p2, ARRAY_LENGTH(ar9300PciePhy_clkreq_enable_L1_osprey_2p2), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } else { //no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } else { if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_CONTROL) {//registry control if (ah->ah_config.ath_hal_pll_pwr_save & AR_PCIE_PLL_PWRSAVE_ON_D0) {//bit2, out of D3 INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH(ar9300PciePhy_clkreq_disable_L1_osprey_2p2), 2); } else { INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } else { //no registry control, default is pll on INIT_INI_ARRAY( &ahp->ah_ini_pcie_serdes_low_power, ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2, ARRAY_LENGTH( ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2), 2); } } ah->ah_config.ath_hal_pcie_power_save_enable = 0; #ifdef ATH_BUS_PM /*Use HAL to config PCI powersave by writing into the SerDes Registers */ ah->ah_config.ath_hal_pcie_ser_des_write = 1; #endif #if 0 /* ATH_WOW */ /* SerDes values during WOW sleep */ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_awow, ARRAY_LENGTH(ar9300_pcie_phy_awow), 2); #endif /* Fast clock modal settings */ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional, ar9300Modes_fast_clock_osprey_2p2, ARRAY_LENGTH(ar9300Modes_fast_clock_osprey_2p2), 3); INIT_INI_ARRAY(&ahp->ah_ini_japan2484, ar9300_osprey_2p2_baseband_core_txfir_coeff_japan_2484, ARRAY_LENGTH( ar9300_osprey_2p2_baseband_core_txfir_coeff_japan_2484), 2); } if(AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { #define AR_SOC_RST_OTP_INTF 0xB80600B4 #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) ahp->ah_enterprise_mode = REG_READ(AR_SOC_RST_OTP_INTF); if (AR_SREV_SCORPION(ah)) { ahp->ah_enterprise_mode = ahp->ah_enterprise_mode << 12; } ath_hal_printf (ah, "Enterprise mode: 0x%08x\n", ahp->ah_enterprise_mode); #undef REG_READ #undef AR_SOC_RST_OTP_INTF } else { ahp->ah_enterprise_mode = OS_REG_READ(ah, AR_ENT_OTP); } if (ahpriv->ah_ispcie) { ar9300_config_pci_power_save(ah, 0, 0); } else { ar9300_disable_pcie_phy(ah); } ath_hal_printf(ah, "%s: calling ar9300_hw_attach\n", __func__); ecode = ar9300_hw_attach(ah); if (ecode != HAL_OK) { goto bad; } /* set gain table pointers according to values read from the eeprom */ ar9300_tx_gain_table_apply(ah); ar9300_rx_gain_table_apply(ah); /* ** ** Got everything we need now to setup the capabilities. */ if (!ar9300_fill_capability_info(ah)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s:failed ar9300_fill_capability_info\n", __func__); ecode = HAL_EEREAD; goto bad; } ecode = ar9300_init_mac_addr(ah); if (ecode != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: failed initializing mac address\n", __func__); goto bad; } /* * Initialize receive buffer size to MAC default */ ahp->rx_buf_size = HAL_RXBUFSIZE_DEFAULT; #if ATH_WOW #if 0 /* * Needs to be removed once we stop using XB92 XXX * FIXME: Check with latest boards too - SriniK */ ar9300_wow_set_gpio_reset_low(ah); #endif /* * Clear the Wow Status. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL)) | AR_PMCTRL_WOW_PME_CLR); OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, AR_WOW_CLEAR_EVENTS(OS_REG_READ(ah, AR_WOW_PATTERN_REG))); #endif /* * Set the cur_trig_level to a value that works all modes - 11a/b/g or 11n * with aggregation enabled or disabled. */ ahp->ah_tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); if (AR_SREV_HORNET(ah)) { ahp->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_HORNET_2GHZ; ahp->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ; ahp->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_2GHZ; ahp->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ; ahp->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ; ahp->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_5GHZ; ahp->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA; } else if(AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)){ ahp->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_JUPITER_2GHZ; ahp->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ; ahp->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_JUPITER_2GHZ; ahp->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_JUPITER_5GHZ; ahp->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ; ahp->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_JUPITER_5GHZ; ahp->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA; } else { ahp->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_2GHZ; ahp->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ; ahp->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_2GHZ; if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { ahp->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_PEACOCK_5GHZ; } else { ahp->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ; } ahp->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ; ahp->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_5GHZ; ahp->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA; } /* init BB Panic Watchdog timeout */ if (AR_SREV_HORNET(ah)) { ahp->ah_bb_panic_timeout_ms = HAL_BB_PANIC_WD_TMO_HORNET; } else { ahp->ah_bb_panic_timeout_ms = HAL_BB_PANIC_WD_TMO; } /* * Determine whether tx IQ calibration HW should be enabled, * and whether tx IQ calibration should be performed during * AGC calibration, or separately. */ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* * Register not initialized yet. This flag will be re-initialized * after INI loading following each reset. */ ahp->tx_iq_cal_enable = 1; /* if tx IQ cal is enabled, do it together with AGC cal */ ahp->tx_iq_cal_during_agc_cal = 1; } else if (AR_SREV_POSEIDON_OR_LATER(ah) && !AR_SREV_WASP(ah)) { ahp->tx_iq_cal_enable = 1; ahp->tx_iq_cal_during_agc_cal = 1; } else { /* osprey, hornet, wasp */ ahp->tx_iq_cal_enable = 1; ahp->tx_iq_cal_during_agc_cal = 0; } return ah; bad: if (ahp) { ar9300_detach((struct ath_hal *) ahp); } if (status) { *status = ecode; } return AH_NULL; } void ar9300_detach(struct ath_hal *ah) { HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR9300_MAGIC); /* Make sure that chip is awake before writing to it */ if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: failed to wake up chip\n", __func__); } ar9300_hw_detach(ah); ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); // ath_hal_hdprintf_deregister(ah); if (AH9300(ah)->ah_cal_mem) ath_hal_free(AH9300(ah)->ah_cal_mem); AH9300(ah)->ah_cal_mem = AH_NULL; ath_hal_free(ah); } struct ath_hal_9300 * ar9300_new_state(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { static const u_int8_t defbssidmask[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; struct ath_hal_9300 *ahp; struct ath_hal *ah; /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof(struct ath_hal_9300)); if (ahp == AH_NULL) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; } ah = &ahp->ah_priv.h; /* set initial values */ /* stub everything first */ ar9300_set_stub_functions(ah); /* setup the FreeBSD HAL methods */ ar9300_attach_freebsd_ops(ah); /* These are private to this particular file, so .. */ ah->ah_disablePCIE = ar9300_disable_pcie_phy; AH_PRIVATE(ah)->ah_getNfAdjust = ar9300_get_nf_adjust; AH_PRIVATE(ah)->ah_getChipPowerLimits = ar9300_get_chip_power_limits; #if 0 /* Attach Osprey structure as default hal structure */ OS_MEMCPY(&ahp->ah_priv.priv, &ar9300hal, sizeof(ahp->ah_priv.priv)); #endif #if 0 AH_PRIVATE(ah)->amem_handle = amem_handle; AH_PRIVATE(ah)->ah_osdev = osdev; #endif ah->ah_sc = sc; ah->ah_st = st; ah->ah_sh = sh; ah->ah_magic = AR9300_MAGIC; AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_flags = 0; /* ** Initialize factory defaults in the private space */ // ath_hal_factory_defaults(AH_PRIVATE(ah), hal_conf_parm); ar9300_config_defaults_freebsd(ah, ah_config); /* XXX FreeBSD: cal is always in EEPROM */ #if 0 if (!hal_conf_parm->calInFlash) { AH_PRIVATE(ah)->ah_flags |= AH_USE_EEPROM; } #endif AH_PRIVATE(ah)->ah_flags |= AH_USE_EEPROM; #if 0 if (ar9300_eep_data_in_flash(ah)) { ahp->ah_priv.priv.ah_eeprom_read = ar9300_flash_read; ahp->ah_priv.priv.ah_eeprom_dump = AH_NULL; } else { ahp->ah_priv.priv.ah_eeprom_read = ar9300_eeprom_read_word; } #endif /* XXX FreeBSD - for now, just supports EEPROM reading */ ahp->ah_priv.ah_eepromRead = ar9300_eeprom_read_word; AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ahp->ah_atim_window = 0; /* [0..1000] */ ahp->ah_diversity_control = ah->ah_config.ath_hal_diversity_control; ahp->ah_antenna_switch_swap = ah->ah_config.ath_hal_antenna_switch_swap; /* * Enable MIC handling. */ ahp->ah_sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ahp->ah_enable32k_hz_clock = DONT_USE_32KHZ;/* XXX */ ahp->ah_slot_time = (u_int) -1; ahp->ah_ack_timeout = (u_int) -1; OS_MEMCPY(&ahp->ah_bssid_mask, defbssidmask, IEEE80211_ADDR_LEN); /* * 11g-specific stuff */ ahp->ah_g_beacon_rate = 0; /* adhoc beacon fixed rate */ /* SM power mode: Attach time, disable any setting */ ahp->ah_sm_power_mode = HAL_SMPS_DEFAULT; return ahp; } HAL_BOOL ar9300_chip_test(struct ath_hal *ah) { /*u_int32_t reg_addr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };*/ u_int32_t reg_addr[2] = { AR_STA_ID0 }; u_int32_t reg_hold[2]; u_int32_t pattern_data[4] = { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; int i, j; /* Test PHY & MAC registers */ for (i = 0; i < 1; i++) { u_int32_t addr = reg_addr[i]; u_int32_t wr_data, rd_data; reg_hold[i] = OS_REG_READ(ah, addr); for (j = 0; j < 0x100; j++) { wr_data = (j << 16) | j; OS_REG_WRITE(ah, addr, wr_data); rd_data = OS_REG_READ(ah, addr); if (rd_data != wr_data) { HALDEBUG(ah, HAL_DEBUG_REGIO, "%s: address test failed addr: " "0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wr_data, rd_data); return AH_FALSE; } } for (j = 0; j < 4; j++) { wr_data = pattern_data[j]; OS_REG_WRITE(ah, addr, wr_data); rd_data = OS_REG_READ(ah, addr); if (wr_data != rd_data) { HALDEBUG(ah, HAL_DEBUG_REGIO, "%s: address test failed addr: " "0x%08x - wr:0x%08x != rd:0x%08x\n", __func__, addr, wr_data, rd_data); return AH_FALSE; } } OS_REG_WRITE(ah, reg_addr[i], reg_hold[i]); } OS_DELAY(100); return AH_TRUE; } /* * Store the channel edges for the requested operational mode */ HAL_BOOL ar9300_get_channel_edges(struct ath_hal *ah, u_int16_t flags, u_int16_t *low, u_int16_t *high) { struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps; if (flags & IEEE80211_CHAN_5GHZ) { *low = p_cap->halLow5GhzChan; *high = p_cap->halHigh5GhzChan; return AH_TRUE; } if ((flags & IEEE80211_CHAN_2GHZ)) { *low = p_cap->halLow2GhzChan; *high = p_cap->halHigh2GhzChan; return AH_TRUE; } return AH_FALSE; } HAL_BOOL ar9300_regulatory_domain_override(struct ath_hal *ah, u_int16_t regdmn) { AH_PRIVATE(ah)->ah_currentRD = regdmn; return AH_TRUE; } /* * Fill all software cached or static hardware state information. * Return failure if capabilities are to come from EEPROM and * cannot be read. */ HAL_BOOL ar9300_fill_capability_info(struct ath_hal *ah) { #define AR_KEYTABLE_SIZE 128 struct ath_hal_9300 *ahp = AH9300(ah); struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps; u_int16_t cap_field = 0, eeval; ahpriv->ah_devType = (u_int16_t)ar9300_eeprom_get(ahp, EEP_DEV_TYPE); eeval = ar9300_eeprom_get(ahp, EEP_REG_0); /* XXX record serial number */ AH_PRIVATE(ah)->ah_currentRD = eeval; /* Always enable fast clock; leave it up to EEPROM and channel */ p_cap->halSupportsFastClock5GHz = AH_TRUE; p_cap->halIntrMitigation = AH_TRUE; eeval = ar9300_eeprom_get(ahp, EEP_REG_1); AH_PRIVATE(ah)->ah_currentRDext = eeval | AR9300_RDEXT_DEFAULT; /* Read the capability EEPROM location */ cap_field = ar9300_eeprom_get(ahp, EEP_OP_CAP); /* Construct wireless mode from EEPROM */ p_cap->halWirelessModes = 0; eeval = ar9300_eeprom_get(ahp, EEP_OP_MODE); /* * XXX FreeBSD specific: for now, set ath_hal_ht_enable to 1, * or we won't have 11n support. */ ah->ah_config.ath_hal_ht_enable = 1; if (eeval & AR9300_OPFLAGS_11A) { p_cap->halWirelessModes |= HAL_MODE_11A | ((!ah->ah_config.ath_hal_ht_enable || (eeval & AR9300_OPFLAGS_N_5G_HT20)) ? 0 : (HAL_MODE_11NA_HT20 | ((eeval & AR9300_OPFLAGS_N_5G_HT40) ? 0 : (HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS)))); } if (eeval & AR9300_OPFLAGS_11G) { p_cap->halWirelessModes |= HAL_MODE_11B | HAL_MODE_11G | ((!ah->ah_config.ath_hal_ht_enable || (eeval & AR9300_OPFLAGS_N_2G_HT20)) ? 0 : (HAL_MODE_11NG_HT20 | ((eeval & AR9300_OPFLAGS_N_2G_HT40) ? 0 : (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS)))); } /* Get chainamsks from eeprom */ p_cap->halTxChainMask = ar9300_eeprom_get(ahp, EEP_TX_MASK); p_cap->halRxChainMask = ar9300_eeprom_get(ahp, EEP_RX_MASK); #define owl_get_ntxchains(_txchainmask) \ (((_txchainmask >> 2) & 1) + ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) /* FreeBSD: Update number of TX/RX streams */ p_cap->halTxStreams = owl_get_ntxchains(p_cap->halTxChainMask); p_cap->halRxStreams = owl_get_ntxchains(p_cap->halRxChainMask); /* * This being a newer chip supports TKIP non-splitmic mode. * */ ahp->ah_misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; p_cap->halTkipMicTxRxKeySupport = AH_TRUE; p_cap->halLow2GhzChan = 2312; p_cap->halHigh2GhzChan = 2732; p_cap->halLow5GhzChan = 4920; p_cap->halHigh5GhzChan = 6100; p_cap->halCipherCkipSupport = AH_FALSE; p_cap->halCipherTkipSupport = AH_TRUE; p_cap->halCipherAesCcmSupport = AH_TRUE; p_cap->halMicCkipSupport = AH_FALSE; p_cap->halMicTkipSupport = AH_TRUE; p_cap->halMicAesCcmSupport = AH_TRUE; p_cap->halChanSpreadSupport = AH_TRUE; p_cap->halSleepAfterBeaconBroken = AH_TRUE; p_cap->halBurstSupport = AH_TRUE; p_cap->halChapTuningSupport = AH_TRUE; p_cap->halTurboPrimeSupport = AH_TRUE; p_cap->halFastFramesSupport = AH_FALSE; p_cap->halTurboGSupport = p_cap->halWirelessModes & HAL_MODE_108G; // p_cap->hal_xr_support = AH_FALSE; p_cap->halHTSupport = ah->ah_config.ath_hal_ht_enable ? AH_TRUE : AH_FALSE; p_cap->halGTTSupport = AH_TRUE; p_cap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ p_cap->halNumMRRetries = 4; /* Hardware supports 4 MRR */ p_cap->halHTSGI20Support = AH_TRUE; p_cap->halVEOLSupport = AH_TRUE; p_cap->halBssIdMaskSupport = AH_TRUE; /* Bug 26802, fixed in later revs? */ p_cap->halMcastKeySrchSupport = AH_TRUE; p_cap->halTsfAddSupport = AH_TRUE; if (cap_field & AR_EEPROM_EEPCAP_MAXQCU) { p_cap->halTotalQueues = MS(cap_field, AR_EEPROM_EEPCAP_MAXQCU); } else { p_cap->halTotalQueues = HAL_NUM_TX_QUEUES; } if (cap_field & AR_EEPROM_EEPCAP_KC_ENTRIES) { p_cap->halKeyCacheSize = 1 << MS(cap_field, AR_EEPROM_EEPCAP_KC_ENTRIES); } else { p_cap->halKeyCacheSize = AR_KEYTABLE_SIZE; } p_cap->halFastCCSupport = AH_TRUE; // p_cap->hal_num_mr_retries = 4; // ahp->hal_tx_trig_level_max = MAX_TX_FIFO_THRESHOLD; p_cap->halNumGpioPins = AR9382_MAX_GPIO_PIN_NUM; #if 0 /* XXX Verify support in Osprey */ if (AR_SREV_MERLIN_10_OR_LATER(ah)) { p_cap->halWowSupport = AH_TRUE; p_cap->hal_wow_match_pattern_exact = AH_TRUE; if (AR_SREV_MERLIN(ah)) { p_cap->hal_wow_pattern_match_dword = AH_TRUE; } } else { p_cap->halWowSupport = AH_FALSE; p_cap->hal_wow_match_pattern_exact = AH_FALSE; } #endif p_cap->halWowSupport = AH_TRUE; p_cap->halWowMatchPatternExact = AH_TRUE; if (AR_SREV_POSEIDON(ah)) { p_cap->halWowMatchPatternExact = AH_TRUE; } p_cap->halCSTSupport = AH_TRUE; p_cap->halRifsRxSupport = AH_TRUE; p_cap->halRifsTxSupport = AH_TRUE; #define IEEE80211_AMPDU_LIMIT_MAX (65536) p_cap->halRtsAggrLimit = IEEE80211_AMPDU_LIMIT_MAX; #undef IEEE80211_AMPDU_LIMIT_MAX p_cap->halMfpSupport = ah->ah_config.ath_hal_mfp_support; p_cap->halForcePpmSupport = AH_TRUE; p_cap->halHwBeaconProcSupport = AH_TRUE; /* ar9300 - has the HW UAPSD trigger support, * but it has the following limitations * The power state change from the following * frames are not put in High priority queue. * i) Mgmt frames * ii) NoN QoS frames * iii) QoS frames form the access categories for which * UAPSD is not enabled. * so we can not enable this feature currently. * could be enabled, if these limitations are fixed * in later versions of ar9300 chips */ p_cap->halHasUapsdSupport = AH_FALSE; /* Number of buffers that can be help in a single TxD */ p_cap->halNumTxMaps = 4; p_cap->halTxDescLen = sizeof(struct ar9300_txc); p_cap->halTxStatusLen = sizeof(struct ar9300_txs); p_cap->halRxStatusLen = sizeof(struct ar9300_rxs); p_cap->halRxHpFifoDepth = HAL_HP_RXFIFO_DEPTH; p_cap->halRxLpFifoDepth = HAL_LP_RXFIFO_DEPTH; /* Enable extension channel DFS support */ p_cap->halUseCombinedRadarRssi = AH_TRUE; p_cap->halExtChanDfsSupport = AH_TRUE; #if ATH_SUPPORT_SPECTRAL p_cap->halSpectralScanSupport = AH_TRUE; #endif ahpriv->ah_rfsilent = ar9300_eeprom_get(ahp, EEP_RF_SILENT); if (ahpriv->ah_rfsilent & EEP_RFSILENT_ENABLED) { ahp->ah_gpio_select = MS(ahpriv->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); ahp->ah_polarity = MS(ahpriv->ah_rfsilent, EEP_RFSILENT_POLARITY); ath_hal_enable_rfkill(ah, AH_TRUE); p_cap->halRfSilentSupport = AH_TRUE; } /* XXX */ p_cap->halWpsPushButtonSupport = AH_FALSE; #ifdef ATH_BT_COEX p_cap->halBtCoexSupport = AH_TRUE; p_cap->halBtCoexApsmWar = AH_FALSE; #endif p_cap->halGenTimerSupport = AH_TRUE; ahp->ah_avail_gen_timers = ~((1 << AR_FIRST_NDP_TIMER) - 1); ahp->ah_avail_gen_timers &= (1 << AR_NUM_GEN_TIMERS) - 1; /* * According to Kyungwan, generic timer 0 and 8 are special * timers. Remove timer 8 from the available gen timer list. * Jupiter testing shows timer won't trigger with timer 8. */ ahp->ah_avail_gen_timers &= ~(1 << AR_GEN_TIMER_RESERVED); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { #if ATH_SUPPORT_MCI if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_DISABLE_MCI) { p_cap->halMciSupport = AH_FALSE; } else #endif { p_cap->halMciSupport = (ahp->ah_enterprise_mode & AR_ENT_OTP_49GHZ_DISABLE) ? AH_FALSE: AH_TRUE; } HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: (MCI) MCI support = %d\n", __func__, p_cap->halMciSupport); } else { p_cap->halMciSupport = AH_FALSE; } if (AR_SREV_JUPITER_20(ah)) { p_cap->halRadioRetentionSupport = AH_TRUE; } else { p_cap->halRadioRetentionSupport = AH_FALSE; } p_cap->halAutoSleepSupport = AH_TRUE; p_cap->halMbssidAggrSupport = AH_TRUE; // p_cap->hal_proxy_sta_support = AH_TRUE; /* XXX Mark it true after it is verfied as fixed */ p_cap->hal4kbSplitTransSupport = AH_FALSE; /* Read regulatory domain flag */ if (AH_PRIVATE(ah)->ah_currentRDext & (1 << REG_EXT_JAPAN_MIDBAND)) { /* * If REG_EXT_JAPAN_MIDBAND is set, turn on U1 EVEN, U2, and MIDBAND. */ p_cap->halRegCap = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | AR_EEPROM_EEREGCAP_EN_KK_U2 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; } else { p_cap->halRegCap = AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; } /* For AR9300 and above, midband channels are always supported */ p_cap->halRegCap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; p_cap->halNumAntCfg5GHz = ar9300_eeprom_get_num_ant_config(ahp, HAL_FREQ_BAND_5GHZ); p_cap->halNumAntCfg2GHz = ar9300_eeprom_get_num_ant_config(ahp, HAL_FREQ_BAND_2GHZ); /* STBC supported */ p_cap->halRxStbcSupport = 1; /* number of streams for STBC recieve. */ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { p_cap->halTxStbcSupport = 0; } else { p_cap->halTxStbcSupport = 1; } p_cap->halEnhancedDmaSupport = AH_TRUE; p_cap->halEnhancedDfsSupport = AH_TRUE; /* * EV61133 (missing interrupts due to AR_ISR_RAC). * Fixed in Osprey 2.0. */ p_cap->halIsrRacSupport = AH_TRUE; /* XXX FreeBSD won't support TKIP and WEP aggregation */ #if 0 p_cap->hal_wep_tkip_aggr_support = AH_TRUE; p_cap->hal_wep_tkip_aggr_num_tx_delim = 10; /* TBD */ p_cap->hal_wep_tkip_aggr_num_rx_delim = 10; /* TBD */ p_cap->hal_wep_tkip_max_ht_rate = 15; /* TBD */ #endif /* * XXX FreeBSD won't need these; but eventually add them * and add the WARs - AGGR extra delim WAR is useful to know * about. */ #if 0 p_cap->hal_cfend_fix_support = AH_FALSE; p_cap->hal_aggr_extra_delim_war = AH_FALSE; #endif p_cap->halHasLongRxDescTsf = AH_TRUE; // p_cap->hal_rx_desc_timestamp_bits = 32; p_cap->halRxTxAbortSupport = AH_TRUE; p_cap->hal_ani_poll_interval = AR9300_ANI_POLLINTERVAL; p_cap->hal_channel_switch_time_usec = AR9300_CHANNEL_SWITCH_TIME_USEC; /* Transmit Beamforming supported, fill capabilities */ p_cap->halPaprdEnabled = ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED); p_cap->halChanHalfRate = !(ahp->ah_enterprise_mode & AR_ENT_OTP_10MHZ_DISABLE); p_cap->halChanQuarterRate = !(ahp->ah_enterprise_mode & AR_ENT_OTP_5MHZ_DISABLE); if(AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)){ /* There is no AR_ENT_OTP_49GHZ_DISABLE feature in Jupiter, now the bit is used to disable BT. */ p_cap->hal49GhzSupport = 1; } else { p_cap->hal49GhzSupport = !(ahp->ah_enterprise_mode & AR_ENT_OTP_49GHZ_DISABLE); } if (AR_SREV_POSEIDON(ah) || AR_SREV_HORNET(ah) || AR_SREV_APHRODITE(ah)) { /* LDPC supported */ /* Poseidon doesn't support LDPC, or it will cause receiver CRC Error */ p_cap->halLDPCSupport = AH_FALSE; /* PCI_E LCR offset */ if (AR_SREV_POSEIDON(ah)) { p_cap->hal_pcie_lcr_offset = 0x80; /*for Poseidon*/ } /*WAR method for APSM L0s with Poseidon 1.0*/ if (AR_SREV_POSEIDON_10(ah)) { p_cap->hal_pcie_lcr_extsync_en = AH_TRUE; } } else { p_cap->halLDPCSupport = AH_TRUE; } /* XXX is this a flag, or a chainmask number? */ p_cap->halApmEnable = !! ar9300_eeprom_get(ahp, EEP_CHAIN_MASK_REDUCE); #if ATH_ANT_DIV_COMB if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) { if (ahp->ah_diversity_control == HAL_ANT_VARIABLE) { u_int8_t ant_div_control1 = ar9300_eeprom_get(ahp, EEP_ANTDIV_control); /* if enable_lnadiv is 0x1 and enable_fast_div is 0x1, * we enable the diversity-combining algorithm. */ if ((ant_div_control1 >> 0x6) == 0x3) { p_cap->halAntDivCombSupport = AH_TRUE; } p_cap->halAntDivCombSupportOrg = p_cap->halAntDivCombSupport; } } #endif /* ATH_ANT_DIV_COMB */ /* * FreeBSD: enable LNA mixing if the chip is Hornet or Poseidon. */ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) { p_cap->halRxUsingLnaMixing = AH_TRUE; } /* * AR5416 and later NICs support MYBEACON filtering. */ p_cap->halRxDoMyBeacon = AH_TRUE; #if ATH_WOW_OFFLOAD if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { p_cap->hal_wow_gtk_offload_support = AH_TRUE; p_cap->hal_wow_arp_offload_support = AH_TRUE; p_cap->hal_wow_ns_offload_support = AH_TRUE; p_cap->hal_wow_4way_hs_wakeup_support = AH_TRUE; p_cap->hal_wow_acer_magic_support = AH_TRUE; p_cap->hal_wow_acer_swka_support = AH_TRUE; } else { p_cap->hal_wow_gtk_offload_support = AH_FALSE; p_cap->hal_wow_arp_offload_support = AH_FALSE; p_cap->hal_wow_ns_offload_support = AH_FALSE; p_cap->hal_wow_4way_hs_wakeup_support = AH_FALSE; p_cap->hal_wow_acer_magic_support = AH_FALSE; p_cap->hal_wow_acer_swka_support = AH_FALSE; } #endif /* ATH_WOW_OFFLOAD */ return AH_TRUE; #undef AR_KEYTABLE_SIZE } #if 0 static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans) { struct ath_hal_9300 *ahp = AH9300(ah); return ahp->ah_rf_hal.get_chip_power_lim(ah, chans, nchans); } #endif /* XXX FreeBSD */ static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah, struct ieee80211_channel *chan) { chan->ic_maxpower = AR9300_MAX_RATE_POWER; chan->ic_minpower = 0; return AH_TRUE; } /* * Disable PLL when in L0s as well as receiver clock when in L1. * This power saving option must be enabled through the Serdes. * * Programming the Serdes must go through the same 288 bit serial shift * register as the other analog registers. Hence the 9 writes. * * XXX Clean up the magic numbers. */ void ar9300_config_pci_power_save(struct ath_hal *ah, int restore, int power_off) { struct ath_hal_9300 *ahp = AH9300(ah); int i; if (AH_PRIVATE(ah)->ah_ispcie != AH_TRUE) { return; } /* * Increase L1 Entry Latency. Some WB222 boards don't have * this change in eeprom/OTP. */ if (AR_SREV_JUPITER(ah)) { u_int32_t val = ah->ah_config.ath_hal_war70c; if ((val & 0xff000000) == 0x17000000) { val &= 0x00ffffff; val |= 0x27000000; OS_REG_WRITE(ah, 0x570c, val); } } /* Do not touch SERDES registers */ if (ah->ah_config.ath_hal_pcie_power_save_enable == 2) { return; } /* Nothing to do on restore for 11N */ if (!restore) { /* set bit 19 to allow forcing of pcie core into L1 state */ OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), AR_PCIE_PM_CTRL_ENA); /* * Set PCIE workaround config only if requested, else use the reset * value of this register. */ if (ah->ah_config.ath_hal_pcie_waen) { OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ah->ah_config.ath_hal_pcie_waen); } else { /* Set Bits 17 and 14 in the AR_WA register. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val); } } /* Configure PCIE after Ini init. SERDES values now come from ini file */ if (ah->ah_config.ath_hal_pcie_ser_des_write) { if (power_off) { for (i = 0; i < ahp->ah_ini_pcie_serdes.ia_rows; i++) { OS_REG_WRITE(ah, INI_RA(&ahp->ah_ini_pcie_serdes, i, 0), INI_RA(&ahp->ah_ini_pcie_serdes, i, 1)); } } else { for (i = 0; i < ahp->ah_ini_pcie_serdes_low_power.ia_rows; i++) { OS_REG_WRITE(ah, INI_RA(&ahp->ah_ini_pcie_serdes_low_power, i, 0), INI_RA(&ahp->ah_ini_pcie_serdes_low_power, i, 1)); } } } } /* * Recipe from charles to turn off PCIe PHY in PCI mode for power savings */ void ar9300_disable_pcie_phy(struct ath_hal *ah) { /* Osprey does not support PCI mode */ } static inline HAL_STATUS ar9300_init_mac_addr(struct ath_hal *ah) { u_int32_t sum; int i; u_int16_t eeval; struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t EEP_MAC [] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; sum = 0; for (i = 0; i < 3; i++) { eeval = ar9300_eeprom_get(ahp, EEP_MAC[i]); sum += eeval; ahp->ah_macaddr[2*i] = eeval >> 8; ahp->ah_macaddr[2*i + 1] = eeval & 0xff; } if (sum == 0 || sum == 0xffff*3) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: mac address read failed: %s\n", __func__, ath_hal_ether_sprintf(ahp->ah_macaddr)); return HAL_EEBADMAC; } return HAL_OK; } /* * Code for the "real" chip i.e. non-emulation. Review and revisit * when actual hardware is at hand. */ static inline HAL_STATUS ar9300_hw_attach(struct ath_hal *ah) { HAL_STATUS ecode; if (!ar9300_chip_test(ah)) { HALDEBUG(ah, HAL_DEBUG_REGIO, "%s: hardware self-test failed\n", __func__); return HAL_ESELFTEST; } ath_hal_printf(ah, "%s: calling ar9300_eeprom_attach\n", __func__); ecode = ar9300_eeprom_attach(ah); ath_hal_printf(ah, "%s: ar9300_eeprom_attach returned %d\n", __func__, ecode); if (ecode != HAL_OK) { return ecode; } if (!ar9300_rf_attach(ah, &ecode)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: RF setup failed, status %u\n", __func__, ecode); } if (ecode != HAL_OK) { return ecode; } ar9300_ani_attach(ah); return HAL_OK; } static inline void ar9300_hw_detach(struct ath_hal *ah) { /* XXX EEPROM allocated state */ ar9300_ani_detach(ah); } static int16_t ar9300_get_nf_adjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) { return 0; } void ar9300_set_immunity(struct ath_hal *ah, HAL_BOOL enable) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t m1_thresh_low = enable ? 127 : ahp->ah_immunity_vals[0], m2_thresh_low = enable ? 127 : ahp->ah_immunity_vals[1], m1_thresh = enable ? 127 : ahp->ah_immunity_vals[2], m2_thresh = enable ? 127 : ahp->ah_immunity_vals[3], m2_count_thr = enable ? 31 : ahp->ah_immunity_vals[4], m2_count_thr_low = enable ? 63 : ahp->ah_immunity_vals[5]; if (ahp->ah_immunity_on == enable) { return; } ahp->ah_immunity_on = enable; OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M1_THRESH, m1_thresh); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2_THRESH, m2_thresh); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2COUNT_THR, m2_count_thr); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2_count_thr_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2_thresh_low); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH, m1_thresh); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH, m2_thresh); if (!enable) { OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); } else { OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); } } /* XXX FreeBSD: I'm not sure how to implement this.. */ #if 0 int ar9300_get_cal_intervals(struct ath_hal *ah, HAL_CALIBRATION_TIMER **timerp, HAL_CAL_QUERY query) { #define AR9300_IS_CHAIN_RX_IQCAL_INVALID(_ah, _reg) \ ((OS_REG_READ((_ah), _reg) & 0x3fff) == 0) #define AR9300_IS_RX_IQCAL_DISABLED(_ah) \ (!(OS_REG_READ((_ah), AR_PHY_RX_IQCAL_CORR_B0) & \ AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE)) /* Avoid comilation warnings. Variables are not used when EMULATION. */ struct ath_hal_9300 *ahp = AH9300(ah); u_int8_t rxchainmask = ahp->ah_rx_chainmask, i; int rx_iqcal_invalid = 0, num_chains = 0; static const u_int32_t offset_array[3] = { AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2}; *timerp = ar9300_cals; switch (query) { case HAL_QUERY_CALS: return AR9300_NUM_CAL_TYPES; case HAL_QUERY_RERUN_CALS: for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (rxchainmask & (1 << i)) { num_chains++; } } for (i = 0; i < num_chains; i++) { if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { HALASSERT(num_chains == 0x1); } if (AR9300_IS_CHAIN_RX_IQCAL_INVALID(ah, offset_array[i])) { rx_iqcal_invalid = 1; } } if (AR9300_IS_RX_IQCAL_DISABLED(ah)) { rx_iqcal_invalid = 1; } return rx_iqcal_invalid; default: HALASSERT(0); } return 0; } #endif #if ATH_TRAFFIC_FAST_RECOVER #define PLL3 0x16188 #define PLL3_DO_MEAS_MASK 0x40000000 #define PLL4 0x1618c #define PLL4_MEAS_DONE 0x8 #define SQSUM_DVC_MASK 0x007ffff8 unsigned long ar9300_get_pll3_sqsum_dvc(struct ath_hal *ah) { if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { OS_REG_WRITE(ah, PLL3, (OS_REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); OS_DELAY(100); OS_REG_WRITE(ah, PLL3, (OS_REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); while ( (OS_REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { OS_DELAY(100); } return (( OS_REG_READ(ah, PLL3) & SQSUM_DVC_MASK ) >> 3); } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: unable to get pll3_sqsum_dvc\n", __func__); return 0; } } #endif #define RX_GAIN_TABLE_LENGTH 128 // this will be called if rfGainCAP is enabled and rfGainCAP setting is changed, // or rxGainTable setting is changed HAL_BOOL ar9300_rf_gain_cap_apply(struct ath_hal *ah, int is_2GHz) { int i, done = 0, i_rx_gain = 32; u_int32_t rf_gain_cap; u_int32_t rx_gain_value, a_Byte, rx_gain_value_caped; static u_int32_t rx_gain_table[RX_GAIN_TABLE_LENGTH * 2][2]; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; struct ath_hal_9300 *ahp = AH9300(ah); if ( !((eep->base_eep_header.misc_configuration & 0x80) >> 7) ) return AH_FALSE; if (is_2GHz) { rf_gain_cap = (u_int32_t) eep->modal_header_2g.rf_gain_cap; } else { rf_gain_cap = (u_int32_t) eep->modal_header_5g.rf_gain_cap; } if (rf_gain_cap == 0) return AH_FALSE; for (i = 0; i< RX_GAIN_TABLE_LENGTH * 2; i++) { if (AR_SREV_AR9580(ah)) { // BB_rx_ocgain2 i_rx_gain = 128 + 32; switch (ar9300_rx_gain_index_get(ah)) { case 0: rx_gain_table[i][0] = ar9300_common_rx_gain_table_ar9580_1p0[i][0]; rx_gain_table[i][1] = ar9300_common_rx_gain_table_ar9580_1p0[i][1]; break; case 1: rx_gain_table[i][0] = ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0[i][0]; rx_gain_table[i][1] = ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0[i][1]; break; } } else if (AR_SREV_OSPREY_22(ah)) { i_rx_gain = 128 + 32; switch (ar9300_rx_gain_index_get(ah)) { case 0: rx_gain_table[i][0] = ar9300_common_rx_gain_table_osprey_2p2[i][0]; rx_gain_table[i][1] = ar9300_common_rx_gain_table_osprey_2p2[i][1]; break; case 1: rx_gain_table[i][0] = ar9300Common_wo_xlna_rx_gain_table_osprey_2p2[i][0]; rx_gain_table[i][1] = ar9300Common_wo_xlna_rx_gain_table_osprey_2p2[i][1]; break; } } else { return AH_FALSE; } } while (1) { rx_gain_value = rx_gain_table[i_rx_gain][1]; rx_gain_value_caped = rx_gain_value; a_Byte = rx_gain_value & (0x000000FF); if (a_Byte>rf_gain_cap) { rx_gain_value_caped = (rx_gain_value_caped & (0xFFFFFF00)) + rf_gain_cap; } a_Byte = rx_gain_value & (0x0000FF00); if ( a_Byte > ( rf_gain_cap << 8 ) ) { rx_gain_value_caped = (rx_gain_value_caped & (0xFFFF00FF)) + (rf_gain_cap<<8); } a_Byte = rx_gain_value & (0x00FF0000); if ( a_Byte > ( rf_gain_cap << 16 ) ) { rx_gain_value_caped = (rx_gain_value_caped & (0xFF00FFFF)) + (rf_gain_cap<<16); } a_Byte = rx_gain_value & (0xFF000000); if ( a_Byte > ( rf_gain_cap << 24 ) ) { rx_gain_value_caped = (rx_gain_value_caped & (0x00FFFFFF)) + (rf_gain_cap<<24); } else { done = 1; } HALDEBUG(ah, HAL_DEBUG_RESET, "%s: rx_gain_address: %x, rx_gain_value: %x rx_gain_value_caped: %x\n", __func__, rx_gain_table[i_rx_gain][0], rx_gain_value, rx_gain_value_caped); if (rx_gain_value_caped != rx_gain_value) { rx_gain_table[i_rx_gain][1] = rx_gain_value_caped; } if (done == 1) break; i_rx_gain ++; } INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, rx_gain_table, ARRAY_LENGTH(rx_gain_table), 2); return AH_TRUE; } void ar9300_rx_gain_table_apply(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); //struct ath_hal_private *ahpriv = AH_PRIVATE(ah); u_int32_t xlan_gpio_cfg; u_int8_t i; if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah)) { // this will be called if rxGainTable setting is changed if (ar9300_rf_gain_cap_apply(ah, 1)) return; } switch (ar9300_rx_gain_index_get(ah)) { case 2: if (AR_SREV_JUPITER_10(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_mixed_rx_gain_table_jupiter_1p0, ARRAY_LENGTH(ar9300_common_mixed_rx_gain_table_jupiter_1p0), 2); break; } else if (AR_SREV_JUPITER_20(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300Common_mixed_rx_gain_table_jupiter_2p0, ARRAY_LENGTH(ar9300Common_mixed_rx_gain_table_jupiter_2p0), 2); break; } case 0: default: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_rx_gain_hornet1_2, ARRAY_LENGTH(ar9331_common_rx_gain_hornet1_2), 2); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_rx_gain_hornet1_1, ARRAY_LENGTH(ar9331_common_rx_gain_hornet1_1), 2); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485_common_wo_xlna_rx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_common_wo_xlna_rx_gain_poseidon1_1), 2); /* XXX FreeBSD: this needs to be revisited!! */ xlan_gpio_cfg = ah->ah_config.ath_hal_ext_lna_ctl_gpio; if (xlan_gpio_cfg) { for (i = 0; i < 32; i++) { if (xlan_gpio_cfg & (1 << i)) { /* * XXX FreeBSD: definitely make sure this * results in the correct value being written * to the hardware, or weird crap is very likely * to occur! */ ath_hal_gpioCfgOutput(ah, i, HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED); } } } } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485Common_wo_xlna_rx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Common_wo_xlna_rx_gain_poseidon1_0), 2); } else if (AR_SREV_JUPITER_10(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_jupiter_1p0, ARRAY_LENGTH(ar9300_common_rx_gain_table_jupiter_1p0), 2); } else if (AR_SREV_JUPITER_20(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300Common_rx_gain_table_jupiter_2p0, ARRAY_LENGTH(ar9300Common_rx_gain_table_jupiter_2p0), 2); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300_common_rx_gain_table_ar9580_1p0), 2); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9340Common_rx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Common_rx_gain_table_wasp_1p0), 2); } else if (AR_SREV_SCORPION(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar955xCommon_rx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_rx_gain_table_scorpion_1p0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, ar955xCommon_rx_gain_bounds_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_rx_gain_bounds_scorpion_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_rx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300_common_rx_gain_table_osprey_2p2), 2); } break; case 1: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_wo_xlna_rx_gain_hornet1_2, ARRAY_LENGTH(ar9331_common_wo_xlna_rx_gain_hornet1_2), 2); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9331_common_wo_xlna_rx_gain_hornet1_1, ARRAY_LENGTH(ar9331_common_wo_xlna_rx_gain_hornet1_1), 2); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485_common_wo_xlna_rx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_common_wo_xlna_rx_gain_poseidon1_1), 2); } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9485Common_wo_xlna_rx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Common_wo_xlna_rx_gain_poseidon1_0), 2); } else if (AR_SREV_JUPITER_10(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_wo_xlna_rx_gain_table_jupiter_1p0, ARRAY_LENGTH(ar9300_common_wo_xlna_rx_gain_table_jupiter_1p0), 2); } else if (AR_SREV_JUPITER_20(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300Common_wo_xlna_rx_gain_table_jupiter_2p0, ARRAY_LENGTH(ar9300Common_wo_xlna_rx_gain_table_jupiter_2p0), 2); } else if (AR_SREV_APHRODITE(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar956XCommon_wo_xlna_rx_gain_table_aphrodite_1p0, ARRAY_LENGTH(ar956XCommon_wo_xlna_rx_gain_table_aphrodite_1p0), 2); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0), 2); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9340Common_wo_xlna_rx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Common_wo_xlna_rx_gain_table_wasp_1p0), 2); } else if (AR_SREV_SCORPION(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0), 2); INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0, ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, ar9300Common_wo_xlna_rx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300Common_wo_xlna_rx_gain_table_osprey_2p2), 2); } break; } } void ar9300_tx_gain_table_apply(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); switch (ar9300_tx_gain_index_get(ah)) { case 0: default: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_lowest_ob_db_tx_gain_hornet1_2, ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_2), 5); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_lowest_ob_db_tx_gain_hornet1_1, ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_1), 5); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1), 5); } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0), 5); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0), 5); } else if (AR_SREV_SCORPION(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar955xModes_xpa_tx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xModes_xpa_tx_gain_table_scorpion_1p0), 9); } else if (AR_SREV_JUPITER_10(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_low_ob_db_tx_gain_table_jupiter_1p0, ARRAY_LENGTH(ar9300_modes_low_ob_db_tx_gain_table_jupiter_1p0), 5); } else if (AR_SREV_JUPITER_20(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_low_ob_db_tx_gain_table_jupiter_2p0, ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_jupiter_2p0), 5); } else if (AR_SREV_APHRODITE(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0, ARRAY_LENGTH(ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2), 5); } break; case 1: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_high_ob_db_tx_gain_hornet1_2, ARRAY_LENGTH(ar9331_modes_high_ob_db_tx_gain_hornet1_2), 5); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_high_ob_db_tx_gain_hornet1_1, ARRAY_LENGTH(ar9331_modes_high_ob_db_tx_gain_hornet1_1), 5); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_high_ob_db_tx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_modes_high_ob_db_tx_gain_poseidon1_1), 5); } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485Modes_high_ob_db_tx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Modes_high_ob_db_tx_gain_poseidon1_0), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_high_ob_db_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_high_ob_db_tx_gain_table_ar9580_1p0), 5); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0), 5); } else if (AR_SREV_SCORPION(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar955xModes_no_xpa_tx_gain_table_scorpion_1p0, ARRAY_LENGTH(ar955xModes_no_xpa_tx_gain_table_scorpion_1p0), 9); } else if (AR_SREV_JUPITER_10(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_high_ob_db_tx_gain_table_jupiter_1p0, ARRAY_LENGTH( ar9300_modes_high_ob_db_tx_gain_table_jupiter_1p0), 5); } else if (AR_SREV_JUPITER_20(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p0, ARRAY_LENGTH( ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p0), 5); } else if (AR_SREV_APHRODITE(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar956XModes_high_ob_db_tx_gain_table_aphrodite_1p0, ARRAY_LENGTH( ar956XModes_high_ob_db_tx_gain_table_aphrodite_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_high_ob_db_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300Modes_high_ob_db_tx_gain_table_osprey_2p2), 5); } break; case 2: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_low_ob_db_tx_gain_hornet1_2, ARRAY_LENGTH(ar9331_modes_low_ob_db_tx_gain_hornet1_2), 5); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_low_ob_db_tx_gain_hornet1_1, ARRAY_LENGTH(ar9331_modes_low_ob_db_tx_gain_hornet1_1), 5); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_low_ob_db_tx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_modes_low_ob_db_tx_gain_poseidon1_1), 5); } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485Modes_low_ob_db_tx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Modes_low_ob_db_tx_gain_poseidon1_0), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_low_ob_db_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_ar9580_1p0), 5); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_low_ob_db_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_low_ob_db_tx_gain_table_wasp_1p0), 5); } else if (AR_SREV_APHRODITE(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0, ARRAY_LENGTH(ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_low_ob_db_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_osprey_2p2), 5); } break; case 3: if (AR_SREV_HORNET_12(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_high_power_tx_gain_hornet1_2, ARRAY_LENGTH(ar9331_modes_high_power_tx_gain_hornet1_2), 5); } else if (AR_SREV_HORNET_11(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9331_modes_high_power_tx_gain_hornet1_1, ARRAY_LENGTH(ar9331_modes_high_power_tx_gain_hornet1_1), 5); } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_high_power_tx_gain_poseidon1_1, ARRAY_LENGTH(ar9485_modes_high_power_tx_gain_poseidon1_1), 5); } else if (AR_SREV_POSEIDON(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485Modes_high_power_tx_gain_poseidon1_0, ARRAY_LENGTH(ar9485Modes_high_power_tx_gain_poseidon1_0), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_high_power_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300Modes_high_power_tx_gain_table_ar9580_1p0), 5); } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_high_power_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_high_power_tx_gain_table_wasp_1p0), 5); } else if (AR_SREV_APHRODITE(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar956XModes_high_power_tx_gain_table_aphrodite_1p0, ARRAY_LENGTH(ar956XModes_high_power_tx_gain_table_aphrodite_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_high_power_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300Modes_high_power_tx_gain_table_osprey_2p2), 5); } break; case 4: if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_mixed_ob_db_tx_gain_table_wasp_1p0, ARRAY_LENGTH(ar9340Modes_mixed_ob_db_tx_gain_table_wasp_1p0), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_mixed_ob_db_tx_gain_table_ar9580_1p0, ARRAY_LENGTH(ar9300_modes_mixed_ob_db_tx_gain_table_ar9580_1p0), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300Modes_mixed_ob_db_tx_gain_table_osprey_2p2, ARRAY_LENGTH(ar9300Modes_mixed_ob_db_tx_gain_table_osprey_2p2), 5); } break; case 5: /* HW Green TX */ if (AR_SREV_POSEIDON(ah)) { if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_green_ob_db_tx_gain_poseidon1_1, sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_1) / sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_1[0]), 5); } else { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_green_ob_db_tx_gain_poseidon1_0, sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_0) / sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_0[0]), 5); } ahp->ah_hw_green_tx_enable = 1; } else if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340_modes_ub124_tx_gain_table_wasp_1p0, sizeof(ar9340_modes_ub124_tx_gain_table_wasp_1p0) / sizeof(ar9340_modes_ub124_tx_gain_table_wasp_1p0[0]), 5); } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_type5_tx_gain_table_ar9580_1p0, ARRAY_LENGTH( ar9300_modes_type5_tx_gain_table_ar9580_1p0), 5); } else if (AR_SREV_OSPREY_22(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_number_5_tx_gain_table_osprey_2p2, ARRAY_LENGTH( ar9300_modes_number_5_tx_gain_table_osprey_2p2), 5); } break; case 6: if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0, sizeof(ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0) / sizeof(ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0[0]), 5); } /* HW Green TX */ else if (AR_SREV_POSEIDON(ah)) { if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1, sizeof(ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1) / sizeof(ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1[0]), 5); } ahp->ah_hw_green_tx_enable = 1; } else if (AR_SREV_AR9580(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9300_modes_type6_tx_gain_table_ar9580_1p0, ARRAY_LENGTH( ar9300_modes_type6_tx_gain_table_ar9580_1p0), 5); } break; case 7: if (AR_SREV_WASP(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, ar9340Modes_cus227_tx_gain_table_wasp_1p0, sizeof(ar9340Modes_cus227_tx_gain_table_wasp_1p0) / sizeof(ar9340Modes_cus227_tx_gain_table_wasp_1p0[0]), 5); } break; } } #if ATH_ANT_DIV_COMB void ar9300_ant_div_comb_get_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG *div_comb_conf) { u_int32_t reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); div_comb_conf->main_lna_conf = MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__READ(reg_val); div_comb_conf->alt_lna_conf = MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__READ(reg_val); div_comb_conf->fast_div_bias = MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__READ(reg_val); if (AR_SREV_HORNET_11(ah)) { div_comb_conf->antdiv_configgroup = HAL_ANTDIV_CONFIG_GROUP_1; } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) { div_comb_conf->antdiv_configgroup = HAL_ANTDIV_CONFIG_GROUP_2; } else { div_comb_conf->antdiv_configgroup = DEFAULT_ANTDIV_CONFIG_GROUP; } /* * XXX TODO: allow the HAL to override the rssithres and fast_div_bias * values (eg CUS198.) */ } void ar9300_ant_div_comb_set_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG *div_comb_conf) { u_int32_t reg_val; struct ath_hal_9300 *ahp = AH9300(ah); /* DO NOTHING when set to fixed antenna for manufacturing purpose */ if (AR_SREV_POSEIDON(ah) && ( ahp->ah_diversity_control == HAL_ANT_FIXED_A || ahp->ah_diversity_control == HAL_ANT_FIXED_B)) { return; } reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); reg_val &= ~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK ); reg_val |= MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__WRITE( div_comb_conf->main_gaintb); reg_val |= MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__WRITE( div_comb_conf->alt_gaintb); reg_val |= MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__WRITE( div_comb_conf->main_lna_conf); reg_val |= MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__WRITE( div_comb_conf->alt_lna_conf); reg_val |= MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__WRITE( div_comb_conf->fast_div_bias); OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val); } #endif /* ATH_ANT_DIV_COMB */ static void ar9300_init_hostif_offsets(struct ath_hal *ah) { AR_HOSTIF_REG(ah, AR_RC) = AR9300_HOSTIF_OFFSET(HOST_INTF_RESET_CONTROL); AR_HOSTIF_REG(ah, AR_WA) = AR9300_HOSTIF_OFFSET(HOST_INTF_WORK_AROUND); AR_HOSTIF_REG(ah, AR_PM_STATE) = AR9300_HOSTIF_OFFSET(HOST_INTF_PM_STATE); AR_HOSTIF_REG(ah, AR_H_INFOL) = AR9300_HOSTIF_OFFSET(HOST_INTF_CXPL_DEBUG_INFOL); AR_HOSTIF_REG(ah, AR_H_INFOH) = AR9300_HOSTIF_OFFSET(HOST_INTF_CXPL_DEBUG_INFOH); AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL) = AR9300_HOSTIF_OFFSET(HOST_INTF_PM_CTRL); AR_HOSTIF_REG(ah, AR_HOST_TIMEOUT) = AR9300_HOSTIF_OFFSET(HOST_INTF_TIMEOUT); AR_HOSTIF_REG(ah, AR_EEPROM) = AR9300_HOSTIF_OFFSET(HOST_INTF_EEPROM_CTRL); AR_HOSTIF_REG(ah, AR_SREV) = AR9300_HOSTIF_OFFSET(HOST_INTF_SREV); AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_ENABLE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_ENABLE); AR_HOSTIF_REG(ah, AR_PCIE_SERDES) = AR9300_HOSTIF_OFFSET(HOST_INTF_PCIE_PHY_RW); AR_HOSTIF_REG(ah, AR_PCIE_SERDES2) = AR9300_HOSTIF_OFFSET(HOST_INTF_PCIE_PHY_LOAD); AR_HOSTIF_REG(ah, AR_GPIO_OUT) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OUT); AR_HOSTIF_REG(ah, AR_GPIO_IN) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_IN); AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OE); AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OE1); AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_INTR_POLAR); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_VALUE); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_MUX1); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_MUX2); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX1); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX2); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX3); AR_HOSTIF_REG(ah, AR_INPUT_STATE) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_STATE); AR_HOSTIF_REG(ah, AR_SPARE) = AR9300_HOSTIF_OFFSET(HOST_INTF_SPARE); AR_HOSTIF_REG(ah, AR_PCIE_CORE_RESET_EN) = AR9300_HOSTIF_OFFSET(HOST_INTF_PCIE_CORE_RST_EN); AR_HOSTIF_REG(ah, AR_CLKRUN) = AR9300_HOSTIF_OFFSET(HOST_INTF_CLKRUN); AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA) = AR9300_HOSTIF_OFFSET(HOST_INTF_EEPROM_STS); AR_HOSTIF_REG(ah, AR_OBS) = AR9300_HOSTIF_OFFSET(HOST_INTF_OBS_CTRL); AR_HOSTIF_REG(ah, AR_RFSILENT) = AR9300_HOSTIF_OFFSET(HOST_INTF_RFSILENT); AR_HOSTIF_REG(ah, AR_GPIO_PDPU) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_PDPU); AR_HOSTIF_REG(ah, AR_GPIO_DS) = AR9300_HOSTIF_OFFSET(HOST_INTF_GPIO_DS); AR_HOSTIF_REG(ah, AR_MISC) = AR9300_HOSTIF_OFFSET(HOST_INTF_MISC); AR_HOSTIF_REG(ah, AR_PCIE_MSI) = AR9300_HOSTIF_OFFSET(HOST_INTF_PCIE_MSI); #if 0 /* Offsets are not defined in reg_map structure */ AR_HOSTIF_REG(ah, AR_TSF_SNAPSHOT_BT_ACTIVE) = AR9300_HOSTIF_OFFSET(HOST_INTF_TSF_SNAPSHOT_BT_ACTIVE); AR_HOSTIF_REG(ah, AR_TSF_SNAPSHOT_BT_PRIORITY) = AR9300_HOSTIF_OFFSET(HOST_INTF_TSF_SNAPSHOT_BT_PRIORITY); AR_HOSTIF_REG(ah, AR_TSF_SNAPSHOT_BT_CNTL) = AR9300_HOSTIF_OFFSET(HOST_INTF_MAC_TSF_SNAPSHOT_BT_CNTL); #endif AR_HOSTIF_REG(ah, AR_PCIE_PHY_LATENCY_NFTS_ADJ) = AR9300_HOSTIF_OFFSET(HOST_INTF_PCIE_PHY_LATENCY_NFTS_ADJ); AR_HOSTIF_REG(ah, AR_TDMA_CCA_CNTL) = AR9300_HOSTIF_OFFSET(HOST_INTF_MAC_TDMA_CCA_CNTL); AR_HOSTIF_REG(ah, AR_TXAPSYNC) = AR9300_HOSTIF_OFFSET(HOST_INTF_MAC_TXAPSYNC); AR_HOSTIF_REG(ah, AR_TXSYNC_INIT_SYNC_TMR) = AR9300_HOSTIF_OFFSET(HOST_INTF_MAC_TXSYNC_INITIAL_SYNC_TMR); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_CAUSE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_ENABLE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_ENABLE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_MASK) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_CAUSE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE) = AR9300_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_ENABLE); } static void ar9340_init_hostif_offsets(struct ath_hal *ah) { AR_HOSTIF_REG(ah, AR_RC) = AR9340_HOSTIF_OFFSET(HOST_INTF_RESET_CONTROL); AR_HOSTIF_REG(ah, AR_WA) = AR9340_HOSTIF_OFFSET(HOST_INTF_WORK_AROUND); AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL) = AR9340_HOSTIF_OFFSET(HOST_INTF_PM_CTRL); AR_HOSTIF_REG(ah, AR_HOST_TIMEOUT) = AR9340_HOSTIF_OFFSET(HOST_INTF_TIMEOUT); AR_HOSTIF_REG(ah, AR_SREV) = AR9340_HOSTIF_OFFSET(HOST_INTF_SREV); AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_ENABLE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_SYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_ASYNC_ENABLE); AR_HOSTIF_REG(ah, AR_GPIO_OUT) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OUT); AR_HOSTIF_REG(ah, AR_GPIO_IN) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_IN); AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OE); AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OE1); AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_INTR_POLAR); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_VALUE); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_MUX1); AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_MUX2); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX1); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX2); AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_OUTPUT_MUX3); AR_HOSTIF_REG(ah, AR_INPUT_STATE) = AR9340_HOSTIF_OFFSET(HOST_INTF_GPIO_INPUT_STATE); AR_HOSTIF_REG(ah, AR_CLKRUN) = AR9340_HOSTIF_OFFSET(HOST_INTF_CLKRUN); AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA) = AR9340_HOSTIF_OFFSET(HOST_INTF_EEPROM_STS); AR_HOSTIF_REG(ah, AR_OBS) = AR9340_HOSTIF_OFFSET(HOST_INTF_OBS_CTRL); AR_HOSTIF_REG(ah, AR_RFSILENT) = AR9340_HOSTIF_OFFSET(HOST_INTF_RFSILENT); AR_HOSTIF_REG(ah, AR_MISC) = AR9340_HOSTIF_OFFSET(HOST_INTF_MISC); AR_HOSTIF_REG(ah, AR_PCIE_MSI) = AR9340_HOSTIF_OFFSET(HOST_INTF_PCIE_MSI); AR_HOSTIF_REG(ah, AR_TDMA_CCA_CNTL) = AR9340_HOSTIF_OFFSET(HOST_INTF_MAC_TDMA_CCA_CNTL); AR_HOSTIF_REG(ah, AR_TXAPSYNC) = AR9340_HOSTIF_OFFSET(HOST_INTF_MAC_TXAPSYNC); AR_HOSTIF_REG(ah, AR_TXSYNC_INIT_SYNC_TMR) = AR9340_HOSTIF_OFFSET(HOST_INTF_MAC_TXSYNC_INITIAL_SYNC_TMR); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_CAUSE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_ENABLE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_ENABLE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_MASK) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_SYNC_MASK); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_CAUSE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_CAUSE); AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE) = AR9340_HOSTIF_OFFSET(HOST_INTF_INTR_PRIORITY_ASYNC_ENABLE); } /* * Host interface register offsets are different for Osprey and Wasp * and hence store the offsets in hal structure */ static int ar9300_init_offsets(struct ath_hal *ah, u_int16_t devid) { if (devid == AR9300_DEVID_AR9340) { ar9340_init_hostif_offsets(ah); } else { ar9300_init_hostif_offsets(ah); } return 0; } static const char* ar9300_probe(uint16_t vendorid, uint16_t devid) { if (vendorid != ATHEROS_VENDOR_ID) return AH_NULL; switch (devid) { case AR9300_DEVID_AR9380_PCIE: /* PCIE (Osprey) */ return "Atheros AR938x"; case AR9300_DEVID_AR9340: /* Wasp */ return "Atheros AR934x"; case AR9300_DEVID_AR9485_PCIE: /* Poseidon */ return "Atheros AR9485"; case AR9300_DEVID_AR9580_PCIE: /* Peacock */ return "Atheros AR9580"; case AR9300_DEVID_AR946X_PCIE: /* AR9462, AR9463, AR9482 */ return "Atheros AR946x/AR948x"; case AR9300_DEVID_AR9330: /* Hornet */ return "Atheros AR933x"; case AR9300_DEVID_QCA955X: /* Scorpion */ return "Qualcomm Atheros QCA955x"; case AR9300_DEVID_QCA9565: /* Aphrodite */ return "Qualcomm Atheros AR9565"; case AR9300_DEVID_AR1111_PCIE: return "Atheros AR1111"; default: return AH_NULL; } return AH_NULL; } AH_CHIP(AR9300, ar9300_probe, ar9300_attach); Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c (revision 278741) @@ -1,195 +1,201 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #define TU_TO_USEC(_tu) ((_tu) << 10) #define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7) extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q); /* * Initializes all of the hardware registers used to * send beacons. Note that for station operation the * driver calls ar9300_set_sta_beacon_timers instead. */ void ar9300_beacon_init(struct ath_hal *ah, - u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode) + u_int32_t next_beacon, u_int32_t beacon_period, + u_int32_t beacon_period_fraction, HAL_OPMODE opmode) { u_int32_t beacon_period_usec; HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP); if (opmode == HAL_M_IBSS) { OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); } OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, ONE_EIGHTH_TU_TO_USEC(next_beacon)); OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, (ONE_EIGHTH_TU_TO_USEC(next_beacon) - ah->ah_config.ah_dma_beacon_response_time)); OS_REG_WRITE(ah, AR_NEXT_SWBA, (ONE_EIGHTH_TU_TO_USEC(next_beacon) - ah->ah_config.ah_sw_beacon_response_time)); beacon_period_usec = ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8); + + /* Add the fraction adjustment lost due to unit conversions. */ + beacon_period_usec += beacon_period_fraction; + + OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec); OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec); OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec); /* reset TSF if required */ if (beacon_period & HAL_BEACON_RESET_TSF) { ar9300_reset_tsf(ah); } /* enable timers */ OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN); } /* * Set all the beacon related bits on the h/w for stations * i.e. initializes the corresponding h/w timers; */ void ar9300_set_sta_beacon_timers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) { u_int32_t next_tbtt, beaconintval, dtimperiod, beacontimeout; HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; HALASSERT(bs->bs_intval != 0); /* no cfp setting since h/w automatically takes care */ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); /* * Start the beacon timers by setting the BEACON register * to the beacon interval; no need to write tim offset since * h/w parses IEs. */ OS_REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD)); /* * Configure the BMISS interrupt. Note that we * assume the caller blocks interrupts while enabling * the threshold. */ HALASSERT(bs->bs_bmissthreshold <= (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S)); OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); /* * Program the sleep registers to correlate with the beacon setup. */ /* * Current implementation assumes sw processing of beacons - * assuming an interrupt is generated every beacon which * causes the hardware to become awake until the sw tells * it to go to sleep again; beacon timeout is to allow for * beacon jitter; cab timeout is max time to wait for cab * after seeing the last DTIM or MORE CAB bit */ #define CAB_TIMEOUT_VAL 10 /* in TU */ #define BEACON_TIMEOUT_VAL 10 /* in TU */ #define MIN_BEACON_TIMEOUT_VAL 1 /* in 1/8 TU */ #define SLEEP_SLOP 3 /* in TU */ /* * For max powersave mode we may want to sleep for longer than a * beacon period and not want to receive all beacons; modify the * timers accordingly; make sure to align the next TIM to the * next DTIM if we decide to wake for DTIMs only */ beaconintval = bs->bs_intval & HAL_BEACON_PERIOD; HALASSERT(beaconintval != 0); if (bs->bs_sleepduration > beaconintval) { HALASSERT(roundup(bs->bs_sleepduration, beaconintval) == bs->bs_sleepduration); beaconintval = bs->bs_sleepduration; } dtimperiod = bs->bs_dtimperiod; if (bs->bs_sleepduration > dtimperiod) { HALASSERT(dtimperiod == 0 || roundup(bs->bs_sleepduration, dtimperiod) == bs->bs_sleepduration); dtimperiod = bs->bs_sleepduration; } HALASSERT(beaconintval <= dtimperiod); if (beaconintval == dtimperiod) { next_tbtt = bs->bs_nextdtim; } else { next_tbtt = bs->bs_nexttbtt; } HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", __func__, bs->bs_nextdtim); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", __func__, next_tbtt); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n", __func__, beaconintval); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n", __func__, dtimperiod); OS_REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(next_tbtt - SLEEP_SLOP)); /* cab timeout is now in 1/8 TU */ OS_REG_WRITE(ah, AR_SLEEP1, SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) | AR_SLEEP1_ASSUME_DTIM); /* beacon timeout is now in 1/8 TU */ if (p_cap->halAutoSleepSupport) { beacontimeout = (BEACON_TIMEOUT_VAL << 3); } else { /* * Use a very small value to make sure the timeout occurs before * the TBTT. In this case the chip will not go back to sleep * automatically, instead it will wait for the SW to explicitly * set it to that mode. */ beacontimeout = MIN_BEACON_TIMEOUT_VAL; } OS_REG_WRITE(ah, AR_SLEEP2, SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); /* clear HOST AP related timers first */ OS_REG_CLR_BIT(ah, AR_TIMER_MODE, (AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN)); OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | AR_DTIM_TIMER_EN); /* TSF out of range threshold */ OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); #undef CAB_TIMEOUT_VAL #undef BEACON_TIMEOUT_VAL #undef SLEEP_SLOP } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c (revision 278741) @@ -1,4611 +1,4720 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #ifdef AH_DEBUG #include "ah_desc.h" /* NB: for HAL_PHYERR* */ #endif #include "ar9300/ar9300.h" #include "ar9300/ar9300eep.h" #include "ar9300/ar9300template_generic.h" #include "ar9300/ar9300template_xb112.h" #include "ar9300/ar9300template_hb116.h" #include "ar9300/ar9300template_xb113.h" #include "ar9300/ar9300template_hb112.h" #include "ar9300/ar9300template_ap121.h" #include "ar9300/ar9300template_osprey_k31.h" #include "ar9300/ar9300template_wasp_2.h" #include "ar9300/ar9300template_wasp_k31.h" #include "ar9300/ar9300template_aphrodite.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300phy.h" #if AH_BYTE_ORDER == AH_BIG_ENDIAN void ar9300_swap_eeprom(ar9300_eeprom_t *eep); void ar9300_eeprom_template_swap(void); #endif static u_int16_t ar9300_eeprom_get_spur_chan(struct ath_hal *ah, int spur_chan, HAL_BOOL is_2ghz); #ifdef UNUSED static inline HAL_BOOL ar9300_fill_eeprom(struct ath_hal *ah); static inline HAL_STATUS ar9300_check_eeprom(struct ath_hal *ah); #endif static ar9300_eeprom_t *default9300[] = { &ar9300_template_generic, &ar9300_template_xb112, &ar9300_template_hb116, &ar9300_template_hb112, &ar9300_template_xb113, &ar9300_template_ap121, &ar9300_template_wasp_2, &ar9300_template_wasp_k31, &ar9300_template_osprey_k31, &ar9300_template_aphrodite, }; /* * Different types of memory where the calibration data might be stored. * All types are searched in ar9300_eeprom_restore() * in the order flash, eeprom, otp. * To disable searching a type, set its parameter to 0. */ /* * This is where we look for the calibration data. * must be set before ath_attach() is called */ static int calibration_data_try = calibration_data_none; static int calibration_data_try_address = 0; /* * Set the type of memory used to store calibration data. * Used by nart to force reading/writing of a specific type. * The driver can normally allow autodetection * by setting source to calibration_data_none=0. */ void ar9300_calibration_data_set(struct ath_hal *ah, int32_t source) { if (ah != 0) { AH9300(ah)->calibration_data_source = source; } else { calibration_data_try = source; } } int32_t ar9300_calibration_data_get(struct ath_hal *ah) { if (ah != 0) { return AH9300(ah)->calibration_data_source; } else { return calibration_data_try; } } /* * Set the address of first byte used to store calibration data. * Used by nart to force reading/writing at a specific address. * The driver can normally allow autodetection by setting size=0. */ void ar9300_calibration_data_address_set(struct ath_hal *ah, int32_t size) { if (ah != 0) { AH9300(ah)->calibration_data_source_address = size; } else { calibration_data_try_address = size; } } int32_t ar9300_calibration_data_address_get(struct ath_hal *ah) { if (ah != 0) { return AH9300(ah)->calibration_data_source_address; } else { return calibration_data_try_address; } } /* * This is the template that is loaded if ar9300_eeprom_restore() * can't find valid data in the memory. */ static int Ar9300_eeprom_template_preference = ar9300_eeprom_template_generic; void ar9300_eeprom_template_preference(int32_t value) { Ar9300_eeprom_template_preference = value; } /* * Install the specified default template. * Overwrites any existing calibration and configuration information in memory. */ int32_t ar9300_eeprom_template_install(struct ath_hal *ah, int32_t value) { struct ath_hal_9300 *ahp = AH9300(ah); ar9300_eeprom_t *mptr, *dptr; int mdata_size; mptr = &ahp->ah_eeprom; mdata_size = ar9300_eeprom_struct_size(); if (mptr != 0) { #if 0 calibration_data_source = calibration_data_none; calibration_data_source_address = 0; #endif dptr = ar9300_eeprom_struct_default_find_by_id(value); if (dptr != 0) { OS_MEMCPY(mptr, dptr, mdata_size); return 0; } } return -1; } static int ar9300_eeprom_restore_something(struct ath_hal *ah, ar9300_eeprom_t *mptr, int mdata_size) { int it; ar9300_eeprom_t *dptr; int nptr; nptr = -1; /* * if we didn't find any blocks in the memory, * put the prefered template in place */ if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; dptr = ar9300_eeprom_struct_default_find_by_id( Ar9300_eeprom_template_preference); if (dptr != 0) { OS_MEMCPY(mptr, dptr, mdata_size); nptr = 0; } } /* * if we didn't find the prefered one, * put the normal default template in place */ if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; dptr = ar9300_eeprom_struct_default_find_by_id( ar9300_eeprom_template_default); if (dptr != 0) { OS_MEMCPY(mptr, dptr, mdata_size); nptr = 0; } } /* * if we can't find the best template, put any old template in place * presume that newer ones are better, so search backwards */ if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; for (it = ar9300_eeprom_struct_default_many() - 1; it >= 0; it--) { dptr = ar9300_eeprom_struct_default(it); if (dptr != 0) { OS_MEMCPY(mptr, dptr, mdata_size); nptr = 0; break; } } } return nptr; } /* * Read 16 bits of data from offset into *data */ HAL_BOOL ar9300_eeprom_read_word(struct ath_hal *ah, u_int off, u_int16_t *data) { if (AR_SREV_OSPREY(ah) || AR_SREV_POSEIDON(ah)) { (void) OS_REG_READ(ah, AR9300_EEPROM_OFFSET + (off << AR9300_EEPROM_S)); if (!ath_hal_wait(ah, AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA), AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { return AH_FALSE; } *data = MS(OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA)), AR_EEPROM_STATUS_DATA_VAL); return AH_TRUE; } else { *data = 0; return AH_FALSE; } } HAL_BOOL ar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi) { int time_out = 1000; int status = 0; u_int32_t addr; addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah))? OTP_MEM_START_ADDRESS_WASP : OTP_MEM_START_ADDRESS; if (!is_wifi) { addr = BTOTP_MEM_START_ADDRESS; } addr += off * 4; /* OTP is 32 bit addressable */ (void) OS_REG_READ(ah, addr); addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ? OTP_STATUS0_OTP_SM_BUSY_WASP : OTP_STATUS0_OTP_SM_BUSY; if (!is_wifi) { addr = BTOTP_STATUS0_OTP_SM_BUSY; } while ((time_out > 0) && (!status)) { /* wait for access complete */ /* Read data valid, access not busy, sm not busy */ status = ((OS_REG_READ(ah, addr) & 0x7) == 0x4) ? 1 : 0; time_out--; } if (time_out == 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Timed out during OTP Status0 validation\n", __func__); return AH_FALSE; } addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ? OTP_STATUS1_EFUSE_READ_DATA_WASP : OTP_STATUS1_EFUSE_READ_DATA; if (!is_wifi) { addr = BTOTP_STATUS1_EFUSE_READ_DATA; } *data = OS_REG_READ(ah, addr); return AH_TRUE; } static HAL_STATUS ar9300_flash_map(struct ath_hal *ah) { /* XXX disable flash remapping for now (ie, SoC support) */ ath_hal_printf(ah, "%s: unimplemented for now\n", __func__); #if 0 struct ath_hal_9300 *ahp = AH9300(ah); #if defined(AR9100) || defined(__NetBSD__) ahp->ah_cal_mem = OS_REMAP(ah, AR9300_EEPROM_START_ADDR, AR9300_EEPROM_MAX); #else ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st), (AR9300_EEPROM_MAX + AR9300_FLASH_CAL_START_OFFSET)); #endif if (!ahp->ah_cal_mem) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: cannot remap eeprom region \n", __func__); return HAL_EIO; } #endif return HAL_OK; } HAL_BOOL ar9300_flash_read(struct ath_hal *ah, u_int off, u_int16_t *data) { struct ath_hal_9300 *ahp = AH9300(ah); *data = ((u_int16_t *)ahp->ah_cal_mem)[off]; return AH_TRUE; } HAL_BOOL ar9300_flash_write(struct ath_hal *ah, u_int off, u_int16_t data) { struct ath_hal_9300 *ahp = AH9300(ah); ((u_int16_t *)ahp->ah_cal_mem)[off] = data; return AH_TRUE; } HAL_STATUS ar9300_eeprom_attach(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->try_dram = 1; ahp->try_eeprom = 1; ahp->try_otp = 1; #ifdef ATH_CAL_NAND_FLASH ahp->try_nand = 1; #else ahp->try_flash = 1; #endif ahp->calibration_data_source = calibration_data_none; ahp->calibration_data_source_address = 0; ahp->calibration_data_try = calibration_data_try; ahp->calibration_data_try_address = 0; /* * In case flash will be used for EEPROM. Otherwise ahp->ah_cal_mem * must be set to NULL or the real EEPROM address. */ ar9300_flash_map(ah); /* * ###### This function always return NO SPUR. * This is not AH_TRUE for many board designs. * Does anyone use this? */ AH_PRIVATE(ah)->ah_getSpurChan = ar9300_eeprom_get_spur_chan; #ifdef OLDCODE /* XXX Needs to be moved for dynamic selection */ ahp->ah_eeprom = *(default9300[ar9300_eeprom_template_default]); if (AR_SREV_HORNET(ah)) { /* Set default values for Hornet. */ ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags = AR9300_OPFLAGS_11G; ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11; } else if (AR_SREV_POSEIDON(ah)) { /* Set default values for Poseidon. */ ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags = AR9300_OPFLAGS_11G; ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11; } if (AH_PRIVATE(ah)->ah_config.ath_hal_skip_eeprom_read) { ahp->ah_emu_eeprom = 1; return HAL_OK; } ahp->ah_emu_eeprom = 1; #ifdef UNUSED #endif if (!ar9300_fill_eeprom(ah)) { return HAL_EIO; } return HAL_OK; /* return ar9300_check_eeprom(ah); */ #else ahp->ah_emu_eeprom = 1; #if 0 /*#ifdef MDK_AP*/ /* MDK_AP is defined only in NART AP build */ u_int8_t buffer[10]; int caldata_check = 0; ar9300_calibration_data_read_flash( ah, FLASH_BASE_CALDATA_OFFSET, buffer, 4); printf("flash caldata:: %x\n", buffer[0]); if (buffer[0] != 0xff) { caldata_check = 1; } if (!caldata_check) { ar9300_eeprom_t *mptr; int mdata_size; if (AR_SREV_HORNET(ah)) { /* XXX: For initial testing */ mptr = &ahp->ah_eeprom; mdata_size = ar9300_eeprom_struct_size(); ahp->ah_eeprom = ar9300_template_ap121; ahp->ah_emu_eeprom = 1; /* need it to let art save in to flash ????? */ calibration_data_source = calibration_data_flash; } else if (AR_SREV_WASP(ah)) { /* XXX: For initial testing */ ath_hal_printf(ah, " wasp eep attach\n"); mptr = &ahp->ah_eeprom; mdata_size = ar9300_eeprom_struct_size(); ahp->ah_eeprom = ar9300_template_generic; ahp->ah_eeprom.mac_addr[0] = 0x00; ahp->ah_eeprom.mac_addr[1] = 0x03; ahp->ah_eeprom.mac_addr[2] = 0x7F; ahp->ah_eeprom.mac_addr[3] = 0xBA; ahp->ah_eeprom.mac_addr[4] = 0xD0; ahp->ah_eeprom.mac_addr[5] = 0x00; ahp->ah_emu_eeprom = 1; ahp->ah_eeprom.base_eep_header.txrx_mask = 0x33; ahp->ah_eeprom.base_eep_header.txrxgain = 0x10; /* need it to let art save in to flash ????? */ calibration_data_source = calibration_data_flash; } return HAL_OK; } #endif if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { ahp->try_eeprom = 0; } if (!ar9300_eeprom_restore(ah)) { return HAL_EIO; } return HAL_OK; #endif } u_int32_t ar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param) { ar9300_eeprom_t *eep = &ahp->ah_eeprom; OSPREY_BASE_EEP_HEADER *p_base = &eep->base_eep_header; OSPREY_BASE_EXTENSION_1 *base_ext1 = &eep->base_ext1; switch (param) { #ifdef NOTYET case EEP_NFTHRESH_5: return p_modal[0].noise_floor_thresh_ch[0]; case EEP_NFTHRESH_2: return p_modal[1].noise_floor_thresh_ch[0]; #endif case EEP_MAC_LSW: return eep->mac_addr[0] << 8 | eep->mac_addr[1]; case EEP_MAC_MID: return eep->mac_addr[2] << 8 | eep->mac_addr[3]; case EEP_MAC_MSW: return eep->mac_addr[4] << 8 | eep->mac_addr[5]; case EEP_REG_0: return p_base->reg_dmn[0]; case EEP_REG_1: return p_base->reg_dmn[1]; case EEP_OP_CAP: return p_base->device_cap; case EEP_OP_MODE: return p_base->op_cap_flags.op_flags; case EEP_RF_SILENT: return p_base->rf_silent; #ifdef NOTYET case EEP_OB_5: return p_modal[0].ob; case EEP_DB_5: return p_modal[0].db; case EEP_OB_2: return p_modal[1].ob; case EEP_DB_2: return p_modal[1].db; case EEP_MINOR_REV: return p_base->eeprom_version & AR9300_EEP_VER_MINOR_MASK; #endif case EEP_TX_MASK: return (p_base->txrx_mask >> 4) & 0xf; case EEP_RX_MASK: return p_base->txrx_mask & 0xf; #ifdef NOTYET case EEP_FSTCLK_5G: return p_base->fast_clk5g; case EEP_RXGAIN_TYPE: return p_base->rx_gain_type; #endif case EEP_DRIVE_STRENGTH: #define AR9300_EEP_BASE_DRIVE_STRENGTH 0x1 return p_base->misc_configuration & AR9300_EEP_BASE_DRIVE_STRENGTH; case EEP_INTERNAL_REGULATOR: /* Bit 4 is internal regulator flag */ return ((p_base->feature_enable & 0x10) >> 4); case EEP_SWREG: return (p_base->swreg); case EEP_PAPRD_ENABLED: /* Bit 5 is paprd flag */ return ((p_base->feature_enable & 0x20) >> 5); case EEP_ANTDIV_control: return (u_int32_t)(base_ext1->ant_div_control); case EEP_CHAIN_MASK_REDUCE: return ((p_base->misc_configuration >> 3) & 0x1); case EEP_OL_PWRCTRL: return 0; case EEP_DEV_TYPE: return p_base->device_type; default: HALASSERT(0); return 0; } } /******************************************************************************/ /*! ** \brief EEPROM fixup code for INI values ** ** This routine provides a place to insert "fixup" code for specific devices ** that need to modify INI values based on EEPROM values, BEFORE the INI values ** are written. ** Certain registers in the INI file can only be written once without ** undesired side effects, and this provides a place for EEPROM overrides ** in these cases. ** ** This is called at attach time once. It should not affect run time ** performance at all ** ** \param ah Pointer to HAL object (this) ** \param p_eep_data Pointer to (filled in) eeprom data structure ** \param reg register being inspected on this call ** \param value value in INI file ** ** \return Updated value for INI file. */ u_int32_t ar9300_ini_fixup(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, u_int32_t reg, u_int32_t value) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "ar9300_eeprom_def_ini_fixup: FIXME\n"); #if 0 BASE_EEPDEF_HEADER *p_base = &(p_eep_data->base_eep_header); switch (AH_PRIVATE(ah)->ah_devid) { case AR9300_DEVID_AR9300_PCI: /* ** Need to set the external/internal regulator bit to the proper value. ** Can only write this ONCE. */ if ( reg == 0x7894 ) { /* ** Check for an EEPROM data structure of "0x0b" or better */ HALDEBUG(ah, HAL_DEBUG_EEPROM, "ini VAL: %x EEPROM: %x\n", value, (p_base->version & 0xff)); if ( (p_base->version & 0xff) > 0x0a) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "PWDCLKIND: %d\n", p_base->pwdclkind); value &= ~AR_AN_TOP2_PWDCLKIND; value |= AR_AN_TOP2_PWDCLKIND & (p_base->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); } else { HALDEBUG(ah, HAL_DEBUG_EEPROM, "PWDCLKIND Earlier Rev\n"); } HALDEBUG(ah, HAL_DEBUG_EEPROM, "final ini VAL: %x\n", value); } break; } return (value); #else return 0; #endif } /* * Returns the interpolated y value corresponding to the specified x value * from the np ordered pairs of data (px,py). * The pairs do not have to be in any order. * If the specified x value is less than any of the px, * the returned y value is equal to the py for the lowest px. * If the specified x value is greater than any of the px, * the returned y value is equal to the py for the highest px. */ static int interpolate(int32_t x, int32_t *px, int32_t *py, u_int16_t np) { int ip = 0; int lx = 0, ly = 0, lhave = 0; int hx = 0, hy = 0, hhave = 0; int dx = 0; int y = 0; int bf, factor, plus; lhave = 0; hhave = 0; /* * identify best lower and higher x calibration measurement */ for (ip = 0; ip < np; ip++) { dx = x - px[ip]; /* this measurement is higher than our desired x */ if (dx <= 0) { if (!hhave || dx > (x - hx)) { /* new best higher x measurement */ hx = px[ip]; hy = py[ip]; hhave = 1; } } /* this measurement is lower than our desired x */ if (dx >= 0) { if (!lhave || dx < (x - lx)) { /* new best lower x measurement */ lx = px[ip]; ly = py[ip]; lhave = 1; } } } /* the low x is good */ if (lhave) { /* so is the high x */ if (hhave) { /* they're the same, so just pick one */ if (hx == lx) { y = ly; } else { /* interpolate with round off */ bf = (2 * (hy - ly) * (x - lx)) / (hx - lx); plus = (bf % 2); factor = bf / 2; y = ly + factor + plus; } } else { /* only low is good, use it */ y = ly; } } else if (hhave) { /* only high is good, use it */ y = hy; } else { /* nothing is good,this should never happen unless np=0, ???? */ y = -(1 << 30); } return y; } u_int8_t ar9300_eeprom_get_legacy_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, u_int16_t freq, HAL_BOOL is_2ghz) { u_int16_t num_piers, i; int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS]; int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS]; u_int8_t *p_freq_bin; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; CAL_TARGET_POWER_LEG *p_eeprom_target_pwr; if (is_2ghz) { num_piers = OSPREY_NUM_2G_20_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_2g; p_freq_bin = eep->cal_target_freqbin_2g; } else { num_piers = OSPREY_NUM_5G_20_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_5g; p_freq_bin = eep->cal_target_freqbin_5g; } /* * create array of channels and targetpower from * targetpower piers stored on eeprom */ for (i = 0; i < num_piers; i++) { freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; } /* interpolate to get target power for given frequency */ return ((u_int8_t)interpolate( (int32_t)freq, freq_array, target_power_array, num_piers)); } u_int8_t ar9300_eeprom_get_ht20_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, u_int16_t freq, HAL_BOOL is_2ghz) { u_int16_t num_piers, i; int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS]; int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS]; u_int8_t *p_freq_bin; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr; if (is_2ghz) { num_piers = OSPREY_NUM_2G_20_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_2g_ht20; p_freq_bin = eep->cal_target_freqbin_2g_ht20; } else { num_piers = OSPREY_NUM_5G_20_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_5g_ht20; p_freq_bin = eep->cal_target_freqbin_5g_ht20; } /* * create array of channels and targetpower from * targetpower piers stored on eeprom */ for (i = 0; i < num_piers; i++) { freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; } /* interpolate to get target power for given frequency */ return ((u_int8_t)interpolate( (int32_t)freq, freq_array, target_power_array, num_piers)); } u_int8_t ar9300_eeprom_get_ht40_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, u_int16_t freq, HAL_BOOL is_2ghz) { u_int16_t num_piers, i; int32_t target_power_array[OSPREY_NUM_5G_40_TARGET_POWERS]; int32_t freq_array[OSPREY_NUM_5G_40_TARGET_POWERS]; u_int8_t *p_freq_bin; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr; if (is_2ghz) { num_piers = OSPREY_NUM_2G_40_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_2g_ht40; p_freq_bin = eep->cal_target_freqbin_2g_ht40; } else { num_piers = OSPREY_NUM_5G_40_TARGET_POWERS; p_eeprom_target_pwr = eep->cal_target_power_5g_ht40; p_freq_bin = eep->cal_target_freqbin_5g_ht40; } /* * create array of channels and targetpower from * targetpower piers stored on eeprom */ for (i = 0; i < num_piers; i++) { freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; } /* interpolate to get target power for given frequency */ return ((u_int8_t)interpolate( (int32_t)freq, freq_array, target_power_array, num_piers)); } u_int8_t ar9300_eeprom_get_cck_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, u_int16_t freq) { u_int16_t num_piers = OSPREY_NUM_2G_CCK_TARGET_POWERS, i; int32_t target_power_array[OSPREY_NUM_2G_CCK_TARGET_POWERS]; int32_t freq_array[OSPREY_NUM_2G_CCK_TARGET_POWERS]; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; u_int8_t *p_freq_bin = eep->cal_target_freqbin_cck; CAL_TARGET_POWER_LEG *p_eeprom_target_pwr = eep->cal_target_power_cck; /* * create array of channels and targetpower from * targetpower piers stored on eeprom */ for (i = 0; i < num_piers; i++) { freq_array[i] = FBIN2FREQ(p_freq_bin[i], 1); target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; } /* interpolate to get target power for given frequency */ return ((u_int8_t)interpolate( (int32_t)freq, freq_array, target_power_array, num_piers)); } /* * Set tx power registers to array of values passed in */ int ar9300_transmit_power_reg_write(struct ath_hal *ah, u_int8_t *p_pwr_array) { #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) /* make sure forced gain is not set */ #if 0 field_write("force_dac_gain", 0); OS_REG_WRITE(ah, 0xa3f8, 0); field_write("force_tx_gain", 0); #endif OS_REG_WRITE(ah, 0xa458, 0); /* Write the OFDM power per rate set */ /* 6 (LSB), 9, 12, 18 (MSB) */ OS_REG_WRITE(ah, 0xa3c0, POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) ); /* 24 (LSB), 36, 48, 54 (MSB) */ OS_REG_WRITE(ah, 0xa3c4, POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) ); /* Write the CCK power per rate set */ /* 1L (LSB), reserved, 2L, 2S (MSB) */ OS_REG_WRITE(ah, 0xa3c8, POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) /* | POW_SM(tx_power_times2, 8)*/ /* this is reserved for Osprey */ | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) ); /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ OS_REG_WRITE(ah, 0xa3cc, POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) ); /* write the power for duplicated frames - HT40 */ /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ OS_REG_WRITE(ah, 0xa3e0, POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) ); /* Write the HT20 power per rate set */ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ OS_REG_WRITE(ah, 0xa3d0, POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0) ); /* 6 (LSB), 7, 12, 13 (MSB) */ OS_REG_WRITE(ah, 0xa3d4, POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0) ); /* 14 (LSB), 15, 20, 21 */ OS_REG_WRITE(ah, 0xa3e4, POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0) ); /* Mixed HT20 and HT40 rates */ /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ OS_REG_WRITE(ah, 0xa3e8, POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0) ); /* Write the HT40 power per rate set */ /* correct PAR difference between HT40 and HT20/LEGACY */ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ OS_REG_WRITE(ah, 0xa3d8, POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0) ); /* 6 (LSB), 7, 12, 13 (MSB) */ OS_REG_WRITE(ah, 0xa3dc, POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0) ); /* 14 (LSB), 15, 20, 21 */ OS_REG_WRITE(ah, 0xa3ec, POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24) | POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16) | POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8) | POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0) ); return 0; #undef POW_SM } static void ar9300_selfgen_tpc_reg_write(struct ath_hal *ah, const struct ieee80211_channel *chan, u_int8_t *p_pwr_array) { u_int32_t tpc_reg_val; /* Set the target power values for self generated frames (ACK,RTS/CTS) to * be within limits. This is just a safety measure.With per packet TPC mode * enabled the target power value used with self generated frames will be * MIN( TPC reg, BB_powertx_rate register) */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_ACK) | SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_CTS) | SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT)); } else { tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_ACK) | SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_CTS) | SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT)); } OS_REG_WRITE(ah, AR_TPC, tpc_reg_val); } void ar9300_set_target_power_from_eeprom(struct ath_hal *ah, u_int16_t freq, u_int8_t *target_power_val_t2) { /* hard code for now, need to get from eeprom struct */ u_int8_t ht40_power_inc_for_pdadc = 0; HAL_BOOL is_2ghz = 0; if (freq < 4000) { is_2ghz = 1; } target_power_val_t2[ALL_TARGET_LEGACY_6_24] = ar9300_eeprom_get_legacy_trgt_pwr( ah, LEGACY_TARGET_RATE_6_24, freq, is_2ghz); target_power_val_t2[ALL_TARGET_LEGACY_36] = ar9300_eeprom_get_legacy_trgt_pwr( ah, LEGACY_TARGET_RATE_36, freq, is_2ghz); target_power_val_t2[ALL_TARGET_LEGACY_48] = ar9300_eeprom_get_legacy_trgt_pwr( ah, LEGACY_TARGET_RATE_48, freq, is_2ghz); target_power_val_t2[ALL_TARGET_LEGACY_54] = ar9300_eeprom_get_legacy_trgt_pwr( ah, LEGACY_TARGET_RATE_54, freq, is_2ghz); target_power_val_t2[ALL_TARGET_LEGACY_1L_5L] = ar9300_eeprom_get_cck_trgt_pwr( ah, LEGACY_TARGET_RATE_1L_5L, freq); target_power_val_t2[ALL_TARGET_LEGACY_5S] = ar9300_eeprom_get_cck_trgt_pwr( ah, LEGACY_TARGET_RATE_5S, freq); target_power_val_t2[ALL_TARGET_LEGACY_11L] = ar9300_eeprom_get_cck_trgt_pwr( ah, LEGACY_TARGET_RATE_11L, freq); target_power_val_t2[ALL_TARGET_LEGACY_11S] = ar9300_eeprom_get_cck_trgt_pwr( ah, LEGACY_TARGET_RATE_11S, freq); target_power_val_t2[ALL_TARGET_HT20_0_8_16] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_1_3_9_11_17_19] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_4] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_4, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_5] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_5, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_6] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_6, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_7] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_7, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_12] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_12, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_13] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_13, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_14] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_14, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_15] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_15, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_20] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_20, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_21] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_21, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_22] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_22, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT20_23] = ar9300_eeprom_get_ht20_trgt_pwr( ah, HT_TARGET_RATE_23, freq, is_2ghz); target_power_val_t2[ALL_TARGET_HT40_0_8_16] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_1_3_9_11_17_19] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_4] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_4, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_5] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_5, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_6] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_6, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_7] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_7, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_12] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_12, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_13] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_13, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_14] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_14, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_15] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_15, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_20] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_20, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_21] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_21, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_22] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_22, freq, is_2ghz) + ht40_power_inc_for_pdadc; target_power_val_t2[ALL_TARGET_HT40_23] = ar9300_eeprom_get_ht40_trgt_pwr( ah, HT_TARGET_RATE_23, freq, is_2ghz) + ht40_power_inc_for_pdadc; #ifdef AH_DEBUG { int i = 0; HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: APPLYING TARGET POWERS\n", __func__); while (i < ar9300_rate_size) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", __func__, i, target_power_val_t2[i]); i++; if (i == ar9300_rate_size) { break; } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", __func__, i, target_power_val_t2[i]); i++; if (i == ar9300_rate_size) { break; } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", __func__, i, target_power_val_t2[i]); i++; if (i == ar9300_rate_size) { break; } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x \n", __func__, i, target_power_val_t2[i]); i++; } } #endif } u_int16_t *ar9300_regulatory_domain_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return eep->base_eep_header.reg_dmn; } int32_t ar9300_eeprom_write_enable_gpio_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return eep->base_eep_header.eeprom_write_enable_gpio; } int32_t ar9300_wlan_disable_gpio_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return eep->base_eep_header.wlan_disable_gpio; } int32_t ar9300_wlan_led_gpio_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return eep->base_eep_header.wlan_led_gpio; } int32_t ar9300_rx_band_select_gpio_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return eep->base_eep_header.rx_band_select_gpio; } /* * since valid noise floor values are negative, returns 1 on error */ int32_t ar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency, int32_t ichain, HAL_BOOL use_cal) { int nf_use = 1; /* start with an error return value */ int32_t fx[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS]; int32_t nf[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS]; int nnf; int is_2ghz; int ipier, npier; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; u_int8_t *p_cal_pier; OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct; /* * check chain value */ if (ichain < 0 || ichain >= OSPREY_MAX_CHAINS) { return 1; } /* figure out which band we're using */ is_2ghz = (frequency < 4000); if (is_2ghz) { npier = OSPREY_NUM_2G_CAL_PIERS; p_cal_pier = eep->cal_freq_pier_2g; p_cal_pier_struct = eep->cal_pier_data_2g[ichain]; } else { npier = OSPREY_NUM_5G_CAL_PIERS; p_cal_pier = eep->cal_freq_pier_5g; p_cal_pier_struct = eep->cal_pier_data_5g[ichain]; } /* look for valid noise floor values */ nnf = 0; for (ipier = 0; ipier < npier; ipier++) { fx[nnf] = FBIN2FREQ(p_cal_pier[ipier], is_2ghz); nf[nnf] = use_cal ? p_cal_pier_struct[ipier].rx_noisefloor_cal : p_cal_pier_struct[ipier].rx_noisefloor_power; if (nf[nnf] < 0) { nnf++; } } /* * If we have some valid values, interpolate to find the value * at the desired frequency. */ if (nnf > 0) { nf_use = interpolate(frequency, fx, nf, nnf); } return nf_use; } +/* + * Return the Rx NF offset for specific channel. + * The values saved in EEPROM/OTP/Flash is converted through the following way: + * ((_p) - NOISE_PWR_DATA_OFFSET) << 2 + * So we need to convert back to the original values. + */ +int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) { + HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); + int8_t rx_nf_pwr, rx_nf_cal; + int i; + //HALASSERT(ichan); + + /* Fill 0 if valid internal channel is not found */ + if (ichan == AH_NULL) { + OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS); + OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS); + return -1; + } + + for (i = 0; i < OSPREY_MAX_CHAINS; i++) { + if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) { + nf_pwr[i] = 0; + } else { + //printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr); + nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr); + } + + if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) { + nf_cal[i] = 0; + } else { + //printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal); + nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal); + } + } + + return 0; +} + int32_t ar9300_rx_gain_index_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return (eep->base_eep_header.txrxgain) & 0xf; /* bits 3:0 */ } int32_t ar9300_tx_gain_index_get(struct ath_hal *ah) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; return (eep->base_eep_header.txrxgain >> 4) & 0xf; /* bits 7:4 */ } HAL_BOOL ar9300_internal_regulator_apply(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); int internal_regulator = ar9300_eeprom_get(ahp, EEP_INTERNAL_REGULATOR); int reg_pmu1, reg_pmu2, reg_pmu1_set, reg_pmu2_set; u_int32_t reg_PMU1, reg_PMU2; unsigned long eep_addr; u_int32_t reg_val, reg_usb = 0, reg_pmu = 0; int usb_valid = 0, pmu_valid = 0; unsigned char pmu_refv; if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { reg_PMU1 = AR_PHY_PMU1_JUPITER; reg_PMU2 = AR_PHY_PMU2_JUPITER; } else { reg_PMU1 = AR_PHY_PMU1; reg_PMU2 = AR_PHY_PMU2; } if (internal_regulator) { if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { if (AR_SREV_HORNET(ah)) { /* Read OTP first */ for (eep_addr = 0x14; ; eep_addr -= 0x10) { ar9300_otp_read(ah, eep_addr / 4, ®_val, 1); if ((reg_val & 0x80) == 0x80){ usb_valid = 1; reg_usb = reg_val & 0x000000ff; } if ((reg_val & 0x80000000) == 0x80000000){ pmu_valid = 1; reg_pmu = (reg_val & 0xff000000) >> 24; } if (eep_addr == 0x4) { break; } } if (pmu_valid) { pmu_refv = reg_pmu & 0xf; } else { pmu_refv = 0x8; } /* * If (valid) { * Usb_phy_ctrl2_tx_cal_en -> 0 * Usb_phy_ctrl2_tx_cal_sel -> 0 * Usb_phy_ctrl2_tx_man_cal -> 0, 1, 3, 7 or 15 from OTP * } */ if (usb_valid) { OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_EN, 0x0); OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_SEL, 0x0); OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_MAN_CAL, (reg_usb & 0xf)); } } else { pmu_refv = 0x8; } /*#ifndef USE_HIF*/ /* Follow the MDK settings for Hornet PMU. * my $pwd = 0x0; * my $Nfdiv = 0x3; # xtal_freq = 25MHz * my $Nfdiv = 0x4; # xtal_freq = 40MHz * my $Refv = 0x7; # 0x5:1.22V; 0x8:1.29V * my $Gm1 = 0x3; #Poseidon $Gm1=1 * my $classb = 0x0; * my $Cc = 0x1; #Poseidon $Cc=7 * my $Rc = 0x6; * my $ramp_slope = 0x1; * my $Segm = 0x3; * my $use_local_osc = 0x0; * my $force_xosc_stable = 0x0; * my $Selfb = 0x0; #Poseidon $Selfb=1 * my $Filterfb = 0x3; #Poseidon $Filterfb=0 * my $Filtervc = 0x0; * my $disc = 0x0; * my $discdel = 0x4; * my $spare = 0x0; * $reg_PMU1 = * $pwd | ($Nfdiv<<1) | ($Refv<<4) | ($Gm1<<8) | * ($classb<<11) | ($Cc<<14) | ($Rc<<17) | ($ramp_slope<<20) | * ($Segm<<24) | ($use_local_osc<<26) | * ($force_xosc_stable<<27) | ($Selfb<<28) | ($Filterfb<<29); * $reg_PMU2 = $handle->reg_rd("ch0_PMU2"); * $reg_PMU2 = ($reg_PMU2 & 0xfe3fffff) | ($Filtervc<<22); * $reg_PMU2 = ($reg_PMU2 & 0xe3ffffff) | ($discdel<<26); * $reg_PMU2 = ($reg_PMU2 & 0x1fffffff) | ($spare<<29); */ if (ahp->clk_25mhz) { reg_pmu1_set = 0 | (3 << 1) | (pmu_refv << 4) | (3 << 8) | (0 << 11) | (1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | (0 << 26) | (0 << 27) | (0 << 28) | (0 << 29); } else { if (AR_SREV_POSEIDON(ah)) { reg_pmu1_set = 0 | (5 << 1) | (7 << 4) | (2 << 8) | (0 << 11) | (2 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | (0 << 26) | (0 << 27) | (1 << 28) | (0 << 29) ; } else { reg_pmu1_set = 0 | (4 << 1) | (7 << 4) | (3 << 8) | (0 << 11) | (1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | (0 << 26) | (0 << 27) | (0 << 28) | (0 << 29) ; } } OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0); OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */ reg_pmu1 = OS_REG_READ(ah, reg_PMU1); while (reg_pmu1 != reg_pmu1_set) { OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */ OS_DELAY(10); reg_pmu1 = OS_REG_READ(ah, reg_PMU1); } reg_pmu2_set = (OS_REG_READ(ah, reg_PMU2) & (~0xFFC00000)) | (4 << 26); OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); reg_pmu2 = OS_REG_READ(ah, reg_PMU2); while (reg_pmu2 != reg_pmu2_set) { OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); OS_DELAY(10); reg_pmu2 = OS_REG_READ(ah, reg_PMU2); } reg_pmu2_set = (OS_REG_READ(ah, reg_PMU2) & (~0x00200000)) | (1 << 21); OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); reg_pmu2 = OS_REG_READ(ah, reg_PMU2); while (reg_pmu2 != reg_pmu2_set) { OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); OS_DELAY(10); reg_pmu2 = OS_REG_READ(ah, reg_PMU2); } /*#endif*/ } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* Internal regulator is ON. Write swreg register. */ int swreg = ar9300_eeprom_get(ahp, EEP_SWREG); OS_REG_WRITE(ah, reg_PMU1, swreg); } else { /* Internal regulator is ON. Write swreg register. */ int swreg = ar9300_eeprom_get(ahp, EEP_SWREG); OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1, OS_REG_READ(ah, AR_RTC_REG_CONTROL1) & (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); OS_REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); /* Set REG_CONTROL1.SWREG_PROGRAM */ OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1, OS_REG_READ(ah, AR_RTC_REG_CONTROL1) | AR_RTC_REG_CONTROL1_SWREG_PROGRAM); } } else { if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0); reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); while (reg_pmu2) { OS_DELAY(10); reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); } OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1); reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD); while (!reg_pmu1) { OS_DELAY(10); reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD); } OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x1); reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); while (!reg_pmu2) { OS_DELAY(10); reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); } } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1); } else { OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, (OS_REG_READ(ah, AR_RTC_SLEEP_CLK) | AR_RTC_FORCE_SWREG_PRD | AR_RTC_PCIE_RST_PWDN_EN)); } } return 0; } HAL_BOOL ar9300_drive_strength_apply(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); int drive_strength; unsigned long reg; drive_strength = ar9300_eeprom_get(ahp, EEP_DRIVE_STRENGTH); if (drive_strength) { reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS1); reg &= ~0x00ffffc0; reg |= 0x5 << 21; reg |= 0x5 << 18; reg |= 0x5 << 15; reg |= 0x5 << 12; reg |= 0x5 << 9; reg |= 0x5 << 6; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg); reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS2); reg &= ~0xffffffe0; reg |= 0x5 << 29; reg |= 0x5 << 26; reg |= 0x5 << 23; reg |= 0x5 << 20; reg |= 0x5 << 17; reg |= 0x5 << 14; reg |= 0x5 << 11; reg |= 0x5 << 8; reg |= 0x5 << 5; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg); reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS4); reg &= ~0xff800000; reg |= 0x5 << 29; reg |= 0x5 << 26; reg |= 0x5 << 23; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); } return 0; } int32_t ar9300_xpa_bias_level_get(struct ath_hal *ah, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (is_2ghz) { return eep->modal_header_2g.xpa_bias_lvl; } else { return eep->modal_header_5g.xpa_bias_lvl; } } HAL_BOOL ar9300_xpa_bias_level_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) { /* * In ar9330 emu, we can't access radio registers, * merlin is used for radio part. */ int bias; bias = ar9300_xpa_bias_level_get(ah, is_2ghz); if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) { OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_TOP2, AR_HORNET_CH0_TOP2_XPABIASLVL, bias); } else if (AR_SREV_SCORPION(ah)) { OS_REG_RMW_FIELD(ah, AR_SCORPION_CH0_TOP, AR_SCORPION_CH0_TOP_XPABIASLVL, bias); } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TOP_JUPITER, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias); } else { OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TOP, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB, bias >> 2); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPASHORT2GND, 1); } return 0; } u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (is_2ghz) { return eep->modal_header_2g.ant_ctrl_common; } else { return eep->modal_header_5g.ant_ctrl_common; } } static u_int16_t ar9300_switch_com_spdt_get(struct ath_hal *ah, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (is_2ghz) { return eep->modal_header_2g.switchcomspdt; } else { return eep->modal_header_5g.switchcomspdt; } } u_int32_t ar9300_ant_ctrl_common2_get(struct ath_hal *ah, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (is_2ghz) { return eep->modal_header_2g.ant_ctrl_common2; } else { return eep->modal_header_5g.ant_ctrl_common2; } } u_int16_t ar9300_ant_ctrl_chain_get(struct ath_hal *ah, int chain, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { if (is_2ghz) { return eep->modal_header_2g.ant_ctrl_chain[chain]; } else { return eep->modal_header_5g.ant_ctrl_chain[chain]; } } return 0; } +/* + * Select the usage of antenna via the RF switch. + * Default values are loaded from eeprom. + */ +HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops, + u_int32_t *common_tbl1, u_int32_t *common_tbl2) +{ + ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; + struct ath_hal_private *ap = AH_PRIVATE(ah); + const struct ieee80211_channel *curchan = ap->ah_curchan; + enum { + ANT_SELECT_OPS_GET, + ANT_SELECT_OPS_SET, + }; + + if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah)) + return AH_FALSE; + + if (!curchan) + return AH_FALSE; + +#define AR_SWITCH_TABLE_COM_ALL (0xffff) +#define AR_SWITCH_TABLE_COM_ALL_S (0) +#define AR_SWITCH_TABLE_COM2_ALL (0xffffff) +#define AR_SWITCH_TABLE_COM2_ALL_S (0) + switch (ops) { + case ANT_SELECT_OPS_GET: + *common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM, + AR_SWITCH_TABLE_COM_ALL); + *common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2, + AR_SWITCH_TABLE_COM2_ALL); + break; + case ANT_SELECT_OPS_SET: + OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, + AR_SWITCH_TABLE_COM_ALL, *common_tbl1); + OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, + AR_SWITCH_TABLE_COM2_ALL, *common_tbl2); + + /* write back to eeprom */ + if (IEEE80211_IS_CHAN_2GHZ(curchan)) { + eep->modal_header_2g.ant_ctrl_common = *common_tbl1; + eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2; + } else { + eep->modal_header_5g.ant_ctrl_common = *common_tbl1; + eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2; + } + + break; + default: + break; + } + + return AH_TRUE; +} + HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) { u_int32_t value; struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t regval; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); #if ATH_ANT_DIV_COMB HAL_CAPABILITIES *pcap = &ahpriv->ah_caps; #endif /* ATH_ANT_DIV_COMB */ u_int32_t xlan_gpio_cfg; u_int8_t i; if (AR_SREV_POSEIDON(ah)) { xlan_gpio_cfg = ah->ah_config.ath_hal_ext_lna_ctl_gpio; if (xlan_gpio_cfg) { for (i = 0; i < 32; i++) { if (xlan_gpio_cfg & (1 << i)) { ath_hal_gpioCfgOutput(ah, i, HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED); } } } } #define AR_SWITCH_TABLE_COM_ALL (0xffff) #define AR_SWITCH_TABLE_COM_ALL_S (0) #define AR_SWITCH_TABLE_COM_JUPITER_ALL (0xffffff) #define AR_SWITCH_TABLE_COM_JUPITER_ALL_S (0) #define AR_SWITCH_TABLE_COM_SCORPION_ALL (0xffffff) #define AR_SWITCH_TABLE_COM_SCORPION_ALL_S (0) #define AR_SWITCH_TABLE_COM_SPDT (0x00f00000) value = ar9300_ant_ctrl_common_get(ah, is_2ghz); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { if (AR_SREV_JUPITER_10(ah)) { /* Force SPDT setting for Jupiter 1.0 chips. */ value &= ~AR_SWITCH_TABLE_COM_SPDT; value |= 0x00100000; } OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_JUPITER_ALL, value); } else if (AR_SREV_SCORPION(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_SCORPION_ALL, value); } else { OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); } /* * Jupiter2.0 defines new switch table for BT/WLAN, * here's new field name in WB222.ref for both 2G and 5G. * Register: [GLB_CONTROL] GLB_CONTROL (@0x20044) * 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX SWITCH_TABLE_COM_SPDT_WLAN_RX * 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX SWITCH_TABLE_COM_SPDT_WLAN_TX * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE SWITCH_TABLE_COM_SPDT_WLAN_IDLE */ #define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0) #define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4) if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { value = ar9300_switch_com_spdt_get(ah, is_2ghz); OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_SWITCH_TABLE_COM_SPDT_ALL, value); OS_REG_SET_BIT(ah, AR_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE); //OS_REG_SET_BIT(ah, AR_GLB_CONTROL, // AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); } #define AR_SWITCH_TABLE_COM2_ALL (0xffffff) #define AR_SWITCH_TABLE_COM2_ALL_S (0) value = ar9300_ant_ctrl_common2_get(ah, is_2ghz); #if ATH_ANT_DIV_COMB if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { value &= ~AR_SWITCH_TABLE_COM2_ALL; value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable; HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value) } #endif /* ATH_ANT_DIV_COMB */ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); #define AR_SWITCH_TABLE_ALL (0xfff) #define AR_SWITCH_TABLE_ALL_S (0) value = ar9300_ant_ctrl_chain_get(ah, 0, is_2ghz); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) { value = ar9300_ant_ctrl_chain_get(ah, 1, is_2ghz); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) { value = ar9300_ant_ctrl_chain_get(ah, 2, is_2ghz); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); } } if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control); /* main_lnaconf, alt_lnaconf, main_tb, alt_tb */ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */ regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S; /* enable_lnadiv */ regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK); regval |= ((value >> 6) & 0x1) << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT; #if ATH_ANT_DIV_COMB if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { regval |= ANT_DIV_ENABLE; } #endif /* ATH_ANT_DIV_COMB */ OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); /* enable fast_div */ regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); regval |= ((value >> 7) & 0x1) << BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT; #if ATH_ANT_DIV_COMB if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { regval |= FAST_DIV_ENABLE; } #endif /* ATH_ANT_DIV_COMB */ OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); } #if ATH_ANT_DIV_COMB if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) { if (pcap->halAntDivCombSupport) { /* If support DivComb, set MAIN to LNA1, ALT to LNA2 at beginning */ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); /* clear bit 25~30 main_lnaconf, alt_lnaconf, main_tb, alt_tb */ regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK)); regval |= (HAL_ANT_DIV_COMB_LNA1 << MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); regval |= (HAL_ANT_DIV_COMB_LNA2 << MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); } } #endif /* ATH_ANT_DIV_COMB */ if (AR_SREV_POSEIDON(ah) && ( ahp->ah_diversity_control == HAL_ANT_FIXED_A || ahp->ah_diversity_control == HAL_ANT_FIXED_B)) { u_int32_t reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); reg_val &= ~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK ); switch (ahp->ah_diversity_control) { case HAL_ANT_FIXED_A: /* Enable first antenna only */ reg_val |= (HAL_ANT_DIV_COMB_LNA1 << MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); reg_val |= (HAL_ANT_DIV_COMB_LNA2 << MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); /* main/alt gain table and Fast Div Bias all set to 0 */ OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val); regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); break; case HAL_ANT_FIXED_B: /* Enable second antenna only, after checking capability */ reg_val |= (HAL_ANT_DIV_COMB_LNA2 << MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); reg_val |= (HAL_ANT_DIV_COMB_LNA1 << MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); /* main/alt gain table and Fast Div all set to 0 */ OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val); regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); /* For WB225, need to swith ANT2 from BT to Wifi * This will not affect HB125 LNA diversity feature. */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable) OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable); break; default: break; } } return 0; } static u_int16_t ar9300_attenuation_chain_get(struct ath_hal *ah, int chain, u_int16_t channel) { int32_t f[3], t[3]; u_int16_t value; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { if (channel < 4000) { return eep->modal_header_2g.xatten1_db[chain]; } else { if (eep->base_ext2.xatten1_db_low[chain] != 0) { t[0] = eep->base_ext2.xatten1_db_low[chain]; f[0] = 5180; t[1] = eep->modal_header_5g.xatten1_db[chain]; f[1] = 5500; t[2] = eep->base_ext2.xatten1_db_high[chain]; f[2] = 5785; value = interpolate(channel, f, t, 3); return value; } else { return eep->modal_header_5g.xatten1_db[chain]; } } } return 0; } static u_int16_t ar9300_attenuation_margin_chain_get(struct ath_hal *ah, int chain, u_int16_t channel) { int32_t f[3], t[3]; u_int16_t value; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { if (channel < 4000) { return eep->modal_header_2g.xatten1_margin[chain]; } else { if (eep->base_ext2.xatten1_margin_low[chain] != 0) { t[0] = eep->base_ext2.xatten1_margin_low[chain]; f[0] = 5180; t[1] = eep->modal_header_5g.xatten1_margin[chain]; f[1] = 5500; t[2] = eep->base_ext2.xatten1_margin_high[chain]; f[2] = 5785; value = interpolate(channel, f, t, 3); return value; } else { return eep->modal_header_5g.xatten1_margin[chain]; } } } return 0; } #if 0 HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel) { u_int32_t value; // struct ath_hal_private *ahpriv = AH_PRIVATE(ah); /* Test value. if 0 then attenuation is unused. Don't load anything. */ value = ar9300_attenuation_chain_get(ah, 0, channel); OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9300_attenuation_margin_chain_get(ah, 0, channel); if (ar9300_rx_gain_index_get(ah) == 0 && ah->ah_config.ath_hal_ext_atten_margin_cfg) { value = 5; } OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { value = ar9300_attenuation_chain_get(ah, 1, channel); OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9300_attenuation_margin_chain_get(ah, 1, channel); OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) { value = ar9300_attenuation_chain_get(ah, 2, channel); OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9300_attenuation_margin_chain_get(ah, 2, channel); OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } } return 0; } #endif HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel) { int i; uint32_t value; uint32_t ext_atten_reg[3] = { AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_2 }; /* * If it's an AR9462 and we're receiving on the second * chain only, set the chain 0 details from chain 1 * calibration. * * This is from ath9k. */ if (AR_SREV_JUPITER(ah) && (AH9300(ah)->ah_rx_chainmask == 0x2)) { value = ar9300_attenuation_chain_get(ah, 1, channel); OS_REG_RMW_FIELD(ah, ext_atten_reg[0], AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9300_attenuation_margin_chain_get(ah, 1, channel); OS_REG_RMW_FIELD(ah, ext_atten_reg[0], AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } /* * Now, loop over the configured transmit chains and * load in the attenuation/margin settings as appropriate. */ for (i = 0; i < 3; i++) { if ((AH9300(ah)->ah_tx_chainmask & (1 << i)) == 0) continue; value = ar9300_attenuation_chain_get(ah, i, channel); OS_REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); if (AR_SREV_POSEIDON(ah) && (ar9300_rx_gain_index_get(ah) == 0) && ah->ah_config.ath_hal_ext_atten_margin_cfg) { value = 5; } else { value = ar9300_attenuation_margin_chain_get(ah, 0, channel); } /* * I'm not sure why it's loading in this setting into * the chain 0 margin regardless of the current chain. */ if (ah->ah_config.ath_hal_min_gainidx) OS_REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); OS_REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } return (0); } static u_int16_t ar9300_quick_drop_get(struct ath_hal *ah, int chain, u_int16_t channel) { int32_t f[3], t[3]; u_int16_t value; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (channel < 4000) { return eep->modal_header_2g.quick_drop; } else { t[0] = eep->base_ext1.quick_drop_low; f[0] = 5180; t[1] = eep->modal_header_5g.quick_drop; f[1] = 5500; t[2] = eep->base_ext1.quick_drop_high; f[2] = 5785; value = interpolate(channel, f, t, 3); return value; } } static HAL_BOOL ar9300_quick_drop_apply(struct ath_hal *ah, u_int16_t channel) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; u_int32_t value; // // Test value. if 0 then quickDrop is unused. Don't load anything. // if (eep->base_eep_header.misc_configuration & 0x10) { if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) { value = ar9300_quick_drop_get(ah, 0, channel); OS_REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, value); } } return 0; } static u_int16_t ar9300_tx_end_to_xpa_off_get(struct ath_hal *ah, u_int16_t channel) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (channel < 4000) { return eep->modal_header_2g.tx_end_to_xpa_off; } else { return eep->modal_header_5g.tx_end_to_xpa_off; } } static HAL_BOOL ar9300_tx_end_to_xpab_off_apply(struct ath_hal *ah, u_int16_t channel) { u_int32_t value; value = ar9300_tx_end_to_xpa_off_get(ah, channel); /* Apply to both xpaa and xpab */ if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value); OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value); } return 0; } static int ar9300_eeprom_cal_pier_get(struct ath_hal *ah, int mode, int ipier, int ichain, int *pfrequency, int *pcorrection, int *ptemperature, int *pvoltage) { u_int8_t *p_cal_pier; OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct; int is_2ghz; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (ichain >= OSPREY_MAX_CHAINS) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Invalid chain index, must be less than %d\n", __func__, OSPREY_MAX_CHAINS); return -1; } if (mode) {/* 5GHz */ if (ipier >= OSPREY_NUM_5G_CAL_PIERS){ HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Invalid 5GHz cal pier index, must be less than %d\n", __func__, OSPREY_NUM_5G_CAL_PIERS); return -1; } p_cal_pier = &(eep->cal_freq_pier_5g[ipier]); p_cal_pier_struct = &(eep->cal_pier_data_5g[ichain][ipier]); is_2ghz = 0; } else { if (ipier >= OSPREY_NUM_2G_CAL_PIERS){ HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Invalid 2GHz cal pier index, must be less than %d\n", __func__, OSPREY_NUM_2G_CAL_PIERS); return -1; } p_cal_pier = &(eep->cal_freq_pier_2g[ipier]); p_cal_pier_struct = &(eep->cal_pier_data_2g[ichain][ipier]); is_2ghz = 1; } *pfrequency = FBIN2FREQ(*p_cal_pier, is_2ghz); *pcorrection = p_cal_pier_struct->ref_power; *ptemperature = p_cal_pier_struct->temp_meas; *pvoltage = p_cal_pier_struct->volt_meas; return 0; } /* * Apply the recorded correction values. */ static int ar9300_calibration_apply(struct ath_hal *ah, int frequency) { struct ath_hal_9300 *ahp = AH9300(ah); int ichain, ipier, npier; int mode; int fdiff; int pfrequency, pcorrection, ptemperature, pvoltage; int bf, factor, plus; int lfrequency[AR9300_MAX_CHAINS]; int hfrequency[AR9300_MAX_CHAINS]; int lcorrection[AR9300_MAX_CHAINS]; int hcorrection[AR9300_MAX_CHAINS]; int correction[AR9300_MAX_CHAINS]; int ltemperature[AR9300_MAX_CHAINS]; int htemperature[AR9300_MAX_CHAINS]; int temperature[AR9300_MAX_CHAINS]; int lvoltage[AR9300_MAX_CHAINS]; int hvoltage[AR9300_MAX_CHAINS]; int voltage[AR9300_MAX_CHAINS]; mode = (frequency >= 4000); npier = (mode) ? OSPREY_NUM_5G_CAL_PIERS : OSPREY_NUM_2G_CAL_PIERS; for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { lfrequency[ichain] = 0; hfrequency[ichain] = 100000; } /* * identify best lower and higher frequency calibration measurement */ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { for (ipier = 0; ipier < npier; ipier++) { if (ar9300_eeprom_cal_pier_get( ah, mode, ipier, ichain, &pfrequency, &pcorrection, &ptemperature, &pvoltage) == 0) { fdiff = frequency - pfrequency; /* * this measurement is higher than our desired frequency */ if (fdiff <= 0) { if (hfrequency[ichain] <= 0 || hfrequency[ichain] >= 100000 || fdiff > (frequency - hfrequency[ichain])) { /* * new best higher frequency measurement */ hfrequency[ichain] = pfrequency; hcorrection[ichain] = pcorrection; htemperature[ichain] = ptemperature; hvoltage[ichain] = pvoltage; } } if (fdiff >= 0) { if (lfrequency[ichain] <= 0 || fdiff < (frequency - lfrequency[ichain])) { /* * new best lower frequency measurement */ lfrequency[ichain] = pfrequency; lcorrection[ichain] = pcorrection; ltemperature[ichain] = ptemperature; lvoltage[ichain] = pvoltage; } } } } } /* interpolate */ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: ch=%d f=%d low=%d %d h=%d %d\n", __func__, ichain, frequency, lfrequency[ichain], lcorrection[ichain], hfrequency[ichain], hcorrection[ichain]); /* * they're the same, so just pick one */ if (hfrequency[ichain] == lfrequency[ichain]) { correction[ichain] = lcorrection[ichain]; voltage[ichain] = lvoltage[ichain]; temperature[ichain] = ltemperature[ichain]; } else if (frequency - lfrequency[ichain] < 1000) { /* the low frequency is good */ if (hfrequency[ichain] - frequency < 1000) { /* * The high frequency is good too - * interpolate with round off. */ int mult, div, diff; mult = frequency - lfrequency[ichain]; div = hfrequency[ichain] - lfrequency[ichain]; diff = hcorrection[ichain] - lcorrection[ichain]; bf = 2 * diff * mult / div; plus = (bf % 2); factor = bf / 2; correction[ichain] = lcorrection[ichain] + factor + plus; diff = htemperature[ichain] - ltemperature[ichain]; bf = 2 * diff * mult / div; plus = (bf % 2); factor = bf / 2; temperature[ichain] = ltemperature[ichain] + factor + plus; diff = hvoltage[ichain] - lvoltage[ichain]; bf = 2 * diff * mult / div; plus = (bf % 2); factor = bf / 2; voltage[ichain] = lvoltage[ichain] + factor + plus; } else { /* only low is good, use it */ correction[ichain] = lcorrection[ichain]; temperature[ichain] = ltemperature[ichain]; voltage[ichain] = lvoltage[ichain]; } } else if (hfrequency[ichain] - frequency < 1000) { /* only high is good, use it */ correction[ichain] = hcorrection[ichain]; temperature[ichain] = htemperature[ichain]; voltage[ichain] = hvoltage[ichain]; } else { /* nothing is good, presume 0???? */ correction[ichain] = 0; temperature[ichain] = 0; voltage[ichain] = 0; } } /* GreenTx isn't currently supported */ /* GreenTx */ if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable) { if (AR_SREV_POSEIDON(ah)) { /* Get calibrated OLPC gain delta value for GreenTx */ ahp->ah_db2[POSEIDON_STORED_REG_G2_OLPC_OFFSET] = (u_int32_t) correction[0]; } } ar9300_power_control_override( ah, frequency, correction, voltage, temperature); HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: for frequency=%d, calibration correction = %d %d %d\n", __func__, frequency, correction[0], correction[1], correction[2]); return 0; } int ar9300_power_control_override(struct ath_hal *ah, int frequency, int *correction, int *voltage, int *temperature) { int temp_slope = 0; int temp_slope_1 = 0; int temp_slope_2 = 0; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; int32_t f[8], t[8],t1[3], t2[3]; int i; OS_REG_RMW(ah, AR_PHY_TPC_11_B0, (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), AR_PHY_TPC_OLPC_GAIN_DELTA); if (!AR_SREV_POSEIDON(ah)) { OS_REG_RMW(ah, AR_PHY_TPC_11_B1, (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), AR_PHY_TPC_OLPC_GAIN_DELTA); if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) { OS_REG_RMW(ah, AR_PHY_TPC_11_B2, (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), AR_PHY_TPC_OLPC_GAIN_DELTA); } } /* * enable open loop power control on chip */ OS_REG_RMW(ah, AR_PHY_TPC_6_B0, (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); if (!AR_SREV_POSEIDON(ah)) { OS_REG_RMW(ah, AR_PHY_TPC_6_B1, (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) { OS_REG_RMW(ah, AR_PHY_TPC_6_B2, (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); } } /* * Enable temperature compensation * Need to use register names */ if (frequency < 4000) { temp_slope = eep->modal_header_2g.temp_slope; } else { if ((eep->base_eep_header.misc_configuration & 0x20) != 0) { for(i=0;i<8;i++) { t[i]=eep->base_ext1.tempslopextension[i]; f[i]=FBIN2FREQ(eep->cal_freq_pier_5g[i], 0); } temp_slope=interpolate(frequency,f,t,8); } else { if(!AR_SREV_SCORPION(ah)) { if (eep->base_ext2.temp_slope_low != 0) { t[0] = eep->base_ext2.temp_slope_low; f[0] = 5180; t[1] = eep->modal_header_5g.temp_slope; f[1] = 5500; t[2] = eep->base_ext2.temp_slope_high; f[2] = 5785; temp_slope = interpolate(frequency, f, t, 3); } else { temp_slope = eep->modal_header_5g.temp_slope; } } else { /* * Scorpion has individual chain tempslope values */ t[0] = eep->base_ext1.tempslopextension[2]; t1[0]= eep->base_ext1.tempslopextension[3]; t2[0]= eep->base_ext1.tempslopextension[4]; f[0] = 5180; t[1] = eep->modal_header_5g.temp_slope; t1[1]= eep->base_ext1.tempslopextension[0]; t2[1]= eep->base_ext1.tempslopextension[1]; f[1] = 5500; t[2] = eep->base_ext1.tempslopextension[5]; t1[2]= eep->base_ext1.tempslopextension[6]; t2[2]= eep->base_ext1.tempslopextension[7]; f[2] = 5785; temp_slope = interpolate(frequency, f, t, 3); temp_slope_1=interpolate(frequency, f, t1,3); temp_slope_2=interpolate(frequency, f, t2,3); } } } if (!AR_SREV_SCORPION(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); } else { /*Scorpion has tempSlope register for each chain*/ /*Check whether temp_compensation feature is enabled or not*/ if (eep->base_eep_header.feature_enable & 0x1){ if(frequency < 4000) { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, eep->base_ext2.temp_slope_low); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, eep->base_ext2.temp_slope_high); } else { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, temp_slope_1); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, temp_slope_2); } }else { /* If temp compensation is not enabled, set all registers to 0*/ OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 0); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 0); OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 0); } } OS_REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, temperature[0]); return 0; } /************************************************************** * ar9300_eep_def_get_max_edge_power * * Find the maximum conformance test limit for the given channel and CTL info */ static inline u_int16_t ar9300_eep_def_get_max_edge_power(ar9300_eeprom_t *p_eep_data, u_int16_t freq, int idx, HAL_BOOL is_2ghz) { u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER; u_int8_t *ctl_freqbin = is_2ghz ? &p_eep_data->ctl_freqbin_2G[idx][0] : &p_eep_data->ctl_freqbin_5G[idx][0]; u_int16_t num_edges = is_2ghz ? OSPREY_NUM_BAND_EDGES_2G : OSPREY_NUM_BAND_EDGES_5G; int i; /* Get the edge power */ for (i = 0; (i < num_edges) && (ctl_freqbin[i] != AR9300_BCHAN_UNUSED); i++) { /* * If there's an exact channel match or an inband flag set * on the lower channel use the given rd_edge_power */ if (freq == fbin2freq(ctl_freqbin[i], is_2ghz)) { if (is_2ghz) { twice_max_edge_power = p_eep_data->ctl_power_data_2g[idx].ctl_edges[i].t_power; } else { twice_max_edge_power = p_eep_data->ctl_power_data_5g[idx].ctl_edges[i].t_power; } break; } else if ((i > 0) && (freq < fbin2freq(ctl_freqbin[i], is_2ghz))) { if (is_2ghz) { if (fbin2freq(ctl_freqbin[i - 1], 1) < freq && p_eep_data->ctl_power_data_2g[idx].ctl_edges[i - 1].flag) { twice_max_edge_power = p_eep_data->ctl_power_data_2g[idx]. ctl_edges[i - 1].t_power; } } else { if (fbin2freq(ctl_freqbin[i - 1], 0) < freq && p_eep_data->ctl_power_data_5g[idx].ctl_edges[i - 1].flag) { twice_max_edge_power = p_eep_data->ctl_power_data_5g[idx]. ctl_edges[i - 1].t_power; } } /* * Leave loop - no more affecting edges possible * in this monotonic increasing list */ break; } } /* * EV89475: EEPROM might contain 0 txpower in CTL table for certain * 2.4GHz channels. We workaround it by overwriting 60 (30 dBm) here. */ if (is_2ghz && (twice_max_edge_power == 0)) { twice_max_edge_power = 60; } HALASSERT(twice_max_edge_power > 0); return twice_max_edge_power; } HAL_BOOL ar9300_eeprom_set_power_per_rate_table( struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, const struct ieee80211_channel *chan, u_int8_t *p_pwr_array, u_int16_t cfg_ctl, u_int16_t antenna_reduction, u_int16_t twice_max_regulatory_power, u_int16_t power_limit, u_int8_t chainmask) { /* Local defines to distinguish between extension and control CTL's */ #define EXT_ADDITIVE (0x8000) #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */ #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */ #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */ static const u_int16_t tp_scale_reduction_table[5] = { 0, 3, 6, 9, AR9300_MAX_RATE_POWER }; int i; int16_t twice_largest_antenna; u_int16_t twice_antenna_reduction = 2*antenna_reduction ; int16_t scaled_power = 0, min_ctl_power, max_reg_allowed_power; #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ u_int16_t ctl_modes_for11a[] = {CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40}; u_int16_t ctl_modes_for11g[] = {CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; u_int16_t num_ctl_modes, *p_ctl_mode, ctl_mode, freq; CHAN_CENTERS centers; int tx_chainmask; struct ath_hal_9300 *ahp = AH9300(ah); u_int8_t *ctl_index; u_int8_t ctl_num; u_int16_t twice_min_edge_power; u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER; #ifdef AH_DEBUG HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); #endif - tx_chainmask = chainmask ? chainmask : ahp->ah_tx_chainmask; + if (chainmask) + tx_chainmask = chainmask; + else + tx_chainmask = ahp->ah_tx_chainmaskopt ? + ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask; ar9300_get_channel_centers(ah, chan, ¢ers); +#if 1 if (IEEE80211_IS_CHAN_2GHZ(chan)) { ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain; } else { ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain; } +#else + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain, + AH_PRIVATE(ah)->ah_antenna_gain_2g); + } else { + ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain, + AH_PRIVATE(ah)->ah_antenna_gain_5g); + } +#endif + /* Save max allowed antenna gain to ease future lookups */ ahp->twice_antenna_reduction = twice_antenna_reduction; /* Deduct antenna gain from EIRP to get the upper limit */ twice_largest_antenna = (int16_t)AH_MIN((twice_antenna_reduction - ahp->twice_antenna_gain), 0); max_reg_allowed_power = twice_max_regulatory_power + twice_largest_antenna; /* Use ah_tp_scale - see bug 30070. */ if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { max_reg_allowed_power -= (tp_scale_reduction_table[(AH_PRIVATE(ah)->ah_tpScale)] * 2); } scaled_power = AH_MIN(power_limit, max_reg_allowed_power); /* * Reduce scaled Power by number of chains active to get to * per chain tx power level */ /* TODO: better value than these? */ switch (ar9300_get_ntxchains(tx_chainmask)) { case 1: ahp->upper_limit[0] = AH_MAX(0, scaled_power); break; case 2: scaled_power -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; ahp->upper_limit[1] = AH_MAX(0, scaled_power); break; case 3: scaled_power -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; ahp->upper_limit[2] = AH_MAX(0, scaled_power); break; default: HALASSERT(0); /* Unsupported number of chains */ } scaled_power = AH_MAX(0, scaled_power); /* Get target powers from EEPROM - our baseline for TX Power */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { /* Setup for CTL modes */ /* CTL_11B, CTL_11G, CTL_2GHT20 */ num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11g) - SUB_NUM_CTL_MODES_AT_2G_40; p_ctl_mode = ctl_modes_for11g; if (IEEE80211_IS_CHAN_HT40(chan)) { num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11g); /* All 2G CTL's */ } } else { /* Setup for CTL modes */ /* CTL_11A, CTL_5GHT20 */ num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11a) - SUB_NUM_CTL_MODES_AT_5G_40; p_ctl_mode = ctl_modes_for11a; if (IEEE80211_IS_CHAN_HT40(chan)) { num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11a); /* All 5G CTL's */ } } /* * For MIMO, need to apply regulatory caps individually across dynamically * running modes: CCK, OFDM, HT20, HT40 * * The outer loop walks through each possible applicable runtime mode. * The inner loop walks through each ctl_index entry in EEPROM. * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. * */ for (ctl_mode = 0; ctl_mode < num_ctl_modes; ctl_mode++) { HAL_BOOL is_ht40_ctl_mode = (p_ctl_mode[ctl_mode] == CTL_5GHT40) || (p_ctl_mode[ctl_mode] == CTL_2GHT40); if (is_ht40_ctl_mode) { freq = centers.synth_center; } else if (p_ctl_mode[ctl_mode] & EXT_ADDITIVE) { freq = centers.ext_center; } else { freq = centers.ctl_center; } HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "LOOP-Mode ctl_mode %d < %d, " "is_ht40_ctl_mode %d, EXT_ADDITIVE %d\n", ctl_mode, num_ctl_modes, is_ht40_ctl_mode, (p_ctl_mode[ctl_mode] & EXT_ADDITIVE)); /* walk through each CTL index stored in EEPROM */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { ctl_index = p_eep_data->ctl_index_2g; ctl_num = OSPREY_NUM_CTLS_2G; } else { ctl_index = p_eep_data->ctl_index_5g; ctl_num = OSPREY_NUM_CTLS_5G; } for (i = 0; (i < ctl_num) && ctl_index[i]; i++) { HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, " LOOP-Ctlidx %d: cfg_ctl 0x%2.2x p_ctl_mode 0x%2.2x " "ctl_index 0x%2.2x chan %d chanctl 0x%x\n", i, cfg_ctl, p_ctl_mode[ctl_mode], ctl_index[i], ichan->channel, ath_hal_getctl(ah, chan)); /* * compare test group from regulatory channel list * with test mode from p_ctl_mode list */ if ((((cfg_ctl & ~CTL_MODE_M) | (p_ctl_mode[ctl_mode] & CTL_MODE_M)) == ctl_index[i]) || (((cfg_ctl & ~CTL_MODE_M) | (p_ctl_mode[ctl_mode] & CTL_MODE_M)) == ((ctl_index[i] & CTL_MODE_M) | SD_NO_CTL))) { twice_min_edge_power = ar9300_eep_def_get_max_edge_power( p_eep_data, freq, i, IEEE80211_IS_CHAN_2GHZ(chan)); HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, " MATCH-EE_IDX %d: ch %d is2 %d " "2xMinEdge %d chainmask %d chains %d\n", i, freq, IEEE80211_IS_CHAN_2GHZ(chan), twice_min_edge_power, tx_chainmask, ar9300_get_ntxchains(tx_chainmask)); if ((cfg_ctl & ~CTL_MODE_M) == SD_NO_CTL) { /* * Find the minimum of all CTL edge powers * that apply to this channel */ twice_max_edge_power = AH_MIN(twice_max_edge_power, twice_min_edge_power); } else { /* specific */ twice_max_edge_power = twice_min_edge_power; break; } } } min_ctl_power = (u_int8_t)AH_MIN(twice_max_edge_power, scaled_power); HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, " SEL-Min ctl_mode %d p_ctl_mode %d " "2xMaxEdge %d sP %d min_ctl_pwr %d\n", ctl_mode, p_ctl_mode[ctl_mode], twice_max_edge_power, scaled_power, min_ctl_power); /* Apply ctl mode to correct target power set */ switch (p_ctl_mode[ctl_mode]) { case CTL_11B: for (i = ALL_TARGET_LEGACY_1L_5L; i <= ALL_TARGET_LEGACY_11S; i++) { p_pwr_array[i] = (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); } break; case CTL_11A: case CTL_11G: for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { p_pwr_array[i] = (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); #ifdef ATH_BT_COEX if ((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) { if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) && (ahp->ah_bt_wlan_isolation < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) { u_int8_t reduce_pow; reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX - ahp->ah_bt_wlan_isolation) << 1; if (reduce_pow <= p_pwr_array[i]) { p_pwr_array[i] -= reduce_pow; } } if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) && (i != ALL_TARGET_LEGACY_36) && (i != ALL_TARGET_LEGACY_48) && (i != ALL_TARGET_LEGACY_54) && (p_ctl_mode[ctl_mode] == CTL_11G)) { p_pwr_array[i] = 0; } } #endif } break; case CTL_5GHT20: case CTL_2GHT20: for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_23; i++) { p_pwr_array[i] = (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); #ifdef ATH_BT_COEX if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) && (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) && (ahp->ah_bt_wlan_isolation < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) { u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX - ahp->ah_bt_wlan_isolation) << 1; if (reduce_pow <= p_pwr_array[i]) { p_pwr_array[i] -= reduce_pow; } } #if ATH_SUPPORT_MCI else if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) && (p_ctl_mode[ctl_mode] == CTL_2GHT20) && (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) { u_int8_t max_pwr; max_pwr = MS(mci_concur_tx_max_pwr[2][1], ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK); if (p_pwr_array[i] > max_pwr) { p_pwr_array[i] = max_pwr; } } #endif #endif } break; case CTL_11B_EXT: #ifdef NOT_YET target_power_cck_ext.t_pow2x[0] = (u_int8_t) AH_MIN(target_power_cck_ext.t_pow2x[0], min_ctl_power); #endif /* NOT_YET */ break; case CTL_11A_EXT: case CTL_11G_EXT: #ifdef NOT_YET target_power_ofdm_ext.t_pow2x[0] = (u_int8_t) AH_MIN(target_power_ofdm_ext.t_pow2x[0], min_ctl_power); #endif /* NOT_YET */ break; case CTL_5GHT40: case CTL_2GHT40: for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_23; i++) { p_pwr_array[i] = (u_int8_t) AH_MIN(p_pwr_array[i], min_ctl_power); #ifdef ATH_BT_COEX if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) && (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) && (ahp->ah_bt_wlan_isolation < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) { u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX - ahp->ah_bt_wlan_isolation) << 1; if (reduce_pow <= p_pwr_array[i]) { p_pwr_array[i] -= reduce_pow; } } #if ATH_SUPPORT_MCI else if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) && (p_ctl_mode[ctl_mode] == CTL_2GHT40) && (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) { u_int8_t max_pwr; max_pwr = MS(mci_concur_tx_max_pwr[3][1], ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK); if (p_pwr_array[i] > max_pwr) { p_pwr_array[i] = max_pwr; } } #endif #endif } break; default: HALASSERT(0); break; } } /* end ctl mode checking */ return AH_TRUE; #undef EXT_ADDITIVE #undef CTL_11A_EXT #undef CTL_11G_EXT #undef CTL_11B_EXT #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN } /************************************************************** * ar9300_eeprom_set_transmit_power * * Set the transmit power in the baseband for the given * operating channel and mode. */ HAL_STATUS ar9300_eeprom_set_transmit_power(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, const struct ieee80211_channel *chan, u_int16_t cfg_ctl, u_int16_t antenna_reduction, u_int16_t twice_max_regulatory_power, u_int16_t power_limit) { #define ABS(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x) #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ u_int8_t target_power_val_t2[ar9300_rate_size]; u_int8_t target_power_val_t2_eep[ar9300_rate_size]; int16_t twice_array_gain = 0, max_power_level = 0; struct ath_hal_9300 *ahp = AH9300(ah); int i = 0; u_int32_t tmp_paprd_rate_mask = 0, *tmp_ptr = NULL; int paprd_scale_factor = 5; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); u_int8_t *ptr_mcs_rate2power_table_index; u_int8_t mcs_rate2power_table_index_ht20[24] = { ALL_TARGET_HT20_0_8_16, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_4, ALL_TARGET_HT20_5, ALL_TARGET_HT20_6, ALL_TARGET_HT20_7, ALL_TARGET_HT20_0_8_16, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_12, ALL_TARGET_HT20_13, ALL_TARGET_HT20_14, ALL_TARGET_HT20_15, ALL_TARGET_HT20_0_8_16, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_1_3_9_11_17_19, ALL_TARGET_HT20_20, ALL_TARGET_HT20_21, ALL_TARGET_HT20_22, ALL_TARGET_HT20_23 }; u_int8_t mcs_rate2power_table_index_ht40[24] = { ALL_TARGET_HT40_0_8_16, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_4, ALL_TARGET_HT40_5, ALL_TARGET_HT40_6, ALL_TARGET_HT40_7, ALL_TARGET_HT40_0_8_16, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_12, ALL_TARGET_HT40_13, ALL_TARGET_HT40_14, ALL_TARGET_HT40_15, ALL_TARGET_HT40_0_8_16, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_1_3_9_11_17_19, ALL_TARGET_HT40_20, ALL_TARGET_HT40_21, ALL_TARGET_HT40_22, ALL_TARGET_HT40_23, }; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] +++chan %d,cfgctl 0x%04x " "antenna_reduction 0x%04x, twice_max_regulatory_power 0x%04x " "power_limit 0x%04x\n", __func__, __LINE__, ichan->channel, cfg_ctl, antenna_reduction, twice_max_regulatory_power, power_limit); ar9300_set_target_power_from_eeprom(ah, ichan->channel, target_power_val_t2); if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) { if (IEEE80211_IS_CHAN_2GHZ(chan)) { if (IEEE80211_IS_CHAN_HT40(chan)) { tmp_paprd_rate_mask = p_eep_data->modal_header_2g.paprd_rate_mask_ht40; tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht40; } else { tmp_paprd_rate_mask = p_eep_data->modal_header_2g.paprd_rate_mask_ht20; tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht20; } } else { if (IEEE80211_IS_CHAN_HT40(chan)) { tmp_paprd_rate_mask = p_eep_data->modal_header_5g.paprd_rate_mask_ht40; tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht40; } else { tmp_paprd_rate_mask = p_eep_data->modal_header_5g.paprd_rate_mask_ht20; tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht20; } } AH_PAPRD_GET_SCALE_FACTOR( paprd_scale_factor, p_eep_data, IEEE80211_IS_CHAN_2GHZ(chan), ichan->channel); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] paprd_scale_factor %d\n", __func__, __LINE__, paprd_scale_factor); /* PAPRD is not done yet, Scale down the EEP power */ if (IEEE80211_IS_CHAN_HT40(chan)) { ptr_mcs_rate2power_table_index = &mcs_rate2power_table_index_ht40[0]; } else { ptr_mcs_rate2power_table_index = &mcs_rate2power_table_index_ht20[0]; } if (! ichan->paprd_table_write_done) { for (i = 0; i < 24; i++) { /* PAPRD is done yet, so Scale down Power for PAPRD Rates*/ if (tmp_paprd_rate_mask & (1 << i)) { target_power_val_t2[ptr_mcs_rate2power_table_index[i]] -= paprd_scale_factor; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d]: Chan %d " "Scale down target_power_val_t2[%d] = 0x%04x\n", __func__, __LINE__, ichan->channel, i, target_power_val_t2[i]); } } } else { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d]: PAPRD Done No TGT PWR Scaling\n", __func__, __LINE__); } } /* Save the Target power for future use */ OS_MEMCPY(target_power_val_t2_eep, target_power_val_t2, sizeof(target_power_val_t2)); ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan, target_power_val_t2, cfg_ctl, antenna_reduction, twice_max_regulatory_power, power_limit, 0); /* Save this for quick lookup */ ahp->reg_dmn = ath_hal_getctl(ah, chan); /* * Always use CDD/direct per rate power table for register based approach. * For FCC, CDD calculations should factor in the array gain, hence * this adjust call. ETSI and MKK does not have this requirement. */ if (is_reg_dmn_fcc(ahp->reg_dmn)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: FCC regdomain, calling reg_txpower_cdd\n", __func__); ar9300_adjust_reg_txpower_cdd(ah, target_power_val_t2); } if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) { for (i = 0; i < ar9300_rate_size; i++) { /* * EEPROM TGT PWR is not same as current TGT PWR, * so Disable PAPRD for this rate. * Some of APs might ask to reduce Target Power, * if target power drops significantly, * disable PAPRD for that rate. */ if (tmp_paprd_rate_mask & (1 << i)) { if (ABS(target_power_val_t2_eep[i], target_power_val_t2[i]) > paprd_scale_factor) { tmp_paprd_rate_mask &= ~(1 << i); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: EEP TPC[%02d] 0x%08x " "Curr TPC[%02d] 0x%08x mask = 0x%08x\n", __func__, i, target_power_val_t2_eep[i], i, target_power_val_t2[i], tmp_paprd_rate_mask); } } } HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Chan %d After tmp_paprd_rate_mask = 0x%08x\n", __func__, ichan->channel, tmp_paprd_rate_mask); if (tmp_ptr) { *tmp_ptr = tmp_paprd_rate_mask; } } /* Write target power array to registers */ ar9300_transmit_power_reg_write(ah, target_power_val_t2); /* Write target power for self generated frames to the TPC register */ ar9300_selfgen_tpc_reg_write(ah, chan, target_power_val_t2); /* GreenTx or Paprd */ if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable || AH_PRIVATE(ah)->ah_caps.halPaprdEnabled) { if (AR_SREV_POSEIDON(ah)) { /*For HAL_RSSI_TX_POWER_NONE array*/ OS_MEMCPY(ahp->ah_default_tx_power, target_power_val_t2, sizeof(target_power_val_t2)); /* Get defautl tx related register setting for GreenTx */ /* Record OB/DB */ ahp->ah_ob_db1[POSEIDON_STORED_REG_OBDB] = OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF2); /* Record TPC settting */ ahp->ah_ob_db1[POSEIDON_STORED_REG_TPC] = OS_REG_READ(ah, AR_TPC); /* Record BB_powertx_rate9 setting */ ahp->ah_ob_db1[POSEIDON_STORED_REG_BB_PWRTX_RATE9] = OS_REG_READ(ah, AR_PHY_BB_POWERTX_RATE9); } } /* * Return tx power used to iwconfig. * Since power is rate dependent, use one of the indices from the * AR9300_Rates enum to select an entry from target_power_val_t2[] * to report. * Currently returns the power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps * as CCK power is less interesting (?). */ i = ALL_TARGET_LEGACY_6_24; /* legacy */ if (IEEE80211_IS_CHAN_HT40(chan)) { i = ALL_TARGET_HT40_0_8_16; /* ht40 */ } else if (IEEE80211_IS_CHAN_HT20(chan)) { i = ALL_TARGET_HT20_0_8_16; /* ht20 */ } max_power_level = target_power_val_t2[i]; /* Adjusting the ah_max_power_level based on chains and antennaGain*/ - switch (ar9300_get_ntxchains(ahp->ah_tx_chainmask)) + switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ? + ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask))) { case 1: break; case 2: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0: ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_TWO_CHAIN)), 0)); /* Adjusting maxpower with antennaGain */ max_power_level -= twice_array_gain; /* Adjusting maxpower based on chain */ max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; break; case 3: twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0: ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_THREE_CHAIN)), 0)); /* Adjusting maxpower with antennaGain */ max_power_level -= twice_array_gain; /* Adjusting maxpower based on chain */ max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; break; default: HALASSERT(0); /* Unsupported number of chains */ } AH_PRIVATE(ah)->ah_maxPowerLevel = (int8_t)max_power_level; ar9300_calibration_apply(ah, ichan->channel); #undef ABS /* Handle per packet TPC initializations */ if (ah->ah_config.ath_hal_desc_tpc) { /* Transmit Power per-rate per-chain are computed here. A separate * power table is maintained for different MIMO modes (i.e. TXBF ON, * STBC) to enable easy lookup during packet transmit. * The reason for maintaing each of these tables per chain is that * the transmit power used for different number of chains is different * depending on whether the power has been limited by the target power, * the regulatory domain or the CTL limits. */ u_int mode = ath_hal_get_curmode(ah, chan); u_int32_t val = 0; u_int8_t chainmasks[AR9300_MAX_CHAINS] = {OSPREY_1_CHAINMASK, OSPREY_2LOHI_CHAINMASK, OSPREY_3_CHAINMASK}; for (i = 0; i < AR9300_MAX_CHAINS; i++) { OS_MEMCPY(target_power_val_t2, target_power_val_t2_eep, sizeof(target_power_val_t2_eep)); ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan, target_power_val_t2, cfg_ctl, antenna_reduction, twice_max_regulatory_power, power_limit, chainmasks[i]); HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, " Channel = %d Chainmask = %d, Upper Limit = [%2d.%1d dBm]\n", ichan->channel, i, ahp->upper_limit[i]/2, ahp->upper_limit[i]%2 * 5); ar9300_init_rate_txpower(ah, mode, chan, target_power_val_t2, chainmasks[i]); } /* Enable TPC */ OS_REG_WRITE(ah, AR_PHY_PWRTX_MAX, AR_PHY_PWRTX_MAX_TPC_ENABLE); /* * Disable per chain power reduction since we are already * accounting for this in our calculations */ val = OS_REG_READ(ah, AR_PHY_POWER_TX_SUB); if (AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, val & AR_PHY_POWER_TX_SUB_2_DISABLE); } else { OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, val & AR_PHY_POWER_TX_SUB_3_DISABLE); } } return HAL_OK; } /************************************************************** * ar9300_eeprom_set_addac * * Set the ADDAC from eeprom. */ void ar9300_eeprom_set_addac(struct ath_hal *ah, struct ieee80211_channel *chan) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "FIXME: ar9300_eeprom_def_set_addac called\n"); #if 0 MODAL_EEPDEF_HEADER *p_modal; struct ath_hal_9300 *ahp = AH9300(ah); ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; u_int8_t biaslevel; if (AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_SOWL) { return; } HALASSERT(owl_get_eepdef_ver(ahp) == AR9300_EEP_VER); /* Xpa bias levels in eeprom are valid from rev 14.7 */ if (owl_get_eepdef_rev(ahp) < AR9300_EEP_MINOR_VER_7) { return; } if (ahp->ah_emu_eeprom) { return; } p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]); if (p_modal->xpa_bias_lvl != 0xff) { biaslevel = p_modal->xpa_bias_lvl; } else { /* Use freqeuncy specific xpa bias level */ u_int16_t reset_freq_bin, freq_bin, freq_count = 0; CHAN_CENTERS centers; ar9300_get_channel_centers(ah, chan, ¢ers); reset_freq_bin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)); freq_bin = p_modal->xpa_bias_lvl_freq[0] & 0xff; biaslevel = (u_int8_t)(p_modal->xpa_bias_lvl_freq[0] >> 14); freq_count++; while (freq_count < 3) { if (p_modal->xpa_bias_lvl_freq[freq_count] == 0x0) { break; } freq_bin = p_modal->xpa_bias_lvl_freq[freq_count] & 0xff; if (reset_freq_bin >= freq_bin) { biaslevel = (u_int8_t)(p_modal->xpa_bias_lvl_freq[freq_count] >> 14); } else { break; } freq_count++; } } /* Apply bias level to the ADDAC values in the INI array */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { INI_RA(&ahp->ah_ini_addac, 7, 1) = (INI_RA(&ahp->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3; } else { INI_RA(&ahp->ah_ini_addac, 6, 1) = (INI_RA(&ahp->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6; } #endif } u_int ar9300_eeprom_dump_support(struct ath_hal *ah, void **pp_e) { *pp_e = &(AH9300(ah)->ah_eeprom); return sizeof(ar9300_eeprom_t); } u_int8_t ar9300_eeprom_get_num_ant_config(struct ath_hal_9300 *ahp, HAL_FREQ_BAND freq_band) { #if 0 ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; MODAL_EEPDEF_HEADER *p_modal = &(eep->modal_header[HAL_FREQ_BAND_2GHZ == freq_band]); BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header; u_int8_t num_ant_config; num_ant_config = 1; /* default antenna configuration */ if (p_base->version >= 0x0E0D) { if (p_modal->use_ant1) { num_ant_config += 1; } } return num_ant_config; #else return 1; #endif } HAL_STATUS ar9300_eeprom_get_ant_cfg(struct ath_hal_9300 *ahp, const struct ieee80211_channel *chan, u_int8_t index, u_int16_t *config) { #if 0 ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; MODAL_EEPDEF_HEADER *p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]); BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header; switch (index) { case 0: *config = p_modal->ant_ctrl_common & 0xFFFF; return HAL_OK; case 1: if (p_base->version >= 0x0E0D) { if (p_modal->use_ant1) { *config = ((p_modal->ant_ctrl_common & 0xFFFF0000) >> 16); return HAL_OK; } } break; default: break; } #endif return HAL_EINVAL; } u_int8_t* ar9300_eeprom_get_cust_data(struct ath_hal_9300 *ahp) { return (u_int8_t *)ahp; } #ifdef UNUSED static inline HAL_STATUS ar9300_check_eeprom(struct ath_hal *ah) { #if 0 u_int32_t sum = 0, el; u_int16_t *eepdata; int i; struct ath_hal_9300 *ahp = AH9300(ah); HAL_BOOL need_swap = AH_FALSE; ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom.def; u_int16_t magic, magic2; int addr; u_int16_t temp; /* ** We need to check the EEPROM data regardless of if it's in flash or ** in EEPROM. */ if (!ahp->ah_priv.priv.ah_eeprom_read( ah, AR9300_EEPROM_MAGIC_OFFSET, &magic)) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Reading Magic # failed\n", __func__); return AH_FALSE; } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Read Magic = 0x%04X\n", __func__, magic); if (!ar9300_eep_data_in_flash(ah)) { if (magic != AR9300_EEPROM_MAGIC) { magic2 = SWAP16(magic); if (magic2 == AR9300_EEPROM_MAGIC) { need_swap = AH_TRUE; eepdata = (u_int16_t *)(&ahp->ah_eeprom); for (addr = 0; addr < sizeof(ar9300_eeprom_t) / sizeof(u_int16_t); addr++) { temp = SWAP16(*eepdata); *eepdata = temp; eepdata++; HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "0x%04X ", *eepdata); if (((addr + 1) % 6) == 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "\n"); } } } else { HALDEBUG(ah, HAL_DEBUG_EEPROM, "Invalid EEPROM Magic. endianness missmatch.\n"); return HAL_EEBADSUM; } } } else { HALDEBUG(ah, HAL_DEBUG_EEPROM, "EEPROM being read from flash @0x%p\n", AH_PRIVATE(ah)->ah_st); } HALDEBUG(ah, HAL_DEBUG_EEPROM, "need_swap = %s.\n", need_swap?"True":"False"); if (need_swap) { el = SWAP16(ahp->ah_eeprom.def.base_eep_header.length); } else { el = ahp->ah_eeprom.def.base_eep_header.length; } eepdata = (u_int16_t *)(&ahp->ah_eeprom.def); for (i = 0; i < AH_MIN(el, sizeof(ar9300_eeprom_t)) / sizeof(u_int16_t); i++) { sum ^= *eepdata++; } if (need_swap) { /* * preddy: EEPROM endianness does not match. So change it * 8bit values in eeprom data structure does not need to be swapped * Only >8bits (16 & 32) values need to be swapped * If a new 16 or 32 bit field is added to the EEPROM contents, * please make sure to swap the field here */ u_int32_t integer, j; u_int16_t word; HALDEBUG(ah, HAL_DEBUG_EEPROM, "EEPROM Endianness is not native.. Changing \n"); /* convert Base Eep header */ word = SWAP16(eep->base_eep_header.length); eep->base_eep_header.length = word; word = SWAP16(eep->base_eep_header.checksum); eep->base_eep_header.checksum = word; word = SWAP16(eep->base_eep_header.version); eep->base_eep_header.version = word; word = SWAP16(eep->base_eep_header.reg_dmn[0]); eep->base_eep_header.reg_dmn[0] = word; word = SWAP16(eep->base_eep_header.reg_dmn[1]); eep->base_eep_header.reg_dmn[1] = word; word = SWAP16(eep->base_eep_header.rf_silent); eep->base_eep_header.rf_silent = word; word = SWAP16(eep->base_eep_header.blue_tooth_options); eep->base_eep_header.blue_tooth_options = word; word = SWAP16(eep->base_eep_header.device_cap); eep->base_eep_header.device_cap = word; /* convert Modal Eep header */ for (j = 0; j < ARRAY_LENGTH(eep->modal_header); j++) { MODAL_EEPDEF_HEADER *p_modal = &eep->modal_header[j]; integer = SWAP32(p_modal->ant_ctrl_common); p_modal->ant_ctrl_common = integer; for (i = 0; i < AR9300_MAX_CHAINS; i++) { integer = SWAP32(p_modal->ant_ctrl_chain[i]); p_modal->ant_ctrl_chain[i] = integer; } for (i = 0; i < AR9300_EEPROM_MODAL_SPURS; i++) { word = SWAP16(p_modal->spur_chans[i].spur_chan); p_modal->spur_chans[i].spur_chan = word; } } } /* Check CRC - Attach should fail on a bad checksum */ if (sum != 0xffff || owl_get_eepdef_ver(ahp) != AR9300_EEP_VER || owl_get_eepdef_rev(ahp) < AR9300_EEP_NO_BACK_VER) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", sum, owl_get_eepdef_ver(ahp)); return HAL_EEBADSUM; } #ifdef EEPROM_DUMP ar9300_eeprom_def_dump(ah, eep); #endif #if 0 #ifdef AH_AR9300_OVRD_TGT_PWR /* * 14.4 EEPROM contains low target powers. * Hardcode until EEPROM > 14.4 */ if (owl_get_eepdef_ver(ahp) == 14 && owl_get_eepdef_rev(ahp) <= 4) { MODAL_EEPDEF_HEADER *p_modal; #ifdef EEPROM_DUMP HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Original Target Powers\n"); ar9300_eep_def_dump_tgt_power(ah, eep); #endif HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Override Target Powers. EEPROM Version is %d.%d, " "Device Type %d\n", owl_get_eepdef_ver(ahp), owl_get_eepdef_rev(ahp), eep->base_eep_header.device_type); ar9300_eep_def_override_tgt_power(ah, eep); if (eep->base_eep_header.device_type == 5) { /* for xb72 only: improve transmit EVM for interop */ p_modal = &eep->modal_header[1]; p_modal->tx_frame_to_data_start = 0x23; p_modal->tx_frame_to_xpa_on = 0x23; p_modal->tx_frame_to_pa_on = 0x23; } #ifdef EEPROM_DUMP HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Modified Target Powers\n"); ar9300_eep_def_dump_tgt_power(ah, eep); #endif } #endif /* AH_AR9300_OVRD_TGT_PWR */ #endif #endif return HAL_OK; } #endif static u_int16_t ar9300_eeprom_get_spur_chan(struct ath_hal *ah, int i, HAL_BOOL is_2ghz) { u_int16_t spur_val = AR_NO_SPUR; #if 0 struct ath_hal_9300 *ahp = AH9300(ah); ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom; HALASSERT(i < AR_EEPROM_MODAL_SPURS ); HALDEBUG(ah, HAL_DEBUG_ANI, "Getting spur idx %d is2Ghz. %d val %x\n", i, is_2ghz, AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz]); switch (AH_PRIVATE(ah)->ah_config.ath_hal_spur_mode) { case SPUR_DISABLE: /* returns AR_NO_SPUR */ break; case SPUR_ENABLE_IOCTL: spur_val = AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz]; HALDEBUG(ah, HAL_DEBUG_ANI, "Getting spur val from new loc. %d\n", spur_val); break; case SPUR_ENABLE_EEPROM: spur_val = eep->modal_header[is_2ghz].spur_chans[i].spur_chan; break; } #endif return spur_val; } #ifdef UNUSED static inline HAL_BOOL ar9300_fill_eeprom(struct ath_hal *ah) { return ar9300_eeprom_restore(ah); } #endif u_int16_t ar9300_eeprom_struct_size(void) { return sizeof(ar9300_eeprom_t); } int ar9300_eeprom_struct_default_many(void) { return ARRAY_LENGTH(default9300); } ar9300_eeprom_t * ar9300_eeprom_struct_default(int default_index) { if (default_index >= 0 && default_index < ARRAY_LENGTH(default9300)) { return default9300[default_index]; } else { return 0; } } ar9300_eeprom_t * ar9300_eeprom_struct_default_find_by_id(int id) { int it; for (it = 0; it < ARRAY_LENGTH(default9300); it++) { if (default9300[it] != 0 && default9300[it]->template_version == id) { return default9300[it]; } } return 0; } HAL_BOOL ar9300_calibration_data_read_flash(struct ath_hal *ah, long address, u_int8_t *buffer, int many) { if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { return AH_FALSE; } return AH_FALSE; } HAL_BOOL ar9300_calibration_data_read_eeprom(struct ath_hal *ah, long address, u_int8_t *buffer, int many) { int i; u_int8_t value[2]; unsigned long eep_addr; unsigned long byte_addr; u_int16_t *svalue; if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE)) { return AH_FALSE; } for (i = 0; i < many; i++) { eep_addr = (u_int16_t) (address + i) / 2; byte_addr = (u_int16_t) (address + i) % 2; svalue = (u_int16_t *) value; if (! ath_hal_eepromRead(ah, eep_addr, svalue)) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Unable to read eeprom region \n", __func__); return AH_FALSE; } buffer[i] = (*svalue >> (8 * byte_addr)) & 0xff; } return AH_TRUE; } HAL_BOOL ar9300_calibration_data_read_otp(struct ath_hal *ah, long address, u_int8_t *buffer, int many, HAL_BOOL is_wifi) { int i; unsigned long eep_addr; unsigned long byte_addr; u_int32_t svalue; if (((address) < 0) || ((address + many) > 0x400)) { return AH_FALSE; } for (i = 0; i < many; i++) { eep_addr = (u_int16_t) (address + i) / 4; /* otp is 4 bytes long???? */ byte_addr = (u_int16_t) (address + i) % 4; if (!ar9300_otp_read(ah, eep_addr, &svalue, is_wifi)) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Unable to read otp region \n", __func__); return AH_FALSE; } buffer[i] = (svalue >> (8 * byte_addr)) & 0xff; } return AH_TRUE; } #ifdef ATH_CAL_NAND_FLASH HAL_BOOL ar9300_calibration_data_read_nand(struct ath_hal *ah, long address, u_int8_t *buffer, int many) { int ret_len; int ret_val = 1; /* Calling OS based API to read NAND */ ret_val = OS_NAND_FLASH_READ(ATH_CAL_NAND_PARTITION, address, many, &ret_len, buffer); return (ret_val ? AH_FALSE: AH_TRUE); } #endif HAL_BOOL ar9300_calibration_data_read(struct ath_hal *ah, long address, u_int8_t *buffer, int many) { switch (AH9300(ah)->calibration_data_source) { case calibration_data_flash: return ar9300_calibration_data_read_flash(ah, address, buffer, many); case calibration_data_eeprom: return ar9300_calibration_data_read_eeprom(ah, address, buffer, many); case calibration_data_otp: return ar9300_calibration_data_read_otp(ah, address, buffer, many, 1); #ifdef ATH_CAL_NAND_FLASH case calibration_data_nand: return ar9300_calibration_data_read_nand(ah,address,buffer,many); #endif } return AH_FALSE; } HAL_BOOL ar9300_calibration_data_read_array(struct ath_hal *ah, int address, u_int8_t *buffer, int many) { int it; for (it = 0; it < many; it++) { (void)ar9300_calibration_data_read(ah, address - it, buffer + it, 1); } return AH_TRUE; } /* * the address where the first configuration block is written */ static const int base_address = 0x3ff; /* 1KB */ static const int base_address_512 = 0x1ff; /* 512Bytes */ /* * the address where the NAND first configuration block is written */ #ifdef ATH_CAL_NAND_FLASH static const int base_address_nand = AR9300_FLASH_CAL_START_OFFSET; #endif /* * the lower limit on configuration data */ static const int low_limit = 0x040; /* * returns size of the physical eeprom in bytes. * 1024 and 2048 are normal sizes. * 0 means there is no eeprom. */ int32_t ar9300_eeprom_size(struct ath_hal *ah) { u_int16_t data; /* * first we'll try for 4096 bytes eeprom */ if (ar9300_eeprom_read_word(ah, 2047, &data)) { if (data != 0) { return 4096; } } /* * then we'll try for 2048 bytes eeprom */ if (ar9300_eeprom_read_word(ah, 1023, &data)) { if (data != 0) { return 2048; } } /* * then we'll try for 1024 bytes eeprom */ if (ar9300_eeprom_read_word(ah, 511, &data)) { if (data != 0) { return 1024; } } return 0; } /* * returns size of the physical otp in bytes. * 1024 and 2048 are normal sizes. * 0 means there is no eeprom. */ int32_t ar9300_otp_size(struct ath_hal *ah) { if (AR_SREV_POSEIDON(ah) || AR_SREV_HORNET(ah)) { return base_address_512+1; } else { return base_address+1; } } /* * find top of memory */ int ar9300_eeprom_base_address(struct ath_hal *ah) { int size; if (AH9300(ah)->calibration_data_source == calibration_data_otp) { return ar9300_otp_size(ah)-1; } else { size = ar9300_eeprom_size(ah); if (size > 0) { return size - 1; } else { return ar9300_otp_size(ah)-1; } } } int ar9300_eeprom_volatile(struct ath_hal *ah) { if (AH9300(ah)->calibration_data_source == calibration_data_otp) { return 0; /* no eeprom, use otp */ } else { return 1; /* board has eeprom or flash */ } } /* * need to change this to look for the pcie data in the low parts of memory * cal data needs to stop a few locations above */ int ar9300_eeprom_low_limit(struct ath_hal *ah) { return low_limit; } u_int16_t ar9300_compression_checksum(u_int8_t *data, int dsize) { int it; int checksum = 0; for (it = 0; it < dsize; it++) { checksum += data[it]; checksum &= 0xffff; } return checksum; } int ar9300_compression_header_unpack(u_int8_t *best, int *code, int *reference, int *length, int *major, int *minor) { unsigned long value[4]; value[0] = best[0]; value[1] = best[1]; value[2] = best[2]; value[3] = best[3]; *code = ((value[0] >> 5) & 0x0007); *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020); *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f); *major = (value[2] & 0x000f); *minor = (value[3] & 0x00ff); return 4; } static HAL_BOOL ar9300_uncompress_block(struct ath_hal *ah, u_int8_t *mptr, int mdata_size, u_int8_t *block, int size) { int it; int spot; int offset; int length; spot = 0; for (it = 0; it < size; it += (length + 2)) { offset = block[it]; offset &= 0xff; spot += offset; length = block[it + 1]; length &= 0xff; if (length > 0 && spot >= 0 && spot + length <= mdata_size) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Restore at %d: spot=%d offset=%d length=%d\n", __func__, it, spot, offset, length); OS_MEMCPY(&mptr[spot], &block[it + 2], length); spot += length; } else if (length > 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Bad restore at %d: spot=%d offset=%d length=%d\n", __func__, it, spot, offset, length); return AH_FALSE; } } return AH_TRUE; } static int ar9300_eeprom_restore_internal_address(struct ath_hal *ah, ar9300_eeprom_t *mptr, int mdata_size, int cptr, u_int8_t blank) { u_int8_t word[MOUTPUT]; ar9300_eeprom_t *dptr; /* was uint8 */ int code; int reference, length, major, minor; int osize; int it; int restored; u_int16_t checksum, mchecksum; restored = 0; for (it = 0; it < MSTATE; it++) { (void) ar9300_calibration_data_read_array( ah, cptr, word, compression_header_length); if (word[0] == blank && word[1] == blank && word[2] == blank && word[3] == blank) { break; } ar9300_compression_header_unpack( word, &code, &reference, &length, &major, &minor); HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Found block at %x: " "code=%d ref=%d length=%d major=%d minor=%d\n", __func__, cptr, code, reference, length, major, minor); #ifdef DONTUSE if (length >= 1024) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Skipping bad header\n", __func__); cptr -= compression_header_length; continue; } #endif osize = length; (void) ar9300_calibration_data_read_array( ah, cptr, word, compression_header_length + osize + compression_checksum_length); checksum = ar9300_compression_checksum( &word[compression_header_length], length); mchecksum = word[compression_header_length + osize] | (word[compression_header_length + osize + 1] << 8); HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: checksum %x %x\n", __func__, checksum, mchecksum); if (checksum == mchecksum) { switch (code) { case _compress_none: if (length != mdata_size) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: EEPROM structure size mismatch " "memory=%d eeprom=%d\n", __func__, mdata_size, length); return -1; } OS_MEMCPY((u_int8_t *)mptr, (u_int8_t *)(word + compression_header_length), length); HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: restored eeprom %d: uncompressed, length %d\n", __func__, it, length); restored = 1; break; #ifdef UNUSED case _compress_lzma: if (reference == reference_current) { dptr = mptr; } else { dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id( reference); if (dptr == 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Can't find reference eeprom struct %d\n", __func__, reference); goto done; } } usize = -1; if (usize != mdata_size) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: uncompressed data is wrong size %d %d\n", __func__, usize, mdata_size); goto done; } for (ib = 0; ib < mdata_size; ib++) { mptr[ib] = dptr[ib] ^ word[ib + overhead]; } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: restored eeprom %d: compressed, " "reference %d, length %d\n", __func__, it, reference, length); break; case _compress_pairs: if (reference == reference_current) { dptr = mptr; } else { dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id( reference); if (dptr == 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Can't find the reference " "eeprom structure %d\n", __func__, reference); goto done; } } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: restored eeprom %d: " "pairs, reference %d, length %d,\n", __func__, it, reference, length); break; #endif case _compress_block: if (reference == reference_current) { dptr = mptr; } else { dptr = ar9300_eeprom_struct_default_find_by_id(reference); if (dptr == 0) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: cant find reference eeprom struct %d\n", __func__, reference); break; } OS_MEMCPY(mptr, dptr, mdata_size); } HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: restore eeprom %d: block, reference %d, length %d\n", __func__, it, reference, length); (void) ar9300_uncompress_block(ah, (u_int8_t *) mptr, mdata_size, (u_int8_t *) (word + compression_header_length), length); restored = 1; break; default: HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: unknown compression code %d\n", __func__, code); break; } } else { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: skipping block with bad checksum\n", __func__); } cptr -= compression_header_length + osize + compression_checksum_length; } if (!restored) { cptr = -1; } return cptr; } static int ar9300_eeprom_restore_from_dram(struct ath_hal *ah, ar9300_eeprom_t *mptr, int mdata_size) { struct ath_hal_9300 *ahp = AH9300(ah); #if !defined(USE_PLATFORM_FRAMEWORK) char *cal_ptr; #endif HALASSERT(mdata_size > 0); /* if cal_in_flash is AH_TRUE, the address sent by LMAC to HAL (i.e. ah->ah_st) is corresponding to Flash. so return from here if ar9300_eep_data_in_flash(ah) returns AH_TRUE */ if(ar9300_eep_data_in_flash(ah)) return -1; #if 0 /* check if LMAC sent DRAM address is valid */ if (!(uintptr_t)(AH_PRIVATE(ah)->ah_st)) { return -1; } #endif /* When calibration data is from host, Host will copy the compressed data to the predefined DRAM location saved at ah->ah_st */ #if 0 ath_hal_printf(ah, "Restoring Cal data from DRAM\n"); ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st), HOST_CALDATA_SIZE); #endif if (!ahp->ah_cal_mem) { HALDEBUG(ah, HAL_DEBUG_EEPROM,"%s: can't remap dram region\n", __func__); return -1; } #if !defined(USE_PLATFORM_FRAMEWORK) cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET]; OS_MEMCPY(mptr, cal_ptr, mdata_size); #else OS_MEMCPY(mptr, ahp->ah_cal_mem, mdata_size); #endif if (mptr->eeprom_version == 0xff || mptr->template_version == 0xff || mptr->eeprom_version == 0 || mptr->template_version == 0) { /* The board is uncalibrated */ return -1; } if (mptr->eeprom_version != 0x2) { return -1; } return mdata_size; } static int ar9300_eeprom_restore_from_flash(struct ath_hal *ah, ar9300_eeprom_t *mptr, int mdata_size) { struct ath_hal_9300 *ahp = AH9300(ah); char *cal_ptr; HALASSERT(mdata_size > 0); if (!ahp->ah_cal_mem) { return -1; } ath_hal_printf(ah, "Restoring Cal data from Flash\n"); /* * When calibration data is saved in flash, read * uncompressed eeprom structure from flash and return */ cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET]; OS_MEMCPY(mptr, cal_ptr, mdata_size); #if 0 ar9300_swap_eeprom((ar9300_eeprom_t *)mptr); DONE IN ar9300_restore() #endif if (mptr->eeprom_version == 0xff || mptr->template_version == 0xff || mptr->eeprom_version == 0 || mptr->template_version == 0) { /* The board is uncalibrated */ return -1; } if (mptr->eeprom_version != 0x2) { return -1; } return mdata_size; } /* * Read the configuration data from the storage. We try the order with: * EEPROM, Flash, OTP. If all of above failed, use the default template. * The data can be put in any specified memory buffer. * * Returns -1 on error. * Returns address of next memory location on success. */ int ar9300_eeprom_restore_internal(struct ath_hal *ah, ar9300_eeprom_t *mptr, int mdata_size) { int nptr; nptr = -1; if ((AH9300(ah)->calibration_data_try == calibration_data_none || AH9300(ah)->calibration_data_try == calibration_data_dram) && AH9300(ah)->try_dram && nptr < 0) { ath_hal_printf(ah, "Restoring Cal data from DRAM\n"); AH9300(ah)->calibration_data_source = calibration_data_dram; AH9300(ah)->calibration_data_source_address = 0; nptr = ar9300_eeprom_restore_from_dram(ah, mptr, mdata_size); if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; } } if ((AH9300(ah)->calibration_data_try == calibration_data_none || AH9300(ah)->calibration_data_try == calibration_data_eeprom) && AH9300(ah)->try_eeprom && nptr < 0) { /* * need to look at highest eeprom address as well as at * base_address=0x3ff where we used to write the data */ ath_hal_printf(ah, "Restoring Cal data from EEPROM\n"); AH9300(ah)->calibration_data_source = calibration_data_eeprom; if (AH9300(ah)->calibration_data_try_address != 0) { AH9300(ah)->calibration_data_source_address = AH9300(ah)->calibration_data_try_address; nptr = ar9300_eeprom_restore_internal_address( ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0xff); } else { AH9300(ah)->calibration_data_source_address = ar9300_eeprom_base_address(ah); nptr = ar9300_eeprom_restore_internal_address( ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0xff); if (nptr < 0 && AH9300(ah)->calibration_data_source_address != base_address) { AH9300(ah)->calibration_data_source_address = base_address; nptr = ar9300_eeprom_restore_internal_address( ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0xff); } } if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; } } /* * ##### should be an ifdef test for any AP usage, * either in driver or in nart */ if ((AH9300(ah)->calibration_data_try == calibration_data_none || AH9300(ah)->calibration_data_try == calibration_data_flash) && AH9300(ah)->try_flash && nptr < 0) { ath_hal_printf(ah, "Restoring Cal data from Flash\n"); AH9300(ah)->calibration_data_source = calibration_data_flash; /* how are we supposed to set this for flash? */ AH9300(ah)->calibration_data_source_address = 0; nptr = ar9300_eeprom_restore_from_flash(ah, mptr, mdata_size); if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; } } if ((AH9300(ah)->calibration_data_try == calibration_data_none || AH9300(ah)->calibration_data_try == calibration_data_otp) && AH9300(ah)->try_otp && nptr < 0) { ath_hal_printf(ah, "Restoring Cal data from OTP\n"); AH9300(ah)->calibration_data_source = calibration_data_otp; if (AH9300(ah)->calibration_data_try_address != 0) { AH9300(ah)->calibration_data_source_address = AH9300(ah)->calibration_data_try_address; } else { AH9300(ah)->calibration_data_source_address = ar9300_eeprom_base_address(ah); } nptr = ar9300_eeprom_restore_internal_address( ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0); if (nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; } } #ifdef ATH_CAL_NAND_FLASH if ((AH9300(ah)->calibration_data_try == calibration_data_none || AH9300(ah)->calibration_data_try == calibration_data_nand) && AH9300(ah)->try_nand && nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_nand; AH9300(ah)->calibration_data_source_address = ((unsigned int)(AH_PRIVATE(ah)->ah_st)) + base_address_nand; if(ar9300_calibration_data_read( ah, AH9300(ah)->calibration_data_source_address, (u_int8_t *)mptr, mdata_size) == AH_TRUE) { nptr = mdata_size; } /*nptr=ar9300EepromRestoreInternalAddress(ah, mptr, mdataSize, CalibrationDataSourceAddress);*/ if(nptr < 0) { AH9300(ah)->calibration_data_source = calibration_data_none; AH9300(ah)->calibration_data_source_address = 0; } } #endif if (nptr < 0) { ath_hal_printf(ah, "%s[%d] No vaid CAL, calling default template\n", __func__, __LINE__); nptr = ar9300_eeprom_restore_something(ah, mptr, mdata_size); } return nptr; } /******************************************************************************/ /*! ** \brief Eeprom Swapping Function ** ** This function will swap the contents of the "longer" EEPROM data items ** to ensure they are consistent with the endian requirements for the platform ** they are being compiled for ** ** \param eh Pointer to the EEPROM data structure ** \return N/A */ #if AH_BYTE_ORDER == AH_BIG_ENDIAN void ar9300_swap_eeprom(ar9300_eeprom_t *eep) { u_int32_t dword; u_int16_t word; int i; word = __bswap16(eep->base_eep_header.reg_dmn[0]); eep->base_eep_header.reg_dmn[0] = word; word = __bswap16(eep->base_eep_header.reg_dmn[1]); eep->base_eep_header.reg_dmn[1] = word; dword = __bswap32(eep->base_eep_header.swreg); eep->base_eep_header.swreg = dword; dword = __bswap32(eep->modal_header_2g.ant_ctrl_common); eep->modal_header_2g.ant_ctrl_common = dword; dword = __bswap32(eep->modal_header_2g.ant_ctrl_common2); eep->modal_header_2g.ant_ctrl_common2 = dword; dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht20); eep->modal_header_2g.paprd_rate_mask_ht20 = dword; dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht40); eep->modal_header_2g.paprd_rate_mask_ht40 = dword; dword = __bswap32(eep->modal_header_5g.ant_ctrl_common); eep->modal_header_5g.ant_ctrl_common = dword; dword = __bswap32(eep->modal_header_5g.ant_ctrl_common2); eep->modal_header_5g.ant_ctrl_common2 = dword; dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht20); eep->modal_header_5g.paprd_rate_mask_ht20 = dword; dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht40); eep->modal_header_5g.paprd_rate_mask_ht40 = dword; for (i = 0; i < OSPREY_MAX_CHAINS; i++) { word = __bswap16(eep->modal_header_2g.ant_ctrl_chain[i]); eep->modal_header_2g.ant_ctrl_chain[i] = word; word = __bswap16(eep->modal_header_5g.ant_ctrl_chain[i]); eep->modal_header_5g.ant_ctrl_chain[i] = word; } } void ar9300_eeprom_template_swap(void) { int it; ar9300_eeprom_t *dptr; for (it = 0; it < ARRAY_LENGTH(default9300); it++) { dptr = ar9300_eeprom_struct_default(it); if (dptr != 0) { ar9300_swap_eeprom(dptr); } } } #endif /* * Restore the configuration structure by reading the eeprom. * This function destroys any existing in-memory structure content. */ HAL_BOOL ar9300_eeprom_restore(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); ar9300_eeprom_t *mptr; int mdata_size; HAL_BOOL status = AH_FALSE; mptr = &ahp->ah_eeprom; mdata_size = ar9300_eeprom_struct_size(); if (mptr != 0 && mdata_size > 0) { #if AH_BYTE_ORDER == AH_BIG_ENDIAN ar9300_eeprom_template_swap(); ar9300_swap_eeprom(mptr); #endif /* * At this point, mptr points to the eeprom data structure * in it's "default" state. If this is big endian, swap the * data structures back to "little endian" form. */ if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) { status = AH_TRUE; } #if AH_BYTE_ORDER == AH_BIG_ENDIAN /* Second Swap, back to Big Endian */ ar9300_eeprom_template_swap(); ar9300_swap_eeprom(mptr); #endif } ahp->ah_2g_paprd_rate_mask_ht40 = mptr->modal_header_2g.paprd_rate_mask_ht40; ahp->ah_2g_paprd_rate_mask_ht20 = mptr->modal_header_2g.paprd_rate_mask_ht20; ahp->ah_5g_paprd_rate_mask_ht40 = mptr->modal_header_5g.paprd_rate_mask_ht40; ahp->ah_5g_paprd_rate_mask_ht20 = mptr->modal_header_5g.paprd_rate_mask_ht20; return status; } int32_t ar9300_thermometer_get(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); int thermometer; thermometer = (ahp->ah_eeprom.base_eep_header.misc_configuration >> 1) & 0x3; thermometer--; return thermometer; } HAL_BOOL ar9300_thermometer_apply(struct ath_hal *ah) { int thermometer = ar9300_thermometer_get(ah); /* ch0_RXTX4 */ /*#define AR_PHY_65NM_CH0_RXTX4 AR_PHY_65NM(ch0_RXTX4)*/ #define AR_PHY_65NM_CH1_RXTX4 AR_PHY_65NM(ch1_RXTX4) #define AR_PHY_65NM_CH2_RXTX4 AR_PHY_65NM(ch2_RXTX4) /*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000*/ /*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28*/ #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S 29 #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR \ (0x1<ah_eeprom; tuning_caps_params = eep->base_eep_header.params_for_tuning_caps[0]; return tuning_caps_params; } /* * Read the tuning caps params from eeprom and set to correct register. * To regulation the frequency accuracy. */ HAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah) { int tuning_caps_params; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; tuning_caps_params = ar9300_tuning_caps_params_get(ah); if ((eep->base_eep_header.feature_enable & 0x40) >> 6) { tuning_caps_params &= 0x7f; if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) { return AH_TRUE; } else if (AR_SREV_SCORPION(ah)) { OS_REG_RMW_FIELD(ah, AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, tuning_caps_params); OS_REG_RMW_FIELD(ah, AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, tuning_caps_params); } else { OS_REG_RMW_FIELD(ah, AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, tuning_caps_params); OS_REG_RMW_FIELD(ah, AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, tuning_caps_params); } } return AH_TRUE; } /* * Read the tx_frame_to_xpa_on param from eeprom and apply the value to * correct register. */ HAL_BOOL ar9300_xpa_timing_control_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) { u_int8_t xpa_timing_control; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if ((eep->base_eep_header.feature_enable & 0x80) >> 7) { if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) { if (is_2ghz) { xpa_timing_control = eep->modal_header_2g.tx_frame_to_xpa_on; OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON, xpa_timing_control); } else { xpa_timing_control = eep->modal_header_5g.tx_frame_to_xpa_on; OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON, xpa_timing_control); } } } return AH_TRUE; } /* * Read the xLNA_bias_strength param from eeprom and apply the value to * correct register. */ HAL_BOOL ar9300_x_lNA_bias_strength_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) { u_int8_t x_lNABias; u_int32_t value = 0; ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if ((eep->base_eep_header.misc_configuration & 0x40) >> 6) { if (AR_SREV_OSPREY(ah)) { if (is_2ghz) { x_lNABias = eep->modal_header_2g.xLNA_bias_strength; } else { x_lNABias = eep->modal_header_5g.xLNA_bias_strength; } value = x_lNABias & ( 0x03 ); // bit0,1 for chain0 OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); value = (x_lNABias >> 2) & ( 0x03 ); // bit2,3 for chain1 OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); value = (x_lNABias >> 4) & ( 0x03 ); // bit4,5 for chain2 OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); } } return AH_TRUE; } /* * Read EEPROM header info and program the device for correct operation * given the channel value. */ HAL_BOOL ar9300_eeprom_set_board_values(struct ath_hal *ah, const struct ieee80211_channel *chan) { HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); ar9300_xpa_bias_level_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); ar9300_xpa_timing_control_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); ar9300_ant_ctrl_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); ar9300_drive_strength_apply(ah); ar9300_x_lNA_bias_strength_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); /* wait for Poseidon internal regular turnning */ /* for Hornet we move it before initPLL to avoid an access issue */ /* Function not used when EMULATION. */ if (!AR_SREV_HORNET(ah) && !AR_SREV_WASP(ah)) { ar9300_internal_regulator_apply(ah); } ar9300_attenuation_apply(ah, ichan->channel); ar9300_quick_drop_apply(ah, ichan->channel); ar9300_thermometer_apply(ah); if(!AR_SREV_WASP(ah)) { ar9300_tuning_caps_apply(ah); } ar9300_tx_end_to_xpab_off_apply(ah, ichan->channel); return AH_TRUE; } u_int8_t * ar9300_eeprom_get_spur_chans_ptr(struct ath_hal *ah, HAL_BOOL is_2ghz) { ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; if (is_2ghz) { return &(eep->modal_header_2g.spur_chans[0]); } else { return &(eep->modal_header_5g.spur_chans[0]); } } static u_int8_t ar9300_eeprom_get_tx_gain_table_number_max(struct ath_hal *ah) { unsigned long tx_gain_table_max; tx_gain_table_max = OS_REG_READ_FIELD(ah, AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX); return tx_gain_table_max; } u_int8_t ar9300_eeprom_tx_gain_table_index_max_apply(struct ath_hal *ah, u_int16_t channel) { unsigned int index; ar9300_eeprom_t *ahp_Eeprom; struct ath_hal_9300 *ahp = AH9300(ah); ahp_Eeprom = &ahp->ah_eeprom; if (ahp_Eeprom->base_ext1.misc_enable == 0) return AH_FALSE; if (channel < 4000) { index = ahp_Eeprom->modal_header_2g.tx_gain_cap; } else { index = ahp_Eeprom->modal_header_5g.tx_gain_cap; } OS_REG_RMW_FIELD(ah, AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX, index); return AH_TRUE; } static u_int8_t ar9300_eeprom_get_pcdac_tx_gain_table_i(struct ath_hal *ah, int i, u_int8_t *pcdac) { unsigned long tx_gain; u_int8_t tx_gain_table_max; tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah); if (i <= 0 || i > tx_gain_table_max) { *pcdac = 0; return AH_FALSE; } tx_gain = OS_REG_READ(ah, AR_PHY_TXGAIN_TAB(1) + i * 4); *pcdac = ((tx_gain >> 24) & 0xff); return AH_TRUE; } u_int8_t ar9300_eeprom_set_tx_gain_cap(struct ath_hal *ah, int *tx_gain_max) // pcdac read back from reg, read back value depends on reset 2GHz/5GHz ini // tx_gain_table, this function will be called twice after each // band's calibration. // after 2GHz cal, tx_gain_max[0] has 2GHz, calibration max txgain, // tx_gain_max[1]=-100 // after 5GHz cal, tx_gain_max[0],tx_gain_max[1] have calibration // value for both band // reset is on 5GHz, reg reading from tx_gain_table is for 5GHz, // so program can't recalculate 2g.tx_gain_cap at this point. { int i = 0, ig, im = 0; u_int8_t pcdac = 0; u_int8_t tx_gain_table_max; ar9300_eeprom_t *ahp_Eeprom; struct ath_hal_9300 *ahp = AH9300(ah); ahp_Eeprom = &ahp->ah_eeprom; if (ahp_Eeprom->base_ext1.misc_enable == 0) return AH_FALSE; tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah); for (i = 0; i < 2; i++) { if (tx_gain_max[i]>-100) { // -100 didn't cal that band. if ( i== 0) { if (tx_gain_max[1]>-100) { continue; // both band are calibrated, skip 2GHz 2g.tx_gain_cap reset } } for (ig = 1; ig <= tx_gain_table_max; ig++) { if (ah != 0 && ah->ah_reset != 0) { ar9300_eeprom_get_pcdac_tx_gain_table_i(ah, ig, &pcdac); if (pcdac >= tx_gain_max[i]) break; } } if (ig+1 <= tx_gain_table_max) { if (pcdac == tx_gain_max[i]) im = ig; else im = ig + 1; if (i == 0) { ahp_Eeprom->modal_header_2g.tx_gain_cap = im; } else { ahp_Eeprom->modal_header_5g.tx_gain_cap = im; } } else { if (i == 0) { ahp_Eeprom->modal_header_2g.tx_gain_cap = ig; } else { ahp_Eeprom->modal_header_5g.tx_gain_cap = ig; } } } } return AH_TRUE; } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c (revision 278741) @@ -1,691 +1,691 @@ /* * Copyright (c) 2012, 2013 Adrian Chadd . * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ah_desc.h" #include "ar9300.h" #include "ar9300reg.h" #include "ar9300phy.h" #include "ar9300desc.h" #include "ar9300_freebsd.h" #include "ar9300_stub.h" #include "ar9300_stub_funcs.h" #define FIX_NOISE_FLOOR 1 #define NEXT_TBTT_NOW 5 static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix); static HAL_BOOL ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix); static void ar9300SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, uint32_t rx_chainmask) { AH9300(ah)->ah_tx_chainmask = tx_chainmask & AH_PRIVATE(ah)->ah_caps.halTxChainMask; AH9300(ah)->ah_rx_chainmask = rx_chainmask & AH_PRIVATE(ah)->ah_caps.halRxChainMask; } static u_int ar9300GetSlotTime(struct ath_hal *ah) { u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; return (ath_hal_mac_usec(ah, clks)); /* convert from system clocks */ } static HAL_BOOL ar9300_freebsd_set_tx_power_limit(struct ath_hal *ah, uint32_t limit) { return (ar9300_set_tx_power_limit(ah, limit, 0, 0)); } static uint64_t ar9300_get_next_tbtt(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_NEXT_TBTT_TIMER)); } void ar9300_attach_freebsd_ops(struct ath_hal *ah) { /* Global functions */ ah->ah_detach = ar9300_detach; ah->ah_getRateTable = ar9300_get_rate_table; /* Reset functions */ ah->ah_reset = ar9300_reset_freebsd; ah->ah_phyDisable = ar9300_phy_disable; ah->ah_disable = ar9300_disable; ah->ah_configPCIE = ar9300_config_pcie_freebsd; // ah->ah_disablePCIE = ar9300_disable_pcie_phy; ah->ah_setPCUConfig = ar9300_set_pcu_config; // perCalibration ah->ah_perCalibrationN = ar9300_per_calibration_freebsd; ah->ah_resetCalValid = ar9300_reset_cal_valid_freebsd; ah->ah_setTxPowerLimit = ar9300_freebsd_set_tx_power_limit; ah->ah_getChanNoise = ath_hal_getChanNoise; /* Transmit functions */ ah->ah_setupTxQueue = ar9300_setup_tx_queue; ah->ah_setTxQueueProps = ar9300_set_tx_queue_props; ah->ah_getTxQueueProps = ar9300_get_tx_queue_props; ah->ah_releaseTxQueue = ar9300_release_tx_queue; ah->ah_resetTxQueue = ar9300_reset_tx_queue; ah->ah_getTxDP = ar9300_get_tx_dp; ah->ah_setTxDP = ar9300_set_tx_dp; ah->ah_numTxPending = ar9300_num_tx_pending; ah->ah_startTxDma = ar9300_start_tx_dma; ah->ah_stopTxDma = ar9300_stop_tx_dma_freebsd; ah->ah_setupTxDesc = ar9300_freebsd_setup_tx_desc; ah->ah_setupXTxDesc = ar9300_freebsd_setup_x_tx_desc; ah->ah_fillTxDesc = ar9300_freebsd_fill_tx_desc; ah->ah_procTxDesc = ar9300_freebsd_proc_tx_desc; ah->ah_getTxIntrQueue = ar9300_get_tx_intr_queue; // reqTxIntrDesc ah->ah_getTxCompletionRates = ar9300_freebsd_get_tx_completion_rates; ah->ah_setTxDescLink = ar9300_set_desc_link; ah->ah_getTxDescLink = ar9300_freebsd_get_desc_link; ah->ah_getTxDescLinkPtr = ar9300_get_desc_link_ptr; ah->ah_setupTxStatusRing = ar9300_setup_tx_status_ring; ah->ah_getTxRawTxDesc = ar9300_get_raw_tx_desc; ah->ah_updateTxTrigLevel = ar9300_update_tx_trig_level; /* RX functions */ ah->ah_getRxDP = ar9300_get_rx_dp; ah->ah_setRxDP = ar9300_set_rx_dp; ah->ah_enableReceive = ar9300_enable_receive; ah->ah_stopDmaReceive = ar9300_stop_dma_receive_freebsd; ah->ah_startPcuReceive = ar9300_start_pcu_receive_freebsd; ah->ah_stopPcuReceive = ar9300_stop_pcu_receive; ah->ah_setMulticastFilter = ar9300_set_multicast_filter; ah->ah_setMulticastFilterIndex = ar9300SetMulticastFilterIndex; ah->ah_clrMulticastFilterIndex = ar9300ClrMulticastFilterIndex; ah->ah_getRxFilter = ar9300_get_rx_filter; ah->ah_setRxFilter = ar9300_set_rx_filter; /* setupRxDesc */ ah->ah_procRxDesc = ar9300_proc_rx_desc_freebsd; ah->ah_rxMonitor = ar9300_ani_rxmonitor_freebsd; ah->ah_aniPoll = ar9300_ani_poll_freebsd; ah->ah_procMibEvent = ar9300_process_mib_intr; /* Misc functions */ ah->ah_getCapability = ar9300_get_capability; ah->ah_setCapability = ar9300_set_capability; ah->ah_getDiagState = ar9300_get_diag_state; ah->ah_getMacAddress = ar9300_get_mac_address; ah->ah_setMacAddress = ar9300_set_mac_address; ah->ah_getBssIdMask = ar9300_get_bss_id_mask; ah->ah_setBssIdMask = ar9300_set_bss_id_mask; ah->ah_setRegulatoryDomain = ar9300_set_regulatory_domain; ah->ah_setLedState = ar9300_set_led_state; ah->ah_writeAssocid = ar9300_write_associd; ah->ah_gpioCfgInput = ar9300_gpio_cfg_input; ah->ah_gpioCfgOutput = ar9300_gpio_cfg_output; ah->ah_gpioGet = ar9300_gpio_get; ah->ah_gpioSet = ar9300_gpio_set; ah->ah_gpioSetIntr = ar9300_gpio_set_intr; /* polarity */ /* mask */ ah->ah_getTsf32 = ar9300_get_tsf32; ah->ah_getTsf64 = ar9300_get_tsf64; ah->ah_resetTsf = ar9300_reset_tsf; ah->ah_detectCardPresent = ar9300_detect_card_present; // ah->ah_updateMibCounters = ar9300_update_mib_counters; ah->ah_getRfGain = ar9300_get_rfgain; ah->ah_getDefAntenna = ar9300_get_def_antenna; ah->ah_setDefAntenna = ar9300_set_def_antenna; // ah->ah_getAntennaSwitch = ar9300_get_antenna_switch; // ah->ah_setAntennaSwitch = ar9300_set_antenna_switch; // ah->ah_setSifsTime = ar9300_set_sifs_time; // ah->ah_getSifsTime = ar9300_get_sifs_time; ah->ah_setSlotTime = ar9300_set_slot_time; ah->ah_getSlotTime = ar9300GetSlotTime; ah->ah_getAckTimeout = ar9300_get_ack_timeout; ah->ah_setAckTimeout = ar9300_set_ack_timeout; // XXX ack/ctsrate // XXX CTS timeout // XXX decompmask // coverageclass ah->ah_setQuiet = ar9300_set_quiet; ah->ah_getMibCycleCounts = ar9300_freebsd_get_mib_cycle_counts; /* DFS functions */ ah->ah_enableDfs = ar9300_enable_dfs; ah->ah_getDfsThresh = ar9300_get_dfs_thresh; ah->ah_getDfsDefaultThresh = ar9300_freebsd_get_dfs_default_thresh; // procradarevent ah->ah_isFastClockEnabled = ar9300_is_fast_clock_enabled; ah->ah_get11nExtBusy = ar9300_get_11n_ext_busy; /* Key cache functions */ ah->ah_getKeyCacheSize = ar9300_get_key_cache_size; ah->ah_resetKeyCacheEntry = ar9300_reset_key_cache_entry; ah->ah_isKeyCacheEntryValid = ar9300_is_key_cache_entry_valid; ah->ah_setKeyCacheEntry = ar9300_set_key_cache_entry; ah->ah_setKeyCacheEntryMac = ar9300_set_key_cache_entry_mac; /* Power management functions */ ah->ah_setPowerMode = ar9300_set_power_mode; ah->ah_getPowerMode = ar9300_get_power_mode; /* Beacon functions */ /* ah_setBeaconTimers */ ah->ah_beaconInit = ar9300_freebsd_beacon_init; /* ah_setBeaconTimers */ ah->ah_setStationBeaconTimers = ar9300_set_sta_beacon_timers; /* ah_resetStationBeaconTimers */ /* ah_getNextTBTT */ ah->ah_getNextTBTT = ar9300_get_next_tbtt; /* Interrupt functions */ ah->ah_isInterruptPending = ar9300_is_interrupt_pending; ah->ah_getPendingInterrupts = ar9300_get_pending_interrupts_freebsd; ah->ah_getInterrupts = ar9300_get_interrupts; ah->ah_setInterrupts = ar9300_set_interrupts_freebsd; /* Regulatory/internal functions */ // AH_PRIVATE(ah)->ah_getNfAdjust = ar9300_get_nf_adjust; AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word; // AH_PRIVATE(ah)->ah_getChipPowerLimits = ar9300_get_chip_power_limits; AH_PRIVATE(ah)->ah_getWirelessModes = ar9300_get_wireless_modes; AH_PRIVATE(ah)->ah_getChannelEdges = ar9300_get_channel_edges; AH_PRIVATE(ah)->ah_eepromRead = ar9300_eeprom_read_word; /* XXX ah_eeprom */ /* XXX ah_eeversion */ /* XXX ah_eepromDetach */ /* XXX ah_eepromGet */ AH_PRIVATE(ah)->ah_eepromGet = ar9300_eeprom_get_freebsd; /* XXX ah_eepromSet */ /* XXX ah_getSpurChan */ /* XXX ah_eepromDiag */ /* 802.11n functions */ ah->ah_chainTxDesc = ar9300_freebsd_chain_tx_desc; ah->ah_setupFirstTxDesc= ar9300_freebsd_setup_first_tx_desc; ah->ah_setupLastTxDesc = ar9300_freebsd_setup_last_tx_desc; ah->ah_set11nRateScenario = ar9300_freebsd_set_11n_rate_scenario; ah->ah_set11nTxDesc = ar9300_freebsd_setup_11n_desc; ah->ah_set11nAggrFirst = ar9300_set_11n_aggr_first; ah->ah_set11nAggrMiddle = ar9300_set_11n_aggr_middle; ah->ah_set11nAggrLast = ar9300_set_11n_aggr_last; ah->ah_clr11nAggr = ar9300_clr_11n_aggr; ah->ah_set11nBurstDuration = ar9300_set_11n_burst_duration; /* ah_get11nExtBusy */ ah->ah_set11nMac2040 = ar9300_set_11n_mac2040; ah->ah_setChainMasks = ar9300SetChainMasks; /* ah_get11nRxClear */ /* ah_set11nRxClear */ /* bluetooth coexistence functions */ ah->ah_btCoexSetInfo = ar9300_set_bt_coex_info; ah->ah_btCoexSetConfig = ar9300_bt_coex_config; ah->ah_btCoexSetQcuThresh = ar9300_bt_coex_set_qcu_thresh; ah->ah_btCoexSetWeights = ar9300_bt_coex_set_weights; ah->ah_btCoexSetBmissThresh = ar9300_bt_coex_setup_bmiss_thresh; ah->ah_btCoexSetParameter = ar9300_bt_coex_set_parameter; ah->ah_btCoexDisable = ar9300_bt_coex_disable; ah->ah_btCoexEnable = ar9300_bt_coex_enable; /* MCI bluetooth functions */ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights; ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable; ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable; } ah->ah_btMciSetup = ar9300_mci_setup; ah->ah_btMciSendMessage = ar9300_mci_send_message; ah->ah_btMciGetInterrupt = ar9300_mci_get_interrupt; ah->ah_btMciGetState = ar9300_mci_state; ah->ah_btMciDetach = ar9300_mci_detach; /* LNA diversity functions */ ah->ah_divLnaConfGet = ar9300_ant_div_comb_get_config; ah->ah_divLnaConfSet = ar9300_ant_div_comb_set_config; } HAL_BOOL ar9300_reset_freebsd(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_BOOL bChannelChange, HAL_STATUS *status) { HAL_BOOL r; HAL_HT_MACMODE macmode; struct ath_hal_private *ap = AH_PRIVATE(ah); macmode = IEEE80211_IS_CHAN_HT40(chan) ? HAL_HT_MACMODE_2040 : HAL_HT_MACMODE_20; r = ar9300_reset(ah, opmode, chan, macmode, ap->ah_caps.halTxChainMask, ap->ah_caps.halRxChainMask, HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */ bChannelChange, status, AH_FALSE); /* XXX should really extend ath_hal_reset() */ return (r); } void ar9300_config_pcie_freebsd(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL powerOff) { ar9300_config_pci_power_save(ah, restore ? 1 : 0, powerOff ? 1 : 0); } /* * This is a copy from ar9300_eeprom_get(), purely because the FreeBSD * API is very silly and inconsistent. * * The AR93xx HAL doesn't call the eepromGetFlag() function, so this * only occurs for FreeBSD code. * * When I fix this particular API, I'll undo this. */ HAL_STATUS ar9300_eeprom_get_freebsd(struct ath_hal *ah, int param, void *val) { switch (param) { case AR_EEP_FSTCLK_5G: return HAL_OK; default: ath_hal_printf(ah, "%s: called, param=%d\n", __func__, param); return HAL_EIO; } } HAL_BOOL ar9300_stop_tx_dma_freebsd(struct ath_hal *ah, u_int q) { return ar9300_stop_tx_dma(ah, q, 1000); } void ar9300_ani_poll_freebsd(struct ath_hal *ah, const struct ieee80211_channel *chan) { HAL_NODE_STATS stats; HAL_ANISTATS anistats; OS_MEMZERO(&stats, sizeof(stats)); OS_MEMZERO(&anistats, sizeof(anistats)); ar9300_ani_ar_poll(ah, &stats, chan, &anistats); } /* * Setup the configuration parameters in the style the AR9300 HAL * wants. */ void ar9300_config_defaults_freebsd(struct ath_hal *ah, HAL_OPS_CONFIG *ah_config) { /* Until FreeBSD's HAL does this by default - just copy */ OS_MEMCPY(&ah->ah_config, ah_config, sizeof(HAL_OPS_CONFIG)); ah->ah_config.ath_hal_enable_ani = AH_TRUE; } HAL_BOOL ar9300_stop_dma_receive_freebsd(struct ath_hal *ah) { return ar9300_stop_dma_receive(ah, 1000); } HAL_BOOL ar9300_get_pending_interrupts_freebsd(struct ath_hal *ah, HAL_INT *masked) { /* Non-MSI, so no MSI vector; and 'nortc' = 0 */ return ar9300_get_pending_interrupts(ah, masked, HAL_INT_LINE, 0, 0); } HAL_INT ar9300_set_interrupts_freebsd(struct ath_hal *ah, HAL_INT ints) { /* nortc = 0 */ return ar9300_set_interrupts(ah, ints, 0); } HAL_BOOL ar9300_per_calibration_freebsd(struct ath_hal *ah, struct ieee80211_channel *chan, u_int rxchainmask, HAL_BOOL long_cal, HAL_BOOL *isCalDone) { /* XXX fake scheduled calibrations for now */ u_int32_t sched_cals = 0xfffffff; return ar9300_calibration(ah, chan, AH_PRIVATE(ah)->ah_caps.halRxChainMask, long_cal, isCalDone, 0, /* is_scan */ &sched_cals); } HAL_BOOL ar9300_reset_cal_valid_freebsd(struct ath_hal *ah, const struct ieee80211_channel *chan) { HAL_BOOL is_cal_done = AH_TRUE; ar9300_reset_cal_valid(ah, chan, &is_cal_done, 0xffffffff); return (is_cal_done); } void ar9300_start_pcu_receive_freebsd(struct ath_hal *ah) { /* is_scanning flag == NULL */ ar9300_start_pcu_receive(ah, AH_FALSE); } /* * FreeBSD will just pass in the descriptor value as 'pa'. * The Atheros HAL treats 'pa' as the physical address of the RX * descriptor and 'bufaddr' as the physical address of the RX buffer. * I'm not sure why they didn't collapse them - the AR9300 RX descriptor * routine doesn't check 'pa'. */ HAL_STATUS ar9300_proc_rx_desc_freebsd(struct ath_hal *ah, struct ath_desc *ds, uint32_t pa, struct ath_desc *ds_next, uint64_t tsf, struct ath_rx_status *rxs) { return (ar9300_proc_rx_desc_fast(ah, ds, 0, ds_next, rxs, (void *) ds)); } void ar9300_ani_rxmonitor_freebsd(struct ath_hal *ah, const HAL_NODE_STATS *stats, const struct ieee80211_channel *chan) { } void ar9300_freebsd_get_desc_link(struct ath_hal *ah, void *ds, uint32_t *link) { struct ar9300_txc *ads = AR9300TXC(ds); (*link) = ads->ds_link; } /* * TX descriptor field setting wrappers - eek. */ HAL_BOOL ar9300_freebsd_setup_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsCtsDuration, u_int compicvLen, u_int compivLen, u_int comp) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_KEY_TYPE keyType = 0; /* XXX No padding */ if (keyIx != HAL_TXKEYIX_INVALID) keyType = ahp->ah_keytype[keyIx]; /* XXX bounds check keyix */ ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx, keyType, flags); return AH_TRUE; } HAL_BOOL ar9300_freebsd_setup_x_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int txRate1, u_int txTries1, u_int txRate2, u_int txTries2, u_int txRate3, u_int txTries3) { #if 0 ath_hal_printf(ah, "%s: called, 0x%x/%d, 0x%x/%d, 0x%x/%d\n", __func__, txRate1, txTries1, txRate2, txTries2, txRate3, txTries3); #endif /* XXX should only be called during probe */ return (AH_TRUE); } HAL_BOOL ar9300_freebsd_fill_tx_desc(struct ath_hal *ah, struct ath_desc *ds, HAL_DMA_ADDR *bufListPtr, uint32_t *segLenPtr, u_int descId, u_int qid, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0) { HAL_KEY_TYPE keyType = 0; const struct ar9300_txc *ads = AR9300TXC_CONST(ds0); /* * FreeBSD's HAL doesn't pass the keytype to fill_tx_desc(); * it's copied as part of the descriptor chaining. * * So, extract it from ds0. */ keyType = MS(ads->ds_ctl17, AR_encr_type); return ar9300_fill_tx_desc(ah, ds, bufListPtr, segLenPtr, descId, qid, keyType, firstSeg, lastSeg, ds0); } HAL_BOOL ar9300_freebsd_get_tx_completion_rates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; /* XXX for now */ } /* * 802.11n TX descriptor wrappers */ void ar9300_freebsd_set_11n_rate_scenario(struct ath_hal *ah, struct ath_desc *ds, u_int durUpdateEn, u_int rtsctsRate, HAL_11N_RATE_SERIES series[], u_int nseries, u_int flags) { /* lastds=NULL, rtscts_duration is 0, smart antenna is 0 */ ar9300_set_11n_rate_scenario(ah, (void *) ds, (void *)ds, durUpdateEn, rtsctsRate, 0, series, nseries, flags, 0); } /* chaintxdesc */ HAL_BOOL ar9300_freebsd_chain_tx_desc(struct ath_hal *ah, struct ath_desc *ds, HAL_DMA_ADDR *bufLenList, uint32_t *segLenList, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx, HAL_CIPHER cipher, uint8_t numDelims, HAL_BOOL firstSeg, HAL_BOOL lastSeg, HAL_BOOL lastAggr) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } /* setupfirsttxdesc */ HAL_BOOL ar9300_freebsd_setup_first_tx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen, u_int flags, u_int txPower, u_int txRate0, u_int txTries0, u_int antMode, u_int rtsctsRate, u_int rtsctsDuration) { ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } /* setuplasttxdesc */ /* * This gets called but for now let's not log anything; * it's only used to update the rate control information. */ HAL_BOOL ar9300_freebsd_setup_last_tx_desc(struct ath_hal *ah, struct ath_desc *ds, const struct ath_desc *ds0) { // ath_hal_printf(ah, "%s: called\n", __func__); return AH_FALSE; } void ar9300_freebsd_setup_11n_desc(struct ath_hal *ah, void *ds, u_int pktLen, HAL_PKT_TYPE type, u_int txPower, u_int keyIx, u_int flags) { ath_hal_printf(ah, "%s: called\n", __func__); #if 0 struct ath_hal_9300 *ahp = AH9300(ah); HAL_KEY_TYPE keyType = 0; /* XXX No padding */ if (keyIx != HAL_TXKEYIX_INVALID) keyType = ahp->ah_keytype[keyIx]; /* XXX bounds check keyix */ ar9300_set_11n_tx_desc(ah, ds, pktLen, type, txPower, keyIx, keyType, flags); #endif } HAL_STATUS ar9300_freebsd_proc_tx_desc(struct ath_hal *ah, struct ath_desc *ds, struct ath_tx_status *ts) { return ar9300_proc_tx_desc(ah, ts); } void ar9300_freebsd_beacon_init(struct ath_hal *ah, uint32_t next_beacon, uint32_t beacon_period) { - ar9300_beacon_init(ah, next_beacon, beacon_period, + ar9300_beacon_init(ah, next_beacon, beacon_period, 0, AH_PRIVATE(ah)->ah_opmode); } HAL_BOOL ar9300_freebsd_get_mib_cycle_counts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) { return (AH_FALSE); } HAL_BOOL ar9300_freebsd_get_dfs_default_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { /* XXX not yet */ return (AH_FALSE); } /* * Clear multicast filter by index - from FreeBSD ar5212_recv.c */ static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix) { uint32_t val; if (ix >= 64) return (AH_FALSE); if (ix >= 32) { val = OS_REG_READ(ah, AR_MCAST_FIL1); OS_REG_WRITE(ah, AR_MCAST_FIL1, (val &~ (1<<(ix-32)))); } else { val = OS_REG_READ(ah, AR_MCAST_FIL0); OS_REG_WRITE(ah, AR_MCAST_FIL0, (val &~ (1<= 64) return (AH_FALSE); if (ix >= 32) { val = OS_REG_READ(ah, AR_MCAST_FIL1); OS_REG_WRITE(ah, AR_MCAST_FIL1, (val | (1<<(ix-32)))); } else { val = OS_REG_READ(ah, AR_MCAST_FIL0); OS_REG_WRITE(ah, AR_MCAST_FIL0, (val | (1< -122dBm to -59dBm * resolution (2 bits) is 0.25dBm */ #define NOISE_PWR_DATA_OFFSET -90 /* dbm - all pwr report data is represented offset by this */ #define INT_2_NOISE_PWR_DBM(_p) (((_p) - NOISE_PWR_DATA_OFFSET) << 2) #define NOISE_PWR_DBM_2_INT(_p) ((((_p) + 3) >> 2) + NOISE_PWR_DATA_OFFSET) #define NOISE_PWR_DBM_2_DEC(_p) (((-(_p)) & 3) * 25) #define N2DBM(_x,_y) ((((_x) - NOISE_PWR_DATA_OFFSET) << 2) - (_y)/25) /* SPECTRAL SCAN defines end */ typedef struct halvowstats { u_int32_t tx_frame_count; u_int32_t rx_frame_count; u_int32_t rx_clear_count; u_int32_t cycle_count; u_int32_t ext_cycle_count; } HAL_VOWSTATS; #define HAL_BT_COEX_FLAG_LOW_ACK_PWR 0x00000001 #define HAL_BT_COEX_FLAG_LOWER_TX_PWR 0x00000002 #define HAL_BT_COEX_FLAG_ANT_DIV_ALLOW 0x00000004 /* Check Rx Diversity is allowed */ #define HAL_BT_COEX_FLAG_ANT_DIV_ENABLE 0x00000008 /* Check Diversity is on or off */ #define HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR 0x00000010 #define HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX 0x00000020 /* * Weight table configurations. */ #define AR9300_BT_WGHT 0xcccc4444 #define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 #define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 #define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 #define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 #define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 #define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 #define AR9300_STOMP_ALL_FORCE_WLAN_WGHT0 0xffffffff // Stomp BT even when WLAN is idle #define AR9300_STOMP_ALL_FORCE_WLAN_WGHT1 0xffffffff #define AR9300_STOMP_LOW_FORCE_WLAN_WGHT0 0x88888888 // Stomp BT even when WLAN is idle #define AR9300_STOMP_LOW_FORCE_WLAN_WGHT1 0x88888888 #define JUPITER_STOMP_ALL_WLAN_WGHT0 0x01017d01 #define JUPITER_STOMP_ALL_WLAN_WGHT1 0x41414101 #define JUPITER_STOMP_ALL_WLAN_WGHT2 0x41414101 #define JUPITER_STOMP_ALL_WLAN_WGHT3 0x41414141 #define JUPITER_STOMP_LOW_WLAN_WGHT0 0x01017d01 #define JUPITER_STOMP_LOW_WLAN_WGHT1 0x3b3b3b01 #define JUPITER_STOMP_LOW_WLAN_WGHT2 0x3b3b3b01 #define JUPITER_STOMP_LOW_WLAN_WGHT3 0x3b3b3b3b #define JUPITER_STOMP_LOW_FTP_WLAN_WGHT0 0x01017d01 #define JUPITER_STOMP_LOW_FTP_WLAN_WGHT1 0x013b0101 #define JUPITER_STOMP_LOW_FTP_WLAN_WGHT2 0x3b3b0101 #define JUPITER_STOMP_LOW_FTP_WLAN_WGHT3 0x3b3b013b #define JUPITER_STOMP_NONE_WLAN_WGHT0 0x01017d01 #define JUPITER_STOMP_NONE_WLAN_WGHT1 0x01010101 #define JUPITER_STOMP_NONE_WLAN_WGHT2 0x01010101 #define JUPITER_STOMP_NONE_WLAN_WGHT3 0x01010101 #define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0 0x01017d7d #define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1 0x7d7d7d01 #define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2 0x7d7d7d7d #define JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3 0x7d7d7d7d #define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0 0x01013b3b #define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1 0x3b3b3b01 #define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2 0x3b3b3b3b #define JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3 0x3b3b3b3b #define MCI_CONCUR_TX_WLAN_WGHT1_MASK 0xff000000 #define MCI_CONCUR_TX_WLAN_WGHT1_MASK_S 24 #define MCI_CONCUR_TX_WLAN_WGHT2_MASK 0x00ff0000 #define MCI_CONCUR_TX_WLAN_WGHT2_MASK_S 16 #define MCI_CONCUR_TX_WLAN_WGHT3_MASK 0x000000ff #define MCI_CONCUR_TX_WLAN_WGHT3_MASK_S 0 #define MCI_CONCUR_TX_WLAN_WGHT3_MASK2 0x00ff0000 #define MCI_CONCUR_TX_WLAN_WGHT3_MASK2_S 16 #define MCI_QUERY_BT_VERSION_VERBOSE 0 #define MCI_LINKID_INDEX_MGMT_PENDING 1 #define HAL_MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ typedef enum mci_message_header { MCI_LNA_CTRL = 0x10, /* len = 0 */ MCI_CONT_NACK = 0x20, /* len = 0 */ MCI_CONT_INFO = 0x30, /* len = 4 */ MCI_CONT_RST = 0x40, /* len = 0 */ MCI_SCHD_INFO = 0x50, /* len = 16 */ MCI_CPU_INT = 0x60, /* len = 4 */ MCI_SYS_WAKING = 0x70, /* len = 0 */ MCI_GPM = 0x80, /* len = 16 */ MCI_LNA_INFO = 0x90, /* len = 1 */ MCI_LNA_STATE = 0x94, MCI_LNA_TAKE = 0x98, MCI_LNA_TRANS = 0x9c, MCI_SYS_SLEEPING = 0xa0, /* len = 0 */ MCI_REQ_WAKE = 0xc0, /* len = 0 */ MCI_DEBUG_16 = 0xfe, /* len = 2 */ MCI_REMOTE_RESET = 0xff /* len = 16 */ } MCI_MESSAGE_HEADER; /* Default remote BT device MCI COEX version */ #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 #define MCI_GPM_COEX_MINOR_VERSION_DEFAULT 0 /* Local WLAN MCI COEX version */ #define MCI_GPM_COEX_MAJOR_VERSION_WLAN 3 #define MCI_GPM_COEX_MINOR_VERSION_WLAN 0 typedef enum mci_gpm_subtype { MCI_GPM_BT_CAL_REQ = 0, MCI_GPM_BT_CAL_GRANT = 1, MCI_GPM_BT_CAL_DONE = 2, MCI_GPM_WLAN_CAL_REQ = 3, MCI_GPM_WLAN_CAL_GRANT = 4, MCI_GPM_WLAN_CAL_DONE = 5, MCI_GPM_COEX_AGENT = 0x0C, MCI_GPM_RSVD_PATTERN = 0xFE, MCI_GPM_RSVD_PATTERN32 = 0xFEFEFEFE, MCI_GPM_BT_DEBUG = 0xFF } MCI_GPM_SUBTYPE_T; typedef enum mci_gpm_coex_opcode { MCI_GPM_COEX_VERSION_QUERY = 0, MCI_GPM_COEX_VERSION_RESPONSE = 1, MCI_GPM_COEX_STATUS_QUERY = 2, MCI_GPM_COEX_HALT_BT_GPM = 3, MCI_GPM_COEX_WLAN_CHANNELS = 4, MCI_GPM_COEX_BT_PROFILE_INFO = 5, MCI_GPM_COEX_BT_STATUS_UPDATE = 6, MCI_GPM_COEX_BT_UPDATE_FLAGS = 7 } MCI_GPM_COEX_OPCODE_T; typedef enum mci_gpm_coex_query_type { /* WLAN information */ MCI_GPM_COEX_QUERY_WLAN_ALL_INFO = 0x01, /* BT information */ MCI_GPM_COEX_QUERY_BT_ALL_INFO = 0x01, MCI_GPM_COEX_QUERY_BT_TOPOLOGY = 0x02, MCI_GPM_COEX_QUERY_BT_DEBUG = 0x04 } MCI_GPM_COEX_QUERY_TYPE_T; typedef enum mci_gpm_coex_halt_bt_gpm { MCI_GPM_COEX_BT_GPM_UNHALT = 0, MCI_GPM_COEX_BT_GPM_HALT = 1 } MCI_GPM_COEX_HALT_BT_GPM_T; typedef enum mci_gpm_coex_profile_type { MCI_GPM_COEX_PROFILE_UNKNOWN = 0, MCI_GPM_COEX_PROFILE_RFCOMM = 1, MCI_GPM_COEX_PROFILE_A2DP = 2, MCI_GPM_COEX_PROFILE_HID = 3, MCI_GPM_COEX_PROFILE_BNEP = 4, MCI_GPM_COEX_PROFILE_VOICE = 5, MCI_GPM_COEX_PROFILE_MAX } MCI_GPM_COEX_PROFILE_TYPE_T; typedef enum mci_gpm_coex_profile_state { MCI_GPM_COEX_PROFILE_STATE_END = 0, MCI_GPM_COEX_PROFILE_STATE_START = 1 } MCI_GPM_COEX_PROFILE_STATE_T; typedef enum mci_gpm_coex_profile_role { MCI_GPM_COEX_PROFILE_SLAVE = 0, MCI_GPM_COEX_PROFILE_MASTER = 1 } MCI_GPM_COEX_PROFILE_ROLE_T; typedef enum mci_gpm_coex_bt_status_type { MCI_GPM_COEX_BT_NONLINK_STATUS = 0, MCI_GPM_COEX_BT_LINK_STATUS = 1 } MCI_GPM_COEX_BT_STATUS_TYPE_T; typedef enum mci_gpm_coex_bt_status_state { MCI_GPM_COEX_BT_NORMAL_STATUS = 0, MCI_GPM_COEX_BT_CRITICAL_STATUS = 1 } MCI_GPM_COEX_BT_STATUS_STATE_T; #define MCI_GPM_INVALID_PROFILE_HANDLE 0xff typedef enum mci_gpm_coex_bt_updata_flags_op { MCI_GPM_COEX_BT_FLAGS_READ = 0x00, MCI_GPM_COEX_BT_FLAGS_SET = 0x01, MCI_GPM_COEX_BT_FLAGS_CLEAR = 0x02 } MCI_GPM_COEX_BT_FLAGS_OP_T; /* MCI GPM/Coex opcode/type definitions */ enum { MCI_GPM_COEX_W_GPM_PAYLOAD = 1, MCI_GPM_COEX_B_GPM_TYPE = 4, MCI_GPM_COEX_B_GPM_OPCODE = 5, /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */ MCI_GPM_WLAN_CAL_W_SEQUENCE = 2, /* MCI_GPM_COEX_VERSION_QUERY */ /* MCI_GPM_COEX_VERSION_RESPONSE */ MCI_GPM_COEX_B_MAJOR_VERSION = 6, MCI_GPM_COEX_B_MINOR_VERSION = 7, /* MCI_GPM_COEX_STATUS_QUERY */ MCI_GPM_COEX_B_BT_BITMAP = 6, MCI_GPM_COEX_B_WLAN_BITMAP = 7, /* MCI_GPM_COEX_HALT_BT_GPM */ MCI_GPM_COEX_B_HALT_STATE = 6, /* MCI_GPM_COEX_WLAN_CHANNELS */ MCI_GPM_COEX_B_CHANNEL_MAP = 6, /* MCI_GPM_COEX_BT_PROFILE_INFO */ MCI_GPM_COEX_B_PROFILE_TYPE = 6, MCI_GPM_COEX_B_PROFILE_LINKID = 7, MCI_GPM_COEX_B_PROFILE_STATE = 8, MCI_GPM_COEX_B_PROFILE_ROLE = 9, MCI_GPM_COEX_B_PROFILE_RATE = 10, MCI_GPM_COEX_B_PROFILE_VOTYPE = 11, MCI_GPM_COEX_H_PROFILE_T = 12, MCI_GPM_COEX_B_PROFILE_W = 14, MCI_GPM_COEX_B_PROFILE_A = 15, /* MCI_GPM_COEX_BT_STATUS_UPDATE */ MCI_GPM_COEX_B_STATUS_TYPE = 6, MCI_GPM_COEX_B_STATUS_LINKID = 7, MCI_GPM_COEX_B_STATUS_STATE = 8, /* MCI_GPM_COEX_BT_UPDATE_FLAGS */ MCI_GPM_COEX_B_BT_FLAGS_OP = 10, MCI_GPM_COEX_W_BT_FLAGS = 6 }; #define MCI_GPM_RECYCLE(_p_gpm) \ { \ *(((u_int32_t *)(_p_gpm)) + MCI_GPM_COEX_W_GPM_PAYLOAD) = MCI_GPM_RSVD_PATTERN32; \ } #define MCI_GPM_TYPE(_p_gpm) \ (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff) #define MCI_GPM_OPCODE(_p_gpm) \ (*(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff) #define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type) \ { \ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff; \ } #define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) \ { \ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff; \ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff; \ } #define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE) #define MCI_NUM_BT_CHANNELS 79 #define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \ { \ if (_bt_chan < MCI_NUM_BT_CHANNELS) { \ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ (_bt_chan / 8)) |= 1 << (_bt_chan & 7); \ } \ } #define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \ { \ if (_bt_chan < MCI_NUM_BT_CHANNELS) { \ *(((u_int8_t *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7)); \ } \ } #define HAL_MCI_INTERRUPT_SW_MSG_DONE 0x00000001 #define HAL_MCI_INTERRUPT_CPU_INT_MSG 0x00000002 #define HAL_MCI_INTERRUPT_RX_CHKSUM_FAIL 0x00000004 #define HAL_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008 #define HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010 #define HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020 #define HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080 #define HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100 #define HAL_MCI_INTERRUPT_RX_MSG 0x00000200 #define HAL_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400 #define HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000 #define HAL_MCI_INTERRUPT_MSG_FAIL_MASK ( HAL_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ HAL_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ HAL_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ HAL_MCI_INTERRUPT_TX_SW_MSG_FAIL ) #define HAL_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 #define HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 #define HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 #define HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 #define HAL_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 #define HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 #define HAL_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 #define HAL_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 #define HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 #define HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 #define HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 #define HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 #define HAL_MCI_INTERRUPT_RX_MSG_MONITOR (HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ HAL_MCI_INTERRUPT_RX_MSG_CONT_RST) typedef enum mci_bt_state { MCI_BT_SLEEP, MCI_BT_AWAKE, MCI_BT_CAL_START, MCI_BT_CAL } MCI_BT_STATE_T; /* Type of state query */ typedef enum mci_state_type { HAL_MCI_STATE_ENABLE, HAL_MCI_STATE_INIT_GPM_OFFSET, HAL_MCI_STATE_NEXT_GPM_OFFSET, HAL_MCI_STATE_LAST_GPM_OFFSET, HAL_MCI_STATE_BT, HAL_MCI_STATE_SET_BT_SLEEP, HAL_MCI_STATE_SET_BT_AWAKE, HAL_MCI_STATE_SET_BT_CAL_START, HAL_MCI_STATE_SET_BT_CAL, HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET, HAL_MCI_STATE_REMOTE_SLEEP, HAL_MCI_STATE_CONT_RSSI_POWER, HAL_MCI_STATE_CONT_PRIORITY, HAL_MCI_STATE_CONT_TXRX, HAL_MCI_STATE_RESET_REQ_WAKE, HAL_MCI_STATE_SEND_WLAN_COEX_VERSION, HAL_MCI_STATE_SET_BT_COEX_VERSION, HAL_MCI_STATE_SEND_WLAN_CHANNELS, HAL_MCI_STATE_SEND_VERSION_QUERY, HAL_MCI_STATE_SEND_STATUS_QUERY, HAL_MCI_STATE_NEED_FLUSH_BT_INFO, HAL_MCI_STATE_SET_CONCUR_TX_PRI, HAL_MCI_STATE_RECOVER_RX, HAL_MCI_STATE_NEED_FTP_STOMP, HAL_MCI_STATE_NEED_TUNING, HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX, HAL_MCI_STATE_DEBUG, HAL_MCI_STATE_MAX } HAL_MCI_STATE_TYPE; #define HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG 1 #define HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR 0x00000002 #define HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR 0x00000004 #define HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD 0x00000008 #define HAL_MCI_BT_MCI_FLAGS_LNA_CTRL 0x00000010 #define HAL_MCI_BT_MCI_FLAGS_DEBUG 0x00000020 #define HAL_MCI_BT_MCI_FLAGS_SCHED_MSG 0x00000040 #define HAL_MCI_BT_MCI_FLAGS_CONT_MSG 0x00000080 #define HAL_MCI_BT_MCI_FLAGS_COEX_GPM 0x00000100 #define HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG 0x00000200 #define HAL_MCI_BT_MCI_FLAGS_MCI_MODE 0x00000400 #define HAL_MCI_BT_MCI_FLAGS_EGRET_MODE 0x00000800 #define HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE 0x00001000 #define HAL_MCI_BT_MCI_FLAGS_OTHER 0x00010000 #define HAL_MCI_DEFAULT_BT_MCI_FLAGS 0x00011dde /* HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR = 1 HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR = 1 HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD = 1 HAL_MCI_BT_MCI_FLAGS_LNA_CTRL = 1 HAL_MCI_BT_MCI_FLAGS_DEBUG = 0 HAL_MCI_BT_MCI_FLAGS_SCHED_MSG = 1 HAL_MCI_BT_MCI_FLAGS_CONT_MSG = 1 HAL_MCI_BT_MCI_FLAGS_COEX_GPM = 1 HAL_MCI_BT_MCI_FLAGS_CPU_INT_MSG = 0 HAL_MCI_BT_MCI_FLAGS_MCI_MODE = 1 HAL_MCI_BT_MCI_FLAGS_EGRET_MODE = 1 HAL_MCI_BT_MCI_FLAGS_JUPITER_MODE = 1 HAL_MCI_BT_MCI_FLAGS_OTHER = 1 */ #define HAL_MCI_TOGGLE_BT_MCI_FLAGS \ ( HAL_MCI_BT_MCI_FLAGS_UPDATE_CORR | \ HAL_MCI_BT_MCI_FLAGS_UPDATE_HDR | \ HAL_MCI_BT_MCI_FLAGS_UPDATE_PLD | \ HAL_MCI_BT_MCI_FLAGS_MCI_MODE ) #define HAL_MCI_2G_FLAGS_CLEAR_MASK 0x00000000 #define HAL_MCI_2G_FLAGS_SET_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS #define HAL_MCI_2G_FLAGS HAL_MCI_DEFAULT_BT_MCI_FLAGS #define HAL_MCI_5G_FLAGS_CLEAR_MASK HAL_MCI_TOGGLE_BT_MCI_FLAGS #define HAL_MCI_5G_FLAGS_SET_MASK 0x00000000 #define HAL_MCI_5G_FLAGS (HAL_MCI_DEFAULT_BT_MCI_FLAGS & \ ~HAL_MCI_TOGGLE_BT_MCI_FLAGS) #define HAL_MCI_GPM_NOMORE 0 #define HAL_MCI_GPM_MORE 1 #define HAL_MCI_GPM_INVALID 0xffffffff #define ATH_AIC_MAX_BT_CHANNEL 79 /* * Default value for Jupiter is 0x00002201 * Default value for Aphrodite is 0x00002282 */ #define ATH_MCI_CONFIG_CONCUR_TX 0x00000003 #define ATH_MCI_CONFIG_MCI_OBS_MCI 0x00000004 #define ATH_MCI_CONFIG_MCI_OBS_TXRX 0x00000008 #define ATH_MCI_CONFIG_MCI_OBS_BT 0x00000010 #define ATH_MCI_CONFIG_DISABLE_MCI_CAL 0x00000020 #define ATH_MCI_CONFIG_DISABLE_OSLA 0x00000040 #define ATH_MCI_CONFIG_DISABLE_FTP_STOMP 0x00000080 #define ATH_MCI_CONFIG_AGGR_THRESH 0x00000700 #define ATH_MCI_CONFIG_AGGR_THRESH_S 8 #define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH 0x00000800 #define ATH_MCI_CONFIG_CLK_DIV 0x00003000 #define ATH_MCI_CONFIG_CLK_DIV_S 12 #define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000 #define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000 #define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000 #define ATH_MCI_CONFIG_MCI_OBS_MASK ( ATH_MCI_CONFIG_MCI_OBS_MCI | \ ATH_MCI_CONFIG_MCI_OBS_TXRX | \ ATH_MCI_CONFIG_MCI_OBS_BT ) #define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F #define ATH_MCI_CONCUR_TX_SHARED_CHN 0x01 #define ATH_MCI_CONCUR_TX_UNSHARED_CHN 0x02 #define ATH_MCI_CONCUR_TX_DEBUG 0x03 /* * The values below come from the system team test result. * For Jupiter, BT tx power level is from 0(-20dBm) to 6(4dBm). * Lowest WLAN tx power would be in bit[23:16] of dword 1. */ static const u_int32_t mci_concur_tx_max_pwr[4][8] = { /* No limit */ {0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f}, /* 11G */ {0x16161616, 0x12121516, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x7f121212}, /* HT20 */ {0x15151515, 0x14141515, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x7f141414}, /* HT40 */ {0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x7f101010}}; #define ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK 0x00ff0000 #define ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK_S 16 #endif /* __AR9300_FREEBSD_INC_H__ */ Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c (revision 278741) @@ -1,438 +1,591 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" /* * Note: The key cache hardware requires that each double-word * pair be written in even/odd order (since the destination is * a 64-bit register). Don't reorder the writes in this code * w/o considering this! */ #define KEY_XOR 0xaa #define IS_MIC_ENABLED(ah) \ (AH9300(ah)->ah_sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) /* * This isn't the keytable type; this is actually something separate * for the TX descriptor. */ static const int keyType[] = { 1, /* HAL_CIPHER_WEP */ 0, /* HAL_CIPHER_AES_OCB */ 2, /* HAL_CIPHER_AES_CCM */ 0, /* HAL_CIPHER_CKIP */ 3, /* HAL_CIPHER_TKIP */ 0 /* HAL_CIPHER_CLR */ }; /* * Return the size of the hardware key cache. */ u_int32_t ar9300_get_key_cache_size(struct ath_hal *ah) { return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize; } /* * Return AH_TRUE if the specific key cache entry is valid. */ HAL_BOOL ar9300_is_key_cache_entry_valid(struct ath_hal *ah, u_int16_t entry) { if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { u_int32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); if (val & AR_KEYTABLE_VALID) { return AH_TRUE; } } return AH_FALSE; } /* * Clear the specified key cache entry and any associated MIC entry. */ HAL_BOOL ar9300_reset_key_cache_entry(struct ath_hal *ah, u_int16_t entry) { u_int32_t key_type; struct ath_hal_9300 *ahp = AH9300(ah); if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry %u out of range\n", __func__, entry); return AH_FALSE; } ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR]; key_type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)); /* XXX why not clear key type/valid bit first? */ OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { u_int16_t micentry = entry + 64; /* MIC goes at slot+64 */ HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize); OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); /* NB: key type and MAC are known to be ok */ } if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) { return AH_TRUE; } if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL) == HAL_OK) { if (key_type == AR_KEYTABLE_TYPE_TKIP || key_type == AR_KEYTABLE_TYPE_40 || key_type == AR_KEYTABLE_TYPE_104 || key_type == AR_KEYTABLE_TYPE_128) { /* SW WAR for Bug 31602 */ if (--ahp->ah_rifs_sec_cnt == 0) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: Count = %d, enabling RIFS\n", __func__, ahp->ah_rifs_sec_cnt); ar9300_set_rifs_delay(ah, AH_TRUE); } } } return AH_TRUE; } /* * Sets the mac part of the specified key cache entry (and any * associated MIC entry) and mark them valid. */ HAL_BOOL ar9300_set_key_cache_entry_mac( struct ath_hal *ah, u_int16_t entry, const u_int8_t *mac) { u_int32_t mac_hi, mac_lo; u_int32_t unicast_addr = AR_KEYTABLE_VALID; if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry %u out of range\n", __func__, entry); return AH_FALSE; } /* * Set MAC address -- shifted right by 1. mac_lo is * the 4 MSBs, and mac_hi is the 2 LSBs. */ if (mac != AH_NULL) { /* * If upper layers have requested mcast MACaddr lookup, then * signify this to the hw by setting the (poorly named) valid_bit * to 0. Yes, really 0. The hardware specs, pcu_registers.txt, is * has incorrectly named valid_bit. It should be called "Unicast". * When the Key Cache entry is to decrypt Unicast frames, this bit * should be '1'; for multicast and broadcast frames, this bit is '0'. */ if (mac[0] & 0x01) { unicast_addr = 0; /* Not an unicast address */ } mac_hi = (mac[5] << 8) | mac[4]; mac_lo = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]; mac_lo >>= 1; /* Note that the bit 0 is shifted out. This bit is used to * indicate that this is a multicast key cache. */ mac_lo |= (mac_hi & 1) << 31; /* carry */ mac_hi >>= 1; } else { mac_lo = mac_hi = 0; } OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), mac_lo); OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), mac_hi | unicast_addr); return AH_TRUE; } /* * Sets the contents of the specified key cache entry * and any associated MIC entry. */ HAL_BOOL ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry, const HAL_KEYVAL *k, const u_int8_t *mac, int xor_key) { const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; u_int32_t key0, key1, key2, key3, key4; u_int32_t key_type; u_int32_t xor_mask = xor_key ? (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t pwrmgt, pwrmgt_mic, uapsd_cfg, psta = 0; int is_proxysta_key = k->kv_type & HAL_KEY_PROXY_STA_MASK; if (entry >= p_cap->halKeyCacheSize) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry %u out of range\n", __func__, entry); return AH_FALSE; } HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n", __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null", is_proxysta_key); switch (k->kv_type & AH_KEYTYPE_MASK) { case HAL_CIPHER_AES_OCB: key_type = AR_KEYTABLE_TYPE_AES; break; case HAL_CIPHER_AES_CCM: if (!p_cap->halCipherAesCcmSupport) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by " "mac rev 0x%x\n", __func__, AH_PRIVATE(ah)->ah_macRev); return AH_FALSE; } key_type = AR_KEYTABLE_TYPE_CCM; break; case HAL_CIPHER_TKIP: key_type = AR_KEYTABLE_TYPE_TKIP; if (IS_MIC_ENABLED(ah) && entry + 64 >= p_cap->halKeyCacheSize) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry %u inappropriate for TKIP\n", __func__, entry); return AH_FALSE; } break; case HAL_CIPHER_WEP: if (k->kv_len < 40 / NBBY) { HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n", __func__, k->kv_len); return AH_FALSE; } if (k->kv_len <= 40 / NBBY) { key_type = AR_KEYTABLE_TYPE_40; } else if (k->kv_len <= 104 / NBBY) { key_type = AR_KEYTABLE_TYPE_104; } else { key_type = AR_KEYTABLE_TYPE_128; } break; case HAL_CIPHER_CLR: key_type = AR_KEYTABLE_TYPE_CLR; break; default: HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n", __func__, k->kv_type); return AH_FALSE; } key0 = LE_READ_4(k->kv_val + 0) ^ xor_mask; key1 = (LE_READ_2(k->kv_val + 4) ^ xor_mask) & 0xffff; key2 = LE_READ_4(k->kv_val + 6) ^ xor_mask; key3 = (LE_READ_2(k->kv_val + 10) ^ xor_mask) & 0xffff; key4 = LE_READ_4(k->kv_val + 12) ^ xor_mask; if (k->kv_len <= 104 / NBBY) { key4 &= 0xff; } /* Extract the UAPSD AC bits and shift it appropriately */ uapsd_cfg = k->kv_apsd; uapsd_cfg = (u_int32_t) SM(uapsd_cfg, AR_KEYTABLE_UAPSD); /* Need to preserve the power management bit used by MAC */ pwrmgt = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEYTABLE_PWRMGT; if (is_proxysta_key) { u_int8_t bcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (!mac || OS_MEMCMP(mac, bcast_mac, 6)) { psta = AR_KEYTABLE_DIR_ACK_BIT; } } /* * Note: key cache hardware requires that each double-word * pair be written in even/odd order (since the destination is * a 64-bit register). Don't reorder these writes w/o * considering this! */ if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { u_int16_t micentry = entry + 64; /* MIC goes at slot+64 */ /* Need to preserve the power management bit used by MAC */ pwrmgt_mic = OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEYTABLE_PWRMGT; /* * Invalidate the encrypt/decrypt key until the MIC * key is installed so pending rx frames will fail * with decrypt errors rather than a MIC error. */ OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), key_type | pwrmgt | uapsd_cfg | psta); ar9300_set_key_cache_entry_mac(ah, entry, mac); /* * since the AR_MISC_MODE register was written with the contents of * ah_misc_mode (if any) in ar9300_attach, just check ah_misc_mode and * save a pci read per key set. */ if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { u_int32_t mic0, mic1, mic2, mic3, mic4; /* * both RX and TX mic values can be combined into * one cache slot entry. * 8*N + 800 31:0 RX Michael key 0 * 8*N + 804 15:0 TX Michael key 0 [31:16] * 8*N + 808 31:0 RX Michael key 1 * 8*N + 80C 15:0 TX Michael key 0 [15:0] * 8*N + 810 31:0 TX Michael key 1 * 8*N + 814 15:0 reserved * 8*N + 818 31:0 reserved * 8*N + 81C 14:0 reserved * 15 key valid == 0 */ /* RX mic */ mic0 = LE_READ_4(k->kv_mic + 0); mic2 = LE_READ_4(k->kv_mic + 4); /* TX mic */ mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff; mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff; mic4 = LE_READ_4(k->kv_txmic + 4); OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR | pwrmgt_mic | uapsd_cfg); } else { u_int32_t mic0, mic2; mic0 = LE_READ_4(k->kv_mic + 0); mic2 = LE_READ_4(k->kv_mic + 4); OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry | pwrmgt_mic | uapsd_cfg), AR_KEYTABLE_TYPE_CLR); } /* NB: MIC key is not marked valid and has no MAC address */ OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); /* correct intentionally corrupted key */ OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); } else { OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), key_type | pwrmgt | uapsd_cfg | psta); /* ath_hal_printf(ah, "%s[%d] mac %s proxy %d\n", __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null", is_proxysta_key); */ ar9300_set_key_cache_entry_mac(ah, entry, mac); } ahp->ah_keytype[entry] = keyType[k->kv_type]; HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry=%d, k->kv_type=%d," "keyType=%d\n", __func__, entry, k->kv_type, keyType[k->kv_type]); if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) { return AH_TRUE; } if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL) == HAL_OK) { if (key_type == AR_KEYTABLE_TYPE_TKIP || key_type == AR_KEYTABLE_TYPE_40 || key_type == AR_KEYTABLE_TYPE_104 || key_type == AR_KEYTABLE_TYPE_128) { /* SW WAR for Bug 31602 */ ahp->ah_rifs_sec_cnt++; HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: Count = %d, disabling RIFS\n", __func__, ahp->ah_rifs_sec_cnt); ar9300_set_rifs_delay(ah, AH_FALSE); } } HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n", __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null", is_proxysta_key); return AH_TRUE; } /* * Enable the Keysearch for every subframe of an aggregate */ void ar9300_enable_keysearch_always(struct ath_hal *ah, int enable) { u_int32_t val; if (!ah) { return; } val = OS_REG_READ(ah, AR_PCU_MISC); if (enable) { val |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; } else { val &= ~AR_PCU_ALWAYS_PERFORM_KEYSEARCH; } OS_REG_WRITE(ah, AR_PCU_MISC, val); } void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry) { #define AH_KEY_REG_SIZE 8 int i; for (i = 0; i < AH_KEY_REG_SIZE; i++) { entry[i] = OS_REG_READ(ah, AR_KEYTABLE_KEY0(n) + i * 4); } #undef AH_KEY_REG_SIZE } + +#if ATH_SUPPORT_KEYPLUMB_WAR +/* + * Check the contents of the specified key cache entry + * and any associated MIC entry. + */ + HAL_BOOL +ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry, + const HAL_KEYVAL *k, int xorKey) +{ + const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + u_int32_t key0, key1, key2, key3, key4; + u_int32_t keyType; + u_int32_t xorMask = xorKey ? + (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; + struct ath_hal_9300 *ahp = AH9300(ah); + + + if (entry >= pCap->hal_key_cache_size) { + HALDEBUG(ah, HAL_DEBUG_KEYCACHE, + "%s: entry %u out of range\n", __func__, entry); + return AH_FALSE; + } + switch (k->kv_type) { + case HAL_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case HAL_CIPHER_AES_CCM: + if (!pCap->hal_cipher_aes_ccm_support) { + HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by " + "mac rev 0x%x\n", + __func__, AH_PRIVATE(ah)->ah_macRev); + return AH_FALSE; + } + keyType = AR_KEYTABLE_TYPE_CCM; + break; + case HAL_CIPHER_TKIP: + keyType = AR_KEYTABLE_TYPE_TKIP; + if (IS_MIC_ENABLED(ah) && entry + 64 >= pCap->hal_key_cache_size) { + HALDEBUG(ah, HAL_DEBUG_KEYCACHE, + "%s: entry %u inappropriate for TKIP\n", + __func__, entry); + return AH_FALSE; + } + break; + case HAL_CIPHER_WEP: + if (k->kv_len < 40 / NBBY) { + HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n", + __func__, k->kv_len); + return AH_FALSE; + } + if (k->kv_len <= 40 / NBBY) { + keyType = AR_KEYTABLE_TYPE_40; + } else if (k->kv_len <= 104 / NBBY) { + keyType = AR_KEYTABLE_TYPE_104; + } else { + keyType = AR_KEYTABLE_TYPE_128; + } + break; + case HAL_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + return AH_TRUE; + default: + HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n", + __func__, k->kv_type); + return AH_TRUE; + } + + key0 = LE_READ_4(k->kv_val + 0) ^ xorMask; + key1 = (LE_READ_2(k->kv_val + 4) ^ xorMask) & 0xffff; + key2 = LE_READ_4(k->kv_val + 6) ^ xorMask; + key3 = (LE_READ_2(k->kv_val + 10) ^ xorMask) & 0xffff; + key4 = LE_READ_4(k->kv_val + 12) ^ xorMask; + if (k->kv_len <= 104 / NBBY) { + key4 &= 0xff; + } + + /* + * Note: key cache hardware requires that each double-word + * pair be written in even/odd order (since the destination is + * a 64-bit register). Don't reorder these writes w/o + * considering this! + */ + if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) { + u_int16_t micentry = entry + 64; /* MIC goes at slot+64 */ + + + /* + * Invalidate the encrypt/decrypt key until the MIC + * key is installed so pending rx frames will fail + * with decrypt errors rather than a MIC error. + */ + if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) && + ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) + { + + /* + * since the AR_MISC_MODE register was written with the contents of + * ah_miscMode (if any) in ar9300Attach, just check ah_miscMode and + * save a pci read per key set. + */ + if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { + u_int32_t mic0,mic1,mic2,mic3,mic4; + /* + * both RX and TX mic values can be combined into + * one cache slot entry. + * 8*N + 800 31:0 RX Michael key 0 + * 8*N + 804 15:0 TX Michael key 0 [31:16] + * 8*N + 808 31:0 RX Michael key 1 + * 8*N + 80C 15:0 TX Michael key 0 [15:0] + * 8*N + 810 31:0 TX Michael key 1 + * 8*N + 814 15:0 reserved + * 8*N + 818 31:0 reserved + * 8*N + 81C 14:0 reserved + * 15 key valid == 0 + */ + /* RX mic */ + mic0 = LE_READ_4(k->kv_mic + 0); + mic2 = LE_READ_4(k->kv_mic + 4); + /* TX mic */ + mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff; + mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff; + mic4 = LE_READ_4(k->kv_txmic + 4); + if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(micentry)) == mic0) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY1(micentry)) == mic1) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY2(micentry)) == mic2) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY3(micentry)) == mic3) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY4(micentry)) == mic4) && + ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEY_TYPE) == (AR_KEYTABLE_TYPE_CLR & AR_KEY_TYPE))) { + return AH_TRUE; + } + + } else { + return AH_TRUE; + } + } + } else { + if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) && + (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) && + ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) { + return AH_TRUE; + } + } + return AH_FALSE; +} +#endif Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c (revision 278741) @@ -1,3765 +1,3807 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #ifdef AH_DEBUG #include "ah_desc.h" /* NB: for HAL_PHYERR* */ #endif #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300phy.h" void ar9300_get_hw_hangs(struct ath_hal *ah, hal_hw_hangs_t *hangs) { struct ath_hal_9300 *ahp = AH9300(ah); *hangs = 0; if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL) == HAL_OK) { *hangs |= HAL_RIFS_BB_HANG_WAR; } if (ar9300_get_capability(ah, HAL_CAP_BB_DFS_HANG, 0, AH_NULL) == HAL_OK) { *hangs |= HAL_DFS_BB_HANG_WAR; } if (ar9300_get_capability(ah, HAL_CAP_BB_RX_CLEAR_STUCK_HANG, 0, AH_NULL) == HAL_OK) { *hangs |= HAL_RX_STUCK_LOW_BB_HANG_WAR; } if (ar9300_get_capability(ah, HAL_CAP_MAC_HANG, 0, AH_NULL) == HAL_OK) { *hangs |= HAL_MAC_HANG_WAR; } if (ar9300_get_capability(ah, HAL_CAP_PHYRESTART_CLR_WAR, 0, AH_NULL) == HAL_OK) { *hangs |= HAL_PHYRESTART_CLR_WAR; } ahp->ah_hang_wars = *hangs; } /* * XXX FreeBSD: the HAL version of ath_hal_mac_usec() knows about * HT20, HT40, fast-clock, turbo mode, etc. */ static u_int ar9300_mac_to_usec(struct ath_hal *ah, u_int clks) { #if 0 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; if (chan && IEEE80211_IS_CHAN_HT40(chan)) { return (ath_hal_mac_usec(ah, clks) / 2); } else { return (ath_hal_mac_usec(ah, clks)); } #endif return (ath_hal_mac_usec(ah, clks)); } u_int ar9300_mac_to_clks(struct ath_hal *ah, u_int usecs) { #if 0 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; if (chan && IEEE80211_IS_CHAN_HT40(chan)) { return (ath_hal_mac_clks(ah, usecs) * 2); } else { return (ath_hal_mac_clks(ah, usecs)); } #endif return (ath_hal_mac_clks(ah, usecs)); } void ar9300_get_mac_address(struct ath_hal *ah, u_int8_t *mac) { struct ath_hal_9300 *ahp = AH9300(ah); OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); } HAL_BOOL ar9300_set_mac_address(struct ath_hal *ah, const u_int8_t *mac) { struct ath_hal_9300 *ahp = AH9300(ah); OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); return AH_TRUE; } void ar9300_get_bss_id_mask(struct ath_hal *ah, u_int8_t *mask) { struct ath_hal_9300 *ahp = AH9300(ah); OS_MEMCPY(mask, ahp->ah_bssid_mask, IEEE80211_ADDR_LEN); } HAL_BOOL ar9300_set_bss_id_mask(struct ath_hal *ah, const u_int8_t *mask) { struct ath_hal_9300 *ahp = AH9300(ah); /* save it since it must be rewritten on reset */ OS_MEMCPY(ahp->ah_bssid_mask, mask, IEEE80211_ADDR_LEN); OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssid_mask)); OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssid_mask + 4)); return AH_TRUE; } /* * Attempt to change the cards operating regulatory domain to the given value * Returns: A_EINVAL for an unsupported regulatory domain. * A_HARDWARE for an unwritable EEPROM or bad EEPROM version */ HAL_BOOL ar9300_set_regulatory_domain(struct ath_hal *ah, u_int16_t reg_domain, HAL_STATUS *status) { HAL_STATUS ecode; if (AH_PRIVATE(ah)->ah_currentRD == 0) { AH_PRIVATE(ah)->ah_currentRD = reg_domain; return AH_TRUE; } ecode = HAL_EIO; #if 0 bad: #endif if (status) { *status = ecode; } return AH_FALSE; } /* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. * */ u_int ar9300_get_wireless_modes(struct ath_hal *ah) { return AH_PRIVATE(ah)->ah_caps.halWirelessModes; } /* * Set the interrupt and GPIO values so the ISR can disable RF * on a switch signal. Assumes GPIO port and interrupt polarity * are set prior to call. */ void ar9300_enable_rf_kill(struct ath_hal *ah) { /* TODO - can this really be above the hal on the GPIO interface for * TODO - the client only? */ struct ath_hal_9300 *ahp = AH9300(ah); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* Check RF kill GPIO before set/clear RFSILENT bits. */ if (ar9300_gpio_get(ah, ahp->ah_gpio_select) == ahp->ah_polarity) { OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_RFSILENT), AR_RFSILENT_FORCE); OS_REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); } else { OS_REG_CLR_BIT(ah, AR_HOSTIF_REG(ah, AR_RFSILENT), AR_RFSILENT_FORCE); OS_REG_CLR_BIT(ah, AR_PHY_TEST, RFSILENT_BB); } } else { /* Connect rfsilent_bb_l to baseband */ OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); /* Set input mux for rfsilent_bb_l to GPIO #0 */ OS_REG_CLR_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2), AR_GPIO_INPUT_MUX2_RFSILENT); OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2), (ahp->ah_gpio_select & 0x0f) << 4); /* * Configure the desired GPIO port for input and * enable baseband rf silence */ ath_hal_gpioCfgInput(ah, ahp->ah_gpio_select); OS_REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); } /* * If radio disable switch connection to GPIO bit x is enabled * program GPIO interrupt. * If rfkill bit on eeprom is 1, setupeeprommap routine has already * verified that it is a later version of eeprom, it has a place for * rfkill bit and it is set to 1, indicating that GPIO bit x hardware * connection is present. */ /* * RFKill uses polling not interrupt, * disable interrupt to avoid Eee PC 2.6.21.4 hang up issue */ if (ath_hal_hasrfkill_int(ah)) { if (ahp->ah_gpio_bit == ar9300_gpio_get(ah, ahp->ah_gpio_select)) { /* switch already closed, set to interrupt upon open */ ar9300_gpio_set_intr(ah, ahp->ah_gpio_select, !ahp->ah_gpio_bit); } else { ar9300_gpio_set_intr(ah, ahp->ah_gpio_select, ahp->ah_gpio_bit); } } } /* * Change the LED blinking pattern to correspond to the connectivity */ void ar9300_set_led_state(struct ath_hal *ah, HAL_LED_STATE state) { static const u_int32_t ledbits[8] = { AR_CFG_LED_ASSOC_NONE, /* HAL_LED_RESET */ AR_CFG_LED_ASSOC_PENDING, /* HAL_LED_INIT */ AR_CFG_LED_ASSOC_PENDING, /* HAL_LED_READY */ AR_CFG_LED_ASSOC_PENDING, /* HAL_LED_SCAN */ AR_CFG_LED_ASSOC_PENDING, /* HAL_LED_AUTH */ AR_CFG_LED_ASSOC_ACTIVE, /* HAL_LED_ASSOC */ AR_CFG_LED_ASSOC_ACTIVE, /* HAL_LED_RUN */ AR_CFG_LED_ASSOC_NONE, }; OS_REG_RMW_FIELD(ah, AR_CFG_LED, AR_CFG_LED_ASSOC_CTL, ledbits[state]); } /* * Sets the Power LED on the cardbus without affecting the Network LED. */ void ar9300_set_power_led_state(struct ath_hal *ah, u_int8_t enabled) { u_int32_t val; val = enabled ? AR_CFG_LED_MODE_POWER_ON : AR_CFG_LED_MODE_POWER_OFF; OS_REG_RMW_FIELD(ah, AR_CFG_LED, AR_CFG_LED_POWER, val); } /* * Sets the Network LED on the cardbus without affecting the Power LED. */ void ar9300_set_network_led_state(struct ath_hal *ah, u_int8_t enabled) { u_int32_t val; val = enabled ? AR_CFG_LED_MODE_NETWORK_ON : AR_CFG_LED_MODE_NETWORK_OFF; OS_REG_RMW_FIELD(ah, AR_CFG_LED, AR_CFG_LED_NETWORK, val); } /* * Change association related fields programmed into the hardware. * Writing a valid BSSID to the hardware effectively enables the hardware * to synchronize its TSF to the correct beacons and receive frames coming * from that BSSID. It is called by the SME JOIN operation. */ void ar9300_write_associd(struct ath_hal *ah, const u_int8_t *bssid, u_int16_t assoc_id) { struct ath_hal_9300 *ahp = AH9300(ah); /* save bssid and assoc_id for restore on reset */ OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); ahp->ah_assoc_id = assoc_id; OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4) | ((assoc_id & 0x3fff) << AR_BSS_ID1_AID_S)); } /* * Get the current hardware tsf for stamlme */ u_int64_t ar9300_get_tsf64(struct ath_hal *ah) { u_int64_t tsf; /* XXX sync multi-word read? */ tsf = OS_REG_READ(ah, AR_TSF_U32); tsf = (tsf << 32) | OS_REG_READ(ah, AR_TSF_L32); return tsf; } void ar9300_set_tsf64(struct ath_hal *ah, u_int64_t tsf) { OS_REG_WRITE(ah, AR_TSF_L32, (tsf & 0xffffffff)); OS_REG_WRITE(ah, AR_TSF_U32, ((tsf >> 32) & 0xffffffff)); } /* * Get the current hardware tsf for stamlme */ u_int32_t ar9300_get_tsf32(struct ath_hal *ah) { return OS_REG_READ(ah, AR_TSF_L32); } u_int32_t ar9300_get_tsf2_32(struct ath_hal *ah) { return OS_REG_READ(ah, AR_TSF2_L32); } /* * Reset the current hardware tsf for stamlme. */ void ar9300_reset_tsf(struct ath_hal *ah) { int count; count = 0; while (OS_REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { count++; if (count > 10) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n", __func__); break; } OS_DELAY(10); } OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); } /* * Set or clear hardware basic rate bit * Set hardware basic rate set if basic rate is found * and basic rate is equal or less than 2Mbps */ void ar9300_set_basic_rate(struct ath_hal *ah, HAL_RATE_SET *rs) { const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; u_int32_t reg; u_int8_t xset; int i; if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan)) { return; } xset = 0; for (i = 0; i < rs->rs_count; i++) { u_int8_t rset = rs->rs_rates[i]; /* Basic rate defined? */ if ((rset & 0x80) && (rset &= 0x7f) >= xset) { xset = rset; } } /* * Set the h/w bit to reflect whether or not the basic * rate is found to be equal or less than 2Mbps. */ reg = OS_REG_READ(ah, AR_STA_ID1); if (xset && xset / 2 <= 2) { OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); } else { OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); } } /* * Grab a semi-random value from hardware registers - may not * change often */ u_int32_t ar9300_get_random_seed(struct ath_hal *ah) { u_int32_t nf; nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; if (nf & 0x100) { nf = 0 - ((nf ^ 0x1ff) + 1); } return (OS_REG_READ(ah, AR_TSF_U32) ^ OS_REG_READ(ah, AR_TSF_L32) ^ nf); } /* * Detect if our card is present */ HAL_BOOL ar9300_detect_card_present(struct ath_hal *ah) { u_int16_t mac_version, mac_rev; u_int32_t v; /* * Read the Silicon Revision register and compare that * to what we read at attach time. If the same, we say * a card/device is present. */ v = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_SREV)) & AR_SREV_ID; if (v == 0xFF) { /* new SREV format */ v = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_SREV)); /* * Include 6-bit Chip Type (masked to 0) to differentiate * from pre-Sowl versions */ mac_version = (v & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; mac_rev = MS(v, AR_SREV_REVISION2); } else { mac_version = MS(v, AR_SREV_VERSION); mac_rev = v & AR_SREV_REVISION; } return (AH_PRIVATE(ah)->ah_macVersion == mac_version && AH_PRIVATE(ah)->ah_macRev == mac_rev); } /* * Update MIB Counters */ void ar9300_update_mib_mac_stats(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_MIB_STATS* stats = &ahp->ah_stats.ast_mibstats; stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); } void ar9300_get_mib_mac_stats(struct ath_hal *ah, HAL_MIB_STATS* stats) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_MIB_STATS* istats = &ahp->ah_stats.ast_mibstats; stats->ackrcv_bad = istats->ackrcv_bad; stats->rts_bad = istats->rts_bad; stats->fcs_bad = istats->fcs_bad; stats->rts_good = istats->rts_good; stats->beacons = istats->beacons; } /* * Detect if the HW supports spreading a CCK signal on channel 14 */ HAL_BOOL ar9300_is_japan_channel_spread_supported(struct ath_hal *ah) { return AH_TRUE; } /* * Get the rssi of frame curently being received. */ u_int32_t ar9300_get_cur_rssi(struct ath_hal *ah) { /* XXX return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); */ /* get combined RSSI */ return (OS_REG_READ(ah, AR_PHY_RSSI_3) & 0xff); } #if ATH_GEN_RANDOMNESS /* * Get the rssi value from BB on ctl chain0. */ u_int32_t ar9300_get_rssi_chain0(struct ath_hal *ah) { /* get ctl chain0 RSSI */ return OS_REG_READ(ah, AR_PHY_RSSI_0) & 0xff; } #endif u_int ar9300_get_def_antenna(struct ath_hal *ah) { return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); } /* Setup coverage class */ void ar9300_set_coverage_class(struct ath_hal *ah, u_int8_t coverageclass, int now) { } void ar9300_set_def_antenna(struct ath_hal *ah, u_int antenna) { OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); } HAL_BOOL ar9300_set_antenna_switch(struct ath_hal *ah, HAL_ANT_SETTING settings, const struct ieee80211_channel *chan, u_int8_t *tx_chainmask, u_int8_t *rx_chainmask, u_int8_t *antenna_cfgd) { struct ath_hal_9300 *ahp = AH9300(ah); /* * Owl does not support diversity or changing antennas. * * Instead this API and function are defined differently for AR9300. * To support Tablet PC's, this interface allows the system * to dramatically reduce the TX power on a particular chain. * * Based on the value of (redefined) diversity_control, the * reset code will decrease power on chain 0 or chain 1/2. * * Based on the value of bit 0 of antenna_switch_swap, * the mapping between OID call and chain is defined as: * 0: map A -> 0, B -> 1; * 1: map A -> 1, B -> 0; * * NOTE: * The devices that use this OID should use a tx_chain_mask and * tx_chain_select_legacy setting of 5 or 3 if ANTENNA_FIXED_B is * used in order to ensure an active transmit antenna. This * API will allow the host to turn off the only transmitting * antenna to ensure the antenna closest to the user's body is * powered-down. */ /* * Set antenna control for use during reset sequence by * ar9300_decrease_chain_power() */ ahp->ah_diversity_control = settings; return AH_TRUE; } HAL_BOOL ar9300_is_sleep_after_beacon_broken(struct ath_hal *ah) { return AH_TRUE; } HAL_BOOL ar9300_set_slot_time(struct ath_hal *ah, u_int us) { struct ath_hal_9300 *ahp = AH9300(ah); if (us < HAL_SLOT_TIME_9 || us > ar9300_mac_to_usec(ah, 0xffff)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: bad slot time %u\n", __func__, us); ahp->ah_slot_time = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ar9300_mac_to_clks(ah, us)); ahp->ah_slot_time = us; return AH_TRUE; } } HAL_BOOL ar9300_set_ack_timeout(struct ath_hal *ah, u_int us) { struct ath_hal_9300 *ahp = AH9300(ah); if (us > ar9300_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: bad ack timeout %u\n", __func__, us); ahp->ah_ack_timeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, ar9300_mac_to_clks(ah, us)); ahp->ah_ack_timeout = us; return AH_TRUE; } } u_int ar9300_get_ack_timeout(struct ath_hal *ah) { u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); return ar9300_mac_to_usec(ah, clks); /* convert from system clocks */ } HAL_STATUS ar9300_set_quiet(struct ath_hal *ah, u_int32_t period, u_int32_t duration, u_int32_t next_start, HAL_QUIET_FLAG flag) { #define TU_TO_USEC(_tu) ((_tu) << 10) HAL_STATUS status = HAL_EIO; u_int32_t tsf = 0, j, next_start_us = 0; if (flag & HAL_QUIET_ENABLE) { for (j = 0; j < 2; j++) { next_start_us = TU_TO_USEC(next_start); tsf = OS_REG_READ(ah, AR_TSF_L32); if ((!next_start) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) { next_start_us += tsf; } if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) { next_start_us += ah->ah_config.ah_sw_beacon_response_time; } OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR)); OS_REG_WRITE(ah, AR_QUIET_PERIOD, TU_TO_USEC(period)); OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, next_start_us); OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == tsf >> 10) { status = HAL_OK; break; } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: TSF have moved " "while trying to set quiet time TSF: 0x%08x\n", __func__, tsf); /* TSF shouldn't count twice or reg access is taking forever */ HALASSERT(j < 1); } } else { OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); status = HAL_OK; } return status; #undef TU_TO_USEC } #ifdef ATH_SUPPORT_DFS void ar9300_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL enable) { u32 reg1, reg2; reg1 = OS_REG_READ(ah, AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE)); reg2 = OS_REG_READ(ah, AR_MAC_PCU_OFFSET(MAC_PCU_QUIET_TIME_1)); AH9300(ah)->ah_cac_quiet_enabled = enable; if (enable) { OS_REG_WRITE(ah, AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE), reg1 | AR_PCU_FORCE_QUIET_COLL); OS_REG_WRITE(ah, AR_MAC_PCU_OFFSET(MAC_PCU_QUIET_TIME_1), reg2 & ~AR_QUIET1_QUIET_ACK_CTS_ENABLE); } else { OS_REG_WRITE(ah, AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE), reg1 & ~AR_PCU_FORCE_QUIET_COLL); OS_REG_WRITE(ah, AR_MAC_PCU_OFFSET(MAC_PCU_QUIET_TIME_1), reg2 | AR_QUIET1_QUIET_ACK_CTS_ENABLE); } } #endif /* ATH_SUPPORT_DFS */ void ar9300_set_pcu_config(struct ath_hal *ah) { ar9300_set_operating_mode(ah, AH_PRIVATE(ah)->ah_opmode); } HAL_STATUS ar9300_get_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, u_int32_t capability, u_int32_t *result) { struct ath_hal_9300 *ahp = AH9300(ah); const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; switch (type) { case HAL_CAP_CIPHER: /* cipher handled in hardware */ switch (capability) { case HAL_CIPHER_AES_CCM: case HAL_CIPHER_AES_OCB: case HAL_CIPHER_TKIP: case HAL_CIPHER_WEP: case HAL_CIPHER_MIC: case HAL_CIPHER_CLR: return HAL_OK; default: return HAL_ENOTSUPP; } case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return (ahp->ah_sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; default: return HAL_ENOTSUPP; } case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ switch (capability) { case 0: /* hardware capability */ return p_cap->halTkipMicTxRxKeySupport ? HAL_ENXIO : HAL_OK; case 1: /* current setting */ return (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? HAL_ENXIO : HAL_OK; default: return HAL_ENOTSUPP; } case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ return HAL_OK; case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ return HAL_OK; case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: /* current setting */ return (OS_REG_READ(ah, AR_PHY_CCK_DETECT) & AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TPC: switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return ah->ah_config.ath_hal_desc_tpc ? HAL_OK : HAL_ENXIO; } return HAL_OK; case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ return HAL_OK; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: if (OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { /* * Owl and Merlin have problems in mcast key search. * Disable this cap. in Ad-hoc mode. see Bug 25776 and * 26802 */ return HAL_ENXIO; } else { return (ahp->ah_sta_id1_defaults & AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; } } return HAL_EINVAL; case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ switch (capability) { case 0: /* hardware capability */ return p_cap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; case 1: return (ahp->ah_misc_mode & AR_PCU_TX_ADD_TSF) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_RFSILENT: /* rfsilent support */ if (capability == 3) { /* rfkill interrupt */ /* * XXX: Interrupt-based notification of RF Kill state * changes not working yet. Report that this feature * is not supported so that polling is used instead. */ return (HAL_ENOTSUPP); } return ath_hal_getcapability(ah, type, capability, result); case HAL_CAP_4ADDR_AGGR: return HAL_OK; case HAL_CAP_BB_RIFS_HANG: return HAL_ENOTSUPP; case HAL_CAP_BB_DFS_HANG: return HAL_ENOTSUPP; case HAL_CAP_BB_RX_CLEAR_STUCK_HANG: /* Track chips that are known to have BB hangs related * to rx_clear stuck low. */ return HAL_ENOTSUPP; case HAL_CAP_MAC_HANG: /* Track chips that are known to have MAC hangs. */ return HAL_OK; case HAL_CAP_RIFS_RX_ENABLED: /* Is RIFS RX currently enabled */ return (ahp->ah_rifs_enabled == AH_TRUE) ? HAL_OK : HAL_ENOTSUPP; #if 0 case HAL_CAP_ANT_CFG_2GHZ: *result = p_cap->halNumAntCfg2Ghz; return HAL_OK; case HAL_CAP_ANT_CFG_5GHZ: *result = p_cap->halNumAntCfg5Ghz; return HAL_OK; case HAL_CAP_RX_STBC: *result = p_cap->hal_rx_stbc_support; return HAL_OK; case HAL_CAP_TX_STBC: *result = p_cap->hal_tx_stbc_support; return HAL_OK; #endif case HAL_CAP_LDPC: *result = p_cap->halLDPCSupport; return HAL_OK; case HAL_CAP_DYNAMIC_SMPS: return HAL_OK; case HAL_CAP_DS: return (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah) || (p_cap->halTxChainMask & 0x3) != 0x3 || (p_cap->halRxChainMask & 0x3) != 0x3) ? HAL_ENOTSUPP : HAL_OK; case HAL_CAP_TS: return (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah) || (p_cap->halTxChainMask & 0x7) != 0x7 || (p_cap->halRxChainMask & 0x7) != 0x7) ? HAL_ENOTSUPP : HAL_OK; case HAL_CAP_OL_PWRCTRL: return (ar9300_eeprom_get(ahp, EEP_OL_PWRCTRL)) ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_CRDC: #if ATH_SUPPORT_CRDC return (AR_SREV_WASP(ah) && ah->ah_config.ath_hal_crdc_enable) ? HAL_OK : HAL_ENOTSUPP; #else return HAL_ENOTSUPP; #endif #if 0 case HAL_CAP_MAX_WEP_TKIP_HT20_TX_RATEKBPS: *result = (u_int32_t)(-1); return HAL_OK; case HAL_CAP_MAX_WEP_TKIP_HT40_TX_RATEKBPS: *result = (u_int32_t)(-1); return HAL_OK; #endif case HAL_CAP_BB_PANIC_WATCHDOG: return HAL_OK; case HAL_CAP_PHYRESTART_CLR_WAR: if ((AH_PRIVATE((ah))->ah_macVersion == AR_SREV_VERSION_OSPREY) && (AH_PRIVATE((ah))->ah_macRev < AR_SREV_REVISION_AR9580_10)) { return HAL_OK; } else { return HAL_ENOTSUPP; } case HAL_CAP_ENTERPRISE_MODE: *result = ahp->ah_enterprise_mode >> 16; /* * WAR for EV 77658 - Add delimiters to first sub-frame when using * RTS/CTS with aggregation and non-enterprise Osprey. * * Bug fixed in AR9580/Peacock, Wasp1.1 and later */ if ((ahp->ah_enterprise_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE) && !AR_SREV_AR9580_10_OR_LATER(ah) && (!AR_SREV_WASP(ah) || AR_SREV_WASP_10(ah))) { *result |= AH_ENT_RTSCTS_DELIM_WAR; } return HAL_OK; case HAL_CAP_LDPCWAR: /* WAR for RIFS+LDPC issue is required for all chips currently * supported by ar9300 HAL. */ return HAL_OK; case HAL_CAP_ENABLE_APM: *result = p_cap->halApmEnable; return HAL_OK; case HAL_CAP_PCIE_LCR_EXTSYNC_EN: return (p_cap->hal_pcie_lcr_extsync_en == AH_TRUE) ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_PCIE_LCR_OFFSET: *result = p_cap->hal_pcie_lcr_offset; return HAL_OK; case HAL_CAP_SMARTANTENNA: /* FIXME A request is pending with h/w team to add feature bit in * caldata to detect if board has smart antenna or not, once added * we need to fix his piece of code to read and return value without * any compile flags */ #if UMAC_SUPPORT_SMARTANTENNA /* enable smart antenna for Peacock, Wasp and scorpion for future chips need to modify */ if (AR_SREV_AR9580_10(ah) || (AR_SREV_WASP(ah)) || AR_SREV_SCORPION(ah)) { return HAL_OK; } else { return HAL_ENOTSUPP; } #else return HAL_ENOTSUPP; #endif #ifdef ATH_TRAFFIC_FAST_RECOVER case HAL_CAP_TRAFFIC_FAST_RECOVER: if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP_11(ah)) { return HAL_OK; } else { return HAL_ENOTSUPP; } #endif default: return ath_hal_getcapability(ah, type, capability, result); } } HAL_BOOL ar9300_set_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, u_int32_t capability, u_int32_t setting, HAL_STATUS *status) { struct ath_hal_9300 *ahp = AH9300(ah); const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; u_int32_t v; switch (type) { case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ if (! p_cap->halTkipMicTxRxKeySupport) return AH_FALSE; if (setting) ahp->ah_misc_mode &= ~AR_PCU_MIC_NEW_LOC_ENA; else ahp->ah_misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; OS_REG_WRITE(ah, AR_PCU_MISC, ahp->ah_misc_mode); return AH_TRUE; case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ if (setting) { ahp->ah_sta_id1_defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; } else { ahp->ah_sta_id1_defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; } return AH_TRUE; case HAL_CAP_DIVERSITY: v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); if (setting) { v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; } else { v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; } OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); return AH_TRUE; case HAL_CAP_DIAG: /* hardware diagnostic support */ /* * NB: could split this up into virtual capabilities, * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly * seems worth the additional complexity. */ #ifdef AH_DEBUG AH_PRIVATE(ah)->ah_diagreg = setting; #else AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ #endif OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); return AH_TRUE; case HAL_CAP_TPC: ah->ah_config.ath_hal_desc_tpc = (setting != 0); return AH_TRUE; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ if (setting) { ahp->ah_sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; } else { ahp->ah_sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; } return AH_TRUE; case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ if (p_cap->halTsfAddSupport) { if (setting) { ahp->ah_misc_mode |= AR_PCU_TX_ADD_TSF; } else { ahp->ah_misc_mode &= ~AR_PCU_TX_ADD_TSF; } return AH_TRUE; } return AH_FALSE; case HAL_CAP_RXBUFSIZE: /* set MAC receive buffer size */ ahp->rx_buf_size = setting & AR_DATABUF_MASK; OS_REG_WRITE(ah, AR_DATABUF, ahp->rx_buf_size); return AH_TRUE; /* fall thru... */ default: return ath_hal_setcapability(ah, type, capability, setting, status); } } #ifdef AH_DEBUG static void ar9300_print_reg(struct ath_hal *ah, u_int32_t args) { u_int32_t i = 0; /* Read 0x80d0 to trigger pcie analyzer */ HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", 0x80d0, OS_REG_READ(ah, 0x80d0)); if (args & HAL_DIAG_PRINT_REG_COUNTER) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t tf, rf, rc, cc; tf = OS_REG_READ(ah, AR_TFCNT); rf = OS_REG_READ(ah, AR_RFCNT); rc = OS_REG_READ(ah, AR_RCCNT); cc = OS_REG_READ(ah, AR_CCCNT); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "AR_TFCNT Diff= 0x%x\n", tf - ahp->last_tf); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "AR_RFCNT Diff= 0x%x\n", rf - ahp->last_rf); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "AR_RCCNT Diff= 0x%x\n", rc - ahp->last_rc); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "AR_CCCNT Diff= 0x%x\n", cc - ahp->last_cc); ahp->last_tf = tf; ahp->last_rf = rf; ahp->last_rc = rc; ahp->last_cc = cc; HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG0 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_0)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG1 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_1)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG2 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_2)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG3 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_3)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG4 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_4)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG5 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_5)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG6 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_6)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "DMADBG7 = 0x%x\n", OS_REG_READ(ah, AR_DMADBG_7)); } if (args & HAL_DIAG_PRINT_REG_ALL) { for (i = 0x8; i <= 0xB8; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x800; i <= (0x800 + (10 << 2)); i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", 0x840, OS_REG_READ(ah, i)); HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", 0x880, OS_REG_READ(ah, i)); for (i = 0x8C0; i <= (0x8C0 + (10 << 2)); i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x1F00; i <= 0x1F04; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x4000; i <= 0x408C; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x5000; i <= 0x503C; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x7040; i <= 0x7058; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x8000; i <= 0x8098; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x80D4; i <= 0x8200; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x8240; i <= 0x97FC; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x9800; i <= 0x99f0; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0x9c10; i <= 0x9CFC; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } for (i = 0xA200; i <= 0xA26C; i += sizeof(u_int32_t)) { HALDEBUG(ah, HAL_DEBUG_PRINT_REG, "0x%04x 0x%08x\n", i, OS_REG_READ(ah, i)); } } } #endif HAL_BOOL ar9300_get_diag_state(struct ath_hal *ah, int request, const void *args, u_int32_t argsize, void **result, u_int32_t *resultsize) { struct ath_hal_9300 *ahp = AH9300(ah); (void) ahp; if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) { return AH_TRUE; } switch (request) { #ifdef AH_PRIVATE_DIAG case HAL_DIAG_EEPROM: *result = &ahp->ah_eeprom; *resultsize = sizeof(ar9300_eeprom_t); return AH_TRUE; #if 0 /* XXX - TODO */ case HAL_DIAG_EEPROM_EXP_11A: case HAL_DIAG_EEPROM_EXP_11B: case HAL_DIAG_EEPROM_EXP_11G: pe = &ahp->ah_mode_power_array2133[request - HAL_DIAG_EEPROM_EXP_11A]; *result = pe->p_channels; *resultsize = (*result == AH_NULL) ? 0 : roundup(sizeof(u_int16_t) * pe->num_channels, sizeof(u_int32_t)) + sizeof(EXPN_DATA_PER_CHANNEL_2133) * pe->num_channels; return AH_TRUE; #endif case HAL_DIAG_RFGAIN: *result = &ahp->ah_gain_values; *resultsize = sizeof(GAIN_VALUES); return AH_TRUE; case HAL_DIAG_RFGAIN_CURSTEP: *result = (void *) ahp->ah_gain_values.curr_step; *resultsize = (*result == AH_NULL) ? 0 : sizeof(GAIN_OPTIMIZATION_STEP); return AH_TRUE; #if 0 /* XXX - TODO */ case HAL_DIAG_PCDAC: *result = ahp->ah_pcdac_table; *resultsize = ahp->ah_pcdac_table_size; return AH_TRUE; #endif case HAL_DIAG_ANI_CURRENT: *result = ar9300_ani_get_current_state(ah); *resultsize = (*result == AH_NULL) ? 0 : sizeof(struct ar9300_ani_state); return AH_TRUE; case HAL_DIAG_ANI_STATS: *result = ar9300_ani_get_current_stats(ah); *resultsize = (*result == AH_NULL) ? 0 : sizeof(struct ar9300_stats); return AH_TRUE; case HAL_DIAG_ANI_CMD: if (argsize != 2*sizeof(u_int32_t)) { return AH_FALSE; } ar9300_ani_control( ah, ((const u_int32_t *)args)[0], ((const u_int32_t *)args)[1]); return AH_TRUE; #if 0 case HAL_DIAG_TXCONT: /*AR9300_CONTTXMODE(ah, (struct ath_desc *)args, argsize );*/ return AH_TRUE; #endif /* 0 */ #endif /* AH_PRIVATE_DIAG */ case HAL_DIAG_CHANNELS: #if 0 *result = &(ahp->ah_priv.ah_channels[0]); *resultsize = sizeof(ahp->ah_priv.ah_channels[0]) * ahp->ah_priv.priv.ah_nchan; #endif return AH_TRUE; #ifdef AH_DEBUG case HAL_DIAG_PRINT_REG: ar9300_print_reg(ah, *((const u_int32_t *)args)); return AH_TRUE; #endif default: break; } return AH_FALSE; } void ar9300_dma_reg_dump(struct ath_hal *ah) { #ifdef AH_DEBUG #define NUM_DMA_DEBUG_REGS 8 #define NUM_QUEUES 10 u_int32_t val[NUM_DMA_DEBUG_REGS]; int qcu_offset = 0, dcu_offset = 0; u_int32_t *qcu_base = &val[0], *dcu_base = &val[4], reg; int i, j, k; int16_t nfarray[HAL_NUM_NF_READINGS]; #ifdef ATH_NF_PER_CHAN HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan); #endif /* ATH_NF_PER_CHAN */ HAL_NFCAL_HIST_FULL *h = AH_HOME_CHAN_NFCAL_HIST(ah, ichan); /* selecting DMA OBS 8 */ OS_REG_WRITE(ah, AR_MACMISC, ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S))); ath_hal_printf(ah, "Raw DMA Debug values:\n"); for (i = 0; i < NUM_DMA_DEBUG_REGS; i++) { if (i % 4 == 0) { ath_hal_printf(ah, "\n"); } val[i] = OS_REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u_int32_t))); ath_hal_printf(ah, "%d: %08x ", i, val[i]); } ath_hal_printf(ah, "\n\n"); ath_hal_printf(ah, "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); for (i = 0; i < NUM_QUEUES; i++, qcu_offset += 4, dcu_offset += 5) { if (i == 8) { /* only 8 QCU entries in val[0] */ qcu_offset = 0; qcu_base++; } if (i == 6) { /* only 6 DCU entries in val[4] */ dcu_offset = 0; dcu_base++; } ath_hal_printf(ah, "%2d %2x %1x %2x %2x\n", i, (*qcu_base & (0x7 << qcu_offset)) >> qcu_offset, (*qcu_base & (0x8 << qcu_offset)) >> (qcu_offset + 3), val[2] & (0x7 << (i * 3)) >> (i * 3), (*dcu_base & (0x1f << dcu_offset)) >> dcu_offset); } ath_hal_printf(ah, "\n"); ath_hal_printf(ah, "qcu_stitch state: %2x qcu_fetch state: %2x\n", (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); ath_hal_printf(ah, "qcu_complete state: %2x dcu_complete state: %2x\n", (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); ath_hal_printf(ah, "dcu_arb state: %2x dcu_fp state: %2x\n", (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); ath_hal_printf(ah, "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); ath_hal_printf(ah, "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); ath_hal_printf(ah, "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); ath_hal_printf(ah, "pcu observe 0x%x \n", OS_REG_READ(ah, AR_OBS_BUS_1)); ath_hal_printf(ah, "AR_CR 0x%x \n", OS_REG_READ(ah, AR_CR)); ar9300_upload_noise_floor(ah, 1, nfarray); ath_hal_printf(ah, "2G:\n"); ath_hal_printf(ah, "Min CCA Out:\n"); ath_hal_printf(ah, "\t\tChain 0\t\tChain 1\t\tChain 2\n"); ath_hal_printf(ah, "Control:\t%8d\t%8d\t%8d\n", nfarray[0], nfarray[1], nfarray[2]); ath_hal_printf(ah, "Extension:\t%8d\t%8d\t%8d\n\n", nfarray[3], nfarray[4], nfarray[5]); ar9300_upload_noise_floor(ah, 0, nfarray); ath_hal_printf(ah, "5G:\n"); ath_hal_printf(ah, "Min CCA Out:\n"); ath_hal_printf(ah, "\t\tChain 0\t\tChain 1\t\tChain 2\n"); ath_hal_printf(ah, "Control:\t%8d\t%8d\t%8d\n", nfarray[0], nfarray[1], nfarray[2]); ath_hal_printf(ah, "Extension:\t%8d\t%8d\t%8d\n\n", nfarray[3], nfarray[4], nfarray[5]); for (i = 0; i < HAL_NUM_NF_READINGS; i++) { ath_hal_printf(ah, "%s Chain %d NF History:\n", ((i < 3) ? "Control " : "Extension "), i%3); for (j = 0, k = h->base.curr_index; j < HAL_NF_CAL_HIST_LEN_FULL; j++, k++) { ath_hal_printf(ah, "Element %d: %d\n", j, h->nf_cal_buffer[k % HAL_NF_CAL_HIST_LEN_FULL][i]); } ath_hal_printf(ah, "Last Programmed NF: %d\n\n", h->base.priv_nf[i]); } reg = OS_REG_READ(ah, AR_PHY_FIND_SIG_LOW); ath_hal_printf(ah, "FIRStep Low = 0x%x (%d)\n", MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW), MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW)); reg = OS_REG_READ(ah, AR_PHY_DESIRED_SZ); ath_hal_printf(ah, "Total Desired = 0x%x (%d)\n", MS(reg, AR_PHY_DESIRED_SZ_TOT_DES), MS(reg, AR_PHY_DESIRED_SZ_TOT_DES)); ath_hal_printf(ah, "ADC Desired = 0x%x (%d)\n", MS(reg, AR_PHY_DESIRED_SZ_ADC), MS(reg, AR_PHY_DESIRED_SZ_ADC)); reg = OS_REG_READ(ah, AR_PHY_FIND_SIG); ath_hal_printf(ah, "FIRStep = 0x%x (%d)\n", MS(reg, AR_PHY_FIND_SIG_FIRSTEP), MS(reg, AR_PHY_FIND_SIG_FIRSTEP)); reg = OS_REG_READ(ah, AR_PHY_AGC); ath_hal_printf(ah, "Coarse High = 0x%x (%d)\n", MS(reg, AR_PHY_AGC_COARSE_HIGH), MS(reg, AR_PHY_AGC_COARSE_HIGH)); ath_hal_printf(ah, "Coarse Low = 0x%x (%d)\n", MS(reg, AR_PHY_AGC_COARSE_LOW), MS(reg, AR_PHY_AGC_COARSE_LOW)); ath_hal_printf(ah, "Coarse Power Constant = 0x%x (%d)\n", MS(reg, AR_PHY_AGC_COARSE_PWR_CONST), MS(reg, AR_PHY_AGC_COARSE_PWR_CONST)); reg = OS_REG_READ(ah, AR_PHY_TIMING5); ath_hal_printf(ah, "Enable Cyclic Power Thresh = %d\n", MS(reg, AR_PHY_TIMING5_CYCPWR_THR1_ENABLE)); ath_hal_printf(ah, "Cyclic Power Thresh = 0x%x (%d)\n", MS(reg, AR_PHY_TIMING5_CYCPWR_THR1), MS(reg, AR_PHY_TIMING5_CYCPWR_THR1)); ath_hal_printf(ah, "Cyclic Power Thresh 1A= 0x%x (%d)\n", MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A), MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A)); reg = OS_REG_READ(ah, AR_PHY_DAG_CTRLCCK); ath_hal_printf(ah, "Barker RSSI Thresh Enable = %d\n", MS(reg, AR_PHY_DAG_CTRLCCK_EN_RSSI_THR)); ath_hal_printf(ah, "Barker RSSI Thresh = 0x%x (%d)\n", MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR), MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR)); /* Step 1a: Set bit 23 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x00800000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2a: Set register 0xa364 to 0x1000 */ reg = 0x1000; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3a: Read bits 17:0 of register 0x9c20 */ reg = OS_REG_READ(ah, 0x9c20); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x1000] 0x9c20[17:0] = 0x%x\n", __func__, reg); /* Step 1b: Set bit 23 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x00800000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2b: Set register 0xa364 to 0x1400 */ reg = 0x1400; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3b: Read bits 17:0 of register 0x9c20 */ reg = OS_REG_READ(ah, 0x9c20); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x1400] 0x9c20[17:0] = 0x%x\n", __func__, reg); /* Step 1c: Set bit 23 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x00800000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2c: Set register 0xa364 to 0x3C00 */ reg = 0x3c00; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3c: Read bits 17:0 of register 0x9c20 */ reg = OS_REG_READ(ah, 0x9c20); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x3C00] 0x9c20[17:0] = 0x%x\n", __func__, reg); /* Step 1d: Set bit 24 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x001040000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2d: Set register 0xa364 to 0x5005D */ reg = 0x5005D; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3d: Read bits 17:0 of register 0xa368 */ reg = OS_REG_READ(ah, 0xa368); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x5005D] 0xa368[17:0] = 0x%x\n", __func__, reg); /* Step 1e: Set bit 24 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x001040000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2e: Set register 0xa364 to 0x7005D */ reg = 0x7005D; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3e: Read bits 17:0 of register 0xa368 */ reg = OS_REG_READ(ah, 0xa368); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x7005D] 0xa368[17:0] = 0x%x\n", __func__, reg); /* Step 1f: Set bit 24 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x001000000; reg |= 0x40000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2f: Set register 0xa364 to 0x3005D */ reg = 0x3005D; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3f: Read bits 17:0 of register 0xa368 */ reg = OS_REG_READ(ah, 0xa368); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x3005D] 0xa368[17:0] = 0x%x\n", __func__, reg); /* Step 1g: Set bit 24 of register 0xa360 to 0 */ reg = OS_REG_READ(ah, 0xa360); reg &= ~0x001000000; reg |= 0x40000; OS_REG_WRITE(ah, 0xa360, reg); /* Step 2g: Set register 0xa364 to 0x6005D */ reg = 0x6005D; OS_REG_WRITE(ah, 0xa364, reg); /* Step 3g: Read bits 17:0 of register 0xa368 */ reg = OS_REG_READ(ah, 0xa368); reg &= 0x0003ffff; ath_hal_printf(ah, "%s: Test Control Status [0x6005D] 0xa368[17:0] = 0x%x\n", __func__, reg); #endif /* AH_DEBUG */ } /* * Return the busy for rx_frame, rx_clear, and tx_frame */ u_int32_t ar9300_get_mib_cycle_counts_pct(struct ath_hal *ah, u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t good = 1; u_int32_t rc = OS_REG_READ(ah, AR_RCCNT); u_int32_t rf = OS_REG_READ(ah, AR_RFCNT); u_int32_t tf = OS_REG_READ(ah, AR_TFCNT); u_int32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ if (ahp->ah_cycles == 0 || ahp->ah_cycles > cc) { /* * Cycle counter wrap (or initial call); it's not possible * to accurately calculate a value because the registers * right shift rather than wrap--so punt and return 0. */ HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: cycle counter wrap. ExtBusy = 0\n", __func__); good = 0; } else { u_int32_t cc_d = cc - ahp->ah_cycles; u_int32_t rc_d = rc - ahp->ah_rx_clear; u_int32_t rf_d = rf - ahp->ah_rx_frame; u_int32_t tf_d = tf - ahp->ah_tx_frame; if (cc_d != 0) { *rxc_pcnt = rc_d * 100 / cc_d; *rxf_pcnt = rf_d * 100 / cc_d; *txf_pcnt = tf_d * 100 / cc_d; } else { good = 0; } } ahp->ah_cycles = cc; ahp->ah_rx_frame = rf; ahp->ah_rx_clear = rc; ahp->ah_tx_frame = tf; return good; } /* * Return approximation of extension channel busy over an time interval * 0% (clear) -> 100% (busy) * -1 for invalid estimate */ uint32_t ar9300_get_11n_ext_busy(struct ath_hal *ah) { /* * Overflow condition to check before multiplying to get % * (x * 100 > 0xFFFFFFFF ) => (x > 0x28F5C28) */ #define OVERFLOW_LIMIT 0x28F5C28 #define ERROR_CODE -1 struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t busy = 0; /* percentage */ int8_t busyper = 0; u_int32_t cycle_count, ctl_busy, ext_busy; /* cycle_count will always be the first to wrap; therefore, read it last * This sequence of reads is not atomic, and MIB counter wrap * could happen during it ? */ ctl_busy = OS_REG_READ(ah, AR_RCCNT); ext_busy = OS_REG_READ(ah, AR_EXTRCCNT); cycle_count = OS_REG_READ(ah, AR_CCCNT); if ((ahp->ah_cycle_count == 0) || (ahp->ah_cycle_count > cycle_count) || (ahp->ah_ctl_busy > ctl_busy) || (ahp->ah_ext_busy > ext_busy)) { /* * Cycle counter wrap (or initial call); it's not possible * to accurately calculate a value because the registers * right shift rather than wrap--so punt and return 0. */ busyper = ERROR_CODE; HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: cycle counter wrap. ExtBusy = 0\n", __func__); } else { u_int32_t cycle_delta = cycle_count - ahp->ah_cycle_count; u_int32_t ext_busy_delta = ext_busy - ahp->ah_ext_busy; /* * Compute extension channel busy percentage * Overflow condition: 0xFFFFFFFF < ext_busy_delta * 100 * Underflow condition/Divide-by-zero: check that cycle_delta >> 7 != 0 * Will never happen, since (ext_busy_delta < cycle_delta) always, * and shift necessitated by large ext_busy_delta. * Due to timing difference to read the registers and counter overflow, * it may still happen that cycle_delta >> 7 = 0. * */ if (cycle_delta) { if (ext_busy_delta > OVERFLOW_LIMIT) { if (cycle_delta >> 7) { busy = ((ext_busy_delta >> 7) * 100) / (cycle_delta >> 7); } else { busyper = ERROR_CODE; } } else { busy = (ext_busy_delta * 100) / cycle_delta; } } else { busyper = ERROR_CODE; } if (busy > 100) { busy = 100; } if ( busyper != ERROR_CODE ) { busyper = busy; } } ahp->ah_cycle_count = cycle_count; ahp->ah_ctl_busy = ctl_busy; ahp->ah_ext_busy = ext_busy; return busyper; #undef OVERFLOW_LIMIT #undef ERROR_CODE } /* BB Panic Watchdog declarations */ #define HAL_BB_PANIC_WD_HT20_FACTOR 74 /* 0.74 */ #define HAL_BB_PANIC_WD_HT40_FACTOR 37 /* 0.37 */ void ar9300_config_bb_panic_watchdog(struct ath_hal *ah) { #define HAL_BB_PANIC_IDLE_TIME_OUT 0x0a8c0000 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; u_int32_t idle_tmo_ms = AH9300(ah)->ah_bb_panic_timeout_ms; u_int32_t val, idle_count; if (idle_tmo_ms != 0) { /* enable IRQ, disable chip-reset for BB panic */ val = OS_REG_READ(ah, AR_PHY_PANIC_WD_CTL_2) & AR_PHY_BB_PANIC_CNTL2_MASK; OS_REG_WRITE(ah, AR_PHY_PANIC_WD_CTL_2, (val | AR_PHY_BB_PANIC_IRQ_ENABLE) & ~AR_PHY_BB_PANIC_RST_ENABLE); /* bound limit to 10 secs */ if (idle_tmo_ms > 10000) { idle_tmo_ms = 10000; } if (chan != AH_NULL && IEEE80211_IS_CHAN_HT40(chan)) { idle_count = (100 * idle_tmo_ms) / HAL_BB_PANIC_WD_HT40_FACTOR; } else { idle_count = (100 * idle_tmo_ms) / HAL_BB_PANIC_WD_HT20_FACTOR; } /* * enable panic in non-IDLE mode, * disable in IDLE mode, * set idle time-out */ // EV92527 : Enable IDLE mode panic OS_REG_WRITE(ah, AR_PHY_PANIC_WD_CTL_1, AR_PHY_BB_PANIC_NON_IDLE_ENABLE | AR_PHY_BB_PANIC_IDLE_ENABLE | (AR_PHY_BB_PANIC_IDLE_MASK & HAL_BB_PANIC_IDLE_TIME_OUT) | (AR_PHY_BB_PANIC_NON_IDLE_MASK & (idle_count << 2))); } else { /* disable IRQ, disable chip-reset for BB panic */ OS_REG_WRITE(ah, AR_PHY_PANIC_WD_CTL_2, OS_REG_READ(ah, AR_PHY_PANIC_WD_CTL_2) & ~(AR_PHY_BB_PANIC_RST_ENABLE | AR_PHY_BB_PANIC_IRQ_ENABLE)); /* disable panic in non-IDLE mode, disable in IDLE mode */ OS_REG_WRITE(ah, AR_PHY_PANIC_WD_CTL_1, OS_REG_READ(ah, AR_PHY_PANIC_WD_CTL_1) & ~(AR_PHY_BB_PANIC_NON_IDLE_ENABLE | AR_PHY_BB_PANIC_IDLE_ENABLE)); } HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: %s BB Panic Watchdog tmo=%ums\n", __func__, idle_tmo_ms ? "Enabled" : "Disabled", idle_tmo_ms); #undef HAL_BB_PANIC_IDLE_TIME_OUT } void ar9300_handle_bb_panic(struct ath_hal *ah) { u_int32_t status; /* * we want to avoid printing in ISR context so we save * panic watchdog status to be printed later in DPC context */ AH9300(ah)->ah_bb_panic_last_status = status = OS_REG_READ(ah, AR_PHY_PANIC_WD_STATUS); /* * panic watchdog timer should reset on status read * but to make sure we write 0 to the watchdog status bit */ OS_REG_WRITE(ah, AR_PHY_PANIC_WD_STATUS, status & ~AR_PHY_BB_WD_STATUS_CLR); } int ar9300_get_bb_panic_info(struct ath_hal *ah, struct hal_bb_panic_info *bb_panic) { bb_panic->status = AH9300(ah)->ah_bb_panic_last_status; /* * For signature 04000539 do not print anything. * This is a very common occurence as a compromise between * BB Panic and AH_FALSE detects (EV71009). It indicates * radar hang, which can be cleared by reprogramming * radar related register and does not requre a chip reset */ /* Suppress BB Status mesg following signature */ switch (bb_panic->status) { - case 0x04000539: - case 0x04008009: - case 0x04000b09: - case 0x1300000a: + case 0x04000539: + case 0x04008009: + case 0x04000b09: + case 0x1300000a: return -1; } bb_panic->tsf = ar9300_get_tsf32(ah); bb_panic->wd = MS(bb_panic->status, AR_PHY_BB_WD_STATUS); bb_panic->det = MS(bb_panic->status, AR_PHY_BB_WD_DET_HANG); bb_panic->rdar = MS(bb_panic->status, AR_PHY_BB_WD_RADAR_SM); bb_panic->r_odfm = MS(bb_panic->status, AR_PHY_BB_WD_RX_OFDM_SM); bb_panic->r_cck = MS(bb_panic->status, AR_PHY_BB_WD_RX_CCK_SM); bb_panic->t_odfm = MS(bb_panic->status, AR_PHY_BB_WD_TX_OFDM_SM); bb_panic->t_cck = MS(bb_panic->status, AR_PHY_BB_WD_TX_CCK_SM); bb_panic->agc = MS(bb_panic->status, AR_PHY_BB_WD_AGC_SM); bb_panic->src = MS(bb_panic->status, AR_PHY_BB_WD_SRCH_SM); bb_panic->phy_panic_wd_ctl1 = OS_REG_READ(ah, AR_PHY_PANIC_WD_CTL_1); bb_panic->phy_panic_wd_ctl2 = OS_REG_READ(ah, AR_PHY_PANIC_WD_CTL_2); bb_panic->phy_gen_ctrl = OS_REG_READ(ah, AR_PHY_GEN_CTRL); bb_panic->rxc_pcnt = bb_panic->rxf_pcnt = bb_panic->txf_pcnt = 0; bb_panic->cycles = ar9300_get_mib_cycle_counts_pct(ah, &bb_panic->rxc_pcnt, &bb_panic->rxf_pcnt, &bb_panic->txf_pcnt); if (ah->ah_config.ath_hal_show_bb_panic) { ath_hal_printf(ah, "\n==== BB update: BB status=0x%08x, " "tsf=0x%08x ====\n", bb_panic->status, bb_panic->tsf); ath_hal_printf(ah, "** BB state: wd=%u det=%u rdar=%u rOFDM=%d " "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", bb_panic->wd, bb_panic->det, bb_panic->rdar, bb_panic->r_odfm, bb_panic->r_cck, bb_panic->t_odfm, bb_panic->t_cck, bb_panic->agc, bb_panic->src); ath_hal_printf(ah, "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", bb_panic->phy_panic_wd_ctl1, bb_panic->phy_panic_wd_ctl2); ath_hal_printf(ah, "** BB mode: BB_gen_controls=0x%08x **\n", bb_panic->phy_gen_ctrl); if (bb_panic->cycles) { ath_hal_printf(ah, "** BB busy times: rx_clear=%d%%, " "rx_frame=%d%%, tx_frame=%d%% **\n", bb_panic->rxc_pcnt, bb_panic->rxf_pcnt, bb_panic->txf_pcnt); } ath_hal_printf(ah, "==== BB update: done ====\n\n"); } return 0; //The returned data will be stored for athstats to retrieve it } /* set the reason for HAL reset */ void ar9300_set_hal_reset_reason(struct ath_hal *ah, u_int8_t resetreason) { AH9300(ah)->ah_reset_reason = resetreason; } /* * Configure 20/40 operation * * 20/40 = joint rx clear (control and extension) * 20 = rx clear (control) * * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz * when changing from 20/40 => 20 only */ void ar9300_set_11n_mac2040(struct ath_hal *ah, HAL_HT_MACMODE mode) { u_int32_t macmode; /* Configure MAC for 20/40 operation */ if (mode == HAL_HT_MACMODE_2040 && !ah->ah_config.ath_hal_cwm_ignore_ext_cca) { macmode = AR_2040_JOINED_RX_CLEAR; } else { macmode = 0; } OS_REG_WRITE(ah, AR_2040_MODE, macmode); } /* * Get Rx clear (control/extension channel) * * Returns active low (busy) for ctrl/ext channel * Owl 2.0 */ HAL_HT_RXCLEAR ar9300_get_11n_rx_clear(struct ath_hal *ah) { HAL_HT_RXCLEAR rxclear = 0; u_int32_t val; val = OS_REG_READ(ah, AR_DIAG_SW); /* control channel */ if (val & AR_DIAG_RX_CLEAR_CTL_LOW) { rxclear |= HAL_RX_CLEAR_CTL_LOW; } /* extension channel */ if (val & AR_DIAG_RX_CLEAR_EXT_LOW) { rxclear |= HAL_RX_CLEAR_EXT_LOW; } return rxclear; } /* * Set Rx clear (control/extension channel) * * Useful for forcing the channel to appear busy for * debugging/diagnostics * Owl 2.0 */ void ar9300_set_11n_rx_clear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear) { /* control channel */ if (rxclear & HAL_RX_CLEAR_CTL_LOW) { OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_CLEAR_CTL_LOW); } else { OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_CLEAR_CTL_LOW); } /* extension channel */ if (rxclear & HAL_RX_CLEAR_EXT_LOW) { OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_CLEAR_EXT_LOW); } else { OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_CLEAR_EXT_LOW); } } /* * HAL support code for force ppm tracking workaround. */ u_int32_t ar9300_ppm_get_rssi_dump(struct ath_hal *ah) { u_int32_t retval; u_int32_t off1; u_int32_t off2; if (OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) & AR_PHY_SWAP_ALT_CHAIN) { off1 = 0x2000; off2 = 0x1000; } else { off1 = 0x1000; off2 = 0x2000; } retval = ((0xff & OS_REG_READ(ah, AR_PHY_CHAN_INFO_GAIN_0 )) << 0) | ((0xff & OS_REG_READ(ah, AR_PHY_CHAN_INFO_GAIN_0 + off1)) << 8) | ((0xff & OS_REG_READ(ah, AR_PHY_CHAN_INFO_GAIN_0 + off2)) << 16); return retval; } u_int32_t ar9300_ppm_force(struct ath_hal *ah) { u_int32_t data_fine; u_int32_t data4; //u_int32_t off1; //u_int32_t off2; HAL_BOOL signed_val = AH_FALSE; // if (OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) & AR_PHY_SWAP_ALT_CHAIN) { // off1 = 0x2000; // off2 = 0x1000; // } else { // off1 = 0x1000; // off2 = 0x2000; // } data_fine = AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK & OS_REG_READ(ah, AR_PHY_CHNINFO_GAINDIFF); /* * bit [11-0] is new ppm value. bit 11 is the signed bit. * So check value from bit[10:0]. * Now get the abs val of the ppm value read in bit[0:11]. * After that do bound check on abs value. * if value is off limit, CAP the value and and restore signed bit. */ if (data_fine & AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT) { /* get the positive value */ data_fine = (~data_fine + 1) & AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK; signed_val = AH_TRUE; } if (data_fine > AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT) { HALDEBUG(ah, HAL_DEBUG_REGIO, "%s Correcting ppm out of range %x\n", __func__, (data_fine & 0x7ff)); data_fine = AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT; } /* * Restore signed value if changed above. * Use typecast to avoid compilation errors */ if (signed_val) { data_fine = (-(int32_t)data_fine) & AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK; } /* write value */ data4 = OS_REG_READ(ah, AR_PHY_TIMING2) & ~(AR_PHY_TIMING2_USE_FORCE_PPM | AR_PHY_TIMING2_FORCE_PPM_VAL); OS_REG_WRITE(ah, AR_PHY_TIMING2, data4 | data_fine | AR_PHY_TIMING2_USE_FORCE_PPM); return data_fine; } void ar9300_ppm_un_force(struct ath_hal *ah) { u_int32_t data4; data4 = OS_REG_READ(ah, AR_PHY_TIMING2) & ~AR_PHY_TIMING2_USE_FORCE_PPM; OS_REG_WRITE(ah, AR_PHY_TIMING2, data4); } u_int32_t ar9300_ppm_arm_trigger(struct ath_hal *ah) { u_int32_t val; u_int32_t ret; val = OS_REG_READ(ah, AR_PHY_CHAN_INFO_MEMORY); ret = OS_REG_READ(ah, AR_TSF_L32); OS_REG_WRITE(ah, AR_PHY_CHAN_INFO_MEMORY, val | AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK); /* return low word of TSF at arm time */ return ret; } int ar9300_ppm_get_trigger(struct ath_hal *ah) { if (OS_REG_READ(ah, AR_PHY_CHAN_INFO_MEMORY) & AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK) { /* has not triggered yet, return AH_FALSE */ return 0; } /* else triggered, return AH_TRUE */ return 1; } void ar9300_mark_phy_inactive(struct ath_hal *ah) { OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); } /* DEBUG */ u_int32_t ar9300_ppm_get_force_state(struct ath_hal *ah) { return OS_REG_READ(ah, AR_PHY_TIMING2) & (AR_PHY_TIMING2_USE_FORCE_PPM | AR_PHY_TIMING2_FORCE_PPM_VAL); } /* * Return the Cycle counts for rx_frame, rx_clear, and tx_frame */ HAL_BOOL ar9300_get_mib_cycle_counts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) { /* * XXX FreeBSD todo: reimplement this */ #if 0 p_cnts->tx_frame_count = OS_REG_READ(ah, AR_TFCNT); p_cnts->rx_frame_count = OS_REG_READ(ah, AR_RFCNT); p_cnts->rx_clear_count = OS_REG_READ(ah, AR_RCCNT); p_cnts->cycle_count = OS_REG_READ(ah, AR_CCCNT); p_cnts->is_tx_active = (OS_REG_READ(ah, AR_TFCNT) == p_cnts->tx_frame_count) ? AH_FALSE : AH_TRUE; p_cnts->is_rx_active = (OS_REG_READ(ah, AR_RFCNT) == p_cnts->rx_frame_count) ? AH_FALSE : AH_TRUE; #endif return AH_FALSE; } void ar9300_clear_mib_counters(struct ath_hal *ah) { u_int32_t reg_val; reg_val = OS_REG_READ(ah, AR_MIBC); OS_REG_WRITE(ah, AR_MIBC, reg_val | AR_MIBC_CMC); OS_REG_WRITE(ah, AR_MIBC, reg_val & ~AR_MIBC_CMC); } /* Enable or Disable RIFS Rx capability as part of SW WAR for Bug 31602 */ HAL_BOOL ar9300_set_rifs_delay(struct ath_hal *ah, HAL_BOOL enable) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan); HAL_BOOL is_chan_2g = IS_CHAN_2GHZ(ichan); u_int32_t tmp = 0; if (enable) { if (ahp->ah_rifs_enabled == AH_TRUE) { return AH_TRUE; } OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, ahp->ah_rifs_reg[0]); OS_REG_WRITE(ah, AR_PHY_RIFS_SRCH, ahp->ah_rifs_reg[1]); ahp->ah_rifs_enabled = AH_TRUE; OS_MEMZERO(ahp->ah_rifs_reg, sizeof(ahp->ah_rifs_reg)); } else { if (ahp->ah_rifs_enabled == AH_TRUE) { ahp->ah_rifs_reg[0] = OS_REG_READ(ah, AR_PHY_SEARCH_START_DELAY); ahp->ah_rifs_reg[1] = OS_REG_READ(ah, AR_PHY_RIFS_SRCH); } /* Change rifs init delay to 0 */ OS_REG_WRITE(ah, AR_PHY_RIFS_SRCH, (ahp->ah_rifs_reg[1] & ~(AR_PHY_RIFS_INIT_DELAY))); tmp = 0xfffff000 & OS_REG_READ(ah, AR_PHY_SEARCH_START_DELAY); if (is_chan_2g) { if (IEEE80211_IS_CHAN_HT40(AH_PRIVATE(ah)->ah_curchan)) { OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, tmp | 500); } else { /* Sowl 2G HT-20 default is 0x134 for search start delay */ OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, tmp | 250); } } else { if (IEEE80211_IS_CHAN_HT40(AH_PRIVATE(ah)->ah_curchan)) { OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, tmp | 0x370); } else { /* Sowl 5G HT-20 default is 0x1b8 for search start delay */ OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, tmp | 0x1b8); } } ahp->ah_rifs_enabled = AH_FALSE; } return AH_TRUE; } /* ar9300_set_rifs_delay () */ /* Set the current RIFS Rx setting */ HAL_BOOL ar9300_set_11n_rx_rifs(struct ath_hal *ah, HAL_BOOL enable) { /* Non-Owl 11n chips */ if ((ath_hal_getcapability(ah, HAL_CAP_RIFS_RX, 0, AH_NULL) == HAL_OK)) { if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK) { return ar9300_set_rifs_delay(ah, enable); } return AH_FALSE; } return AH_TRUE; } /* ar9300_set_11n_rx_rifs () */ static hal_mac_hangs_t ar9300_compare_dbg_hang(struct ath_hal *ah, mac_dbg_regs_t mac_dbg, hal_mac_hang_check_t hang_check, hal_mac_hangs_t hangs, u_int8_t *dcu_chain) { int i = 0; hal_mac_hangs_t found_hangs = 0; if (hangs & dcu_chain_state) { for (i = 0; i < 6; i++) { if (((mac_dbg.dma_dbg_4 >> (5 * i)) & 0x1f) == hang_check.dcu_chain_state) { found_hangs |= dcu_chain_state; *dcu_chain = i; } } for (i = 0; i < 4; i++) { if (((mac_dbg.dma_dbg_5 >> (5 * i)) & 0x1f) == hang_check.dcu_chain_state) { found_hangs |= dcu_chain_state; *dcu_chain = i + 6; } } } if (hangs & dcu_complete_state) { if ((mac_dbg.dma_dbg_6 & 0x3) == hang_check.dcu_complete_state) { found_hangs |= dcu_complete_state; } } return found_hangs; } /* end - ar9300_compare_dbg_hang */ #define NUM_STATUS_READS 50 HAL_BOOL ar9300_detect_mac_hang(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); mac_dbg_regs_t mac_dbg; hal_mac_hang_check_t hang_sig1_val = {0x6, 0x1, 0, 0, 0, 0, 0, 0}; hal_mac_hangs_t hang_sig1 = (dcu_chain_state | dcu_complete_state); int i = 0; u_int8_t dcu_chain = 0, current_dcu_chain_state, shift_val; if (!(ahp->ah_hang_wars & HAL_MAC_HANG_WAR)) { return AH_FALSE; } OS_MEMZERO(&mac_dbg, sizeof(mac_dbg)); mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4); mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5); mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6); HALDEBUG(ah, HAL_DEBUG_DFS, " dma regs: %X %X %X \n", mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5, mac_dbg.dma_dbg_6); if (hang_sig1 != ar9300_compare_dbg_hang(ah, mac_dbg, hang_sig1_val, hang_sig1, &dcu_chain)) { HALDEBUG(ah, HAL_DEBUG_DFS, " hang sig1 not found \n"); return AH_FALSE; } shift_val = (dcu_chain >= 6) ? (dcu_chain-6) : (dcu_chain); shift_val *= 5; for (i = 1; i <= NUM_STATUS_READS; i++) { if (dcu_chain < 6) { mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4); current_dcu_chain_state = ((mac_dbg.dma_dbg_4 >> shift_val) & 0x1f); } else { mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5); current_dcu_chain_state = ((mac_dbg.dma_dbg_5 >> shift_val) & 0x1f); } mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6); if (((mac_dbg.dma_dbg_6 & 0x3) != hang_sig1_val.dcu_complete_state) || (current_dcu_chain_state != hang_sig1_val.dcu_chain_state)) { return AH_FALSE; } } HALDEBUG(ah, HAL_DEBUG_DFS, "%s sig5count=%d sig6count=%d ", __func__, ahp->ah_hang[MAC_HANG_SIG1], ahp->ah_hang[MAC_HANG_SIG2]); ahp->ah_hang[MAC_HANG_SIG1]++; return AH_TRUE; } /* end - ar9300_detect_mac_hang */ /* Determine if the baseband is hung by reading the Observation Bus Register */ HAL_BOOL ar9300_detect_bb_hang(struct ath_hal *ah) { #define N(a) (sizeof(a) / sizeof(a[0])) struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t hang_sig = 0; int i = 0; /* Check the PCU Observation Bus 1 register (0x806c) NUM_STATUS_READS times * * 4 known BB hang signatures - * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E * [2] bits 8,9 are 1, bit 11 is 0. State machine state (bits 25-31) is 0x52 * [3] bits 8,9 are 1, bit 11 is 0. State machine state (bits 25-31) is 0x18 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2, * Rx State (bits 20-24) is 0x7. */ hal_hw_hang_check_t hang_list [] = { /* Offset Reg Value Reg Mask Hang Offset */ {AR_OBS_BUS_1, 0x1E000000, 0x7E000B00, BB_HANG_SIG1}, {AR_OBS_BUS_1, 0x52000B00, 0x7E000B00, BB_HANG_SIG2}, {AR_OBS_BUS_1, 0x18000B00, 0x7E000B00, BB_HANG_SIG3}, {AR_OBS_BUS_1, 0x00702400, 0x7E7FFFEF, BB_HANG_SIG4} }; if (!(ahp->ah_hang_wars & (HAL_RIFS_BB_HANG_WAR | HAL_DFS_BB_HANG_WAR | HAL_RX_STUCK_LOW_BB_HANG_WAR))) { return AH_FALSE; } hang_sig = OS_REG_READ(ah, AR_OBS_BUS_1); for (i = 1; i <= NUM_STATUS_READS; i++) { if (hang_sig != OS_REG_READ(ah, AR_OBS_BUS_1)) { return AH_FALSE; } } for (i = 0; i < N(hang_list); i++) { if ((hang_sig & hang_list[i].hang_mask) == hang_list[i].hang_val) { ahp->ah_hang[hang_list[i].hang_offset]++; HALDEBUG(ah, HAL_DEBUG_DFS, "%s sig1count=%d sig2count=%d " "sig3count=%d sig4count=%d\n", __func__, ahp->ah_hang[BB_HANG_SIG1], ahp->ah_hang[BB_HANG_SIG2], ahp->ah_hang[BB_HANG_SIG3], ahp->ah_hang[BB_HANG_SIG4]); return AH_TRUE; } } HALDEBUG(ah, HAL_DEBUG_DFS, "%s Found an unknown BB hang signature! " "<0x806c>=0x%x\n", __func__, hang_sig); return AH_FALSE; #undef N } /* end - ar9300_detect_bb_hang () */ #undef NUM_STATUS_READS HAL_STATUS ar9300_select_ant_config(struct ath_hal *ah, u_int32_t cfg) { struct ath_hal_9300 *ahp = AH9300(ah); const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; u_int16_t ant_config; u_int32_t hal_num_ant_config; hal_num_ant_config = IS_CHAN_2GHZ(ichan) ? p_cap->halNumAntCfg2GHz: p_cap->halNumAntCfg5GHz; if (cfg < hal_num_ant_config) { if (HAL_OK == ar9300_eeprom_get_ant_cfg(ahp, chan, cfg, &ant_config)) { OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); return HAL_OK; } } return HAL_EINVAL; } /* * Functions to get/set DCS mode */ void ar9300_set_dcs_mode(struct ath_hal *ah, u_int32_t mode) { AH9300(ah)->ah_dcs_enable = mode; } u_int32_t ar9300_get_dcs_mode(struct ath_hal *ah) { return AH9300(ah)->ah_dcs_enable; } #if ATH_BT_COEX void ar9300_set_bt_coex_info(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_bt_module = btinfo->bt_module; ahp->ah_bt_coex_config_type = btinfo->bt_coex_config; ahp->ah_bt_active_gpio_select = btinfo->bt_gpio_bt_active; ahp->ah_bt_priority_gpio_select = btinfo->bt_gpio_bt_priority; ahp->ah_wlan_active_gpio_select = btinfo->bt_gpio_wlan_active; ahp->ah_bt_active_polarity = btinfo->bt_active_polarity; ahp->ah_bt_coex_single_ant = btinfo->bt_single_ant; ahp->ah_bt_wlan_isolation = btinfo->bt_isolation; } void ar9300_bt_coex_config(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_BOOL rx_clear_polarity; /* * For Kiwi and Osprey, the polarity of rx_clear is active high. * The bt_rxclear_polarity flag from ath_dev needs to be inverted. */ rx_clear_polarity = !btconf->bt_rxclear_polarity; ahp->ah_bt_coex_mode = (ahp->ah_bt_coex_mode & AR_BT_QCU_THRESH) | SM(btconf->bt_time_extend, AR_BT_TIME_EXTEND) | SM(btconf->bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | SM(btconf->bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | SM(btconf->bt_mode, AR_BT_MODE) | SM(btconf->bt_quiet_collision, AR_BT_QUIET) | SM(rx_clear_polarity, AR_BT_RX_CLEAR_POLARITY) | SM(btconf->bt_priority_time, AR_BT_PRIORITY_TIME) | SM(btconf->bt_first_slot_time, AR_BT_FIRST_SLOT_TIME); ahp->ah_bt_coex_mode2 |= SM(btconf->bt_hold_rxclear, AR_BT_HOLD_RX_CLEAR); if (ahp->ah_bt_coex_single_ant == AH_FALSE) { /* Enable ACK to go out even though BT has higher priority. */ ahp->ah_bt_coex_mode2 |= AR_BT_DISABLE_BT_ANT; } } void ar9300_bt_coex_set_qcu_thresh(struct ath_hal *ah, int qnum) { struct ath_hal_9300 *ahp = AH9300(ah); /* clear the old value, then set the new value */ ahp->ah_bt_coex_mode &= ~AR_BT_QCU_THRESH; ahp->ah_bt_coex_mode |= SM(qnum, AR_BT_QCU_THRESH); } void ar9300_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_bt_coex_bt_weight[0] = AR9300_BT_WGHT; ahp->ah_bt_coex_bt_weight[1] = AR9300_BT_WGHT; ahp->ah_bt_coex_bt_weight[2] = AR9300_BT_WGHT; ahp->ah_bt_coex_bt_weight[3] = AR9300_BT_WGHT; switch (stomp_type) { case HAL_BT_COEX_STOMP_ALL: ahp->ah_bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0; ahp->ah_bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1; break; case HAL_BT_COEX_STOMP_LOW: ahp->ah_bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0; ahp->ah_bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1; break; case HAL_BT_COEX_STOMP_ALL_FORCE: ahp->ah_bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_FORCE_WLAN_WGHT0; ahp->ah_bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_FORCE_WLAN_WGHT1; break; case HAL_BT_COEX_STOMP_LOW_FORCE: ahp->ah_bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_FORCE_WLAN_WGHT0; ahp->ah_bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_FORCE_WLAN_WGHT1; break; case HAL_BT_COEX_STOMP_NONE: case HAL_BT_COEX_NO_STOMP: ahp->ah_bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0; ahp->ah_bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1; break; default: /* There is a force_weight from registry */ ahp->ah_bt_coex_wlan_weight[0] = stomp_type; ahp->ah_bt_coex_wlan_weight[1] = stomp_type; break; } } void ar9300_bt_coex_setup_bmiss_thresh(struct ath_hal *ah, u_int32_t thresh) { struct ath_hal_9300 *ahp = AH9300(ah); /* clear the old value, then set the new value */ ahp->ah_bt_coex_mode2 &= ~AR_BT_BCN_MISS_THRESH; ahp->ah_bt_coex_mode2 |= SM(thresh, AR_BT_BCN_MISS_THRESH); } static void ar9300_bt_coex_antenna_diversity(struct ath_hal *ah, u_int32_t value) { struct ath_hal_9300 *ahp = AH9300(ah); #if ATH_ANT_DIV_COMB //struct ath_hal_private *ahpriv = AH_PRIVATE(ah); const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; #endif if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) { if (ahp->ah_diversity_control == HAL_ANT_VARIABLE) { /* Config antenna diversity */ #if ATH_ANT_DIV_COMB ar9300_ant_ctrl_set_lna_div_use_bt_ant(ah, value, chan); #endif } } } void ar9300_bt_coex_set_parameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) { struct ath_hal_9300 *ahp = AH9300(ah); struct ath_hal_private *ahpriv = AH_PRIVATE(ah); switch (type) { case HAL_BT_COEX_SET_ACK_PWR: if (value) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_LOW_ACK_PWR; } else { ahp->ah_bt_coex_flag &= ~HAL_BT_COEX_FLAG_LOW_ACK_PWR; } ar9300_set_tx_power_limit(ah, ahpriv->ah_powerLimit, ahpriv->ah_extraTxPow, 0); break; case HAL_BT_COEX_ANTENNA_DIVERSITY: if (AR_SREV_POSEIDON(ah)) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW; if (value) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; } else { ahp->ah_bt_coex_flag &= ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; } ar9300_bt_coex_antenna_diversity(ah, value); } break; case HAL_BT_COEX_LOWER_TX_PWR: if (value) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_LOWER_TX_PWR; } else { ahp->ah_bt_coex_flag &= ~HAL_BT_COEX_FLAG_LOWER_TX_PWR; } ar9300_set_tx_power_limit(ah, ahpriv->ah_powerLimit, ahpriv->ah_extraTxPow, 0); break; #if ATH_SUPPORT_MCI case HAL_BT_COEX_MCI_MAX_TX_PWR: if ((ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_SHARED_CHN) { if (value) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR; ahp->ah_mci_concur_tx_en = AH_TRUE; } else { ahp->ah_bt_coex_flag &= ~HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR; ahp->ah_mci_concur_tx_en = AH_FALSE; } ar9300_set_tx_power_limit(ah, ahpriv->ah_powerLimit, ahpriv->ah_extraTxPow, 0); } HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) concur_tx_en = %d\n", ahp->ah_mci_concur_tx_en); break; case HAL_BT_COEX_MCI_FTP_STOMP_RX: if (value) { ahp->ah_bt_coex_flag |= HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX; } else { ahp->ah_bt_coex_flag &= ~HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX; } break; #endif default: break; } } void ar9300_bt_coex_disable(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); /* Always drive rx_clear_external output as 0 */ ath_hal_gpioCfgOutput(ah, ahp->ah_wlan_active_gpio_select, HAL_GPIO_OUTPUT_MUX_AS_OUTPUT); if (ahp->ah_bt_coex_single_ant == AH_TRUE) { OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); } OS_REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); OS_REG_WRITE(ah, AR_BT_COEX_MODE2, 0); OS_REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0); OS_REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0); ahp->ah_bt_coex_enabled = AH_FALSE; } int ar9300_bt_coex_enable(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); /* Program coex mode and weight registers to actually enable coex */ OS_REG_WRITE(ah, AR_BT_COEX_MODE, ahp->ah_bt_coex_mode); OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_bt_coex_mode2); OS_REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]); OS_REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ahp->ah_bt_coex_bt_weight[0]); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ahp->ah_bt_coex_bt_weight[1]); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ahp->ah_bt_coex_bt_weight[2]); OS_REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ahp->ah_bt_coex_bt_weight[3]); if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) { OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER); } else { OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER); } OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); if (ahp->ah_bt_coex_single_ant == AH_TRUE) { OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 1); } else { OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); } if (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) { /* For 3-wire, configure the desired GPIO port for rx_clear */ ath_hal_gpioCfgOutput(ah, ahp->ah_wlan_active_gpio_select, HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE); } else if ((ahp->ah_bt_coex_config_type >= HAL_BT_COEX_CFG_2WIRE_2CH) && (ahp->ah_bt_coex_config_type <= HAL_BT_COEX_CFG_2WIRE_CH0)) { /* For 2-wire, configure the desired GPIO port for TX_FRAME output */ ath_hal_gpioCfgOutput(ah, ahp->ah_wlan_active_gpio_select, HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME); } /* * Enable a weak pull down on BT_ACTIVE. * When BT device is disabled, BT_ACTIVE might be floating. */ OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU), (AR_GPIO_PULL_DOWN << (ahp->ah_bt_active_gpio_select * 2)), (AR_GPIO_PDPU_OPTION << (ahp->ah_bt_active_gpio_select * 2))); ahp->ah_bt_coex_enabled = AH_TRUE; return 0; } u_int32_t ar9300_get_bt_active_gpio(struct ath_hal *ah, u_int32_t reg) { return 0; } u_int32_t ar9300_get_wlan_active_gpio(struct ath_hal *ah, u_int32_t reg,u_int32_t bOn) { return bOn; } void ar9300_init_bt_coex(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); if (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) { OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); /* * Set input mux for bt_prority_async and * bt_active_async to GPIO pins */ OS_REG_RMW_FIELD(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1), AR_GPIO_INPUT_MUX1_BT_ACTIVE, ahp->ah_bt_active_gpio_select); OS_REG_RMW_FIELD(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1), AR_GPIO_INPUT_MUX1_BT_PRIORITY, ahp->ah_bt_priority_gpio_select); /* Configure the desired GPIO ports for input */ ath_hal_gpioCfgInput(ah, ahp->ah_bt_active_gpio_select); ath_hal_gpioCfgInput(ah, ahp->ah_bt_priority_gpio_select); if (ahp->ah_bt_coex_enabled) { ar9300_bt_coex_enable(ah); } else { ar9300_bt_coex_disable(ah); } } else if ((ahp->ah_bt_coex_config_type >= HAL_BT_COEX_CFG_2WIRE_2CH) && (ahp->ah_bt_coex_config_type <= HAL_BT_COEX_CFG_2WIRE_CH0)) { /* 2-wire */ if (ahp->ah_bt_coex_enabled) { /* Connect bt_active_async to baseband */ OS_REG_CLR_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); /* * Set input mux for bt_prority_async and * bt_active_async to GPIO pins */ OS_REG_RMW_FIELD(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1), AR_GPIO_INPUT_MUX1_BT_ACTIVE, ahp->ah_bt_active_gpio_select); /* Configure the desired GPIO ports for input */ ath_hal_gpioCfgInput(ah, ahp->ah_bt_active_gpio_select); /* Enable coexistence on initialization */ ar9300_bt_coex_enable(ah); } } #if ATH_SUPPORT_MCI else if (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI) { if (ahp->ah_bt_coex_enabled) { ar9300_mci_bt_coex_enable(ah); } else { ar9300_mci_bt_coex_disable(ah); } } #endif /* ATH_SUPPORT_MCI */ } #endif /* ATH_BT_COEX */ HAL_STATUS ar9300_set_proxy_sta(struct ath_hal *ah, HAL_BOOL enable) { u_int32_t val; int wasp_mm_rev; #define AR_SOC_RST_REVISION_ID 0xB8060090 #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) wasp_mm_rev = (REG_READ(AR_SOC_RST_REVISION_ID) & AR_SREV_REVISION_WASP_MINOR_MINOR_MASK) >> AR_SREV_REVISION_WASP_MINOR_MINOR_SHIFT; #undef AR_SOC_RST_REVISION_ID #undef REG_READ /* * Azimuth (ProxySTA) Mode is only supported correctly by * Peacock or WASP 1.3.0.1 or later (hopefully) chips. * * Enable this feature for Scorpion at this time. The silicon * still needs to be validated. */ if (!(AH_PRIVATE((ah))->ah_macVersion == AR_SREV_VERSION_AR9580) && !(AH_PRIVATE((ah))->ah_macVersion == AR_SREV_VERSION_SCORPION) && !((AH_PRIVATE((ah))->ah_macVersion == AR_SREV_VERSION_WASP) && ((AH_PRIVATE((ah))->ah_macRev > AR_SREV_REVISION_WASP_13) || (AH_PRIVATE((ah))->ah_macRev == AR_SREV_REVISION_WASP_13 && wasp_mm_rev >= 0 /* 1 */)))) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s error: current chip (ver 0x%x, " "rev 0x%x, minor minor rev 0x%x) cannot support Azimuth Mode\n", __func__, AH_PRIVATE((ah))->ah_macVersion, AH_PRIVATE((ah))->ah_macRev, wasp_mm_rev); return HAL_ENOTSUPP; } OS_REG_WRITE(ah, AR_MAC_PCU_LOGIC_ANALYZER, AR_MAC_PCU_LOGIC_ANALYZER_PSTABUG75996); /* turn on mode bit[24] for proxy sta */ OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, OS_REG_READ(ah, AR_PCU_MISC_MODE2) | AR_PCU_MISC_MODE2_PROXY_STA); val = OS_REG_READ(ah, AR_AZIMUTH_MODE); if (enable) { val |= AR_AZIMUTH_KEY_SEARCH_AD1 | AR_AZIMUTH_CTS_MATCH_TX_AD2 | AR_AZIMUTH_BA_USES_AD1; /* turn off filter pass hold (bit 9) */ val &= ~AR_AZIMUTH_FILTER_PASS_HOLD; } else { val &= ~(AR_AZIMUTH_KEY_SEARCH_AD1 | AR_AZIMUTH_CTS_MATCH_TX_AD2 | AR_AZIMUTH_BA_USES_AD1); } OS_REG_WRITE(ah, AR_AZIMUTH_MODE, val); /* enable promiscous mode */ OS_REG_WRITE(ah, AR_RX_FILTER, OS_REG_READ(ah, AR_RX_FILTER) | HAL_RX_FILTER_PROM); /* enable promiscous in azimuth mode */ OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_PROM_VC_MODE); OS_REG_WRITE(ah, AR_MAC_PCU_LOGIC_ANALYZER, AR_MAC_PCU_LOGIC_ANALYZER_VC_MODE); /* turn on filter pass hold (bit 9) */ OS_REG_WRITE(ah, AR_AZIMUTH_MODE, OS_REG_READ(ah, AR_AZIMUTH_MODE) | AR_AZIMUTH_FILTER_PASS_HOLD); return HAL_OK; } #if 0 void ar9300_mat_enable(struct ath_hal *ah, int enable) { /* * MAT (s/w ProxySTA) implementation requires to turn off interrupt * mitigation and turn on key search always for better performance. */ struct ath_hal_9300 *ahp = AH9300(ah); struct ath_hal_private *ap = AH_PRIVATE(ah); ahp->ah_intr_mitigation_rx = !enable; if (ahp->ah_intr_mitigation_rx) { /* * Enable Interrupt Mitigation for Rx. * If no build-specific limits for the rx interrupt mitigation * timer have been specified, use conservative defaults. */ #ifndef AH_RIMT_VAL_LAST #define AH_RIMT_LAST_MICROSEC 500 #endif #ifndef AH_RIMT_VAL_FIRST #define AH_RIMT_FIRST_MICROSEC 2000 #endif OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, AH_RIMT_LAST_MICROSEC); OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, AH_RIMT_FIRST_MICROSEC); } else { OS_REG_WRITE(ah, AR_RIMT, 0); } ahp->ah_enable_keysearch_always = !!enable; ar9300_enable_keysearch_always(ah, ahp->ah_enable_keysearch_always); } #endif void ar9300_enable_tpc(struct ath_hal *ah) { u_int32_t val = 0; ah->ah_config.ath_hal_desc_tpc = 1; /* Enable TPC */ OS_REG_RMW_FIELD(ah, AR_PHY_PWRTX_MAX, AR_PHY_PER_PACKET_POWERTX_MAX, 1); /* * Disable per chain power reduction since we are already * accounting for this in our calculations */ val = OS_REG_READ(ah, AR_PHY_POWER_TX_SUB); if (AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, val & AR_PHY_POWER_TX_SUB_2_DISABLE); } else { OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, val & AR_PHY_POWER_TX_SUB_3_DISABLE); } } /* * ar9300_force_tsf_sync * This function forces the TSF sync to the given bssid, this is implemented * as a temp hack to get the AoW demo, and is primarily used in the WDS client * mode of operation, where we sync the TSF to RootAP TSF values */ void ar9300_force_tsf_sync(struct ath_hal *ah, const u_int8_t *bssid, u_int16_t assoc_id) { ar9300_set_operating_mode(ah, HAL_M_STA); ar9300_write_associd(ah, bssid, assoc_id); } void ar9300_chk_rssi_update_tx_pwr(struct ath_hal *ah, int rssi) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t temp_obdb_reg_val = 0, temp_tcp_reg_val; u_int32_t temp_powertx_rate9_reg_val; int8_t olpc_power_offset = 0; int8_t tmp_olpc_val = 0; HAL_RSSI_TX_POWER old_greentx_status; u_int8_t target_power_val_t[ar9300_rate_size]; int8_t tmp_rss1_thr1, tmp_rss1_thr2; if ((AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) || !ah->ah_config.ath_hal_sta_update_tx_pwr_enable) { return; } old_greentx_status = AH9300(ah)->green_tx_status; if (ahp->ah_hw_green_tx_enable) { tmp_rss1_thr1 = AR9485_HW_GREEN_TX_THRES1_DB; tmp_rss1_thr2 = AR9485_HW_GREEN_TX_THRES2_DB; } else { tmp_rss1_thr1 = WB225_SW_GREEN_TX_THRES1_DB; tmp_rss1_thr2 = WB225_SW_GREEN_TX_THRES2_DB; } if ((ah->ah_config.ath_hal_sta_update_tx_pwr_enable_S1) && (rssi > tmp_rss1_thr1)) { if (old_greentx_status != HAL_RSSI_TX_POWER_SHORT) { AH9300(ah)->green_tx_status = HAL_RSSI_TX_POWER_SHORT; } } else if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable_S2 && (rssi > tmp_rss1_thr2)) { if (old_greentx_status != HAL_RSSI_TX_POWER_MIDDLE) { AH9300(ah)->green_tx_status = HAL_RSSI_TX_POWER_MIDDLE; } } else if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable_S3) { if (old_greentx_status != HAL_RSSI_TX_POWER_LONG) { AH9300(ah)->green_tx_status = HAL_RSSI_TX_POWER_LONG; } } /* If status is not change, don't do anything */ if (old_greentx_status == AH9300(ah)->green_tx_status) { return; } /* for Poseidon which ath_hal_sta_update_tx_pwr_enable is enabled */ if ((AH9300(ah)->green_tx_status != HAL_RSSI_TX_POWER_NONE) && AR_SREV_POSEIDON(ah)) { if (ahp->ah_hw_green_tx_enable) { switch (AH9300(ah)->green_tx_status) { case HAL_RSSI_TX_POWER_SHORT: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, ar9485_hw_gtx_tp_distance_short, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = 0; /* 2. Store OB/DB */ /* 3. Store TPC settting */ temp_tcp_reg_val = (SM(14, AR_TPC_ACK) | SM(14, AR_TPC_CTS) | SM(14, AR_TPC_CHIRP) | SM(14, AR_TPC_RPT)); /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = AR9485_BBPWRTXRATE9_HW_GREEN_TX_SHORT_VALUE; break; case HAL_RSSI_TX_POWER_MIDDLE: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, ar9485_hw_gtx_tp_distance_middle, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = 0; /* 2. Store OB/DB */ /* 3. Store TPC settting */ temp_tcp_reg_val = (SM(18, AR_TPC_ACK) | SM(18, AR_TPC_CTS) | SM(18, AR_TPC_CHIRP) | SM(18, AR_TPC_RPT)); /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = AR9485_BBPWRTXRATE9_HW_GREEN_TX_MIDDLE_VALUE; break; case HAL_RSSI_TX_POWER_LONG: default: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, ahp->ah_default_tx_power, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = 0; /* 2. Store OB/DB1/DB2 */ /* 3. Store TPC settting */ temp_tcp_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_TPC]; /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_BB_PWRTX_RATE9]; break; } } else { switch (AH9300(ah)->green_tx_status) { case HAL_RSSI_TX_POWER_SHORT: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, wb225_sw_gtx_tp_distance_short, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = wb225_gtx_olpc_cal_offset[WB225_OB_GREEN_TX_SHORT_VALUE] - wb225_gtx_olpc_cal_offset[WB225_OB_CALIBRATION_VALUE]; /* 2. Store OB/DB */ temp_obdb_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_OBDB]; temp_obdb_reg_val &= ~(AR_PHY_65NM_CH0_TXRF2_DB2G | AR_PHY_65NM_CH0_TXRF2_OB2G_CCK | AR_PHY_65NM_CH0_TXRF2_OB2G_PSK | AR_PHY_65NM_CH0_TXRF2_OB2G_QAM); temp_obdb_reg_val |= (SM(5, AR_PHY_65NM_CH0_TXRF2_DB2G) | SM(WB225_OB_GREEN_TX_SHORT_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_CCK) | SM(WB225_OB_GREEN_TX_SHORT_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_PSK) | SM(WB225_OB_GREEN_TX_SHORT_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_QAM)); /* 3. Store TPC settting */ temp_tcp_reg_val = (SM(6, AR_TPC_ACK) | SM(6, AR_TPC_CTS) | SM(6, AR_TPC_CHIRP) | SM(6, AR_TPC_RPT)); /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = WB225_BBPWRTXRATE9_SW_GREEN_TX_SHORT_VALUE; break; case HAL_RSSI_TX_POWER_MIDDLE: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, wb225_sw_gtx_tp_distance_middle, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = wb225_gtx_olpc_cal_offset[WB225_OB_GREEN_TX_MIDDLE_VALUE] - wb225_gtx_olpc_cal_offset[WB225_OB_CALIBRATION_VALUE]; /* 2. Store OB/DB */ temp_obdb_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_OBDB]; temp_obdb_reg_val &= ~(AR_PHY_65NM_CH0_TXRF2_DB2G | AR_PHY_65NM_CH0_TXRF2_OB2G_CCK | AR_PHY_65NM_CH0_TXRF2_OB2G_PSK | AR_PHY_65NM_CH0_TXRF2_OB2G_QAM); temp_obdb_reg_val |= (SM(5, AR_PHY_65NM_CH0_TXRF2_DB2G) | SM(WB225_OB_GREEN_TX_MIDDLE_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_CCK) | SM(WB225_OB_GREEN_TX_MIDDLE_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_PSK) | SM(WB225_OB_GREEN_TX_MIDDLE_VALUE, AR_PHY_65NM_CH0_TXRF2_OB2G_QAM)); /* 3. Store TPC settting */ temp_tcp_reg_val = (SM(14, AR_TPC_ACK) | SM(14, AR_TPC_CTS) | SM(14, AR_TPC_CHIRP) | SM(14, AR_TPC_RPT)); /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = WB225_BBPWRTXRATE9_SW_GREEN_TX_MIDDLE_VALUE; break; case HAL_RSSI_TX_POWER_LONG: default: /* 1. TxPower Config */ OS_MEMCPY(target_power_val_t, ahp->ah_default_tx_power, sizeof(target_power_val_t)); /* 1.1 Store OLPC Delta Calibration Offset*/ olpc_power_offset = wb225_gtx_olpc_cal_offset[WB225_OB_GREEN_TX_LONG_VALUE] - wb225_gtx_olpc_cal_offset[WB225_OB_CALIBRATION_VALUE]; /* 2. Store OB/DB1/DB2 */ temp_obdb_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_OBDB]; /* 3. Store TPC settting */ temp_tcp_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_TPC]; /* 4. Store BB_powertx_rate9 value */ temp_powertx_rate9_reg_val = AH9300(ah)->ah_ob_db1[POSEIDON_STORED_REG_BB_PWRTX_RATE9]; break; } } /* 1.1 Do OLPC Delta Calibration Offset */ tmp_olpc_val = (int8_t) AH9300(ah)->ah_db2[POSEIDON_STORED_REG_G2_OLPC_OFFSET]; tmp_olpc_val += olpc_power_offset; OS_REG_RMW(ah, AR_PHY_TPC_11_B0, (tmp_olpc_val << AR_PHY_TPC_OLPC_GAIN_DELTA_S), AR_PHY_TPC_OLPC_GAIN_DELTA); /* 1.2 TxPower Config */ ar9300_transmit_power_reg_write(ah, target_power_val_t); /* 2. Config OB/DB */ if (!ahp->ah_hw_green_tx_enable) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF2, temp_obdb_reg_val); } /* 3. config TPC settting */ OS_REG_WRITE(ah, AR_TPC, temp_tcp_reg_val); /* 4. config BB_powertx_rate9 value */ OS_REG_WRITE(ah, AR_PHY_BB_POWERTX_RATE9, temp_powertx_rate9_reg_val); } } #if 0 void ar9300_get_vow_stats( struct ath_hal *ah, HAL_VOWSTATS* p_stats, u_int8_t vow_reg_flags) { if (vow_reg_flags & AR_REG_TX_FRM_CNT) { p_stats->tx_frame_count = OS_REG_READ(ah, AR_TFCNT); } if (vow_reg_flags & AR_REG_RX_FRM_CNT) { p_stats->rx_frame_count = OS_REG_READ(ah, AR_RFCNT); } if (vow_reg_flags & AR_REG_RX_CLR_CNT) { p_stats->rx_clear_count = OS_REG_READ(ah, AR_RCCNT); } if (vow_reg_flags & AR_REG_CYCLE_CNT) { p_stats->cycle_count = OS_REG_READ(ah, AR_CCCNT); } if (vow_reg_flags & AR_REG_EXT_CYCLE_CNT) { p_stats->ext_cycle_count = OS_REG_READ(ah, AR_EXTRCCNT); } } #endif /* * ar9300_is_skip_paprd_by_greentx * * This function check if we need to skip PAPRD tuning * when GreenTx in specific state. */ HAL_BOOL ar9300_is_skip_paprd_by_greentx(struct ath_hal *ah) { if (AR_SREV_POSEIDON(ah) && ah->ah_config.ath_hal_sta_update_tx_pwr_enable && ((AH9300(ah)->green_tx_status == HAL_RSSI_TX_POWER_SHORT) || (AH9300(ah)->green_tx_status == HAL_RSSI_TX_POWER_MIDDLE))) { return AH_TRUE; } return AH_FALSE; } void ar9300_control_signals_for_green_tx_mode(struct ath_hal *ah) { unsigned int valid_obdb_0_b0 = 0x2d; // 5,5 - dB[0:2],oB[5:3] unsigned int valid_obdb_1_b0 = 0x25; // 4,5 - dB[0:2],oB[5:3] unsigned int valid_obdb_2_b0 = 0x1d; // 3,5 - dB[0:2],oB[5:3] unsigned int valid_obdb_3_b0 = 0x15; // 2,5 - dB[0:2],oB[5:3] unsigned int valid_obdb_4_b0 = 0xd; // 1,5 - dB[0:2],oB[5:3] struct ath_hal_9300 *ahp = AH9300(ah); if (AR_SREV_POSEIDON(ah) && ahp->ah_hw_green_tx_enable) { OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_VALID_OBDB_POSEIDON, AR_PHY_PAPRD_VALID_OBDB_0, valid_obdb_0_b0); OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_VALID_OBDB_POSEIDON, AR_PHY_PAPRD_VALID_OBDB_1, valid_obdb_1_b0); OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_VALID_OBDB_POSEIDON, AR_PHY_PAPRD_VALID_OBDB_2, valid_obdb_2_b0); OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_VALID_OBDB_POSEIDON, AR_PHY_PAPRD_VALID_OBDB_3, valid_obdb_3_b0); OS_REG_RMW_FIELD_ALT(ah, AR_PHY_PAPRD_VALID_OBDB_POSEIDON, AR_PHY_PAPRD_VALID_OBDB_4, valid_obdb_4_b0); } } void ar9300_hwgreentx_set_pal_spare(struct ath_hal *ah, int value) { struct ath_hal_9300 *ahp = AH9300(ah); if (AR_SREV_POSEIDON(ah) && ahp->ah_hw_green_tx_enable) { if ((value == 0) || (value == 1)) { OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, AR_PHY_65NM_CH0_TXRF3_OLD_PAL_SPARE, value); } } } void ar9300_reset_hw_beacon_proc_crc(struct ath_hal *ah) { OS_REG_SET_BIT(ah, AR_HWBCNPROC1, AR_HWBCNPROC1_RESET_CRC); } int32_t ar9300_get_hw_beacon_rssi(struct ath_hal *ah) { int32_t val = OS_REG_READ_FIELD(ah, AR_BCN_RSSI_AVE, AR_BCN_RSSI_AVE_VAL); /* RSSI format is 8.4. Ignore lowest four bits */ val = val >> 4; return val; } void ar9300_set_hw_beacon_rssi_threshold(struct ath_hal *ah, u_int32_t rssi_threshold) { struct ath_hal_9300 *ahp = AH9300(ah); OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_VAL, rssi_threshold); /* save value for restoring after chip reset */ ahp->ah_beacon_rssi_threshold = rssi_threshold; } void ar9300_reset_hw_beacon_rssi(struct ath_hal *ah) { OS_REG_SET_BIT(ah, AR_RSSI_THR, AR_RSSI_BCN_RSSI_RST); } void ar9300_set_hw_beacon_proc(struct ath_hal *ah, HAL_BOOL on) { if (on) { OS_REG_SET_BIT(ah, AR_HWBCNPROC1, AR_HWBCNPROC1_CRC_ENABLE | AR_HWBCNPROC1_EXCLUDE_TIM_ELM); } else { OS_REG_CLR_BIT(ah, AR_HWBCNPROC1, AR_HWBCNPROC1_CRC_ENABLE | AR_HWBCNPROC1_EXCLUDE_TIM_ELM); } } /* * Gets the contents of the specified key cache entry. */ HAL_BOOL ar9300_print_keycache(struct ath_hal *ah) { const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; u_int32_t key0, key1, key2, key3, key4; u_int32_t mac_hi, mac_lo; u_int16_t entry = 0; u_int32_t valid = 0; u_int32_t key_type; ath_hal_printf(ah, "Slot Key\t\t\t Valid Type Mac \n"); for (entry = 0 ; entry < p_cap->halKeyCacheSize; entry++) { key0 = OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)); key1 = OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)); key2 = OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)); key3 = OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)); key4 = OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)); key_type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)); mac_lo = OS_REG_READ(ah, AR_KEYTABLE_MAC0(entry)); mac_hi = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); if (mac_hi & AR_KEYTABLE_VALID) { valid = 1; } else { valid = 0; } if ((mac_hi != 0) && (mac_lo != 0)) { mac_hi &= ~0x8000; mac_hi <<= 1; mac_hi |= ((mac_lo & (1 << 31) )) >> 31; mac_lo <<= 1; } ath_hal_printf(ah, "%03d " "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" " %02d %02d " "%02x:%02x:%02x:%02x:%02x:%02x \n", entry, (key0 << 24) >> 24, (key0 << 16) >> 24, (key0 << 8) >> 24, key0 >> 24, (key1 << 24) >> 24, (key1 << 16) >> 24, //(key1 << 8) >> 24, key1 >> 24, (key2 << 24) >> 24, (key2 << 16) >> 24, (key2 << 8) >> 24, key2 >> 24, (key3 << 24) >> 24, (key3 << 16) >> 24, //(key3 << 8) >> 24, key3 >> 24, (key4 << 24) >> 24, (key4 << 16) >> 24, (key4 << 8) >> 24, key4 >> 24, valid, key_type, (mac_lo << 24) >> 24, (mac_lo << 16) >> 24, (mac_lo << 8) >> 24, (mac_lo) >> 24, (mac_hi << 24) >> 24, (mac_hi << 16) >> 24 ); } return AH_TRUE; } /* enable/disable smart antenna mode */ HAL_BOOL ar9300_set_smart_antenna(struct ath_hal *ah, HAL_BOOL enable) { struct ath_hal_9300 *ahp = AH9300(ah); if (enable) { OS_REG_SET_BIT(ah, AR_XRTO, AR_ENABLE_SMARTANTENNA); } else { OS_REG_CLR_BIT(ah, AR_XRTO, AR_ENABLE_SMARTANTENNA); } /* if scropion and smart antenna is enabled, write swcom1 with 0x440 * and swcom2 with 0 * FIXME Ideally these registers need to be made read from caldata. * Until the calibration team gets them, keep them along with board * configuration. */ if (enable && AR_SREV_SCORPION(ah) && (HAL_OK == ar9300_get_capability(ah, HAL_CAP_SMARTANTENNA, 0,0))) { OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0x440); OS_REG_WRITE(ah, AR_PHY_SWITCH_COM_2, 0); } ahp->ah_smartantenna_enable = enable; return 1; } #ifdef ATH_TX99_DIAG #ifndef ATH_SUPPORT_HTC void ar9300_tx99_channel_pwr_update(struct ath_hal *ah, HAL_CHANNEL *c, u_int32_t txpower) { #define PWR_MAS(_r, _s) (((_r) & 0x3f) << (_s)) static int16_t p_pwr_array[ar9300_rate_size] = { 0 }; int32_t i; /* The max power is limited to 63 */ if (txpower <= AR9300_MAX_RATE_POWER) { for (i = 0; i < ar9300_rate_size; i++) { p_pwr_array[i] = txpower; } } else { for (i = 0; i < ar9300_rate_size; i++) { p_pwr_array[i] = AR9300_MAX_RATE_POWER; } } OS_REG_WRITE(ah, 0xa458, 0); /* Write the OFDM power per rate set */ /* 6 (LSB), 9, 12, 18 (MSB) */ OS_REG_WRITE(ah, 0xa3c0, PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) ); /* 24 (LSB), 36, 48, 54 (MSB) */ OS_REG_WRITE(ah, 0xa3c4, PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_54], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_48], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_36], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) ); /* Write the CCK power per rate set */ /* 1L (LSB), reserved, 2L, 2S (MSB) */ OS_REG_WRITE(ah, 0xa3c8, PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) /* | PWR_MAS(txPowerTimes2, 8) */ /* this is reserved for Osprey */ | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) ); /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ OS_REG_WRITE(ah, 0xa3cc, PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) ); /* Write the HT20 power per rate set */ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ OS_REG_WRITE(ah, 0xa3d0, PWR_MAS(p_pwr_array[ALL_TARGET_HT20_5], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_4], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0) ); /* 6 (LSB), 7, 12, 13 (MSB) */ OS_REG_WRITE(ah, 0xa3d4, PWR_MAS(p_pwr_array[ALL_TARGET_HT20_13], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_12], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_7], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_6], 0) ); /* 14 (LSB), 15, 20, 21 */ OS_REG_WRITE(ah, 0xa3e4, PWR_MAS(p_pwr_array[ALL_TARGET_HT20_21], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_20], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_15], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_14], 0) ); /* Mixed HT20 and HT40 rates */ /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ OS_REG_WRITE(ah, 0xa3e8, PWR_MAS(p_pwr_array[ALL_TARGET_HT40_23], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_22], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_23], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT20_22], 0) ); /* Write the HT40 power per rate set */ /* correct PAR difference between HT40 and HT20/LEGACY */ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ OS_REG_WRITE(ah, 0xa3d8, PWR_MAS(p_pwr_array[ALL_TARGET_HT40_5], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_4], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0) ); /* 6 (LSB), 7, 12, 13 (MSB) */ OS_REG_WRITE(ah, 0xa3dc, PWR_MAS(p_pwr_array[ALL_TARGET_HT40_13], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_12], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_7], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_6], 0) ); /* 14 (LSB), 15, 20, 21 */ OS_REG_WRITE(ah, 0xa3ec, PWR_MAS(p_pwr_array[ALL_TARGET_HT40_21], 24) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_20], 16) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_15], 8) | PWR_MAS(p_pwr_array[ALL_TARGET_HT40_14], 0) ); #undef PWR_MAS } void ar9300_tx99_chainmsk_setup(struct ath_hal *ah, int tx_chainmask) { if (tx_chainmask == 0x5) { OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) | AR_PHY_SWAP_ALT_CHAIN); } OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, tx_chainmask); OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, tx_chainmask); OS_REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); if (tx_chainmask == 0x5) { OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, OS_REG_READ(ah, AR_PHY_ANALOG_SWAP) | AR_PHY_SWAP_ALT_CHAIN); } } void ar9300_tx99_set_single_carrier(struct ath_hal *ah, int tx_chain_mask, int chtype) { OS_REG_WRITE(ah, 0x98a4, OS_REG_READ(ah, 0x98a4) | (0x7ff << 11) | 0x7ff); OS_REG_WRITE(ah, 0xa364, OS_REG_READ(ah, 0xa364) | (1 << 7) | (1 << 1)); OS_REG_WRITE(ah, 0xa350, (OS_REG_READ(ah, 0xa350) | (1 << 31) | (1 << 15)) & ~(1 << 13)); /* 11G mode */ if (!chtype) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2) | (0x1 << 3) | (0x1 << 2)); if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP2, (OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP2) | (0x1 << 26) | (0x7 << 24)) & ~(0x1 << 22)); } else { OS_REG_WRITE(ah, AR_HORNET_CH0_TOP, OS_REG_READ(ah, AR_HORNET_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_HORNET_CH0_TOP2, (OS_REG_READ(ah, AR_HORNET_CH0_TOP2) | (0x1 << 26) | (0x7 << 24)) & ~(0x1 << 22)); } /* chain zero */ if ((tx_chain_mask & 0x01) == 0x01) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX1) | (0x1 << 31) | (0x5 << 15) | (0x3 << 9)) & ~(0x1 << 27) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7)) & ~(0x1 << 11)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH0_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH0_BB2) | (0x1 << 31)); } if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { /* chain one */ if ((tx_chain_mask & 0x02) == 0x02 ) { OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX1) | (0x1 << 31) | (0x5 << 15) | (0x3 << 9)) & ~(0x1 << 27) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7)) & ~(0x1 << 11)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH1_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH1_BB2) | (0x1 << 31)); } } if (AR_SREV_OSPREY(ah)) { /* chain two */ if ((tx_chain_mask & 0x04) == 0x04 ) { OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX1) | (0x1 << 31) | (0x5 << 15) | (0x3 << 9)) & ~(0x1 << 27) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7)) & ~(0x1 << 11)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH2_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH2_BB2) | (0x1 << 31)); } } OS_REG_WRITE(ah, 0xa28c, 0x11111); OS_REG_WRITE(ah, 0xa288, 0x111); } else { /* chain zero */ if ((tx_chain_mask & 0x01) == 0x01) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX1) | (0x1 << 31) | (0x1 << 27) | (0x3 << 23) | (0x1 << 19) | (0x1 << 15) | (0x3 << 9)) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 11)& ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF2, OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF2) | (0x3 << 3) | (0x3 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF3, (OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF3) | (0x3 << 29) | (0x3 << 26) | (0x2 << 23) | (0x2 << 20) | (0x2 << 17))& ~(0x1 << 14)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH0_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH0_BB2) | (0x1 << 31)); if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP2, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } else { OS_REG_WRITE(ah, AR_HORNET_CH0_TOP, OS_REG_READ(ah, AR_HORNET_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_HORNET_CH0_TOP2, OS_REG_READ(ah, AR_HORNET_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF1) | (0x1 << 23)); } if (AR_SREV_OSPREY(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF1) | (0x1 << 23)); } } if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { /* chain one */ if ((tx_chain_mask & 0x02) == 0x02 ) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF1) | (0x1 << 23)); if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP2, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } else { OS_REG_WRITE(ah, AR_HORNET_CH0_TOP, OS_REG_READ(ah, AR_HORNET_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_HORNET_CH0_TOP2, OS_REG_READ(ah, AR_HORNET_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX1) | (0x1 << 31) | (0x1 << 27) | (0x3 << 23) | (0x1 << 19) | (0x1 << 15) | (0x3 << 9)) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 11)& ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF2, OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF2) | (0x3 << 3) | (0x3 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF3, (OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF3) | (0x3 << 29) | (0x3 << 26) | (0x2 << 23) | (0x2 << 20) | (0x2 << 17))& ~(0x1 << 14)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH1_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH1_BB2) | (0x1 << 31)); if (AR_SREV_OSPREY(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF1) | (0x1 << 23)); } } } if (AR_SREV_OSPREY(ah)) { /* chain two */ if ((tx_chain_mask & 0x04) == 0x04 ) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF1) | (0x1 << 23)); if (AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_PHY_65NM_CH0_TOP2, OS_REG_READ(ah, AR_PHY_65NM_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } else { OS_REG_WRITE(ah, AR_HORNET_CH0_TOP, OS_REG_READ(ah, AR_HORNET_CH0_TOP) & ~(0x1 << 4)); OS_REG_WRITE(ah, AR_HORNET_CH0_TOP2, OS_REG_READ(ah, AR_HORNET_CH0_TOP2) | (0x1 << 26) | (0x7 << 24) | (0x3 << 22)); } OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX2) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX3, OS_REG_READ(ah, AR_PHY_65NM_CH1_RXTX3) | (0x1 << 19) | (0x1 << 3)); OS_REG_WRITE(ah, AR_PHY_65NM_CH1_TXRF1, OS_REG_READ(ah, AR_PHY_65NM_CH1_TXRF1) | (0x1 << 23)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX1, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX1) | (0x1 << 31) | (0x1 << 27) | (0x3 << 23) | (0x1 << 19) | (0x1 << 15) | (0x3 << 9)) & ~(0x1 << 12)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX2, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX2) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 7) | (0x1 << 3) | (0x1 << 2) | (0x1 << 1)) & ~(0x1 << 11)& ~(0x1 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_RXTX3, (OS_REG_READ(ah, AR_PHY_65NM_CH2_RXTX3) | (0x1 << 29) | (0x1 << 25) | (0x1 << 23) | (0x1 << 19) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 3)) & ~(0x1 << 28)& ~(0x1 << 24) & ~(0x1 << 22)& ~(0x1 << 7)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF1, (OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF1) | (0x1 << 23))& ~(0x1 << 21)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF2, OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF2) | (0x3 << 3) | (0x3 << 0)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_TXRF3, (OS_REG_READ(ah, AR_PHY_65NM_CH2_TXRF3) | (0x3 << 29) | (0x3 << 26) | (0x2 << 23) | (0x2 << 20) | (0x2 << 17))& ~(0x1 << 14)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, OS_REG_READ(ah, AR_PHY_65NM_CH2_BB1) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (0x1 << 6) | (0x1 << 5) | (0x1 << 4) | (0x1 << 3) | (0x1 << 2)); OS_REG_WRITE(ah, AR_PHY_65NM_CH2_BB2, OS_REG_READ(ah, AR_PHY_65NM_CH2_BB2) | (0x1 << 31)); } } OS_REG_WRITE(ah, 0xa28c, 0x22222); OS_REG_WRITE(ah, 0xa288, 0x222); } } void ar9300_tx99_start(struct ath_hal *ah, u_int8_t *data) { u_int32_t val; u_int32_t qnum = (u_int32_t)data; /* Disable AGC to A2 */ OS_REG_WRITE(ah, AR_PHY_TEST, (OS_REG_READ(ah, AR_PHY_TEST) | PHY_AGC_CLR)); - OS_REG_WRITE(ah, 0x9864, OS_REG_READ(ah, 0x9864) | 0x7f000); - OS_REG_WRITE(ah, 0x9924, OS_REG_READ(ah, 0x9924) | 0x7f00fe); OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS); OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* set receive disable */ /* set CW_MIN and CW_MAX both to 0, AIFS=2 */ OS_REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20); /* 50 OK */ OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20); /* 200 ok for HT20, 400 ok for HT40 */ OS_REG_WRITE(ah, AR_TIME_OUT, 0x00000400); OS_REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff); /* set QCU modes to early termination */ val = OS_REG_READ(ah, AR_QMISC(qnum)); OS_REG_WRITE(ah, AR_QMISC(qnum), val | AR_Q_MISC_DCU_EARLY_TERM_REQ); } void ar9300_tx99_stop(struct ath_hal *ah) { /* this should follow the setting of start */ OS_REG_WRITE(ah, AR_PHY_TEST, OS_REG_READ(ah, AR_PHY_TEST) &~ PHY_AGC_CLR); OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) | AR_DIAG_RX_DIS); } #endif /* ATH_TX99_DIAG */ #endif /* ATH_SUPPORT_HTC */ HAL_BOOL ar9300Get3StreamSignature(struct ath_hal *ah) { return AH_FALSE; } HAL_BOOL ar9300ForceVCS(struct ath_hal *ah) { return AH_FALSE; } HAL_BOOL ar9300SetDfs3StreamFix(struct ath_hal *ah, u_int32_t val) { return AH_FALSE; +} + +HAL_BOOL +ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array) +{ + struct ath_hal_9300 *ahp = AH9300(ah); + ar9300_eeprom_t *p_eep_data = &ahp->ah_eeprom; + u_int8_t *ctl_index; + u_int32_t offset = 0; + + if (!ctl_array) + return AH_FALSE; + + /* copy 2G ctl freqbin and power data */ + ctl_index = p_eep_data->ctl_index_2g; + OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_2G, ctl_array, + OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G + /* ctl_freqbin_2G */ + OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G)); /* ctl_power_data_2g */ + offset = (OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G) + + ( OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G)); + + + /* copy 2G ctl freqbin and power data */ + ctl_index = p_eep_data->ctl_index_5g; + OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_5G, ctl_array + offset, + OSPREY_NUM_CTLS_5G * OSPREY_NUM_BAND_EDGES_5G + /* ctl_freqbin_5G */ + OSPREY_NUM_CTLS_5G * sizeof(OSP_CAL_CTL_DATA_5G)); /* ctl_power_data_5g */ + + return AH_FALSE; +} + +void +ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask) +{ + struct ath_hal_9300 *ahp = AH9300(ah); + + /* optional txchainmask should be subset of primary txchainmask */ + if ((mask & ahp->ah_tx_chainmask) != mask) { + ahp->ah_tx_chainmaskopt = 0; + ath_hal_printf(ah, "Error: ah_tx_chainmask=%d, mask=%d\n", ahp->ah_tx_chainmask, mask); + return; + } + + ahp->ah_tx_chainmaskopt = mask; } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini (revision 278741) @@ -1,2188 +1,2188 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ static const u_int32_t ar9300_osprey_2p2_mac_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00008014 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 }, { 0x0000801c , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 }, }; static const u_int32_t ar9300Modes_low_ob_db_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x52022470 , 0x52022470 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x55022490 , 0x55022490 , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x59022492 , 0x59022492 , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x5d022692 , 0x5d022692 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x61022892 , 0x61022892 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x65024890 , 0x65024890 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x69024892 , 0x69024892 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6e024c92 , 0x6e024c92 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x52822470 , 0x52822470 , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x55822490 , 0x55822490 , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x59822492 , 0x59822492 , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x5d822692 , 0x5d822692 , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x61822892 , 0x61822892 , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x65824890 , 0x65824890 , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x69824892 , 0x69824892 , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x6e824c92 , 0x6e824c92 , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x02004000 , 0x02004000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x02004801 , 0x02004801 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02808a02 , 0x02808a02 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0380ce03 , 0x0380ce03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04411104 , 0x04411104 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04411104 , 0x04411104 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_osprey_2p2_baseband_core_emulation[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafa68e30 }, { 0x00009884 , 0x00002842 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009e50 , 0x00000000 }, { 0x00009fcc , 0x00000014 }, { 0x0000a344 , 0x00000010 }, { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x71733d01 }, { 0x0000a3a0 , 0xd0ad5c12 }, { 0x0000a3c0 , 0x22222220 }, { 0x0000a3c4 , 0x22222222 }, { 0x0000a404 , 0x00418a11 }, { 0x0000a418 , 0x050001ce }, { 0x0000a438 , 0x00001800 }, { 0x0000a458 , 0x01444452 }, { 0x0000a690 , 0x00000038 }, { 0x0000b8dc , 0x00400000 }, }; static const u_int32_t ar9300_osprey_2p2_radio_core[][2] = { /* Addr allmodes */ { 0x00016000 , 0x36db6db6 }, { 0x00016004 , 0x6db6db40 }, { 0x00016008 , 0x73f00000 }, { 0x0001600c , 0x00000000 }, { 0x00016040 , 0x7f80fff8 }, { 0x0001604c , 0x76d005b5 }, { 0x00016050 , 0x556cf031 }, { 0x00016054 , 0x13449440 }, { 0x00016058 , 0x0c51c92c }, { 0x0001605c , 0x3db7fffc }, { 0x00016060 , 0xfffffffc }, { 0x00016064 , 0x000f0278 }, { 0x0001606c , 0x6db60000 }, { 0x00016080 , 0x00000000 }, { 0x00016084 , 0x0e48048c }, { 0x00016088 , 0x54214514 }, { 0x0001608c , 0x119f481e }, { 0x00016090 , 0x24926490 }, { 0x00016098 , 0xd2888888 }, { 0x000160a0 , 0x0a108ffe }, { 0x000160a4 , 0x812fc370 }, { 0x000160a8 , 0x423c8000 }, { 0x000160b4 , 0x92480080 }, { 0x000160c0 , 0x00adb6d0 }, { 0x000160c4 , 0x6db6db60 }, { 0x000160c8 , 0x6db6db6c }, { 0x000160cc , 0x01e6c000 }, { 0x00016100 , 0x3fffbe01 }, { 0x00016104 , 0xfff80000 }, { 0x00016108 , 0x00080010 }, { 0x00016144 , 0x02084080 }, { 0x00016148 , 0x00000000 }, { 0x00016280 , 0x058a0001 }, { 0x00016284 , 0x3d840208 }, { 0x00016288 , 0x05a20408 }, { 0x0001628c , 0x00038c07 }, { 0x00016290 , 0x00000004 }, { 0x00016294 , 0x458a214f }, { 0x00016380 , 0x00000000 }, { 0x00016384 , 0x00000000 }, { 0x00016388 , 0x00800700 }, { 0x0001638c , 0x00800700 }, { 0x00016390 , 0x00800700 }, { 0x00016394 , 0x00000000 }, { 0x00016398 , 0x00000000 }, { 0x0001639c , 0x00000000 }, { 0x000163a0 , 0x00000001 }, { 0x000163a4 , 0x00000001 }, { 0x000163a8 , 0x00000000 }, { 0x000163ac , 0x00000000 }, { 0x000163b0 , 0x00000000 }, { 0x000163b4 , 0x00000000 }, { 0x000163b8 , 0x00000000 }, { 0x000163bc , 0x00000000 }, { 0x000163c0 , 0x000000a0 }, { 0x000163c4 , 0x000c0000 }, { 0x000163c8 , 0x14021402 }, { 0x000163cc , 0x00001402 }, { 0x000163d0 , 0x00000000 }, { 0x000163d4 , 0x00000000 }, { 0x00016400 , 0x36db6db6 }, { 0x00016404 , 0x6db6db40 }, { 0x00016408 , 0x73f00000 }, { 0x0001640c , 0x00000000 }, { 0x00016440 , 0x7f80fff8 }, { 0x0001644c , 0x76d005b5 }, { 0x00016450 , 0x556cf031 }, { 0x00016454 , 0x13449440 }, { 0x00016458 , 0x0c51c92c }, { 0x0001645c , 0x3db7fffc }, { 0x00016460 , 0xfffffffc }, { 0x00016464 , 0x000f0278 }, { 0x0001646c , 0x6db60000 }, { 0x00016500 , 0x3fffbe01 }, { 0x00016504 , 0xfff80000 }, { 0x00016508 , 0x00080010 }, { 0x00016544 , 0x02084080 }, { 0x00016548 , 0x00000000 }, { 0x00016780 , 0x00000000 }, { 0x00016784 , 0x00000000 }, { 0x00016788 , 0x00800700 }, { 0x0001678c , 0x00800700 }, { 0x00016790 , 0x00800700 }, { 0x00016794 , 0x00000000 }, { 0x00016798 , 0x00000000 }, { 0x0001679c , 0x00000000 }, { 0x000167a0 , 0x00000001 }, { 0x000167a4 , 0x00000001 }, { 0x000167a8 , 0x00000000 }, { 0x000167ac , 0x00000000 }, { 0x000167b0 , 0x00000000 }, { 0x000167b4 , 0x00000000 }, { 0x000167b8 , 0x00000000 }, { 0x000167bc , 0x00000000 }, { 0x000167c0 , 0x000000a0 }, { 0x000167c4 , 0x000c0000 }, { 0x000167c8 , 0x14021402 }, { 0x000167cc , 0x00001402 }, { 0x000167d0 , 0x00000000 }, { 0x000167d4 , 0x00000000 }, { 0x00016800 , 0x36db6db6 }, { 0x00016804 , 0x6db6db40 }, { 0x00016808 , 0x73f00000 }, { 0x0001680c , 0x00000000 }, { 0x00016840 , 0x7f80fff8 }, { 0x0001684c , 0x76d005b5 }, { 0x00016850 , 0x556cf031 }, { 0x00016854 , 0x13449440 }, { 0x00016858 , 0x0c51c92c }, { 0x0001685c , 0x3db7fffc }, { 0x00016860 , 0xfffffffc }, { 0x00016864 , 0x000f0278 }, { 0x0001686c , 0x6db60000 }, { 0x00016900 , 0x3fffbe01 }, { 0x00016904 , 0xfff80000 }, { 0x00016908 , 0x00080010 }, { 0x00016944 , 0x02084080 }, { 0x00016948 , 0x00000000 }, { 0x00016b80 , 0x00000000 }, { 0x00016b84 , 0x00000000 }, { 0x00016b88 , 0x00800700 }, { 0x00016b8c , 0x00800700 }, { 0x00016b90 , 0x00800700 }, { 0x00016b94 , 0x00000000 }, { 0x00016b98 , 0x00000000 }, { 0x00016b9c , 0x00000000 }, { 0x00016ba0 , 0x00000001 }, { 0x00016ba4 , 0x00000001 }, { 0x00016ba8 , 0x00000000 }, { 0x00016bac , 0x00000000 }, { 0x00016bb0 , 0x00000000 }, { 0x00016bb4 , 0x00000000 }, { 0x00016bb8 , 0x00000000 }, { 0x00016bbc , 0x00000000 }, { 0x00016bc0 , 0x000000a0 }, { 0x00016bc4 , 0x000c0000 }, { 0x00016bc8 , 0x14021402 }, { 0x00016bcc , 0x00001402 }, { 0x00016bd0 , 0x00000000 }, { 0x00016bd4 , 0x00000000 }, }; static const u_int32_t ar9300_osprey_2p2_tx_gain_table_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a410 , 0x000000d5 , 0x000000d5 , 0x000000d5 , 0x000000d5 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x00004002 , 0x00004002 , 0x00004002 , 0x00004002 }, { 0x0000a508 , 0x00008004 , 0x00008004 , 0x00008004 , 0x00008004 }, { 0x0000a510 , 0x0001000c , 0x0001000c , 0x0001000c , 0x0001000c }, { 0x0000a514 , 0x0001420b , 0x0001420b , 0x0001420b , 0x0001420b }, { 0x0000a518 , 0x0001824a , 0x0001824a , 0x0001824a , 0x0001824a }, { 0x0000a51c , 0x0001c44a , 0x0001c44a , 0x0001c44a , 0x0001c44a }, { 0x0000a520 , 0x0002064a , 0x0002064a , 0x0002064a , 0x0002064a }, { 0x0000a524 , 0x0002484a , 0x0002484a , 0x0002484a , 0x0002484a }, { 0x0000a528 , 0x00028a4a , 0x00028a4a , 0x00028a4a , 0x00028a4a }, { 0x0000a52c , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a }, { 0x0000a530 , 0x00030e4a , 0x00030e4a , 0x00030e4a , 0x00030e4a }, { 0x0000a534 , 0x00034e8a , 0x00034e8a , 0x00034e8a , 0x00034e8a }, }; static const u_int32_t ar9300_osprey_2p2_baseband_postamble_dfs_channel[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00009824 , 0x5ac668d0 , 0x5ac668d0 }, { 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 }, { 0x00009e14 , 0x37b9625e , 0x37b9625e }, }; static const u_int32_t ar9300Modes_fast_clock_osprey_2p2[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00001030 , 0x00000268 , 0x000004d0 }, { 0x00001070 , 0x0000018c , 0x00000318 }, { 0x000010b0 , 0x00000fd0 , 0x00001fa0 }, { 0x00008014 , 0x044c044c , 0x08980898 }, { 0x0000801c , 0x148ec02b , 0x148ec057 }, { 0x00008318 , 0x000044c0 , 0x00008980 }, { 0x00009e00 , 0x0372131c , 0x0372131c }, { 0x0000a230 , 0x0000000b , 0x00000016 }, { 0x0000a254 , 0x00000898 , 0x00001130 }, }; static const u_int32_t ar9300_osprey_2p2_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0001609c , 0x0dd08f29 , 0x0dd08f29 , 0x0b283f31 , 0x0b283f31 }, { 0x000160ac , 0xa4653c00 , 0xa4653c00 , 0x24652800 , 0x24652800 }, { 0x000160b0 , 0x03284f3e , 0x03284f3e , 0x05d08f20 , 0x05d08f20 }, { 0x0001610c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016140 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, { 0x0001650c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016540 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, { 0x0001690c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016940 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, }; static const u_int32_t ar9300_modes_number_5_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x15000028 , 0x15000028 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1b00002b , 0x1b00002b , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x1f020028 , 0x1f020028 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x2502002b , 0x2502002b , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2a04002a , 0x2a04002a , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2e06002a , 0x2e06002a , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x3302202d , 0x3302202d , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3804202c , 0x3804202c , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3c06202c , 0x3c06202c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4108202d , 0x4108202d , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4506402d , 0x4506402d , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4906222d , 0x4906222d , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4d062231 , 0x4d062231 , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x50082231 , 0x50082231 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5608422e , 0x5608422e , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5e08442e , 0x5e08442e , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x620a4431 , 0x620a4431 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x640a4432 , 0x640a4432 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x680a4434 , 0x680a4434 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x6c0a6434 , 0x6c0a6434 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6f0a6633 , 0x6f0a6633 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01804601 , 0x01804601 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01804601 , 0x01804601 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x01804601 , 0x01804601 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x03408d02 , 0x03408d02 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x03410d04 , 0x03410d04 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_osprey_2p2_mac_core_emulation[][2] = { /* Addr allmodes */ { 0x00000030 , 0x00020085 }, { 0x00000044 , 0x00000008 }, { 0x0000805c , 0xffffc7ff }, { 0x00008344 , 0xaa4a105b }, }; static const u_int32_t ar9300_osprey_2p2_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00009e3c , 0xcf946221 , 0xcf946221 , 0xcf946221 , 0xcf946221 }, { 0x00009e44 , 0x005c0000 , 0x005c0000 , 0x005c0000 , 0x005c0000 }, { 0x0000a258 , 0x02020200 , 0x02020200 , 0x02020200 , 0x02020200 }, { 0x0000a25c , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a28c , 0x00011111 , 0x00011111 , 0x00011111 , 0x00011111 }, { 0x0000a2c4 , 0x00148d18 , 0x00148d18 , 0x00148d20 , 0x00148d20 }, { 0x0000a2d8 , 0xf999a801 , 0xf999a801 , 0xf999a80d , 0xf999a80d }, { 0x0000a50c , 0x0000c00a , 0x0000c00a , 0x0000c00a , 0x0000c00a }, { 0x0000a538 , 0x00038e8c , 0x00038e8c , 0x00038e8c , 0x00038e8c }, { 0x0000a53c , 0x0003cecc , 0x0003cecc , 0x0003cecc , 0x0003cecc }, { 0x0000a540 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 }, { 0x0000a544 , 0x00044edc , 0x00044edc , 0x00044edc , 0x00044edc }, { 0x0000a548 , 0x00048ede , 0x00048ede , 0x00048ede , 0x00048ede }, { 0x0000a54c , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e }, { 0x0000a550 , 0x00050f5e , 0x00050f5e , 0x00050f5e , 0x00050f5e }, { 0x0000a554 , 0x00054f9e , 0x00054f9e , 0x00054f9e , 0x00054f9e }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000be18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, }; static const u_int32_t ar9300_osprey_2p2_baseband_core[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafe68e30 }, { 0x00009804 , 0xfd14e000 }, { 0x00009808 , 0x9c0a9f6b }, { 0x0000980c , 0x04900000 }, { 0x00009814 , 0x9280c00a }, { 0x00009818 , 0x00000000 }, { 0x0000981c , 0x00020028 }, { 0x00009834 , 0x6400a190 }, { 0x00009838 , 0x0108ecff }, { 0x0000983c , 0x14000600 }, { 0x00009880 , 0x201fff00 }, { 0x00009884 , 0x00001042 }, { 0x000098a4 , 0x00200400 }, { 0x000098b0 , 0x32840bbe }, { 0x000098d0 , 0x004b6a8e }, { 0x000098d4 , 0x00000820 }, { 0x000098dc , 0x00000000 }, { 0x000098f0 , 0x00000000 }, { 0x000098f4 , 0x00000000 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009c0c , 0x00000000 }, { 0x00009c10 , 0x00000000 }, { 0x00009c14 , 0x00046384 }, { 0x00009c18 , 0x05b6b440 }, { 0x00009c1c , 0x00b6b440 }, { 0x00009d00 , 0xc080a333 }, { 0x00009d04 , 0x40206c10 }, { 0x00009d08 , 0x009c4060 }, { 0x00009d0c , 0x9883800a }, { 0x00009d10 , 0x01834061 }, { 0x00009d14 , 0x00c0040b }, { 0x00009d18 , 0x00000000 }, { 0x00009e08 , 0x0038230c }, { 0x00009e24 , 0x990bb515 }, { 0x00009e28 , 0x0c6f0000 }, { 0x00009e30 , 0x06336f77 }, { 0x00009e34 , 0x6af6532f }, { 0x00009e38 , 0x0cc80c00 }, { 0x00009e40 , 0x0d261820 }, { 0x00009e4c , 0x00001004 }, { 0x00009e50 , 0x00ff03f1 }, { 0x00009e54 , 0x00000000 }, { 0x00009fc0 , 0x803e4788 }, { 0x00009fc4 , 0x0001efb5 }, { 0x00009fcc , 0x40000014 }, { 0x00009fd0 , 0x01193b93 }, { 0x0000a20c , 0x00000000 }, { 0x0000a220 , 0x00000000 }, { 0x0000a224 , 0x00000000 }, { 0x0000a228 , 0x10002310 }, { 0x0000a23c , 0x00000000 }, { 0x0000a244 , 0x0c000000 }, { 0x0000a2a0 , 0x00000001 }, { 0x0000a2c0 , 0x00000001 }, { 0x0000a2c8 , 0x00000000 }, { 0x0000a2cc , 0x18c43433 }, { 0x0000a2d4 , 0x00000000 }, { 0x0000a2ec , 0x00000000 }, { 0x0000a2f0 , 0x00000000 }, { 0x0000a2f4 , 0x00000000 }, { 0x0000a2f8 , 0x00000000 }, { 0x0000a344 , 0x00000000 }, { 0x0000a34c , 0x00000000 }, { 0x0000a350 , 0x0000a000 }, { 0x0000a364 , 0x00000000 }, { 0x0000a370 , 0x00000000 }, { 0x0000a390 , 0x00000001 }, { 0x0000a394 , 0x00000444 }, { 0x0000a398 , 0x001f0e0f }, { 0x0000a39c , 0x0075393f }, { 0x0000a3a0 , 0xb79f6427 }, { 0x0000a3a4 , 0x00000000 }, { 0x0000a3a8 , 0xaaaaaaaa }, { 0x0000a3ac , 0x3c466478 }, { 0x0000a3c0 , 0x20202020 }, { 0x0000a3c4 , 0x22222220 }, { 0x0000a3c8 , 0x20200020 }, { 0x0000a3cc , 0x20202020 }, { 0x0000a3d0 , 0x20202020 }, { 0x0000a3d4 , 0x20202020 }, { 0x0000a3d8 , 0x20202020 }, { 0x0000a3dc , 0x20202020 }, { 0x0000a3e0 , 0x20202020 }, { 0x0000a3e4 , 0x20202020 }, { 0x0000a3e8 , 0x20202020 }, { 0x0000a3ec , 0x20202020 }, { 0x0000a3f0 , 0x00000000 }, { 0x0000a3f4 , 0x00000000 }, { 0x0000a3f8 , 0x0c9bd380 }, { 0x0000a3fc , 0x000f0f01 }, { 0x0000a400 , 0x8fa91f01 }, { 0x0000a404 , 0x00000000 }, { 0x0000a408 , 0x0e79e5c6 }, { 0x0000a40c , 0x00820820 }, { 0x0000a414 , 0x1ce739ce }, { 0x0000a418 , 0x2d001dce }, { 0x0000a41c , 0x1ce739ce }, { 0x0000a420 , 0x000001ce }, { 0x0000a424 , 0x1ce739ce }, { 0x0000a428 , 0x000001ce }, { 0x0000a42c , 0x1ce739ce }, { 0x0000a430 , 0x1ce739ce }, { 0x0000a434 , 0x00000000 }, { 0x0000a438 , 0x00001801 }, { 0x0000a43c , 0x00100000 }, { 0x0000a440 , 0x00000000 }, { 0x0000a444 , 0x00000000 }, { 0x0000a448 , 0x05000080 }, { 0x0000a44c , 0x00000001 }, { 0x0000a450 , 0x00010000 }, { 0x0000a458 , 0x00000000 }, { 0x0000a640 , 0x00000000 }, { 0x0000a644 , 0x3fad9d74 }, { 0x0000a648 , 0x0048060a }, { 0x0000a64c , 0x00003c37 }, { 0x0000a670 , 0x03020100 }, { 0x0000a674 , 0x09080504 }, { 0x0000a678 , 0x0d0c0b0a }, { 0x0000a67c , 0x13121110 }, { 0x0000a680 , 0x31301514 }, { 0x0000a684 , 0x35343332 }, { 0x0000a688 , 0x00000036 }, { 0x0000a690 , 0x00000838 }, { 0x0000a7c0 , 0x00000000 }, { 0x0000a7c4 , 0xfffffffc }, { 0x0000a7c8 , 0x00000000 }, { 0x0000a7cc , 0x00000000 }, { 0x0000a7d0 , 0x00000000 }, { 0x0000a7d4 , 0x00000004 }, { 0x0000a7dc , 0x00000001 }, { 0x0000a8d0 , 0x004b6a8e }, { 0x0000a8d4 , 0x00000820 }, { 0x0000a8dc , 0x00000000 }, { 0x0000a8f0 , 0x00000000 }, { 0x0000a8f4 , 0x00000000 }, { 0x0000b2d0 , 0x00000080 }, { 0x0000b2d4 , 0x00000000 }, { 0x0000b2ec , 0x00000000 }, { 0x0000b2f0 , 0x00000000 }, { 0x0000b2f4 , 0x00000000 }, { 0x0000b2f8 , 0x00000000 }, { 0x0000b408 , 0x0e79e5c0 }, { 0x0000b40c , 0x00820820 }, { 0x0000b420 , 0x00000000 }, { 0x0000b8d0 , 0x004b6a8e }, { 0x0000b8d4 , 0x00000820 }, { 0x0000b8dc , 0x00000000 }, { 0x0000b8f0 , 0x00000000 }, { 0x0000b8f4 , 0x00000000 }, { 0x0000c2d0 , 0x00000080 }, { 0x0000c2d4 , 0x00000000 }, { 0x0000c2ec , 0x00000000 }, { 0x0000c2f0 , 0x00000000 }, { 0x0000c2f4 , 0x00000000 }, { 0x0000c2f8 , 0x00000000 }, { 0x0000c408 , 0x0e79e5c0 }, { 0x0000c40c , 0x00820820 }, { 0x0000c420 , 0x00000000 }, }; static const u_int32_t ar9300Modes_high_ob_db_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d4 , 0x000050d4 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x04002222 , 0x04002222 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x09002421 , 0x09002421 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x0d002621 , 0x0d002621 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x13004620 , 0x13004620 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x19004a20 , 0x19004a20 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x1d004e20 , 0x1d004e20 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x21005420 , 0x21005420 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x26005e20 , 0x26005e20 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2b005e40 , 0x2b005e40 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x2f005e42 , 0x2f005e42 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x33005e44 , 0x33005e44 , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x38005e65 , 0x38005e65 , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x3c005e69 , 0x3c005e69 , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x40005e6b , 0x40005e6b , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x44005e6d , 0x44005e6d , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x49005e72 , 0x49005e72 , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x4e005eb2 , 0x4e005eb2 , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x53005f12 , 0x53005f12 , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x59025eb2 , 0x59025eb2 , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x5e025f12 , 0x5e025f12 , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x61027f12 , 0x61027f12 , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6702bf12 , 0x6702bf12 , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x6b02bf14 , 0x6b02bf14 , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x6f02bf16 , 0x6f02bf16 , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00802220 , 0x00802220 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x04802222 , 0x04802222 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x09802421 , 0x09802421 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x0d802621 , 0x0d802621 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x13804620 , 0x13804620 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x19804a20 , 0x19804a20 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x1d804e20 , 0x1d804e20 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x21805420 , 0x21805420 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x26805e20 , 0x26805e20 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2b805e40 , 0x2b805e40 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x2f805e42 , 0x2f805e42 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x33805e44 , 0x33805e44 , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x38805e65 , 0x38805e65 , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x3c805e69 , 0x3c805e69 , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x40805e6b , 0x40805e6b , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x44805e6d , 0x44805e6d , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x49805e72 , 0x49805e72 , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x4e805eb2 , 0x4e805eb2 , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x53805f12 , 0x53805f12 , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x59825eb2 , 0x59825eb2 , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x5e825f12 , 0x5e825f12 , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x61827f12 , 0x61827f12 , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6782bf12 , 0x6782bf12 , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x6b82bf14 , 0x6b82bf14 , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x6f82bf16 , 0x6f82bf16 , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00804000 , 0x00804000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x00804201 , 0x00804201 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x0280c802 , 0x0280c802 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x0280ca03 , 0x0280ca03 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x04c15104 , 0x04c15104 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04c15305 , 0x04c15305 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04c15305 , 0x04c15305 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016048 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016448 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016848 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_osprey_2p2_mac_core[][2] = { /* Addr allmodes */ { 0x00000008 , 0x00000000 }, { 0x00000030 , 0x00020085 }, { 0x00000034 , 0x00000005 }, { 0x00000040 , 0x00000000 }, { 0x00000044 , 0x00000000 }, { 0x00000048 , 0x00000008 }, { 0x0000004c , 0x00000010 }, { 0x00000050 , 0x00000000 }, { 0x00001040 , 0x002ffc0f }, { 0x00001044 , 0x002ffc0f }, { 0x00001048 , 0x002ffc0f }, { 0x0000104c , 0x002ffc0f }, { 0x00001050 , 0x002ffc0f }, { 0x00001054 , 0x002ffc0f }, { 0x00001058 , 0x002ffc0f }, { 0x0000105c , 0x002ffc0f }, { 0x00001060 , 0x002ffc0f }, { 0x00001064 , 0x002ffc0f }, { 0x000010f0 , 0x00000100 }, { 0x00001270 , 0x00000000 }, { 0x000012b0 , 0x00000000 }, { 0x000012f0 , 0x00000000 }, { 0x0000143c , 0x00000000 }, { 0x0000147c , 0x00000000 }, { 0x00008000 , 0x00000000 }, { 0x00008004 , 0x00000000 }, { 0x00008008 , 0x00000000 }, { 0x0000800c , 0x00000000 }, { 0x00008018 , 0x00000000 }, { 0x00008020 , 0x00000000 }, { 0x00008038 , 0x00000000 }, { 0x0000803c , 0x00000000 }, { 0x00008040 , 0x00000000 }, { 0x00008044 , 0x00000000 }, { 0x00008048 , 0x00000000 }, { 0x0000804c , 0xffffffff }, { 0x00008054 , 0x00000000 }, { 0x00008058 , 0x00000000 }, { 0x0000805c , 0x000fc78f }, { 0x00008060 , 0x0000000f }, { 0x00008064 , 0x00000000 }, { 0x00008070 , 0x00000310 }, { 0x00008074 , 0x00000020 }, { 0x00008078 , 0x00000000 }, { 0x0000809c , 0x0000000f }, { 0x000080a0 , 0x00000000 }, { 0x000080a4 , 0x02ff0000 }, { 0x000080a8 , 0x0e070605 }, { 0x000080ac , 0x0000000d }, { 0x000080b0 , 0x00000000 }, { 0x000080b4 , 0x00000000 }, { 0x000080b8 , 0x00000000 }, { 0x000080bc , 0x00000000 }, { 0x000080c0 , 0x2a800000 }, { 0x000080c4 , 0x06900168 }, { 0x000080c8 , 0x13881c20 }, { 0x000080cc , 0x01f40000 }, { 0x000080d0 , 0x00252500 }, { 0x000080d4 , 0x00a00000 }, { 0x000080d8 , 0x00400000 }, { 0x000080dc , 0x00000000 }, { 0x000080e0 , 0xffffffff }, { 0x000080e4 , 0x0000ffff }, { 0x000080e8 , 0x3f3f3f3f }, { 0x000080ec , 0x00000000 }, { 0x000080f0 , 0x00000000 }, { 0x000080f4 , 0x00000000 }, { 0x000080fc , 0x00020000 }, { 0x00008100 , 0x00000000 }, { 0x00008108 , 0x00000052 }, { 0x0000810c , 0x00000000 }, { 0x00008110 , 0x00000000 }, { 0x00008114 , 0x000007ff }, { 0x00008118 , 0x000000aa }, { 0x0000811c , 0x00003210 }, { 0x00008124 , 0x00000000 }, { 0x00008128 , 0x00000000 }, { 0x0000812c , 0x00000000 }, { 0x00008130 , 0x00000000 }, { 0x00008134 , 0x00000000 }, { 0x00008138 , 0x00000000 }, { 0x0000813c , 0x0000ffff }, { 0x00008144 , 0xffffffff }, { 0x00008168 , 0x00000000 }, { 0x0000816c , 0x00000000 }, { 0x000081c0 , 0x00000000 }, { 0x000081c4 , 0x33332210 }, { 0x000081ec , 0x00000000 }, { 0x000081f0 , 0x00000000 }, { 0x000081f4 , 0x00000000 }, { 0x000081f8 , 0x00000000 }, { 0x000081fc , 0x00000000 }, { 0x00008240 , 0x00100000 }, { 0x00008244 , 0x0010f400 }, { 0x00008248 , 0x00000800 }, { 0x0000824c , 0x0001e800 }, { 0x00008250 , 0x00000000 }, { 0x00008254 , 0x00000000 }, { 0x00008258 , 0x00000000 }, { 0x0000825c , 0x40000000 }, { 0x00008260 , 0x00080922 }, - { 0x00008264 , 0x9bc00010 }, + { 0x00008264 , 0x9d400010 }, { 0x00008268 , 0xffffffff }, { 0x0000826c , 0x0000ffff }, { 0x00008270 , 0x00000000 }, { 0x00008274 , 0x40000000 }, { 0x00008278 , 0x003e4180 }, { 0x0000827c , 0x00000004 }, { 0x00008284 , 0x0000002c }, { 0x00008288 , 0x0000002c }, { 0x0000828c , 0x000000ff }, { 0x00008294 , 0x00000000 }, { 0x00008298 , 0x00000000 }, { 0x0000829c , 0x00000000 }, { 0x00008300 , 0x00000140 }, { 0x00008314 , 0x00000000 }, { 0x0000831c , 0x0000010d }, { 0x00008328 , 0x00000000 }, { 0x0000832c , 0x00000007 }, { 0x00008330 , 0x00000302 }, { 0x00008334 , 0x00000700 }, { 0x00008338 , 0x00ff0000 }, { 0x0000833c , 0x02400000 }, { 0x00008340 , 0x000107ff }, { 0x00008344 , 0xaa48105b }, { 0x00008348 , 0x008f0000 }, { 0x0000835c , 0x00000000 }, { 0x00008360 , 0xffffffff }, { 0x00008364 , 0xffffffff }, { 0x00008368 , 0x00000000 }, { 0x00008370 , 0x00000000 }, { 0x00008374 , 0x000000ff }, { 0x00008378 , 0x00000000 }, { 0x0000837c , 0x00000000 }, { 0x00008380 , 0xffffffff }, { 0x00008384 , 0xffffffff }, { 0x00008390 , 0xffffffff }, { 0x00008394 , 0xffffffff }, { 0x00008398 , 0x00000000 }, { 0x0000839c , 0x00000000 }, { 0x000083a0 , 0x00000000 }, { 0x000083a4 , 0x0000fa14 }, { 0x000083a8 , 0x000f0c00 }, { 0x000083ac , 0x33332210 }, { 0x000083b0 , 0x33332210 }, { 0x000083b4 , 0x33332210 }, { 0x000083b8 , 0x33332210 }, { 0x000083bc , 0x00000000 }, { 0x000083c0 , 0x00000000 }, { 0x000083c4 , 0x00000000 }, { 0x000083c8 , 0x00000000 }, { 0x000083cc , 0x00000200 }, { 0x000083d0 , 0x000301ff }, }; static const u_int32_t ar9300_osprey_2p2_soc_preamble[][2] = { /* Addr allmodes */ { 0x000040a4 , 0x00a0c1c9 }, { 0x00007008 , 0x00000000 }, { 0x00007020 , 0x00000000 }, { 0x00007034 , 0x00000002 }, { 0x00007038 , 0x000004c2 }, { 0x00007048 , 0x00000008 }, }; static const u_int32_t ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x52022470 , 0x52022470 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x55022490 , 0x55022490 , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x59022492 , 0x59022492 , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x5d022692 , 0x5d022692 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x61022892 , 0x61022892 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x65024890 , 0x65024890 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x69024892 , 0x69024892 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6e024c92 , 0x6e024c92 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x74026e92 , 0x74026e92 , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x52822470 , 0x52822470 , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x55822490 , 0x55822490 , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x59822492 , 0x59822492 , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x5d822692 , 0x5d822692 , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x61822892 , 0x61822892 , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x65824890 , 0x65824890 , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x69824892 , 0x69824892 , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x6e824c92 , 0x6e824c92 , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x74826e92 , 0x74826e92 , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x02004000 , 0x02004000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x02004801 , 0x02004801 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02808a02 , 0x02808a02 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0380ce03 , 0x0380ce03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04411104 , 0x04411104 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04411104 , 0x04411104 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300Modes_mixed_ob_db_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x52022470 , 0x52022470 , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x55022490 , 0x55022490 , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x59022492 , 0x59022492 , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x5d022692 , 0x5d022692 , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x61022892 , 0x61022892 , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x65024890 , 0x65024890 , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x69024892 , 0x69024892 , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x6e024c92 , 0x6e024c92 , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x74026e92 , 0x74026e92 , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x52822470 , 0x52822470 , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x55822490 , 0x55822490 , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x59822492 , 0x59822492 , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x5d822692 , 0x5d822692 , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x61822892 , 0x61822892 , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x65824890 , 0x65824890 , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x69824892 , 0x69824892 , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x6e824c92 , 0x6e824c92 , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x74826e92 , 0x74826e92 , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x02004000 , 0x02004000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x02004801 , 0x02004801 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02808a02 , 0x02808a02 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0380ce03 , 0x0380ce03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04411104 , 0x04411104 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04411104 , 0x04411104 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04411104 , 0x04411104 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x00033800 , 0x00033800 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0003c000 , 0x0003c000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03fc0000 , 0x03fc0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016048 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016448 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016848 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_osprey_2p2_baseband_core_txfir_coeff_japan_2484[][2] = { /* Addr allmodes */ { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x6f7f0301 }, { 0x0000a3a0 , 0xca9228ee }, }; static const u_int32_t ar9300_osprey_2p2_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00001030 , 0x00000230 , 0x00000460 , 0x000002c0 , 0x00000160 }, { 0x00001070 , 0x00000168 , 0x000002d0 , 0x00000318 , 0x0000018c }, { 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 }, { 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 }, { 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b }, - { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 }, + { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 }, { 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a }, { 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 }, }; static const u_int32_t ar9300Modes_high_power_tx_gain_table_osprey_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x15000028 , 0x15000028 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1b00002b , 0x1b00002b , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x1f020028 , 0x1f020028 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x2502002b , 0x2502002b , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2a04002a , 0x2a04002a , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2e06002a , 0x2e06002a , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x3302202d , 0x3302202d , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3804202c , 0x3804202c , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3c06202c , 0x3c06202c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4108202d , 0x4108202d , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4506402d , 0x4506402d , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4906222d , 0x4906222d , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4d062231 , 0x4d062231 , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x50082231 , 0x50082231 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5608422e , 0x5608422e , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5e08442e , 0x5e08442e , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x620a4431 , 0x620a4431 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x640a4432 , 0x640a4432 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x680a4434 , 0x680a4434 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x6c0a6434 , 0x6c0a6434 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6f0a6633 , 0x6f0a6633 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x15800028 , 0x15800028 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1b80002b , 0x1b80002b , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x1f820028 , 0x1f820028 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x2582002b , 0x2582002b , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2a84002a , 0x2a84002a , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2e86002a , 0x2e86002a , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x3382202d , 0x3382202d , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3884202c , 0x3884202c , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3c86202c , 0x3c86202c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4188202d , 0x4188202d , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4586402d , 0x4586402d , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4986222d , 0x4986222d , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4d862231 , 0x4d862231 , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x50882231 , 0x50882231 , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5688422e , 0x5688422e , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5e88442e , 0x5e88442e , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x628a4431 , 0x628a4431 , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x648a4432 , 0x648a4432 , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x688a4434 , 0x688a4434 , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x6c8a6434 , 0x6c8a6434 , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x6f8a6633 , 0x6f8a6633 , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01804601 , 0x01804601 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01804601 , 0x01804601 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x01804601 , 0x01804601 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x03408d02 , 0x03408d02 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x03410d04 , 0x03410d04 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9200_merlin_2p2_radio_core[][2] = { /* Addr common */ { 0x00007800 , 0x00040000 }, { 0x00007804 , 0xdb005012 }, { 0x00007808 , 0x04924914 }, { 0x0000780c , 0x21084210 }, { 0x00007810 , 0x6d801300 }, { 0x00007814 , 0x0019beff }, { 0x00007818 , 0x07e41000 }, { 0x0000781c , 0x00392000 }, { 0x00007820 , 0x92592480 }, { 0x00007824 , 0x00040000 }, { 0x00007828 , 0xdb005012 }, { 0x0000782c , 0x04924914 }, { 0x00007830 , 0x21084210 }, { 0x00007834 , 0x6d801300 }, { 0x00007838 , 0x0019beff }, { 0x0000783c , 0x07e40000 }, { 0x00007840 , 0x00392000 }, { 0x00007844 , 0x92592480 }, { 0x00007848 , 0x00100000 }, { 0x0000784c , 0x773f0567 }, { 0x00007850 , 0x54214514 }, { 0x00007854 , 0x12035828 }, { 0x00007858 , 0x92592692 }, { 0x0000785c , 0x00000000 }, { 0x00007860 , 0x56400000 }, { 0x00007864 , 0x0a8e370e }, { 0x00007868 , 0xc0102850 }, { 0x0000786c , 0x812d4000 }, { 0x00007870 , 0x807ec400 }, { 0x00007874 , 0x001b6db0 }, { 0x00007878 , 0x00376b63 }, { 0x0000787c , 0x06db6db6 }, { 0x00007880 , 0x006d8000 }, { 0x00007884 , 0xffeffffe }, { 0x00007888 , 0xffeffffe }, { 0x0000788c , 0x00010000 }, { 0x00007890 , 0x02060aeb }, { 0x00007894 , 0x5a108000 }, }; static const u_int32_t ar9300_osprey_2p2_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009810 , 0xd00a8005 , 0xd00a8005 , 0xd00a8011 , 0xd00a8011 }, { 0x00009820 , 0x206a022e , 0x206a022e , 0x206a012e , 0x206a012e }, { 0x00009824 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 }, { 0x00009828 , 0x06903081 , 0x06903081 , 0x06903881 , 0x06903881 }, { 0x0000982c , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 }, { 0x00009830 , 0x0000059c , 0x0000059c , 0x0000119c , 0x0000119c }, { 0x00009c00 , 0x000000c4 , 0x000000c4 , 0x000000c4 , 0x000000c4 }, { 0x00009e00 , 0x0372111a , 0x0372111a , 0x037216a0 , 0x037216a0 }, { 0x00009e04 , 0x001c2020 , 0x001c2020 , 0x001c2020 , 0x001c2020 }, { 0x00009e0c , 0x6c4000e2 , 0x6d4000e2 , 0x6d4000e2 , 0x6c4000e2 }, { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec84d2e , 0x7ec84d2e }, { 0x00009e14 , 0x37b95d5e , 0x37b9605e , 0x3379605e , 0x33795d5e }, { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c }, { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce }, { 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 }, { 0x00009e3c , 0xcf946220 , 0xcf946220 , 0xcf946222 , 0xcf946222 }, { 0x00009e44 , 0x02321e27 , 0x02321e27 , 0x02291e27 , 0x02291e27 }, { 0x00009e48 , 0x5030201a , 0x5030201a , 0x50302012 , 0x50302012 }, { 0x00009fc8 , 0x0003f000 , 0x0003f000 , 0x0001a000 , 0x0001a000 }, { 0x0000a204 , 0x000036c0 , 0x000036c4 , 0x000036c4 , 0x000036c0 }, { 0x0000a208 , 0x00000104 , 0x00000104 , 0x00000004 , 0x00000004 }, { 0x0000a22c , 0x01026a2f , 0x01026a2f , 0x01026a2f , 0x01026a2f }, { 0x0000a230 , 0x0000000a , 0x00000014 , 0x00000016 , 0x0000000b }, { 0x0000a234 , 0x00000fff , 0x10000fff , 0x10000fff , 0x00000fff }, { 0x0000a238 , 0xffb81018 , 0xffb81018 , 0xffb81018 , 0xffb81018 }, { 0x0000a250 , 0x00000000 , 0x00000000 , 0x00000210 , 0x00000108 }, { 0x0000a254 , 0x000007d0 , 0x00000fa0 , 0x00001130 , 0x00000898 }, { 0x0000a258 , 0x02020002 , 0x02020002 , 0x02020002 , 0x02020002 }, { 0x0000a25c , 0x01000e0e , 0x01000e0e , 0x01000e0e , 0x01000e0e }, { 0x0000a260 , 0x0a021501 , 0x0a021501 , 0x3a021501 , 0x3a021501 }, { 0x0000a264 , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a280 , 0x00000007 , 0x00000007 , 0x0000000b , 0x0000000b }, { 0x0000a284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, { 0x0000a288 , 0x00000110 , 0x00000110 , 0x00000110 , 0x00000110 }, { 0x0000a28c , 0x00022222 , 0x00022222 , 0x00022222 , 0x00022222 }, { 0x0000a2c4 , 0x00158d18 , 0x00158d18 , 0x00158d18 , 0x00158d18 }, { 0x0000a2d0 , 0x00041983 , 0x00041983 , 0x00041981 , 0x00041982 }, { 0x0000a2d8 , 0x7999a83b , 0x7999a83b , 0x7999a83b , 0x7999a83b }, { 0x0000a358 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a830 , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae04 , 0x001c0000 , 0x001c0000 , 0x001c0000 , 0x001c0000 }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000ae1c , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae20 , 0x000001b5 , 0x000001b5 , 0x000001ce , 0x000001ce }, { 0x0000b284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, { 0x0000b830 , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000be04 , 0x001c0000 , 0x001c0000 , 0x001c0000 , 0x001c0000 }, { 0x0000be18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000be1c , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000be20 , 0x000001b5 , 0x000001b5 , 0x000001ce , 0x000001ce }, { 0x0000c284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, }; static const u_int32_t ar9300Common_wo_xlna_rx_gain_table_osprey_2p2[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x03820190 }, { 0x0000a030 , 0x03840383 }, { 0x0000a034 , 0x03880385 }, { 0x0000a038 , 0x038a0389 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x29292929 }, { 0x0000a084 , 0x29292929 }, { 0x0000a088 , 0x29292929 }, { 0x0000a08c , 0x29292929 }, { 0x0000a090 , 0x22292929 }, { 0x0000a094 , 0x1d1d2222 }, { 0x0000a098 , 0x0c111117 }, { 0x0000a09c , 0x00030303 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x32323232 }, { 0x0000b084 , 0x2f2f3232 }, { 0x0000b088 , 0x23282a2d }, { 0x0000b08c , 0x1c1e2123 }, { 0x0000b090 , 0x14171919 }, { 0x0000b094 , 0x0e0e1214 }, { 0x0000b098 , 0x03050707 }, { 0x0000b09c , 0x00030303 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; static const u_int32_t ar9300_osprey_2p2_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00007010 , 0x00000023 , 0x00000023 , 0x00000023 , 0x00000023 }, }; static const u_int32_t ar9300Common_rx_gain_table_merlin_2p2[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x02000101 }, { 0x0000a004 , 0x02000102 }, { 0x0000a008 , 0x02000103 }, { 0x0000a00c , 0x02000104 }, { 0x0000a010 , 0x02000200 }, { 0x0000a014 , 0x02000201 }, { 0x0000a018 , 0x02000202 }, { 0x0000a01c , 0x02000203 }, { 0x0000a020 , 0x02000204 }, { 0x0000a024 , 0x02000205 }, { 0x0000a028 , 0x02000208 }, { 0x0000a02c , 0x02000302 }, { 0x0000a030 , 0x02000303 }, { 0x0000a034 , 0x02000304 }, { 0x0000a038 , 0x02000400 }, { 0x0000a03c , 0x02010300 }, { 0x0000a040 , 0x02010301 }, { 0x0000a044 , 0x02010302 }, { 0x0000a048 , 0x02000500 }, { 0x0000a04c , 0x02010400 }, { 0x0000a050 , 0x02020300 }, { 0x0000a054 , 0x02020301 }, { 0x0000a058 , 0x02020302 }, { 0x0000a05c , 0x02020303 }, { 0x0000a060 , 0x02020400 }, { 0x0000a064 , 0x02030300 }, { 0x0000a068 , 0x02030301 }, { 0x0000a06c , 0x02030302 }, { 0x0000a070 , 0x02030303 }, { 0x0000a074 , 0x02030400 }, { 0x0000a078 , 0x02040300 }, { 0x0000a07c , 0x02040301 }, { 0x0000a080 , 0x02040302 }, { 0x0000a084 , 0x02040303 }, { 0x0000a088 , 0x02030500 }, { 0x0000a08c , 0x02040400 }, { 0x0000a090 , 0x02050203 }, { 0x0000a094 , 0x02050204 }, { 0x0000a098 , 0x02050205 }, { 0x0000a09c , 0x02040500 }, { 0x0000a0a0 , 0x02050301 }, { 0x0000a0a4 , 0x02050302 }, { 0x0000a0a8 , 0x02050303 }, { 0x0000a0ac , 0x02050400 }, { 0x0000a0b0 , 0x02050401 }, { 0x0000a0b4 , 0x02050402 }, { 0x0000a0b8 , 0x02050403 }, { 0x0000a0bc , 0x02050500 }, { 0x0000a0c0 , 0x02050501 }, { 0x0000a0c4 , 0x02050502 }, { 0x0000a0c8 , 0x02050503 }, { 0x0000a0cc , 0x02050504 }, { 0x0000a0d0 , 0x02050600 }, { 0x0000a0d4 , 0x02050601 }, { 0x0000a0d8 , 0x02050602 }, { 0x0000a0dc , 0x02050603 }, { 0x0000a0e0 , 0x02050604 }, { 0x0000a0e4 , 0x02050700 }, { 0x0000a0e8 , 0x02050701 }, { 0x0000a0ec , 0x02050702 }, { 0x0000a0f0 , 0x02050703 }, { 0x0000a0f4 , 0x02050704 }, { 0x0000a0f8 , 0x02050705 }, { 0x0000a0fc , 0x02050708 }, { 0x0000a100 , 0x02050709 }, { 0x0000a104 , 0x0205070a }, { 0x0000a108 , 0x0205070b }, { 0x0000a10c , 0x0205070c }, { 0x0000a110 , 0x0205070d }, { 0x0000a114 , 0x02050710 }, { 0x0000a118 , 0x02050711 }, { 0x0000a11c , 0x02050712 }, { 0x0000a120 , 0x02050713 }, { 0x0000a124 , 0x02050714 }, { 0x0000a128 , 0x02050715 }, { 0x0000a12c , 0x02050730 }, { 0x0000a130 , 0x02050731 }, { 0x0000a134 , 0x02050732 }, { 0x0000a138 , 0x02050733 }, { 0x0000a13c , 0x02050734 }, { 0x0000a140 , 0x02050735 }, { 0x0000a144 , 0x02050750 }, { 0x0000a148 , 0x02050751 }, { 0x0000a14c , 0x02050752 }, { 0x0000a150 , 0x02050753 }, { 0x0000a154 , 0x02050754 }, { 0x0000a158 , 0x02050755 }, { 0x0000a15c , 0x02050770 }, { 0x0000a160 , 0x02050771 }, { 0x0000a164 , 0x02050772 }, { 0x0000a168 , 0x02050773 }, { 0x0000a16c , 0x02050774 }, { 0x0000a170 , 0x02050775 }, { 0x0000a174 , 0x00000776 }, { 0x0000a178 , 0x00000776 }, { 0x0000a17c , 0x00000776 }, { 0x0000a180 , 0x00000776 }, { 0x0000a184 , 0x00000776 }, { 0x0000a188 , 0x00000776 }, { 0x0000a18c , 0x00000776 }, { 0x0000a190 , 0x00000776 }, { 0x0000a194 , 0x00000776 }, { 0x0000a198 , 0x00000776 }, { 0x0000a19c , 0x00000776 }, { 0x0000a1a0 , 0x00000776 }, { 0x0000a1a4 , 0x00000776 }, { 0x0000a1a8 , 0x00000776 }, { 0x0000a1ac , 0x00000776 }, { 0x0000a1b0 , 0x00000776 }, { 0x0000a1b4 , 0x00000776 }, { 0x0000a1b8 , 0x00000776 }, { 0x0000a1bc , 0x00000776 }, { 0x0000a1c0 , 0x00000776 }, { 0x0000a1c4 , 0x00000776 }, { 0x0000a1c8 , 0x00000776 }, { 0x0000a1cc , 0x00000776 }, { 0x0000a1d0 , 0x00000776 }, { 0x0000a1d4 , 0x00000776 }, { 0x0000a1d8 , 0x00000776 }, { 0x0000a1dc , 0x00000776 }, { 0x0000a1e0 , 0x00000776 }, { 0x0000a1e4 , 0x00000776 }, { 0x0000a1e8 , 0x00000776 }, { 0x0000a1ec , 0x00000776 }, { 0x0000a1f0 , 0x00000776 }, { 0x0000a1f4 , 0x00000776 }, { 0x0000a1f8 , 0x00000776 }, { 0x0000a1fc , 0x00000776 }, { 0x0000b000 , 0x02000101 }, { 0x0000b004 , 0x02000102 }, { 0x0000b008 , 0x02000103 }, { 0x0000b00c , 0x02000104 }, { 0x0000b010 , 0x02000200 }, { 0x0000b014 , 0x02000201 }, { 0x0000b018 , 0x02000202 }, { 0x0000b01c , 0x02000203 }, { 0x0000b020 , 0x02000204 }, { 0x0000b024 , 0x02000205 }, { 0x0000b028 , 0x02000208 }, { 0x0000b02c , 0x02000302 }, { 0x0000b030 , 0x02000303 }, { 0x0000b034 , 0x02000304 }, { 0x0000b038 , 0x02000400 }, { 0x0000b03c , 0x02010300 }, { 0x0000b040 , 0x02010301 }, { 0x0000b044 , 0x02010302 }, { 0x0000b048 , 0x02000500 }, { 0x0000b04c , 0x02010400 }, { 0x0000b050 , 0x02020300 }, { 0x0000b054 , 0x02020301 }, { 0x0000b058 , 0x02020302 }, { 0x0000b05c , 0x02020303 }, { 0x0000b060 , 0x02020400 }, { 0x0000b064 , 0x02030300 }, { 0x0000b068 , 0x02030301 }, { 0x0000b06c , 0x02030302 }, { 0x0000b070 , 0x02030303 }, { 0x0000b074 , 0x02030400 }, { 0x0000b078 , 0x02040300 }, { 0x0000b07c , 0x02040301 }, { 0x0000b080 , 0x02040302 }, { 0x0000b084 , 0x02040303 }, { 0x0000b088 , 0x02030500 }, { 0x0000b08c , 0x02040400 }, { 0x0000b090 , 0x02050203 }, { 0x0000b094 , 0x02050204 }, { 0x0000b098 , 0x02050205 }, { 0x0000b09c , 0x02040500 }, { 0x0000b0a0 , 0x02050301 }, { 0x0000b0a4 , 0x02050302 }, { 0x0000b0a8 , 0x02050303 }, { 0x0000b0ac , 0x02050400 }, { 0x0000b0b0 , 0x02050401 }, { 0x0000b0b4 , 0x02050402 }, { 0x0000b0b8 , 0x02050403 }, { 0x0000b0bc , 0x02050500 }, { 0x0000b0c0 , 0x02050501 }, { 0x0000b0c4 , 0x02050502 }, { 0x0000b0c8 , 0x02050503 }, { 0x0000b0cc , 0x02050504 }, { 0x0000b0d0 , 0x02050600 }, { 0x0000b0d4 , 0x02050601 }, { 0x0000b0d8 , 0x02050602 }, { 0x0000b0dc , 0x02050603 }, { 0x0000b0e0 , 0x02050604 }, { 0x0000b0e4 , 0x02050700 }, { 0x0000b0e8 , 0x02050701 }, { 0x0000b0ec , 0x02050702 }, { 0x0000b0f0 , 0x02050703 }, { 0x0000b0f4 , 0x02050704 }, { 0x0000b0f8 , 0x02050705 }, { 0x0000b0fc , 0x02050708 }, { 0x0000b100 , 0x02050709 }, { 0x0000b104 , 0x0205070a }, { 0x0000b108 , 0x0205070b }, { 0x0000b10c , 0x0205070c }, { 0x0000b110 , 0x0205070d }, { 0x0000b114 , 0x02050710 }, { 0x0000b118 , 0x02050711 }, { 0x0000b11c , 0x02050712 }, { 0x0000b120 , 0x02050713 }, { 0x0000b124 , 0x02050714 }, { 0x0000b128 , 0x02050715 }, { 0x0000b12c , 0x02050730 }, { 0x0000b130 , 0x02050731 }, { 0x0000b134 , 0x02050732 }, { 0x0000b138 , 0x02050733 }, { 0x0000b13c , 0x02050734 }, { 0x0000b140 , 0x02050735 }, { 0x0000b144 , 0x02050750 }, { 0x0000b148 , 0x02050751 }, { 0x0000b14c , 0x02050752 }, { 0x0000b150 , 0x02050753 }, { 0x0000b154 , 0x02050754 }, { 0x0000b158 , 0x02050755 }, { 0x0000b15c , 0x02050770 }, { 0x0000b160 , 0x02050771 }, { 0x0000b164 , 0x02050772 }, { 0x0000b168 , 0x02050773 }, { 0x0000b16c , 0x02050774 }, { 0x0000b170 , 0x02050775 }, { 0x0000b174 , 0x00000776 }, { 0x0000b178 , 0x00000776 }, { 0x0000b17c , 0x00000776 }, { 0x0000b180 , 0x00000776 }, { 0x0000b184 , 0x00000776 }, { 0x0000b188 , 0x00000776 }, { 0x0000b18c , 0x00000776 }, { 0x0000b190 , 0x00000776 }, { 0x0000b194 , 0x00000776 }, { 0x0000b198 , 0x00000776 }, { 0x0000b19c , 0x00000776 }, { 0x0000b1a0 , 0x00000776 }, { 0x0000b1a4 , 0x00000776 }, { 0x0000b1a8 , 0x00000776 }, { 0x0000b1ac , 0x00000776 }, { 0x0000b1b0 , 0x00000776 }, { 0x0000b1b4 , 0x00000776 }, { 0x0000b1b8 , 0x00000776 }, { 0x0000b1bc , 0x00000776 }, { 0x0000b1c0 , 0x00000776 }, { 0x0000b1c4 , 0x00000776 }, { 0x0000b1c8 , 0x00000776 }, { 0x0000b1cc , 0x00000776 }, { 0x0000b1d0 , 0x00000776 }, { 0x0000b1d4 , 0x00000776 }, { 0x0000b1d8 , 0x00000776 }, { 0x0000b1dc , 0x00000776 }, { 0x0000b1e0 , 0x00000776 }, { 0x0000b1e4 , 0x00000776 }, { 0x0000b1e8 , 0x00000776 }, { 0x0000b1ec , 0x00000776 }, { 0x0000b1f0 , 0x00000776 }, { 0x0000b1f4 , 0x00000776 }, { 0x0000b1f8 , 0x00000776 }, { 0x0000b1fc , 0x00000776 }, }; static const u_int32_t ar9300_common_rx_gain_table_osprey_2p2[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x01910190 }, { 0x0000a030 , 0x01930192 }, { 0x0000a034 , 0x01950194 }, { 0x0000a038 , 0x038a0196 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x22222229 }, { 0x0000a084 , 0x1d1d1d1d }, { 0x0000a088 , 0x1d1d1d1d }, { 0x0000a08c , 0x1d1d1d1d }, { 0x0000a090 , 0x171d1d1d }, { 0x0000a094 , 0x11111717 }, { 0x0000a098 , 0x00030311 }, { 0x0000a09c , 0x00000000 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x23232323 }, { 0x0000b084 , 0x21232323 }, { 0x0000b088 , 0x19191c1e }, { 0x0000b08c , 0x12141417 }, { 0x0000b090 , 0x07070e0e }, { 0x0000b094 , 0x03030305 }, { 0x0000b098 , 0x00000003 }, { 0x0000b09c , 0x00000000 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p2[][2] = { {0x00004040, 0x0821265e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_clkreq_enable_L1_osprey_2p2[][2] = { {0x00004040, 0x0825365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_clkreq_disable_L1_osprey_2p2[][2] = { {0x00004040, 0x0821365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c (revision 278741) @@ -1,1565 +1,1566 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #if ATH_WOW_OFFLOAD void ar9300_wowoffload_prep(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_mcast_filter_l32_set = 0; ahp->ah_mcast_filter_u32_set = 0; } void ar9300_wowoffload_post(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t val; if (ahp->ah_mcast_filter_l32_set != 0) { val = OS_REG_READ(ah, AR_MCAST_FIL0); val &= ~ahp->ah_mcast_filter_l32_set; OS_REG_WRITE(ah, AR_MCAST_FIL0, val); } if (ahp->ah_mcast_filter_u32_set != 0) { val = OS_REG_READ(ah, AR_MCAST_FIL1); val &= ~ahp->ah_mcast_filter_u32_set; OS_REG_WRITE(ah, AR_MCAST_FIL1, val); } ahp->ah_mcast_filter_l32_set = 0; ahp->ah_mcast_filter_u32_set = 0; } static void ar9300_wowoffload_add_mcast_filter(struct ath_hal *ah, u_int8_t *mc_addr) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t reg, val; u_int8_t pos, high32; memcpy((u_int8_t *) &val, &mc_addr[0], 3); pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; memcpy((u_int8_t *) &val, &mc_addr[3], 3); pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; high32 = pos & 0x20; reg = high32 ? AR_MCAST_FIL1 : AR_MCAST_FIL0; pos &= 0x1F; val = OS_REG_READ(ah, reg); if ((val & (1 << pos)) == 0) { val |= (1 << pos); if (high32) { ahp->ah_mcast_filter_u32_set |= (1 << pos); } else { ahp->ah_mcast_filter_l32_set |= (1 << pos); } OS_REG_WRITE(ah, reg, val); } } /* * DeviceID SWAR - EV91928 * * During SW WOW, 0x4004[13] is set to allow BT eCPU to access WLAN MAC * registers. Setting 00x4004[13] will prevent eeprom state machine to * load customizable PCIE configuration registers, which lead to the PCIE * device id stay as default 0xABCD. The SWAR to have BT eCPU to write * to PCIE registers as soon as it detects PCIE reset is deasserted. */ void ar9300_wowoffload_download_devid_swar(struct ath_hal *ah) { u_int32_t addr = AR_WOW_OFFLOAD_WLAN_REGSET_NUM; OS_REG_WRITE(ah, addr, 8); addr += 4; OS_REG_WRITE(ah, addr, 0x5000); addr += 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_000 = %08x\n", AH_PRIVATE(ah)->ah_config.ath_hal_pcie_000); OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_000); addr += 4; OS_REG_WRITE(ah, addr, 0x5008); addr += 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_008 = %08x\n", AH_PRIVATE(ah)->ah_config.ath_hal_pcie_008); OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_008); addr += 4; OS_REG_WRITE(ah, addr, 0x502c); addr += 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_02c = %08x\n", AH_PRIVATE(ah)->ah_config.ath_hal_pcie_02c); OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_02c); addr += 4; OS_REG_WRITE(ah, addr, 0x18c00); addr += 4; OS_REG_WRITE(ah, addr, 0x18212ede); addr += 4; OS_REG_WRITE(ah, addr, 0x18c04); addr += 4; OS_REG_WRITE(ah, addr, 0x008001d8); addr += 4; OS_REG_WRITE(ah, addr, 0x18c08); addr += 4; OS_REG_WRITE(ah, addr, 0x0003580c); addr += 4; OS_REG_WRITE(ah, addr, 0x570c); addr += 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_70c = %08x\n", AH_PRIVATE(ah)->ah_config.ath_hal_pcie_70c); OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_70c); addr += 4; OS_REG_WRITE(ah, addr, 0x5040); addr += 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) pcie_040 = %08x\n", AH_PRIVATE(ah)->ah_config.ath_hal_pcie_040); OS_REG_WRITE(ah, addr, AH_PRIVATE(ah)->ah_config.ath_hal_pcie_040); addr += 4; /* A_SOC_REG_WRITE(0x45000, 0x0034168c); A_SOC_REG_WRITE(0x45008, 0x02800001); A_SOC_REG_WRITE(0x4502c, 0x3117168c); A_SOC_REG_WRITE(0x58c00, 0x18212ede); A_SOC_REG_WRITE(0x58c04, 0x000801d8); A_SOC_REG_WRITE(0x58c08, 0x0003580c); A_SOC_REG_WRITE(0x4570c, 0x275f3f01); A_SOC_REG_WRITE(0x45040, 0xffc25001); */ } /* Retrieve updated information from MAC PCU buffer. * Embedded CPU would have written the value before exiting WoW * */ void ar9300_wowoffload_retrieve_data(struct ath_hal *ah, void *buf, u_int32_t param) { u_int32_t rc_lower, rc_upper; if (param == WOW_PARAM_REPLAY_CNTR) { rc_lower = OS_REG_READ(ah, AR_WOW_TXBUF(0)); rc_upper = OS_REG_READ(ah, AR_WOW_TXBUF(1)); *(u_int64_t *)buf = rc_lower + (rc_upper << 32); } else if (param == WOW_PARAM_KEY_TSC) { rc_lower = OS_REG_READ(ah, AR_WOW_TXBUF(2)); rc_upper = OS_REG_READ(ah, AR_WOW_TXBUF(3)); *(u_int64_t *)buf = rc_lower + (rc_upper << 32); } else if (param == WOW_PARAM_TX_SEQNUM) { *(u_int32_t *)buf = OS_REG_READ(ah, AR_WOW_TXBUF(4)); } } /* Download GTK rekey related information to the embedded CPU */ u_int32_t ar9300_wowoffload_download_rekey_data(struct ath_hal *ah, u_int32_t *data, u_int32_t bytes) { int i; int mbox_status = OS_REG_READ(ah, AR_MBOX_CTRL_STATUS); u_int32_t gtk_data_start; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) %s, bytes=%d\n", __func__, bytes); if (AR_SREV_JUPITER(ah) && (bytes > (AR_WOW_OFFLOAD_GTK_DATA_WORDS_JUPITER * 4))) { bytes = AR_WOW_OFFLOAD_GTK_DATA_WORDS_JUPITER * 4; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) bytes truncated to %d\n", bytes); } /* Check if mailbox is busy */ if (mbox_status != 0) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: Mailbox register busy! Reg = 0x%x", __func__, mbox_status); return 1; } /* Clear status */ OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0); OS_REG_WRITE(ah, AR_WLAN_WOW_ENABLE, 0); OS_REG_WRITE(ah, AR_WLAN_WOW_STATUS, 0xFFFFFFFF); if (AR_SREV_JUPITER(ah)) { gtk_data_start = AR_WOW_OFFLOAD_GTK_DATA_START_JUPITER; } else { gtk_data_start = AR_WOW_OFFLOAD_GTK_DATA_START; } for (i = 0;i < bytes/4; i++) { OS_REG_WRITE(ah, gtk_data_start + i * 4, data[i]); } return 0; } void ar9300_wowoffload_download_acer_magic( struct ath_hal *ah, HAL_BOOL valid, u_int8_t* datap, u_int32_t bytes) { u_int32_t *p32 = (u_int32_t *) datap; u_int32_t l = 0, u = 0; if (valid) { l = *p32; p32++; u = *(u_int16_t *) p32; } OS_REG_WRITE(ah, AR_WOW_OFFLOAD_ACER_MAGIC_START, l); OS_REG_WRITE(ah, AR_WOW_OFFLOAD_ACER_MAGIC_START + 4, u); HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: Aer Magic: %02x-%02x-%02x-%02x-%02x-%02x\n", __func__, datap[0], datap[1], datap[2], datap[3], datap[4], datap[5]); } void ar9300_wowoffload_download_acer_swka( struct ath_hal *ah, u_int32_t id, HAL_BOOL valid, u_int32_t period, u_int32_t size, u_int32_t* datap) { u_int32_t ka_period[2] = { AR_WOW_OFFLOAD_ACER_KA0_PERIOD_MS, AR_WOW_OFFLOAD_ACER_KA1_PERIOD_MS }; u_int32_t ka_size[2] = { AR_WOW_OFFLOAD_ACER_KA0_SIZE, AR_WOW_OFFLOAD_ACER_KA1_SIZE }; u_int32_t ka_data[2] = { AR_WOW_OFFLOAD_ACER_KA0_DATA, AR_WOW_OFFLOAD_ACER_KA1_DATA }; u_int32_t n_data = AR_WOW_OFFLOAD_ACER_KA0_DATA_WORDS; int i; if (id >= 2) { return; } if (valid) { OS_REG_WRITE(ah, ka_period[id], period); OS_REG_WRITE(ah, ka_size[id], size); } else { OS_REG_WRITE(ah, ka_period[id], 0); OS_REG_WRITE(ah, ka_size[id], 0); } HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: id=%d, period=%d ms, size=%d bytes\n", __func__, id, period, size); if (size < (n_data * 4)) { n_data = (size + 3) / 4; } for (i=0; ivalid) { OS_REG_WRITE(ah, addr, 0x1); addr += 4; OS_REG_WRITE(ah, addr, p_info->RemoteIPv4Address.u32); addr += 4; OS_REG_WRITE(ah, addr, p_info->HostIPv4Address.u32); addr += 4; OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[0]); addr += 4; OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[1]); } else { OS_REG_WRITE(ah, addr, 0x0); } } #define WOW_WRITE_NS_IPV6_ADDRESS(_ah, _buf_addr, _p_ipv6_addr) \ { \ u_int32_t offset = (_buf_addr); \ u_int32_t *p_ipv6_addr = (u_int32_t *) (_p_ipv6_addr); \ int i; \ for (i = 0; i < 4; i++) { \ OS_REG_WRITE((_ah), offset, *p_ipv6_addr); \ offset += 4; \ p_ipv6_addr ++; \ } \ } void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data) { u_int32_t addr; struct hal_wow_offload_ns_info *p_info = (struct hal_wow_offload_ns_info *) data; u_int8_t mc_addr[6]; if (id == 0) { addr = AR_WOW_OFFLOAD_NS0_VALID; } else if (id == 1) { addr = AR_WOW_OFFLOAD_NS1_VALID; } else { return; } if (p_info->valid) { OS_REG_WRITE(ah, addr, 0x1); addr += 4; WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->RemoteIPv6Address.u32[0]); addr += 4 * 4; WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->SolicitedNodeIPv6Address.u32[0]); addr += 4 * 4; OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[0]); addr += 4; OS_REG_WRITE(ah, addr, p_info->MacAddress.u32[1]); addr += 4; WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->TargetIPv6Addresses[0].u32[0]); addr += 4 * 4; WOW_WRITE_NS_IPV6_ADDRESS(ah, addr, &p_info->TargetIPv6Addresses[1].u32[0]); mc_addr[0] = 0x33; mc_addr[1] = 0x33; mc_addr[2] = 0xFF; mc_addr[3] = p_info->SolicitedNodeIPv6Address.u8[13]; mc_addr[4] = p_info->SolicitedNodeIPv6Address.u8[14]; mc_addr[5] = p_info->SolicitedNodeIPv6Address.u8[15]; ar9300_wowoffload_add_mcast_filter(ah, mc_addr); } else { OS_REG_WRITE(ah, addr, 0x0); } } /* Download transmit parameters for GTK response frame during WoW * offload */ u_int32_t ar9300_wow_offload_download_hal_params(struct ath_hal *ah) { u_int32_t tpc = 0x3f; /* Transmit Power Control */ u_int32_t tx_tries_series = 7; u_int32_t tx_rate_series, transmit_rate; u_int32_t gtk_txdesc_param_start; if (AH_PRIVATE(ah)->ah_curchan->channel_flags & CHANNEL_CCK) { transmit_rate = 0x1B; /* CCK_1M */ } else { transmit_rate = 0xB; /* OFDM_6M */ } /* Use single rate for now. Change later as need be */ tx_rate_series = transmit_rate; tx_tries_series = 7; if (AR_SREV_JUPITER(ah)) { gtk_txdesc_param_start = AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START_JUPITER; } else { gtk_txdesc_param_start = AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START; } #define AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(x) (gtk_txdesc_param_start + ((x) * 4)) /* Do not change the data order unless firmware code on embedded * CPU is changed correspondingly */ OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(0), tx_rate_series); OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(1), tx_tries_series); OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(2), AH9300(ah)->ah_tx_chainmask); OS_REG_WRITE(ah, AR_WOW_OFFLOAD_GTK_TXDESC_PARAM(3), tpc); return 0; } /* Indicate to the embedded CPU that host is ready to enter WoW mode. * Embedded CPU will copy relevant information from the MAC PCU buffer */ u_int32_t ar9300_wow_offload_handshake(struct ath_hal *ah, u_int32_t pattern_enable) { int val; int mbox_status = OS_REG_READ(ah, AR_MBOX_CTRL_STATUS); #if ATH_WOW_OFFLOAD u_int32_t bt_handshake_timeout_us = HAL_WOW_CTRL_WAIT_BT_TO(ah) * 100000; #define AH_DEFAULT_BT_WAIT_TIMEOUT 3000000; /* 3 sec */ if (bt_handshake_timeout_us == 0) { bt_handshake_timeout_us = AH_DEFAULT_BT_WAIT_TIMEOUT; } HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) TIMEOUT: %d us\n", bt_handshake_timeout_us); #endif /* ATH_WOW_OFFLOAD */ if (mbox_status & AR_MBOX_WOW_REQ) { /* WOW mode request handshake is already in progress. * Do nothing */ return 0; } /* Clear status */ OS_REG_WRITE(ah, AR_MBOX_CTRL_STATUS, 0); OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0); OS_REG_WRITE(ah, AR_WLAN_WOW_ENABLE, 0); OS_REG_WRITE(ah, AR_WLAN_WOW_STATUS, 0xFFFFFFFF); OS_REG_WRITE(ah, AR_RIMT, 0); OS_REG_WRITE(ah, AR_TIMT, 0); val = 0; if (pattern_enable & AH_WOW_USER_PATTERN_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - User pattern\n"); val |= AR_EMB_CPU_WOW_ENABLE_PATTERN_MATCH; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - User pattern\n"); } if ((pattern_enable & AH_WOW_MAGIC_PATTERN_EN) #if ATH_WOW_OFFLOAD || (pattern_enable & AH_WOW_ACER_MAGIC_EN) #endif ) { val |= AR_EMB_CPU_WOW_ENABLE_MAGIC_PATTERN; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Magic pattern\n"); } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Magic pattern\n"); } if ((pattern_enable & AH_WOW_LINK_CHANGE) #if ATH_WOW_OFFLOAD || HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_KAFAIL_ENABLE) #endif ) { val |= AR_EMB_CPU_WOW_ENABLE_KEEP_ALIVE_FAIL; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Kepp alive fail\n"); } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Kepp alive fail\n"); } if (pattern_enable & AH_WOW_BEACON_MISS) { val |= AR_EMB_CPU_WOW_ENABLE_BEACON_MISS; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Becon Miss\n"); } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Becon Miss\n"); } OS_REG_WRITE(ah, AR_EMB_CPU_WOW_ENABLE, val); OS_REG_CLR_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF); OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_REQ); OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_INT_EMB_CPU); - if (!ath_hal_wait(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) { + if (!ath_hal_waitfor(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: WoW offload handshake failed", __func__); return 0; } else { OS_REG_CLR_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF); HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: WoW offload handshake successful",__func__); } return 1; } #endif /* ATH_WOW_OFFLOAD */ /* * Notify Power Mgt is enabled in self-generated frames. * If requested, force chip awake. * * Returns A_OK if chip is awake or successfully forced awake. * * WARNING WARNING WARNING * There is a problem with the chip where sometimes it will not wake up. */ HAL_BOOL ar9300_set_power_mode_awake(struct ath_hal *ah, int set_chip) { struct ath_hal_9300 *ahp = AH9300(ah); #define POWER_UP_TIME 10000 u_int32_t val; int i; /* Set Bits 14 and 17 of AR_WA before powering on the chip. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val); OS_DELAY(10); /* delay to allow the write to take effect. */ if (set_chip) { /* Do a Power-On-Reset if MAC is shutdown */ if ((OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_SHUTDOWN)) { if (ar9300_set_reset_reg(ah, HAL_RESET_POWER_ON) != AH_TRUE) { HALASSERT(0); return AH_FALSE; } } OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); OS_DELAY(50); for (i = POWER_UP_TIME / 50; i > 0; i--) { val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; if (val == AR_RTC_STATUS_ON) { break; } OS_DELAY(50); OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); } if (i == 0) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: Failed to wakeup in %uus\n", __func__, POWER_UP_TIME / 20); return AH_FALSE; } } OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); return AH_TRUE; #undef POWER_UP_TIME } /* * Notify Power Mgt is disabled in self-generated frames. * If requested, force chip to sleep. */ static void ar9300_set_power_mode_sleep(struct ath_hal *ah, int set_chip) { struct ath_hal_9300 *ahp = AH9300(ah); OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); if (set_chip ) { if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_WRITE(ah, AR_TIMER_MODE, OS_REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00); OS_REG_WRITE(ah, AR_GEN_TIMERS2_MODE, OS_REG_READ(ah, AR_GEN_TIMERS2_MODE) & 0xFFFFFF00); OS_REG_WRITE(ah, AR_SLP32_INC, OS_REG_READ(ah, AR_SLP32_INC) & 0xFFF00000); OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); OS_DELAY(100); } /* Clear the RTC force wake bit to allow the mac to go to sleep */ OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* * In Jupiter, after enter sleep mode, hardware will send * a SYS_SLEEPING message through MCI interface. Add a * few us delay to make sure the message can reach BT side. */ OS_DELAY(100); } if (!AR_SREV_JUPITER_10(ah)) { /* Shutdown chip. Active low */ OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); /* Settle time */ OS_DELAY(2); } } #if ATH_WOW_OFFLOAD if (!AR_SREV_JUPITER(ah) || !HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SET_4004_BIT14)) #endif /* ATH_WOW_OFFLOAD */ { /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val & ~AR_WA_D3_TO_L1_DISABLE); } } /* * Notify Power Management is enabled in self-generating * frames. If request, set power mode of chip to * auto/normal. Duration in units of 128us (1/8 TU). */ static void ar9300_set_power_mode_network_sleep(struct ath_hal *ah, int set_chip) { struct ath_hal_9300 *ahp = AH9300(ah); OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); if (set_chip) { HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; if (! p_cap->halAutoSleepSupport) { /* Set wake_on_interrupt bit; clear force_wake bit */ OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); } else { /* * When chip goes into network sleep, it could be waken up by * MCI_INT interrupt caused by BT's HW messages (LNA_xxx, CONT_xxx) * which chould be in a very fast rate (~100us). This will cause * chip to leave and re-enter network sleep mode frequently, which * in consequence will have WLAN MCI HW to generate lots of * SYS_WAKING and SYS_SLEEPING messages which will make BT CPU * to busy to process. */ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) & ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK); } /* Clear the RTC force wake bit to allow the mac to go to sleep */ OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* * In Jupiter, after enter sleep mode, hardware will send * a SYS_SLEEPING message through MCI interface. Add a * few us delay to make sure the message can reach BT side. */ OS_DELAY(30); } } } #if ATH_WOW_OFFLOAD if (!AR_SREV_JUPITER(ah) || !HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SET_4004_BIT14)) #endif /* ATH_WOW_OFFLOAD */ { /* Clear Bit 14 of AR_WA after putting chip into Sleep mode. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), ahp->ah_wa_reg_val & ~AR_WA_D3_TO_L1_DISABLE); } } /* * Set power mgt to the requested mode, and conditionally set * the chip as well */ HAL_BOOL ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip) { struct ath_hal_9300 *ahp = AH9300(ah); #if defined(AH_DEBUG) || defined(AH_PRINT_FILTER) static const char* modes[] = { "AWAKE", "FULL-SLEEP", "NETWORK SLEEP", "UNDEFINED" }; #endif int status = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__, modes[ar9300_get_power_mode(ah)], modes[mode], set_chip ? "set chip " : ""); OS_MARK(ah, AH_MARK_CHIP_POWER, mode); switch (mode) { case HAL_PM_AWAKE: if (set_chip) ah->ah_powerMode = mode; status = ar9300_set_power_mode_awake(ah, set_chip); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif + ahp->ah_chip_full_sleep = AH_FALSE; break; case HAL_PM_FULL_SLEEP: #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { if (ar9300_get_power_mode(ah) == HAL_PM_AWAKE) { if ((ar9300_mci_state(ah, HAL_MCI_STATE_ENABLE, NULL) != 0) && (ahp->ah_mci_bt_state != MCI_BT_SLEEP) && !ahp->ah_mci_halted_bt_gpm) { HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: HALT BT GPM (full_sleep)\n", __func__); ar9300_mci_send_coex_halt_bt_gpm(ah, AH_TRUE, AH_TRUE); } } ahp->ah_mci_ready = AH_FALSE; } #endif #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif ar9300_set_power_mode_sleep(ah, set_chip); if (set_chip) { ahp->ah_chip_full_sleep = AH_TRUE; ah->ah_powerMode = mode; } break; case HAL_PM_NETWORK_SLEEP: #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif ar9300_set_power_mode_network_sleep(ah, set_chip); if (set_chip) { ah->ah_powerMode = mode; } break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: unknown power mode %u\n", __func__, mode); OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, -1); return AH_FALSE; } OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, status); return status; } /* * Return the current sleep mode of the chip */ HAL_POWER_MODE ar9300_get_power_mode(struct ath_hal *ah) { int mode = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; switch (mode) { case AR_RTC_STATUS_ON: case AR_RTC_STATUS_WAKEUP: return HAL_PM_AWAKE; break; case AR_RTC_STATUS_SLEEP: return HAL_PM_NETWORK_SLEEP; break; case AR_RTC_STATUS_SHUTDOWN: return HAL_PM_FULL_SLEEP; break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: unknown power mode 0x%x\n", __func__, mode); return HAL_PM_UNDEFINED; } } /* * Set SM power save mode */ void ar9300_set_sm_power_mode(struct ath_hal *ah, HAL_SMPS_MODE mode) { int regval; struct ath_hal_9300 *ahp = AH9300(ah); if (ar9300_get_capability(ah, HAL_CAP_DYNAMIC_SMPS, 0, AH_NULL) != HAL_OK) { return; } /* Program low & high power chainmask settings and enable MAC control */ regval = SM(AR_PCU_SMPS_LPWR_CHNMSK_VAL, AR_PCU_SMPS_LPWR_CHNMSK) | SM(ahp->ah_rx_chainmask, AR_PCU_SMPS_HPWR_CHNMSK) | AR_PCU_SMPS_MAC_CHAINMASK; /* Program registers according to required SM power mode.*/ switch (mode) { case HAL_SMPS_SW_CTRL_LOW_PWR: OS_REG_WRITE(ah, AR_PCU_SMPS, regval); break; case HAL_SMPS_SW_CTRL_HIGH_PWR: OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_SW_CTRL_HPWR); break; case HAL_SMPS_HW_CTRL: OS_REG_WRITE(ah, AR_PCU_SMPS, regval | AR_PCU_SMPS_HW_CTRL_EN); break; case HAL_SMPS_DEFAULT: OS_REG_WRITE(ah, AR_PCU_SMPS, 0); break; default: break; } ahp->ah_sm_power_mode = mode; } #if ATH_WOW #if NOT_NEEDED_FOR_OSPREY /* not compiled for darwin */ /* * This routine is called to configure the SerDes register for the * Merlin 2.0 and above chip during WOW sleep. */ static void ar9280_config_ser_des__wow_sleep(struct ath_hal *ah) { int i; struct ath_hal_9300 *ahp = AH9300(ah); /* * For WOW sleep, we reprogram the SerDes so that the PLL and CHK REQ * are both enabled. This uses more power but the Maverick team reported * that otherwise, WOW sleep is unstable and chip may disappears. */ for (i = 0; i < ahp->ah_ini_pcie_serdes_wow.ia_rows; i++) { OS_REG_WRITE(ah, INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 0), INI_RA(&ahp->ah_ini_pcie_serdes_wow, i, 1)); } OS_DELAY(1000); } #endif /* if NOT_NEEDED_FOR_OSPREY */ static HAL_BOOL ar9300_wow_create_keep_alive_pattern(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t frame_len = 28; u_int32_t tpc = 0x3f; u_int32_t transmit_rate; u_int32_t frame_type = 0x2; /* Frame Type -> Data; */ u_int32_t sub_type = 0x4; /* Subtype -> Null Data */ u_int32_t to_ds = 1; u_int32_t duration_id = 0x3d; u_int8_t *sta_mac_addr, *ap_mac_addr; u_int8_t *addr1, *addr2, *addr3; u_int32_t ctl[13] = { 0, }; #define NUM_KA_DATA_WORDS 6 u_int32_t data_word[NUM_KA_DATA_WORDS]; u_int32_t i; u_int32_t wow_ka_dataword0; sta_mac_addr = (u_int8_t *)ahp->ah_macaddr; ap_mac_addr = (u_int8_t *)ahp->ah_bssid; addr2 = sta_mac_addr; addr1 = addr3 = ap_mac_addr; if (AH_PRIVATE(ah)->ah_curchan->channel_flags & CHANNEL_CCK) { transmit_rate = 0x1B; /* CCK_1M */ } else { transmit_rate = 0xB; /* OFDM_6M */ } /* Set the Transmit Buffer. */ ctl[0] = (frame_len | (tpc << 16)); ctl[1] = 0; ctl[2] = (0x7 << 16); /* tx_tries0 */ ctl[3] = transmit_rate; ctl[4] = 0; ctl[7] = ahp->ah_tx_chainmask << 2; for (i = 0; i < 13; i++) { OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); } data_word[0] = (frame_type << 2) | (sub_type << 4) | (to_ds << 8) | (duration_id << 16); data_word[1] = (((u_int32_t)addr1[3] << 24) | ((u_int32_t)addr1[2] << 16) | ((u_int32_t)addr1[1]) << 8 | ((u_int32_t)addr1[0])); data_word[2] = (((u_int32_t)addr2[1] << 24) | ((u_int32_t)addr2[0] << 16) | ((u_int32_t)addr1[5]) << 8 | ((u_int32_t)addr1[4])); data_word[3] = (((u_int32_t)addr2[5] << 24) | ((u_int32_t)addr2[4] << 16) | ((u_int32_t)addr2[3]) << 8 | ((u_int32_t)addr2[2])); data_word[4] = (((u_int32_t)addr3[3] << 24) | ((u_int32_t)addr3[2] << 16) | ((u_int32_t)addr3[1]) << 8 | (u_int32_t)addr3[0]); data_word[5] = (((u_int32_t)addr3[5]) << 8 | ((u_int32_t)addr3[4])); if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { /* Jupiter 2.0 has an extra descriptor word (Time based * discard) compared to other chips */ OS_REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + 12 * 4), 0); wow_ka_dataword0 = AR_WOW_TXBUF(13); } else { wow_ka_dataword0 = AR_WOW_TXBUF(12); } for (i = 0; i < NUM_KA_DATA_WORDS; i++) { OS_REG_WRITE(ah, (wow_ka_dataword0 + i * 4), data_word[i]); } return AH_TRUE; } /* TBD: Should querying hal for hardware capability */ #define MAX_PATTERN_SIZE 256 #define MAX_PATTERN_MASK_SIZE 32 #define MAX_NUM_USER_PATTERN 6 /* Deducting the disassoc/deauth packets */ void ar9300_wow_apply_pattern( struct ath_hal *ah, u_int8_t *p_ath_pattern, u_int8_t *p_ath_mask, int32_t pattern_count, u_int32_t ath_pattern_len) { int i; u_int32_t reg_pat[] = { AR_WOW_TB_PATTERN0, AR_WOW_TB_PATTERN1, AR_WOW_TB_PATTERN2, AR_WOW_TB_PATTERN3, AR_WOW_TB_PATTERN4, AR_WOW_TB_PATTERN5, AR_WOW_TB_PATTERN6, AR_WOW_TB_PATTERN7 }; u_int32_t reg_mask[] = { AR_WOW_TB_MASK0, AR_WOW_TB_MASK1, AR_WOW_TB_MASK2, AR_WOW_TB_MASK3, AR_WOW_TB_MASK4, AR_WOW_TB_MASK5, AR_WOW_TB_MASK6, AR_WOW_TB_MASK7 }; u_int32_t pattern_val; u_int32_t mask_val; u_int32_t val; u_int8_t mask_bit = 0x1; u_int8_t pattern; /* TBD: should check count by querying the hardware capability */ if (pattern_count >= MAX_NUM_USER_PATTERN) { return; } pattern = (u_int8_t)OS_REG_READ(ah, AR_WOW_PATTERN_REG); pattern = pattern | (mask_bit << pattern_count); OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, pattern); /* Set the registers for pattern */ for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { pattern_val = (((u_int32_t)p_ath_pattern[i + 0]) | ((u_int32_t)p_ath_pattern[i + 1] << 8) | ((u_int32_t)p_ath_pattern[i + 2] << 16) | ((u_int32_t)p_ath_pattern[i + 3] << 24)); OS_REG_WRITE(ah, (reg_pat[pattern_count] + i), pattern_val); } /* Set the registers for mask */ for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { mask_val = (((u_int32_t)p_ath_mask[i + 0]) | ((u_int32_t)p_ath_mask[i + 1] << 8) | ((u_int32_t)p_ath_mask[i + 2] << 16) | ((u_int32_t)p_ath_mask[i + 3] << 24)); OS_REG_WRITE(ah, (reg_mask[pattern_count] + i), mask_val); } /* XXX */ /* Set the pattern length to be matched */ if (pattern_count < 4) { /* Pattern 0-3 uses AR_WOW_LENGTH1_REG register */ val = OS_REG_READ(ah, AR_WOW_LENGTH1_REG); val = ((val & (~AR_WOW_LENGTH1_MASK(pattern_count))) | ((ath_pattern_len & AR_WOW_LENGTH_MAX) << AR_WOW_LENGTH1_SHIFT(pattern_count))); OS_REG_WRITE(ah, AR_WOW_LENGTH1_REG, val); } else { /* Pattern 4-7 uses AR_WOW_LENGTH2_REG register */ val = OS_REG_READ(ah, AR_WOW_LENGTH2_REG); val = ((val & (~AR_WOW_LENGTH2_MASK(pattern_count))) | ((ath_pattern_len & AR_WOW_LENGTH_MAX) << AR_WOW_LENGTH2_SHIFT(pattern_count))); OS_REG_WRITE(ah, AR_WOW_LENGTH2_REG, val); } AH_PRIVATE(ah)->ah_wow_event_mask |= (1 << (pattern_count + AR_WOW_PATTERN_FOUND_SHIFT)); return; } HAL_BOOL ar9300_set_power_mode_wow_sleep(struct ath_hal *ah) { OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */ - if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { + if (!ath_hal_waitfor(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: dma failed to stop in 10ms\n" "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__, OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW)); return AH_FALSE; } else { #if 0 OS_REG_WRITE(ah, AR_RXDP, 0x0); #endif HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: TODO How to disable RXDP!!\n", __func__); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); return AH_TRUE; } } HAL_BOOL ar9300_wow_enable( struct ath_hal *ah, u_int32_t pattern_enable, u_int32_t timeout_in_seconds, int clearbssid, HAL_BOOL offloadEnable) { uint32_t init_val, val, rval = 0; const int ka_delay = 4; /* Delay of 4 millisec between two keep_alive's */ uint32_t wow_event_mask; #if ATH_WOW_OFFLOAD uint32_t wow_feature_enable = //AR_WOW_OFFLOAD_ENA_GTK | //AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD | //AR_WOW_OFFLOAD_ENA_NS_OFFLOAD | //AR_WOW_OFFLOAD_ENA_ACER_MAGIC | //AR_WOW_OFFLOAD_ENA_STD_MAGIC | //AR_WOW_OFFLOAD_ENA_4WAY_WAKE | //AR_WOW_OFFLOAD_ENA_SWKA | //AR_WOW_OFFLOAD_ENA_BT_SLEEP | AR_WOW_OFFLOAD_ENA_SW_NULL; #endif /* * ah_wow_event_mask is a mask to the AR_WOW_PATTERN_REG register to * indicate which WOW events that we have enabled. The WOW Events are * from the pattern_enable in this function and pattern_count of * ar9300_wow_apply_pattern() */ wow_event_mask = AH_PRIVATE(ah)->ah_wow_event_mask; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: offload: %d, pattern: %08x, event_mask: %08x\n", __func__, offloadEnable, pattern_enable, wow_event_mask); /* * Untie Power-On-Reset from the PCI-E Reset. When we are in WOW sleep, * we do not want the Reset from the PCI-E to disturb our hw state. */ if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) { u_int32_t wa_reg_val; /* * We need to untie the internal POR (power-on-reset) to the external * PCI-E reset. We also need to tie the PCI-E Phy reset to the PCI-E * reset. */ HAL_DEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Untie POR and PCIE reset\n", __func__); wa_reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_WA)); wa_reg_val = wa_reg_val & ~(AR_WA_UNTIE_RESET_EN); wa_reg_val = wa_reg_val | AR_WA_RESET_EN | AR_WA_POR_SHORT; /* * This bit is to bypass the EEPROM/OTP state machine, (by clearing its * busy state while PCIE_rst is asserted), to allow BT embedded CPU * be able to access WLAN registers. Otherwise the eCPU access will be * stalled as eeprom_sm is held in busy state. * * EV91928 is that when this bit is set, after host wakeup and PCIE_rst * deasserted, PCIE configuration registers will be reset and DeviceID * SubsystemID etc. registers will be different from values before * entering sleep. This will cause Windows to detect a device removal. * * For HW WOW, this bit should keep as cleared. */ if (offloadEnable) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Set AR_WA.13 COLD_RESET_OVERRIDE\n", __func__); wa_reg_val = wa_reg_val | AR_WA_COLD_RESET_OVERRIDE; #if ATH_WOW_OFFLOAD if (AR_SREV_JUPITER(ah)) { wa_reg_val = wa_reg_val | AR_WA_D3_TO_L1_DISABLE; } #endif } OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), wa_reg_val); } /* * Set the power states appropriately and enable pme. */ val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL)); val |= AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | AR_PMCTRL_AUX_PWR_DET; /* * Set and clear WOW_PME_CLEAR registers for the chip to generate next * wow signal. */ val |= AR_PMCTRL_WOW_PME_CLR; OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val); val &= ~AR_PMCTRL_WOW_PME_CLR; OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val); /* * Setup for for: * - beacon misses * - magic pattern * - keep alive timeout * - pattern matching */ /* * Program some default values for keep-alives, beacon misses, etc. */ init_val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); val = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF) | init_val; OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val); rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG); val = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); OS_REG_WRITE(ah, AR_WOW_COUNT_REG, val); rval = OS_REG_READ(ah, AR_WOW_COUNT_REG); if (pattern_enable & AH_WOW_BEACON_MISS) { val = AR_WOW_BEACON_TIMO; } else { /* We are not using the beacon miss. Program a large value. */ val = AR_WOW_BEACON_TIMO_MAX; } OS_REG_WRITE(ah, AR_WOW_BCN_TIMO_REG, val); rval = OS_REG_READ(ah, AR_WOW_BCN_TIMO_REG); /* * Keep Alive Timo in ms. */ if (pattern_enable == 0) { val = AR_WOW_KEEP_ALIVE_NEVER; } else { val = AH_PRIVATE(ah)->ah_config.ath_hal_keep_alive_timeout * 32; } OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO_REG, val); rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_TIMO_REG); /* * Keep Alive delay in us. */ val = ka_delay * 1000; OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY_REG, val); rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_DELAY_REG); /* * Create keep_alive Pattern to respond to beacons. */ ar9300_wow_create_keep_alive_pattern(ah); /* * Configure Mac Wow Registers. */ val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG); /* * Send keep alive timeouts anyway. */ val &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS; if (pattern_enable & AH_WOW_LINK_CHANGE) { val &= ~ AR_WOW_KEEP_ALIVE_FAIL_DIS; wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; } else { val |= AR_WOW_KEEP_ALIVE_FAIL_DIS; } #if ATH_WOW_OFFLOAD if (offloadEnable) { /* Don't enable KA frames yet. BT CPU is not * yet ready. */ } else #endif /* ATH_WOW_OFFLOAD */ { OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_REG, val); val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG); } /* * We are relying on a bmiss failure. Ensure we have enough * threshold to prevent AH_FALSE positives. */ OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, AR_WOW_BMISSTHRESHOLD); val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG); if (pattern_enable & AH_WOW_BEACON_MISS) { val |= AR_WOW_BEACON_FAIL_EN; wow_event_mask |= AR_WOW_BEACON_FAIL; } else { val &= ~AR_WOW_BEACON_FAIL_EN; } OS_REG_WRITE(ah, AR_WOW_BCN_EN_REG, val); val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG); /* * Enable the magic packet registers. */ val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); if ((pattern_enable & AH_WOW_MAGIC_PATTERN_EN) #if ATH_WOW_OFFLOAD || (pattern_enable & AH_WOW_ACER_MAGIC_EN) #endif ) { val |= AR_WOW_MAGIC_EN; wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; } else { val &= ~AR_WOW_MAGIC_EN; } val |= AR_WOW_MAC_INTR_EN; OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val); val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); #if ATH_WOW_OFFLOAD if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_BT_SLEEP)) { wow_feature_enable |= AR_WOW_OFFLOAD_ENA_BT_SLEEP; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - BT SLEEP\n"); } else { wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_BT_SLEEP; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - BT SLEEP\n"); } if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_SW_NULL_DISABLE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - SW NULL\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SW_NULL; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - SW NULL\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SW_NULL; } if (HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_DEVID_SWAR_DISABLE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - DevID SWAR\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_DEVID_SWAR; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - DevID SWAR\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_DEVID_SWAR; } if (pattern_enable & AH_WOW_ACER_KEEP_ALIVE_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer SWKA\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_SWKA; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer SWKA\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_SWKA; } if (pattern_enable & AH_WOW_ACER_MAGIC_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Standard Magic\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_STD_MAGIC; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Acer Magic\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ACER_MAGIC; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - Standard Magic\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_STD_MAGIC; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - Acer Magic\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ACER_MAGIC; } if ((pattern_enable & AH_WOW_4WAY_HANDSHAKE_EN) || HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_4WAY_HS_WAKE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - 4Way Handshake\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_4WAY_WAKE; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - 4Way Handshake\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_4WAY_WAKE; } if((pattern_enable & AH_WOW_AP_ASSOCIATION_LOST_EN) || HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_AP_LOSS_WAKE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - AP loss wake\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - AP loss wake\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE; } if((pattern_enable & AH_WOW_GTK_HANDSHAKE_ERROR_EN) || HAL_WOW_CTRL(ah, HAL_WOW_OFFLOAD_FORCE_GTK_ERR_WAKE)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK error wake\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK error wake\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE; } if (pattern_enable & AH_WOW_GTK_OFFLOAD_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - GTK offload\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_GTK; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - GTK offload\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_GTK; } if (pattern_enable & AH_WOW_ARP_OFFLOAD_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - ARP offload\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - ARP offload\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD; } if (pattern_enable & AH_WOW_NS_OFFLOAD_EN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) ENA - NS offload\n"); wow_feature_enable |= AR_WOW_OFFLOAD_ENA_NS_OFFLOAD; } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) DIS - NS offload\n"); wow_feature_enable &= ~AR_WOW_OFFLOAD_ENA_NS_OFFLOAD; } #endif /* ATH_WOW_OFFLOAD */ /* For Kite and later version of the chips * enable wow pattern match for packets less than * 256 bytes for all patterns. */ /* XXX */ OS_REG_WRITE( ah, AR_WOW_PATTERN_MATCH_LT_256B_REG, AR_WOW_PATTERN_SUPPORTED); /* * Set the power states appropriately and enable PME. */ val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL)); val |= AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA; val &= ~AR_PCIE_PM_CTRL_ENA; OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val); /* Wake on Timer Interrupt. Test mode only. Used in Manufacturing line. */ if (timeout_in_seconds) { /* convert Timeout to u_secs */ OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER, OS_REG_READ(ah, AR_TSF_L32) + timeout_in_seconds * 1000000 ); /* timer_period = 30 seconds always */ OS_REG_WRITE(ah, AR_NDP_PERIOD, 30 * 1000000); OS_REG_WRITE(ah, AR_TIMER_MODE, OS_REG_READ(ah, AR_TIMER_MODE) | 0x80); OS_REG_WRITE(ah, AR_IMR_S5, OS_REG_READ(ah, AR_IMR_S5) | 0x80); OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_GENTMR); if (clearbssid) { OS_REG_WRITE(ah, AR_BSS_ID0, 0); OS_REG_WRITE(ah, AR_BSS_ID1, 0); } } /* Enable Seq# generation when asleep. */ OS_REG_WRITE(ah, AR_STA_ID1, OS_REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_PRESERVE_SEQNUM); AH_PRIVATE(ah)->ah_wow_event_mask = wow_event_mask; #if ATH_WOW_OFFLOAD if (offloadEnable) { /* Force MAC awake before entering SW WoW mode */ OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif OS_REG_WRITE(ah, AR_WOW_OFFLOAD_COMMAND_JUPITER, wow_feature_enable); OS_REG_WRITE(ah, AR_WOW_OFFLOAD_STATUS_JUPITER, 0x0); if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_SW_NULL) { OS_REG_WRITE(ah, AR_WOW_SW_NULL_PARAMETER, ((1000) | (4 << AR_WOW_SW_NULL_SHORT_PERIOD_MASK_S))); } if (wow_feature_enable & AR_WOW_OFFLOAD_ENA_DEVID_SWAR) { ar9300_wowoffload_download_devid_swar(ah); } ar9300_wow_offload_download_hal_params(ah); ar9300_wow_offload_handshake(ah, pattern_enable); AH9300(ah)->ah_chip_full_sleep = AH_FALSE; //OS_REG_SET_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE); } else #endif /* ATH_WOW_OFFLOAD */ { #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif ar9300_set_power_mode_wow_sleep(ah); AH9300(ah)->ah_chip_full_sleep = AH_TRUE; } return (AH_TRUE); } u_int32_t //ar9300_wow_wake_up(struct ath_hal *ah, u_int8_t *chipPatternBytes) ar9300_wow_wake_up(struct ath_hal *ah, HAL_BOOL offloadEnabled) { uint32_t wow_status = 0; uint32_t val = 0, rval; OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_HW_WOW_DISABLE); OS_REG_CLR_BIT(ah, AR_SW_WOW_CONTROL, AR_SW_WOW_ENABLE); #if ATH_WOW_OFFLOAD /* If WoW was offloaded to embedded CPU, use the global * shared register to know the wakeup reason */ if (offloadEnabled) { val = OS_REG_READ(ah, AR_EMB_CPU_WOW_STATUS); if (val) { if (val & AR_EMB_CPU_WOW_STATUS_MAGIC_PATTERN) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW MAGIC_PATTERN\n"); wow_status |= AH_WOW_MAGIC_PATTERN_EN; } if (val & AR_EMB_CPU_WOW_STATUS_PATTERN_MATCH) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW USER_PATTERN\n"); wow_status |= AH_WOW_USER_PATTERN_EN; } if (val & AR_EMB_CPU_WOW_STATUS_KEEP_ALIVE_FAIL) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW KEEP_ALIVE_FAIL\n"); wow_status |= AH_WOW_LINK_CHANGE; } if (val & AR_EMB_CPU_WOW_STATUS_BEACON_MISS) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) SW BEACON_FAIL\n"); wow_status |= AH_WOW_BEACON_MISS; } } /* Clear status and mask registers */ OS_REG_WRITE(ah, AR_EMB_CPU_WOW_STATUS, 0x0); OS_REG_WRITE(ah, AR_EMB_CPU_WOW_ENABLE, 0); OS_REG_WRITE(ah, AR_MBOX_CTRL_STATUS, 0); } else #endif /* ATH_WOW_OFFLOAD */ { /* * Read the WOW Status register to know the wakeup reason. */ rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG); val = AR_WOW_STATUS(rval); /* * Mask only the WOW events that we have enabled. * Sometimes we have spurious WOW events from the AR_WOW_PATTERN_REG * register. This mask will clean it up. */ val &= AH_PRIVATE(ah)->ah_wow_event_mask; if (val) { if (val & AR_WOW_MAGIC_PAT_FOUND) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW MAGIC_PATTERN\n"); wow_status |= AH_WOW_MAGIC_PATTERN_EN; } if (AR_WOW_PATTERN_FOUND(val)) { //int i, offset; //offset = OS_REG_READ(ah, AR_WOW_RXBUF_START_ADDR); //// Read matched pattern for wake packet detection indication. //for( i = 0; i< MAX_PATTERN_SIZE/4; i+=4) //{ // // RX FIFO is only 8K wrapping. // if(offset >= 8 * 1024 / 4) offset = 0; // *(u_int32_t*)(chipPatternBytes + i) = OS_REG_READ( ah,offset ); // offset++; //} wow_status |= AH_WOW_USER_PATTERN_EN; HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW USER_PATTERN\n"); } if (val & AR_WOW_KEEP_ALIVE_FAIL) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW KEEP_ALIVE_FAIL\n"); wow_status |= AH_WOW_LINK_CHANGE; } if (val & AR_WOW_BEACON_FAIL) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "(WOW) HW BEACON_FAIL\n"); wow_status |= AH_WOW_BEACON_MISS; } } } /* * Set and clear WOW_PME_CLEAR registers for the chip to generate next * wow signal. * Disable D3 before accessing other registers ? */ val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL)); /* Check the bit value 0x01000000 (7-10)? */ val &= ~AR_PMCTRL_PWR_STATE_D1D3; val |= AR_PMCTRL_WOW_PME_CLR; OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), val); /* * Clear all events. */ OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, AR_WOW_CLEAR_EVENTS(OS_REG_READ(ah, AR_WOW_PATTERN_REG))); //HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, // "%s: Skip PCIE WA programming\n", __func__); #if 0 /* * Tie reset register. * FIXME: Per David Quan not tieing it back might have some repurcussions. */ /* XXX */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), OS_REG_READ(ah, AR_WA) | AR_WA_UNTIE_RESET_EN | AR_WA_POR_SHORT | AR_WA_RESET_EN); #endif /* Restore the Beacon Threshold to init value */ OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, INIT_RSSI_THR); /* * Restore the way the PCI-E Reset, Power-On-Reset, external PCIE_POR_SHORT * pins are tied to its original value. Previously just before WOW sleep, * we untie the PCI-E Reset to our Chip's Power On Reset so that * any PCI-E reset from the bus will not reset our chip. */ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: restore AR_WA\n", __func__); if (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE) { ar9300_config_pci_power_save(ah, 0, 0); } AH_PRIVATE(ah)->ah_wow_event_mask = 0; HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "(WOW) wow_status=%08x\n", wow_status); return (wow_status); } void ar9300_wow_set_gpio_reset_low(struct ath_hal *ah) { uint32_t val; val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)); val |= (1 << (2 * 2)); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), val); val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)); /* val = OS_REG_READ(ah,AR_GPIO_IN_OUT ); */ } #endif /* ATH_WOW */ Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c (revision 278741) @@ -1,195 +1,197 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_desc.h" #include "ah_internal.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300desc.h" /* * Process an RX descriptor, and return the status to the caller. * Copy some hardware specific items into the software portion * of the descriptor. * * NB: the caller is responsible for validating the memory contents * of the descriptor (e.g. flushing any cached copy). */ HAL_STATUS ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds, u_int32_t pa, struct ath_desc *nds, struct ath_rx_status *rxs, void *buf_addr) { struct ar9300_rxs *rxsp = AR9300RXS(buf_addr); /* ath_hal_printf(ah,"CHH=RX: ds_info 0x%x status1: 0x%x status11: 0x%x\n", rxsp->ds_info,rxsp->status1,rxsp->status11); */ if ((rxsp->status11 & AR_rx_done) == 0) { return HAL_EINPROGRESS; } if (MS(rxsp->ds_info, AR_desc_id) != 0x168c) { #if __PKT_SERIOUS_ERRORS__ /*BUG: 63564-HT */ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Rx Descriptor error 0x%x\n", __func__, rxsp->ds_info); #endif return HAL_EINVAL; } if ((rxsp->ds_info & (AR_tx_rx_desc | AR_ctrl_stat)) != 0) { #if __PKT_SERIOUS_ERRORS__ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Rx Descriptor wrong info 0x%x\n", __func__, rxsp->ds_info); #endif return HAL_EINPROGRESS; } rxs->rs_status = 0; rxs->rs_flags = 0; + rxs->rs_phyerr = 0; rxs->rs_datalen = rxsp->status2 & AR_data_len; rxs->rs_tstamp = rxsp->status3; /* XXX what about key_cache_miss? */ rxs->rs_rssi = MS(rxsp->status5, AR_rx_rssi_combined); rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_rx_rssi_ant00); rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_rx_rssi_ant01); rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_rx_rssi_ant02); rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_rx_rssi_ant10); rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_rx_rssi_ant11); rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_rx_rssi_ant12); if (rxsp->status11 & AR_rx_key_idx_valid) { rxs->rs_keyix = MS(rxsp->status11, AR_key_idx); } else { rxs->rs_keyix = HAL_RXKEYIX_INVALID; } /* NB: caller expected to do rate table mapping */ rxs->rs_rate = MS(rxsp->status1, AR_rx_rate); rxs->rs_more = (rxsp->status2 & AR_rx_more) ? 1 : 0; rxs->rs_isaggr = (rxsp->status11 & AR_rx_aggr) ? 1 : 0; rxs->rs_moreaggr = (rxsp->status11 & AR_rx_more_aggr) ? 1 : 0; rxs->rs_antenna = (MS(rxsp->status4, AR_rx_antenna) & 0x7); rxs->rs_flags = (rxsp->status11 & AR_apsd_trig) ? HAL_RX_IS_APSD : 0; rxs->rs_flags |= (rxsp->status4 & AR_gi) ? HAL_RX_GI : 0; rxs->rs_flags |= (rxsp->status4 & AR_2040) ? HAL_RX_2040 : 0; /* Copy EVM information */ rxs->rs_evm0 = rxsp->status6; rxs->rs_evm1 = rxsp->status7; rxs->rs_evm2 = rxsp->status8; rxs->rs_evm3 = rxsp->status9; rxs->rs_evm4 = (rxsp->status10 & 0xffff); if (rxsp->status11 & AR_pre_delim_crc_err) { rxs->rs_flags |= HAL_RX_DELIM_CRC_PRE; } if (rxsp->status11 & AR_post_delim_crc_err) { rxs->rs_flags |= HAL_RX_DELIM_CRC_POST; } if (rxsp->status11 & AR_decrypt_busy_err) { rxs->rs_flags |= HAL_RX_DECRYPT_BUSY; } if (rxsp->status11 & AR_hi_rx_chain) { rxs->rs_flags |= HAL_RX_HI_RX_CHAIN; } if (rxsp->status11 & AR_key_miss) { rxs->rs_status |= HAL_RXERR_KEYMISS; } if ((rxsp->status11 & AR_rx_frame_ok) == 0) { /* * These four bits should not be set together. The * 9300 spec states a Michael error can only occur if * decrypt_crc_err not set (and TKIP is used). Experience * indicates however that you can also get Michael errors * when a CRC error is detected, but these are specious. * Consequently we filter them out here so we don't * confuse and/or complicate drivers. */ + if (rxsp->status11 & AR_crc_err) { rxs->rs_status |= HAL_RXERR_CRC; /* - * ignore CRC flag for spectral phy reports + * ignore CRC flag for phy reports */ if (rxsp->status11 & AR_phyerr) { u_int phyerr = MS(rxsp->status11, AR_phy_err_code); - if (phyerr == HAL_PHYERR_SPECTRAL) { - rxs->rs_status |= HAL_RXERR_PHY; - rxs->rs_phyerr = phyerr; - } + rxs->rs_status |= HAL_RXERR_PHY; + rxs->rs_phyerr = phyerr; } } else if (rxsp->status11 & AR_phyerr) { u_int phyerr; /* * Packets with OFDM_RESTART on post delimiter are CRC OK and * usable and MAC ACKs them. * To avoid packet from being lost, we remove the PHY Err flag * so that lmac layer does not drop them. * (EV 70071) */ phyerr = MS(rxsp->status11, AR_phy_err_code); if ((phyerr == HAL_PHYERR_OFDM_RESTART) && (rxsp->status11 & AR_post_delim_crc_err)) { rxs->rs_phyerr = 0; } else { rxs->rs_status |= HAL_RXERR_PHY; rxs->rs_phyerr = phyerr; } } else if (rxsp->status11 & AR_decrypt_crc_err) { rxs->rs_status |= HAL_RXERR_DECRYPT; } else if (rxsp->status11 & AR_michael_err) { rxs->rs_status |= HAL_RXERR_MIC; } } - +#if 0 + rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel; +#endif return HAL_OK; } HAL_STATUS ar9300_proc_rx_desc(struct ath_hal *ah, struct ath_desc *ds, u_int32_t pa, struct ath_desc *nds, u_int64_t tsf, struct ath_rx_status *rxs) { return HAL_ENOTSUPP; } /* * rx path in ISR is different for ar9300 from ar5416, and * ath_rx_proc_descfast will not be called if edmasupport is true. * So this function ath_hal_get_rxkeyidx will not be * called for ar9300. * This function in ar9300's HAL is just a stub one because we need * to link something to the callback interface of the HAL module. */ HAL_STATUS ar9300_get_rx_key_idx(struct ath_hal *ah, struct ath_desc *ds, u_int8_t *keyix, u_int8_t *status) { *status = 0; *keyix = HAL_RXKEYIX_INVALID; return HAL_ENOTSUPP; } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c (revision 278741) @@ -1,6203 +1,6404 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" #include "ah_desc.h" #include "ar9300.h" #include "ar9300reg.h" #include "ar9300phy.h" #include "ar9300desc.h" #define FIX_NOISE_FLOOR 1 - /* Additional Time delay to wait after activiting the Base band */ #define BASE_ACTIVATE_DELAY 100 /* usec */ #define RTC_PLL_SETTLE_DELAY 100 /* usec */ #define COEF_SCALE_S 24 #define HT40_CHANNEL_CENTER_SHIFT 10 /* MHz */ #define DELPT 32 /* XXX Duplicates! (in ar9300desc.h) */ #if 0 extern HAL_BOOL ar9300_reset_tx_queue(struct ath_hal *ah, u_int q); extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q); #endif #define MAX_MEASUREMENT 8 #define MAXIQCAL 3 struct coeff_t { int32_t mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; int32_t phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; int32_t iqc_coeff[2]; int last_nmeasurement; HAL_BOOL last_cal; }; static HAL_BOOL ar9300_tx_iq_cal_hw_run(struct ath_hal *ah); static void ar9300_tx_iq_cal_post_proc(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan, int iqcal_idx, int max_iqcal, HAL_BOOL is_cal_reusable, HAL_BOOL apply_last_corr); static void ar9300_tx_iq_cal_outlier_detection(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan, u_int32_t num_chains, struct coeff_t *coeff, HAL_BOOL is_cal_reusable); #if ATH_SUPPORT_CAL_REUSE static void ar9300_tx_iq_cal_apply(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan); #endif static inline void ar9300_prog_ini(struct ath_hal *ah, struct ar9300_ini_array *ini_arr, int column); static inline void ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan); static inline HAL_BOOL ar9300_init_cal(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL skip_if_none, HAL_BOOL apply_last_corr); static inline void ar9300_init_user_settings(struct ath_hal *ah); #ifdef HOST_OFFLOAD /* * For usb offload solution, some USB registers must be tuned * to gain better stability/performance but these registers * might be changed while doing wlan reset so do this here */ #define WAR_USB_DISABLE_PLL_LOCK_DETECT(__ah) \ do { \ if (AR_SREV_HORNET(__ah) || AR_SREV_WASP(__ah)) { \ volatile u_int32_t *usb_ctrl_r1 = (u_int32_t *) 0xb8116c84; \ volatile u_int32_t *usb_ctrl_r2 = (u_int32_t *) 0xb8116c88; \ *usb_ctrl_r1 = (*usb_ctrl_r1 & 0xffefffff); \ *usb_ctrl_r2 = (*usb_ctrl_r2 & 0xfc1fffff) | (1 << 21) | (3 << 22); \ } \ } while (0) #else #define WAR_USB_DISABLE_PLL_LOCK_DETECT(__ah) #endif static inline void ar9300_attach_hw_platform(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_hwp = HAL_TRUE_CHIP; return; } /* Adjust various register settings based on half/quarter rate clock setting. * This includes: +USEC, TX/RX latency, * + IFS params: slot, eifs, misc etc. * SIFS stays the same. */ static void ar9300_set_ifs_timing(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t tx_lat, rx_lat, usec, slot, regval, eifs; regval = OS_REG_READ(ah, AR_USEC); regval &= ~(AR_USEC_RX_LATENCY | AR_USEC_TX_LATENCY | AR_USEC_USEC); if (IEEE80211_IS_CHAN_HALF(chan)) { /* half rates */ slot = ar9300_mac_to_clks(ah, AR_SLOT_HALF); eifs = ar9300_mac_to_clks(ah, AR_EIFS_HALF); if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* fast clock */ rx_lat = SM(AR_RX_LATENCY_HALF_FAST_CLOCK, AR_USEC_RX_LATENCY); tx_lat = SM(AR_TX_LATENCY_HALF_FAST_CLOCK, AR_USEC_TX_LATENCY); usec = SM(AR_USEC_HALF_FAST_CLOCK, AR_USEC_USEC); } else { rx_lat = SM(AR_RX_LATENCY_HALF, AR_USEC_RX_LATENCY); tx_lat = SM(AR_TX_LATENCY_HALF, AR_USEC_TX_LATENCY); usec = SM(AR_USEC_HALF, AR_USEC_USEC); } } else { /* quarter rate */ slot = ar9300_mac_to_clks(ah, AR_SLOT_QUARTER); eifs = ar9300_mac_to_clks(ah, AR_EIFS_QUARTER); if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* fast clock */ rx_lat = SM(AR_RX_LATENCY_QUARTER_FAST_CLOCK, AR_USEC_RX_LATENCY); tx_lat = SM(AR_TX_LATENCY_QUARTER_FAST_CLOCK, AR_USEC_TX_LATENCY); usec = SM(AR_USEC_QUARTER_FAST_CLOCK, AR_USEC_USEC); } else { rx_lat = SM(AR_RX_LATENCY_QUARTER, AR_USEC_RX_LATENCY); tx_lat = SM(AR_TX_LATENCY_QUARTER, AR_USEC_TX_LATENCY); usec = SM(AR_USEC_QUARTER, AR_USEC_USEC); } } OS_REG_WRITE(ah, AR_USEC, (usec | regval | tx_lat | rx_lat)); OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); } /* * This inline function configures the chip either * to encrypt/decrypt management frames or pass thru */ static inline void ar9300_init_mfp(struct ath_hal * ah) { u_int32_t mfpcap, mfp_qos; ath_hal_getcapability(ah, HAL_CAP_MFP, 0, &mfpcap); if (mfpcap == HAL_MFP_QOSDATA) { /* Treat like legacy hardware. Do not touch the MFP registers. */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s forced to use QOSDATA\n", __func__); return; } /* MFP support (Sowl 1.0 or greater) */ if (mfpcap == HAL_MFP_HW_CRYPTO) { /* configure hardware MFP support */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s using HW crypto\n", __func__); OS_REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, AR_AES_MUTE_MASK1_FC_MGMT_MFP); OS_REG_RMW(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE, AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); /* * Mask used to construct AAD for CCMP-AES * Cisco spec defined bits 0-3 as mask * IEEE802.11w defined as bit 4. */ if (ath_hal_get_mfp_qos(ah)) { mfp_qos = AR_MFP_QOS_MASK_IEEE; } else { mfp_qos = AR_MFP_QOS_MASK_CISCO; } OS_REG_RMW_FIELD(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_QOS, mfp_qos); } else if (mfpcap == HAL_MFP_PASSTHRU) { /* Disable en/decrypt by hardware */ HALDEBUG(ah, HAL_DEBUG_RESET, "%s using passthru\n", __func__); OS_REG_RMW(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT, AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); } } void ar9300_get_channel_centers(struct ath_hal *ah, const struct ieee80211_channel *chan, CHAN_CENTERS *centers) { int8_t extoff; struct ath_hal_9300 *ahp = AH9300(ah); HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); if (!IEEE80211_IS_CHAN_HT40(chan)) { centers->ctl_center = centers->ext_center = centers->synth_center = ichan->channel; return; } HALASSERT(IEEE80211_IS_CHAN_HT40(chan)); /* * In 20/40 phy mode, the center frequency is * "between" the primary and extension channels. */ if (IEEE80211_IS_CHAN_HT40U(chan)) { centers->synth_center = ichan->channel + HT40_CHANNEL_CENTER_SHIFT; extoff = 1; } else { centers->synth_center = ichan->channel - HT40_CHANNEL_CENTER_SHIFT; extoff = -1; } centers->ctl_center = centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); centers->ext_center = centers->synth_center + (extoff * ((ahp->ah_ext_prot_spacing == HAL_HT_EXTPROTSPACING_20) ? HT40_CHANNEL_CENTER_SHIFT : 15)); } /* * Read the noise-floor values from the HW. * Specifically, read the minimum clear-channel assessment value for * each chain, for both the control and extension channels. * (The received power level during clear-channel periods is the * noise floor.) * These noise floor values computed by the HW will be stored in the * NF history buffer. * The HW sometimes produces bogus NF values. To avoid using these * bogus values, the NF data is (a) range-limited, and (b) filtered. * However, this data-processing is done when reading the NF values * out of the history buffer. The history buffer stores the raw values. * This allows the NF history buffer to be used to check for interference. * A single high NF reading might be a bogus HW value, but if the NF * readings are consistently high, it must be due to interference. * This is the purpose of storing raw NF values in the history buffer, * rather than processed values. By looking at a history of NF values * that have not been range-limited, we can check if they are consistently * high (due to interference). */ #define AH_NF_SIGN_EXTEND(nf) \ ((nf) & 0x100) ? \ 0 - (((nf) ^ 0x1ff) + 1) : \ (nf) void ar9300_upload_noise_floor(struct ath_hal *ah, int is_2g, int16_t nfarray[HAL_NUM_NF_READINGS]) { int16_t nf; int chan, chain; u_int32_t regs[HAL_NUM_NF_READINGS] = { /* control channel */ AR_PHY_CCA_0, /* chain 0 */ AR_PHY_CCA_1, /* chain 1 */ AR_PHY_CCA_2, /* chain 2 */ /* extension channel */ AR_PHY_EXT_CCA, /* chain 0 */ AR_PHY_EXT_CCA_1, /* chain 1 */ AR_PHY_EXT_CCA_2, /* chain 2 */ }; u_int8_t chainmask; /* * Within a given channel (ctl vs. ext), the CH0, CH1, and CH2 * masks and shifts are the same, though they differ for the * control vs. extension channels. */ u_int32_t masks[2] = { AR_PHY_MINCCA_PWR, /* control channel */ AR_PHY_EXT_MINCCA_PWR, /* extention channel */ }; u_int8_t shifts[2] = { AR_PHY_MINCCA_PWR_S, /* control channel */ AR_PHY_EXT_MINCCA_PWR_S, /* extention channel */ }; /* * Force NF calibration for all chains. */ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { chainmask = 0x01; } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah)) { chainmask = 0x03; } else { chainmask = 0x07; } for (chan = 0; chan < 2 /*ctl,ext*/; chan++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { int i; if (!((chainmask >> chain) & 0x1)) { continue; } i = chan * AR9300_MAX_CHAINS + chain; nf = (OS_REG_READ(ah, regs[i]) & masks[chan]) >> shifts[chan]; nfarray[i] = AH_NF_SIGN_EXTEND(nf); } } } /* ar9300_get_min_cca_pwr - * Used by the scan function for a quick read of the noise floor. * This is used to detect presence of CW interference such as video bridge. * The noise floor is assumed to have been already started during reset * called during channel change. The function checks if the noise floor * reading is done. In case it has been done, it reads the noise floor value. * If the noise floor calibration has not been finished, it assumes this is * due to presence of CW interference an returns a high value for noise floor, * derived from the CW interference threshold + margin fudge factor. */ #define BAD_SCAN_NF_MARGIN (30) int16_t ar9300_get_min_cca_pwr(struct ath_hal *ah) { int16_t nf; // struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) { nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR9280_PHY_MINCCA_PWR); if (nf & 0x100) { nf = 0 - ((nf ^ 0x1ff) + 1); } } else { /* NF calibration is not done, assume CW interference */ nf = AH9300(ah)->nfp->nominal + AH9300(ah)->nf_cw_int_delta + BAD_SCAN_NF_MARGIN; } return nf; } /* * Noise Floor values for all chains. * Most recently updated values from the NF history buffer are used. */ void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf, struct ieee80211_channel *chan, int is_scan) { struct ath_hal_9300 *ahp = AH9300(ah); int i, nf_hist_len, recent_nf_index = 0; HAL_NFCAL_HIST_FULL *h; u_int8_t rx_chainmask = ahp->ah_rx_chainmask | (ahp->ah_rx_chainmask << 3); HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); HALASSERT(ichan); #ifdef ATH_NF_PER_CHAN /* Fill 0 if valid internal channel is not found */ if (ichan == AH_NULL) { OS_MEMZERO(nf_buf, sizeof(nf_buf[0])*HAL_NUM_NF_READINGS); return; } h = &ichan->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL; #else /* * If a scan is not in progress, then the most recent value goes * into ahpriv->nf_cal_hist. If a scan is in progress, then * the most recent value goes into ichan->nf_cal_hist. * Thus, return the value from ahpriv->nf_cal_hist if there's * no scan, and if the specified channel is the current channel. * Otherwise, return the noise floor from ichan->nf_cal_hist. */ if ((!is_scan) && chan == AH_PRIVATE(ah)->ah_curchan) { h = &AH_PRIVATE(ah)->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL; } else { /* Fill 0 if valid internal channel is not found */ if (ichan == AH_NULL) { OS_MEMZERO(nf_buf, sizeof(nf_buf[0])*HAL_NUM_NF_READINGS); return; } /* * It is okay to treat a HAL_NFCAL_HIST_SMALL struct as if it were a * HAL_NFCAL_HIST_FULL struct, as long as only the index 0 of the * nf_cal_buffer is used (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1]) */ h = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL; } #endif /* Get most recently updated values from nf cal history buffer */ recent_nf_index = (h->base.curr_index) ? h->base.curr_index - 1 : nf_hist_len - 1; for (i = 0; i < HAL_NUM_NF_READINGS; i++) { /* Fill 0 for unsupported chains */ if (!(rx_chainmask & (1 << i))) { nf_buf[i] = 0; continue; } nf_buf[i] = h->nf_cal_buffer[recent_nf_index][i]; } } +/* + * Return the current NF value in register. + * If the current NF cal is not completed, return 0. + */ +int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time) +{ + int16_t nfarray[HAL_NUM_NF_READINGS] = {0}; + int is_2g = 0; + HAL_CHANNEL_INTERNAL *ichan = NULL; + ichan = ath_hal_checkchannel(ah, chan); + if (ichan == NULL) + return (0); + + if (wait_time <= 0) { + return 0; + } + + if (!ath_hal_waitfor(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0, wait_time)) { + ath_hal_printf(ah, "%s: NF cal is not complete in %dus", __func__, wait_time); + return 0; + } + is_2g = !! (IS_CHAN_2GHZ(ichan)); + ar9300_upload_noise_floor(ah, is_2g, nfarray); + + return nfarray[0]; +} + /* * Pick up the medium one in the noise floor buffer and update the * corresponding range for valid noise floor values */ static int16_t ar9300_get_nf_hist_mid(struct ath_hal *ah, HAL_NFCAL_HIST_FULL *h, int reading, int hist_len) { int16_t nfval; int16_t sort[HAL_NF_CAL_HIST_LEN_FULL]; /* upper bound for hist_len */ int i, j; + for (i = 0; i < hist_len; i++) { sort[i] = h->nf_cal_buffer[i][reading]; HALDEBUG(ah, HAL_DEBUG_NFCAL, "nf_cal_buffer[%d][%d] = %d\n", i, reading, (int)sort[i]); } for (i = 0; i < hist_len - 1; i++) { for (j = 1; j < hist_len - i; j++) { if (sort[j] > sort[j - 1]) { nfval = sort[j]; sort[j] = sort[j - 1]; sort[j - 1] = nfval; } } } nfval = sort[(hist_len - 1) >> 1]; return nfval; } static int16_t ar9300_limit_nf_range(struct ath_hal *ah, int16_t nf) { if (nf < AH9300(ah)->nfp->min) { return AH9300(ah)->nfp->nominal; } else if (nf > AH9300(ah)->nfp->max) { return AH9300(ah)->nfp->max; } return nf; } #ifndef ATH_NF_PER_CHAN inline static void ar9300_reset_nf_hist_buff(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) { HAL_CHAN_NFCAL_HIST *h = &ichan->nf_cal_hist; HAL_NFCAL_HIST_FULL *home = &AH_PRIVATE(ah)->nf_cal_hist; int i; - + /* * Copy the value for the channel in question into the home-channel * NF history buffer. The channel NF is probably a value filled in by * a prior background channel scan, but if no scan has been done then * it is the nominal noise floor filled in by ath_hal_init_NF_buffer * for this chip and the channel's band. * Replicate this channel NF into all entries of the home-channel NF * history buffer. * If the channel NF was filled in by a channel scan, it has not had * bounds limits applied to it yet - do so now. It is important to * apply bounds limits to the priv_nf value that gets loaded into the * WLAN chip's min_cca_pwr register field. It is also necessary to * apply bounds limits to the nf_cal_buffer[] elements. Since we are * replicating a single NF reading into all nf_cal_buffer elements, * if the single reading were above the CW_INT threshold, the CW_INT * check in ar9300_get_nf would immediately conclude that CW interference * is present, even though we're not supposed to set CW_INT unless * NF values are _consistently_ above the CW_INT threshold. * Applying the bounds limits to the nf_cal_buffer contents fixes this * problem. */ for (i = 0; i < HAL_NUM_NF_READINGS; i ++) { int j; int16_t nf; /* * No need to set curr_index, since it already has a value in * the range [0..HAL_NF_CAL_HIST_LEN_FULL), and all nf_cal_buffer * values will be the same. */ nf = ar9300_limit_nf_range(ah, h->nf_cal_buffer[0][i]); for (j = 0; j < HAL_NF_CAL_HIST_LEN_FULL; j++) { home->nf_cal_buffer[j][i] = nf; } AH_PRIVATE(ah)->nf_cal_hist.base.priv_nf[i] = nf; } } #endif /* * Update the noise floor buffer as a ring buffer */ static int16_t ar9300_update_nf_hist_buff(struct ath_hal *ah, HAL_NFCAL_HIST_FULL *h, int16_t *nfarray, int hist_len) { int i, nr; int16_t nf_no_lim_chain0; nf_no_lim_chain0 = ar9300_get_nf_hist_mid(ah, h, 0, hist_len); HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s[%d] BEFORE\n", __func__, __LINE__); for (nr = 0; nr < HAL_NF_CAL_HIST_LEN_FULL; nr++) { for (i = 0; i < HAL_NUM_NF_READINGS; i++) { HALDEBUG(ah, HAL_DEBUG_NFCAL, "nf_cal_buffer[%d][%d] = %d\n", nr, i, (int)h->nf_cal_buffer[nr][i]); } } for (i = 0; i < HAL_NUM_NF_READINGS; i++) { h->nf_cal_buffer[h->base.curr_index][i] = nfarray[i]; h->base.priv_nf[i] = ar9300_limit_nf_range( ah, ar9300_get_nf_hist_mid(ah, h, i, hist_len)); } HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s[%d] AFTER\n", __func__, __LINE__); for (nr = 0; nr < HAL_NF_CAL_HIST_LEN_FULL; nr++) { for (i = 0; i < HAL_NUM_NF_READINGS; i++) { HALDEBUG(ah, HAL_DEBUG_NFCAL, "nf_cal_buffer[%d][%d] = %d\n", nr, i, (int)h->nf_cal_buffer[nr][i]); } } if (++h->base.curr_index >= hist_len) { h->base.curr_index = 0; } return nf_no_lim_chain0; } #ifdef UNUSED static HAL_BOOL get_noise_floor_thresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan, int16_t *nft) { struct ath_hal_9300 *ahp = AH9300(ah); + switch (chan->channel_flags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: case CHANNEL_A_HT20: case CHANNEL_A_HT40PLUS: case CHANNEL_A_HT40MINUS: *nft = (int8_t)ar9300_eeprom_get(ahp, EEP_NFTHRESH_5); break; case CHANNEL_B: case CHANNEL_G: case CHANNEL_G_HT20: case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: *nft = (int8_t)ar9300_eeprom_get(ahp, EEP_NFTHRESH_2); break; default: HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel flags 0x%x\n", __func__, chan->channel_flags); return AH_FALSE; } return AH_TRUE; } #endif /* * Read the NF and check it against the noise floor threshhold */ #define IS(_c, _f) (((_c)->channel_flags & _f) || 0) static int ar9300_store_new_nf(struct ath_hal *ah, struct ieee80211_channel *chan, int is_scan) { // struct ath_hal_private *ahpriv = AH_PRIVATE(ah); int nf_hist_len; int16_t nf_no_lim; int16_t nfarray[HAL_NUM_NF_READINGS] = {0}; HAL_NFCAL_HIST_FULL *h; int is_2g = 0; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); struct ath_hal_9300 *ahp = AH9300(ah); if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { u_int32_t tsf32, nf_cal_dur_tsf; /* * The reason the NF calibration did not complete may just be that * not enough time has passed since the NF calibration was started, * because under certain conditions (when first moving to a new * channel) the NF calibration may be checked very repeatedly. * Or, there may be CW interference keeping the NF calibration * from completing. Check the delta time between when the NF * calibration was started and now to see whether the NF calibration * should have already completed (but hasn't, probably due to CW * interference), or hasn't had enough time to finish yet. */ /* * AH_NF_CAL_DUR_MAX_TSF - A conservative maximum time that the * HW should need to finish a NF calibration. If the HW * does not complete a NF calibration within this time period, * there must be a problem - probably CW interference. * AH_NF_CAL_PERIOD_MAX_TSF - A conservative maximum time between * check of the HW's NF calibration being finished. * If the difference between the current TSF and the TSF * recorded when the NF calibration started is larger than this * value, the TSF must have been reset. * In general, we expect the TSF to only be reset during * regular operation for STAs, not for APs. However, an * AP's TSF could be reset when joining an IBSS. * There's an outside chance that this could result in the * CW_INT flag being erroneously set, if the TSF adjustment * is smaller than AH_NF_CAL_PERIOD_MAX_TSF but larger than * AH_NF_CAL_DUR_TSF. However, even if this does happen, * it shouldn't matter, as the IBSS case shouldn't be * concerned about CW_INT. */ /* AH_NF_CAL_DUR_TSF - 90 sec in usec units */ #define AH_NF_CAL_DUR_TSF (90 * 1000 * 1000) /* AH_NF_CAL_PERIOD_MAX_TSF - 180 sec in usec units */ #define AH_NF_CAL_PERIOD_MAX_TSF (180 * 1000 * 1000) /* wraparound handled by using unsigned values */ tsf32 = ar9300_get_tsf32(ah); nf_cal_dur_tsf = tsf32 - AH9300(ah)->nf_tsf32; if (nf_cal_dur_tsf > AH_NF_CAL_PERIOD_MAX_TSF) { /* * The TSF must have gotten reset during the NF cal - * just reset the NF TSF timestamp, so the next time * this function is called, the timestamp comparison * will be valid. */ AH9300(ah)->nf_tsf32 = tsf32; } else if (nf_cal_dur_tsf > AH_NF_CAL_DUR_TSF) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: NF did not complete in calibration window\n", __func__); /* the NF incompletion is probably due to CW interference */ chan->ic_state |= IEEE80211_CHANSTATE_CWINT; } return 0; /* HW's NF measurement not finished */ } HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s[%d] chan %d\n", __func__, __LINE__, ichan->channel); is_2g = !! IS_CHAN_2GHZ(ichan); ar9300_upload_noise_floor(ah, is_2g, nfarray); /* Update the NF buffer for each chain masked by chainmask */ #ifdef ATH_NF_PER_CHAN h = &ichan->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL; #else if (is_scan) { /* * This channel's NF cal info is just a HAL_NFCAL_HIST_SMALL struct * rather than a HAL_NFCAL_HIST_FULL struct. * As long as we only use the first history element of nf_cal_buffer * (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1]), we can use * HAL_NFCAL_HIST_SMALL and HAL_NFCAL_HIST_FULL interchangeably. */ h = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL; } else { h = &AH_PRIVATE(ah)->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL; } #endif /* * nf_no_lim = median value from NF history buffer without bounds limits, * priv_nf = median value from NF history buffer with bounds limits. */ nf_no_lim = ar9300_update_nf_hist_buff(ah, h, nfarray, nf_hist_len); ichan->rawNoiseFloor = h->base.priv_nf[0]; /* check if there is interference */ // ichan->channel_flags &= (~CHANNEL_CW_INT); /* * Use AR9300_EMULATION to check for emulation purpose as PCIE Device ID * 0xABCD is recognized as valid Osprey as WAR in some EVs. */ if (nf_no_lim > ahp->nfp->nominal + ahp->nf_cw_int_delta) { /* * Since this CW interference check is being applied to the * median element of the NF history buffer, this indicates that * the CW interference is persistent. A single high NF reading * will not show up in the median, and thus will not cause the * CW_INT flag to be set. */ HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s: NF Cal: CW interferer detected through NF: %d\n", __func__, nf_no_lim); chan->ic_state |= IEEE80211_CHANSTATE_CWINT; } return 1; /* HW's NF measurement finished */ } #undef IS static inline void ar9300_get_delta_slope_values(struct ath_hal *ah, u_int32_t coef_scaled, u_int32_t *coef_mantissa, u_int32_t *coef_exponent) { u_int32_t coef_exp, coef_man; /* * ALGO -> coef_exp = 14-floor(log2(coef)); * floor(log2(x)) is the highest set bit position */ for (coef_exp = 31; coef_exp > 0; coef_exp--) { if ((coef_scaled >> coef_exp) & 0x1) { break; } } /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */ HALASSERT(coef_exp); coef_exp = 14 - (coef_exp - COEF_SCALE_S); /* * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5); * The coefficient is already shifted up for scaling */ coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); *coef_exponent = coef_exp - 16; } #define MAX_ANALOG_START 319 /* XXX */ /* * Delta slope coefficient computation. * Required for OFDM operation. */ static void ar9300_set_delta_slope(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t coef_scaled, ds_coef_exp, ds_coef_man; u_int32_t fclk = COEFF; /* clock * 2.5 */ u_int32_t clock_mhz_scaled = 0x1000000 * fclk; CHAN_CENTERS centers; /* * half and quarter rate can divide the scaled clock by 2 or 4 * scale for selected channel bandwidth */ if (IEEE80211_IS_CHAN_HALF(chan)) { clock_mhz_scaled = clock_mhz_scaled >> 1; } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { clock_mhz_scaled = clock_mhz_scaled >> 2; } /* * ALGO -> coef = 1e8/fcarrier*fclock/40; * scaled coef to provide precision for this floating calculation */ ar9300_get_channel_centers(ah, chan, ¢ers); coef_scaled = clock_mhz_scaled / centers.synth_center; ar9300_get_delta_slope_values(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, AR_PHY_TIMING3_DSC_MAN, ds_coef_man); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); /* * For Short GI, * scaled coeff is 9/10 that of normal coeff */ coef_scaled = (9 * coef_scaled) / 10; ar9300_get_delta_slope_values(ah, coef_scaled, &ds_coef_man, &ds_coef_exp); /* for short gi */ OS_REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, AR_PHY_SGI_DSC_MAN, ds_coef_man); OS_REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, AR_PHY_SGI_DSC_EXP, ds_coef_exp); } #define IS(_c, _f) (IEEE80211_IS_ ## _f(_c)) /* * XXX FreeBSD: This should be turned into something generic in ath_hal! */ HAL_CHANNEL_INTERNAL * ar9300_check_chan(struct ath_hal *ah, const struct ieee80211_channel *chan) { if (chan == NULL) { return AH_NULL; } if ((IS(chan, CHAN_2GHZ) ^ IS(chan, CHAN_5GHZ)) == 0) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", __func__, chan->ic_freq , chan->ic_flags); return AH_NULL; } /* * FreeBSD sets multiple flags, so this will fail. */ #if 0 if ((IS(chan, CHAN_OFDM) ^ IS(chan, CHAN_CCK) ^ IS(chan, CHAN_DYN) ^ IS(chan, CHAN_HT20) ^ IS(chan, CHAN_HT40U) ^ IS(chan, CHAN_HT40D)) == 0) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; not marked as " "OFDM or CCK or DYN or HT20 or HT40PLUS or HT40MINUS\n", __func__, chan->ic_freq , chan->ic_flags); return AH_NULL; } #endif return (ath_hal_checkchannel(ah, chan)); } #undef IS static void ar9300_set_11n_regs(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode) { u_int32_t phymode; // struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t enable_dac_fifo; /* XXX */ enable_dac_fifo = OS_REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO; /* Enable 11n HT, 20 MHz */ phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_SHORT_GI_40 | enable_dac_fifo; /* Configure baseband for dynamic 20/40 operation */ if (IEEE80211_IS_CHAN_HT40(chan)) { phymode |= AR_PHY_GC_DYN2040_EN; /* Configure control (primary) channel at +-10MHz */ if (IEEE80211_IS_CHAN_HT40U(chan)) { phymode |= AR_PHY_GC_DYN2040_PRI_CH; } #if 0 /* Configure 20/25 spacing */ if (ahp->ah_ext_prot_spacing == HAL_HT_EXTPROTSPACING_25) { phymode |= AR_PHY_GC_DYN2040_EXT_CH; } #endif } /* make sure we preserve INI settings */ phymode |= OS_REG_READ(ah, AR_PHY_GEN_CTRL); /* EV 62881/64991 - turn off Green Field detection for Maverick STA beta */ phymode &= ~AR_PHY_GC_GF_DETECT_EN; OS_REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); /* Set IFS timing for half/quarter rates */ if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) { u_int32_t modeselect = OS_REG_READ(ah, AR_PHY_MODE); if (IEEE80211_IS_CHAN_HALF(chan)) { modeselect |= AR_PHY_MS_HALF_RATE; } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { modeselect |= AR_PHY_MS_QUARTER_RATE; } OS_REG_WRITE(ah, AR_PHY_MODE, modeselect); ar9300_set_ifs_timing(ah, chan); OS_REG_RMW_FIELD( ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW, 0x3); } /* Configure MAC for 20/40 operation */ ar9300_set_11n_mac2040(ah, macmode); /* global transmit timeout (25 TUs default)*/ /* XXX - put this elsewhere??? */ OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); /* carrier sense timeout */ OS_REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); } /* * Spur mitigation for MRC CCK */ static void ar9300_spur_mitigate_mrc_cck(struct ath_hal *ah, struct ieee80211_channel *chan) { int i; /* spur_freq_for_osprey - hardcoded by Systems team for now. */ u_int32_t spur_freq_for_osprey[4] = { 2420, 2440, 2464, 2480 }; u_int32_t spur_freq_for_jupiter[2] = { 2440, 2464}; int cur_bb_spur, negative = 0, cck_spur_freq; u_int8_t* spur_fbin_ptr = NULL; int synth_freq; int range = 10; int max_spurcounts = OSPREY_EEPROM_MODAL_SPURS; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); /* * Need to verify range +/- 10 MHz in control channel, otherwise spur * is out-of-band and can be ignored. */ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { spur_fbin_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 1); if (spur_fbin_ptr[0] == 0) { return; /* No spur in the mode */ } if (IEEE80211_IS_CHAN_HT40(chan)) { range = 19; if (OS_REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) { synth_freq = ichan->channel + 10; } else { synth_freq = ichan->channel - 10; } } else { range = 10; synth_freq = ichan->channel; } } else if(AR_SREV_JUPITER(ah)) { range = 5; max_spurcounts = 2; /* Hardcoded by Jupiter Systems team for now. */ synth_freq = ichan->channel; } else { range = 10; max_spurcounts = 4; /* Hardcoded by Osprey Systems team for now. */ synth_freq = ichan->channel; } for (i = 0; i < max_spurcounts; i++) { negative = 0; if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], HAL_FREQ_BAND_2GHZ) - synth_freq; } else if(AR_SREV_JUPITER(ah)) { cur_bb_spur = spur_freq_for_jupiter[i] - synth_freq; } else { cur_bb_spur = spur_freq_for_osprey[i] - synth_freq; } if (cur_bb_spur < 0) { negative = 1; cur_bb_spur = -cur_bb_spur; } if (cur_bb_spur < range) { cck_spur_freq = (int)((cur_bb_spur << 19) / 11); if (negative == 1) { cck_spur_freq = -cck_spur_freq; } cck_spur_freq = cck_spur_freq & 0xfffff; /*OS_REG_WRITE_field(ah, BB_agc_control.ycok_max, 0x7);*/ OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7); /*OS_REG_WRITE_field(ah, BB_cck_spur_mit.spur_rssi_thr, 0x7f);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f); /*OS_REG_WRITE(ah, BB_cck_spur_mit.spur_filter_type, 0x2);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, 0x2); /*OS_REG_WRITE(ah, BB_cck_spur_mit.use_cck_spur_mit, 0x1);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x1); /*OS_REG_WRITE(ah, BB_cck_spur_mit.cck_spur_freq, cck_spur_freq);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, cck_spur_freq); return; } } /*OS_REG_WRITE(ah, BB_agc_control.ycok_max, 0x5);*/ OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5); /*OS_REG_WRITE(ah, BB_cck_spur_mit.use_cck_spur_mit, 0x0);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0); /*OS_REG_WRITE(ah, BB_cck_spur_mit.cck_spur_freq, 0x0);*/ OS_REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0); } /* Spur mitigation for OFDM */ static void ar9300_spur_mitigate_ofdm(struct ath_hal *ah, struct ieee80211_channel *chan) { int synth_freq; int range = 10; int freq_offset = 0; int spur_freq_sd = 0; int spur_subchannel_sd = 0; int spur_delta_phase = 0; int mask_index = 0; int i; int mode; u_int8_t* spur_chans_ptr; struct ath_hal_9300 *ahp; ahp = AH9300(ah); HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); if (IS_CHAN_5GHZ(ichan)) { spur_chans_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 0); mode = 0; } else { spur_chans_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 1); mode = 1; } if (IEEE80211_IS_CHAN_HT40(chan)) { range = 19; if (OS_REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) { synth_freq = ichan->channel - 10; } else { synth_freq = ichan->channel + 10; } } else { range = 10; synth_freq = ichan->channel; } /* Clean all spur register fields */ OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_FREQ_SD, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0); OS_REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0); i = 0; while (spur_chans_ptr[i] && i < 5) { freq_offset = FBIN2FREQ(spur_chans_ptr[i], mode) - synth_freq; if (abs(freq_offset) < range) { /* printf( "Spur Mitigation for OFDM: Synth Frequency = %d, " "Spur Frequency = %d\n", synth_freq, FBIN2FREQ(spur_chans_ptr[i], mode)); */ if (IEEE80211_IS_CHAN_HT40(chan)) { if (freq_offset < 0) { if (OS_REG_READ_FIELD( ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) { spur_subchannel_sd = 1; } else { spur_subchannel_sd = 0; } spur_freq_sd = ((freq_offset + 10) << 9) / 11; } else { if (OS_REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) { spur_subchannel_sd = 0; } else { spur_subchannel_sd = 1; } spur_freq_sd = ((freq_offset - 10) << 9) / 11; } spur_delta_phase = (freq_offset << 17) / 5; } else { spur_subchannel_sd = 0; spur_freq_sd = (freq_offset << 9) / 11; spur_delta_phase = (freq_offset << 18) / 5; } spur_freq_sd = spur_freq_sd & 0x3ff; spur_delta_phase = spur_delta_phase & 0xfffff; /* printf( "spur_subchannel_sd = %d, spur_freq_sd = 0x%x, " "spur_delta_phase = 0x%x\n", spur_subchannel_sd, spur_freq_sd, spur_delta_phase); */ /* OFDM Spur mitigation */ OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase); OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1); /* * Do not subtract spur power from noise floor for wasp. * This causes the maximum client test (on Veriwave) to fail * when run on spur channel (2464 MHz). * Refer to ev#82746 and ev#82744. */ if (!AR_SREV_WASP(ah) && (OS_REG_READ_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DYNAMIC) == 0x1)) { OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1); } mask_index = (freq_offset << 4) / 5; if (mask_index < 0) { mask_index = mask_index - 1; } mask_index = mask_index & 0x7f; /*printf("Bin 0x%x\n", mask_index);*/ OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index); OS_REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0); OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff); /* printf("BB_timing_control_4 = 0x%x\n", OS_REG_READ(ah, AR_PHY_TIMING4)); printf("BB_timing_control_11 = 0x%x\n", OS_REG_READ(ah, AR_PHY_TIMING11)); printf("BB_ext_chan_scorr_thr = 0x%x\n", OS_REG_READ(ah, AR_PHY_SFCORR_EXT)); printf("BB_spur_mask_controls = 0x%x\n", OS_REG_READ(ah, AR_PHY_SPUR_REG)); printf("BB_pilot_spur_mask = 0x%x\n", OS_REG_READ(ah, AR_PHY_PILOT_SPUR_MASK)); printf("BB_chan_spur_mask = 0x%x\n", OS_REG_READ(ah, AR_PHY_CHAN_SPUR_MASK)); printf("BB_vit_spur_mask_A = 0x%x\n", OS_REG_READ(ah, AR_PHY_SPUR_MASK_A)); */ break; } i++; } } /* * Convert to baseband spur frequency given input channel frequency * and compute register settings below. */ static void ar9300_spur_mitigate(struct ath_hal *ah, struct ieee80211_channel *chan) { ar9300_spur_mitigate_ofdm(ah, chan); ar9300_spur_mitigate_mrc_cck(ah, chan); } /************************************************************** * ar9300_channel_change * Assumes caller wants to change channel, and not reset. */ static inline HAL_BOOL ar9300_channel_change(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_CHANNEL_INTERNAL *ichan, HAL_HT_MACMODE macmode) { u_int32_t synth_delay, qnum; struct ath_hal_9300 *ahp = AH9300(ah); /* TX must be stopped by now */ for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ar9300_num_tx_pending(ah, qnum)) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Transmit frames pending on queue %d\n", __func__, qnum); HALASSERT(0); return AH_FALSE; } } /* * Kill last Baseband Rx Frame - Request analog bus grant */ OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); if (!ath_hal_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) { HALDEBUG(ah, HAL_DEBUG_PHYIO, "%s: Could not kill baseband RX\n", __func__); return AH_FALSE; } /* Setup 11n MAC/Phy mode registers */ ar9300_set_11n_regs(ah, chan, macmode); /* * Change the synth */ if (!ahp->ah_rf_hal.set_channel(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: failed to set channel\n", __func__); return AH_FALSE; } /* * Some registers get reinitialized during ATH_INI_POST INI programming. */ ar9300_init_user_settings(ah); /* * Setup the transmit power values. * * After the public to private hal channel mapping, ichan contains the * valid regulatory power value. * ath_hal_getctl and ath_hal_getantennaallowed look up ichan from chan. */ if (ar9300_eeprom_set_transmit_power( ah, &ahp->ah_eeprom, chan, ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan), ath_hal_get_twice_max_regpower(AH_PRIVATE(ah), ichan, chan), AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit)) != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: error init'ing transmit power\n", __func__); return AH_FALSE; } /* * Release the RFBus Grant. */ OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); /* * Write spur immunity and delta slope for OFDM enabled modes (A, G, Turbo) */ if (IEEE80211_IS_CHAN_OFDM(chan) || IEEE80211_IS_CHAN_HT(chan)) { ar9300_set_delta_slope(ah, chan); } else { /* Set to Ini default */ OS_REG_WRITE(ah, AR_PHY_TIMING3, 0x9c0a9f6b); OS_REG_WRITE(ah, AR_PHY_SGI_DELTA, 0x00046384); } ar9300_spur_mitigate(ah, chan); /* * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). * Read the phy active delay register. Value is in 100ns increments. */ synth_delay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; if (IEEE80211_IS_CHAN_CCK(chan)) { synth_delay = (4 * synth_delay) / 22; } else { synth_delay /= 10; } OS_DELAY(synth_delay + BASE_ACTIVATE_DELAY); /* * Do calibration. */ return AH_TRUE; } void ar9300_set_operating_mode(struct ath_hal *ah, int opmode) { u_int32_t val; val = OS_REG_READ(ah, AR_STA_ID1); val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); switch (opmode) { case HAL_M_HOSTAP: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP | AR_STA_ID1_KSRCH_MODE); OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; case HAL_M_IBSS: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | AR_STA_ID1_KSRCH_MODE); OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; case HAL_M_STA: case HAL_M_MONITOR: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); break; } } /* XXX need the logic for Osprey */ void ar9300_init_pll(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t pll; u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; HAL_CHANNEL_INTERNAL *ichan = NULL; if (chan) ichan = ath_hal_checkchannel(ah, chan); if (AR_SREV_HORNET(ah)) { if (clk_25mhz) { /* Hornet uses PLL_CONTROL_2. Xtal is 25MHz for Hornet. * REFDIV set to 0x1. * $xtal_freq = 25; * $PLL2_div = (704/$xtal_freq); # 176 * 4 = 704. * MAC and BB run at 176 MHz. * $PLL2_divint = int($PLL2_div); * $PLL2_divfrac = $PLL2_div - $PLL2_divint; * $PLL2_divfrac = int($PLL2_divfrac * 0x4000); # 2^14 * $PLL2_Val = ($PLL2_divint & 0x3f) << 19 | (0x1) << 14 | * $PLL2_divfrac & 0x3fff; * Therefore, $PLL2_Val = 0xe04a3d */ #define DPLL2_KD_VAL 0x1D #define DPLL2_KI_VAL 0x06 #define DPLL3_PHASE_SHIFT_VAL 0x1 /* Rewrite DDR PLL2 and PLL3 */ /* program DDR PLL ki and kd value, ki=0x6, kd=0x1d */ OS_REG_WRITE(ah, AR_HORNET_CH0_DDR_DPLL2, 0x18e82f01); /* program DDR PLL phase_shift to 0x1 */ OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_DDR_DPLL3, AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); OS_DELAY(1000); /* program refdiv, nint, frac to RTC register */ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0xe04a3d); /* program BB PLL ki and kd value, ki=0x6, kd=0x1d */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KD, DPLL2_KD_VAL); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KI, DPLL2_KI_VAL); /* program BB PLL phase_shift to 0x1 */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3, AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); } else { /* 40MHz */ #undef DPLL2_KD_VAL #undef DPLL2_KI_VAL #define DPLL2_KD_VAL 0x3D #define DPLL2_KI_VAL 0x06 /* Rewrite DDR PLL2 and PLL3 */ /* program DDR PLL ki and kd value, ki=0x6, kd=0x3d */ OS_REG_WRITE(ah, AR_HORNET_CH0_DDR_DPLL2, 0x19e82f01); /* program DDR PLL phase_shift to 0x1 */ OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_DDR_DPLL3, AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); OS_DELAY(1000); /* program refdiv, nint, frac to RTC register */ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); /* program BB PLL ki and kd value, ki=0x6, kd=0x3d */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KD, DPLL2_KD_VAL); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KI, DPLL2_KI_VAL); /* program BB PLL phase_shift to 0x1 */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3, AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); } OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); OS_DELAY(1000); } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_PLL_PWD, 0x1); /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KD, 0x40); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_KI, 0x4); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1, AR_PHY_BB_DPLL1_REFDIV, 0x5); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1, AR_PHY_BB_DPLL1_NINI, 0x58); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1, AR_PHY_BB_DPLL1_NFRAC, 0x0); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_OUTDIV, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_LOCAL_PLL, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_EN_NEGTRIG, 0x1); /* program BB PLL phase_shift to 0x6 */ OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3, AR_PHY_BB_DPLL3_PHASE_SHIFT, 0x6); OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_PLL_PWD, 0x0); OS_DELAY(1000); OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); OS_DELAY(1000); } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { #define SRIF_PLL 1 u_int32_t regdata, pll2_divint, pll2_divfrac; #ifndef SRIF_PLL u_int32_t pll2_clkmode; #endif #ifdef SRIF_PLL u_int32_t refdiv; #endif if (clk_25mhz) { #ifndef SRIF_PLL pll2_divint = 0x1c; pll2_divfrac = 0xa3d7; #else pll2_divint = 0x54; pll2_divfrac = 0x1eb85; refdiv = 3; #endif } else { #ifndef SRIF_PLL pll2_divint = 0x11; pll2_divfrac = 0x26666; #else if (AR_SREV_WASP(ah)) { pll2_divint = 88; pll2_divfrac = 0; refdiv = 5; } else { pll2_divint = 0x11; pll2_divfrac = 0x26666; refdiv = 1; } #endif } #ifndef SRIF_PLL pll2_clkmode = 0x3d; #endif /* PLL programming through SRIF Local Mode */ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); /* Bypass mode */ OS_DELAY(1000); do { regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE); regdata = regdata | (0x1 << 16); OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata); /* PWD_PLL set to 1 */ OS_DELAY(100); /* override int, frac, refdiv */ #ifndef SRIF_PLL OS_REG_WRITE(ah, AR_PHY_PLL_CONTROL, ((1 << 27) | (pll2_divint << 18) | pll2_divfrac)); #else OS_REG_WRITE(ah, AR_PHY_PLL_CONTROL, ((refdiv << 27) | (pll2_divint << 18) | pll2_divfrac)); #endif OS_DELAY(100); regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE); #ifndef SRIF_PLL regdata = (regdata & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | (0x6 << 26) | (pll2_clkmode << 19); #else if (AR_SREV_WASP(ah)) { regdata = (regdata & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | (0x4 << 26) | (0x18 << 19); } else { regdata = (regdata & 0x80071fff) | (0x3 << 30) | (0x1 << 13) | (0x4 << 26) | (0x60 << 19); } #endif /* Ki, Kd, Local PLL, Outdiv */ OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata); regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE); regdata = (regdata & 0xfffeffff); OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata); /* PWD_PLL set to 0 */ OS_DELAY(1000); if (AR_SREV_WASP(ah)) { /* clear do measure */ regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3); regdata &= ~(1 << 30); OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata); OS_DELAY(100); /* set do measure */ regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3); regdata |= (1 << 30); OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata); /* wait for measure done */ do { regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL4); } while ((regdata & (1 << 3)) == 0); /* clear do measure */ regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3); regdata &= ~(1 << 30); OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata); /* get measure sqsum dvc */ regdata = (OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3) & 0x007FFFF8) >> 3; } else { break; } } while (regdata >= 0x40000); /* Remove from Bypass mode */ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); OS_DELAY(1000); } else { pll = SM(0x5, AR_RTC_PLL_REFDIV); /* Supposedly not needed on Osprey */ #if 0 if (chan && IS_CHAN_HALF_RATE(chan)) { pll |= SM(0x1, AR_RTC_PLL_CLKSEL); } else if (chan && IS_CHAN_QUARTER_RATE(chan)) { pll |= SM(0x2, AR_RTC_PLL_CLKSEL); } #endif if (ichan && IS_CHAN_5GHZ(ichan)) { pll |= SM(0x28, AR_RTC_PLL_DIV); /* * When doing fast clock, set PLL to 0x142c */ if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { pll = 0x142c; } } else { pll |= SM(0x2c, AR_RTC_PLL_DIV); } OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); } /* TODO: * For multi-band owl, switch between bands by reiniting the PLL. */ OS_DELAY(RTC_PLL_SETTLE_DELAY); OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK | AR_RTC_PCIE_RST_PWDN_EN); if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { if (clk_25mhz) { OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x17c << 1)); /* 32KHz sleep clk */ OS_REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); OS_REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); } else { OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x261 << 1)); /* 32KHz sleep clk */ OS_REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); OS_REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); } OS_DELAY(100); } } static inline HAL_BOOL ar9300_set_reset(struct ath_hal *ah, int type) { u_int32_t rst_flags; u_int32_t tmp_reg; + struct ath_hal_9300 *ahp = AH9300(ah); HALASSERT(type == HAL_RESET_WARM || type == HAL_RESET_COLD); /* * RTC Force wake should be done before resetting the MAC. * MDK/ART does it that way. */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val); OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */ OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); /* Reset AHB */ /* Bug26871 */ tmp_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)); if (AR_SREV_WASP(ah)) { if (tmp_reg & (AR9340_INTR_SYNC_LOCAL_TIMEOUT)) { OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF); } } else { if (tmp_reg & (AR9300_INTR_SYNC_LOCAL_TIMEOUT | AR9300_INTR_SYNC_RADM_CPL_TIMEOUT)) { OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF); } else { /* NO AR_RC_AHB in Osprey */ /*OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_AHB);*/ } } rst_flags = AR_RTC_RC_MAC_WARM; if (type == HAL_RESET_COLD) { rst_flags |= AR_RTC_RC_MAC_COLD; } #ifdef AH_SUPPORT_HORNET /* Hornet WAR: trigger SoC to reset WMAC if ... * (1) doing cold reset. Ref: EV 69254 * (2) beacon pending. Ref: EV 70983 */ if (AR_SREV_HORNET(ah) && (ar9300_num_tx_pending( ah, AH_PRIVATE(ah)->ah_caps.halTotalQueues - 1) != 0 || type == HAL_RESET_COLD)) { u_int32_t time_out; #define AR_SOC_RST_RESET 0xB806001C #define AR_SOC_BOOT_STRAP 0xB80600AC #define AR_SOC_WLAN_RST 0x00000800 /* WLAN reset */ #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val); #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Hornet SoC reset WMAC.\n", __func__); REG_WRITE(AR_SOC_RST_RESET, REG_READ(AR_SOC_RST_RESET) | AR_SOC_WLAN_RST); REG_WRITE(AR_SOC_RST_RESET, REG_READ(AR_SOC_RST_RESET) & (~AR_SOC_WLAN_RST)); time_out = 0; while (1) { tmp_reg = REG_READ(AR_SOC_BOOT_STRAP); if ((tmp_reg & 0x10) == 0) { break; } if (time_out > 20) { break; } OS_DELAY(10000); time_out++; } OS_REG_WRITE(ah, AR_RTC_RESET, 1); #undef REG_READ #undef REG_WRITE #undef AR_SOC_WLAN_RST #undef AR_SOC_RST_RESET #undef AR_SOC_BOOT_STRAP } #endif /* AH_SUPPORT_HORNET */ #ifdef AH_SUPPORT_SCORPION if (AR_SREV_SCORPION(ah)) { #define DDR_CTL_CONFIG_ADDRESS 0xb8000000 #define DDR_CTL_CONFIG_OFFSET 0x0108 #define DDR_CTL_CONFIG_CLIENT_ACTIVITY_MSB 29 #define DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB 21 #define DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK 0x3fe00000 #define DDR_CTL_CONFIG_CLIENT_ACTIVITY_GET(x) (((x) & DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK) >> DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB) #define DDR_CTL_CONFIG_CLIENT_ACTIVITY_SET(x) (((x) << DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB) & DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK) #define MAC_DMA_CFG_ADDRESS 0xb8100000 #define MAC_DMA_CFG_OFFSET 0x0014 #define MAC_DMA_CFG_HALT_REQ_MSB 11 #define MAC_DMA_CFG_HALT_REQ_LSB 11 #define MAC_DMA_CFG_HALT_REQ_MASK 0x00000800 #define MAC_DMA_CFG_HALT_REQ_GET(x) (((x) & MAC_DMA_CFG_HALT_REQ_MASK) >> MAC_DMA_CFG_HALT_REQ_LSB) #define MAC_DMA_CFG_HALT_REQ_SET(x) (((x) << MAC_DMA_CFG_HALT_REQ_LSB) & MAC_DMA_CFG_HALT_REQ_MASK) #define MAC_DMA_CFG_HALT_ACK_MSB 12 #define MAC_DMA_CFG_HALT_ACK_LSB 12 #define MAC_DMA_CFG_HALT_ACK_MASK 0x00001000 #define MAC_DMA_CFG_HALT_ACK_GET(x) (((x) & MAC_DMA_CFG_HALT_ACK_MASK) >> MAC_DMA_CFG_HALT_ACK_LSB) #define MAC_DMA_CFG_HALT_ACK_SET(x) (((x) << MAC_DMA_CFG_HALT_ACK_LSB) & MAC_DMA_CFG_HALT_ACK_MASK) #define RST_RESET 0xB806001c #define RTC_RESET (1<<27) #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val); #define DDR_REG_READ(_ah, _reg) \ *((volatile u_int32_t *)( DDR_CTL_CONFIG_ADDRESS + (_reg))) #define DDR_REG_WRITE(_ah, _reg, _val) \ *((volatile u_int32_t *)(DDR_CTL_CONFIG_ADDRESS + (_reg))) = (_val) OS_REG_WRITE(ah,MAC_DMA_CFG_OFFSET, (OS_REG_READ(ah,MAC_DMA_CFG_OFFSET) & ~MAC_DMA_CFG_HALT_REQ_MASK) | MAC_DMA_CFG_HALT_REQ_SET(1)); { int count; u_int32_t data; count = 0; while (!MAC_DMA_CFG_HALT_ACK_GET(OS_REG_READ(ah, MAC_DMA_CFG_OFFSET) )) { count++; if (count > 10) { ath_hal_printf(ah, "Halt ACK timeout\n"); break; } OS_DELAY(10); } data = DDR_REG_READ(ah,DDR_CTL_CONFIG_OFFSET); ath_hal_printf(ah, "check DDR Activity - HIGH\n"); count = 0; while (DDR_CTL_CONFIG_CLIENT_ACTIVITY_GET(data)) { // AVE_DEBUG(0,"DDR Activity - HIGH\n"); ath_hal_printf(ah, "DDR Activity - HIGH\n"); count++; OS_DELAY(10); data = DDR_REG_READ(ah,DDR_CTL_CONFIG_OFFSET); if (count > 10) { ath_hal_printf(ah, "DDR Activity timeout\n"); break; } } } { //Force RTC reset REG_WRITE(RST_RESET, (REG_READ(RST_RESET) | RTC_RESET)); OS_DELAY(10); REG_WRITE(RST_RESET, (REG_READ(RST_RESET) & ~RTC_RESET)); OS_DELAY(10); OS_REG_WRITE(ah, AR_RTC_RESET, 0); OS_DELAY(10); OS_REG_WRITE(ah, AR_RTC_RESET, 1); OS_DELAY(10); ath_hal_printf(ah,"%s: Scorpion SoC RTC reset done.\n", __func__); } #undef REG_READ #undef REG_WRITE } #endif /* AH_SUPPORT_SCORPION */ /* * Set Mac(BB,Phy) Warm Reset */ OS_REG_WRITE(ah, AR_RTC_RC, rst_flags); OS_DELAY(50); /* XXX 50 usec */ /* * Clear resets and force wakeup */ OS_REG_WRITE(ah, AR_RTC_RC, 0); if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: RTC stuck in MAC reset\n", __FUNCTION__); HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: AR_RTC_RC = 0x%x\n", __func__, OS_REG_READ(ah, AR_RTC_RC)); return AH_FALSE; } /* Clear AHB reset */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0); ar9300_attach_hw_platform(ah); + ahp->ah_chip_reset_done = 1; return AH_TRUE; } static inline HAL_BOOL ar9300_set_reset_power_on(struct ath_hal *ah) { /* Force wake */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val); OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */ OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); /* * RTC reset and clear. Some delay in between is needed * to give the chip time to settle. */ OS_REG_WRITE(ah, AR_RTC_RESET, 0); OS_DELAY(2); OS_REG_WRITE(ah, AR_RTC_RESET, 1); /* * Poll till RTC is ON */ if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_STATUS_M, AR_RTC_STATUS_ON)) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: RTC not waking up for %d\n", __FUNCTION__, 1000); return AH_FALSE; } /* * Read Revisions from Chip right after RTC is on for the first time. * This helps us detect the chip type early and initialize it accordingly. */ ar9300_read_revisions(ah); /* * Warm reset if we aren't really powering on, * just restarting the driver. */ return ar9300_set_reset(ah, HAL_RESET_WARM); } /* * Write the given reset bit mask into the reset register */ HAL_BOOL ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type) { HAL_BOOL ret = AH_FALSE; /* * Set force wake */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val); OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */ OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); switch (type) { case HAL_RESET_POWER_ON: ret = ar9300_set_reset_power_on(ah); break; case HAL_RESET_WARM: case HAL_RESET_COLD: ret = ar9300_set_reset(ah, type); break; default: break; } #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } #endif return ret; } /* * Places the PHY and Radio chips into reset. A full reset * must be called to leave this state. The PCI/MAC/PCU are * not placed into reset as we must receive interrupt to * re-enable the hardware. */ HAL_BOOL ar9300_phy_disable(struct ath_hal *ah) { if (!ar9300_set_reset_reg(ah, HAL_RESET_WARM)) { return AH_FALSE; } #ifdef ATH_SUPPORT_LED #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val); #define ATH_GPIO_OE 0xB8040000 #define ATH_GPIO_OUT 0xB8040008 /* GPIO Ouput Value reg.*/ if (AR_SREV_WASP(ah)) { if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) { REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 13))); } else { REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12))); } } else if (AR_SREV_SCORPION(ah)) { if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) { REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 13))); } else { REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12))); } /* Turn off JMPST led */ REG_WRITE(ATH_GPIO_OUT, (REG_READ(ATH_GPIO_OUT) | (0x1 << 15))); } #undef REG_READ #undef REG_WRITE #endif if ( AR_SREV_OSPREY(ah) ) { OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1), 0x0, 0x1f); } ar9300_init_pll(ah, AH_NULL); return AH_TRUE; } /* * Places all of hardware into reset */ HAL_BOOL ar9300_disable(struct ath_hal *ah) { if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) { return AH_FALSE; } if (!ar9300_set_reset_reg(ah, HAL_RESET_COLD)) { return AH_FALSE; } ar9300_init_pll(ah, AH_NULL); return AH_TRUE; } /* * TODO: Only write the PLL if we're changing to or from CCK mode * * WARNING: The order of the PLL and mode registers must be correct. */ static inline void ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t rf_mode = 0; if (chan == AH_NULL) { return; } switch (AH9300(ah)->ah_hwp) { case HAL_TRUE_CHIP: rf_mode |= (IEEE80211_IS_CHAN_B(chan) || IEEE80211_IS_CHAN_G(chan)) ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; break; default: HALASSERT(0); break; } /* Phy mode bits for 5GHz channels requiring Fast Clock */ if ( IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { rf_mode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); } OS_REG_WRITE(ah, AR_PHY_MODE, rf_mode); } /* * Places the hardware into reset and then pulls it out of reset */ HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan) { struct ath_hal_9300 *ahp = AH9300(ah); int type = HAL_RESET_WARM; OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); /* * Warm reset is optimistic. * * If the TX/RX DMA engines aren't shut down (eg, they're * wedged) then we're better off doing a full cold reset * to try and shake that condition. */ if (ahp->ah_chip_full_sleep || (ah->ah_config.ah_force_full_reset == 1) || OS_REG_READ(ah, AR_Q_TXE) || (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) { type = HAL_RESET_COLD; } if (!ar9300_set_reset_reg(ah, type)) { return AH_FALSE; } /* Bring out of sleep mode (AGAIN) */ if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) { return AH_FALSE; } ahp->ah_chip_full_sleep = AH_FALSE; if (AR_SREV_HORNET(ah)) { ar9300_internal_regulator_apply(ah); } ar9300_init_pll(ah, chan); /* * Perform warm reset before the mode/PLL/turbo registers * are changed in order to deactivate the radio. Mode changes * with an active radio can result in corrupted shifts to the * radio device. */ ar9300_set_rf_mode(ah, chan); return AH_TRUE; } /* ar9300_setup_calibration * Setup HW to collect samples used for current cal */ inline static void ar9300_setup_calibration(struct ath_hal *ah, HAL_CAL_LIST *curr_cal) { /* Select calibration to run */ switch (curr_cal->cal_data->cal_type) { case IQ_MISMATCH_CAL: /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, curr_cal->cal_data->cal_count_max); OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: starting IQ Mismatch Calibration\n", __func__); /* Kick-off cal */ OS_REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); break; case TEMP_COMP_CAL: if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL, 1); OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_THERM, AR_PHY_65NM_CH0_THERM_START, 1); } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM_JUPITER, AR_PHY_65NM_CH0_THERM_LOCAL, 1); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM_JUPITER, AR_PHY_65NM_CH0_THERM_START, 1); } else { OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL, 1); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_START, 1); } HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: starting Temperature Compensation Calibration\n", __func__); break; default: HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s called with incorrect calibration type.\n", __func__); } } /* ar9300_reset_calibration * Initialize shared data structures and prepare a cal to be run. */ inline static void ar9300_reset_calibration(struct ath_hal *ah, HAL_CAL_LIST *curr_cal) { struct ath_hal_9300 *ahp = AH9300(ah); int i; /* Setup HW for new calibration */ ar9300_setup_calibration(ah, curr_cal); /* Change SW state to RUNNING for this calibration */ curr_cal->cal_state = CAL_RUNNING; /* Reset data structures shared between different calibrations */ for (i = 0; i < AR9300_MAX_CHAINS; i++) { ahp->ah_meas0.sign[i] = 0; ahp->ah_meas1.sign[i] = 0; ahp->ah_meas2.sign[i] = 0; ahp->ah_meas3.sign[i] = 0; } ahp->ah_cal_samples = 0; } #ifdef XXX_UNUSED_FUNCTION /* * Find out which of the RX chains are enabled */ static u_int32_t ar9300_get_rx_chain_mask(struct ath_hal *ah) { u_int32_t ret_val = OS_REG_READ(ah, AR_PHY_RX_CHAINMASK); /* The bits [2:0] indicate the rx chain mask and are to be * interpreted as follows: * 00x => Only chain 0 is enabled * 01x => Chain 1 and 0 enabled * 1xx => Chain 2,1 and 0 enabled */ return (ret_val & 0x7); } #endif static void ar9300_get_nf_hist_base(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, int is_scan, int16_t nf[]) { HAL_NFCAL_BASE *h_base; #ifdef ATH_NF_PER_CHAN h_base = &chan->nf_cal_hist.base; #else if (is_scan) { /* * The channel we are currently on is not the home channel, * so we shouldn't use the home channel NF buffer's values on * this channel. Instead, use the NF single value already * read for this channel. (Or, if we haven't read the NF for * this channel yet, the SW default for this chip/band will * be used.) */ h_base = &chan->nf_cal_hist.base; } else { /* use the home channel NF info */ h_base = &AH_PRIVATE(ah)->nf_cal_hist.base; } #endif OS_MEMCPY(nf, h_base->priv_nf, sizeof(h_base->priv_nf)); } HAL_BOOL ar9300_load_nf(struct ath_hal *ah, int16_t nf[]) { int i, j; int32_t val; /* XXX where are EXT regs defined */ const u_int32_t ar9300_cca_regs[] = { AR_PHY_CCA_0, AR_PHY_CCA_1, AR_PHY_CCA_2, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_1, AR_PHY_EXT_CCA_2, }; u_int8_t chainmask; /* * Force NF calibration for all chains, otherwise Vista station * would conduct a bad performance */ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { chainmask = 0x9; } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah)) { chainmask = 0x1b; } else { chainmask = 0x3F; } /* * Write filtered NF values into max_cca_pwr register parameter * so we can load below. */ for (i = 0; i < HAL_NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar9300_cca_regs[i]); val &= 0xFFFFFE00; val |= (((u_int32_t)(nf[i]) << 1) & 0x1ff); OS_REG_WRITE(ah, ar9300_cca_regs[i], val); } } HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s: load %d %d %d %d %d %d\n", __func__, nf[0], nf[1], nf[2], nf[3], nf[4], nf[5]); /* * Load software filtered NF value into baseband internal min_cca_pwr * variable. */ OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* Wait for load to complete, should be fast, a few 10s of us. */ /* Changed the max delay 250us back to 10000us, since 250us often * results in NF load timeout and causes deaf condition * during stress testing 12/12/2009 */ for (j = 0; j < 10000; j++) { if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0){ break; } OS_DELAY(10); } if (j == 10000) { /* * We timed out waiting for the noisefloor to load, probably * due to an in-progress rx. Simply return here and allow * the load plenty of time to complete before the next * calibration interval. We need to avoid trying to load -50 * (which happens below) while the previous load is still in * progress as this can cause rx deafness (see EV 66368,62830). * Instead by returning here, the baseband nf cal will * just be capped by our present noisefloor until the next * calibration timer. */ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: *** TIMEOUT while waiting for nf to load: " "AR_PHY_AGC_CONTROL=0x%x ***\n", __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); return AH_FALSE; } /* * Restore max_cca_power register parameter again so that we're not capped * by the median we just loaded. This will be initial (and max) value * of next noise floor calibration the baseband does. */ for (i = 0; i < HAL_NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar9300_cca_regs[i]); val &= 0xFFFFFE00; val |= (((u_int32_t)(-50) << 1) & 0x1ff); OS_REG_WRITE(ah, ar9300_cca_regs[i], val); } } return AH_TRUE; } /* ar9300_per_calibration * Generic calibration routine. * Recalibrate the lower PHY chips to account for temperature/environment * changes. */ inline static void ar9300_per_calibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, u_int8_t rxchainmask, HAL_CAL_LIST *curr_cal, HAL_BOOL *is_cal_done) { struct ath_hal_9300 *ahp = AH9300(ah); /* Cal is assumed not done until explicitly set below */ *is_cal_done = AH_FALSE; /* Calibration in progress. */ if (curr_cal->cal_state == CAL_RUNNING) { /* Check to see if it has finished. */ if (!(OS_REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) { int i, num_chains = 0; for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (rxchainmask & (1 << i)) { num_chains++; } } /* * Accumulate cal measures for active chains */ curr_cal->cal_data->cal_collect(ah, num_chains); ahp->ah_cal_samples++; if (ahp->ah_cal_samples >= curr_cal->cal_data->cal_num_samples) { /* * Process accumulated data */ curr_cal->cal_data->cal_post_proc(ah, num_chains); /* Calibration has finished. */ ichan->calValid |= curr_cal->cal_data->cal_type; curr_cal->cal_state = CAL_DONE; *is_cal_done = AH_TRUE; } else { /* Set-up collection of another sub-sample until we * get desired number */ ar9300_setup_calibration(ah, curr_cal); } } } else if (!(ichan->calValid & curr_cal->cal_data->cal_type)) { /* If current cal is marked invalid in channel, kick it off */ ar9300_reset_calibration(ah, curr_cal); } } static void ar9300_start_nf_cal(struct ath_hal *ah) { + struct ath_hal_9300 *ahp = AH9300(ah); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); AH9300(ah)->nf_tsf32 = ar9300_get_tsf32(ah); + +/* + * We are reading the NF values before we start the NF operation, because + * of that we are getting very high values like -45. + * This triggers the CW_INT detected and EACS module triggers the channel change + * chip_reset_done value is used to fix this issue. + * chip_reset_flag is set during the RTC reset. + * chip_reset_flag is cleared during the starting NF operation. + * if flag is set we will clear the flag and will not read the NF values. + */ + ahp->ah_chip_reset_done = 0; } /* ar9300_calibration * Wrapper for a more generic Calibration routine. Primarily to abstract to * upper layers whether there is 1 or more calibrations to be run. */ HAL_BOOL ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t rxchainmask, HAL_BOOL do_nf_cal, HAL_BOOL *is_cal_done, int is_scan, u_int32_t *sched_cals) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CAL_LIST *curr_cal = ahp->ah_cal_list_curr; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); int16_t nf_buf[HAL_NUM_NF_READINGS]; *is_cal_done = AH_TRUE; /* XXX: For initial wasp bringup - disable periodic calibration */ /* Invalid channel check */ if (ichan == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->ic_freq, chan->ic_flags); return AH_FALSE; } HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Entering, Doing NF Cal = %d\n", __func__, do_nf_cal); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Chain 0 Rx IQ Cal Correction 0x%08x\n", __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Chain 1 Rx IQ Cal Correction 0x%08x\n", __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B1)); if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Chain 2 Rx IQ Cal Correction 0x%08x\n", __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B2)); } } OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq); /* For given calibration: * 1. Call generic cal routine * 2. When this cal is done (is_cal_done) if we have more cals waiting * (eg after reset), mask this to upper layers by not propagating * is_cal_done if it is set to TRUE. * Instead, change is_cal_done to FALSE and setup the waiting cal(s) * to be run. */ if (curr_cal && (curr_cal->cal_data->cal_type & *sched_cals) && (curr_cal->cal_state == CAL_RUNNING || curr_cal->cal_state == CAL_WAITING)) { ar9300_per_calibration(ah, ichan, rxchainmask, curr_cal, is_cal_done); if (*is_cal_done == AH_TRUE) { ahp->ah_cal_list_curr = curr_cal = curr_cal->cal_next; if (curr_cal && curr_cal->cal_state == CAL_WAITING) { *is_cal_done = AH_FALSE; ar9300_reset_calibration(ah, curr_cal); } else { *sched_cals &= ~IQ_MISMATCH_CAL; } } } /* Do NF cal only at longer intervals */ if (do_nf_cal) { int nf_done; /* Get the value from the previous NF cal and update history buffer */ nf_done = ar9300_store_new_nf(ah, chan, is_scan); #if 0 if (ichan->channel_flags & CHANNEL_CW_INT) { chan->channel_flags |= CHANNEL_CW_INT; } #endif chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; if (nf_done) { /* * Load the NF from history buffer of the current channel. * NF is slow time-variant, so it is OK to use a historical value. */ ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf); ar9300_load_nf(ah, nf_buf); /* start NF calibration, without updating BB NF register*/ - ar9300_start_nf_cal(ah); + ar9300_start_nf_cal(ah); } } return AH_TRUE; } /* ar9300_iq_cal_collect * Collect data from HW to later perform IQ Mismatch Calibration */ void ar9300_iq_cal_collect(struct ath_hal *ah, u_int8_t num_chains) { struct ath_hal_9300 *ahp = AH9300(ah); int i; /* * Accumulate IQ cal measures for active chains */ for (i = 0; i < num_chains; i++) { ahp->ah_total_power_meas_i[i] = OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); ahp->ah_total_power_meas_q[i] = OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); ahp->ah_total_iq_corr_meas[i] = (int32_t) OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%d: Chn %d " "Reg Offset(0x%04x)pmi=0x%08x; " "Reg Offset(0x%04x)pmq=0x%08x; " "Reg Offset (0x%04x)iqcm=0x%08x;\n", ahp->ah_cal_samples, i, (unsigned) AR_PHY_CAL_MEAS_0(i), ahp->ah_total_power_meas_i[i], (unsigned) AR_PHY_CAL_MEAS_1(i), ahp->ah_total_power_meas_q[i], (unsigned) AR_PHY_CAL_MEAS_2(i), ahp->ah_total_iq_corr_meas[i]); } } /* ar9300_iq_calibration * Use HW data to perform IQ Mismatch Calibration */ void ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t power_meas_q, power_meas_i, iq_corr_meas; u_int32_t q_coff_denom, i_coff_denom; int32_t q_coff, i_coff; int iq_corr_neg, i; + HAL_CHANNEL_INTERNAL *ichan; static const u_int32_t offset_array[3] = { AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2, }; + ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan); + for (i = 0; i < num_chains; i++) { power_meas_i = ahp->ah_total_power_meas_i[i]; power_meas_q = ahp->ah_total_power_meas_q[i]; iq_corr_meas = ahp->ah_total_iq_corr_meas[i]; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Starting IQ Cal and Correction for Chain %d\n", i); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Orignal: Chn %diq_corr_meas = 0x%08x\n", i, ahp->ah_total_iq_corr_meas[i]); iq_corr_neg = 0; /* iq_corr_meas is always negative. */ if (iq_corr_meas > 0x80000000) { iq_corr_meas = (0xffffffff - iq_corr_meas) + 1; iq_corr_neg = 1; } HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n", i, power_meas_i); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n", i, power_meas_q); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "iq_corr_neg is 0x%08x\n", iq_corr_neg); i_coff_denom = (power_meas_i / 2 + power_meas_q / 2) / 256; q_coff_denom = power_meas_q / 64; /* Protect against divide-by-0 */ if ((i_coff_denom != 0) && (q_coff_denom != 0)) { /* IQ corr_meas is already negated if iqcorr_neg == 1 */ i_coff = iq_corr_meas / i_coff_denom; q_coff = power_meas_i / q_coff_denom - 64; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Chn %d i_coff = 0x%08x\n", i, i_coff); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Chn %d q_coff = 0x%08x\n", i, q_coff); /* Force bounds on i_coff */ if (i_coff >= 63) { i_coff = 63; } else if (i_coff <= -63) { i_coff = -63; } /* Negate i_coff if iq_corr_neg == 0 */ if (iq_corr_neg == 0x0) { i_coff = -i_coff; } /* Force bounds on q_coff */ if (q_coff >= 63) { q_coff = 63; } else if (q_coff <= -63) { q_coff = -63; } i_coff = i_coff & 0x7f; q_coff = q_coff & 0x7f; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Chn %d : i_coff = 0x%x q_coff = 0x%x\n", i, i_coff, q_coff); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Register offset (0x%04x) before update = 0x%x\n", offset_array[i], OS_REG_READ(ah, offset_array[i])); OS_REG_RMW_FIELD(ah, offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff); OS_REG_RMW_FIELD(ah, offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff); + /* store the RX cal results */ + if (ichan != NULL) { + ahp->ah_rx_cal_corr[i] = OS_REG_READ(ah, offset_array[i]) & 0x7fff; + ahp->ah_rx_cal_complete = AH_TRUE; + ahp->ah_rx_cal_chan = ichan->channel; +// ahp->ah_rx_cal_chan_flag = ichan->channel_flags &~ CHANNEL_PASSIVE; + ahp->ah_rx_cal_chan_flag = 0; /* XXX */ + } else { + /* XXX? Is this what I should do? */ + ahp->ah_rx_cal_complete = AH_FALSE; + + } + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Register offset (0x%04x) QI COFF (bitfields 0x%08x) " "after update = 0x%x\n", offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, OS_REG_READ(ah, offset_array[i])); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) " "after update = 0x%x\n", offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, OS_REG_READ(ah, offset_array[i])); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "IQ Cal and Correction done for Chain %d\n", i); } } OS_REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "IQ Cal and Correction (offset 0x%04x) enabled " "(bit position 0x%08x). New Value 0x%08x\n", (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); } /* + * When coming back from offchan, we do not perform RX IQ Cal. + * But the chip reset will clear all previous results + * We store the previous results and restore here. + */ +static void +ar9300_rx_iq_cal_restore(struct ath_hal *ah) +{ + struct ath_hal_9300 *ahp = AH9300(ah); + u_int32_t i_coff, q_coff; + HAL_BOOL is_restore = AH_FALSE; + int i; + static const u_int32_t offset_array[3] = { + AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B1, + AR_PHY_RX_IQCAL_CORR_B2, + }; + + for (i=0; iah_rx_cal_corr[i]) { + i_coff = (ahp->ah_rx_cal_corr[i] & + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF) >> + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S; + q_coff = (ahp->ah_rx_cal_corr[i] & + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF) >> + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S; + + OS_REG_RMW_FIELD(ah, offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff); + OS_REG_RMW_FIELD(ah, offset_array[i], + AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff); + + is_restore = AH_TRUE; + } + } + + if (is_restore) + OS_REG_SET_BIT(ah, + AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); + + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "%s: IQ Cal and Correction (offset 0x%04x) enabled " + "(bit position 0x%08x). New Value 0x%08x\n", + __func__, + (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), + AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, + OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); +} + +/* * Set a limit on the overall output power. Used for dynamic * transmit power control and the like. * * NB: limit is in units of 0.5 dbM. */ HAL_BOOL ar9300_set_tx_power_limit(struct ath_hal *ah, u_int32_t limit, u_int16_t extra_txpow, u_int16_t tpc_in_db) { struct ath_hal_9300 *ahp = AH9300(ah); struct ath_hal_private *ahpriv = AH_PRIVATE(ah); const struct ieee80211_channel *chan = ahpriv->ah_curchan; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); if (NULL == chan) { return AH_FALSE; } ahpriv->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); ahpriv->ah_extraTxPow = extra_txpow; if(chan == NULL) { return AH_FALSE; } if (ar9300_eeprom_set_transmit_power(ah, &ahp->ah_eeprom, chan, ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan), ath_hal_get_twice_max_regpower(ahpriv, ichan, chan), AH_MIN(MAX_RATE_POWER, ahpriv->ah_powerLimit)) != HAL_OK) { return AH_FALSE; } return AH_TRUE; } /* * Exported call to check for a recent gain reading and return * the current state of the thermal calibration gain engine. */ HAL_RFGAIN ar9300_get_rfgain(struct ath_hal *ah) { return HAL_RFGAIN_INACTIVE; } #define HAL_GREEN_AP_RX_MASK 0x1 static inline void ar9300_init_chain_masks(struct ath_hal *ah, int rx_chainmask, int tx_chainmask) { if (AH9300(ah)->green_ap_ps_on) { rx_chainmask = HAL_GREEN_AP_RX_MASK; } if (rx_chainmask == 0x5) { OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); } OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); /* * Adaptive Power Management: * Some 3 stream chips exceed the PCIe power requirements. * This workaround will reduce power consumption by using 2 tx chains * for 1 and 2 stream rates (5 GHz only). * * Set the self gen mask to 2 tx chains when APM is enabled. * */ if (AH_PRIVATE(ah)->ah_caps.halApmEnable && (tx_chainmask == 0x7)) { OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); } else { OS_REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); } if (tx_chainmask == 0x5) { OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); } } /* * Override INI values with chip specific configuration. */ static inline void ar9300_override_ini(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t val; HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; /* * Set the RX_ABORT and RX_DIS and clear it only after * RXE is set for MAC. This prevents frames with * corrupted descriptor status. */ OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); /* * For Merlin and above, there is a new feature that allows Multicast * search based on both MAC Address and Key ID. * By default, this feature is enabled. * But since the driver is not using this feature, we switch it off; * otherwise multicast search based on MAC addr only will fail. */ val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val | AR_BUG_58603_FIX_ENABLE | AR_AGG_WEP_ENABLE); /* Osprey revision specific configuration */ /* Osprey 2.0+ - if SW RAC support is disabled, must also disable * the Osprey 2.0 hardware RAC fix. */ if (p_cap->halIsrRacSupport == AH_FALSE) { OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_MISSING_TX_INTR_FIX_ENABLE); } /* try to enable old pal if it is needed for h/w green tx */ ar9300_hwgreentx_set_pal_spare(ah, 1); } static inline void ar9300_prog_ini(struct ath_hal *ah, struct ar9300_ini_array *ini_arr, int column) { int i, reg_writes = 0; /* New INI format: Array may be undefined (pre, core, post arrays) */ if (ini_arr->ia_array == NULL) { return; } /* * New INI format: Pre, core, and post arrays for a given subsystem may be * modal (> 2 columns) or non-modal (2 columns). * Determine if the array is non-modal and force the column to 1. */ if (column >= ini_arr->ia_columns) { column = 1; } for (i = 0; i < ini_arr->ia_rows; i++) { u_int32_t reg = INI_RA(ini_arr, i, 0); u_int32_t val = INI_RA(ini_arr, i, column); /* ** Determine if this is a shift register value ** (reg >= 0x16000 && reg < 0x17000 for Osprey) , ** and insert the configured delay if so. ** -this delay is not required for Osprey (EV#71410) */ OS_REG_WRITE(ah, reg, val); WAR_6773(reg_writes); } } static inline HAL_STATUS ar9300_process_ini(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_CHANNEL_INTERNAL *ichan, HAL_HT_MACMODE macmode) { int reg_writes = 0; struct ath_hal_9300 *ahp = AH9300(ah); u_int modes_index, modes_txgaintable_index = 0; int i; HAL_STATUS status; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); /* Setup the indices for the next set of register array writes */ /* TODO: * If the channel marker is indicative of the current mode rather * than capability, we do not need to check the phy mode below. */ #if 0 switch (chan->channel_flags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_A_HT20: if (AR_SREV_SCORPION(ah)){ if (chan->channel <= 5350){ modes_txgaintable_index = 1; }else if ((chan->channel > 5350) && (chan->channel <= 5600)){ modes_txgaintable_index = 3; }else if (chan->channel > 5600){ modes_txgaintable_index = 5; } } modes_index = 1; break; case CHANNEL_A_HT40PLUS: case CHANNEL_A_HT40MINUS: if (AR_SREV_SCORPION(ah)){ if (chan->channel <= 5350){ modes_txgaintable_index = 2; }else if ((chan->channel > 5350) && (chan->channel <= 5600)){ modes_txgaintable_index = 4; }else if (chan->channel > 5600){ modes_txgaintable_index = 6; } } modes_index = 2; break; case CHANNEL_PUREG: case CHANNEL_G_HT20: case CHANNEL_B: if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 8; } modes_index = 4; break; case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 7; } modes_index = 3; break; case CHANNEL_108G: modes_index = 5; break; default: HALASSERT(0); return HAL_EINVAL; } #endif /* FreeBSD */ if (IS_CHAN_5GHZ(ichan)) { if (IEEE80211_IS_CHAN_HT40U(chan) || IEEE80211_IS_CHAN_HT40D(chan)) { if (AR_SREV_SCORPION(ah)){ if (ichan->channel <= 5350){ modes_txgaintable_index = 2; }else if ((ichan->channel > 5350) && (ichan->channel <= 5600)){ modes_txgaintable_index = 4; }else if (ichan->channel > 5600){ modes_txgaintable_index = 6; } } modes_index = 2; } else if (IEEE80211_IS_CHAN_A(chan) || IEEE80211_IS_CHAN_HT20(chan)) { if (AR_SREV_SCORPION(ah)){ if (ichan->channel <= 5350){ modes_txgaintable_index = 1; }else if ((ichan->channel > 5350) && (ichan->channel <= 5600)){ modes_txgaintable_index = 3; }else if (ichan->channel > 5600){ modes_txgaintable_index = 5; } } modes_index = 1; } else return HAL_EINVAL; } else if (IS_CHAN_2GHZ(ichan)) { if (IEEE80211_IS_CHAN_108G(chan)) { modes_index = 5; } else if (IEEE80211_IS_CHAN_HT40U(chan) || IEEE80211_IS_CHAN_HT40D(chan)) { if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 7; } modes_index = 3; } else if (IEEE80211_IS_CHAN_HT20(chan) || IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_B(chan) || IEEE80211_IS_CHAN_PUREG(chan)) { if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 8; } modes_index = 4; } else return HAL_EINVAL; } else return HAL_EINVAL; #if 0 /* Set correct Baseband to analog shift setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); #endif HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: " "Skipping OS-REG-WRITE(ah, AR-PHY(0), 0x00000007)\n"); HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: no ADDac programming\n"); /* * Osprey 2.0+ - new INI format. * Each subsystem has a pre, core, and post array. */ for (i = 0; i < ATH_INI_NUM_SPLIT; i++) { ar9300_prog_ini(ah, &ahp->ah_ini_soc[i], modes_index); ar9300_prog_ini(ah, &ahp->ah_ini_mac[i], modes_index); ar9300_prog_ini(ah, &ahp->ah_ini_bb[i], modes_index); ar9300_prog_ini(ah, &ahp->ah_ini_radio[i], modes_index); if ((i == ATH_INI_POST) && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah))) { ar9300_prog_ini(ah, &ahp->ah_ini_radio_post_sys2ant, modes_index); } } if (!(AR_SREV_SOC(ah))) { /* Doubler issue : Some board doesn't work well with MCS15. Turn off doubler after freq locking is complete*/ //ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */ //ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */ OS_REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */ OS_DELAY(200); //ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH0_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */ OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH1_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */ OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH2_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */ //ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_DELAY(1); //ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */ //ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); OS_DELAY(200); //ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_SYNTH12, OS_REG_READ(ah, AR_PHY_65NM_CH0_SYNTH12)); OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH12, AR_PHY_65NM_CH0_SYNTH12_VREFMUL3, 0xf); //OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH0_SYNTH12, 1<< 16); /* clr charge pump */ //ath_hal_printf(ah, "%s[%d] ==== After reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_SYNTH12, OS_REG_READ(ah, AR_PHY_65NM_CH0_SYNTH12)); OS_REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */ OS_REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */ OS_REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */ //ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2)); } /* Write rxgain Array Parameters */ REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain, 1, reg_writes); HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Rx Gain programming\n"); if (AR_SREV_SCORPION(ah)) { /* Write rxgain bounds Array */ REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, modes_index, reg_writes); HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Rx Gain table bounds programming\n"); } /* UB124 xLNA settings */ if (AR_SREV_WASP(ah) && ar9300_rx_gain_index_get(ah) == 2) { #define REG_WRITE(_reg,_val) *((volatile u_int32_t *)(_reg)) = (_val); #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) u_int32_t val; /* B8040000: bit[0]=0, bit[3]=0; */ val = REG_READ(0xB8040000); val &= 0xfffffff6; REG_WRITE(0xB8040000, val); /* B804002c: bit[31:24]=0x2e; bit[7:0]=0x2f; */ val = REG_READ(0xB804002c); val &= 0x00ffff00; val |= 0x2e00002f; REG_WRITE(0xB804002c, val); /* B804006c: bit[1]=1; */ val = REG_READ(0xB804006c); val |= 0x2; REG_WRITE(0xB804006c, val); #undef REG_READ #undef REG_WRITE } /* Write txgain Array Parameters */ if (AR_SREV_SCORPION(ah)) { REG_WRITE_ARRAY(&ahp->ah_ini_modes_txgain, modes_txgaintable_index, reg_writes); }else{ REG_WRITE_ARRAY(&ahp->ah_ini_modes_txgain, modes_index, reg_writes); } HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Tx Gain programming\n"); /* For 5GHz channels requiring Fast Clock, apply different modal values */ if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Fast clock enabled, use special ini values\n", __func__); REG_WRITE_ARRAY(&ahp->ah_ini_modes_additional, modes_index, reg_writes); } if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: use xtal ini for AH9300(ah)->clk_25mhz: %d\n", __func__, AH9300(ah)->clk_25mhz); REG_WRITE_ARRAY( &ahp->ah_ini_modes_additional, 1/*modes_index*/, reg_writes); } if (AR_SREV_WASP(ah) && (AH9300(ah)->clk_25mhz == 0)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Apply 40MHz ini settings\n", __func__); REG_WRITE_ARRAY( &ahp->ah_ini_modes_additional_40mhz, 1/*modesIndex*/, reg_writes); } /* Handle Japan Channel 14 channel spreading */ if (2484 == ichan->channel) { ar9300_prog_ini(ah, &ahp->ah_ini_japan2484, 1); } #if 0 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { ar9300_prog_ini(ah, &ahp->ah_ini_BTCOEX_MAX_TXPWR, 1); } #endif /* Override INI with chip specific configuration */ ar9300_override_ini(ah, chan); /* Setup 11n MAC/Phy mode registers */ ar9300_set_11n_regs(ah, chan, macmode); /* * Moved ar9300_init_chain_masks() here to ensure the swap bit is set before * the pdadc table is written. Swap must occur before any radio dependent * replicated register access. The pdadc curve addressing in particular * depends on the consistent setting of the swap bit. */ ar9300_init_chain_masks(ah, ahp->ah_rx_chainmask, ahp->ah_tx_chainmask); /* * Setup the transmit power values. * * After the public to private hal channel mapping, ichan contains the * valid regulatory power value. * ath_hal_getctl and ath_hal_getantennaallowed look up ichan from chan. */ status = ar9300_eeprom_set_transmit_power(ah, &ahp->ah_eeprom, chan, ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan), ath_hal_get_twice_max_regpower(ahpriv, ichan, chan), AH_MIN(MAX_RATE_POWER, ahpriv->ah_powerLimit)); if (status != HAL_OK) { HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: error init'ing transmit power\n", __func__); return HAL_EIO; } return HAL_OK; #undef N } /* ar9300_is_cal_supp * Determine if calibration is supported by device and channel flags */ inline static HAL_BOOL ar9300_is_cal_supp(struct ath_hal *ah, const struct ieee80211_channel *chan, HAL_CAL_TYPES cal_type) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_BOOL retval = AH_FALSE; switch (cal_type & ahp->ah_supp_cals) { case IQ_MISMATCH_CAL: /* Run IQ Mismatch for non-CCK only */ if (!IEEE80211_IS_CHAN_B(chan)) { retval = AH_TRUE; } break; case TEMP_COMP_CAL: retval = AH_TRUE; break; } return retval; } #if 0 /* ar9285_pa_cal * PA Calibration for Kite 1.1 and later versions of Kite. * - from system's team. */ static inline void ar9285_pa_cal(struct ath_hal *ah) { u_int32_t reg_val; int i, lo_gn, offs_6_1, offs_0; u_int8_t reflo; u_int32_t phy_test2_reg_val, phy_adc_ctl_reg_val; u_int32_t an_top2_reg_val, phy_tst_dac_reg_val; /* Kite 1.1 WAR for Bug 35666 * Increase the LDO value to 1.28V before accessing analog Reg */ if (AR_SREV_KITE_11(ah)) { OS_REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14) ); } an_top2_reg_val = OS_REG_READ(ah, AR9285_AN_TOP2); /* set pdv2i pdrxtxbb */ reg_val = OS_REG_READ(ah, AR9285_AN_RXTXBB1); reg_val |= ((0x1 << 5) | (0x1 << 7)); OS_REG_WRITE(ah, AR9285_AN_RXTXBB1, reg_val); /* clear pwddb */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G7); reg_val &= 0xfffffffd; OS_REG_WRITE(ah, AR9285_AN_RF2G7, reg_val); /* clear enpacal */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1); reg_val &= 0xfffff7ff; OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val); /* set offcal */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G2); reg_val |= (0x1 << 12); OS_REG_WRITE(ah, AR9285_AN_RF2G2, reg_val); /* set pdpadrv1=pdpadrv2=pdpaout=1 */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1); reg_val |= (0x7 << 23); OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val); /* Read back reflo, increase it by 1 and write it. */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reflo = ((reg_val >> 26) & 0x7); if (reflo < 0x7) { reflo++; } reg_val = ((reg_val & 0xe3ffffff) | (reflo << 26)); OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val); reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reflo = ((reg_val >> 26) & 0x7); /* use TX single carrier to transmit * dac const * reg. 15 */ phy_tst_dac_reg_val = OS_REG_READ(ah, AR_PHY_TSTDAC_CONST); OS_REG_WRITE(ah, AR_PHY_TSTDAC_CONST, ((0x7ff << 11) | 0x7ff)); reg_val = OS_REG_READ(ah, AR_PHY_TSTDAC_CONST); /* source is dac const * reg. 2 */ phy_test2_reg_val = OS_REG_READ(ah, AR_PHY_TEST2); OS_REG_WRITE(ah, AR_PHY_TEST2, ((0x1 << 7) | (0x1 << 1))); reg_val = OS_REG_READ(ah, AR_PHY_TEST2); /* set dac on * reg. 11 */ phy_adc_ctl_reg_val = OS_REG_READ(ah, AR_PHY_ADC_CTL); OS_REG_WRITE(ah, AR_PHY_ADC_CTL, 0x80008000); reg_val = OS_REG_READ(ah, AR_PHY_ADC_CTL); OS_REG_WRITE(ah, AR9285_AN_TOP2, (0x1 << 27) | (0x1 << 17) | (0x1 << 16) | (0x1 << 14) | (0x1 << 12) | (0x1 << 11) | (0x1 << 7) | (0x1 << 5)); OS_DELAY(10); /* 10 usec */ /* clear off[6:0] */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6); reg_val &= 0xfc0fffff; OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val); reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reg_val &= 0xfdffffff; OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val); offs_6_1 = 0; for (i = 6; i > 0; i--) { /* sef off[$k]==1 */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6); reg_val &= 0xfc0fffff; reg_val = reg_val | (0x1 << (19 + i)) | ((offs_6_1) << 20); OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val); lo_gn = (OS_REG_READ(ah, AR9285_AN_RF2G9)) & 0x1; offs_6_1 = offs_6_1 | (lo_gn << (i - 1)); } reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6); reg_val &= 0xfc0fffff; reg_val = reg_val | ((offs_6_1 - 1) << 20); OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val); /* set off_0=1; */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reg_val &= 0xfdffffff; reg_val = reg_val | (0x1 << 25); OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val); lo_gn = OS_REG_READ(ah, AR9285_AN_RF2G9) & 0x1; offs_0 = lo_gn; reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reg_val &= 0xfdffffff; reg_val = reg_val | (offs_0 << 25); OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val); /* clear pdv2i */ reg_val = OS_REG_READ(ah, AR9285_AN_RXTXBB1); reg_val &= 0xffffff5f; OS_REG_WRITE(ah, AR9285_AN_RXTXBB1, reg_val); /* set enpacal */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1); reg_val |= (0x1 << 11); OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val); /* clear offcal */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G2); reg_val &= 0xffffefff; OS_REG_WRITE(ah, AR9285_AN_RF2G2, reg_val); /* set pdpadrv1=pdpadrv2=pdpaout=0 */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1); reg_val &= 0xfc7fffff; OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val); /* Read back reflo, decrease it by 1 and write it. */ reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reflo = (reg_val >> 26) & 0x7; if (reflo) { reflo--; } reg_val = ((reg_val & 0xe3ffffff) | (reflo << 26)); OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val); reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3); reflo = (reg_val >> 26) & 0x7; /* write back registers */ OS_REG_WRITE(ah, AR_PHY_TSTDAC_CONST, phy_tst_dac_reg_val); OS_REG_WRITE(ah, AR_PHY_TEST2, phy_test2_reg_val); OS_REG_WRITE(ah, AR_PHY_ADC_CTL, phy_adc_ctl_reg_val); OS_REG_WRITE(ah, AR9285_AN_TOP2, an_top2_reg_val); /* Kite 1.1 WAR for Bug 35666 * Decrease the LDO value back to 1.20V */ if (AR_SREV_KITE_11(ah)) { OS_REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); } } #endif /* ar9300_run_init_cals * Runs non-periodic calibrations */ inline static HAL_BOOL ar9300_run_init_cals(struct ath_hal *ah, int init_cal_count) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CHANNEL_INTERNAL ichan; /* bogus */ HAL_BOOL is_cal_done; HAL_CAL_LIST *curr_cal; const HAL_PERCAL_DATA *cal_data; int i; curr_cal = ahp->ah_cal_list_curr; if (curr_cal == AH_NULL) { return AH_FALSE; } cal_data = curr_cal->cal_data; ichan.calValid = 0; for (i = 0; i < init_cal_count; i++) { /* Reset this Cal */ ar9300_reset_calibration(ah, curr_cal); /* Poll for offset calibration complete */ if (!ath_hal_wait( ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL, 0)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Cal %d failed to complete in 100ms.\n", __func__, curr_cal->cal_data->cal_type); /* Re-initialize list pointers for periodic cals */ ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = AH_NULL; return AH_FALSE; } /* Run this cal */ ar9300_per_calibration( ah, &ichan, ahp->ah_rx_chainmask, curr_cal, &is_cal_done); if (is_cal_done == AH_FALSE) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Not able to run Init Cal %d.\n", __func__, curr_cal->cal_data->cal_type); } if (curr_cal->cal_next) { curr_cal = curr_cal->cal_next; } } /* Re-initialize list pointers for periodic cals */ ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = AH_NULL; return AH_TRUE; } #if 0 static void ar9300_tx_carrier_leak_war(struct ath_hal *ah) { unsigned long tx_gain_table_max; unsigned long reg_bb_cl_map_0_b0 = 0xffffffff; unsigned long reg_bb_cl_map_1_b0 = 0xffffffff; unsigned long reg_bb_cl_map_2_b0 = 0xffffffff; unsigned long reg_bb_cl_map_3_b0 = 0xffffffff; unsigned long tx_gain, cal_run = 0; unsigned long cal_gain[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1]; unsigned long cal_gain_index[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1]; unsigned long new_gain[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1]; int i, j; OS_MEMSET(new_gain, 0, sizeof(new_gain)); /*printf(" Running TxCarrierLeakWAR\n");*/ /* process tx gain table, we use cl_map_hw_gen=0. */ OS_REG_RMW_FIELD(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_MAP_HW_GEN, 0); //the table we used is txbb_gc[2:0], 1dB[2:1]. tx_gain_table_max = OS_REG_READ_FIELD(ah, AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX); for (i = 0; i <= tx_gain_table_max; i++) { tx_gain = OS_REG_READ(ah, AR_PHY_TXGAIN_TAB(1) + i * 4); cal_gain[i] = (((tx_gain >> 5)& 0x7) << 2) | (((tx_gain >> 1) & 0x3) << 0); if (i == 0) { cal_gain_index[i] = cal_run; new_gain[i] = 1; cal_run++; } else { new_gain[i] = 1; for (j = 0; j < i; j++) { /* printf("i=%d, j=%d cal_gain[$i]=0x%04x\n", i, j, cal_gain[i]); */ if (new_gain[i]) { if ((cal_gain[i] != cal_gain[j])) { new_gain[i] = 1; } else { /* if old gain found, use old cal_run value. */ new_gain[i] = 0; cal_gain_index[i] = cal_gain_index[j]; } } } /* if new gain found, increase cal_run */ if (new_gain[i] == 1) { cal_gain_index[i] = cal_run; cal_run++; } } reg_bb_cl_map_0_b0 = (reg_bb_cl_map_0_b0 & ~(0x1 << i)) | ((cal_gain_index[i] >> 0 & 0x1) << i); reg_bb_cl_map_1_b0 = (reg_bb_cl_map_1_b0 & ~(0x1 << i)) | ((cal_gain_index[i] >> 1 & 0x1) << i); reg_bb_cl_map_2_b0 = (reg_bb_cl_map_2_b0 & ~(0x1 << i)) | ((cal_gain_index[i] >> 2 & 0x1) << i); reg_bb_cl_map_3_b0 = (reg_bb_cl_map_3_b0 & ~(0x1 << i)) | ((cal_gain_index[i] >> 3 & 0x1) << i); /* printf("i=%2d, cal_gain[$i]= 0x%04x, cal_run= %d, " "cal_gain_index[i]=%d, new_gain[i] = %d\n", i, cal_gain[i], cal_run, cal_gain_index[i], new_gain[i]); */ } OS_REG_WRITE(ah, AR_PHY_CL_MAP_0_B0, reg_bb_cl_map_0_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_1_B0, reg_bb_cl_map_1_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_2_B0, reg_bb_cl_map_2_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_3_B0, reg_bb_cl_map_3_b0); if (AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, AR_PHY_CL_MAP_0_B1, reg_bb_cl_map_0_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_1_B1, reg_bb_cl_map_1_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_2_B1, reg_bb_cl_map_2_b0); OS_REG_WRITE(ah, AR_PHY_CL_MAP_3_B1, reg_bb_cl_map_3_b0); } } #endif static inline void ar9300_invalidate_saved_cals(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) { #if ATH_SUPPORT_CAL_REUSE if (AH_PRIVATE(ah)->ah_config.ath_hal_cal_reuse & ATH_CAL_REUSE_REDO_IN_FULL_RESET) { ichan->one_time_txiqcal_done = AH_FALSE; ichan->one_time_txclcal_done = AH_FALSE; } #endif } static inline HAL_BOOL ar9300_restore_rtt_cals(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) { HAL_BOOL restore_status = AH_FALSE; return restore_status; } /* ar9300_init_cal * Initialize Calibration infrastructure */ static inline HAL_BOOL ar9300_init_cal_internal(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_CHANNEL_INTERNAL *ichan, HAL_BOOL enable_rtt, HAL_BOOL do_rtt_cal, HAL_BOOL skip_if_none, HAL_BOOL apply_last_iqcorr) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_BOOL txiqcal_success_flag = AH_FALSE; HAL_BOOL cal_done = AH_FALSE; int iqcal_idx = 0; HAL_BOOL do_sep_iq_cal = AH_FALSE; HAL_BOOL do_agc_cal = do_rtt_cal; HAL_BOOL is_cal_reusable = AH_TRUE; #if ATH_SUPPORT_CAL_REUSE HAL_BOOL cal_reuse_enable = AH_PRIVATE(ah)->ah_config.ath_hal_cal_reuse & ATH_CAL_REUSE_ENABLE; HAL_BOOL clc_success = AH_FALSE; int32_t ch_idx, j, cl_tab_reg; u_int32_t BB_cl_tab_entry = MAX_BB_CL_TABLE_ENTRY; u_int32_t BB_cl_tab_b[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0, AR_PHY_CL_TAB_1, AR_PHY_CL_TAB_2 }; #endif if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { /* Hornet: 1 x 1 */ ahp->ah_rx_cal_chainmask = 0x1; ahp->ah_tx_cal_chainmask = 0x1; } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah)) { /* Wasp/Jupiter: 2 x 2 */ ahp->ah_rx_cal_chainmask = 0x3; ahp->ah_tx_cal_chainmask = 0x3; } else { /* * Osprey needs to be configured for the correct chain mode * before running AGC/TxIQ cals. */ if (ahp->ah_enterprise_mode & AR_ENT_OTP_CHAIN2_DISABLE) { /* chain 2 disabled - 2 chain mode */ ahp->ah_rx_cal_chainmask = 0x3; ahp->ah_tx_cal_chainmask = 0x3; } else { ahp->ah_rx_cal_chainmask = 0x7; ahp->ah_tx_cal_chainmask = 0x7; } } ar9300_init_chain_masks(ah, ahp->ah_rx_cal_chainmask, ahp->ah_tx_cal_chainmask); if (ahp->tx_cl_cal_enable) { #if ATH_SUPPORT_CAL_REUSE /* disable Carrie Leak or set do_agc_cal accordingly */ if (cal_reuse_enable && ichan->one_time_txclcal_done) { OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); } else #endif /* ATH_SUPPORT_CAL_REUSE */ { OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); do_agc_cal = AH_TRUE; } } /* Do Tx IQ Calibration here for osprey hornet and wasp */ /* XXX: For initial wasp bringup - check and enable this */ /* EV 74233: Tx IQ fails to complete for half/quarter rates */ if (!(IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) { if (ahp->tx_iq_cal_enable) { /* this should be eventually moved to INI file */ OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1(ah), AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); /* * For poseidon and later chips, * Tx IQ cal HW run will be a part of AGC calibration */ if (ahp->tx_iq_cal_during_agc_cal) { /* * txiqcal_success_flag always set to 1 to run * ar9300_tx_iq_cal_post_proc * if following AGC cal passes */ #if ATH_SUPPORT_CAL_REUSE if (!cal_reuse_enable || !ichan->one_time_txiqcal_done) { txiqcal_success_flag = AH_TRUE; OS_REG_WRITE(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah), OS_REG_READ(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah)) | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); } else { OS_REG_WRITE(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah), OS_REG_READ(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah)) & (~AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)); } #else if (OS_REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah), AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)){ if (apply_last_iqcorr == AH_TRUE) { OS_REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah), AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); txiqcal_success_flag = AH_FALSE; } else { txiqcal_success_flag = AH_TRUE; } }else{ txiqcal_success_flag = AH_FALSE; } #endif if (txiqcal_success_flag) { do_agc_cal = AH_TRUE; } } else #if ATH_SUPPORT_CAL_REUSE if (!cal_reuse_enable || !ichan->one_time_txiqcal_done) #endif { do_sep_iq_cal = AH_TRUE; do_agc_cal = AH_TRUE; } } } #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport && IS_CHAN_2GHZ(ichan) && (ahp->ah_mci_bt_state == MCI_BT_AWAKE) && do_agc_cal && !(ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { u_int32_t payload[4] = {0, 0, 0, 0}; /* Send CAL_REQ only when BT is AWAKE. */ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send WLAN_CAL_REQ 0x%X\n", __func__, ahp->ah_mci_wlan_cal_seq); MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_REQ); payload[MCI_GPM_WLAN_CAL_W_SEQUENCE] = ahp->ah_mci_wlan_cal_seq++; ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE); /* Wait BT_CAL_GRANT for 50ms */ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Wait for BT_CAL_GRANT\n", __func__); if (ar9300_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Got BT_CAL_GRANT.\n", __func__); } else { is_cal_reusable = AH_FALSE; HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: BT is not responding.\n", __func__); } } #endif /* ATH_SUPPORT_MCI */ if (do_sep_iq_cal) { /* enable Tx IQ Calibration HW for osprey/hornet/wasp */ txiqcal_success_flag = ar9300_tx_iq_cal_hw_run(ah); OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); OS_DELAY(5); OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); } #if 0 if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { ar9300_tx_carrier_leak_war(ah); } #endif /* * Calibrate the AGC * * Tx IQ cal is a part of AGC cal for Jupiter/Poseidon, etc. * please enable the bit of txiqcal_control_0[31] in INI file * for Jupiter/Poseidon/etc. */ if(!AR_SREV_SCORPION(ah)) { if (do_agc_cal || !skip_if_none) { OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); /* Poll for offset calibration complete */ cal_done = ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0); if (!cal_done) { HALDEBUG(ah, HAL_DEBUG_FCS_RTT, "(FCS) CAL NOT DONE!!! - %d\n", ichan->channel); } } else { cal_done = AH_TRUE; } /* * Tx IQ cal post-processing in SW * This part of code should be common to all chips, * no chip specific code for Jupiter/Posdeion except for register names. */ if (txiqcal_success_flag) { ar9300_tx_iq_cal_post_proc(ah,ichan, 1, 1,is_cal_reusable, AH_FALSE); } } else { if (!txiqcal_success_flag) { OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: offset calibration failed to complete in 1ms; " "noisy environment?\n", __func__); return AH_FALSE; } if (apply_last_iqcorr == AH_TRUE) { ar9300_tx_iq_cal_post_proc(ah, ichan, 0, 0, is_cal_reusable, AH_TRUE); } } else { for (iqcal_idx=0;iqcal_idxah_caps.halMciSupport && IS_CHAN_2GHZ(ichan) && (ahp->ah_mci_bt_state == MCI_BT_AWAKE) && do_agc_cal && !(ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { u_int32_t payload[4] = {0, 0, 0, 0}; HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send WLAN_CAL_DONE 0x%X\n", __func__, ahp->ah_mci_wlan_cal_done); MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE); payload[MCI_GPM_WLAN_CAL_W_SEQUENCE] = ahp->ah_mci_wlan_cal_done++; ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE); } #endif /* ATH_SUPPORT_MCI */ if (!cal_done && !AR_SREV_SCORPION(ah) ) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: offset calibration failed to complete in 1ms; " "noisy environment?\n", __func__); return AH_FALSE; } #if 0 /* Beacon stuck fix, refer to EV 120056 */ if(IS_CHAN_2GHZ(chan) && AR_SREV_SCORPION(ah)) OS_REG_WRITE(ah, AR_PHY_TIMING5, OS_REG_READ(ah,AR_PHY_TIMING5) & ~AR_PHY_TIMING5_CYCPWR_THR1_ENABLE); #endif #if 0 /* Do PA Calibration */ if (AR_SREV_KITE(ah) && AR_SREV_KITE_11_OR_LATER(ah)) { ar9285_pa_cal(ah); } #endif #if ATH_SUPPORT_CAL_REUSE if (ichan->one_time_txiqcal_done) { ar9300_tx_iq_cal_apply(ah, ichan); HALDEBUG(ah, HAL_DEBUG_FCS_RTT, "(FCS) TXIQCAL applied - %d\n", ichan->channel); } #endif /* ATH_SUPPORT_CAL_REUSE */ #if ATH_SUPPORT_CAL_REUSE if (cal_reuse_enable && ahp->tx_cl_cal_enable) { clc_success = (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_CLC_SUCCESS) ? 1 : 0; if (ichan->one_time_txclcal_done) { /* reapply CL cal results */ for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) { if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) { continue; } cl_tab_reg = BB_cl_tab_b[ch_idx]; for (j = 0; j < BB_cl_tab_entry; j++) { OS_REG_WRITE(ah, cl_tab_reg, ichan->tx_clcal[ch_idx][j]); cl_tab_reg += 4;; } } HALDEBUG(ah, HAL_DEBUG_FCS_RTT, "(FCS) TX CL CAL applied - %d\n", ichan->channel); } else if (is_cal_reusable && clc_success) { /* save CL cal results */ for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) { if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) { continue; } cl_tab_reg = BB_cl_tab_b[ch_idx]; for (j = 0; j < BB_cl_tab_entry; j++) { ichan->tx_clcal[ch_idx][j] = OS_REG_READ(ah, cl_tab_reg); cl_tab_reg += 4; } } ichan->one_time_txclcal_done = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_FCS_RTT, "(FCS) TX CL CAL saved - %d\n", ichan->channel); } } #endif /* ATH_SUPPORT_CAL_REUSE */ /* Revert chainmasks to their original values before NF cal */ ar9300_init_chain_masks(ah, ahp->ah_rx_chainmask, ahp->ah_tx_chainmask); #if !FIX_NOISE_FLOOR /* * Do NF calibration after DC offset and other CALs. * Per system engineers, noise floor value can sometimes be 20 dB * higher than normal value if DC offset and noise floor cal are * triggered at the same time. */ OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); #endif /* Initialize list pointers */ ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = AH_NULL; /* * Enable IQ, ADC Gain, ADC DC Offset Cals */ /* Setup all non-periodic, init time only calibrations */ /* XXX: Init DC Offset not working yet */ #ifdef not_yet if (AH_TRUE == ar9300_is_cal_supp(ah, chan, ADC_DC_INIT_CAL)) { INIT_CAL(&ahp->ah_adc_dc_cal_init_data); INSERT_CAL(ahp, &ahp->ah_adc_dc_cal_init_data); } /* Initialize current pointer to first element in list */ ahp->ah_cal_list_curr = ahp->ah_cal_list; if (ahp->ah_cal_list_curr) { if (ar9300_run_init_cals(ah, 0) == AH_FALSE) { return AH_FALSE; } } #endif /* end - Init time calibrations */ + /* Do not do RX cal in case of offchan, or cal data already exists on same channel*/ + if (ahp->ah_skip_rx_iq_cal) { + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "Skip RX IQ Cal\n"); + return AH_TRUE; + } + /* If Cals are supported, add them to list via INIT/INSERT_CAL */ if (AH_TRUE == ar9300_is_cal_supp(ah, chan, IQ_MISMATCH_CAL)) { INIT_CAL(&ahp->ah_iq_cal_data); INSERT_CAL(ahp, &ahp->ah_iq_cal_data); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: enabling IQ Calibration.\n", __func__); } if (AH_TRUE == ar9300_is_cal_supp(ah, chan, TEMP_COMP_CAL)) { INIT_CAL(&ahp->ah_temp_comp_cal_data); INSERT_CAL(ahp, &ahp->ah_temp_comp_cal_data); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: enabling Temperature Compensation Calibration.\n", __func__); } /* Initialize current pointer to first element in list */ ahp->ah_cal_list_curr = ahp->ah_cal_list; /* Reset state within current cal */ if (ahp->ah_cal_list_curr) { ar9300_reset_calibration(ah, ahp->ah_cal_list_curr); } /* Mark all calibrations on this channel as being invalid */ ichan->calValid = 0; return AH_TRUE; } static inline HAL_BOOL ar9300_init_cal(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL skip_if_none, HAL_BOOL apply_last_iqcorr) { HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); HAL_BOOL do_rtt_cal = AH_TRUE; HAL_BOOL enable_rtt = AH_FALSE; HALASSERT(ichan); return ar9300_init_cal_internal(ah, chan, ichan, enable_rtt, do_rtt_cal, skip_if_none, apply_last_iqcorr); } /* ar9300_reset_cal_valid * Entry point for upper layers to restart current cal. * Reset the calibration valid bit in channel. */ void ar9300_reset_cal_valid(struct ath_hal *ah, const struct ieee80211_channel *chan, HAL_BOOL *is_cal_done, u_int32_t cal_type) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); HAL_CAL_LIST *curr_cal = ahp->ah_cal_list_curr; *is_cal_done = AH_TRUE; if (curr_cal == AH_NULL) { return; } if (ichan == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->ic_freq, chan->ic_flags); return; } if (!(cal_type & IQ_MISMATCH_CAL)) { *is_cal_done = AH_FALSE; return; } /* Expected that this calibration has run before, post-reset. * Current state should be done */ if (curr_cal->cal_state != CAL_DONE) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Calibration state incorrect, %d\n", __func__, curr_cal->cal_state); return; } /* Verify Cal is supported on this channel */ if (ar9300_is_cal_supp(ah, chan, curr_cal->cal_data->cal_type) == AH_FALSE) { return; } HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Resetting Cal %d state for channel %u/0x%x\n", __func__, curr_cal->cal_data->cal_type, chan->ic_freq, chan->ic_flags); /* Disable cal validity in channel */ ichan->calValid &= ~curr_cal->cal_data->cal_type; curr_cal->cal_state = CAL_WAITING; /* Indicate to upper layers that we need polling */ *is_cal_done = AH_FALSE; } static inline void ar9300_set_dma(struct ath_hal *ah) { u_int32_t regval; struct ath_hal_9300 *ahp = AH9300(ah); + struct ath_hal_private *ahpriv = AH_PRIVATE(ah); + HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; #if 0 /* * set AHB_MODE not to do cacheline prefetches */ regval = OS_REG_READ(ah, AR_AHB_MODE); OS_REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); #endif /* * let mac dma reads be in 128 byte chunks */ regval = OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; OS_REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); /* * Restore TX Trigger Level to its pre-reset value. * The initial value depends on whether aggregation is enabled, and is * adjusted whenever underruns are detected. */ /* OS_REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, AH_PRIVATE(ah)->ah_tx_trig_level); */ /* * Osprey 1.0 bug (EV 61936). Don't change trigger level from .ini default. * Osprey 2.0 - hardware recommends using the default INI settings. */ #if 0 OS_REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, 0x3f); #endif /* * let mac dma writes be in 128 byte chunks */ regval = OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; OS_REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); /* * Setup receive FIFO threshold to hold off TX activities */ OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); /* * reduce the number of usable entries in PCU TXBUF to avoid * wrap around bugs. (bug 20428) */ if (AR_SREV_WASP(ah) && (AH_PRIVATE((ah))->ah_macRev > AR_SREV_REVISION_WASP_12)) { /* Wasp 1.3 fix for EV#85395 requires usable entries * to be set to 0x500 */ OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, 0x500); } else { OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE); } /* * Enable HPQ for UAPSD */ - if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { - OS_REG_WRITE(ah, AR_HP_Q_CONTROL, - AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN); + if (pCap->halHwUapsdTrig == AH_TRUE) { + /* Only enable this if HAL capabilities says it is OK */ + if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { + OS_REG_WRITE(ah, AR_HP_Q_CONTROL, + AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN); + } + } else { + /* use default value from ini file - which disable HPQ queue usage */ } /* * set the transmit status ring */ ar9300_reset_tx_status_ring(ah); /* * set rxbp threshold. Must be non-zero for RX_EOL to occur. * For Osprey 2.0+, keep the original thresholds * otherwise performance is lost due to excessive RX EOL interrupts. */ OS_REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1); OS_REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1); /* * set receive buffer size. */ if (ahp->rx_buf_size) { OS_REG_WRITE(ah, AR_DATABUF, ahp->rx_buf_size); } } static inline void ar9300_init_bb(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int32_t synth_delay; /* * Wait for the frequency synth to settle (synth goes on * via AR_PHY_ACTIVE_EN). Read the phy active delay register. * Value is in 100ns increments. */ synth_delay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; if (IEEE80211_IS_CHAN_CCK(chan)) { synth_delay = (4 * synth_delay) / 22; } else { synth_delay /= 10; } /* Activate the PHY (includes baseband activate + synthesizer on) */ OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); /* * There is an issue if the AP starts the calibration before * the base band timeout completes. This could result in the * rx_clear AH_FALSE triggering. As a workaround we add delay an * extra BASE_ACTIVATE_DELAY usecs to ensure this condition * does not happen. */ OS_DELAY(synth_delay + BASE_ACTIVATE_DELAY); } static inline void ar9300_init_interrupt_masks(struct ath_hal *ah, HAL_OPMODE opmode) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t msi_cfg = 0; u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT; /* * Setup interrupt handling. Note that ar9300_reset_tx_queue * manipulates the secondary IMR's as queues are enabled * and disabled. This is done with RMW ops to insure the * settings we make here are preserved. */ ahp->ah_mask_reg = AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; if (ahp->ah_intr_mitigation_rx) { /* enable interrupt mitigation for rx */ ahp->ah_mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR | AR_IMR_RXOK_HP; msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR; } else { ahp->ah_mask_reg |= AR_IMR_RXOK_LP | AR_IMR_RXOK_HP; msi_cfg |= AR_INTCFG_MSI_RXOK; } if (ahp->ah_intr_mitigation_tx) { /* enable interrupt mitigation for tx */ ahp->ah_mask_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR; msi_cfg |= AR_INTCFG_MSI_TXINTM | AR_INTCFG_MSI_TXMINTR; } else { ahp->ah_mask_reg |= AR_IMR_TXOK; msi_cfg |= AR_INTCFG_MSI_TXOK; } if (opmode == HAL_M_HOSTAP) { ahp->ah_mask_reg |= AR_IMR_MIB; } OS_REG_WRITE(ah, AR_IMR, ahp->ah_mask_reg); OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); ahp->ah_mask2Reg = OS_REG_READ(ah, AR_IMR_S2); if (ah->ah_config.ath_hal_enable_msi) { /* Cache MSI register value */ ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI)); ahp->ah_msi_reg |= AR_PCIE_MSI_HW_DBI_WR_EN; if (AR_SREV_POSEIDON(ah)) { ahp->ah_msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64; } else { ahp->ah_msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR; } /* Program MSI configuration */ OS_REG_WRITE(ah, AR_INTCFG, msi_cfg); } /* * debug - enable to see all synchronous interrupts status */ /* Clear any pending sync cause interrupts */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE), 0xFFFFFFFF); /* Allow host interface sync interrupt sources to set cause bit */ if (AR_SREV_POSEIDON(ah)) { sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR; } else if (AR_SREV_WASP(ah)) { sync_en_def = AR9340_INTR_SYNC_DEFAULT; } OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), sync_en_def); /* _Disable_ host interface sync interrupt when cause bits set */ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_ENABLE), 0); OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_MASK), 0); } static inline void ar9300_init_qos(struct ath_hal *ah) { OS_REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); /* XXX magic */ OS_REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); /* XXX magic */ /* Turn on NOACK Support for QoS packets */ OS_REG_WRITE(ah, AR_QOS_NO_ACK, SM(2, AR_QOS_NO_ACK_TWO_BIT) | SM(5, AR_QOS_NO_ACK_BIT_OFF) | SM(0, AR_QOS_NO_ACK_BYTE_OFF)); /* * initialize TXOP for all TIDs */ OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); } static inline void ar9300_init_user_settings(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); /* Restore user-specified settings */ HALDEBUG(ah, HAL_DEBUG_RESET, "--AP %s ahp->ah_misc_mode 0x%x\n", __func__, ahp->ah_misc_mode); if (ahp->ah_misc_mode != 0) { OS_REG_WRITE(ah, AR_PCU_MISC, OS_REG_READ(ah, AR_PCU_MISC) | ahp->ah_misc_mode); } if (ahp->ah_get_plcp_hdr) { OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); } if (ahp->ah_slot_time != (u_int) -1) { ar9300_set_slot_time(ah, ahp->ah_slot_time); } if (ahp->ah_ack_timeout != (u_int) -1) { ar9300_set_ack_timeout(ah, ahp->ah_ack_timeout); } if (AH_PRIVATE(ah)->ah_diagreg != 0) { OS_REG_SET_BIT(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); } if (ahp->ah_beacon_rssi_threshold != 0) { ar9300_set_hw_beacon_rssi_threshold(ah, ahp->ah_beacon_rssi_threshold); } #ifdef ATH_SUPPORT_DFS if (ahp->ah_cac_quiet_enabled) { ar9300_cac_tx_quiet(ah, 1); } #endif /* ATH_SUPPORT_DFS */ } int ar9300_get_spur_info(struct ath_hal * ah, int *enable, int len, u_int16_t *freq) { // struct ath_hal_private *ap = AH_PRIVATE(ah); int i, j; for (i = 0; i < len; i++) { freq[i] = 0; } *enable = ah->ah_config.ath_hal_spur_mode; for (i = 0, j = 0; i < AR_EEPROM_MODAL_SPURS; i++) { if (AH9300(ah)->ath_hal_spur_chans[i][0] != AR_NO_SPUR) { freq[j++] = AH9300(ah)->ath_hal_spur_chans[i][0]; HALDEBUG(ah, HAL_DEBUG_ANI, "1. get spur %d\n", AH9300(ah)->ath_hal_spur_chans[i][0]); } if (AH9300(ah)->ath_hal_spur_chans[i][1] != AR_NO_SPUR) { freq[j++] = AH9300(ah)->ath_hal_spur_chans[i][1]; HALDEBUG(ah, HAL_DEBUG_ANI, "2. get spur %d\n", AH9300(ah)->ath_hal_spur_chans[i][1]); } } return 0; } #define ATH_HAL_2GHZ_FREQ_MIN 20000 #define ATH_HAL_2GHZ_FREQ_MAX 29999 #define ATH_HAL_5GHZ_FREQ_MIN 50000 #define ATH_HAL_5GHZ_FREQ_MAX 59999 #if 0 int ar9300_set_spur_info(struct ath_hal * ah, int enable, int len, u_int16_t *freq) { struct ath_hal_private *ap = AH_PRIVATE(ah); int i, j, k; ap->ah_config.ath_hal_spur_mode = enable; if (ap->ah_config.ath_hal_spur_mode == SPUR_ENABLE_IOCTL) { for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { AH9300(ah)->ath_hal_spur_chans[i][0] = AR_NO_SPUR; AH9300(ah)->ath_hal_spur_chans[i][1] = AR_NO_SPUR; } for (i = 0, j = 0, k = 0; i < len; i++) { if (freq[i] > ATH_HAL_2GHZ_FREQ_MIN && freq[i] < ATH_HAL_2GHZ_FREQ_MAX) { /* 2GHz Spur */ if (j < AR_EEPROM_MODAL_SPURS) { AH9300(ah)->ath_hal_spur_chans[j++][1] = freq[i]; HALDEBUG(ah, HAL_DEBUG_ANI, "1 set spur %d\n", freq[i]); } } else if (freq[i] > ATH_HAL_5GHZ_FREQ_MIN && freq[i] < ATH_HAL_5GHZ_FREQ_MAX) { /* 5Ghz Spur */ if (k < AR_EEPROM_MODAL_SPURS) { AH9300(ah)->ath_hal_spur_chans[k++][0] = freq[i]; HALDEBUG(ah, HAL_DEBUG_ANI, "2 set spur %d\n", freq[i]); } } } } return 0; } #endif #define ar9300_check_op_mode(_opmode) \ ((_opmode == HAL_M_STA) || (_opmode == HAL_M_IBSS) ||\ (_opmode == HAL_M_HOSTAP) || (_opmode == HAL_M_MONITOR)) #ifndef ATH_NF_PER_CHAN /* * To fixed first reset noise floor value not correct issue * For ART need it to fixed low rate sens too low issue */ static int First_NFCal(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, int is_scan, struct ieee80211_channel *chan) { HAL_NFCAL_HIST_FULL *nfh; int i, j, k; int16_t nfarray[HAL_NUM_NF_READINGS] = {0}; int is_2g = 0; int nf_hist_len; int stats = 0; int16_t nf_buf[HAL_NUM_NF_READINGS]; #define IS(_c, _f) (((_c)->channel_flags & _f) || 0) if ((!is_scan) && chan->ic_freq == AH_PRIVATE(ah)->ah_curchan->ic_freq) { nfh = &AH_PRIVATE(ah)->nf_cal_hist; } else { nfh = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist; } ar9300_start_nf_cal(ah); for (j = 0; j < 10000; j++) { if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0){ break; } OS_DELAY(10); } if (j < 10000) { is_2g = IEEE80211_IS_CHAN_2GHZ(chan); ar9300_upload_noise_floor(ah, is_2g, nfarray); if (is_scan) { /* * This channel's NF cal info is just a HAL_NFCAL_HIST_SMALL struct * rather than a HAL_NFCAL_HIST_FULL struct. * As long as we only use the first history element of nf_cal_buffer * (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1]), we can use * HAL_NFCAL_HIST_SMALL and HAL_NFCAL_HIST_FULL interchangeably. */ nfh = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL; } else { nfh = &AH_PRIVATE(ah)->nf_cal_hist; nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL; } for (i = 0; i < HAL_NUM_NF_READINGS; i ++) { for (k = 0; k < HAL_NF_CAL_HIST_LEN_FULL; k++) { nfh->nf_cal_buffer[k][i] = nfarray[i]; } nfh->base.priv_nf[i] = ar9300_limit_nf_range(ah, ar9300_get_nf_hist_mid(ah, nfh, i, nf_hist_len)); } //ar9300StoreNewNf(ah, ichan, is_scan); /* * See if the NF value from the old channel should be * retained when switching to a new channel. * TBD: this may need to be changed, as it wipes out the * purpose of saving NF values for each channel. */ for (i = 0; i < HAL_NUM_NF_READINGS; i++) { if (IEEE80211_IS_CHAN_2GHZ(chan)) { if (nfh->nf_cal_buffer[0][i] < AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ) { ichan->nf_cal_hist.nf_cal_buffer[0][i] = AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i]; } } else { if (AR_SREV_AR9580(ah)) { if (nfh->nf_cal_buffer[0][i] < AR_PHY_CCA_NOM_VAL_PEACOCK_5GHZ) { ichan->nf_cal_hist.nf_cal_buffer[0][i] = AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i]; } } else { if (nfh->nf_cal_buffer[0][i] < AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ) { ichan->nf_cal_hist.nf_cal_buffer[0][i] = AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i]; } } } } /* * Copy the channel's NF buffer, which may have been modified * just above here, to the full NF history buffer. */ ar9300_reset_nf_hist_buff(ah, ichan); ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf); ar9300_load_nf(ah, nf_buf); stats = 0; } else { stats = 1; } #undef IS return stats; } #endif /* * Places the device in and out of reset and then places sane * values in the registers based on EEPROM config, initialization * vectors (as determined by the mode), and station configuration * * b_channel_change is used to preserve DMA/PCU registers across * a HW Reset during channel change. */ HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, HAL_BOOL b_channel_change, HAL_STATUS *status, int is_scan) { #define FAIL(_code) do { ecode = _code; goto bad; } while (0) u_int32_t save_led_state; struct ath_hal_9300 *ahp = AH9300(ah); struct ath_hal_private *ap = AH_PRIVATE(ah); HAL_CHANNEL_INTERNAL *ichan; //const struct ieee80211_channel *curchan = ap->ah_curchan; #if ATH_SUPPORT_MCI HAL_BOOL save_full_sleep = ahp->ah_chip_full_sleep; #endif u_int32_t save_def_antenna; u_int32_t mac_sta_id1; HAL_STATUS ecode; int i, rx_chainmask; int nf_hist_buff_reset = 0; int16_t nf_buf[HAL_NUM_NF_READINGS]; #ifdef ATH_FORCE_PPM u_int32_t save_force_val, tmp_reg; #endif HAL_BOOL stopped, cal_ret; HAL_BOOL apply_last_iqcorr = AH_FALSE; + if (OS_REG_READ(ah, AR_IER) == AR_IER_ENABLE) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "** Reset called with WLAN " "interrupt enabled %08x **\n", ar9300_get_interrupts(ah)); } /* * Set the status to "ok" by default to cover the cases * where we return AH_FALSE without going to "bad" */ HALASSERT(status); *status = HAL_OK; if ((ah->ah_config.ath_hal_sta_update_tx_pwr_enable)) { AH9300(ah)->green_tx_status = HAL_RSSI_TX_POWER_NONE; } #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah))) { ar9300_mci_2g5g_changed(ah, IEEE80211_IS_CHAN_2GHZ(chan)); } #endif ahp->ah_ext_prot_spacing = extprotspacing; ahp->ah_tx_chainmask = txchainmask & ap->ah_caps.halTxChainMask; ahp->ah_rx_chainmask = rxchainmask & ap->ah_caps.halRxChainMask; ahp->ah_tx_cal_chainmask = ap->ah_caps.halTxChainMask; ahp->ah_rx_cal_chainmask = ap->ah_caps.halRxChainMask; + + /* + * Keep the previous optinal txchainmask value + */ + HALASSERT(ar9300_check_op_mode(opmode)); OS_MARK(ah, AH_MARK_RESET, b_channel_change); /* * Map public channel to private. */ ichan = ar9300_check_chan(ah, chan); if (ichan == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->ic_freq, chan->ic_flags); FAIL(HAL_EINVAL); } ichan->paprd_table_write_done = 0; /* Clear PAPRD table write flag */ #if 0 chan->paprd_table_write_done = 0; /* Clear PAPRD table write flag */ #endif if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) { /* Need to stop RX DMA before reset otherwise chip might hang */ stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */ ar9300_set_rx_filter(ah, 0); stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */ if (!stopped) { /* * During the transition from full sleep to reset, * recv DMA regs are not available to be read */ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__); b_channel_change = AH_FALSE; } } else { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__); } #if ATH_SUPPORT_MCI if ((AH_PRIVATE(ah)->ah_caps.halMciSupport) && (ahp->ah_mci_bt_state == MCI_BT_CAL_START)) { u_int32_t payload[4] = {0, 0, 0, 0}; HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Stop rx for BT cal.\n", __func__); ahp->ah_mci_bt_state = MCI_BT_CAL; /* * MCIFIX: disable mci interrupt here. This is to avoid SW_MSG_DONE or * RX_MSG bits to trigger MCI_INT and lead to mci_intr reentry. */ ar9300_mci_disable_interrupt(ah); HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send WLAN_CAL_GRANT\n", __func__); MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE); /* Wait BT calibration to be completed for 25ms */ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: BT is calibrating.\n", __func__); if (ar9300_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, 0, 25000)) { HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Got BT_CAL_DONE.\n", __func__); } else { HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: ### BT cal takes too long. Force bt_state to be bt_awake.\n", __func__); } ahp->ah_mci_bt_state = MCI_BT_AWAKE; /* MCIFIX: enable mci interrupt here */ ar9300_mci_enable_interrupt(ah); return AH_TRUE; } #endif /* Bring out of sleep mode */ if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) { *status = HAL_INV_PMODE; return AH_FALSE; } /* Check the Rx mitigation config again, it might have changed * during attach in ath_vap_attach. */ if (ah->ah_config.ath_hal_intr_mitigation_rx != 0) { ahp->ah_intr_mitigation_rx = AH_TRUE; } else { ahp->ah_intr_mitigation_rx = AH_FALSE; } /* * XXX TODO FreeBSD: * * This is painful because we don't have a non-const channel pointer * at this stage. * * Make sure this gets fixed! */ #if 0 /* Get the value from the previous NF cal and update history buffer */ if (curchan && (ahp->ah_chip_full_sleep != AH_TRUE)) { - ar9300_store_new_nf(ah, curchan, is_scan); + + if(ahp->ah_chip_reset_done){ + ahp->ah_chip_reset_done = 0; + } else { + /* + * is_scan controls updating NF for home channel or off channel. + * Home -> Off, update home channel + * Off -> Home, update off channel + * Home -> Home, uppdate home channel + */ + if (ap->ah_curchan->channel != chan->channel) + ar9300_store_new_nf(ah, curchan, !is_scan); + else + ar9300_store_new_nf(ah, curchan, is_scan); + } } #endif /* * Account for the effect of being in either the 2 GHz or 5 GHz band * on the nominal, max allowable, and min allowable noise floor values. */ AH9300(ah)->nfp = IS_CHAN_2GHZ(ichan) ? &ahp->nf_2GHz : &ahp->nf_5GHz; /* - * XXX For now, don't apply the last IQ correction. + * XXX FreeBSD For now, don't apply the last IQ correction. * * This should be done when scorpion is enabled on FreeBSD; just be * sure to fix this channel match code so it uses net80211 flags * instead. */ #if 0 if (AR_SREV_SCORPION(ah) && curchan && (chan->channel == curchan->channel) && ((chan->channel_flags & (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)) == (curchan->channel_flags & (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER)))) { apply_last_iqcorr = AH_TRUE; } #endif apply_last_iqcorr = AH_FALSE; #ifndef ATH_NF_PER_CHAN /* * If there's only one full-size home-channel NF history buffer * rather than a full-size NF history buffer per channel, decide * whether to (re)initialize the home-channel NF buffer. * If this is just a channel change for a scan, or if the channel * is not being changed, don't mess up the home channel NF history * buffer with NF values from this scanned channel. If we're * changing the home channel to a new channel, reset the home-channel * NF history buffer with the most accurate NF known for the new channel. */ if (!is_scan && (!ap->ah_curchan || ap->ah_curchan->ic_freq != chan->ic_freq)) // || // ap->ah_curchan->channel_flags != chan->channel_flags)) { nf_hist_buff_reset = 1; ar9300_reset_nf_hist_buff(ah, ichan); } #endif /* + * In case of + * - offchan scan, or + * - same channel and RX IQ Cal already available + * disable RX IQ Cal. + */ + if (is_scan) { + ahp->ah_skip_rx_iq_cal = AH_TRUE; + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "Skip RX IQ Cal due to scanning\n"); + } else { +#if 0 + /* XXX FreeBSD: always just do the RX IQ cal */ + /* XXX I think it's just going to speed things up; I don't think it's to avoid chan bugs */ + if (ahp->ah_rx_cal_complete && + ahp->ah_rx_cal_chan == ichan->channel && + ahp->ah_rx_cal_chan_flag == chan->channel_flags) { + ahp->ah_skip_rx_iq_cal = AH_TRUE; + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "Skip RX IQ Cal due to same channel with completed RX IQ Cal\n"); + } else +#endif + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } + + /* * Fast channel change (Change synthesizer based on channel freq * without resetting chip) * Don't do it when * - Flag is not set * - Chip is just coming out of full sleep * - Channel to be set is same as current channel * - Channel flags are different, like when moving from 2GHz to 5GHz * channels * - Merlin: Switching in/out of fast clock enabled channels * (not currently coded, since fast clock is enabled * across the 5GHz band * and we already do a full reset when switching in/out * of 5GHz channels) */ #if 0 if (b_channel_change && (ahp->ah_chip_full_sleep != AH_TRUE) && (AH_PRIVATE(ah)->ah_curchan != AH_NULL) && ((chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) && (((CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) & chan->channel_flags) == ((CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) & AH_PRIVATE(ah)->ah_curchan->channel_flags)))) { if (ar9300_channel_change(ah, chan, ichan, macmode)) { chan->channel_flags = ichan->channel_flags; chan->priv_flags = ichan->priv_flags; AH_PRIVATE(ah)->ah_curchan->ah_channel_time = 0; AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar9300_get_tsf64(ah); /* * Load the NF from history buffer of the current channel. * NF is slow time-variant, so it is OK to use a historical value. */ ar9300_get_nf_hist_base(ah, AH_PRIVATE(ah)->ah_curchan, is_scan, nf_buf); ar9300_load_nf(ah, nf_buf); /* start NF calibration, without updating BB NF register*/ ar9300_start_nf_cal(ah); /* * If channel_change completed and DMA was stopped * successfully - skip the rest of reset */ if (AH9300(ah)->ah_dma_stuck != AH_TRUE) { WAR_USB_DISABLE_PLL_LOCK_DETECT(ah); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) { ar9300_mci_2g5g_switch(ah, AH_TRUE); } #endif return HAL_OK; } } } #endif /* #if 0 */ #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { ar9300_mci_disable_interrupt(ah); if (ahp->ah_mci_ready && !save_full_sleep) { ar9300_mci_mute_bt(ah); OS_DELAY(20); OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0); } ahp->ah_mci_bt_state = MCI_BT_SLEEP; ahp->ah_mci_ready = AH_FALSE; } #endif AH9300(ah)->ah_dma_stuck = AH_FALSE; #ifdef ATH_FORCE_PPM /* Preserve force ppm state */ save_force_val = OS_REG_READ(ah, AR_PHY_TIMING2) & (AR_PHY_TIMING2_USE_FORCE | AR_PHY_TIMING2_FORCE_VAL); #endif /* * Preserve the antenna on a channel change */ save_def_antenna = OS_REG_READ(ah, AR_DEF_ANTENNA); if (0 == ahp->ah_smartantenna_enable ) { if (save_def_antenna == 0) { save_def_antenna = 1; } } /* Save hardware flag before chip reset clears the register */ mac_sta_id1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; /* Save led state from pci config register */ save_led_state = OS_REG_READ(ah, AR_CFG_LED) & (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); /* Mark PHY inactive prior to reset, to be undone in ar9300_init_bb () */ ar9300_mark_phy_inactive(ah); if (!ar9300_chip_reset(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); /* Disable JTAG */ OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE); /* * Note that ar9300_init_chain_masks() is called from within * ar9300_process_ini() to ensure the swap bit is set before * the pdadc table is written. */ ecode = ar9300_process_ini(ah, chan, ichan, macmode); if (ecode != HAL_OK) { goto bad; } ahp->ah_immunity_on = AH_FALSE; if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { ahp->tx_iq_cal_enable = OS_REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah), AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL) ? 1 : 0; } ahp->tx_cl_cal_enable = (OS_REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) ? 1 : 0; /* For devices with full HW RIFS Rx support (Sowl/Howl/Merlin, etc), * restore register settings from prior to reset. */ if ((AH_PRIVATE(ah)->ah_curchan != AH_NULL) && (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK)) { /* Re-program RIFS Rx policy after reset */ ar9300_set_rifs_delay(ah, ahp->ah_rifs_enabled); } #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport) { ar9300_mci_reset(ah, AH_FALSE, IS_CHAN_2GHZ(ichan), save_full_sleep); } #endif /* Initialize Management Frame Protection */ ar9300_init_mfp(ah); ahp->ah_immunity_vals[0] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); ahp->ah_immunity_vals[1] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); ahp->ah_immunity_vals[2] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M1_THRESH); ahp->ah_immunity_vals[3] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2_THRESH); ahp->ah_immunity_vals[4] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2COUNT_THR); ahp->ah_immunity_vals[5] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ if (IEEE80211_IS_CHAN_OFDM(chan) || IEEE80211_IS_CHAN_HT(chan)) { ar9300_set_delta_slope(ah, chan); } ar9300_spur_mitigate(ah, chan); if (!ar9300_eeprom_set_board_values(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: error setting board options\n", __func__); FAIL(HAL_EIO); } #ifdef ATH_HAL_WAR_REG16284_APH128 /* temp work around, will be removed. */ if (AR_SREV_WASP(ah)) { OS_REG_WRITE(ah, 0x16284, 0x1553e000); } #endif OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) | mac_sta_id1 | AR_STA_ID1_RTS_USE_DEF | (ah->ah_config.ath_hal_6mb_ack ? AR_STA_ID1_ACKCTS_6MB : 0) | ahp->ah_sta_id1_defaults ); ar9300_set_operating_mode(ah, opmode); /* Set Venice BSSID mask according to current state */ OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssid_mask)); OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssid_mask + 4)); /* Restore previous antenna */ OS_REG_WRITE(ah, AR_DEF_ANTENNA, save_def_antenna); #ifdef ATH_FORCE_PPM /* Restore force ppm state */ tmp_reg = OS_REG_READ(ah, AR_PHY_TIMING2) & ~(AR_PHY_TIMING2_USE_FORCE | AR_PHY_TIMING2_FORCE_VAL); OS_REG_WRITE(ah, AR_PHY_TIMING2, tmp_reg | save_force_val); #endif /* then our BSSID and assocID */ OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4) | ((ahp->ah_assoc_id & 0x3fff) << AR_BSS_ID1_AID_S)); OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, INIT_RSSI_THR); /* HW beacon processing */ /* * XXX what happens if I just leave filter_interval=0? * it stays disabled? */ OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_BCN_WEIGHT, INIT_RSSI_BEACON_WEIGHT); OS_REG_SET_BIT(ah, AR_HWBCNPROC1, AR_HWBCNPROC1_CRC_ENABLE | AR_HWBCNPROC1_EXCLUDE_TIM_ELM); if (ah->ah_config.ath_hal_beacon_filter_interval) { OS_REG_RMW_FIELD(ah, AR_HWBCNPROC2, AR_HWBCNPROC2_FILTER_INTERVAL, ah->ah_config.ath_hal_beacon_filter_interval); OS_REG_SET_BIT(ah, AR_HWBCNPROC2, AR_HWBCNPROC2_FILTER_INTERVAL_ENABLE); } /* * Set Channel now modifies bank 6 parameters for FOWL workaround * to force rf_pwd_icsyndiv bias current as function of synth * frequency.Thus must be called after ar9300_process_ini() to ensure * analog register cache is valid. */ if (!ahp->ah_rf_hal.set_channel(ah, chan)) { FAIL(HAL_EIO); } OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); /* Set 1:1 QCU to DCU mapping for all queues */ for (i = 0; i < AR_NUM_DCU; i++) { OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); } ahp->ah_intr_txqs = 0; for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) { ar9300_reset_tx_queue(ah, i); } ar9300_init_interrupt_masks(ah, opmode); /* Reset ier reference count to disabled */ // OS_ATOMIC_SET(&ahp->ah_ier_ref_count, 1); if (ath_hal_isrfkillenabled(ah)) { ar9300_enable_rf_kill(ah); } /* must be called AFTER ini is processed */ ar9300_ani_init_defaults(ah, macmode); ar9300_init_qos(ah); ar9300_init_user_settings(ah); AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ OS_MARK(ah, AH_MARK_RESET_DONE, 0); /* * disable seq number generation in hw */ OS_REG_WRITE(ah, AR_STA_ID1, OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); ar9300_set_dma(ah); /* * program OBS bus to see MAC interrupts */ #if ATH_SUPPORT_MCI if (!AH_PRIVATE(ah)->ah_caps.halMciSupport) { OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 8); } #else OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 8); #endif /* enabling AR_GTTM_IGNORE_IDLE in GTTM register so that GTT timer will not increment if the channel idle indicates the air is busy or NAV is still counting down */ OS_REG_WRITE(ah, AR_GTTM, AR_GTTM_IGNORE_IDLE); /* * GTT debug mode setting */ /* OS_REG_WRITE(ah, 0x64, 0x00320000); OS_REG_WRITE(ah, 0x68, 7); OS_REG_WRITE(ah, 0x4080, 0xC); */ /* * Disable general interrupt mitigation by setting MIRT = 0x0 * Rx and tx interrupt mitigation are conditionally enabled below. */ OS_REG_WRITE(ah, AR_MIRT, 0); if (ahp->ah_intr_mitigation_rx) { /* * Enable Interrupt Mitigation for Rx. * If no build-specific limits for the rx interrupt mitigation * timer have been specified, use conservative defaults. */ #ifndef AH_RIMT_VAL_LAST #define AH_RIMT_LAST_MICROSEC 500 #endif #ifndef AH_RIMT_VAL_FIRST #define AH_RIMT_FIRST_MICROSEC 2000 #endif #ifndef HOST_OFFLOAD OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, AH_RIMT_LAST_MICROSEC); OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, AH_RIMT_FIRST_MICROSEC); #else /* lower mitigation level to reduce latency for offload arch. */ OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, (AH_RIMT_LAST_MICROSEC >> 2)); OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, (AH_RIMT_FIRST_MICROSEC >> 2)); #endif } if (ahp->ah_intr_mitigation_tx) { /* * Enable Interrupt Mitigation for Tx. * If no build-specific limits for the tx interrupt mitigation * timer have been specified, use the values preferred for * the carrier group's products. */ #ifndef AH_TIMT_LAST #define AH_TIMT_LAST_MICROSEC 300 #endif #ifndef AH_TIMT_FIRST #define AH_TIMT_FIRST_MICROSEC 750 #endif OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, AH_TIMT_LAST_MICROSEC); OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, AH_TIMT_FIRST_MICROSEC); } rx_chainmask = ahp->ah_rx_chainmask; OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); ar9300_init_bb(ah, chan); /* BB Step 7: Calibration */ + /* + * Only kick off calibration not on offchan. + * If coming back from offchan, restore prevous Cal results + * since chip reset will clear existings. + */ + if (!ahp->ah_skip_rx_iq_cal) { + int i; + /* clear existing RX cal data */ + for (i=0; iah_rx_cal_corr[i] = 0; + + ahp->ah_rx_cal_complete = AH_FALSE; +// ahp->ah_rx_cal_chan = chan->channel; +// ahp->ah_rx_cal_chan_flag = ichan->channel_flags; + ahp->ah_rx_cal_chan = 0; + ahp->ah_rx_cal_chan_flag = 0; /* XXX FreeBSD */ + } ar9300_invalidate_saved_cals(ah, ichan); cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) { if (IS_CHAN_2GHZ(ichan) && (ahp->ah_mci_bt_state == MCI_BT_SLEEP)) { if (ar9300_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || ar9300_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { /* * BT is sleeping. Check if BT wakes up duing WLAN * calibration. If BT wakes up during WLAN calibration, need * to go through all message exchanges again and recal. */ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) ### %s: BT wakes up during WLAN calibration.\n", __func__); OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n"); ar9300_mci_remote_reset(ah, AH_TRUE); ar9300_mci_send_sys_waking(ah, AH_TRUE); OS_DELAY(1); if (IS_CHAN_2GHZ(ichan)) { ar9300_mci_send_lna_transfer(ah, AH_TRUE); } ahp->ah_mci_bt_state = MCI_BT_AWAKE; /* Redo calibration */ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Re-calibrate.\n", __func__); ar9300_invalidate_saved_cals(ah, ichan); cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr); } } ar9300_mci_enable_interrupt(ah); } #endif if (!cal_ret) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Init Cal Failed\n", __func__); FAIL(HAL_ESELFTEST); } ar9300_init_txbf(ah); #if 0 /* * WAR for owl 1.0 - restore chain mask for 2-chain cfgs after cal */ rx_chainmask = ahp->ah_rx_chainmask; if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); } #endif /* Restore previous led state */ OS_REG_WRITE(ah, AR_CFG_LED, save_led_state | AR_CFG_SCLK_32KHZ); #if ATH_BT_COEX if (ahp->ah_bt_coex_config_type != HAL_BT_COEX_CFG_NONE) { ar9300_init_bt_coex(ah); #if ATH_SUPPORT_MCI if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) { /* Check BT state again to make sure it's not changed. */ ar9300_mci_sync_bt_state(ah); ar9300_mci_2g5g_switch(ah, AH_TRUE); if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) && (ahp->ah_mci_query_bt == AH_TRUE)) { ahp->ah_mci_need_flush_btinfo = AH_TRUE; } } #endif } #endif /* Start TSF2 for generic timer 8-15. */ ar9300_start_tsf2(ah); /* MIMO Power save setting */ if (ar9300_get_capability(ah, HAL_CAP_DYNAMIC_SMPS, 0, AH_NULL) == HAL_OK) { ar9300_set_sm_power_mode(ah, ahp->ah_sm_power_mode); } /* * For big endian systems turn on swapping for descriptors */ #if AH_BYTE_ORDER == AH_BIG_ENDIAN if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB | AR_CFG_SWRB, 0); } else { ar9300_init_cfg_reg(ah); } #endif if ( AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { OS_REG_RMW(ah, AR_CFG_LED, AR_CFG_LED_ASSOC_CTL, AR_CFG_LED_ASSOC_CTL); } #if !(defined(ART_BUILD)) && defined(ATH_SUPPORT_LED) #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val); #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) #define ATH_GPIO_OUT_FUNCTION3 0xB8040038 #define ATH_GPIO_OE 0xB8040000 if ( AR_SREV_WASP(ah)) { if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) { REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff << 8))) | (0x33 << 8) ); REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) & (~(0x1 << 13) ))); } else { /* Disable 2G WLAN LED. During ath_open, reset function is called even before channel is set. So 2GHz is taken as default and it also blinks. Hence to avoid both from blinking, disable 2G led while in 5G mode */ REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) | (1 << 13) )); REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x33) ); REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) ))); } } else if (AR_SREV_SCORPION(ah)) { if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) { REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff << 8))) | (0x2F << 8) ); REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 13) )) | (0x1 << 12))); } else if (IS_CHAN_5GHZ((AH_PRIVATE(ah)->ah_curchan))) { REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x2F) ); REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) )) | (0x1 << 13))); } } #undef REG_READ #undef REG_WRITE #endif /* XXX FreeBSD What's this? -adrian */ #if 0 chan->channel_flags = ichan->channel_flags; chan->priv_flags = ichan->priv_flags; #endif #if FIX_NOISE_FLOOR /* XXX FreeBSD is ichan appropariate? It was curchan.. */ ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf); ar9300_load_nf(ah, nf_buf); if (nf_hist_buff_reset == 1) { nf_hist_buff_reset = 0; #ifndef ATH_NF_PER_CHAN if (First_NFCal(ah, ichan, is_scan, chan)){ + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } } #endif /* ATH_NF_PER_CHAN */ } else{ ar9300_start_nf_cal(ah); } #endif #ifdef AH_SUPPORT_AR9300 /* BB Panic Watchdog */ if (ar9300_get_capability(ah, HAL_CAP_BB_PANIC_WATCHDOG, 0, AH_NULL) == HAL_OK) { ar9300_config_bb_panic_watchdog(ah); } #endif /* While receiving unsupported rate frame receive state machine * gets into a state 0xb and if phy_restart happens when rx * state machine is in 0xb state, BB would go hang, if we * see 0xb state after first bb panic, make sure that we * disable the phy_restart. * * There may be multiple panics, make sure that we always do * this if we see this panic at least once. This is required * because reset seems to be writing from INI file. */ if ((ar9300_get_capability(ah, HAL_CAP_PHYRESTART_CLR_WAR, 0, AH_NULL) == HAL_OK) && (((MS((AH9300(ah)->ah_bb_panic_last_status), AR_PHY_BB_WD_RX_OFDM_SM)) == 0xb) || AH9300(ah)->ah_phyrestart_disabled) ) { ar9300_disable_phy_restart(ah, 1); } ahp->ah_radar1 = MS(OS_REG_READ(ah, AR_PHY_RADAR_1), AR_PHY_RADAR_1_CF_BIN_THRESH); ahp->ah_dc_offset = MS(OS_REG_READ(ah, AR_PHY_TIMING2), AR_PHY_TIMING2_DC_OFFSET); ahp->ah_disable_cck = MS(OS_REG_READ(ah, AR_PHY_MODE), AR_PHY_MODE_DISABLE_CCK); if (AH9300(ah)->ah_enable_keysearch_always) { ar9300_enable_keysearch_always(ah, 1); } #if ATH_LOW_POWER_ENABLE #define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val) #define REG_READ(_reg) *((volatile u_int32_t *)(_reg)) if (AR_SREV_OSPREY(ah)) { REG_WRITE(0xb4000080, REG_READ(0xb4000080) | 3); OS_REG_WRITE(ah, AR_RTC_RESET, 1); OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL), AR_PCIE_PM_CTRL_ENA); OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_SPARE), 0xffffffff); } #undef REG_READ #undef REG_WRITE #endif /* ATH_LOW_POWER_ENABLE */ WAR_USB_DISABLE_PLL_LOCK_DETECT(ah); /* H/W Green TX */ ar9300_control_signals_for_green_tx_mode(ah); /* Smart Antenna, only for 5GHz on Scropion */ if (IEEE80211_IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan)) && AR_SREV_SCORPION(ah)) { ahp->ah_smartantenna_enable = 0; } ar9300_set_smart_antenna(ah, ahp->ah_smartantenna_enable); + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } + return AH_TRUE; bad: OS_MARK(ah, AH_MARK_RESET_DONE, ecode); *status = ecode; + + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } return AH_FALSE; #undef FAIL } void ar9300_green_ap_ps_on_off( struct ath_hal *ah, u_int16_t on_off) { /* Set/reset the ps flag */ AH9300(ah)->green_ap_ps_on = !!on_off; } /* * This function returns 1, where it is possible to do * single-chain power save. */ u_int16_t ar9300_is_single_ant_power_save_possible(struct ath_hal *ah) { return AH_TRUE; } /* To avoid compilation warnings. Functions not used when EMULATION. */ /* * ar9300_find_mag_approx() */ static int32_t ar9300_find_mag_approx(struct ath_hal *ah, int32_t in_re, int32_t in_im) { int32_t abs_i = abs(in_re); int32_t abs_q = abs(in_im); int32_t max_abs, min_abs; if (abs_i > abs_q) { max_abs = abs_i; min_abs = abs_q; } else { max_abs = abs_q; min_abs = abs_i; } return (max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4)); } /* * ar9300_solve_iq_cal() * solve 4x4 linear equation used in loopback iq cal. */ static HAL_BOOL ar9300_solve_iq_cal( struct ath_hal *ah, int32_t sin_2phi_1, int32_t cos_2phi_1, int32_t sin_2phi_2, int32_t cos_2phi_2, int32_t mag_a0_d0, int32_t phs_a0_d0, int32_t mag_a1_d0, int32_t phs_a1_d0, int32_t solved_eq[]) { int32_t f1 = cos_2phi_1 - cos_2phi_2; int32_t f3 = sin_2phi_1 - sin_2phi_2; int32_t f2; int32_t mag_tx, phs_tx, mag_rx, phs_rx; const int32_t result_shift = 1 << 15; f2 = (((int64_t)f1 * (int64_t)f1) / result_shift) + (((int64_t)f3 * (int64_t)f3) / result_shift); if (0 == f2) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d).\n", __func__, __LINE__); return AH_FALSE; } /* magnitude mismatch, tx */ mag_tx = f1 * (mag_a0_d0 - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0); /* phase mismatch, tx */ phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0); mag_tx = (mag_tx / f2); phs_tx = (phs_tx / f2); /* magnitude mismatch, rx */ mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) / result_shift; /* phase mismatch, rx */ phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) / result_shift; solved_eq[0] = mag_tx; solved_eq[1] = phs_tx; solved_eq[2] = mag_rx; solved_eq[3] = phs_rx; return AH_TRUE; } /* * ar9300_calc_iq_corr() */ static HAL_BOOL ar9300_calc_iq_corr(struct ath_hal *ah, int32_t chain_idx, const int32_t iq_res[], int32_t iqc_coeff[]) { int32_t i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0; int32_t i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1; int32_t i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0; int32_t i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1; int32_t mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1; int32_t phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1; int32_t sin_2phi_1, cos_2phi_1, sin_2phi_2, cos_2phi_2; int32_t mag_tx, phs_tx, mag_rx, phs_rx; int32_t solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx; int32_t q_q_coff, q_i_coff; const int32_t res_scale = 1 << 15; const int32_t delpt_shift = 1 << 8; int32_t mag1, mag2; i2_m_q2_a0_d0 = iq_res[0] & 0xfff; i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff; iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8); if (i2_m_q2_a0_d0 > 0x800) { i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1); } if (iq_corr_a0_d0 > 0x800) { iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1); } i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff; i2_p_q2_a0_d1 = (iq_res[2] & 0xfff); iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff; if (i2_m_q2_a0_d1 > 0x800) { i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1); } if (iq_corr_a0_d1 > 0x800) { iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1); } i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8); i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff; iq_corr_a1_d0 = iq_res[4] & 0xfff; if (i2_m_q2_a1_d0 > 0x800) { i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1); } if (iq_corr_a1_d0 > 0x800) { iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1); } i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff; i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8); iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff; if (i2_m_q2_a1_d1 > 0x800) { i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1); } if (iq_corr_a1_d1 > 0x800) { iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1); } if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d):\na0_d0=%d\na0_d1=%d\na2_d0=%d\na1_d1=%d\n", __func__, __LINE__, i2_p_q2_a0_d0, i2_p_q2_a0_d1, i2_p_q2_a1_d0, i2_p_q2_a1_d1); return AH_FALSE; } if ((i2_p_q2_a0_d0 <= 1024) || (i2_p_q2_a0_d0 > 2047) || (i2_p_q2_a1_d0 < 0) || (i2_p_q2_a1_d1 < 0) || (i2_p_q2_a0_d0 <= i2_m_q2_a0_d0) || (i2_p_q2_a0_d0 <= iq_corr_a0_d0) || (i2_p_q2_a0_d1 <= i2_m_q2_a0_d1) || (i2_p_q2_a0_d1 <= iq_corr_a0_d1) || (i2_p_q2_a1_d0 <= i2_m_q2_a1_d0) || (i2_p_q2_a1_d0 <= iq_corr_a1_d0) || (i2_p_q2_a1_d1 <= i2_m_q2_a1_d1) || (i2_p_q2_a1_d1 <= iq_corr_a1_d1)) { return AH_FALSE; } mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0; phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0; mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1; phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1; mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0; phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0; mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1; phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1; /* without analog phase shift */ sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT); /* without analog phase shift */ cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT); /* with analog phase shift */ sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT); /* with analog phase shift */ cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT); /* force sin^2 + cos^2 = 1; */ /* find magnitude by approximation */ mag1 = ar9300_find_mag_approx(ah, cos_2phi_1, sin_2phi_1); mag2 = ar9300_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); if ((mag1 == 0) || (mag2 == 0)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d): mag1=%d, mag2=%d\n", __func__, __LINE__, mag1, mag2); return AH_FALSE; } /* normalization sin and cos by mag */ sin_2phi_1 = (sin_2phi_1 * res_scale / mag1); cos_2phi_1 = (cos_2phi_1 * res_scale / mag1); sin_2phi_2 = (sin_2phi_2 * res_scale / mag2); cos_2phi_2 = (cos_2phi_2 * res_scale / mag2); /* calculate IQ mismatch */ if (AH_FALSE == ar9300_solve_iq_cal(ah, sin_2phi_1, cos_2phi_1, sin_2phi_2, cos_2phi_2, mag_a0_d0, phs_a0_d0, mag_a1_d0, phs_a1_d0, solved_eq)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Call to ar9300_solve_iq_cal failed.\n", __func__); return AH_FALSE; } mag_tx = solved_eq[0]; phs_tx = solved_eq[1]; mag_rx = solved_eq[2]; phs_rx = solved_eq[3]; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: chain %d: mag mismatch=%d phase mismatch=%d\n", __func__, chain_idx, mag_tx / res_scale, phs_tx / res_scale); if (res_scale == mag_tx) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d): mag_tx=%d, res_scale=%d\n", __func__, __LINE__, mag_tx, res_scale); return AH_FALSE; } /* calculate and quantize Tx IQ correction factor */ mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx); phs_corr_tx = -phs_tx; q_q_coff = (mag_corr_tx * 128 / res_scale); q_i_coff = (phs_corr_tx * 256 / res_scale); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: tx chain %d: mag corr=%d phase corr=%d\n", __func__, chain_idx, q_q_coff, q_i_coff); if (q_i_coff < -63) { q_i_coff = -63; } if (q_i_coff > 63) { q_i_coff = 63; } if (q_q_coff < -63) { q_q_coff = -63; } if (q_q_coff > 63) { q_q_coff = 63; } iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: tx chain %d: iq corr coeff=%x\n", __func__, chain_idx, iqc_coeff[0]); if (-mag_rx == res_scale) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d): mag_rx=%d, res_scale=%d\n", __func__, __LINE__, mag_rx, res_scale); return AH_FALSE; } /* calculate and quantize Rx IQ correction factors */ mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx); phs_corr_rx = -phs_rx; q_q_coff = (mag_corr_rx * 128 / res_scale); q_i_coff = (phs_corr_rx * 256 / res_scale); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: rx chain %d: mag corr=%d phase corr=%d\n", __func__, chain_idx, q_q_coff, q_i_coff); if (q_i_coff < -63) { q_i_coff = -63; } if (q_i_coff > 63) { q_i_coff = 63; } if (q_q_coff < -63) { q_q_coff = -63; } if (q_q_coff > 63) { q_q_coff = 63; } iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: rx chain %d: iq corr coeff=%x\n", __func__, chain_idx, iqc_coeff[1]); return AH_TRUE; } #define MAX_MAG_DELTA 11 //maximum magnitude mismatch delta across gains #define MAX_PHS_DELTA 10 //maximum phase mismatch delta across gains #define ABS(x) ((x) >= 0 ? (x) : (-(x))) u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = { { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, }; static void ar9300_tx_iq_cal_outlier_detection(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, u_int32_t num_chains, struct coeff_t *coeff, HAL_BOOL is_cal_reusable) { int nmeasurement, ch_idx, im; int32_t magnitude, phase; int32_t magnitude_max, phase_max; int32_t magnitude_min, phase_min; int32_t magnitude_max_idx, phase_max_idx; int32_t magnitude_min_idx, phase_min_idx; int32_t magnitude_avg, phase_avg; int32_t outlier_mag_idx = 0; int32_t outlier_phs_idx = 0; if (AR_SREV_POSEIDON(ah)) { HALASSERT(num_chains == 0x1); tx_corr_coeff[0][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON; tx_corr_coeff[1][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON; tx_corr_coeff[2][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON; tx_corr_coeff[3][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON; tx_corr_coeff[4][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON; tx_corr_coeff[5][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON; tx_corr_coeff[6][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON; tx_corr_coeff[7][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON; } for (ch_idx = 0; ch_idx < num_chains; ch_idx++) { nmeasurement = OS_REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0(ah), AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) { nmeasurement = MAX_MEASUREMENT; } if (!AR_SREV_SCORPION(ah)) { /* * reset max/min variable to min/max values so that * we always start with 1st calibrated gain value */ magnitude_max = -64; phase_max = -64; magnitude_min = 63; phase_min = 63; magnitude_avg = 0; phase_avg = 0; magnitude_max_idx = 0; magnitude_min_idx = 0; phase_max_idx = 0; phase_min_idx = 0; /* detect outlier only if nmeasurement > 1 */ if (nmeasurement > 1) { /* printf("----------- start outlier detection -----------\n"); */ /* * find max/min and phase/mag mismatch across all calibrated gains */ for (im = 0; im < nmeasurement; im++) { magnitude = coeff->mag_coeff[ch_idx][im][0]; phase = coeff->phs_coeff[ch_idx][im][0]; magnitude_avg = magnitude_avg + magnitude; phase_avg = phase_avg + phase; if (magnitude > magnitude_max) { magnitude_max = magnitude; magnitude_max_idx = im; } if (magnitude < magnitude_min) { magnitude_min = magnitude; magnitude_min_idx = im; } if (phase > phase_max) { phase_max = phase; phase_max_idx = im; } if (phase < phase_min) { phase_min = phase; phase_min_idx = im; } } /* find average (exclude max abs value) */ for (im = 0; im < nmeasurement; im++) { magnitude = coeff->mag_coeff[ch_idx][im][0]; phase = coeff->phs_coeff[ch_idx][im][0]; if ((ABS(magnitude) < ABS(magnitude_max)) || (ABS(magnitude) < ABS(magnitude_min))) { magnitude_avg = magnitude_avg + magnitude; } if ((ABS(phase) < ABS(phase_max)) || (ABS(phase) < ABS(phase_min))) { phase_avg = phase_avg + phase; } } magnitude_avg = magnitude_avg / (nmeasurement - 1); phase_avg = phase_avg / (nmeasurement - 1); /* detect magnitude outlier */ if (ABS(magnitude_max - magnitude_min) > MAX_MAG_DELTA) { if (ABS(magnitude_max - magnitude_avg) > ABS(magnitude_min - magnitude_avg)) { /* max is outlier, force to avg */ outlier_mag_idx = magnitude_max_idx; } else { /* min is outlier, force to avg */ outlier_mag_idx = magnitude_min_idx; } coeff->mag_coeff[ch_idx][outlier_mag_idx][0] = magnitude_avg; coeff->phs_coeff[ch_idx][outlier_mag_idx][0] = phase_avg; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "[ch%d][outlier mag gain%d]:: " "mag_avg = %d (/128), phase_avg = %d (/256)\n", ch_idx, outlier_mag_idx, magnitude_avg, phase_avg); } /* detect phase outlier */ if (ABS(phase_max - phase_min) > MAX_PHS_DELTA) { if (ABS(phase_max-phase_avg) > ABS(phase_min - phase_avg)) { /* max is outlier, force to avg */ outlier_phs_idx = phase_max_idx; } else{ /* min is outlier, force to avg */ outlier_phs_idx = phase_min_idx; } coeff->mag_coeff[ch_idx][outlier_phs_idx][0] = magnitude_avg; coeff->phs_coeff[ch_idx][outlier_phs_idx][0] = phase_avg; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "[ch%d][outlier phs gain%d]:: " "mag_avg = %d (/128), phase_avg = %d (/256)\n", ch_idx, outlier_phs_idx, magnitude_avg, phase_avg); } } } /*printf("------------ after outlier detection -------------\n");*/ for (im = 0; im < nmeasurement; im++) { magnitude = coeff->mag_coeff[ch_idx][im][0]; phase = coeff->phs_coeff[ch_idx][im][0]; #if 0 printf("[ch%d][gain%d]:: mag = %d (/128), phase = %d (/256)\n", ch_idx, im, magnitude, phase); #endif coeff->iqc_coeff[0] = (phase & 0x7f) | ((magnitude & 0x7f) << 7); if ((im % 2) == 0) { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, coeff->iqc_coeff[0]); } else { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, coeff->iqc_coeff[0]); } #if ATH_SUPPORT_CAL_REUSE ichan->tx_corr_coeff[im][ch_idx] = coeff->iqc_coeff[0]; #endif } #if ATH_SUPPORT_CAL_REUSE ichan->num_measures[ch_idx] = nmeasurement; #endif } OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); #if ATH_SUPPORT_CAL_REUSE if (is_cal_reusable) { ichan->one_time_txiqcal_done = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_FCS_RTT, "(FCS) TXIQCAL saved - %d\n", ichan->channel); } #endif } #if ATH_SUPPORT_CAL_REUSE static void ar9300_tx_iq_cal_apply(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) { struct ath_hal_9300 *ahp = AH9300(ah); int nmeasurement, ch_idx, im; u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = { { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, }; if (AR_SREV_POSEIDON(ah)) { HALASSERT(ahp->ah_tx_cal_chainmask == 0x1); tx_corr_coeff[0][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON; tx_corr_coeff[1][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON; tx_corr_coeff[2][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON; tx_corr_coeff[3][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON; tx_corr_coeff[4][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON; tx_corr_coeff[5][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON; tx_corr_coeff[6][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON; tx_corr_coeff[7][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON; } for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) { if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) { continue; } nmeasurement = ichan->num_measures[ch_idx]; for (im = 0; im < nmeasurement; im++) { if ((im % 2) == 0) { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, ichan->tx_corr_coeff[im][ch_idx]); } else { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, ichan->tx_corr_coeff[im][ch_idx]); } } } OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); } #endif /* * ar9300_tx_iq_cal_hw_run is only needed for osprey/wasp/hornet * It is not needed for jupiter/poseidon. */ HAL_BOOL ar9300_tx_iq_cal_hw_run(struct ath_hal *ah) { int is_tx_gain_forced; is_tx_gain_forced = OS_REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE); if (is_tx_gain_forced) { /*printf("Tx gain can not be forced during tx I/Q cal!\n");*/ OS_REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0); } /* enable tx IQ cal */ OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START(ah), AR_PHY_TX_IQCAL_START_DO_CAL, AR_PHY_TX_IQCAL_START_DO_CAL); if (!ath_hal_wait(ah, AR_PHY_TX_IQCAL_START(ah), AR_PHY_TX_IQCAL_START_DO_CAL, 0)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Tx IQ Cal is never completed.\n", __func__); return AH_FALSE; } return AH_TRUE; } static void ar9300_tx_iq_cal_post_proc(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan, int iqcal_idx, int max_iqcal,HAL_BOOL is_cal_reusable, HAL_BOOL apply_last_corr) { int nmeasurement=0, im, ix, iy, temp; struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0(ah), AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; const u_int32_t chan_info_tab[] = { AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, }; int32_t iq_res[6]; int32_t ch_idx, j; u_int32_t num_chains = 0; static struct coeff_t coeff; txiqcal_status[0] = AR_PHY_TX_IQCAL_STATUS_B0(ah); for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) { if (ahp->ah_tx_chainmask & (1 << ch_idx)) { num_chains++; } } if (apply_last_corr) { if (coeff.last_cal == AH_TRUE) { int32_t magnitude, phase; int ch_idx, im; u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = { { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, AR_PHY_TX_IQCAL_CORR_COEFF_01_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_23_B0, AR_PHY_TX_IQCAL_CORR_COEFF_23_B1, AR_PHY_TX_IQCAL_CORR_COEFF_23_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_45_B0, AR_PHY_TX_IQCAL_CORR_COEFF_45_B1, AR_PHY_TX_IQCAL_CORR_COEFF_45_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, { AR_PHY_TX_IQCAL_CORR_COEFF_67_B0, AR_PHY_TX_IQCAL_CORR_COEFF_67_B1, AR_PHY_TX_IQCAL_CORR_COEFF_67_B2}, }; for (ch_idx = 0; ch_idx < num_chains; ch_idx++) { for (im = 0; im < coeff.last_nmeasurement; im++) { magnitude = coeff.mag_coeff[ch_idx][im][0]; phase = coeff.phs_coeff[ch_idx][im][0]; #if 0 printf("[ch%d][gain%d]:: mag = %d (/128), phase = %d (/256)\n", ch_idx, im, magnitude, phase); #endif coeff.iqc_coeff[0] = (phase & 0x7f) | ((magnitude & 0x7f) << 7); if ((im % 2) == 0) { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, coeff.iqc_coeff[0]); } else { OS_REG_RMW_FIELD(ah, tx_corr_coeff[im][ch_idx], AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, coeff.iqc_coeff[0]); } } } OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); } return; } for (ch_idx = 0; ch_idx < num_chains; ch_idx++) { nmeasurement = OS_REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0(ah), AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) { nmeasurement = MAX_MEASUREMENT; } for (im = 0; im < nmeasurement; im++) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Doing Tx IQ Cal for chain %d.\n", __func__, ch_idx); if (OS_REG_READ(ah, txiqcal_status[ch_idx]) & AR_PHY_TX_IQCAL_STATUS_FAILED) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Tx IQ Cal failed for chain %d.\n", __func__, ch_idx); goto TX_IQ_CAL_FAILED_; } for (j = 0; j < 3; j++) { u_int32_t idx = 2 * j; /* 3 registers for each calibration result */ u_int32_t offset = 4 * (3 * im + j); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 0); /* 32 bits */ iq_res[idx] = OS_REG_READ(ah, chan_info_tab[ch_idx] + offset); OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 1); /* 16 bits */ iq_res[idx + 1] = 0xffff & OS_REG_READ(ah, chan_info_tab[ch_idx] + offset); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", __func__, idx, iq_res[idx], idx + 1, iq_res[idx + 1]); } if (AH_FALSE == ar9300_calc_iq_corr( ah, ch_idx, iq_res, coeff.iqc_coeff)) { HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Failed in calculation of IQ correction.\n", __func__); goto TX_IQ_CAL_FAILED_; } coeff.phs_coeff[ch_idx][im][iqcal_idx-1] = coeff.iqc_coeff[0] & 0x7f; coeff.mag_coeff[ch_idx][im][iqcal_idx-1] = (coeff.iqc_coeff[0] >> 7) & 0x7f; if (coeff.mag_coeff[ch_idx][im][iqcal_idx-1] > 63) { coeff.mag_coeff[ch_idx][im][iqcal_idx-1] -= 128; } if (coeff.phs_coeff[ch_idx][im][iqcal_idx-1] > 63) { coeff.phs_coeff[ch_idx][im][iqcal_idx-1] -= 128; } #if 0 ath_hal_printf(ah, "IQCAL::[ch%d][gain%d]:: mag = %d phase = %d \n", ch_idx, im, coeff.mag_coeff[ch_idx][im][iqcal_idx-1], coeff.phs_coeff[ch_idx][im][iqcal_idx-1]); #endif } } //last iteration; calculate mag and phs if (iqcal_idx == max_iqcal) { if (max_iqcal>1) { for (ch_idx = 0; ch_idx < num_chains; ch_idx++) { for (im = 0; im < nmeasurement; im++) { //sort mag and phs for( ix=0;ixah_phyrestart_disabled = 1; } else { val |= AR_PHY_RESTART_ENA; AH9300(ah)->ah_phyrestart_disabled = 0; } OS_REG_WRITE(ah, AR_PHY_RESTART, val); val = OS_REG_READ(ah, AR_PHY_RESTART); } HAL_BOOL ar9300_interference_is_present(struct ath_hal *ah) { int i; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); const struct ieee80211_channel *chan = ahpriv->ah_curchan; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); if (ichan == NULL) { ath_hal_printf(ah, "%s: called with ichan=NULL\n", __func__); return AH_FALSE; } /* This function is called after a stuck beacon, if EACS is enabled. * If CW interference is severe, then HW goes into a loop of continuous * stuck beacons and resets. On reset the NF cal history is cleared. * So the median value of the history cannot be used - * hence check if any value (Chain 0/Primary Channel) * is outside the bounds. */ HAL_NFCAL_HIST_FULL *h = AH_HOME_CHAN_NFCAL_HIST(ah, ichan); for (i = 0; i < HAL_NF_CAL_HIST_LEN_FULL; i++) { if (h->nf_cal_buffer[i][0] > AH9300(ah)->nfp->nominal + AH9300(ah)->nf_cw_int_delta) { return AH_TRUE; } } return AH_FALSE; } #if ATH_SUPPORT_CRDC void ar9300_crdc_rx_notify(struct ath_hal *ah, struct ath_rx_status *rxs) { struct ath_hal_private *ahpriv = AH_PRIVATE(ah); int rssi_index; if ((!AR_SREV_WASP(ah)) || (!ahpriv->ah_config.ath_hal_crdc_enable)) { return; } if (rxs->rs_isaggr && rxs->rs_moreaggr) { return; } if ((rxs->rs_rssi_ctl0 >= HAL_RSSI_BAD) || (rxs->rs_rssi_ctl1 >= HAL_RSSI_BAD)) { return; } rssi_index = ah->ah_crdc_rssi_ptr % HAL_MAX_CRDC_RSSI_SAMPLE; ah->ah_crdc_rssi_sample[0][rssi_index] = rxs->rs_rssi_ctl0; ah->ah_crdc_rssi_sample[1][rssi_index] = rxs->rs_rssi_ctl1; ah->ah_crdc_rssi_ptr++; } static int ar9300_crdc_avg_rssi(struct ath_hal *ah, int chain) { int crdc_rssi_sum = 0; int crdc_rssi_ptr = ah->ah_crdc_rssi_ptr, i; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); int crdc_window = ahpriv->ah_config.ath_hal_crdc_window; if (crdc_window > HAL_MAX_CRDC_RSSI_SAMPLE) { crdc_window = HAL_MAX_CRDC_RSSI_SAMPLE; } for (i = 1; i <= crdc_window; i++) { crdc_rssi_sum += ah->ah_crdc_rssi_sample[chain] [(crdc_rssi_ptr - i) % HAL_MAX_CRDC_RSSI_SAMPLE]; } return crdc_rssi_sum / crdc_window; } static void ar9300_crdc_activate(struct ath_hal *ah, int rssi_diff, int enable) { int val, orig_val; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); int crdc_numerator = ahpriv->ah_config.ath_hal_crdc_numerator; int crdc_denominator = ahpriv->ah_config.ath_hal_crdc_denominator; int c = (rssi_diff * crdc_numerator) / crdc_denominator; val = orig_val = OS_REG_READ(ah, AR_PHY_MULTICHAIN_CTRL); val &= 0xffffff00; if (enable) { val |= 0x1; val |= ((c << 1) & 0xff); } OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_CTRL, val); HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "diff: %02d comp: %02d reg: %08x %08x\n", rssi_diff, c, orig_val, val); } void ar9300_chain_rssi_diff_compensation(struct ath_hal *ah) { struct ath_hal_private *ahpriv = AH_PRIVATE(ah); int crdc_window = ahpriv->ah_config.ath_hal_crdc_window; int crdc_rssi_ptr = ah->ah_crdc_rssi_ptr; int crdc_rssi_thresh = ahpriv->ah_config.ath_hal_crdc_rssithresh; int crdc_diff_thresh = ahpriv->ah_config.ath_hal_crdc_diffthresh; int avg_rssi[2], avg_rssi_diff; if ((!AR_SREV_WASP(ah)) || (!ahpriv->ah_config.ath_hal_crdc_enable)) { if (ah->ah_crdc_rssi_ptr) { ar9300_crdc_activate(ah, 0, 0); ah->ah_crdc_rssi_ptr = 0; } return; } if (crdc_window > HAL_MAX_CRDC_RSSI_SAMPLE) { crdc_window = HAL_MAX_CRDC_RSSI_SAMPLE; } if (crdc_rssi_ptr < crdc_window) { return; } avg_rssi[0] = ar9300_crdc_avg_rssi(ah, 0); avg_rssi[1] = ar9300_crdc_avg_rssi(ah, 1); avg_rssi_diff = avg_rssi[1] - avg_rssi[0]; HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "crdc: avg: %02d %02d ", avg_rssi[0], avg_rssi[1]); if ((avg_rssi[0] < crdc_rssi_thresh) && (avg_rssi[1] < crdc_rssi_thresh)) { ar9300_crdc_activate(ah, 0, 0); } else { if (ABS(avg_rssi_diff) >= crdc_diff_thresh) { ar9300_crdc_activate(ah, avg_rssi_diff, 1); } else { ar9300_crdc_activate(ah, 0, 1); } } } #endif #if ATH_ANT_DIV_COMB HAL_BOOL ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, const struct ieee80211_channel *chan) { u_int32_t value; u_int32_t regval; struct ath_hal_9300 *ahp = AH9300(ah); HAL_CHANNEL_INTERNAL *ichan; struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pcap = &ahpriv->ah_caps; if (AR_SREV_POSEIDON(ah)) { // Make sure this scheme is only used for WB225(Astra) ahp->ah_lna_div_use_bt_ant_enable = enable; ichan = ar9300_check_chan(ah, chan); if ( ichan == AH_NULL ) { HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->ic_freq, chan->ic_flags); return AH_FALSE; } if ( enable == TRUE ) { pcap->halAntDivCombSupport = TRUE; } else { pcap->halAntDivCombSupport = pcap->halAntDivCombSupportOrg; } #define AR_SWITCH_TABLE_COM2_ALL (0xffffff) #define AR_SWITCH_TABLE_COM2_ALL_S (0) value = ar9300_ant_ctrl_common2_get(ah, IS_CHAN_2GHZ(ichan)); if ( enable == TRUE ) { value &= ~AR_SWITCH_TABLE_COM2_ALL; value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable; } HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control); /* main_lnaconf, alt_lnaconf, main_tb, alt_tb */ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */ regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S; /* enable_lnadiv */ regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK); regval |= ((value >> 6) & 0x1) << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT; if ( enable == TRUE ) { regval |= ANT_DIV_ENABLE; } OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); /* enable fast_div */ regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); regval |= ((value >> 7) & 0x1) << BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT; if ( enable == TRUE ) { regval |= FAST_DIV_ENABLE; } OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); if ( AR_SREV_POSEIDON_11_OR_LATER(ah) ) { if (pcap->halAntDivCombSupport) { /* If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning */ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); /* clear bit 25~30 main_lnaconf, alt_lnaconf, main_tb, alt_tb */ regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK | MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK)); regval |= (HAL_ANT_DIV_COMB_LNA1 << MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); regval |= (HAL_ANT_DIV_COMB_LNA2 << MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); } } return AH_TRUE; } else { return AH_TRUE; } } #endif /* ATH_ANT_DIV_COMB */ Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c (revision 278741) @@ -1,909 +1,973 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "opt_ah.h" #include "ah.h" #include "ah_desc.h" #include "ah_internal.h" #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300phy.h" #include "ar9300/ar9300desc.h" #define TU_TO_USEC(_tu) ((_tu) << 10) #define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7) /* * Update Tx FIFO trigger level. * * Set b_inc_trig_level to TRUE to increase the trigger level. * Set b_inc_trig_level to FALSE to decrease the trigger level. * * Returns TRUE if the trigger level was updated */ HAL_BOOL ar9300_update_tx_trig_level(struct ath_hal *ah, HAL_BOOL b_inc_trig_level) { struct ath_hal_9300 *ahp = AH9300(ah); u_int32_t txcfg, cur_level, new_level; HAL_INT omask; if (AH9300(ah)->ah_tx_trig_level >= MAX_TX_FIFO_THRESHOLD && b_inc_trig_level) { return AH_FALSE; } /* * Disable interrupts while futzing with the fifo level. */ omask = ar9300_set_interrupts(ah, ahp->ah_mask_reg &~ HAL_INT_GLOBAL, 0); txcfg = OS_REG_READ(ah, AR_TXCFG); cur_level = MS(txcfg, AR_FTRIG); new_level = cur_level; if (b_inc_trig_level) { /* increase the trigger level */ if (cur_level < MAX_TX_FIFO_THRESHOLD) { new_level++; } } else if (cur_level > MIN_TX_FIFO_THRESHOLD) { new_level--; } if (new_level != cur_level) { /* Update the trigger level */ OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_FTRIG) | SM(new_level, AR_FTRIG)); } /* re-enable chip interrupts */ ar9300_set_interrupts(ah, omask, 0); AH9300(ah)->ah_tx_trig_level = new_level; return (new_level != cur_level); } /* * Returns the value of Tx Trigger Level */ u_int16_t ar9300_get_tx_trig_level(struct ath_hal *ah) { return (AH9300(ah)->ah_tx_trig_level); } /* * Set the properties of the tx queue with the parameters * from q_info. */ HAL_BOOL ar9300_set_tx_queue_props(struct ath_hal *ah, int q, const HAL_TXQ_INFO *q_info) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; if (q >= p_cap->halTotalQueues) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], q_info); } /* * Return the properties for the specified tx queue. */ HAL_BOOL ar9300_get_tx_queue_props(struct ath_hal *ah, int q, HAL_TXQ_INFO *q_info) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; if (q >= p_cap->halTotalQueues) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } return ath_hal_getTxQProps(ah, q_info, &ahp->ah_txq[q]); } enum { AH_TX_QUEUE_MINUS_OFFSET_BEACON = 1, AH_TX_QUEUE_MINUS_OFFSET_CAB = 2, AH_TX_QUEUE_MINUS_OFFSET_UAPSD = 3, AH_TX_QUEUE_MINUS_OFFSET_PAPRD = 4, }; /* * Allocate and initialize a tx DCU/QCU combination. */ int ar9300_setup_tx_queue(struct ath_hal *ah, HAL_TX_QUEUE type, const HAL_TXQ_INFO *q_info) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_TX_QUEUE_INFO *qi; HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; int q; /* XXX move queue assignment to driver */ switch (type) { case HAL_TX_QUEUE_BEACON: /* highest priority */ q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_BEACON; break; case HAL_TX_QUEUE_CAB: /* next highest priority */ q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_CAB; break; case HAL_TX_QUEUE_UAPSD: q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_UAPSD; break; case HAL_TX_QUEUE_PAPRD: q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD; break; case HAL_TX_QUEUE_DATA: /* * don't infringe on top 4 queues, reserved for: * beacon, CAB, UAPSD, PAPRD */ for (q = 0; q < p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD; q++) { if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) { break; } } if (q == p_cap->halTotalQueues - 3) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: no available tx queue\n", __func__); return -1; } break; default: HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: bad tx queue type %u\n", __func__, type); return -1; } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: queue %u\n", __func__, q); qi = &ahp->ah_txq[q]; if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: tx queue %u already active\n", __func__, q); return -1; } OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); qi->tqi_type = type; if (q_info == AH_NULL) { /* by default enable OK+ERR+DESC+URN interrupts */ qi->tqi_qflags = HAL_TXQ_TXOKINT_ENABLE | HAL_TXQ_TXERRINT_ENABLE | HAL_TXQ_TXDESCINT_ENABLE | HAL_TXQ_TXURNINT_ENABLE; qi->tqi_aifs = INIT_AIFS; qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ qi->tqi_cwmax = INIT_CWMAX; qi->tqi_shretry = INIT_SH_RETRY; qi->tqi_lgretry = INIT_LG_RETRY; qi->tqi_physCompBuf = 0; } else { qi->tqi_physCompBuf = q_info->tqi_compBuf; (void) ar9300_set_tx_queue_props(ah, q, q_info); } /* NB: must be followed by ar9300_reset_tx_queue */ return q; } /* * Update the h/w interrupt registers to reflect a tx q's configuration. */ static void set_tx_q_interrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) { struct ath_hal_9300 *ahp = AH9300(ah); HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: tx ok 0x%x err 0x%x eol 0x%x urn 0x%x\n", __func__, ahp->ah_tx_ok_interrupt_mask, ahp->ah_tx_err_interrupt_mask, ahp->ah_tx_eol_interrupt_mask, ahp->ah_tx_urn_interrupt_mask); OS_REG_WRITE(ah, AR_IMR_S0, SM(ahp->ah_tx_ok_interrupt_mask, AR_IMR_S0_QCU_TXOK)); OS_REG_WRITE(ah, AR_IMR_S1, SM(ahp->ah_tx_err_interrupt_mask, AR_IMR_S1_QCU_TXERR) | SM(ahp->ah_tx_eol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); OS_REG_RMW_FIELD(ah, AR_IMR_S2, AR_IMR_S2_QCU_TXURN, ahp->ah_tx_urn_interrupt_mask); ahp->ah_mask2Reg = OS_REG_READ(ah, AR_IMR_S2); } /* * Free a tx DCU/QCU combination. */ HAL_BOOL ar9300_release_tx_queue(struct ath_hal *ah, u_int q) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; HAL_TX_QUEUE_INFO *qi; if (q >= p_cap->halTotalQueues) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } qi = &ahp->ah_txq[q]; if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q); return AH_FALSE; } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: release queue %u\n", __func__, q); qi->tqi_type = HAL_TX_QUEUE_INACTIVE; ahp->ah_tx_ok_interrupt_mask &= ~(1 << q); ahp->ah_tx_err_interrupt_mask &= ~(1 << q); ahp->ah_tx_eol_interrupt_mask &= ~(1 << q); ahp->ah_tx_urn_interrupt_mask &= ~(1 << q); set_tx_q_interrupts(ah, qi); return AH_TRUE; } /* * Set the retry, aifs, cwmin/max, ready_time regs for specified queue * Assumes: * phw_channel has been set to point to the current channel */ HAL_BOOL ar9300_reset_tx_queue(struct ath_hal *ah, u_int q) { struct ath_hal_9300 *ahp = AH9300(ah); // struct ath_hal_private *ap = AH_PRIVATE(ah); HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; HAL_TX_QUEUE_INFO *qi; u_int32_t cw_min, chan_cw_min, value; if (q >= p_cap->halTotalQueues) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); return AH_FALSE; } qi = &ahp->ah_txq[q]; if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q); return AH_TRUE; /* XXX??? */ } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: reset queue %u\n", __func__, q); if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { /* * Select cwmin according to channel type. * NB: chan can be NULL during attach */ if (chan && IEEE80211_IS_CHAN_B(chan)) { chan_cw_min = INIT_CWMIN_11B; } else { chan_cw_min = INIT_CWMIN; } /* make sure that the CWmin is of the form (2^n - 1) */ for (cw_min = 1; cw_min < chan_cw_min; cw_min = (cw_min << 1) | 1) {} } else { cw_min = qi->tqi_cwmin; } /* set cw_min/Max and AIFS values */ if (q > 3 || (!AH9300(ah)->ah_fccaifs)) /* values should not be overwritten if domain is FCC and manual rate less than 24Mb is set, this check is making sure this */ { OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(cw_min, AR_D_LCL_IFS_CWMIN) | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); } /* Set retry limit values */ OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); /* enable early termination on the QCU */ OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); /* enable DCU to wait for next fragment from QCU */ if (AR_SREV_WASP(ah) && (AH_PRIVATE((ah))->ah_macRev <= AR_SREV_REVISION_WASP_12)) { /* WAR for EV#85395: Wasp Rx overrun issue - reduces Tx queue backoff * threshold to 1 to avoid Rx overruns - Fixed in Wasp 1.3 */ OS_REG_WRITE(ah, AR_DMISC(q), AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1); } else { OS_REG_WRITE(ah, AR_DMISC(q), AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); } /* multiqueue support */ if (qi->tqi_cbrPeriod) { OS_REG_WRITE(ah, AR_QCBRCFG(q), SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); OS_REG_WRITE(ah, AR_QMISC(q), OS_REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi->tqi_cbrOverflowLimit ? AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); } if (qi->tqi_readyTime && (qi->tqi_type != HAL_TX_QUEUE_CAB)) { OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | AR_Q_RDYTIMECFG_EN); } OS_REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); if (qi->tqi_burstTime && (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) { OS_REG_WRITE(ah, AR_QMISC(q), OS_REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_RDYTIME_EXP_POLICY); } if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) { OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | AR_D_MISC_POST_FR_BKOFF_DIS); } if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) { OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | AR_D_MISC_FRAG_BKOFF_EN); } switch (qi->tqi_type) { case HAL_TX_QUEUE_BEACON: /* beacon frames */ OS_REG_WRITE(ah, AR_QMISC(q), OS_REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_BEACON_USE | AR_Q_MISC_CBR_INCR_DIS1); OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS); /* XXX cwmin and cwmax should be 0 for beacon queue */ if (AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS) { OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) | SM(0, AR_D_LCL_IFS_CWMAX) | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); } break; case HAL_TX_QUEUE_CAB: /* CAB frames */ /* * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, * bug #6079. There is an issue with the CAB Queue * not properly refreshing the Tx descriptor if * the TXE clear setting is used. */ OS_REG_WRITE(ah, AR_QMISC(q), OS_REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1 | AR_Q_MISC_CBR_INCR_DIS0); value = TU_TO_USEC(qi->tqi_readyTime) - (ah->ah_config.ah_sw_beacon_response_time - ah->ah_config.ah_dma_beacon_response_time) - ah->ah_config.ah_additional_swba_backoff; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); break; case HAL_TX_QUEUE_PSPOLL: /* * We may configure ps_poll QCU to be TIM-gated in the * future; TIM_GATED bit is not enabled currently because * of a hardware problem in Oahu that overshoots the TIM * bitmap in beacon and may find matching associd bit in * non-TIM elements and send PS-poll PS poll processing * will be done in software */ OS_REG_WRITE(ah, AR_QMISC(q), OS_REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); break; case HAL_TX_QUEUE_UAPSD: OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | AR_D_MISC_POST_FR_BKOFF_DIS); break; default: /* NB: silence compiler */ break; } #ifndef AH_DISABLE_WME /* * Yes, this is a hack and not the right way to do it, but * it does get the lockout bits and backoff set for the * high-pri WME queues for testing. We need to either extend * the meaning of queue_info->mode, or create something like * queue_info->dcumode. */ if (qi->tqi_intFlags & HAL_TXQ_USE_LOCKOUT_BKOFF_DIS) { OS_REG_WRITE(ah, AR_DMISC(q), OS_REG_READ(ah, AR_DMISC(q)) | SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, AR_D_MISC_ARB_LOCKOUT_CNTRL) | AR_D_MISC_POST_FR_BKOFF_DIS); } #endif OS_REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN); /* * Always update the secondary interrupt mask registers - this * could be a new queue getting enabled in a running system or * hw getting re-initialized during a reset! * * Since we don't differentiate between tx interrupts corresponding * to individual queues - secondary tx mask regs are always unmasked; * tx interrupts are enabled/disabled for all queues collectively * using the primary mask reg */ if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) { ahp->ah_tx_ok_interrupt_mask |= (1 << q); } else { ahp->ah_tx_ok_interrupt_mask &= ~(1 << q); } if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) { ahp->ah_tx_err_interrupt_mask |= (1 << q); } else { ahp->ah_tx_err_interrupt_mask &= ~(1 << q); } if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) { ahp->ah_tx_eol_interrupt_mask |= (1 << q); } else { ahp->ah_tx_eol_interrupt_mask &= ~(1 << q); } if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) { ahp->ah_tx_urn_interrupt_mask |= (1 << q); } else { ahp->ah_tx_urn_interrupt_mask &= ~(1 << q); } set_tx_q_interrupts(ah, qi); return AH_TRUE; } /* * Get the TXDP for the specified queue */ u_int32_t ar9300_get_tx_dp(struct ath_hal *ah, u_int q) { HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); return OS_REG_READ(ah, AR_QTXDP(q)); } /* * Set the tx_dp for the specified queue */ HAL_BOOL ar9300_set_tx_dp(struct ath_hal *ah, u_int q, u_int32_t txdp) { HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); HALASSERT(txdp != 0); OS_REG_WRITE(ah, AR_QTXDP(q), txdp); return AH_TRUE; } /* * Transmit Enable is read-only now */ HAL_BOOL ar9300_start_tx_dma(struct ath_hal *ah, u_int q) { return AH_TRUE; } /* * Return the number of pending frames or 0 if the specified * queue is stopped. */ u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q) { u_int32_t npend; HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; if (npend == 0) { /* * Pending frame count (PFC) can momentarily go to zero * while TXE remains asserted. In other words a PFC of * zero is not sufficient to say that the queue has stopped. */ if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) { npend = 1; /* arbitrarily return 1 */ } } #ifdef DEBUG if (npend && (AH9300(ah)->ah_txq[q].tqi_type == HAL_TX_QUEUE_CAB)) { if (OS_REG_READ(ah, AR_Q_RDYTIMESHDN) & (1 << q)) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "RTSD on CAB queue\n"); /* Clear the ready_time shutdown status bits */ OS_REG_WRITE(ah, AR_Q_RDYTIMESHDN, 1 << q); } } #endif HALASSERT((npend == 0) || (AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE)); return npend; } /* * Stop transmit on the specified queue */ HAL_BOOL ar9300_stop_tx_dma(struct ath_hal *ah, u_int q, u_int timeout) { + struct ath_hal_9300 *ahp = AH9300(ah); + /* + * If we call abort txdma instead, no need to stop RX. + * Otherwise, the RX logic might not be restarted properly. + */ + ahp->ah_abort_txdma_norx = AH_FALSE; + + /* * Directly call abort. It is better, hardware-wise, to stop all * queues at once than individual ones. */ return ar9300_abort_tx_dma(ah); #if 0 #define AH_TX_STOP_DMA_TIMEOUT 4000 /* usec */ #define AH_TIME_QUANTUM 100 /* usec */ u_int wait; HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues); HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); if (timeout == 0) { timeout = AH_TX_STOP_DMA_TIMEOUT; } OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { if (ar9300_num_tx_pending(ah, q) == 0) { break; } OS_DELAY(AH_TIME_QUANTUM); /* XXX get actual value */ } #ifdef AH_DEBUG if (wait == 0) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", __func__, OS_REG_READ(ah, AR_QMISC(q)), OS_REG_READ(ah, AR_QRDYTIMECFG(q)), OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); } #endif /* AH_DEBUG */ /* 2413+ and up can kill packets at the PCU level */ if (ar9300_num_tx_pending(ah, q)) { u_int32_t tsf_low, j; HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n", __func__, ar9300_num_tx_pending(ah, q), q); /* Kill last PCU Tx Frame */ /* TODO - save off and restore current values of Q1/Q2? */ for (j = 0; j < 2; j++) { tsf_low = OS_REG_READ(ah, AR_TSF_L32); OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR)); OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10); OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) { break; } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: TSF have moved while trying to set " "quiet time TSF: 0x%08x\n", __func__, tsf_low); /* TSF shouldn't count twice or reg access is taking forever */ HALASSERT(j < 1); } OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); /* Allow the quiet mechanism to do its work */ OS_DELAY(200); OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); /* Verify all transmit is dead */ wait = timeout / AH_TIME_QUANTUM; while (ar9300_num_tx_pending(ah, q)) { if ((--wait) == 0) { HALDEBUG(ah, HAL_DEBUG_TX, "%s: Failed to stop Tx DMA in %d msec " "after killing last frame\n", __func__, timeout / 1000); break; } OS_DELAY(AH_TIME_QUANTUM); } OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); } OS_REG_WRITE(ah, AR_Q_TXD, 0); return (wait != 0); #undef AH_TX_STOP_DMA_TIMEOUT #undef AH_TIME_QUANTUM #endif } /* * Really Stop transmit on the specified queue */ HAL_BOOL ar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout) { #define AH_TX_STOP_DMA_TIMEOUT 4000 /* usec */ #define AH_TIME_QUANTUM 100 /* usec */ u_int wait; HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues); HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); if (timeout == 0) { timeout = AH_TX_STOP_DMA_TIMEOUT; } OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { if (ar9300_num_tx_pending(ah, q) == 0) { break; } OS_DELAY(AH_TIME_QUANTUM); /* XXX get actual value */ } #ifdef AH_DEBUG if (wait == 0) { HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__, OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE), OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q))); HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", __func__, OS_REG_READ(ah, AR_QMISC(q)), OS_REG_READ(ah, AR_QRDYTIMECFG(q)), OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); } #endif /* AH_DEBUG */ /* 2413+ and up can kill packets at the PCU level */ if (ar9300_num_tx_pending(ah, q)) { u_int32_t tsf_low, j; HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n", __func__, ar9300_num_tx_pending(ah, q), q); /* Kill last PCU Tx Frame */ /* TODO - save off and restore current values of Q1/Q2? */ for (j = 0; j < 2; j++) { tsf_low = OS_REG_READ(ah, AR_TSF_L32); OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR)); OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10); OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) { break; } HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: TSF have moved while trying to set " "quiet time TSF: 0x%08x\n", __func__, tsf_low); /* TSF shouldn't count twice or reg access is taking forever */ HALASSERT(j < 1); } OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); /* Allow the quiet mechanism to do its work */ OS_DELAY(200); OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); /* Verify all transmit is dead */ wait = timeout / AH_TIME_QUANTUM; while (ar9300_num_tx_pending(ah, q)) { if ((--wait) == 0) { HALDEBUG(ah, HAL_DEBUG_TX, "%s: Failed to stop Tx DMA in %d msec " "after killing last frame\n", __func__, timeout / 1000); break; } OS_DELAY(AH_TIME_QUANTUM); } OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); } OS_REG_WRITE(ah, AR_Q_TXD, 0); return (wait != 0); #undef AH_TX_STOP_DMA_TIMEOUT #undef AH_TIME_QUANTUM } /* * Abort transmit on all queues */ #define AR9300_ABORT_LOOPS 1000 #define AR9300_ABORT_WAIT 5 +#define NEXT_TBTT_NOW 10 HAL_BOOL ar9300_abort_tx_dma(struct ath_hal *ah) { + struct ath_hal_9300 *ahp = AH9300(ah); int i, q; + u_int32_t nexttbtt, nextdba, tsf_tbtt, tbtt, dba; + HAL_BOOL stopped; + HAL_BOOL status = AH_TRUE; + if (ahp->ah_abort_txdma_norx) { + /* + * First of all, make sure RX has been stopped + */ + if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) { + /* Need to stop RX DMA before reset otherwise chip might hang */ + stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */ + ar9300_set_rx_filter(ah, 0); + stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */ + if (!stopped) { + /* + * During the transition from full sleep to reset, + * recv DMA regs are not available to be read + */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__); + //We still continue to stop TX dma + //return AH_FALSE; + } + } else { + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__); + } + } + /* * set txd on all queues */ OS_REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M); /* * set tx abort bits (also disable rx) */ OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); - OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR)); + /* Add a new receipe from K31 code */ + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | + AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + /* beacon Q flush */ + nexttbtt = OS_REG_READ(ah, AR_NEXT_TBTT_TIMER); + nextdba = OS_REG_READ(ah, AR_NEXT_DMA_BEACON_ALERT); + //printk("%s[%d]:dba: %d, nt: %d \n", __func__, __LINE__, nextdba, nexttbtt); + tsf_tbtt = OS_REG_READ(ah, AR_TSF_L32); + tbtt = tsf_tbtt + NEXT_TBTT_NOW; + dba = tsf_tbtt; + OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, dba); + OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, tbtt); OS_REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); - /* Let TXE (all queues) clear before waiting on any pending frames */ - for (i = 0; i < AR9300_ABORT_LOOPS; i++) { - if (OS_REG_READ(ah, AR_Q_TXE) == 0) { + /* + * Let TXE (all queues) clear before waiting for any pending frames + * This is needed before starting the RF_BUS GRANT sequence other wise causes kernel + * panic + */ + for(i = 0; i < AR9300_ABORT_LOOPS; i++) { + if(OS_REG_READ(ah, AR_Q_TXE) == 0) { break; } OS_DELAY(AR9300_ABORT_WAIT); } if (i == AR9300_ABORT_LOOPS) { HALDEBUG(ah, HAL_DEBUG_TX, "%s[%d] reached max wait on TXE\n", __func__, __LINE__); } /* * wait on all tx queues + * This need to be checked in the last to gain extra 50 usec. on avg. + * Currently checked first since we dont have a previous channel information currently. + * Which is needed to revert the rf changes. */ - for (q = 0; q < AR_NUM_QCU; q++) { + for (q = AR_NUM_QCU - 1; q >= 0; q--) { for (i = 0; i < AR9300_ABORT_LOOPS; i++) { - if (!ar9300_num_tx_pending(ah, q)) { + if (!(ar9300_num_tx_pending(ah, q))) { break; } OS_DELAY(AR9300_ABORT_WAIT); } if (i == AR9300_ABORT_LOOPS) { - HALDEBUG(ah, HAL_DEBUG_TX, - "%s[%d] reached max wait on pending tx, q %d\n", - __func__, __LINE__, q); - return AH_FALSE; + status = AH_FALSE; + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "ABORT LOOP finsihsed for Q: %d, num_pending: %d \n", + q, ar9300_num_tx_pending(ah, q)); + goto exit; } } + /* Updating the beacon alert register with correct value */ + OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, nextdba); + OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, nexttbtt); + +exit: /* * clear tx abort bits */ OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); - OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR)); + /* Added a new receipe from K31 code */ + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | + AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); OS_REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); /* * clear txd */ OS_REG_WRITE(ah, AR_Q_TXD, 0); - return AH_TRUE; + ahp->ah_abort_txdma_norx = AH_TRUE; + + return status; } /* * Determine which tx queues need interrupt servicing. */ void ar9300_get_tx_intr_queue(struct ath_hal *ah, u_int32_t *txqs) { HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "ar9300_get_tx_intr_queue: Should not be called\n"); #if 0 struct ath_hal_9300 *ahp = AH9300(ah); *txqs &= ahp->ah_intr_txqs; ahp->ah_intr_txqs &= ~(*txqs); #endif } void ar9300_reset_tx_status_ring(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ts_tail = 0; /* Zero out the status descriptors */ OS_MEMZERO((void *)ahp->ts_ring, ahp->ts_size * sizeof(struct ar9300_txs)); HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: TS Start 0x%x End 0x%x Virt %p, Size %d\n", __func__, ahp->ts_paddr_start, ahp->ts_paddr_end, ahp->ts_ring, ahp->ts_size); OS_REG_WRITE(ah, AR_Q_STATUS_RING_START, ahp->ts_paddr_start); OS_REG_WRITE(ah, AR_Q_STATUS_RING_END, ahp->ts_paddr_end); } void ar9300_setup_tx_status_ring(struct ath_hal *ah, void *ts_start, u_int32_t ts_paddr_start, u_int16_t size) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ts_paddr_start = ts_paddr_start; ahp->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9300_txs)); ahp->ts_size = size; ahp->ts_ring = (struct ar9300_txs *)ts_start; ar9300_reset_tx_status_ring(ah); } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini (revision 278741) @@ -1,4330 +1,4334 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ static const u_int32_t ar9340_wasp_1p0_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00009e44 , 0x005c0000 , 0x005c0000 , 0x005c0000 , 0x005c0000 }, { 0x0000a258 , 0x02020200 , 0x02020200 , 0x02020200 , 0x02020200 }, { 0x0000a25c , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a28c , 0x00011111 , 0x00011111 , 0x00011111 , 0x00011111 }, { 0x0000a2c4 , 0x00148d18 , 0x00148d18 , 0x00148d20 , 0x00148d20 }, { 0x0000a2d8 , 0xf999a800 , 0xf999a800 , 0xf999a80c , 0xf999a80c }, { 0x0000a50c , 0x0000c00a , 0x0000c00a , 0x0000c00a , 0x0000c00a }, { 0x0000a538 , 0x00038e8c , 0x00038e8c , 0x00038e8c , 0x00038e8c }, { 0x0000a53c , 0x0003cecc , 0x0003cecc , 0x0003cecc , 0x0003cecc }, { 0x0000a540 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 }, { 0x0000a544 , 0x00044edc , 0x00044edc , 0x00044edc , 0x00044edc }, { 0x0000a548 , 0x00048ede , 0x00048ede , 0x00048ede , 0x00048ede }, { 0x0000a54c , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e }, { 0x0000a550 , 0x00050f5e , 0x00050f5e , 0x00050f5e , 0x00050f5e }, { 0x0000a554 , 0x00054f9e , 0x00054f9e , 0x00054f9e , 0x00054f9e }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, }; static const u_int32_t ar9340_wasp_1p0_mac_core_emulation[][2] = { /* Addr allmodes */ { 0x00000030 , 0x00020085 }, { 0x00000044 , 0x00000008 }, { 0x0000805c , 0xffffc7ff }, { 0x00008344 , 0xaa4a105b }, }; static const u_int32_t ar9340_wasp_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x000160ac , 0xa4646800 , 0xa4646800 , 0xa4646800 , 0xa4646800 }, { 0x0001610c , 0x08000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00016140 , 0x10804000 , 0x10804000 , 0x50804000 , 0x50804000 }, { 0x0001650c , 0x08000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00016540 , 0x10804000 , 0x10804000 , 0x50804000 , 0x50804000 }, }; static const u_int32_t ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21020220 , 0x21020220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27020223 , 0x27020223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5c04286b , 0x5c04286b , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x61042a6c , 0x61042a6c , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x66062a6c , 0x66062a6c , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x6b062e6c , 0x6b062e6c , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x7006308c , 0x7006308c , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x730a308a , 0x730a308a , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21820220 , 0x21820220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27820223 , 0x27820223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5c84286b , 0x5c84286b , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x61842a6c , 0x61842a6c , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x66862a6c , 0x66862a6c , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x6b862e6c , 0x6b862e6c , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x7086308c , 0x7086308c , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x738a308a , 0x738a308a , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x00016044 , 0x056db2db , 0x056db2db , 0x056db2db , 0x056db2db }, { 0x00016048 , 0x24925266 , 0x24925266 , 0x24925266 , 0x24925266 }, { 0x00016444 , 0x056db2db , 0x056db2db , 0x056db2db , 0x056db2db }, { 0x00016448 , 0x24925266 , 0x24925266 , 0x24925266 , 0x24925266 }, }; static const u_int32_t ar9340_wasp_1p0_baseband_core_emulation[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafa68e30 }, { 0x00009884 , 0x00002842 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009e3c , 0xcf946221 }, { 0x00009e50 , 0x00000000 }, { 0x00009fcc , 0x00000014 }, { 0x0000a344 , 0x00000010 }, { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x71733d01 }, { 0x0000a3a0 , 0xd0ad5c12 }, { 0x0000a3c0 , 0x22222220 }, { 0x0000a3c4 , 0x22222222 }, { 0x0000a404 , 0x00418a11 }, { 0x0000a418 , 0x050001ce }, { 0x0000a438 , 0x00001800 }, { 0x0000a458 , 0x01444452 }, { 0x0000a690 , 0x00000038 }, }; static const u_int32_t ar9340Modes_fast_clock_wasp_1p0[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00001030 , 0x00000268 , 0x000004d0 }, { 0x00001070 , 0x0000018c , 0x00000318 }, { 0x000010b0 , 0x00000fd0 , 0x00001fa0 }, { 0x00008014 , 0x044c044c , 0x08980898 }, { 0x0000801c , 0x148ec02b , 0x148ec057 }, { 0x00008318 , 0x000044c0 , 0x00008980 }, { 0x00009e00 , 0x0372131c , 0x0372131c }, { 0x0000a230 , 0x0000000b , 0x00000016 }, { 0x0000a254 , 0x00000898 , 0x00001130 }, }; static const u_int32_t ar9340_wasp_1p0_radio_core[][2] = { /* Addr allmodes */ { 0x00016000 , 0x36db6db6 }, //rxrf_bias1 { 0x00016004 , 0x6db6db40 }, //rxrf_bias2 { 0x00016008 , 0x73f00000 }, //rxrf_gainstages { 0x0001600c , 0x00000000 }, //rxrf_agc { 0x00016040 , 0x7f80fff8 }, //txrf1 { 0x00016044 , 0x03b6d2db }, //txrf2 { 0x00016048 , 0x24925266 }, //txrf3 { 0x0001604c , 0x000f0278 }, //txrf4 { 0x00016050 , 0x6db6db6c }, //txrf5 { 0x00016054 , 0x6db60000 }, //txrf6 { 0x00016080 , 0x00080000 }, //synth1 { 0x00016084 , 0x0e48048c }, //synth2 { 0x00016088 , 0x14214514 }, //synth3 { 0x0001608c , 0x119f081c }, //synth4 (beta4 -> beta6 change) ===> Revert to Beta4 setting { 0x00016090 , 0x24926490 }, //synth5 { 0x00016094 , 0x00000000 }, //synth6 { 0x00016098 , 0xd411eb84 }, //synth7 { 0x0001609c , 0x03e47f32 }, //synth8 (beta4 -> beta6 change) { 0x000160a0 , 0xc2108ffe }, //synth9 { 0x000160a4 , 0x812fc370 }, //synth10 { 0x000160a8 , 0x423c8000 }, //synth11 { 0x000160ac , 0xa4646800 }, //synth12 { 0x000160b0 , 0x00fe7f46 }, //synth13 (beta4 -> beta6 change) { 0x000160b4 , 0x92480000 }, //synth14 { 0x000160c0 , 0x006db6db }, //bias1 { 0x000160c4 , 0x6db6db60 }, //bias2 { 0x000160c8 , 0x6db6db6c }, //bias3 { 0x000160cc , 0x6de6db6c }, //bias4 { 0x000160d0 , 0xb6da4924 }, //bias5 { 0x00016100 , 0x04cb0001 }, //rxtx1 { 0x00016104 , 0xfff80000 }, //rxtx2 { 0x00016108 , 0x00080010 }, //rxtx3 { 0x00016140 , 0x50804008 }, //bb1 { 0x00016144 , 0x01884080 }, //bb2 { 0x00016148 , 0x000080c0 }, //bb3 { 0x00016280 , 0x01000015 }, //top { 0x00016284 , 0x15530000 }, //top2 (beta4 -> beta6 change to address the 2G RX reset-reset variation) { 0x00016288 , 0x00318000 }, //top3 { 0x0001628c , 0x50000000 }, //therm { 0x00016380 , 0x00000000 }, //rbist_cntrl { 0x00016384 , 0x00000000 }, //tx_dc_offset { 0x00016388 , 0x00800700 }, //tx_tonegen0 { 0x0001638c , 0x00800700 }, //tx_tonegen1 { 0x00016390 , 0x00800700 }, //tx_lftonegen0 { 0x00016394 , 0x00000000 }, //tx_linear_ramp_i { 0x00016398 , 0x00000000 }, //tx_linear_ramp_q { 0x0001639c , 0x00000000 }, //tx_prbs_mag { 0x000163a0 , 0x00000001 }, //tx_prbs_seed_i { 0x000163a4 , 0x00000001 }, //tx_prbs_seed_q { 0x000163a8 , 0x00000000 }, //cmac_dc_cancel { 0x000163ac , 0x00000000 }, //cmac_dc_offset { 0x000163b0 , 0x00000000 }, //cmac_corr { 0x000163b4 , 0x00000000 }, //cmac_power { 0x000163b8 , 0x00000000 }, //cmac_cross_corr { 0x000163bc , 0x00000000 }, //cmac_i2q2 { 0x000163c0 , 0x000000a0 }, //cmac_power_hpf { 0x000163c4 , 0x000c0000 }, //rxdac_set1 { 0x000163c8 , 0x14021402 }, //rxdac_set2 { 0x000163cc , 0x00001402 }, //rxdac_long_shift { 0x000163d0 , 0x00000000 }, //cmac_results_i { 0x000163d4 , 0x00000000 }, //cmac_results_q { 0x00016400 , 0x36db6db6 }, //ch1_rxrf_bias1 { 0x00016404 , 0x6db6db40 }, //ch1_rxrf_bias2 { 0x00016408 , 0x73f00000 }, //ch1_rxrf_gainstages { 0x0001640c , 0x00000000 }, //ch1_rxrf_agc { 0x00016440 , 0x7f80fff8 }, //ch1_txrf1 { 0x00016444 , 0x03b6d2db }, //ch1_txrf2 { 0x00016448 , 0x24927266 }, //ch1_txrf3 { 0x0001644c , 0x000f0278 }, //ch1_txrf4 { 0x00016450 , 0x6db6db6c }, //ch1_txrf5 { 0x00016454 , 0x6db60000 }, //ch1_txrf6 { 0x00016500 , 0x04cb0001 }, //ch1_rxtx1 { 0x00016504 , 0xfff80000 }, //ch1_rxtx2 { 0x00016508 , 0x00080010 }, //ch1_rxtx3 { 0x0001650c , 0x00000000 }, //ch1_rxtx4 { 0x00016540 , 0x50804008 }, //ch1_bb1 { 0x00016544 , 0x01884080 }, //ch1_bb2 { 0x00016548 , 0x000080c0 }, //ch1_bb3 { 0x00016780 , 0x00000000 }, //ch1_rbist_cntrl { 0x00016784 , 0x00000000 }, //ch1_tx_dc_offset { 0x00016788 , 0x00800700 }, //ch1_tx_tonegen0 { 0x0001678c , 0x00800700 }, //ch1_tx_tonegen1 { 0x00016790 , 0x00800700 }, //ch1_tx_lftonegen0 { 0x00016794 , 0x00000000 }, //ch1_tx_linear_ramp_i { 0x00016798 , 0x00000000 }, //ch1_tx_linear_ramp_q { 0x0001679c , 0x00000000 }, //ch1_tx_prbs_mag { 0x000167a0 , 0x00000001 }, //ch1_tx_prbs_seed_i { 0x000167a4 , 0x00000001 }, //ch1_tx_prbs_seed_q { 0x000167a8 , 0x00000000 }, //ch1_cmac_dc_cancel { 0x000167ac , 0x00000000 }, //ch1_cmac_dc_offset { 0x000167b0 , 0x00000000 }, //ch1_cmac_corr { 0x000167b4 , 0x00000000 }, //ch1_cmac_power { 0x000167b8 , 0x00000000 }, //ch1_cmac_cross_corr { 0x000167bc , 0x00000000 }, //ch1_cmac_i2q2 { 0x000167c0 , 0x000000a0 }, //ch1_cmac_power_hpf { 0x000167c4 , 0x000c0000 }, //ch1_rxdac_set1 { 0x000167c8 , 0x14021402 }, //ch1_rxdac_set2 { 0x000167cc , 0x00001402 }, //ch1_rxdac_long_shift { 0x000167d0 , 0x00000000 }, //ch1_cmac_results_i { 0x000167d4 , 0x00000000 }, //ch1_cmac_results_q }; static const u_int32_t ar9340_wasp_1p0_radio_core_40M[][2] = { { 0x0001609c , 0x02566f3a }, //synth8 (beta4 -> beta6 change) { 0x000160ac , 0xa4647c00 }, //synth12 (beta4 -> beta6 change) { 0x000160b0 , 0x01885f5a }, //synth13 (beta4 -> beta6 change) { 0x00008244 , 0x0010f400 }, // MAC_PCU_SLP32_MODE { 0x0000824c , 0x0001e800 }, // MAC_PCU_SLP32_INC }; static const u_int32_t ar9340Common_rx_gain_table_merlin_2p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x02000101 }, { 0x0000a004 , 0x02000102 }, { 0x0000a008 , 0x02000103 }, { 0x0000a00c , 0x02000104 }, { 0x0000a010 , 0x02000200 }, { 0x0000a014 , 0x02000201 }, { 0x0000a018 , 0x02000202 }, { 0x0000a01c , 0x02000203 }, { 0x0000a020 , 0x02000204 }, { 0x0000a024 , 0x02000205 }, { 0x0000a028 , 0x02000208 }, { 0x0000a02c , 0x02000302 }, { 0x0000a030 , 0x02000303 }, { 0x0000a034 , 0x02000304 }, { 0x0000a038 , 0x02000400 }, { 0x0000a03c , 0x02010300 }, { 0x0000a040 , 0x02010301 }, { 0x0000a044 , 0x02010302 }, { 0x0000a048 , 0x02000500 }, { 0x0000a04c , 0x02010400 }, { 0x0000a050 , 0x02020300 }, { 0x0000a054 , 0x02020301 }, { 0x0000a058 , 0x02020302 }, { 0x0000a05c , 0x02020303 }, { 0x0000a060 , 0x02020400 }, { 0x0000a064 , 0x02030300 }, { 0x0000a068 , 0x02030301 }, { 0x0000a06c , 0x02030302 }, { 0x0000a070 , 0x02030303 }, { 0x0000a074 , 0x02030400 }, { 0x0000a078 , 0x02040300 }, { 0x0000a07c , 0x02040301 }, { 0x0000a080 , 0x02040302 }, { 0x0000a084 , 0x02040303 }, { 0x0000a088 , 0x02030500 }, { 0x0000a08c , 0x02040400 }, { 0x0000a090 , 0x02050203 }, { 0x0000a094 , 0x02050204 }, { 0x0000a098 , 0x02050205 }, { 0x0000a09c , 0x02040500 }, { 0x0000a0a0 , 0x02050301 }, { 0x0000a0a4 , 0x02050302 }, { 0x0000a0a8 , 0x02050303 }, { 0x0000a0ac , 0x02050400 }, { 0x0000a0b0 , 0x02050401 }, { 0x0000a0b4 , 0x02050402 }, { 0x0000a0b8 , 0x02050403 }, { 0x0000a0bc , 0x02050500 }, { 0x0000a0c0 , 0x02050501 }, { 0x0000a0c4 , 0x02050502 }, { 0x0000a0c8 , 0x02050503 }, { 0x0000a0cc , 0x02050504 }, { 0x0000a0d0 , 0x02050600 }, { 0x0000a0d4 , 0x02050601 }, { 0x0000a0d8 , 0x02050602 }, { 0x0000a0dc , 0x02050603 }, { 0x0000a0e0 , 0x02050604 }, { 0x0000a0e4 , 0x02050700 }, { 0x0000a0e8 , 0x02050701 }, { 0x0000a0ec , 0x02050702 }, { 0x0000a0f0 , 0x02050703 }, { 0x0000a0f4 , 0x02050704 }, { 0x0000a0f8 , 0x02050705 }, { 0x0000a0fc , 0x02050708 }, { 0x0000a100 , 0x02050709 }, { 0x0000a104 , 0x0205070a }, { 0x0000a108 , 0x0205070b }, { 0x0000a10c , 0x0205070c }, { 0x0000a110 , 0x0205070d }, { 0x0000a114 , 0x02050710 }, { 0x0000a118 , 0x02050711 }, { 0x0000a11c , 0x02050712 }, { 0x0000a120 , 0x02050713 }, { 0x0000a124 , 0x02050714 }, { 0x0000a128 , 0x02050715 }, { 0x0000a12c , 0x02050730 }, { 0x0000a130 , 0x02050731 }, { 0x0000a134 , 0x02050732 }, { 0x0000a138 , 0x02050733 }, { 0x0000a13c , 0x02050734 }, { 0x0000a140 , 0x02050735 }, { 0x0000a144 , 0x02050750 }, { 0x0000a148 , 0x02050751 }, { 0x0000a14c , 0x02050752 }, { 0x0000a150 , 0x02050753 }, { 0x0000a154 , 0x02050754 }, { 0x0000a158 , 0x02050755 }, { 0x0000a15c , 0x02050770 }, { 0x0000a160 , 0x02050771 }, { 0x0000a164 , 0x02050772 }, { 0x0000a168 , 0x02050773 }, { 0x0000a16c , 0x02050774 }, { 0x0000a170 , 0x02050775 }, { 0x0000a174 , 0x00000776 }, { 0x0000a178 , 0x00000776 }, { 0x0000a17c , 0x00000776 }, { 0x0000a180 , 0x00000776 }, { 0x0000a184 , 0x00000776 }, { 0x0000a188 , 0x00000776 }, { 0x0000a18c , 0x00000776 }, { 0x0000a190 , 0x00000776 }, { 0x0000a194 , 0x00000776 }, { 0x0000a198 , 0x00000776 }, { 0x0000a19c , 0x00000776 }, { 0x0000a1a0 , 0x00000776 }, { 0x0000a1a4 , 0x00000776 }, { 0x0000a1a8 , 0x00000776 }, { 0x0000a1ac , 0x00000776 }, { 0x0000a1b0 , 0x00000776 }, { 0x0000a1b4 , 0x00000776 }, { 0x0000a1b8 , 0x00000776 }, { 0x0000a1bc , 0x00000776 }, { 0x0000a1c0 , 0x00000776 }, { 0x0000a1c4 , 0x00000776 }, { 0x0000a1c8 , 0x00000776 }, { 0x0000a1cc , 0x00000776 }, { 0x0000a1d0 , 0x00000776 }, { 0x0000a1d4 , 0x00000776 }, { 0x0000a1d8 , 0x00000776 }, { 0x0000a1dc , 0x00000776 }, { 0x0000a1e0 , 0x00000776 }, { 0x0000a1e4 , 0x00000776 }, { 0x0000a1e8 , 0x00000776 }, { 0x0000a1ec , 0x00000776 }, { 0x0000a1f0 , 0x00000776 }, { 0x0000a1f4 , 0x00000776 }, { 0x0000a1f8 , 0x00000776 }, { 0x0000a1fc , 0x00000776 }, { 0x0000b000 , 0x02000101 }, { 0x0000b004 , 0x02000102 }, { 0x0000b008 , 0x02000103 }, { 0x0000b00c , 0x02000104 }, { 0x0000b010 , 0x02000200 }, { 0x0000b014 , 0x02000201 }, { 0x0000b018 , 0x02000202 }, { 0x0000b01c , 0x02000203 }, { 0x0000b020 , 0x02000204 }, { 0x0000b024 , 0x02000205 }, { 0x0000b028 , 0x02000208 }, { 0x0000b02c , 0x02000302 }, { 0x0000b030 , 0x02000303 }, { 0x0000b034 , 0x02000304 }, { 0x0000b038 , 0x02000400 }, { 0x0000b03c , 0x02010300 }, { 0x0000b040 , 0x02010301 }, { 0x0000b044 , 0x02010302 }, { 0x0000b048 , 0x02000500 }, { 0x0000b04c , 0x02010400 }, { 0x0000b050 , 0x02020300 }, { 0x0000b054 , 0x02020301 }, { 0x0000b058 , 0x02020302 }, { 0x0000b05c , 0x02020303 }, { 0x0000b060 , 0x02020400 }, { 0x0000b064 , 0x02030300 }, { 0x0000b068 , 0x02030301 }, { 0x0000b06c , 0x02030302 }, { 0x0000b070 , 0x02030303 }, { 0x0000b074 , 0x02030400 }, { 0x0000b078 , 0x02040300 }, { 0x0000b07c , 0x02040301 }, { 0x0000b080 , 0x02040302 }, { 0x0000b084 , 0x02040303 }, { 0x0000b088 , 0x02030500 }, { 0x0000b08c , 0x02040400 }, { 0x0000b090 , 0x02050203 }, { 0x0000b094 , 0x02050204 }, { 0x0000b098 , 0x02050205 }, { 0x0000b09c , 0x02040500 }, { 0x0000b0a0 , 0x02050301 }, { 0x0000b0a4 , 0x02050302 }, { 0x0000b0a8 , 0x02050303 }, { 0x0000b0ac , 0x02050400 }, { 0x0000b0b0 , 0x02050401 }, { 0x0000b0b4 , 0x02050402 }, { 0x0000b0b8 , 0x02050403 }, { 0x0000b0bc , 0x02050500 }, { 0x0000b0c0 , 0x02050501 }, { 0x0000b0c4 , 0x02050502 }, { 0x0000b0c8 , 0x02050503 }, { 0x0000b0cc , 0x02050504 }, { 0x0000b0d0 , 0x02050600 }, { 0x0000b0d4 , 0x02050601 }, { 0x0000b0d8 , 0x02050602 }, { 0x0000b0dc , 0x02050603 }, { 0x0000b0e0 , 0x02050604 }, { 0x0000b0e4 , 0x02050700 }, { 0x0000b0e8 , 0x02050701 }, { 0x0000b0ec , 0x02050702 }, { 0x0000b0f0 , 0x02050703 }, { 0x0000b0f4 , 0x02050704 }, { 0x0000b0f8 , 0x02050705 }, { 0x0000b0fc , 0x02050708 }, { 0x0000b100 , 0x02050709 }, { 0x0000b104 , 0x0205070a }, { 0x0000b108 , 0x0205070b }, { 0x0000b10c , 0x0205070c }, { 0x0000b110 , 0x0205070d }, { 0x0000b114 , 0x02050710 }, { 0x0000b118 , 0x02050711 }, { 0x0000b11c , 0x02050712 }, { 0x0000b120 , 0x02050713 }, { 0x0000b124 , 0x02050714 }, { 0x0000b128 , 0x02050715 }, { 0x0000b12c , 0x02050730 }, { 0x0000b130 , 0x02050731 }, { 0x0000b134 , 0x02050732 }, { 0x0000b138 , 0x02050733 }, { 0x0000b13c , 0x02050734 }, { 0x0000b140 , 0x02050735 }, { 0x0000b144 , 0x02050750 }, { 0x0000b148 , 0x02050751 }, { 0x0000b14c , 0x02050752 }, { 0x0000b150 , 0x02050753 }, { 0x0000b154 , 0x02050754 }, { 0x0000b158 , 0x02050755 }, { 0x0000b15c , 0x02050770 }, { 0x0000b160 , 0x02050771 }, { 0x0000b164 , 0x02050772 }, { 0x0000b168 , 0x02050773 }, { 0x0000b16c , 0x02050774 }, { 0x0000b170 , 0x02050775 }, { 0x0000b174 , 0x00000776 }, { 0x0000b178 , 0x00000776 }, { 0x0000b17c , 0x00000776 }, { 0x0000b180 , 0x00000776 }, { 0x0000b184 , 0x00000776 }, { 0x0000b188 , 0x00000776 }, { 0x0000b18c , 0x00000776 }, { 0x0000b190 , 0x00000776 }, { 0x0000b194 , 0x00000776 }, { 0x0000b198 , 0x00000776 }, { 0x0000b19c , 0x00000776 }, { 0x0000b1a0 , 0x00000776 }, { 0x0000b1a4 , 0x00000776 }, { 0x0000b1a8 , 0x00000776 }, { 0x0000b1ac , 0x00000776 }, { 0x0000b1b0 , 0x00000776 }, { 0x0000b1b4 , 0x00000776 }, { 0x0000b1b8 , 0x00000776 }, { 0x0000b1bc , 0x00000776 }, { 0x0000b1c0 , 0x00000776 }, { 0x0000b1c4 , 0x00000776 }, { 0x0000b1c8 , 0x00000776 }, { 0x0000b1cc , 0x00000776 }, { 0x0000b1d0 , 0x00000776 }, { 0x0000b1d4 , 0x00000776 }, { 0x0000b1d8 , 0x00000776 }, { 0x0000b1dc , 0x00000776 }, { 0x0000b1e0 , 0x00000776 }, { 0x0000b1e4 , 0x00000776 }, { 0x0000b1e8 , 0x00000776 }, { 0x0000b1ec , 0x00000776 }, { 0x0000b1f0 , 0x00000776 }, { 0x0000b1f4 , 0x00000776 }, { 0x0000b1f8 , 0x00000776 }, { 0x0000b1fc , 0x00000776 }, }; static const u_int32_t ar9340_wasp_1p0_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00001030 , 0x00000230 , 0x00000460 , 0x000002c0 , 0x00000160 }, { 0x00001070 , 0x00000168 , 0x000002d0 , 0x00000318 , 0x0000018c }, { 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 }, { 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 }, { 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b }, - { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 }, + { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 }, { 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a }, { 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 }, }; static const u_int32_t ar9340_wasp_1p0_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00007010 , 0x00000023 , 0x00000023 , 0x00000023 , 0x00000023 }, }; static const u_int32_t ar9340_merlin_2p0_radio_core[][2] = { /* Addr common */ { 0x00007800 , 0x00040000 }, { 0x00007804 , 0xdb005012 }, { 0x00007808 , 0x04924914 }, { 0x0000780c , 0x21084210 }, { 0x00007810 , 0x6d801300 }, { 0x00007814 , 0x0019beff }, { 0x00007818 , 0x07e41000 }, { 0x0000781c , 0x00392000 }, { 0x00007820 , 0x92592480 }, { 0x00007824 , 0x00040000 }, { 0x00007828 , 0xdb005012 }, { 0x0000782c , 0x04924914 }, { 0x00007830 , 0x21084210 }, { 0x00007834 , 0x6d801300 }, { 0x00007838 , 0x0019beff }, { 0x0000783c , 0x07e40000 }, { 0x00007840 , 0x00392000 }, { 0x00007844 , 0x92592480 }, { 0x00007848 , 0x00100000 }, { 0x0000784c , 0x773f0567 }, { 0x00007850 , 0x54214514 }, { 0x00007854 , 0x12035828 }, { 0x00007858 , 0x92592692 }, { 0x0000785c , 0x00000000 }, { 0x00007860 , 0x56400000 }, { 0x00007864 , 0x0a8e370e }, { 0x00007868 , 0xc0102850 }, { 0x0000786c , 0x812d4000 }, { 0x00007870 , 0x807ec400 }, { 0x00007874 , 0x001b6db0 }, { 0x00007878 , 0x00376b63 }, { 0x0000787c , 0x06db6db6 }, { 0x00007880 , 0x006d8000 }, { 0x00007884 , 0xffeffffe }, { 0x00007888 , 0xffeffffe }, { 0x0000788c , 0x00010000 }, { 0x00007890 , 0x02060aeb }, { 0x00007894 , 0x5a108000 }, }; static const u_int32_t ar9340_wasp_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009810 , 0xd00a8005 , 0xd00a8005 , 0xd00a8011 , 0xd00a8011 }, { 0x00009820 , 0x206a022e , 0x206a022e , 0x206a022e , 0x206a022e }, { 0x00009824 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 }, { 0x00009828 , 0x06903081 , 0x06903081 , 0x09103881 , 0x09103881 }, { 0x0000982c , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 }, { 0x00009830 , 0x0000059c , 0x0000059c , 0x0000119c , 0x0000119c }, { 0x00009c00 , 0x000000c4 , 0x000000c4 , 0x000000c4 , 0x000000c4 }, { 0x00009e00 , 0x0372111a , 0x0372111a , 0x037216a0 , 0x037216a0 }, { 0x00009e04 , 0x001c2020 , 0x001c2020 , 0x001c2020 , 0x001c2020 }, { 0x00009e0c , 0x6c4000e2 , 0x6d4000e2 , 0x6d4000e2 , 0x6c4000e2 }, { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec88d2e , 0x7ec88d2e }, { 0x00009e14 , 0x37b95d5e , 0x37b9605e , 0x3379605e , 0x33795d5e }, { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, - { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c }, + { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c }, { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce }, { 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 }, { 0x00009e3c , 0xcf946220 , 0xcf946220 , 0xcf946222 , 0xcf946222 }, { 0x00009e44 , 0x02321e27 , 0x02321e27 , 0x02291e27 , 0x02291e27 }, { 0x00009e48 , 0x5030201a , 0x5030201a , 0x50302012 , 0x50302012 }, { 0x00009fc8 , 0x0003f000 , 0x0003f000 , 0x0001a000 , 0x0001a000 }, { 0x0000a204 , 0x00003ec0 , 0x00003ec4 , 0x00003ec4 , 0x00003ec0 }, { 0x0000a208 , 0x00000104 , 0x00000104 , 0x00000004 , 0x00000004 }, { 0x0000a22c , 0x07e26a2f , 0x07e26a2f , 0x01026a2f , 0x01026a2f }, { 0x0000a230 , 0x0000000a , 0x00000014 , 0x00000016 , 0x0000000b }, { 0x0000a234 , 0x00000fff , 0x10000fff , 0x10000fff , 0x00000fff }, { 0x0000a238 , 0xffb81018 , 0xffb81018 , 0xffb81018 , 0xffb81018 }, { 0x0000a250 , 0x00000000 , 0x00000000 , 0x00000210 , 0x00000108 }, { 0x0000a254 , 0x000007d0 , 0x00000fa0 , 0x00001130 , 0x00000898 }, { 0x0000a258 , 0x02020002 , 0x02020002 , 0x02020002 , 0x02020002 }, { 0x0000a25c , 0x01000e0e , 0x01000e0e , 0x01000e0e , 0x01000e0e }, { 0x0000a260 , 0x0a021501 , 0x0a021501 , 0x3a021501 , 0x3a021501 }, { 0x0000a264 , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a280 , 0x00000007 , 0x00000007 , 0x0000000b , 0x0000000b }, { 0x0000a284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, { 0x0000a288 , 0x00000220 , 0x00000220 , 0x00000110 , 0x00000110 }, { 0x0000a28c , 0x00011111 , 0x00011111 , 0x00022222 , 0x00022222 }, { 0x0000a2c4 , 0x00158d18 , 0x00158d18 , 0x00158d18 , 0x00158d18 }, { 0x0000a2d0 , 0x00041983 , 0x00041983 , 0x00041982 , 0x00041982 }, { 0x0000a2d8 , 0x7999a83a , 0x7999a83a , 0x7999a83a , 0x7999a83a }, { 0x0000a358 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a830 , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae04 , 0x001c0000 , 0x001c0000 , 0x001c0000 , 0x001c0000 }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000ae1c , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae20 , 0x000001b5 , 0x000001b5 , 0x000001ce , 0x000001ce }, { 0x0000b284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, }; static const u_int32_t ar9340_wasp_1p0_baseband_core[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafe68e30 }, { 0x00009804 , 0xfd14e000 }, { 0x00009808 , 0x9c0a9f6b }, { 0x0000980c , 0x04900000 }, { 0x00009814 , 0x3280c00a }, { 0x00009818 , 0x00000000 }, { 0x0000981c , 0x00020028 }, { 0x00009834 , 0x6400a190 }, { 0x00009838 , 0x0108ecff }, { 0x0000983c , 0x14000600 }, { 0x00009880 , 0x201fff00 }, { 0x00009884 , 0x00001042 }, { 0x000098a4 , 0x00200400 }, { 0x000098b0 , 0x32840bbe }, { 0x000098d0 , 0x004b6a8e }, { 0x000098d4 , 0x00000820 }, { 0x000098dc , 0x00000000 }, { 0x000098f0 , 0x00000000 }, { 0x000098f4 , 0x00000000 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009c0c , 0x00000000 }, { 0x00009c10 , 0x00000000 }, { 0x00009c14 , 0x00046384 }, { 0x00009c18 , 0x05b6b440 }, { 0x00009c1c , 0x00b6b440 }, { 0x00009d00 , 0xc080a333 }, { 0x00009d04 , 0x40206c10 }, { 0x00009d08 , 0x009c4060 }, { 0x00009d0c , 0x9883800a }, { 0x00009d10 , 0x01834061 }, { 0x00009d14 , 0x00c0040b }, { 0x00009d18 , 0x00000000 }, { 0x00009e08 , 0x0038230c }, { 0x00009e24 , 0x990bb515 }, { 0x00009e28 , 0x0c6f0000 }, { 0x00009e30 , 0x06336f77 }, { 0x00009e34 , 0x6af6532f }, { 0x00009e38 , 0x0cc80c00 }, { 0x00009e40 , 0x0d261820 }, { 0x00009e4c , 0x00001004 }, { 0x00009e50 , 0x00ff03f1 }, { 0x00009e54 , 0x00000000 }, { 0x00009fc0 , 0x803e4788 }, { 0x00009fc4 , 0x0001efb5 }, { 0x00009fcc , 0x40000014 }, { 0x00009fd0 , 0x01193b93 }, { 0x0000a20c , 0x00000000 }, { 0x0000a220 , 0x00000000 }, { 0x0000a224 , 0x00000000 }, { 0x0000a228 , 0x10002310 }, { 0x0000a23c , 0x00000000 }, { 0x0000a244 , 0x0c000000 }, { 0x0000a2a0 , 0x00000001 }, { 0x0000a2c0 , 0x00000001 }, { 0x0000a2c8 , 0x00000000 }, { 0x0000a2cc , 0x18c43433 }, { 0x0000a2d4 , 0x00000000 }, { 0x0000a2ec , 0x00000000 }, { 0x0000a2f0 , 0x00000000 }, { 0x0000a2f4 , 0x00000000 }, { 0x0000a2f8 , 0x00000000 }, { 0x0000a344 , 0x00000000 }, { 0x0000a34c , 0x00000000 }, { 0x0000a350 , 0x0000a000 }, { 0x0000a364 , 0x00000000 }, { 0x0000a370 , 0x00000000 }, { 0x0000a390 , 0x00000001 }, { 0x0000a394 , 0x00000444 }, { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x210d0401 }, { 0x0000a3a0 , 0xab9a7144 }, { 0x0000a3a4 , 0x00000000 }, { 0x0000a3a8 , 0xaaaaaaaa }, { 0x0000a3ac , 0x3c466478 }, { 0x0000a3c0 , 0x20202020 }, { 0x0000a3c4 , 0x22222220 }, { 0x0000a3c8 , 0x20200020 }, { 0x0000a3cc , 0x20202020 }, { 0x0000a3d0 , 0x20202020 }, { 0x0000a3d4 , 0x20202020 }, { 0x0000a3d8 , 0x20202020 }, { 0x0000a3dc , 0x20202020 }, { 0x0000a3e0 , 0x20202020 }, { 0x0000a3e4 , 0x20202020 }, { 0x0000a3e8 , 0x20202020 }, { 0x0000a3ec , 0x20202020 }, { 0x0000a3f0 , 0x00000000 }, { 0x0000a3f4 , 0x00000000 }, { 0x0000a3f8 , 0x0cdbd380 }, { 0x0000a3fc , 0x000f0f01 }, { 0x0000a400 , 0x8fa91f01 }, { 0x0000a404 , 0x00000000 }, { 0x0000a408 , 0x0e79e5c6 }, { 0x0000a40c , 0x00820820 }, { 0x0000a414 , 0x1ce739ce }, { 0x0000a418 , 0x2d001dce }, { 0x0000a41c , 0x1ce739ce }, { 0x0000a420 , 0x000001ce }, { 0x0000a424 , 0x1ce739ce }, { 0x0000a428 , 0x000001ce }, { 0x0000a42c , 0x1ce739ce }, { 0x0000a430 , 0x1ce739ce }, { 0x0000a434 , 0x00000000 }, { 0x0000a438 , 0x00001801 }, { 0x0000a43c , 0x00100000 }, { 0x0000a440 , 0x00000000 }, { 0x0000a444 , 0x00000000 }, { 0x0000a448 , 0x05000080 }, { 0x0000a44c , 0x00000001 }, { 0x0000a450 , 0x00010000 }, { 0x0000a458 , 0x00000000 }, { 0x0000a640 , 0x00000000 }, { 0x0000a644 , 0x3fad9d74 }, { 0x0000a648 , 0x0048060a }, { 0x0000a64c , 0x00003c37 }, { 0x0000a670 , 0x03020100 }, { 0x0000a674 , 0x09080504 }, { 0x0000a678 , 0x0d0c0b0a }, { 0x0000a67c , 0x13121110 }, { 0x0000a680 , 0x31301514 }, { 0x0000a684 , 0x35343332 }, { 0x0000a688 , 0x00000036 }, { 0x0000a690 , 0x00000838 }, { 0x0000a7c0 , 0x00000000 }, { 0x0000a7c4 , 0xfffffffc }, { 0x0000a7c8 , 0x00000000 }, { 0x0000a7cc , 0x00000000 }, { 0x0000a7d0 , 0x00000000 }, { 0x0000a7d4 , 0x00000004 }, { 0x0000a7dc , 0x00000000 }, { 0x0000a8d0 , 0x004b6a8e }, { 0x0000a8d4 , 0x00000820 }, { 0x0000a8dc , 0x00000000 }, { 0x0000a8f0 , 0x00000000 }, { 0x0000a8f4 , 0x00000000 }, { 0x0000b2d0 , 0x00000080 }, { 0x0000b2d4 , 0x00000000 }, { 0x0000b2ec , 0x00000000 }, { 0x0000b2f0 , 0x00000000 }, { 0x0000b2f4 , 0x00000000 }, { 0x0000b2f8 , 0x00000000 }, { 0x0000b408 , 0x0e79e5c0 }, { 0x0000b40c , 0x00820820 }, { 0x0000b420 , 0x00000000 }, }; static const u_int32_t ar9340_wasp_1p0_baseband_postamble_dfs_channel[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00009824 , 0x5ac668d0 , 0x5ac668d0 }, + { 0x00009828 , 0x06903080 , 0x06903080 }, + { 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 }, { 0x00009e14 , 0x37b9625e , 0x37b9625e }, + + { 0x00009814 , 0x3400c00f , 0x3400c00f }, }; static const u_int32_t ar9340_wasp_1p0_mac_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00008014 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 }, { 0x0000801c , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 }, }; static const u_int32_t ar9340Modes_high_power_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d8 , 0x000050d8 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x04002222 , 0x04002222 , 0x02000001 , 0x02000001 }, { 0x0000a508 , 0x09002421 , 0x09002421 , 0x05000003 , 0x05000003 }, { 0x0000a50c , 0x0d002621 , 0x0d002621 , 0x0a000005 , 0x0a000005 }, { 0x0000a510 , 0x13004620 , 0x13004620 , 0x0e000201 , 0x0e000201 }, { 0x0000a514 , 0x19004a20 , 0x19004a20 , 0x11000203 , 0x11000203 }, { 0x0000a518 , 0x1d004e20 , 0x1d004e20 , 0x14000401 , 0x14000401 }, { 0x0000a51c , 0x21005420 , 0x21005420 , 0x18000403 , 0x18000403 }, { 0x0000a520 , 0x26005e20 , 0x26005e20 , 0x1b000602 , 0x1b000602 }, { 0x0000a524 , 0x2b005e40 , 0x2b005e40 , 0x1f000802 , 0x1f000802 }, { 0x0000a528 , 0x2f005e42 , 0x2f005e42 , 0x21000620 , 0x21000620 }, { 0x0000a52c , 0x33005e44 , 0x33005e44 , 0x25000820 , 0x25000820 }, { 0x0000a530 , 0x38005e65 , 0x38005e65 , 0x29000822 , 0x29000822 }, { 0x0000a534 , 0x3c005e69 , 0x3c005e69 , 0x2d000824 , 0x2d000824 }, { 0x0000a538 , 0x40005e6b , 0x40005e6b , 0x30000828 , 0x30000828 }, { 0x0000a53c , 0x44005e6d , 0x44005e6d , 0x3400082a , 0x3400082a }, { 0x0000a540 , 0x49005e72 , 0x49005e72 , 0x38000849 , 0x38000849 }, { 0x0000a544 , 0x4e005eb2 , 0x4e005eb2 , 0x3b000a2c , 0x3b000a2c }, { 0x0000a548 , 0x53005f12 , 0x53005f12 , 0x3e000e2b , 0x3e000e2b }, { 0x0000a54c , 0x59025eb5 , 0x59025eb5 , 0x42000e2d , 0x42000e2d }, { 0x0000a550 , 0x5e025f12 , 0x5e025f12 , 0x4500124a , 0x4500124a }, { 0x0000a554 , 0x61027f12 , 0x61027f12 , 0x4900124c , 0x4900124c }, { 0x0000a558 , 0x6702bf12 , 0x6702bf12 , 0x4c00126c , 0x4c00126c }, { 0x0000a55c , 0x6b02bf14 , 0x6b02bf14 , 0x4f00128c , 0x4f00128c }, { 0x0000a560 , 0x6f02bf16 , 0x6f02bf16 , 0x52001290 , 0x52001290 }, { 0x0000a564 , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a568 , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a56c , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a570 , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a574 , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a578 , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a57c , 0x6f02bf16 , 0x6f02bf16 , 0x56001292 , 0x56001292 }, { 0x0000a580 , 0x00802220 , 0x00802220 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x04802222 , 0x04802222 , 0x02800001 , 0x02800001 }, { 0x0000a588 , 0x09802421 , 0x09802421 , 0x05800003 , 0x05800003 }, { 0x0000a58c , 0x0d802621 , 0x0d802621 , 0x0a800005 , 0x0a800005 }, { 0x0000a590 , 0x13804620 , 0x13804620 , 0x0e800201 , 0x0e800201 }, { 0x0000a594 , 0x19804a20 , 0x19804a20 , 0x11800203 , 0x11800203 }, { 0x0000a598 , 0x1d804e20 , 0x1d804e20 , 0x14800401 , 0x14800401 }, { 0x0000a59c , 0x21805420 , 0x21805420 , 0x18800403 , 0x18800403 }, { 0x0000a5a0 , 0x26805e20 , 0x26805e20 , 0x1b800602 , 0x1b800602 }, { 0x0000a5a4 , 0x2b805e40 , 0x2b805e40 , 0x1f800802 , 0x1f800802 }, { 0x0000a5a8 , 0x2f805e42 , 0x2f805e42 , 0x21800620 , 0x21800620 }, { 0x0000a5ac , 0x33805e44 , 0x33805e44 , 0x25800820 , 0x25800820 }, { 0x0000a5b0 , 0x38805e65 , 0x38805e65 , 0x29800822 , 0x29800822 }, { 0x0000a5b4 , 0x3c805e69 , 0x3c805e69 , 0x2d800824 , 0x2d800824 }, { 0x0000a5b8 , 0x40805e6b , 0x40805e6b , 0x30800828 , 0x30800828 }, { 0x0000a5bc , 0x44805e6d , 0x44805e6d , 0x3480082a , 0x3480082a }, { 0x0000a5c0 , 0x49805e72 , 0x49805e72 , 0x38800849 , 0x38800849 }, { 0x0000a5c4 , 0x4e805eb2 , 0x4e805eb2 , 0x3b800a2c , 0x3b800a2c }, { 0x0000a5c8 , 0x53805f12 , 0x53805f12 , 0x3e800e2b , 0x3e800e2b }, { 0x0000a5cc , 0x59825eb2 , 0x59825eb2 , 0x42800e2d , 0x42800e2d }, { 0x0000a5d0 , 0x5e825f12 , 0x5e825f12 , 0x4580124a , 0x4580124a }, { 0x0000a5d4 , 0x61827f12 , 0x61827f12 , 0x4980124c , 0x4980124c }, { 0x0000a5d8 , 0x6782bf12 , 0x6782bf12 , 0x4c80126c , 0x4c80126c }, { 0x0000a5dc , 0x6b82bf14 , 0x6b82bf14 , 0x4f80128c , 0x4f80128c }, { 0x0000a5e0 , 0x6f82bf16 , 0x6f82bf16 , 0x52801290 , 0x52801290 }, { 0x0000a5e4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5e8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5ec , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5f0 , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5f4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5f8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x0000a5fc , 0x6f82bf16 , 0x6f82bf16 , 0x56801292 , 0x56801292 }, { 0x00016044 , 0x056db2db , 0x056db2db , 0x022492db , 0x022492db }, { 0x00016048 , 0x24925266 , 0x24925266 , 0x24925266 , 0x24925266 }, { 0x00016444 , 0x056db2db , 0x056db2db , 0x022492db , 0x022492db }, { 0x00016448 , 0x24925266 , 0x24925266 , 0x24925266 , 0x24925266 }, }; static const u_int32_t ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d8 , 0x000050d8 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x04002222 , 0x04002222 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x09002421 , 0x09002421 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x0d002621 , 0x0d002621 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x13004620 , 0x13004620 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x19004a20 , 0x19004a20 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x1d004e20 , 0x1d004e20 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x21005420 , 0x21005420 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x26005e20 , 0x26005e20 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2b005e40 , 0x2b005e40 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x2f005e42 , 0x2f005e42 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x33005e44 , 0x33005e44 , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x38005e65 , 0x38005e65 , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x3c005e69 , 0x3c005e69 , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x40005e6b , 0x40005e6b , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x44005e6d , 0x44005e6d , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x49005e72 , 0x49005e72 , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x4e005eb2 , 0x4e005eb2 , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x53005f12 , 0x53005f12 , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x59025eb2 , 0x59025eb2 , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x5e025f12 , 0x5e025f12 , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x61027f12 , 0x61027f12 , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6702bf12 , 0x6702bf12 , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x6b02bf14 , 0x6b02bf14 , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x6f02bf16 , 0x6f02bf16 , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00802220 , 0x00802220 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x04802222 , 0x04802222 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x09802421 , 0x09802421 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x0d802621 , 0x0d802621 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x13804620 , 0x13804620 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x19804a20 , 0x19804a20 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x1d804e20 , 0x1d804e20 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x21805420 , 0x21805420 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x26805e20 , 0x26805e20 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2b805e40 , 0x2b805e40 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x2f805e42 , 0x2f805e42 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x33805e44 , 0x33805e44 , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x38805e65 , 0x38805e65 , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x3c805e69 , 0x3c805e69 , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x40805e6b , 0x40805e6b , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x44805e6d , 0x44805e6d , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x49805e72 , 0x49805e72 , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x4e805eb2 , 0x4e805eb2 , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x53805f12 , 0x53805f12 , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x59825eb2 , 0x59825eb2 , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x5e825f12 , 0x5e825f12 , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x61827f12 , 0x61827f12 , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6782bf12 , 0x6782bf12 , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x6b82bf14 , 0x6b82bf14 , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x6f82bf16 , 0x6f82bf16 , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00804000 , 0x00804000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x00804201 , 0x00804201 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x0280c802 , 0x0280c802 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x0280ca03 , 0x0280ca03 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x04c15104 , 0x04c15104 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04c15305 , 0x04c15305 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04c15305 , 0x04c15305 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016048 , 0x8e481666 , 0x8e481666 , 0x8e481266 , 0x8e481266 }, { 0x00016280 , 0x01000015 , 0x01000015 , 0x01001015 , 0x01001015 }, { 0x00016444 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016448 , 0x8e481666 , 0x8e481666 , 0x8e481266 , 0x8e481266 }, }; static const u_int32_t ar9340_modes_ub124_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009810 , 0xd00a8005 , 0xd00a8005 , 0xd00a8005 , 0xd00a8005 }, { 0x00009820 , 0x206a022e , 0x206a022e , 0x206a00ae , 0x206a00ae }, { 0x00009830 , 0x0000059c , 0x0000059c , 0x0000059c , 0x0000059c }, { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec82d2e , 0x7ec82d2e }, { 0x0000a2dc , 0xfef5d402 , 0xfef5d402 , 0xfdab5b52 , 0xfdab5b52 }, { 0x0000a2e0 , 0xfe896600 , 0xfe896600 , 0xfd339c84 , 0xfd339c84 }, { 0x0000a2e4 , 0xff01f800 , 0xff01f800 , 0xfec3e000 , 0xfec3e000 }, { 0x0000a2e8 , 0xfffe0000 , 0xfffe0000 , 0xfffc0000 , 0xfffc0000 }, { 0x0000a410 , 0x000050d8 , 0x000050d8 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x04002222 , 0x04002222 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x09002421 , 0x09002421 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x0d002621 , 0x0d002621 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x13004620 , 0x13004620 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x19004a20 , 0x19004a20 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x1d004e20 , 0x1d004e20 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x21005420 , 0x21005420 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x26005e20 , 0x26005e20 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2b005e40 , 0x2b005e40 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x2f005e42 , 0x2f005e42 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x33005e44 , 0x33005e44 , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x38005e65 , 0x38005e65 , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x3c005e69 , 0x3c005e69 , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x40005e6b , 0x40005e6b , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x44005e6d , 0x44005e6d , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x49005e72 , 0x49005e72 , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x4e005eb2 , 0x4e005eb2 , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x53005f12 , 0x53005f12 , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x59025eb5 , 0x59025eb5 , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x5e025f12 , 0x5e025f12 , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x61027f12 , 0x61027f12 , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6702bf12 , 0x6702bf12 , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x6b02bf14 , 0x6b02bf14 , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x6f02bf16 , 0x6f02bf16 , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00802220 , 0x00802220 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x04802222 , 0x04802222 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x09802421 , 0x09802421 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x0d802621 , 0x0d802621 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x13804620 , 0x13804620 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x19804a20 , 0x19804a20 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x1d804e20 , 0x1d804e20 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x21805420 , 0x21805420 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x26805e20 , 0x26805e20 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2b805e40 , 0x2b805e40 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x2f805e42 , 0x2f805e42 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x33805e44 , 0x33805e44 , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x38805e65 , 0x38805e65 , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x3c805e69 , 0x3c805e69 , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x40805e6b , 0x40805e6b , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x44805e6d , 0x44805e6d , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x49805e72 , 0x49805e72 , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x4e805eb2 , 0x4e805eb2 , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x53805f12 , 0x53805f12 , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x59825eb2 , 0x59825eb2 , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x5e825f12 , 0x5e825f12 , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x61827f12 , 0x61827f12 , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6782bf12 , 0x6782bf12 , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x6b82bf14 , 0x6b82bf14 , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x6f82bf16 , 0x6f82bf16 , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x00016044 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016048 , 0x8e480086 , 0x8e480086 , 0x8e480086 , 0x8e480086 }, { 0x00016444 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016448 , 0x8e480086 , 0x8e480086 , 0x8e480086 , 0x8e480086 }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00804000 , 0x00804000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x00804201 , 0x00804201 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x0280c802 , 0x0280c802 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x0280ca03 , 0x0280ca03 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x04c15104 , 0x04c15104 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04c15305 , 0x04c15305 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04c15305 , 0x04c15305 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0xfef5d402 , 0xfef5d402 , 0xfdab5b52 , 0xfdab5b52 }, { 0x0000b2e0 , 0xfe896600 , 0xfe896600 , 0xfd339c84 , 0xfd339c84 }, { 0x0000b2e4 , 0xff01f800 , 0xff01f800 , 0xfec3e000 , 0xfec3e000 }, { 0x0000b2e8 , 0xfffe0000 , 0xfffe0000 , 0xfffc0000 , 0xfffc0000 }, }; static const u_int32_t ar9340Common_rx_gain_table_wasp_1p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x01910190 }, { 0x0000a030 , 0x01930192 }, { 0x0000a034 , 0x01950194 }, { 0x0000a038 , 0x038a0196 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x22222229 }, { 0x0000a084 , 0x1d1d1d1d }, { 0x0000a088 , 0x1d1d1d1d }, { 0x0000a08c , 0x1d1d1d1d }, { 0x0000a090 , 0x171d1d1d }, { 0x0000a094 , 0x11111717 }, { 0x0000a098 , 0x00030311 }, { 0x0000a09c , 0x00000000 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x23232323 }, { 0x0000b084 , 0x21232323 }, { 0x0000b088 , 0x19191c1e }, { 0x0000b08c , 0x12141417 }, { 0x0000b090 , 0x07070e0e }, { 0x0000b094 , 0x03030305 }, { 0x0000b098 , 0x00000003 }, { 0x0000b09c , 0x00000000 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; static const u_int32_t ar9340Modes_low_ob_db_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21820220 , 0x21820220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27820223 , 0x27820223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5c84286b , 0x5c84286b , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x61842a6c , 0x61842a6c , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x66862a6c , 0x66862a6c , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x6b862e6c , 0x6b862e6c , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x7086308c , 0x7086308c , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x738a308a , 0x738a308a , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x778a308c , 0x778a308c , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x056db2db , 0x056db2db , 0x056db2db , 0x056db2db }, { 0x00016048 , 0x24925666 , 0x24925666 , 0x24925266 , 0x24925266 }, { 0x00016280 , 0x01000015 , 0x01000015 , 0x01001015 , 0x01001015 }, { 0x00016288 , 0xf0318000 , 0xf0318000 , 0xf0318000 , 0xf0318000 }, //top3 { 0x00016444 , 0x056db2db , 0x056db2db , 0x056db2db , 0x056db2db }, { 0x00016448 , 0x24925666 , 0x24925666 , 0x24925266 , 0x24925266 }, }; static const u_int32_t ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03eaac5a , 0x03eaac5a }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03f330ac , 0x03f330ac }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03fc3f00 , 0x03fc3f00 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ffc000 , 0x03ffc000 }, { 0x0000a394 , 0x00000444 , 0x00000444 , 0x00000404 , 0x00000404 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x02000001 , 0x02000001 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x05000003 , 0x05000003 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0a000005 , 0x0a000005 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0e000201 , 0x0e000201 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x11000203 , 0x11000203 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x14000401 , 0x14000401 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x18000403 , 0x18000403 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1b000602 , 0x1b000602 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x1f000802 , 0x1f000802 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x21000620 , 0x21000620 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x25000820 , 0x25000820 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x29000822 , 0x29000822 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x2d000824 , 0x2d000824 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x30000828 , 0x30000828 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x3400082a , 0x3400082a }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x38000849 , 0x38000849 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3b000a2c , 0x3b000a2c }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x3e000e2b , 0x3e000e2b }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x42000e2d , 0x42000e2d }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x4500124a , 0x4500124a }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x4900124c , 0x4900124c }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x4c00126c , 0x4c00126c }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x4f00128c , 0x4f00128c }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x52001290 , 0x52001290 }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x56001292 , 0x56001292 }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x02800001 , 0x02800001 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x05800003 , 0x05800003 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0a800005 , 0x0a800005 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0e800201 , 0x0e800201 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x11800203 , 0x11800203 }, { 0x0000a598 , 0x21820220 , 0x21820220 , 0x14800401 , 0x14800401 }, { 0x0000a59c , 0x27820223 , 0x27820223 , 0x18800403 , 0x18800403 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1b800602 , 0x1b800602 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x1f800802 , 0x1f800802 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x21800620 , 0x21800620 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x25800820 , 0x25800820 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x29800822 , 0x29800822 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x2d800824 , 0x2d800824 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x30800828 , 0x30800828 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x3480082a , 0x3480082a }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x38800849 , 0x38800849 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3b800a2c , 0x3b800a2c }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x3e800e2b , 0x3e800e2b }, { 0x0000a5cc , 0x5c84286b , 0x5c84286b , 0x42800e2d , 0x42800e2d }, { 0x0000a5d0 , 0x61842a6c , 0x61842a6c , 0x4580124a , 0x4580124a }, { 0x0000a5d4 , 0x66862a6c , 0x66862a6c , 0x4980124c , 0x4980124c }, { 0x0000a5d8 , 0x6b862e6c , 0x6b862e6c , 0x4c80126c , 0x4c80126c }, { 0x0000a5dc , 0x7086308c , 0x7086308c , 0x4f80128c , 0x4f80128c }, { 0x0000a5e0 , 0x738a308a , 0x738a308a , 0x52801290 , 0x52801290 }, { 0x0000a5e4 , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5e8 , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5ec , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5f0 , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5f4 , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5f8 , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a5fc , 0x778a308c , 0x778a308c , 0x56801292 , 0x56801292 }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404501 , 0x01404501 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x01404501 , 0x01404501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x03c0cf02 , 0x03c0cf02 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03c0cf03 , 0x03c0cf03 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04011004 , 0x04011004 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x05419405 , 0x05419405 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x05419506 , 0x05419506 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x05419506 , 0x05419506 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x05419506 , 0x05419506 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x05419506 , 0x05419506 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03eaac5a , 0x03eaac5a }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03f330ac , 0x03f330ac }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03fc3f00 , 0x03fc3f00 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ffc000 , 0x03ffc000 }, { 0x00016044 , 0x022492db , 0x022492db , 0x022492db , 0x022492db }, { 0x00016048 , 0x24925666 , 0x24925666 , 0x24925266 , 0x24925266 }, { 0x00016280 , 0x01000015 , 0x01000015 , 0x01001015 , 0x01001015 }, { 0x00016288 , 0xf0318000 , 0xf0318000 , 0xf0318000 , 0xf0318000 }, //top3 { 0x00016444 , 0x022492db , 0x022492db , 0x022492db , 0x022492db }, { 0x00016448 , 0x24925666 , 0x24925666 , 0x24925266 , 0x24925266 }, }; static const u_int32_t ar9340Modes_mixed_ob_db_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x21820220 , 0x21820220 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x27820223 , 0x27820223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x5c84286b , 0x5c84286b , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x61842a6c , 0x61842a6c , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x66862a6c , 0x66862a6c , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6b862e6c , 0x6b862e6c , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x7086308c , 0x7086308c , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x738a308a , 0x738a308a , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x056db2db , 0x056db2db , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016048 , 0x24925666 , 0x24925666 , 0x8e481266 , 0x8e481266 }, { 0x00016280 , 0x01000015 , 0x01000015 , 0x01001015 , 0x01001015 }, { 0x00016288 , 0x30318000 , 0x30318000 , 0x00318000 , 0x00318000 }, //top3 { 0x00016444 , 0x056db2db , 0x056db2db , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016448 , 0x24925666 , 0x24925666 , 0x8e481266 , 0x8e481266 }, }; static const u_int32_t ar9340Modes_cus227_tx_gain_table_wasp_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2c022220 , 0x2c022220 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x30022222 , 0x30022222 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x35022225 , 0x35022225 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x3b02222a , 0x3b02222a , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x3f02222c , 0x3f02222c , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x21820220 , 0x21820220 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x27820223 , 0x27820223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x5c84286b , 0x5c84286b , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x61842a6c , 0x61842a6c , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x66862a6c , 0x66862a6c , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6b862e6c , 0x6b862e6c , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x7086308c , 0x7086308c , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x738a308a , 0x738a308a , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x778a308c , 0x778a308c , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x056db2db , 0x056db2db , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016048 , 0x24925666 , 0x24925666 , 0x8e481266 , 0x8e481266 }, { 0x00016280 , 0x01000015 , 0x01000015 , 0x01001015 , 0x01001015 }, { 0x00016288 , 0x30318000 , 0x30318000 , 0x00318000 , 0x00318000 }, //top3 { 0x00016444 , 0x056db2db , 0x056db2db , 0x03b6d2e4 , 0x03b6d2e4 }, { 0x00016448 , 0x24925666 , 0x24925666 , 0x8e481266 , 0x8e481266 }, { 0x0000a3a4 , 0x00000011 , 0x00000011 , 0x00000011 , 0x00000011 }, { 0x0000a3a8 , 0x3c3c3c3c , 0x3c3c3c3c , 0x3c3c3c3c , 0x3c3c3c3c }, { 0x0000a3ac , 0x30303030 , 0x30303030 , 0x30303030 , 0x30303030 }, }; static const u_int32_t ar9340_wasp_1p0_mac_core[][2] = { /* Addr allmodes */ { 0x00000008 , 0x00000000 }, { 0x00000030 , 0x00020085 }, { 0x00000034 , 0x00000005 }, { 0x00000040 , 0x00000000 }, { 0x00000044 , 0x00000000 }, { 0x00000048 , 0x00000008 }, { 0x0000004c , 0x00000010 }, { 0x00000050 , 0x00000000 }, { 0x00001040 , 0x002ffc0f }, { 0x00001044 , 0x002ffc0f }, { 0x00001048 , 0x002ffc0f }, { 0x0000104c , 0x002ffc0f }, { 0x00001050 , 0x002ffc0f }, { 0x00001054 , 0x002ffc0f }, { 0x00001058 , 0x002ffc0f }, { 0x0000105c , 0x002ffc0f }, { 0x00001060 , 0x002ffc0f }, { 0x00001064 , 0x002ffc0f }, { 0x000010f0 , 0x00000100 }, { 0x00001270 , 0x00000000 }, { 0x000012b0 , 0x00000000 }, { 0x000012f0 , 0x00000000 }, { 0x0000143c , 0x00000000 }, { 0x0000147c , 0x00000000 }, { 0x00008000 , 0x00000000 }, { 0x00008004 , 0x00000000 }, { 0x00008008 , 0x00000000 }, { 0x0000800c , 0x00000000 }, { 0x00008010 , 0x00080800 }, { 0x00008018 , 0x00000000 }, { 0x00008020 , 0x00000000 }, { 0x00008038 , 0x00000000 }, { 0x0000803c , 0x00000000 }, { 0x00008040 , 0x00000000 }, { 0x00008044 , 0x00000000 }, { 0x00008048 , 0x00000000 }, { 0x0000804c , 0xffffffff }, { 0x00008054 , 0x00000000 }, { 0x00008058 , 0x00000000 }, { 0x0000805c , 0x000fc78f }, { 0x00008060 , 0x0000000f }, { 0x00008064 , 0x00000000 }, { 0x00008070 , 0x00000310 }, { 0x00008074 , 0x00000020 }, { 0x00008078 , 0x00000000 }, { 0x0000809c , 0x0000000f }, { 0x000080a0 , 0x00000000 }, { 0x000080a4 , 0x02ff0000 }, { 0x000080a8 , 0x0e070605 }, { 0x000080ac , 0x0000000d }, { 0x000080b0 , 0x00000000 }, { 0x000080b4 , 0x00000000 }, { 0x000080b8 , 0x00000000 }, { 0x000080bc , 0x00000000 }, { 0x000080c0 , 0x2a800000 }, { 0x000080c4 , 0x06900168 }, { 0x000080c8 , 0x13881c22 }, { 0x000080cc , 0x01f40000 }, { 0x000080d0 , 0x00252500 }, { 0x000080d4 , 0x00a00000 }, { 0x000080d8 , 0x00400000 }, { 0x000080dc , 0x00000000 }, { 0x000080e0 , 0xffffffff }, { 0x000080e4 , 0x0000ffff }, { 0x000080e8 , 0x3f3f3f3f }, { 0x000080ec , 0x00000000 }, { 0x000080f0 , 0x00000000 }, { 0x000080f4 , 0x00000000 }, { 0x000080fc , 0x00020000 }, { 0x00008100 , 0x00000000 }, { 0x00008108 , 0x00000052 }, { 0x0000810c , 0x00000000 }, { 0x00008110 , 0x00000000 }, { 0x00008114 , 0x000007ff }, { 0x00008118 , 0x000000aa }, { 0x0000811c , 0x00003210 }, { 0x00008124 , 0x00000000 }, { 0x00008128 , 0x00000000 }, { 0x0000812c , 0x00000000 }, { 0x00008130 , 0x00000000 }, { 0x00008134 , 0x00000000 }, { 0x00008138 , 0x00000000 }, { 0x0000813c , 0x0000ffff }, { 0x00008144 , 0xffffffff }, { 0x00008168 , 0x00000000 }, { 0x0000816c , 0x00000000 }, { 0x00008170 , 0x18486200 }, { 0x00008174 , 0x33332210 }, { 0x00008178 , 0x00000000 }, { 0x0000817c , 0x00020000 }, { 0x000081c0 , 0x00000000 }, { 0x000081c4 , 0x33332210 }, { 0x000081c8 , 0x00000000 }, { 0x000081cc , 0x00000000 }, { 0x000081d4 , 0x00000000 }, { 0x000081ec , 0x00000000 }, { 0x000081f0 , 0x00000000 }, { 0x000081f4 , 0x00000000 }, { 0x000081f8 , 0x00000000 }, { 0x000081fc , 0x00000000 }, { 0x00008240 , 0x00100000 }, { 0x00008244 , 0x0010f3d7 }, { 0x00008248 , 0x00000800 }, { 0x0000824c , 0x0001e7ae }, { 0x00008250 , 0x00000000 }, { 0x00008254 , 0x00000000 }, { 0x00008258 , 0x00000000 }, { 0x0000825c , 0x40000000 }, { 0x00008260 , 0x00080922 }, { 0x00008264 , 0x9d400010 }, { 0x00008268 , 0xffffffff }, { 0x0000826c , 0x0000ffff }, { 0x00008270 , 0x00000000 }, { 0x00008274 , 0x40000000 }, { 0x00008278 , 0x003e4180 }, { 0x0000827c , 0x00000004 }, { 0x00008284 , 0x0000002c }, { 0x00008288 , 0x0000002c }, { 0x0000828c , 0x000000ff }, { 0x00008294 , 0x00000000 }, { 0x00008298 , 0x00000000 }, { 0x0000829c , 0x00000000 }, { 0x00008300 , 0x00000140 }, { 0x00008314 , 0x00000000 }, { 0x0000831c , 0x0000010d }, { 0x00008328 , 0x00000000 }, { 0x0000832c , 0x00000007 }, { 0x00008330 , 0x00000302 }, { 0x00008334 , 0x00000700 }, { 0x00008338 , 0x00ff0000 }, { 0x0000833c , 0x02400000 }, { 0x00008340 , 0x000107ff }, { 0x00008344 , 0xaa48105b }, { 0x00008348 , 0x008f0000 }, { 0x0000835c , 0x00000000 }, { 0x00008360 , 0xffffffff }, { 0x00008364 , 0xffffffff }, { 0x00008368 , 0x00000000 }, { 0x00008370 , 0x00000000 }, { 0x00008374 , 0x000000ff }, { 0x00008378 , 0x00000000 }, { 0x0000837c , 0x00000000 }, { 0x00008380 , 0xffffffff }, { 0x00008384 , 0xffffffff }, { 0x00008390 , 0xffffffff }, { 0x00008394 , 0xffffffff }, { 0x00008398 , 0x00000000 }, { 0x0000839c , 0x00000000 }, { 0x000083a0 , 0x00000000 }, { 0x000083a4 , 0x0000fa14 }, { 0x000083a8 , 0x000f0c00 }, { 0x000083ac , 0x33332210 }, { 0x000083b0 , 0x33332210 }, { 0x000083b4 , 0x33332210 }, { 0x000083b8 , 0x33332210 }, { 0x000083bc , 0x00000000 }, { 0x000083c0 , 0x00000000 }, { 0x000083c4 , 0x00000000 }, { 0x000083c8 , 0x00000000 }, { 0x000083cc , 0x00000200 }, { 0x000083d0 , 0x000101ff }, }; static const u_int32_t ar9340Common_wo_xlna_rx_gain_table_wasp_1p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x03820190 }, { 0x0000a030 , 0x03840383 }, { 0x0000a034 , 0x03880385 }, { 0x0000a038 , 0x038a0389 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x29292929 }, { 0x0000a084 , 0x29292929 }, { 0x0000a088 , 0x29292929 }, { 0x0000a08c , 0x29292929 }, { 0x0000a090 , 0x22292929 }, { 0x0000a094 , 0x1d1d2222 }, { 0x0000a098 , 0x0c111117 }, { 0x0000a09c , 0x00030303 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x32323232 }, { 0x0000b084 , 0x2f2f3232 }, { 0x0000b088 , 0x23282a2d }, { 0x0000b08c , 0x1c1e2123 }, { 0x0000b090 , 0x14171919 }, { 0x0000b094 , 0x0e0e1214 }, { 0x0000b098 , 0x03050707 }, { 0x0000b09c , 0x00030303 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; static const u_int32_t ar9340_wasp_1p0_tx_gain_table_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a410 , 0x000000d5 , 0x000000d5 , 0x000000d5 , 0x000000d5 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x00004002 , 0x00004002 , 0x00004002 , 0x00004002 }, { 0x0000a508 , 0x00008004 , 0x00008004 , 0x00008004 , 0x00008004 }, { 0x0000a510 , 0x0001000c , 0x0001000c , 0x0001000c , 0x0001000c }, { 0x0000a514 , 0x0001420b , 0x0001420b , 0x0001420b , 0x0001420b }, { 0x0000a518 , 0x0001824a , 0x0001824a , 0x0001824a , 0x0001824a }, { 0x0000a51c , 0x0001c44a , 0x0001c44a , 0x0001c44a , 0x0001c44a }, { 0x0000a520 , 0x0002064a , 0x0002064a , 0x0002064a , 0x0002064a }, { 0x0000a524 , 0x0002484a , 0x0002484a , 0x0002484a , 0x0002484a }, { 0x0000a528 , 0x00028a4a , 0x00028a4a , 0x00028a4a , 0x00028a4a }, { 0x0000a52c , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a }, { 0x0000a530 , 0x00030e4a , 0x00030e4a , 0x00030e4a , 0x00030e4a }, { 0x0000a534 , 0x00034e8a , 0x00034e8a , 0x00034e8a , 0x00034e8a }, }; static const u_int32_t ar9340_wasp_1p0_soc_preamble[][2] = { /* Addr allmodes */ { 0x00007008 , 0x00000000 }, { 0x00007020 , 0x00000000 }, { 0x00007034 , 0x00000002 }, { 0x00007038 , 0x000004c2 }, }; Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini (revision 278740) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini (revision 278741) @@ -1,2219 +1,2221 @@ /* * Copyright (c) 2013 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ static const u_int32_t ar9300_ar9580_1p0_baseband_postamble_dfs_channel[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00009824 , 0x5ac668d0 , 0x5ac668d0 }, + { 0x00009828 , 0x06903080 , 0x06903080 }, { 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 }, { 0x00009e14 , 0x37b9625e , 0x37b9625e }, + { 0x00009814 , 0x3400c00f , 0x3400c00f }, }; static const u_int32_t ar9300Modes_fast_clock_ar9580_1p0[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00001030 , 0x00000268 , 0x000004d0 }, { 0x00001070 , 0x0000018c , 0x00000318 }, { 0x000010b0 , 0x00000fd0 , 0x00001fa0 }, { 0x00008014 , 0x044c044c , 0x08980898 }, { 0x0000801c , 0x148ec02b , 0x148ec057 }, { 0x00008318 , 0x000044c0 , 0x00008980 }, { 0x00009e00 , 0x0372131c , 0x0372131c }, { 0x0000a230 , 0x0000000b , 0x00000016 }, { 0x0000a254 , 0x00000898 , 0x00001130 }, }; static const u_int32_t ar9300_ar9580_1p0_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x00009e3c , 0xcf946221 , 0xcf946221 , 0xcf946221 , 0xcf946221 }, { 0x00009e44 , 0x005c0000 , 0x005c0000 , 0x005c0000 , 0x005c0000 }, { 0x0000a258 , 0x02020200 , 0x02020200 , 0x02020200 , 0x02020200 }, { 0x0000a25c , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a28c , 0x00011111 , 0x00011111 , 0x00011111 , 0x00011111 }, { 0x0000a2c4 , 0x00148d18 , 0x00148d18 , 0x00148d20 , 0x00148d20 }, { 0x0000a2d8 , 0xf999a801 , 0xf999a801 , 0xf999a80d , 0xf999a80d }, { 0x0000a50c , 0x0000c00a , 0x0000c00a , 0x0000c00a , 0x0000c00a }, { 0x0000a538 , 0x00038e8c , 0x00038e8c , 0x00038e8c , 0x00038e8c }, { 0x0000a53c , 0x0003cecc , 0x0003cecc , 0x0003cecc , 0x0003cecc }, { 0x0000a540 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 }, { 0x0000a544 , 0x00044edc , 0x00044edc , 0x00044edc , 0x00044edc }, { 0x0000a548 , 0x00048ede , 0x00048ede , 0x00048ede , 0x00048ede }, { 0x0000a54c , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e }, { 0x0000a550 , 0x00050f5e , 0x00050f5e , 0x00050f5e , 0x00050f5e }, { 0x0000a554 , 0x00054f9e , 0x00054f9e , 0x00054f9e , 0x00054f9e }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000be18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, }; static const u_int32_t ar9300_ar9580_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0001609c , 0x0dd08f29 , 0x0dd08f29 , 0x0b283f31 , 0x0b283f31 }, { 0x000160ac , 0xa4653c00 , 0xa4653c00 , 0x24652800 , 0x24652800 }, { 0x000160b0 , 0x03284f3e , 0x03284f3e , 0x05d08f20 , 0x05d08f20 }, { 0x0001610c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016140 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, { 0x0001650c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016540 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, { 0x0001690c , 0xc8000000 , 0xc0000000 , 0xc0000000 , 0xc0000000 }, { 0x00016940 , 0x10804008 , 0x10804008 , 0x50804008 , 0x50804008 }, }; static const u_int32_t ar9300_ar9580_1p0_baseband_core[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafe68e30 }, { 0x00009804 , 0xfd14e000 }, { 0x00009808 , 0x9c0a9f6b }, { 0x0000980c , 0x04900000 }, { 0x00009814 , 0x3280c00a }, { 0x00009818 , 0x00000000 }, { 0x0000981c , 0x00020028 }, { 0x00009834 , 0x6400a190 }, { 0x00009838 , 0x0108ecff }, { 0x0000983c , 0x14000600 }, { 0x00009880 , 0x201fff00 }, { 0x00009884 , 0x00001042 }, { 0x000098a4 , 0x00200400 }, { 0x000098b0 , 0x32840bbe }, { 0x000098d0 , 0x004b6a8e }, { 0x000098d4 , 0x00000820 }, { 0x000098dc , 0x00000000 }, { 0x000098f0 , 0x00000000 }, { 0x000098f4 , 0x00000000 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009c0c , 0x00000000 }, { 0x00009c10 , 0x00000000 }, { 0x00009c14 , 0x00046384 }, { 0x00009c18 , 0x05b6b440 }, { 0x00009c1c , 0x00b6b440 }, { 0x00009d00 , 0xc080a333 }, { 0x00009d04 , 0x40206c10 }, { 0x00009d08 , 0x009c4060 }, { 0x00009d0c , 0x9883800a }, { 0x00009d10 , 0x01834061 }, { 0x00009d14 , 0x00c0040b }, { 0x00009d18 , 0x00000000 }, { 0x00009e08 , 0x0038230c }, { 0x00009e24 , 0x990bb515 }, { 0x00009e28 , 0x0c6f0000 }, { 0x00009e30 , 0x06336f77 }, { 0x00009e34 , 0x6af6532f }, { 0x00009e38 , 0x0cc80c00 }, { 0x00009e40 , 0x0d261820 }, { 0x00009e4c , 0x00001004 }, { 0x00009e50 , 0x00ff03f1 }, { 0x00009e54 , 0x00000000 }, { 0x00009fc0 , 0x803e4788 }, { 0x00009fc4 , 0x0001efb5 }, { 0x00009fcc , 0x40000014 }, { 0x00009fd0 , 0x01193b93 }, { 0x0000a20c , 0x00000000 }, { 0x0000a220 , 0x00000000 }, { 0x0000a224 , 0x00000000 }, { 0x0000a228 , 0x10002310 }, { 0x0000a23c , 0x00000000 }, { 0x0000a244 , 0x0c000000 }, { 0x0000a2a0 , 0x00000001 }, { 0x0000a2c0 , 0x00000001 }, { 0x0000a2c8 , 0x00000000 }, { 0x0000a2cc , 0x18c43433 }, { 0x0000a2d4 , 0x00000000 }, { 0x0000a2ec , 0x00000000 }, { 0x0000a2f0 , 0x00000000 }, { 0x0000a2f4 , 0x00000000 }, { 0x0000a2f8 , 0x00000000 }, { 0x0000a344 , 0x00000000 }, { 0x0000a34c , 0x00000000 }, { 0x0000a350 , 0x0000a000 }, { 0x0000a364 , 0x00000000 }, { 0x0000a370 , 0x00000000 }, { 0x0000a390 , 0x00000001 }, { 0x0000a394 , 0x00000444 }, { 0x0000a398 , 0x001f0e0f }, { 0x0000a39c , 0x0075393f }, { 0x0000a3a0 , 0xb79f6427 }, { 0x0000a3a4 , 0x00000000 }, { 0x0000a3a8 , 0xaaaaaaaa }, { 0x0000a3ac , 0x3c466478 }, { 0x0000a3c0 , 0x20202020 }, { 0x0000a3c4 , 0x22222220 }, { 0x0000a3c8 , 0x20200020 }, { 0x0000a3cc , 0x20202020 }, { 0x0000a3d0 , 0x20202020 }, { 0x0000a3d4 , 0x20202020 }, { 0x0000a3d8 , 0x20202020 }, { 0x0000a3dc , 0x20202020 }, { 0x0000a3e0 , 0x20202020 }, { 0x0000a3e4 , 0x20202020 }, { 0x0000a3e8 , 0x20202020 }, { 0x0000a3ec , 0x20202020 }, { 0x0000a3f0 , 0x00000000 }, { 0x0000a3f4 , 0x00000000 }, { 0x0000a3f8 , 0x0c9bd380 }, { 0x0000a3fc , 0x000f0f01 }, { 0x0000a400 , 0x8fa91f01 }, { 0x0000a404 , 0x00000000 }, { 0x0000a408 , 0x0e79e5c6 }, { 0x0000a40c , 0x00820820 }, { 0x0000a414 , 0x1ce739ce }, { 0x0000a418 , 0x2d001dce }, { 0x0000a41c , 0x1ce739ce }, { 0x0000a420 , 0x000001ce }, { 0x0000a424 , 0x1ce739ce }, { 0x0000a428 , 0x000001ce }, { 0x0000a42c , 0x1ce739ce }, { 0x0000a430 , 0x1ce739ce }, { 0x0000a434 , 0x00000000 }, { 0x0000a438 , 0x00001801 }, { 0x0000a43c , 0x00100000 }, { 0x0000a440 , 0x00000000 }, { 0x0000a444 , 0x00000000 }, { 0x0000a448 , 0x05000080 }, { 0x0000a44c , 0x00000001 }, { 0x0000a450 , 0x00010000 }, { 0x0000a458 , 0x00000000 }, { 0x0000a640 , 0x00000000 }, { 0x0000a644 , 0x3fad9d74 }, { 0x0000a648 , 0x0048060a }, { 0x0000a64c , 0x00003c37 }, { 0x0000a670 , 0x03020100 }, { 0x0000a674 , 0x09080504 }, { 0x0000a678 , 0x0d0c0b0a }, { 0x0000a67c , 0x13121110 }, { 0x0000a680 , 0x31301514 }, { 0x0000a684 , 0x35343332 }, { 0x0000a688 , 0x00000036 }, { 0x0000a690 , 0x00000838 }, { 0x0000a7c0 , 0x00000000 }, { 0x0000a7c4 , 0xfffffffc }, { 0x0000a7c8 , 0x00000000 }, { 0x0000a7cc , 0x00000000 }, { 0x0000a7d0 , 0x00000000 }, { 0x0000a7d4 , 0x00000004 }, { 0x0000a7dc , 0x00000000 }, { 0x0000a8d0 , 0x004b6a8e }, { 0x0000a8d4 , 0x00000820 }, { 0x0000a8dc , 0x00000000 }, { 0x0000a8f0 , 0x00000000 }, { 0x0000a8f4 , 0x00000000 }, { 0x0000b2d0 , 0x00000080 }, { 0x0000b2d4 , 0x00000000 }, { 0x0000b2ec , 0x00000000 }, { 0x0000b2f0 , 0x00000000 }, { 0x0000b2f4 , 0x00000000 }, { 0x0000b2f8 , 0x00000000 }, { 0x0000b408 , 0x0e79e5c0 }, { 0x0000b40c , 0x00820820 }, { 0x0000b420 , 0x00000000 }, { 0x0000b8d0 , 0x004b6a8e }, { 0x0000b8d4 , 0x00000820 }, { 0x0000b8dc , 0x00000000 }, { 0x0000b8f0 , 0x00000000 }, { 0x0000b8f4 , 0x00000000 }, { 0x0000c2d0 , 0x00000080 }, { 0x0000c2d4 , 0x00000000 }, { 0x0000c2ec , 0x00000000 }, { 0x0000c2f0 , 0x00000000 }, { 0x0000c2f4 , 0x00000000 }, { 0x0000c2f8 , 0x00000000 }, { 0x0000c408 , 0x0e79e5c0 }, { 0x0000c40c , 0x00820820 }, { 0x0000c420 , 0x00000000 }, }; static const u_int32_t ar9300_ar9580_1p0_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00001030 , 0x00000230 , 0x00000460 , 0x000002c0 , 0x00000160 }, { 0x00001070 , 0x00000168 , 0x000002d0 , 0x00000318 , 0x0000018c }, { 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 }, { 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 }, { 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b }, - { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 }, + { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 }, { 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a }, { 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 }, }; static const u_int32_t ar9300Modes_low_ob_db_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5c82486b , 0x5c82486b , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x61824a6c , 0x61824a6c , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x66826a6c , 0x66826a6c , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x6b826e6c , 0x6b826e6c , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x7082708c , 0x7082708c , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x7382b08a , 0x7382b08a , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x66480001 , 0x66480001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300Modes_high_power_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x15000028 , 0x15000028 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1b00002b , 0x1b00002b , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x1f020028 , 0x1f020028 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x2502002b , 0x2502002b , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2a04002a , 0x2a04002a , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2e06002a , 0x2e06002a , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x3302202d , 0x3302202d , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3804202c , 0x3804202c , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3c06202c , 0x3c06202c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4108202d , 0x4108202d , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4506402d , 0x4506402d , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4906222d , 0x4906222d , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4d062231 , 0x4d062231 , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x50082231 , 0x50082231 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5608422e , 0x5608422e , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5e08442e , 0x5e08442e , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x620a4431 , 0x620a4431 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x640a4432 , 0x640a4432 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x680a4434 , 0x680a4434 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x6c0a6434 , 0x6c0a6434 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6f0a6633 , 0x6f0a6633 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x15800028 , 0x15800028 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1b80002b , 0x1b80002b , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x1f820028 , 0x1f820028 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x2582002b , 0x2582002b , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2a84002a , 0x2a84002a , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2e86002a , 0x2e86002a , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x3382202d , 0x3382202d , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3884202c , 0x3884202c , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3c86202c , 0x3c86202c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4188202d , 0x4188202d , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4586402d , 0x4586402d , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4986222d , 0x4986222d , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4d862231 , 0x4d862231 , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x50882231 , 0x50882231 , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5688422e , 0x5688422e , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5a88442e , 0x5a88442e , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x5e8a4431 , 0x5e8a4431 , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x648a4432 , 0x648a4432 , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x688a4434 , 0x688a4434 , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x6c8a6434 , 0x6c8a6434 , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x6f8a6633 , 0x6f8a6633 , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x738c6634 , 0x738c6634 , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01804601 , 0x01804601 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01804601 , 0x01804601 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x01804601 , 0x01804601 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x03408d02 , 0x03408d02 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x03410d04 , 0x03410d04 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016288 , 0x05a2040a , 0x05a2040a , 0x05a20408 , 0x05a20408 }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300Common_rx_gain_table_merlin_1p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x02000101 }, { 0x0000a004 , 0x02000102 }, { 0x0000a008 , 0x02000103 }, { 0x0000a00c , 0x02000104 }, { 0x0000a010 , 0x02000200 }, { 0x0000a014 , 0x02000201 }, { 0x0000a018 , 0x02000202 }, { 0x0000a01c , 0x02000203 }, { 0x0000a020 , 0x02000204 }, { 0x0000a024 , 0x02000205 }, { 0x0000a028 , 0x02000208 }, { 0x0000a02c , 0x02000302 }, { 0x0000a030 , 0x02000303 }, { 0x0000a034 , 0x02000304 }, { 0x0000a038 , 0x02000400 }, { 0x0000a03c , 0x02010300 }, { 0x0000a040 , 0x02010301 }, { 0x0000a044 , 0x02010302 }, { 0x0000a048 , 0x02000500 }, { 0x0000a04c , 0x02010400 }, { 0x0000a050 , 0x02020300 }, { 0x0000a054 , 0x02020301 }, { 0x0000a058 , 0x02020302 }, { 0x0000a05c , 0x02020303 }, { 0x0000a060 , 0x02020400 }, { 0x0000a064 , 0x02030300 }, { 0x0000a068 , 0x02030301 }, { 0x0000a06c , 0x02030302 }, { 0x0000a070 , 0x02030303 }, { 0x0000a074 , 0x02030400 }, { 0x0000a078 , 0x02040300 }, { 0x0000a07c , 0x02040301 }, { 0x0000a080 , 0x02040302 }, { 0x0000a084 , 0x02040303 }, { 0x0000a088 , 0x02030500 }, { 0x0000a08c , 0x02040400 }, { 0x0000a090 , 0x02050203 }, { 0x0000a094 , 0x02050204 }, { 0x0000a098 , 0x02050205 }, { 0x0000a09c , 0x02040500 }, { 0x0000a0a0 , 0x02050301 }, { 0x0000a0a4 , 0x02050302 }, { 0x0000a0a8 , 0x02050303 }, { 0x0000a0ac , 0x02050400 }, { 0x0000a0b0 , 0x02050401 }, { 0x0000a0b4 , 0x02050402 }, { 0x0000a0b8 , 0x02050403 }, { 0x0000a0bc , 0x02050500 }, { 0x0000a0c0 , 0x02050501 }, { 0x0000a0c4 , 0x02050502 }, { 0x0000a0c8 , 0x02050503 }, { 0x0000a0cc , 0x02050504 }, { 0x0000a0d0 , 0x02050600 }, { 0x0000a0d4 , 0x02050601 }, { 0x0000a0d8 , 0x02050602 }, { 0x0000a0dc , 0x02050603 }, { 0x0000a0e0 , 0x02050604 }, { 0x0000a0e4 , 0x02050700 }, { 0x0000a0e8 , 0x02050701 }, { 0x0000a0ec , 0x02050702 }, { 0x0000a0f0 , 0x02050703 }, { 0x0000a0f4 , 0x02050704 }, { 0x0000a0f8 , 0x02050705 }, { 0x0000a0fc , 0x02050708 }, { 0x0000a100 , 0x02050709 }, { 0x0000a104 , 0x0205070a }, { 0x0000a108 , 0x0205070b }, { 0x0000a10c , 0x0205070c }, { 0x0000a110 , 0x0205070d }, { 0x0000a114 , 0x02050710 }, { 0x0000a118 , 0x02050711 }, { 0x0000a11c , 0x02050712 }, { 0x0000a120 , 0x02050713 }, { 0x0000a124 , 0x02050714 }, { 0x0000a128 , 0x02050715 }, { 0x0000a12c , 0x02050730 }, { 0x0000a130 , 0x02050731 }, { 0x0000a134 , 0x02050732 }, { 0x0000a138 , 0x02050733 }, { 0x0000a13c , 0x02050734 }, { 0x0000a140 , 0x02050735 }, { 0x0000a144 , 0x02050750 }, { 0x0000a148 , 0x02050751 }, { 0x0000a14c , 0x02050752 }, { 0x0000a150 , 0x02050753 }, { 0x0000a154 , 0x02050754 }, { 0x0000a158 , 0x02050755 }, { 0x0000a15c , 0x02050770 }, { 0x0000a160 , 0x02050771 }, { 0x0000a164 , 0x02050772 }, { 0x0000a168 , 0x02050773 }, { 0x0000a16c , 0x02050774 }, { 0x0000a170 , 0x02050775 }, { 0x0000a174 , 0x00000776 }, { 0x0000a178 , 0x00000776 }, { 0x0000a17c , 0x00000776 }, { 0x0000a180 , 0x00000776 }, { 0x0000a184 , 0x00000776 }, { 0x0000a188 , 0x00000776 }, { 0x0000a18c , 0x00000776 }, { 0x0000a190 , 0x00000776 }, { 0x0000a194 , 0x00000776 }, { 0x0000a198 , 0x00000776 }, { 0x0000a19c , 0x00000776 }, { 0x0000a1a0 , 0x00000776 }, { 0x0000a1a4 , 0x00000776 }, { 0x0000a1a8 , 0x00000776 }, { 0x0000a1ac , 0x00000776 }, { 0x0000a1b0 , 0x00000776 }, { 0x0000a1b4 , 0x00000776 }, { 0x0000a1b8 , 0x00000776 }, { 0x0000a1bc , 0x00000776 }, { 0x0000a1c0 , 0x00000776 }, { 0x0000a1c4 , 0x00000776 }, { 0x0000a1c8 , 0x00000776 }, { 0x0000a1cc , 0x00000776 }, { 0x0000a1d0 , 0x00000776 }, { 0x0000a1d4 , 0x00000776 }, { 0x0000a1d8 , 0x00000776 }, { 0x0000a1dc , 0x00000776 }, { 0x0000a1e0 , 0x00000776 }, { 0x0000a1e4 , 0x00000776 }, { 0x0000a1e8 , 0x00000776 }, { 0x0000a1ec , 0x00000776 }, { 0x0000a1f0 , 0x00000776 }, { 0x0000a1f4 , 0x00000776 }, { 0x0000a1f8 , 0x00000776 }, { 0x0000a1fc , 0x00000776 }, { 0x0000b000 , 0x02000101 }, { 0x0000b004 , 0x02000102 }, { 0x0000b008 , 0x02000103 }, { 0x0000b00c , 0x02000104 }, { 0x0000b010 , 0x02000200 }, { 0x0000b014 , 0x02000201 }, { 0x0000b018 , 0x02000202 }, { 0x0000b01c , 0x02000203 }, { 0x0000b020 , 0x02000204 }, { 0x0000b024 , 0x02000205 }, { 0x0000b028 , 0x02000208 }, { 0x0000b02c , 0x02000302 }, { 0x0000b030 , 0x02000303 }, { 0x0000b034 , 0x02000304 }, { 0x0000b038 , 0x02000400 }, { 0x0000b03c , 0x02010300 }, { 0x0000b040 , 0x02010301 }, { 0x0000b044 , 0x02010302 }, { 0x0000b048 , 0x02000500 }, { 0x0000b04c , 0x02010400 }, { 0x0000b050 , 0x02020300 }, { 0x0000b054 , 0x02020301 }, { 0x0000b058 , 0x02020302 }, { 0x0000b05c , 0x02020303 }, { 0x0000b060 , 0x02020400 }, { 0x0000b064 , 0x02030300 }, { 0x0000b068 , 0x02030301 }, { 0x0000b06c , 0x02030302 }, { 0x0000b070 , 0x02030303 }, { 0x0000b074 , 0x02030400 }, { 0x0000b078 , 0x02040300 }, { 0x0000b07c , 0x02040301 }, { 0x0000b080 , 0x02040302 }, { 0x0000b084 , 0x02040303 }, { 0x0000b088 , 0x02030500 }, { 0x0000b08c , 0x02040400 }, { 0x0000b090 , 0x02050203 }, { 0x0000b094 , 0x02050204 }, { 0x0000b098 , 0x02050205 }, { 0x0000b09c , 0x02040500 }, { 0x0000b0a0 , 0x02050301 }, { 0x0000b0a4 , 0x02050302 }, { 0x0000b0a8 , 0x02050303 }, { 0x0000b0ac , 0x02050400 }, { 0x0000b0b0 , 0x02050401 }, { 0x0000b0b4 , 0x02050402 }, { 0x0000b0b8 , 0x02050403 }, { 0x0000b0bc , 0x02050500 }, { 0x0000b0c0 , 0x02050501 }, { 0x0000b0c4 , 0x02050502 }, { 0x0000b0c8 , 0x02050503 }, { 0x0000b0cc , 0x02050504 }, { 0x0000b0d0 , 0x02050600 }, { 0x0000b0d4 , 0x02050601 }, { 0x0000b0d8 , 0x02050602 }, { 0x0000b0dc , 0x02050603 }, { 0x0000b0e0 , 0x02050604 }, { 0x0000b0e4 , 0x02050700 }, { 0x0000b0e8 , 0x02050701 }, { 0x0000b0ec , 0x02050702 }, { 0x0000b0f0 , 0x02050703 }, { 0x0000b0f4 , 0x02050704 }, { 0x0000b0f8 , 0x02050705 }, { 0x0000b0fc , 0x02050708 }, { 0x0000b100 , 0x02050709 }, { 0x0000b104 , 0x0205070a }, { 0x0000b108 , 0x0205070b }, { 0x0000b10c , 0x0205070c }, { 0x0000b110 , 0x0205070d }, { 0x0000b114 , 0x02050710 }, { 0x0000b118 , 0x02050711 }, { 0x0000b11c , 0x02050712 }, { 0x0000b120 , 0x02050713 }, { 0x0000b124 , 0x02050714 }, { 0x0000b128 , 0x02050715 }, { 0x0000b12c , 0x02050730 }, { 0x0000b130 , 0x02050731 }, { 0x0000b134 , 0x02050732 }, { 0x0000b138 , 0x02050733 }, { 0x0000b13c , 0x02050734 }, { 0x0000b140 , 0x02050735 }, { 0x0000b144 , 0x02050750 }, { 0x0000b148 , 0x02050751 }, { 0x0000b14c , 0x02050752 }, { 0x0000b150 , 0x02050753 }, { 0x0000b154 , 0x02050754 }, { 0x0000b158 , 0x02050755 }, { 0x0000b15c , 0x02050770 }, { 0x0000b160 , 0x02050771 }, { 0x0000b164 , 0x02050772 }, { 0x0000b168 , 0x02050773 }, { 0x0000b16c , 0x02050774 }, { 0x0000b170 , 0x02050775 }, { 0x0000b174 , 0x00000776 }, { 0x0000b178 , 0x00000776 }, { 0x0000b17c , 0x00000776 }, { 0x0000b180 , 0x00000776 }, { 0x0000b184 , 0x00000776 }, { 0x0000b188 , 0x00000776 }, { 0x0000b18c , 0x00000776 }, { 0x0000b190 , 0x00000776 }, { 0x0000b194 , 0x00000776 }, { 0x0000b198 , 0x00000776 }, { 0x0000b19c , 0x00000776 }, { 0x0000b1a0 , 0x00000776 }, { 0x0000b1a4 , 0x00000776 }, { 0x0000b1a8 , 0x00000776 }, { 0x0000b1ac , 0x00000776 }, { 0x0000b1b0 , 0x00000776 }, { 0x0000b1b4 , 0x00000776 }, { 0x0000b1b8 , 0x00000776 }, { 0x0000b1bc , 0x00000776 }, { 0x0000b1c0 , 0x00000776 }, { 0x0000b1c4 , 0x00000776 }, { 0x0000b1c8 , 0x00000776 }, { 0x0000b1cc , 0x00000776 }, { 0x0000b1d0 , 0x00000776 }, { 0x0000b1d4 , 0x00000776 }, { 0x0000b1d8 , 0x00000776 }, { 0x0000b1dc , 0x00000776 }, { 0x0000b1e0 , 0x00000776 }, { 0x0000b1e4 , 0x00000776 }, { 0x0000b1e8 , 0x00000776 }, { 0x0000b1ec , 0x00000776 }, { 0x0000b1f0 , 0x00000776 }, { 0x0000b1f4 , 0x00000776 }, { 0x0000b1f8 , 0x00000776 }, { 0x0000b1fc , 0x00000776 }, }; static const u_int32_t ar9300_modes_type5_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x15000028 , 0x15000028 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1b00002b , 0x1b00002b , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x1f020028 , 0x1f020028 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x2502002b , 0x2502002b , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2a04002a , 0x2a04002a , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2e06002a , 0x2e06002a , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x3302202d , 0x3302202d , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3804202c , 0x3804202c , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3c06202c , 0x3c06202c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4108202d , 0x4108202d , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4506402d , 0x4506402d , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4906222d , 0x4906222d , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4d062231 , 0x4d062231 , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x50082231 , 0x50082231 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5608422e , 0x5608422e , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5e08442e , 0x5e08442e , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x620a4431 , 0x620a4431 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x640a4432 , 0x640a4432 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x680a4434 , 0x680a4434 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x6c0a6434 , 0x6c0a6434 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6f0a6633 , 0x6f0a6633 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01804601 , 0x01804601 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01804601 , 0x01804601 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x01804601 , 0x01804601 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x03408d02 , 0x03408d02 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x03410d04 , 0x03410d04 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x65240001 , 0x65240001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x5d001eec , 0x5d001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x12800400 , 0x12800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x16800402 , 0x16800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1c800603 , 0x1c800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x21800a02 , 0x21800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x25800a04 , 0x25800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x28800a20 , 0x28800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2c800e20 , 0x2c800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x30800e22 , 0x30800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x34800e24 , 0x34800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x38801640 , 0x38801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x3c801660 , 0x3c801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3f801861 , 0x3f801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x43801a81 , 0x43801a81 }, { 0x0000a5cc , 0x5c82486b , 0x5c82486b , 0x47801a83 , 0x47801a83 }, { 0x0000a5d0 , 0x61824a6c , 0x61824a6c , 0x4a801c84 , 0x4a801c84 }, { 0x0000a5d4 , 0x66826a6c , 0x66826a6c , 0x4e801ce3 , 0x4e801ce3 }, { 0x0000a5d8 , 0x6b826e6c , 0x6b826e6c , 0x52801ce5 , 0x52801ce5 }, { 0x0000a5dc , 0x7082708c , 0x7082708c , 0x56801ce9 , 0x56801ce9 }, { 0x0000a5e0 , 0x7382b08a , 0x7382b08a , 0x5a801ceb , 0x5a801ceb }, { 0x0000a5e4 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5e8 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5ec , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f0 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f4 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5f8 , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a5fc , 0x7782b08c , 0x7782b08c , 0x5d801eec , 0x5d801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x62480001 , 0x62480001 , 0x62480001 , 0x62480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { /* Addr allmodes */ { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x6f7f0301 }, { 0x0000a3a0 , 0xca9228ee }, }; static const u_int32_t ar9300_ar9580_1p0_mac_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00008014 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 }, { 0x0000801c , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 }, }; static const u_int32_t ar9200_merlin_1p0_radio_core[][2] = { /* Addr common */ { 0x00007800 , 0x00040000 }, { 0x00007804 , 0xdb005012 }, { 0x00007808 , 0x04924914 }, { 0x0000780c , 0x21084210 }, { 0x00007810 , 0x6d801300 }, { 0x00007814 , 0x0019beff }, { 0x00007818 , 0x07e41000 }, { 0x0000781c , 0x00392000 }, { 0x00007820 , 0x92592480 }, { 0x00007824 , 0x00040000 }, { 0x00007828 , 0xdb005012 }, { 0x0000782c , 0x04924914 }, { 0x00007830 , 0x21084210 }, { 0x00007834 , 0x6d801300 }, { 0x00007838 , 0x0019beff }, { 0x0000783c , 0x07e40000 }, { 0x00007840 , 0x00392000 }, { 0x00007844 , 0x92592480 }, { 0x00007848 , 0x00100000 }, { 0x0000784c , 0x773f0567 }, { 0x00007850 , 0x54214514 }, { 0x00007854 , 0x12035828 }, { 0x00007858 , 0x92592692 }, { 0x0000785c , 0x00000000 }, { 0x00007860 , 0x56400000 }, { 0x00007864 , 0x0a8e370e }, { 0x00007868 , 0xc0102850 }, { 0x0000786c , 0x812d4000 }, { 0x00007870 , 0x807ec400 }, { 0x00007874 , 0x001b6db0 }, { 0x00007878 , 0x00376b63 }, { 0x0000787c , 0x06db6db6 }, { 0x00007880 , 0x006d8000 }, { 0x00007884 , 0xffeffffe }, { 0x00007888 , 0xffeffffe }, { 0x0000788c , 0x00010000 }, { 0x00007890 , 0x02060aeb }, { 0x00007894 , 0x5a108000 }, }; static const u_int32_t ar9300_ar9580_1p0_tx_gain_table_baseband_postamble_emulation[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a410 , 0x000000d5 , 0x000000d5 , 0x000000d5 , 0x000000d5 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x00004002 , 0x00004002 , 0x00004002 , 0x00004002 }, { 0x0000a508 , 0x00008004 , 0x00008004 , 0x00008004 , 0x00008004 }, { 0x0000a510 , 0x0001000c , 0x0001000c , 0x0001000c , 0x0001000c }, { 0x0000a514 , 0x0001420b , 0x0001420b , 0x0001420b , 0x0001420b }, { 0x0000a518 , 0x0001824a , 0x0001824a , 0x0001824a , 0x0001824a }, { 0x0000a51c , 0x0001c44a , 0x0001c44a , 0x0001c44a , 0x0001c44a }, { 0x0000a520 , 0x0002064a , 0x0002064a , 0x0002064a , 0x0002064a }, { 0x0000a524 , 0x0002484a , 0x0002484a , 0x0002484a , 0x0002484a }, { 0x0000a528 , 0x00028a4a , 0x00028a4a , 0x00028a4a , 0x00028a4a }, { 0x0000a52c , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a }, { 0x0000a530 , 0x00030e4a , 0x00030e4a , 0x00030e4a , 0x00030e4a }, { 0x0000a534 , 0x00034e8a , 0x00034e8a , 0x00034e8a , 0x00034e8a }, }; static const u_int32_t ar9300_ar9580_1p0_mac_core[][2] = { /* Addr allmodes */ { 0x00000008 , 0x00000000 }, { 0x00000030 , 0x00020085 }, { 0x00000034 , 0x00000005 }, { 0x00000040 , 0x00000000 }, { 0x00000044 , 0x00000000 }, { 0x00000048 , 0x00000008 }, { 0x0000004c , 0x00000010 }, { 0x00000050 , 0x00000000 }, { 0x00001040 , 0x002ffc0f }, { 0x00001044 , 0x002ffc0f }, { 0x00001048 , 0x002ffc0f }, { 0x0000104c , 0x002ffc0f }, { 0x00001050 , 0x002ffc0f }, { 0x00001054 , 0x002ffc0f }, { 0x00001058 , 0x002ffc0f }, { 0x0000105c , 0x002ffc0f }, { 0x00001060 , 0x002ffc0f }, { 0x00001064 , 0x002ffc0f }, { 0x000010f0 , 0x00000100 }, { 0x00001270 , 0x00000000 }, { 0x000012b0 , 0x00000000 }, { 0x000012f0 , 0x00000000 }, { 0x0000143c , 0x00000000 }, { 0x0000147c , 0x00000000 }, { 0x00008000 , 0x00000000 }, { 0x00008004 , 0x00000000 }, { 0x00008008 , 0x00000000 }, { 0x0000800c , 0x00000000 }, { 0x00008018 , 0x00000000 }, { 0x00008020 , 0x00000000 }, { 0x00008038 , 0x00000000 }, { 0x0000803c , 0x00000000 }, { 0x00008040 , 0x00000000 }, { 0x00008044 , 0x00000000 }, { 0x00008048 , 0x00000000 }, { 0x0000804c , 0xffffffff }, { 0x00008054 , 0x00000000 }, { 0x00008058 , 0x00000000 }, { 0x0000805c , 0x000fc78f }, { 0x00008060 , 0x0000000f }, { 0x00008064 , 0x00000000 }, { 0x00008070 , 0x00000310 }, { 0x00008074 , 0x00000020 }, { 0x00008078 , 0x00000000 }, { 0x0000809c , 0x0000000f }, { 0x000080a0 , 0x00000000 }, { 0x000080a4 , 0x02ff0000 }, { 0x000080a8 , 0x0e070605 }, { 0x000080ac , 0x0000000d }, { 0x000080b0 , 0x00000000 }, { 0x000080b4 , 0x00000000 }, { 0x000080b8 , 0x00000000 }, { 0x000080bc , 0x00000000 }, { 0x000080c0 , 0x2a800000 }, { 0x000080c4 , 0x06900168 }, { 0x000080c8 , 0x13881c22 }, { 0x000080cc , 0x01f40000 }, { 0x000080d0 , 0x00252500 }, { 0x000080d4 , 0x00a00000 }, { 0x000080d8 , 0x00400000 }, { 0x000080dc , 0x00000000 }, { 0x000080e0 , 0xffffffff }, { 0x000080e4 , 0x0000ffff }, { 0x000080e8 , 0x3f3f3f3f }, { 0x000080ec , 0x00000000 }, { 0x000080f0 , 0x00000000 }, { 0x000080f4 , 0x00000000 }, { 0x000080fc , 0x00020000 }, { 0x00008100 , 0x00000000 }, { 0x00008108 , 0x00000052 }, { 0x0000810c , 0x00000000 }, { 0x00008110 , 0x00000000 }, { 0x00008114 , 0x000007ff }, { 0x00008118 , 0x000000aa }, { 0x0000811c , 0x00003210 }, { 0x00008124 , 0x00000000 }, { 0x00008128 , 0x00000000 }, { 0x0000812c , 0x00000000 }, { 0x00008130 , 0x00000000 }, { 0x00008134 , 0x00000000 }, { 0x00008138 , 0x00000000 }, { 0x0000813c , 0x0000ffff }, { 0x00008144 , 0xffffffff }, { 0x00008168 , 0x00000000 }, { 0x0000816c , 0x00000000 }, { 0x000081c0 , 0x00000000 }, { 0x000081c4 , 0x33332210 }, { 0x000081ec , 0x00000000 }, { 0x000081f0 , 0x00000000 }, { 0x000081f4 , 0x00000000 }, { 0x000081f8 , 0x00000000 }, { 0x000081fc , 0x00000000 }, { 0x00008240 , 0x00100000 }, { 0x00008244 , 0x0010f400 }, { 0x00008248 , 0x00000800 }, { 0x0000824c , 0x0001e800 }, { 0x00008250 , 0x00000000 }, { 0x00008254 , 0x00000000 }, { 0x00008258 , 0x00000000 }, { 0x0000825c , 0x40000000 }, { 0x00008260 , 0x00080922 }, - { 0x00008264 , 0x9bc00010 }, + { 0x00008264 , 0x9d400010 }, { 0x00008268 , 0xffffffff }, { 0x0000826c , 0x0000ffff }, { 0x00008270 , 0x00000000 }, { 0x00008274 , 0x40000000 }, { 0x00008278 , 0x003e4180 }, { 0x0000827c , 0x00000004 }, { 0x00008284 , 0x0000002c }, { 0x00008288 , 0x0000002c }, { 0x0000828c , 0x000000ff }, { 0x00008294 , 0x00000000 }, { 0x00008298 , 0x00000000 }, { 0x0000829c , 0x00000000 }, { 0x00008300 , 0x00000140 }, { 0x00008314 , 0x00000000 }, { 0x0000831c , 0x0000010d }, { 0x00008328 , 0x00000000 }, { 0x0000832c , 0x00000007 }, { 0x00008330 , 0x00000302 }, { 0x00008334 , 0x00000700 }, { 0x00008338 , 0x00ff0000 }, { 0x0000833c , 0x02400000 }, { 0x00008340 , 0x000107ff }, { 0x00008344 , 0xaa48105b }, { 0x00008348 , 0x008f0000 }, { 0x0000835c , 0x00000000 }, { 0x00008360 , 0xffffffff }, { 0x00008364 , 0xffffffff }, { 0x00008368 , 0x00000000 }, { 0x00008370 , 0x00000000 }, { 0x00008374 , 0x000000ff }, { 0x00008378 , 0x00000000 }, { 0x0000837c , 0x00000000 }, { 0x00008380 , 0xffffffff }, { 0x00008384 , 0xffffffff }, { 0x00008390 , 0xffffffff }, { 0x00008394 , 0xffffffff }, { 0x00008398 , 0x00000000 }, { 0x0000839c , 0x00000000 }, { 0x000083a0 , 0x00000000 }, { 0x000083a4 , 0x0000fa14 }, { 0x000083a8 , 0x000f0c00 }, { 0x000083ac , 0x33332210 }, { 0x000083b0 , 0x33332210 }, { 0x000083b4 , 0x33332210 }, { 0x000083b8 , 0x33332210 }, { 0x000083bc , 0x00000000 }, { 0x000083c0 , 0x00000000 }, { 0x000083c4 , 0x00000000 }, { 0x000083c8 , 0x00000000 }, { 0x000083cc , 0x00000200 }, { 0x000083d0 , 0x000301ff }, }; static const u_int32_t ar9300_modes_mixed_ob_db_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x21002220 , 0x21002220 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x27002223 , 0x27002223 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x34022225 , 0x34022225 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x4202242a , 0x4202242a , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x4702244a , 0x4702244a , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x5702286c , 0x5702286c , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x5c02486b , 0x5c02486b , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x61024a6c , 0x61024a6c , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x66026a6c , 0x66026a6c , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6b026e6c , 0x6b026e6c , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x7002708c , 0x7002708c , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x7302b08a , 0x7302b08a , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x7702b08c , 0x7702b08c , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x06800003 , 0x06800003 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x0a800020 , 0x0a800020 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x10800023 , 0x10800023 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x16800220 , 0x16800220 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x1c800223 , 0x1c800223 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x21802220 , 0x21802220 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x27802223 , 0x27802223 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x2b822220 , 0x2b822220 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2f822222 , 0x2f822222 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x34822225 , 0x34822225 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x3a82222a , 0x3a82222a , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x3e82222c , 0x3e82222c , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x4282242a , 0x4282242a , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x4782244a , 0x4782244a , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x4b82244c , 0x4b82244c , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x4e82246c , 0x4e82246c , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x5382266c , 0x5382266c , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x5782286c , 0x5782286c , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x5c82486b , 0x5c82486b , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x61824a6c , 0x61824a6c , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x66826a6c , 0x66826a6c , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6b826e6c , 0x6b826e6c , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x7082708c , 0x7082708c , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x7382b08a , 0x7382b08a , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x7782b08c , 0x7782b08c , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01404000 , 0x01404000 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01404501 , 0x01404501 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x02008802 , 0x02008802 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x0300cc03 , 0x0300cc03 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x0300cc03 , 0x0300cc03 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03810c03 , 0x03810c03 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03810e04 , 0x03810e04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x0380c7fc , 0x0380c7fc , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0000f800 , 0x0000f800 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03ff0000 , 0x03ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016048 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016448 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016848 , 0x66480001 , 0x66480001 , 0x8e480001 , 0x8e480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_ar9580_1p0_mac_core_emulation[][2] = { /* Addr allmodes */ { 0x00000030 , 0x00020085 }, { 0x00000044 , 0x00000008 }, { 0x0000805c , 0xffffc7ff }, { 0x00008344 , 0xaa4a105b }, }; static const u_int32_t ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x03820190 }, { 0x0000a030 , 0x03840383 }, { 0x0000a034 , 0x03880385 }, { 0x0000a038 , 0x038a0389 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x29292929 }, { 0x0000a084 , 0x29292929 }, { 0x0000a088 , 0x29292929 }, { 0x0000a08c , 0x29292929 }, { 0x0000a090 , 0x22292929 }, { 0x0000a094 , 0x1d1d2222 }, { 0x0000a098 , 0x0c111117 }, { 0x0000a09c , 0x00030303 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x32323232 }, { 0x0000b084 , 0x2f2f3232 }, { 0x0000b088 , 0x23282a2d }, { 0x0000b08c , 0x1c1e2123 }, { 0x0000b090 , 0x14171919 }, { 0x0000b094 , 0x0e0e1214 }, { 0x0000b098 , 0x03050707 }, { 0x0000b09c , 0x00030303 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; static const u_int32_t ar9300_ar9580_1p0_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00007010 , 0x00000023 , 0x00000023 , 0x00000023 , 0x00000023 }, }; static const u_int32_t ar9300_modes_type6_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x15000028 , 0x15000028 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x1b00002b , 0x1b00002b , 0x12000400 , 0x12000400 }, { 0x0000a518 , 0x1f020028 , 0x1f020028 , 0x16000402 , 0x16000402 }, { 0x0000a51c , 0x2502002b , 0x2502002b , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x2a04002a , 0x2a04002a , 0x1c000603 , 0x1c000603 }, { 0x0000a524 , 0x2e06002a , 0x2e06002a , 0x21000a02 , 0x21000a02 }, { 0x0000a528 , 0x3302202d , 0x3302202d , 0x25000a04 , 0x25000a04 }, { 0x0000a52c , 0x3804202c , 0x3804202c , 0x28000a20 , 0x28000a20 }, { 0x0000a530 , 0x3c06202c , 0x3c06202c , 0x2c000e20 , 0x2c000e20 }, { 0x0000a534 , 0x4108202d , 0x4108202d , 0x30000e22 , 0x30000e22 }, { 0x0000a538 , 0x4506402d , 0x4506402d , 0x34000e24 , 0x34000e24 }, { 0x0000a53c , 0x4906222d , 0x4906222d , 0x38001640 , 0x38001640 }, { 0x0000a540 , 0x4d062231 , 0x4d062231 , 0x3c001660 , 0x3c001660 }, { 0x0000a544 , 0x50082231 , 0x50082231 , 0x3f001861 , 0x3f001861 }, { 0x0000a548 , 0x5608422e , 0x5608422e , 0x43001a81 , 0x43001a81 }, { 0x0000a54c , 0x5e08442e , 0x5e08442e , 0x47001a83 , 0x47001a83 }, { 0x0000a550 , 0x620a4431 , 0x620a4431 , 0x4a001c84 , 0x4a001c84 }, { 0x0000a554 , 0x640a4432 , 0x640a4432 , 0x4e001ce3 , 0x4e001ce3 }, { 0x0000a558 , 0x680a4434 , 0x680a4434 , 0x52001ce5 , 0x52001ce5 }, { 0x0000a55c , 0x6c0a6434 , 0x6c0a6434 , 0x56001ce9 , 0x56001ce9 }, { 0x0000a560 , 0x6f0a6633 , 0x6f0a6633 , 0x5a001ceb , 0x5a001ceb }, { 0x0000a564 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a568 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a56c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a570 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a574 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a578 , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a57c , 0x730c6634 , 0x730c6634 , 0x5d001eec , 0x5d001eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x01804601 , 0x01804601 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x01804601 , 0x01804601 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x01804601 , 0x01804601 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x01804601 , 0x01804601 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x03408d02 , 0x03408d02 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x0300cc03 , 0x0300cc03 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x03410d04 , 0x03410d04 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x03410d04 , 0x03410d04 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x000cfff0 , 0x000cfff0 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x000f0000 , 0x000f0000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x03f00000 , 0x03f00000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016048 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016448 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x012492d4 , 0x012492d4 , 0x012492d4 , 0x012492d4 }, { 0x00016848 , 0x61200001 , 0x61200001 , 0x66480001 , 0x66480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300Modes_high_ob_db_tx_gain_table_ar9580_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x0000a2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000a2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000a2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000a2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000a410 , 0x000050d4 , 0x000050d4 , 0x000050d9 , 0x000050d9 }, { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 }, { 0x0000a504 , 0x04002222 , 0x04002222 , 0x04000002 , 0x04000002 }, { 0x0000a508 , 0x09002421 , 0x09002421 , 0x08000004 , 0x08000004 }, { 0x0000a50c , 0x0d002621 , 0x0d002621 , 0x0b000200 , 0x0b000200 }, { 0x0000a510 , 0x13004620 , 0x13004620 , 0x0f000202 , 0x0f000202 }, { 0x0000a514 , 0x19004a20 , 0x19004a20 , 0x11000400 , 0x11000400 }, { 0x0000a518 , 0x1d004e20 , 0x1d004e20 , 0x15000402 , 0x15000402 }, { 0x0000a51c , 0x21005420 , 0x21005420 , 0x19000404 , 0x19000404 }, { 0x0000a520 , 0x26005e20 , 0x26005e20 , 0x1b000603 , 0x1b000603 }, { 0x0000a524 , 0x2b005e40 , 0x2b005e40 , 0x1f000a02 , 0x1f000a02 }, { 0x0000a528 , 0x2f005e42 , 0x2f005e42 , 0x23000a04 , 0x23000a04 }, { 0x0000a52c , 0x33005e44 , 0x33005e44 , 0x26000a20 , 0x26000a20 }, { 0x0000a530 , 0x38005e65 , 0x38005e65 , 0x2a000e20 , 0x2a000e20 }, { 0x0000a534 , 0x3c005e69 , 0x3c005e69 , 0x2e000e22 , 0x2e000e22 }, { 0x0000a538 , 0x40005e6b , 0x40005e6b , 0x31000e24 , 0x31000e24 }, { 0x0000a53c , 0x44005e6d , 0x44005e6d , 0x34001640 , 0x34001640 }, { 0x0000a540 , 0x49005e72 , 0x49005e72 , 0x38001660 , 0x38001660 }, { 0x0000a544 , 0x4e005eb2 , 0x4e005eb2 , 0x3b001861 , 0x3b001861 }, { 0x0000a548 , 0x53005f12 , 0x53005f12 , 0x3e001a81 , 0x3e001a81 }, { 0x0000a54c , 0x59025eb2 , 0x59025eb2 , 0x42001a83 , 0x42001a83 }, { 0x0000a550 , 0x5e025f12 , 0x5e025f12 , 0x44001c84 , 0x44001c84 }, { 0x0000a554 , 0x61027f12 , 0x61027f12 , 0x48001ce3 , 0x48001ce3 }, { 0x0000a558 , 0x6702bf12 , 0x6702bf12 , 0x4c001ce5 , 0x4c001ce5 }, { 0x0000a55c , 0x6b02bf14 , 0x6b02bf14 , 0x50001ce9 , 0x50001ce9 }, { 0x0000a560 , 0x6f02bf16 , 0x6f02bf16 , 0x54001ceb , 0x54001ceb }, { 0x0000a564 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a568 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a56c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a570 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a574 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a578 , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a57c , 0x6f02bf16 , 0x6f02bf16 , 0x56001eec , 0x56001eec }, { 0x0000a580 , 0x00802220 , 0x00802220 , 0x00800000 , 0x00800000 }, { 0x0000a584 , 0x04802222 , 0x04802222 , 0x04800002 , 0x04800002 }, { 0x0000a588 , 0x09802421 , 0x09802421 , 0x08800004 , 0x08800004 }, { 0x0000a58c , 0x0d802621 , 0x0d802621 , 0x0b800200 , 0x0b800200 }, { 0x0000a590 , 0x13804620 , 0x13804620 , 0x0f800202 , 0x0f800202 }, { 0x0000a594 , 0x19804a20 , 0x19804a20 , 0x11800400 , 0x11800400 }, { 0x0000a598 , 0x1d804e20 , 0x1d804e20 , 0x15800402 , 0x15800402 }, { 0x0000a59c , 0x21805420 , 0x21805420 , 0x19800404 , 0x19800404 }, { 0x0000a5a0 , 0x26805e20 , 0x26805e20 , 0x1b800603 , 0x1b800603 }, { 0x0000a5a4 , 0x2b805e40 , 0x2b805e40 , 0x1f800a02 , 0x1f800a02 }, { 0x0000a5a8 , 0x2f805e42 , 0x2f805e42 , 0x23800a04 , 0x23800a04 }, { 0x0000a5ac , 0x33805e44 , 0x33805e44 , 0x26800a20 , 0x26800a20 }, { 0x0000a5b0 , 0x38805e65 , 0x38805e65 , 0x2a800e20 , 0x2a800e20 }, { 0x0000a5b4 , 0x3c805e69 , 0x3c805e69 , 0x2e800e22 , 0x2e800e22 }, { 0x0000a5b8 , 0x40805e6b , 0x40805e6b , 0x31800e24 , 0x31800e24 }, { 0x0000a5bc , 0x44805e6d , 0x44805e6d , 0x34801640 , 0x34801640 }, { 0x0000a5c0 , 0x49805e72 , 0x49805e72 , 0x38801660 , 0x38801660 }, { 0x0000a5c4 , 0x4e805eb2 , 0x4e805eb2 , 0x3b801861 , 0x3b801861 }, { 0x0000a5c8 , 0x53805f12 , 0x53805f12 , 0x3e801a81 , 0x3e801a81 }, { 0x0000a5cc , 0x59825eb2 , 0x59825eb2 , 0x42801a83 , 0x42801a83 }, { 0x0000a5d0 , 0x5e825f12 , 0x5e825f12 , 0x44801c84 , 0x44801c84 }, { 0x0000a5d4 , 0x61827f12 , 0x61827f12 , 0x48801ce3 , 0x48801ce3 }, { 0x0000a5d8 , 0x6782bf12 , 0x6782bf12 , 0x4c801ce5 , 0x4c801ce5 }, { 0x0000a5dc , 0x6b82bf14 , 0x6b82bf14 , 0x50801ce9 , 0x50801ce9 }, { 0x0000a5e0 , 0x6f82bf16 , 0x6f82bf16 , 0x54801ceb , 0x54801ceb }, { 0x0000a5e4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5e8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5ec , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f0 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f4 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5f8 , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a5fc , 0x6f82bf16 , 0x6f82bf16 , 0x56801eec , 0x56801eec }, { 0x0000a600 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a604 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a608 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a60c , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a610 , 0x00804000 , 0x00804000 , 0x00000000 , 0x00000000 }, { 0x0000a614 , 0x00804201 , 0x00804201 , 0x01404000 , 0x01404000 }, { 0x0000a618 , 0x0280c802 , 0x0280c802 , 0x01404501 , 0x01404501 }, { 0x0000a61c , 0x0280ca03 , 0x0280ca03 , 0x02008501 , 0x02008501 }, { 0x0000a620 , 0x04c15104 , 0x04c15104 , 0x0280ca03 , 0x0280ca03 }, { 0x0000a624 , 0x04c15305 , 0x04c15305 , 0x03010c04 , 0x03010c04 }, { 0x0000a628 , 0x04c15305 , 0x04c15305 , 0x04014c04 , 0x04014c04 }, { 0x0000a62c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a630 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a634 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a638 , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000a63c , 0x04c15305 , 0x04c15305 , 0x04015005 , 0x04015005 }, { 0x0000b2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000b2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000b2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000b2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x0000c2dc , 0x01feee00 , 0x01feee00 , 0x03aaa352 , 0x03aaa352 }, { 0x0000c2e0 , 0x0000f000 , 0x0000f000 , 0x03ccc584 , 0x03ccc584 }, { 0x0000c2e4 , 0x01ff0000 , 0x01ff0000 , 0x03f0f800 , 0x03f0f800 }, { 0x0000c2e8 , 0x00000000 , 0x00000000 , 0x03ff0000 , 0x03ff0000 }, { 0x00016044 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016048 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016068 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016444 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016448 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016468 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, { 0x00016844 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 , 0x056db2e4 }, { 0x00016848 , 0x8e480001 , 0x8e480001 , 0x8e480001 , 0x8e480001 }, { 0x00016868 , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c , 0x6db6db6c }, }; static const u_int32_t ar9300_ar9580_1p0_soc_preamble[][2] = { /* Addr allmodes */ { 0x000040a4 , 0x00a0c1c9 }, { 0x00007008 , 0x00000000 }, { 0x00007020 , 0x00000000 }, { 0x00007034 , 0x00000002 }, { 0x00007038 , 0x000004c2 }, { 0x00007048 , 0x00000008 }, }; static const u_int32_t ar9300_common_rx_gain_table_ar9580_1p0[][2] = { /* Addr allmodes */ { 0x0000a000 , 0x00010000 }, { 0x0000a004 , 0x00030002 }, { 0x0000a008 , 0x00050004 }, { 0x0000a00c , 0x00810080 }, { 0x0000a010 , 0x00830082 }, { 0x0000a014 , 0x01810180 }, { 0x0000a018 , 0x01830182 }, { 0x0000a01c , 0x01850184 }, { 0x0000a020 , 0x01890188 }, { 0x0000a024 , 0x018b018a }, { 0x0000a028 , 0x018d018c }, { 0x0000a02c , 0x01910190 }, { 0x0000a030 , 0x01930192 }, { 0x0000a034 , 0x01950194 }, { 0x0000a038 , 0x038a0196 }, { 0x0000a03c , 0x038c038b }, { 0x0000a040 , 0x0390038d }, { 0x0000a044 , 0x03920391 }, { 0x0000a048 , 0x03940393 }, { 0x0000a04c , 0x03960395 }, { 0x0000a050 , 0x00000000 }, { 0x0000a054 , 0x00000000 }, { 0x0000a058 , 0x00000000 }, { 0x0000a05c , 0x00000000 }, { 0x0000a060 , 0x00000000 }, { 0x0000a064 , 0x00000000 }, { 0x0000a068 , 0x00000000 }, { 0x0000a06c , 0x00000000 }, { 0x0000a070 , 0x00000000 }, { 0x0000a074 , 0x00000000 }, { 0x0000a078 , 0x00000000 }, { 0x0000a07c , 0x00000000 }, { 0x0000a080 , 0x22222229 }, { 0x0000a084 , 0x1d1d1d1d }, { 0x0000a088 , 0x1d1d1d1d }, { 0x0000a08c , 0x1d1d1d1d }, { 0x0000a090 , 0x171d1d1d }, { 0x0000a094 , 0x11111717 }, { 0x0000a098 , 0x00030311 }, { 0x0000a09c , 0x00000000 }, { 0x0000a0a0 , 0x00000000 }, { 0x0000a0a4 , 0x00000000 }, { 0x0000a0a8 , 0x00000000 }, { 0x0000a0ac , 0x00000000 }, { 0x0000a0b0 , 0x00000000 }, { 0x0000a0b4 , 0x00000000 }, { 0x0000a0b8 , 0x00000000 }, { 0x0000a0bc , 0x00000000 }, { 0x0000a0c0 , 0x001f0000 }, { 0x0000a0c4 , 0x01000101 }, { 0x0000a0c8 , 0x011e011f }, { 0x0000a0cc , 0x011c011d }, { 0x0000a0d0 , 0x02030204 }, { 0x0000a0d4 , 0x02010202 }, { 0x0000a0d8 , 0x021f0200 }, { 0x0000a0dc , 0x0302021e }, { 0x0000a0e0 , 0x03000301 }, { 0x0000a0e4 , 0x031e031f }, { 0x0000a0e8 , 0x0402031d }, { 0x0000a0ec , 0x04000401 }, { 0x0000a0f0 , 0x041e041f }, { 0x0000a0f4 , 0x0502041d }, { 0x0000a0f8 , 0x05000501 }, { 0x0000a0fc , 0x051e051f }, { 0x0000a100 , 0x06010602 }, { 0x0000a104 , 0x061f0600 }, { 0x0000a108 , 0x061d061e }, { 0x0000a10c , 0x07020703 }, { 0x0000a110 , 0x07000701 }, { 0x0000a114 , 0x00000000 }, { 0x0000a118 , 0x00000000 }, { 0x0000a11c , 0x00000000 }, { 0x0000a120 , 0x00000000 }, { 0x0000a124 , 0x00000000 }, { 0x0000a128 , 0x00000000 }, { 0x0000a12c , 0x00000000 }, { 0x0000a130 , 0x00000000 }, { 0x0000a134 , 0x00000000 }, { 0x0000a138 , 0x00000000 }, { 0x0000a13c , 0x00000000 }, { 0x0000a140 , 0x001f0000 }, { 0x0000a144 , 0x01000101 }, { 0x0000a148 , 0x011e011f }, { 0x0000a14c , 0x011c011d }, { 0x0000a150 , 0x02030204 }, { 0x0000a154 , 0x02010202 }, { 0x0000a158 , 0x021f0200 }, { 0x0000a15c , 0x0302021e }, { 0x0000a160 , 0x03000301 }, { 0x0000a164 , 0x031e031f }, { 0x0000a168 , 0x0402031d }, { 0x0000a16c , 0x04000401 }, { 0x0000a170 , 0x041e041f }, { 0x0000a174 , 0x0502041d }, { 0x0000a178 , 0x05000501 }, { 0x0000a17c , 0x051e051f }, { 0x0000a180 , 0x06010602 }, { 0x0000a184 , 0x061f0600 }, { 0x0000a188 , 0x061d061e }, { 0x0000a18c , 0x07020703 }, { 0x0000a190 , 0x07000701 }, { 0x0000a194 , 0x00000000 }, { 0x0000a198 , 0x00000000 }, { 0x0000a19c , 0x00000000 }, { 0x0000a1a0 , 0x00000000 }, { 0x0000a1a4 , 0x00000000 }, { 0x0000a1a8 , 0x00000000 }, { 0x0000a1ac , 0x00000000 }, { 0x0000a1b0 , 0x00000000 }, { 0x0000a1b4 , 0x00000000 }, { 0x0000a1b8 , 0x00000000 }, { 0x0000a1bc , 0x00000000 }, { 0x0000a1c0 , 0x00000000 }, { 0x0000a1c4 , 0x00000000 }, { 0x0000a1c8 , 0x00000000 }, { 0x0000a1cc , 0x00000000 }, { 0x0000a1d0 , 0x00000000 }, { 0x0000a1d4 , 0x00000000 }, { 0x0000a1d8 , 0x00000000 }, { 0x0000a1dc , 0x00000000 }, { 0x0000a1e0 , 0x00000000 }, { 0x0000a1e4 , 0x00000000 }, { 0x0000a1e8 , 0x00000000 }, { 0x0000a1ec , 0x00000000 }, { 0x0000a1f0 , 0x00000396 }, { 0x0000a1f4 , 0x00000396 }, { 0x0000a1f8 , 0x00000396 }, { 0x0000a1fc , 0x00000196 }, { 0x0000b000 , 0x00010000 }, { 0x0000b004 , 0x00030002 }, { 0x0000b008 , 0x00050004 }, { 0x0000b00c , 0x00810080 }, { 0x0000b010 , 0x00830082 }, { 0x0000b014 , 0x01810180 }, { 0x0000b018 , 0x01830182 }, { 0x0000b01c , 0x01850184 }, { 0x0000b020 , 0x02810280 }, { 0x0000b024 , 0x02830282 }, { 0x0000b028 , 0x02850284 }, { 0x0000b02c , 0x02890288 }, { 0x0000b030 , 0x028b028a }, { 0x0000b034 , 0x0388028c }, { 0x0000b038 , 0x038a0389 }, { 0x0000b03c , 0x038c038b }, { 0x0000b040 , 0x0390038d }, { 0x0000b044 , 0x03920391 }, { 0x0000b048 , 0x03940393 }, { 0x0000b04c , 0x03960395 }, { 0x0000b050 , 0x00000000 }, { 0x0000b054 , 0x00000000 }, { 0x0000b058 , 0x00000000 }, { 0x0000b05c , 0x00000000 }, { 0x0000b060 , 0x00000000 }, { 0x0000b064 , 0x00000000 }, { 0x0000b068 , 0x00000000 }, { 0x0000b06c , 0x00000000 }, { 0x0000b070 , 0x00000000 }, { 0x0000b074 , 0x00000000 }, { 0x0000b078 , 0x00000000 }, { 0x0000b07c , 0x00000000 }, { 0x0000b080 , 0x23232323 }, { 0x0000b084 , 0x21232323 }, { 0x0000b088 , 0x19191c1e }, { 0x0000b08c , 0x12141417 }, { 0x0000b090 , 0x07070e0e }, { 0x0000b094 , 0x03030305 }, { 0x0000b098 , 0x00000003 }, { 0x0000b09c , 0x00000000 }, { 0x0000b0a0 , 0x00000000 }, { 0x0000b0a4 , 0x00000000 }, { 0x0000b0a8 , 0x00000000 }, { 0x0000b0ac , 0x00000000 }, { 0x0000b0b0 , 0x00000000 }, { 0x0000b0b4 , 0x00000000 }, { 0x0000b0b8 , 0x00000000 }, { 0x0000b0bc , 0x00000000 }, { 0x0000b0c0 , 0x003f0020 }, { 0x0000b0c4 , 0x00400041 }, { 0x0000b0c8 , 0x0140005f }, { 0x0000b0cc , 0x0160015f }, { 0x0000b0d0 , 0x017e017f }, { 0x0000b0d4 , 0x02410242 }, { 0x0000b0d8 , 0x025f0240 }, { 0x0000b0dc , 0x027f0260 }, { 0x0000b0e0 , 0x0341027e }, { 0x0000b0e4 , 0x035f0340 }, { 0x0000b0e8 , 0x037f0360 }, { 0x0000b0ec , 0x04400441 }, { 0x0000b0f0 , 0x0460045f }, { 0x0000b0f4 , 0x0541047f }, { 0x0000b0f8 , 0x055f0540 }, { 0x0000b0fc , 0x057f0560 }, { 0x0000b100 , 0x06400641 }, { 0x0000b104 , 0x0660065f }, { 0x0000b108 , 0x067e067f }, { 0x0000b10c , 0x07410742 }, { 0x0000b110 , 0x075f0740 }, { 0x0000b114 , 0x077f0760 }, { 0x0000b118 , 0x07800781 }, { 0x0000b11c , 0x07a0079f }, { 0x0000b120 , 0x07c107bf }, { 0x0000b124 , 0x000007c0 }, { 0x0000b128 , 0x00000000 }, { 0x0000b12c , 0x00000000 }, { 0x0000b130 , 0x00000000 }, { 0x0000b134 , 0x00000000 }, { 0x0000b138 , 0x00000000 }, { 0x0000b13c , 0x00000000 }, { 0x0000b140 , 0x003f0020 }, { 0x0000b144 , 0x00400041 }, { 0x0000b148 , 0x0140005f }, { 0x0000b14c , 0x0160015f }, { 0x0000b150 , 0x017e017f }, { 0x0000b154 , 0x02410242 }, { 0x0000b158 , 0x025f0240 }, { 0x0000b15c , 0x027f0260 }, { 0x0000b160 , 0x0341027e }, { 0x0000b164 , 0x035f0340 }, { 0x0000b168 , 0x037f0360 }, { 0x0000b16c , 0x04400441 }, { 0x0000b170 , 0x0460045f }, { 0x0000b174 , 0x0541047f }, { 0x0000b178 , 0x055f0540 }, { 0x0000b17c , 0x057f0560 }, { 0x0000b180 , 0x06400641 }, { 0x0000b184 , 0x0660065f }, { 0x0000b188 , 0x067e067f }, { 0x0000b18c , 0x07410742 }, { 0x0000b190 , 0x075f0740 }, { 0x0000b194 , 0x077f0760 }, { 0x0000b198 , 0x07800781 }, { 0x0000b19c , 0x07a0079f }, { 0x0000b1a0 , 0x07c107bf }, { 0x0000b1a4 , 0x000007c0 }, { 0x0000b1a8 , 0x00000000 }, { 0x0000b1ac , 0x00000000 }, { 0x0000b1b0 , 0x00000000 }, { 0x0000b1b4 , 0x00000000 }, { 0x0000b1b8 , 0x00000000 }, { 0x0000b1bc , 0x00000000 }, { 0x0000b1c0 , 0x00000000 }, { 0x0000b1c4 , 0x00000000 }, { 0x0000b1c8 , 0x00000000 }, { 0x0000b1cc , 0x00000000 }, { 0x0000b1d0 , 0x00000000 }, { 0x0000b1d4 , 0x00000000 }, { 0x0000b1d8 , 0x00000000 }, { 0x0000b1dc , 0x00000000 }, { 0x0000b1e0 , 0x00000000 }, { 0x0000b1e4 , 0x00000000 }, { 0x0000b1e8 , 0x00000000 }, { 0x0000b1ec , 0x00000000 }, { 0x0000b1f0 , 0x00000396 }, { 0x0000b1f4 , 0x00000396 }, { 0x0000b1f8 , 0x00000396 }, { 0x0000b1fc , 0x00000196 }, }; static const u_int32_t ar9300_ar9580_1p0_radio_core[][2] = { /* Addr allmodes */ { 0x00016000 , 0x36db6db6 }, { 0x00016004 , 0x6db6db40 }, { 0x00016008 , 0x73f00000 }, { 0x0001600c , 0x00000000 }, { 0x00016040 , 0x7f80fff8 }, { 0x0001604c , 0x76d005b5 }, { 0x00016050 , 0x556cf031 }, { 0x00016054 , 0x13449440 }, { 0x00016058 , 0x0c51c92c }, { 0x0001605c , 0x3db7fffc }, { 0x00016060 , 0xfffffffc }, { 0x00016064 , 0x000f0278 }, { 0x0001606c , 0x6db60000 }, { 0x00016080 , 0x00000000 }, { 0x00016084 , 0x0e48048c }, { 0x00016088 , 0x54214514 }, { 0x0001608c , 0x119f481e }, { 0x00016090 , 0x24926490 }, { 0x00016098 , 0xd2888888 }, { 0x000160a0 , 0x0a108ffe }, { 0x000160a4 , 0x812fc370 }, { 0x000160a8 , 0x423c8000 }, { 0x000160b4 , 0x92480080 }, { 0x000160c0 , 0x00adb6d0 }, { 0x000160c4 , 0x6db6db60 }, { 0x000160c8 , 0x6db6db6c }, { 0x000160cc , 0x01e6c000 }, { 0x00016100 , 0x3fffbe01 }, { 0x00016104 , 0xfff80000 }, { 0x00016108 , 0x00080010 }, { 0x00016144 , 0x02084080 }, { 0x00016148 , 0x00000000 }, { 0x00016280 , 0x058a0001 }, { 0x00016284 , 0x3d840208 }, { 0x00016288 , 0x05a20408 }, { 0x0001628c , 0x00038c07 }, { 0x00016290 , 0x00000004 }, { 0x00016294 , 0x458a214f }, { 0x00016380 , 0x00000000 }, { 0x00016384 , 0x00000000 }, { 0x00016388 , 0x00800700 }, { 0x0001638c , 0x00800700 }, { 0x00016390 , 0x00800700 }, { 0x00016394 , 0x00000000 }, { 0x00016398 , 0x00000000 }, { 0x0001639c , 0x00000000 }, { 0x000163a0 , 0x00000001 }, { 0x000163a4 , 0x00000001 }, { 0x000163a8 , 0x00000000 }, { 0x000163ac , 0x00000000 }, { 0x000163b0 , 0x00000000 }, { 0x000163b4 , 0x00000000 }, { 0x000163b8 , 0x00000000 }, { 0x000163bc , 0x00000000 }, { 0x000163c0 , 0x000000a0 }, { 0x000163c4 , 0x000c0000 }, { 0x000163c8 , 0x14021402 }, { 0x000163cc , 0x00001402 }, { 0x000163d0 , 0x00000000 }, { 0x000163d4 , 0x00000000 }, { 0x00016400 , 0x36db6db6 }, { 0x00016404 , 0x6db6db40 }, { 0x00016408 , 0x73f00000 }, { 0x0001640c , 0x00000000 }, { 0x00016440 , 0x7f80fff8 }, { 0x0001644c , 0x76d005b5 }, { 0x00016450 , 0x556cf031 }, { 0x00016454 , 0x13449440 }, { 0x00016458 , 0x0c51c92c }, { 0x0001645c , 0x3db7fffc }, { 0x00016460 , 0xfffffffc }, { 0x00016464 , 0x000f0278 }, { 0x0001646c , 0x6db60000 }, { 0x00016500 , 0x3fffbe01 }, { 0x00016504 , 0xfff80000 }, { 0x00016508 , 0x00080010 }, { 0x00016544 , 0x02084080 }, { 0x00016548 , 0x00000000 }, { 0x00016780 , 0x00000000 }, { 0x00016784 , 0x00000000 }, { 0x00016788 , 0x00800700 }, { 0x0001678c , 0x00800700 }, { 0x00016790 , 0x00800700 }, { 0x00016794 , 0x00000000 }, { 0x00016798 , 0x00000000 }, { 0x0001679c , 0x00000000 }, { 0x000167a0 , 0x00000001 }, { 0x000167a4 , 0x00000001 }, { 0x000167a8 , 0x00000000 }, { 0x000167ac , 0x00000000 }, { 0x000167b0 , 0x00000000 }, { 0x000167b4 , 0x00000000 }, { 0x000167b8 , 0x00000000 }, { 0x000167bc , 0x00000000 }, { 0x000167c0 , 0x000000a0 }, { 0x000167c4 , 0x000c0000 }, { 0x000167c8 , 0x14021402 }, { 0x000167cc , 0x00001402 }, { 0x000167d0 , 0x00000000 }, { 0x000167d4 , 0x00000000 }, { 0x00016800 , 0x36db6db6 }, { 0x00016804 , 0x6db6db40 }, { 0x00016808 , 0x73f00000 }, { 0x0001680c , 0x00000000 }, { 0x00016840 , 0x7f80fff8 }, { 0x0001684c , 0x76d005b5 }, { 0x00016850 , 0x556cf031 }, { 0x00016854 , 0x13449440 }, { 0x00016858 , 0x0c51c92c }, { 0x0001685c , 0x3db7fffc }, { 0x00016860 , 0xfffffffc }, { 0x00016864 , 0x000f0278 }, { 0x0001686c , 0x6db60000 }, { 0x00016900 , 0x3fffbe01 }, { 0x00016904 , 0xfff80000 }, { 0x00016908 , 0x00080010 }, { 0x00016944 , 0x02084080 }, { 0x00016948 , 0x00000000 }, { 0x00016b80 , 0x00000000 }, { 0x00016b84 , 0x00000000 }, { 0x00016b88 , 0x00800700 }, { 0x00016b8c , 0x00800700 }, { 0x00016b90 , 0x00800700 }, { 0x00016b94 , 0x00000000 }, { 0x00016b98 , 0x00000000 }, { 0x00016b9c , 0x00000000 }, { 0x00016ba0 , 0x00000001 }, { 0x00016ba4 , 0x00000001 }, { 0x00016ba8 , 0x00000000 }, { 0x00016bac , 0x00000000 }, { 0x00016bb0 , 0x00000000 }, { 0x00016bb4 , 0x00000000 }, { 0x00016bb8 , 0x00000000 }, { 0x00016bbc , 0x00000000 }, { 0x00016bc0 , 0x000000a0 }, { 0x00016bc4 , 0x000c0000 }, { 0x00016bc8 , 0x14021402 }, { 0x00016bcc , 0x00001402 }, { 0x00016bd0 , 0x00000000 }, { 0x00016bd4 , 0x00000000 }, }; static const u_int32_t ar9300_ar9580_1p0_baseband_core_emulation[][2] = { /* Addr allmodes */ { 0x00009800 , 0xafa68e30 }, { 0x00009884 , 0x00002842 }, { 0x00009c04 , 0xff55ff55 }, { 0x00009c08 , 0x0320ff55 }, { 0x00009e50 , 0x00000000 }, { 0x00009fcc , 0x00000014 }, { 0x0000a344 , 0x00000010 }, { 0x0000a398 , 0x00000000 }, { 0x0000a39c , 0x71733d01 }, { 0x0000a3a0 , 0xd0ad5c12 }, { 0x0000a3c0 , 0x22222220 }, { 0x0000a3c4 , 0x22222222 }, { 0x0000a404 , 0x00418a11 }, { 0x0000a418 , 0x050001ce }, { 0x0000a438 , 0x00001800 }, { 0x0000a458 , 0x01444452 }, { 0x0000a690 , 0x00000038 }, { 0x0000b8dc , 0x00400000 }, }; static const u_int32_t ar9300_ar9580_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ { 0x00009810 , 0xd00a8005 , 0xd00a8005 , 0xd00a8011 , 0xd00a8011 }, { 0x00009820 , 0x206a022e , 0x206a022e , 0x206a012e , 0x206a012e }, { 0x00009824 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 }, { 0x00009828 , 0x06903081 , 0x06903081 , 0x06903881 , 0x06903881 }, { 0x0000982c , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 }, { 0x00009830 , 0x0000059c , 0x0000059c , 0x0000119c , 0x0000119c }, { 0x00009c00 , 0x000000c4 , 0x000000c4 , 0x000000c4 , 0x000000c4 }, { 0x00009e00 , 0x0372111a , 0x0372111a , 0x037216a0 , 0x037216a0 }, { 0x00009e04 , 0x001c2020 , 0x001c2020 , 0x001c2020 , 0x001c2020 }, { 0x00009e0c , 0x6c4000e2 , 0x6d4000e2 , 0x6d4000e2 , 0x6c4000e2 }, { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec84d2e , 0x7ec84d2e }, { 0x00009e14 , 0x37b95d5e , 0x37b9605e , 0x3379605e , 0x33795d5e }, { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, - { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c }, + { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c }, { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce }, { 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 }, { 0x00009e3c , 0xcf946220 , 0xcf946220 , 0xcf946222 , 0xcf946222 }, { 0x00009e44 , 0x02321e27 , 0x02321e27 , 0x02291e27 , 0x02291e27 }, { 0x00009e48 , 0x5030201a , 0x5030201a , 0x50302012 , 0x50302012 }, { 0x00009fc8 , 0x0003f000 , 0x0003f000 , 0x0001a000 , 0x0001a000 }, { 0x0000a204 , 0x000036c0 , 0x000036c4 , 0x000036c4 , 0x000036c0 }, { 0x0000a208 , 0x00000104 , 0x00000104 , 0x00000004 , 0x00000004 }, { 0x0000a22c , 0x07e26a2f , 0x07e26a2f , 0x01026a2f , 0x01026a2f }, { 0x0000a230 , 0x0000000a , 0x00000014 , 0x00000016 , 0x0000000b }, { 0x0000a234 , 0x00000fff , 0x10000fff , 0x10000fff , 0x00000fff }, { 0x0000a238 , 0xffb01018 , 0xffb01018 , 0xffb01018 , 0xffb01018 }, { 0x0000a250 , 0x00000000 , 0x00000000 , 0x00000210 , 0x00000108 }, { 0x0000a254 , 0x000007d0 , 0x00000fa0 , 0x00001130 , 0x00000898 }, { 0x0000a258 , 0x02020002 , 0x02020002 , 0x02020002 , 0x02020002 }, { 0x0000a25c , 0x01000e0e , 0x01000e0e , 0x01000e0e , 0x01000e0e }, { 0x0000a260 , 0x0a021501 , 0x0a021501 , 0x3a021501 , 0x3a021501 }, { 0x0000a264 , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e }, { 0x0000a280 , 0x00000007 , 0x00000007 , 0x0000000b , 0x0000000b }, { 0x0000a284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, { 0x0000a288 , 0x00000110 , 0x00000110 , 0x00000110 , 0x00000110 }, { 0x0000a28c , 0x00022222 , 0x00022222 , 0x00022222 , 0x00022222 }, { 0x0000a2c4 , 0x00158d18 , 0x00158d18 , 0x00158d18 , 0x00158d18 }, { 0x0000a2d0 , 0x00041983 , 0x00041983 , 0x00041981 , 0x00041982 }, { 0x0000a2d8 , 0x7999a83b , 0x7999a83b , 0x7999a83b , 0x7999a83b }, { 0x0000a358 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000a830 , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae04 , 0x001c0000 , 0x001c0000 , 0x001c0000 , 0x001c0000 }, { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000ae1c , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000ae20 , 0x000001b5 , 0x000001b5 , 0x000001ce , 0x000001ce }, { 0x0000b284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, { 0x0000b830 , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000be04 , 0x001c0000 , 0x001c0000 , 0x001c0000 , 0x001c0000 }, { 0x0000be18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, { 0x0000be1c , 0x0000019c , 0x0000019c , 0x0000019c , 0x0000019c }, { 0x0000be20 , 0x000001b5 , 0x000001b5 , 0x000001ce , 0x000001ce }, { 0x0000c284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 }, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_clkreq_enable_L1_ar9580_1p0[][2] = { {0x00004040, 0x0835365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_clkreq_disable_L1_ar9580_1p0[][2] = { {0x00004040, 0x0831365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; /* PCIE-PHY programming array */ static const u_int32_t ar9300PciePhy_pll_on_clkreq_disable_L1_ar9580_1p0[][2] = { {0x00004040, 0x0831265e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, };