Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (revision 291437) @@ -1,4172 +1,4283 @@ /* * 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/ar9462_2p1_initvals.h" #include "ar9300/ar9580.ini" #include "ar9300/ar955x.ini" +#include "ar9300/ar953x.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, 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 if(AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_QCA953X) { + /* XXX: AR_SREV register in HoneyBEE reads 0 */ + AH_PRIVATE(ah)->ah_macVersion = AR_SREV_VERSION_HONEYBEE; } 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 } + + if (AR_SREV_HONEYBEE(ah)) { + ahp->clk_25mhz = 1; + } + 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_HONEYBEE && 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); + /* XXX TODO: need to add this for freebsd; it's missing from the current .ini files */ +#if 0 + /* Japan 2484Mhz CCK settings */ + INIT_INI_ARRAY(&ahp->ah_ini_japan2484, + ar9340_wasp_1p0_baseband_core_txfir_coeff_japan_2484, + ARRAY_LENGTH( + ar9340_wasp_1p0_baseband_core_txfir_coeff_japan_2484), 2); +#endif + /* 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_HONEYBEE(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], + qca953x_honeybee_1p0_mac_core, + ARRAY_LENGTH(qca953x_honeybee_1p0_mac_core), 2); + INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST], + qca953x_honeybee_1p0_mac_postamble, + ARRAY_LENGTH(qca953x_honeybee_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], + qca953x_honeybee_1p0_baseband_core, + ARRAY_LENGTH(qca953x_honeybee_1p0_baseband_core), 2); + INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], + qca953x_honeybee_1p0_baseband_postamble, + ARRAY_LENGTH(qca953x_honeybee_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], + qca953x_honeybee_1p0_radio_core, + ARRAY_LENGTH(qca953x_honeybee_1p0_radio_core), 2); + INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST], + qca953x_honeybee_1p0_radio_postamble, + ARRAY_LENGTH(qca953x_honeybee_1p0_radio_postamble), 5); + + /* soc */ + INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], + qca953x_honeybee_1p0_soc_preamble, + ARRAY_LENGTH(qca953x_honeybee_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], + qca953x_honeybee_1p0_soc_postamble, + ARRAY_LENGTH(qca953x_honeybee_1p0_soc_postamble), 5); + + /* rx/tx gain */ + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, + qca953xCommon_wo_xlna_rx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_wo_xlna_rx_gain_table_honeybee_1p0), 2); + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, + qca953xCommon_wo_xlna_rx_gain_bounds_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_wo_xlna_rx_gain_bounds_honeybee_1p0), 5); + INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, + qca953xModes_no_xpa_tx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xModes_no_xpa_tx_gain_table_honeybee_1p0), 2); + + /*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, + qca953xModes_fast_clock_honeybee_1p0, + ARRAY_LENGTH(qca953xModes_fast_clock_honeybee_1p0), 3); + + /* Additional setttings for 40Mhz */ + //INIT_INI_ARRAY(&ahp->ah_ini_modes_additional_40M, + // qca953x_honeybee_1p0_radio_core_40M, + // ARRAY_LENGTH(qca953x_honeybee_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) */ /* FreeBSD: just override the registers for jupiter 2.1 */ /* mac */ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0); if (AR_SREV_JUPITER_21(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE], ar9462_2p1_mac_core, ARRAY_LENGTH(ar9462_2p1_mac_core), 2); } else { 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); if (AR_SREV_JUPITER_21(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST], ar9462_2p1_baseband_postamble, ARRAY_LENGTH(ar9462_2p1_baseband_postamble), 5); } else { 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 */ if (AR_SREV_JUPITER_21(ah)) { INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE], ar9462_2p1_soc_preamble, ARRAY_LENGTH(ar9462_2p1_soc_preamble), 2); } else { 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_TRUE; 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 if (AR_SREV_HONEYBEE(ah)) { + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, + qca953xCommon_rx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_rx_gain_table_honeybee_1p0), 2); + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, + qca953xCommon_rx_gain_bounds_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_rx_gain_bounds_honeybee_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 if (AR_SREV_HONEYBEE(ah)) { + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain, + qca953xCommon_wo_xlna_rx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_wo_xlna_rx_gain_table_honeybee_1p0), 2); + INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, + qca953xCommon_wo_xlna_rx_gain_bounds_honeybee_1p0, + ARRAY_LENGTH(qca953xCommon_wo_xlna_rx_gain_bounds_honeybee_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_HONEYBEE(ah)) { + INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, + qca953xModes_xpa_tx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xModes_xpa_tx_gain_table_honeybee_1p0), + 2); } 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 if (AR_SREV_HONEYBEE(ah)) { + if (AR_SREV_HONEYBEE_11(ah)) { + INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, + qca953xModes_no_xpa_tx_gain_table_honeybee_1p1, + ARRAY_LENGTH(qca953xModes_no_xpa_tx_gain_table_honeybee_1p1), 2); + } else { + INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain, + qca953xModes_no_xpa_tx_gain_table_honeybee_1p0, + ARRAY_LENGTH(qca953xModes_no_xpa_tx_gain_table_honeybee_1p0), 2); + } } 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_QCA953X: /* Honeybee */ + return "Qualcomm Atheros QCA953x"; 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_eeprom.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c (revision 291437) @@ -1,4728 +1,4759 @@ /* * 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; + if (AR_SREV_HONEYBEE(ah)){ /* no OTP for Honeybee */ + return false; + } 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. + * This is not 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)) { + if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) + || AR_SREV_HONEYBEE(ah)) { ahp->try_eeprom = 0; } + if (AR_SREV_HONEYBEE(ah)) { + ahp->try_otp = 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_HONEYBEE_ALL (0xffffff) +#define AR_SWITCH_TABLE_COM_HONEYBEE_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 if (AR_SREV_HONEYBEE(ah)) { + OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, + AR_SWITCH_TABLE_COM_HONEYBEE_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)) { + if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)&& !AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_SCORPION(ah) && !AR_SREV_HONEYBEE(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*/ + /*Scorpion and Honeybee 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) { + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, eep->base_ext2.temp_slope_low); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, eep->base_ext2.temp_slope_high); + } } else { + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, temp_slope_1); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { 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*/ + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { OS_REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 0); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { OS_REG_RMW_FIELD(ah, AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 0); + } + if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { 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 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_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; - /* XXX TODO: ath9k skips it for Wasp and Honeybee/AR9531, not Poseidon */ - if (AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) { - return AH_TRUE; + if (AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) { + return true; } else if (AR_SREV_HORNET(ah)) { OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, tuning_caps_params); OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, tuning_caps_params); } 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 (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_HORNET(ah) && !AR_SREV_WASP(ah) && !AR_SREV_HONEYBEE(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_inc.h =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h (revision 291437) @@ -1,614 +1,617 @@ #ifndef __AR9300_FREEBSD_INC_H__ #define __AR9300_FREEBSD_INC_H__ /* * Define some configuration entries for the AR9300 HAL, so #if entries * don't have to be removed. */ #define ATH_DRIVER_SIM 0 /* SIM */ #define ATH_WOW 0 /* Wake on Wireless */ #define ATH_SUPPORT_MCI 1 /* MCI btcoex */ #define ATH_SUPPORT_AIC 0 /* XXX to do with btcoex? */ #define AH_NEED_TX_DATA_SWAP 0 /* TX descriptor swap? */ #define AH_NEED_RX_DATA_SWAP 0 /* TX descriptor swap? */ #define ATH_SUPPORT_WIRESHARK 0 /* Radiotap HAL code */ #define AH_SUPPORT_WRITE_EEPROM 0 /* EEPROM write support */ #define ATH_SUPPORT_WAPI 0 /* China WAPI support */ #define ATH_ANT_DIV_COMB 1 /* Antenna combining */ #define ATH_SUPPORT_RAW_ADC_CAPTURE 0 /* Raw ADC capture support */ #define ATH_TRAFFIC_FAST_RECOVER 0 /* XXX not sure yet */ #define ATH_SUPPORT_SPECTRAL 0 /* Spectral scan support */ #define ATH_BT_COEX 1 /* Enable BT Coex code */ #define ATH_PCIE_ERROR_MONITOR 0 /* ??? */ #define ATH_SUPPORT_CRDC 0 /* ??? */ #define ATH_LOW_POWER_ENABLE 0 /* ??? */ #define ATH_SUPPORT_VOW_DCS 0 /* Video over wireless dynamic channel select */ #define REMOVE_PKT_LOG 1 #define ATH_VC_MODE_PROXY_STA 0 /* Azimuth + proxysta? */ #define ATH_GEN_RANDOMNESS 0 #define __PKT_SERIOUS_ERRORS__ 0 #define HAL_INTR_REFCOUNT_DISABLE 1 /* XXX wha? And atomics in the HAL!? */ #define UMAC_SUPPORT_SMARTANTENNA 0 /* sigh.. */ #define ATH_SMARTANTENNA_DISABLE_JTAG 0 #define ATH_SUPPORT_WIRESHARK 0 #define ATH_SUPPORT_WIFIPOS 0 #define ATH_SUPPORT_PAPRD 1 #define ATH_SUPPORT_TxBF 0 #define AH_PRIVATE_DIAG 1 #define ATH_SUPPORT_KEYPLUMB_WAR 0 /* XXX need to reverify these; they came in with qcamain */ #define ATH_SUPPORT_FAST_CC 0 #define ATH_SUPPORT_RADIO_RETENTION 0 #define ATH_SUPPORT_CAL_REUSE 0 #define ATH_WOW_OFFLOAD 0 #define HAL_NO_INTERSPERSED_READS /* Required or things will probe/attach, but not work right */ #define AH_SUPPORT_OSPREY 1 #define AH_SUPPORT_POSEIDON 1 #define AH_SUPPORT_AR9300 1 /* These are the embedded boards; we don't currently support these */ #ifdef AH_SUPPORT_AR9330 #define AH_SUPPORT_HORNET 1 #endif /* AH_SUPPORT_AR9330 */ #ifdef AH_SUPPORT_AR9340 #define AH_SUPPORT_WASP 1 #endif /* AH_SUPPORT_AR9340 */ #ifdef AH_SUPPORT_QCA9550 #define AH_SUPPORT_SCORPION 1 #endif /* AH_SUPPORT_QCA9550 */ +#ifdef AH_SUPPORT_QCA9530 +#define AH_SUPPORT_HONEYBEE 1 +#endif /* AH_SUPPORT_QCA9530 */ #define FIX_NOISE_FLOOR 1 /* XXX this needs to be removed! No atomics in the HAL! */ typedef int os_atomic_t; /* XXX shouldn't do atomics here! */ #define OS_ATOMIC_INC(a) (*a)++ #define OS_ATOMIC_DEC(a) (*a)-- /* * HAL definitions which aren't necessarily for public consumption (yet). */ enum { HAL_TRUE_CHIP = 1, HAL_MAC_TO_MAC_EMU, HAL_MAC_BB_EMU, }; /* HAL_KEY_TYPE */ enum { HAL_KEY_PROXY_STA_MASK = 0x10, }; typedef enum { HAL_SMPS_DEFAULT = 0, HAL_SMPS_SW_CTRL_LOW_PWR, /* Software control, low power setting */ HAL_SMPS_SW_CTRL_HIGH_PWR, /* Software control, high power setting */ HAL_SMPS_HW_CTRL /* Hardware Control */ } HAL_SMPS_MODE; /* * 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 GreenTX_thres1 56 /* in dB */ #define GreenTX_thres2 36 /* in dB */ typedef enum { HAL_RSSI_TX_POWER_NONE = 0, HAL_RSSI_TX_POWER_SHORT = 1, /* short range, reduce OB/DB bias current and disable PAL */ HAL_RSSI_TX_POWER_MIDDLE = 2, /* middle range, reduce OB/DB bias current and PAL is enabled */ HAL_RSSI_TX_POWER_LONG = 3, /* long range, orig. OB/DB bias current and PAL is enabled */ } HAL_RSSI_TX_POWER; struct dfs_pulse { u_int32_t rp_numpulses ; /* Num of pulses in radar burst */ u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ u_int32_t rp_pulsefreq; /* Frequency of pulses in burst */ u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ u_int32_t rp_patterntype; /* fixed or variable pattern type*/ u_int32_t rp_pulsevar; /* Time variation of pulse duration for matched filter (single-sided) in usecs */ u_int32_t rp_threshold; /* Threshold for MF output to indicate radar match */ u_int32_t rp_mindur; /* Min pulse duration to be considered for this pulse type */ u_int32_t rp_maxdur; /* Max pusle duration to be considered for this pulse type */ u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ u_int32_t rp_meanoffset; /* Offset for timing adjustment */ int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ /* lower than in non TURBO mode. This will be used to offset that diff.*/ u_int32_t rp_ignore_pri_window; u_int32_t rp_pulseid; /* Unique ID for identifying filter */ }; struct dfs_staggered_pulse { u_int32_t rp_numpulses; /* Num of pulses in radar burst */ u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ u_int32_t rp_min_pulsefreq; /* Frequency of pulses in burst */ u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ u_int32_t rp_patterntype; /* fixed or variable pattern type*/ u_int32_t rp_pulsevar; /* Time variation of pulse duration for matched filter (single-sided) in usecs */ u_int32_t rp_threshold; /* Thershold for MF output to indicateC radar match */ u_int32_t rp_mindur; /* Min pulse duration to be considered for this pulse type */ u_int32_t rp_maxdur; /* Max pusle duration to be considered for this pulse type */ u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ u_int32_t rp_meanoffset; /* Offset for timing adjustment */ int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ /* lower than in non TURBO mode. This will be used to offset that diff.*/ u_int32_t rp_pulseid; /* Unique ID for identifying filter */ }; struct dfs_bin5pulse { u_int32_t b5_threshold; /* Number of bin5 pulses to indicate detection */ u_int32_t b5_mindur; /* Min duration for a bin5 pulse */ u_int32_t b5_maxdur; /* Max duration for a bin5 pulse */ u_int32_t b5_timewindow; /* Window over which to count bin5 pulses */ u_int32_t b5_rssithresh; /* Min rssi to be considered a pulse */ u_int32_t b5_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dB */ }; #if 0 /* SPECTRAL SCAN defines begin */ typedef struct { u_int16_t ss_fft_period; /* Skip interval for FFT reports */ u_int16_t ss_period; /* Spectral scan period */ u_int16_t ss_count; /* # of reports to return from ss_active */ u_int16_t ss_short_report;/* Set to report ony 1 set of FFT results */ u_int8_t radar_bin_thresh_sel; u_int16_t ss_spectral_pri; /* are we doing a noise power cal ? */ int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */ int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */ int32_t ss_nf_temp_data; /* temperature data taken during nf scan */ } HAL_SPECTRAL_PARAM; #define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF #define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ #endif /* * Noise power data definitions * units are: 4 x dBm - NOISE_PWR_DATA_OFFSET (e.g. -25 = (-25/4 - 90) = -96.25 dBm) * range (for 6 signed bits) is (-32 to 31) + offset => -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_radar.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radar.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radar.c (revision 291437) @@ -1,601 +1,601 @@ /* * 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/ar9300phy.h" #include "ar9300/ar9300reg.h" /* * Default 5413/9300 radar phy parameters * Values adjusted to fix EV76432/EV76320 */ #define AR9300_DFS_FIRPWR -28 #define AR9300_DFS_RRSSI 0 #define AR9300_DFS_HEIGHT 10 #define AR9300_DFS_PRSSI 6 #define AR9300_DFS_INBAND 8 #define AR9300_DFS_RELPWR 8 #define AR9300_DFS_RELSTEP 12 #define AR9300_DFS_MAXLEN 255 /* * This PRSSI value should be used during CAC. */ #define AR9300_DFS_PRSSI_CAC 10 /* * make sure that value matches value in ar9300_osprey_2p2_mac_core[][2] * for register 0x1040 to 0x104c */ #define AR9300_DEFAULT_DIFS 0x002ffc0f #define AR9300_FCC_RADARS_FCC_OFFSET 4 struct dfs_pulse ar9300_etsi_radars[] = { /* for short pulses, RSSI threshold should be smaller than * Kquick-drop. The chip has only one chance to drop the gain which * will be reported as the estimated RSSI */ /* TYPE staggered pulse */ /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ /* constant PRF based */ /* 0.8-5us, 200 300 PRF, 10 pulses */ {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ // {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* 0.8-15us, 200-1600 PRF, 15 pulses */ {15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34}, /* Type 2 */ /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35}, /* Type 3 */ /* 20-30us, 2000-4000 PRF, 20 pulses*/ {20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ }; /* The following are for FCC Bin 1-4 pulses */ struct dfs_pulse ar9300_fcc_radars[] = { /* following two filters are specific to Japan/MKK4 */ // {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us // {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us // {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 0, 19}, // 3846 +/- 7 us {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us // {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us /* following filters are common to both FCC and JAPAN */ // FCC TYPE 1 // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0, 0}, // 518 to 3066 {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 8}, {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, // FCC TYPE 6 // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 1}, // 333 +/- 7 us //{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 1}, {9, 1, 3003, 3003, 0, 7, 5, 0, 1, 18, 0, 0, 1, 1}, // FCC TYPE 2 {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, // FCC TYPE 3 {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, // FCC TYPE 4 {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, }; struct dfs_bin5pulse ar9300_bin5pulses[] = { {2, 28, 105, 12, 22, 5}, }; #if 0 /* * Find the internal HAL channel corresponding to the * public HAL channel specified in c */ static HAL_CHANNEL_INTERNAL * getchannel(struct ath_hal *ah, const struct ieee80211_channel *c) { #define CHAN_FLAGS (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER) HAL_CHANNEL_INTERNAL *base, *cc; int flags = c->channel_flags & CHAN_FLAGS; int n, lim; /* * Check current channel to avoid the lookup. */ cc = AH_PRIVATE(ah)->ah_curchan; if (cc != AH_NULL && cc->channel == c->channel && (cc->channel_flags & CHAN_FLAGS) == flags) { return cc; } /* binary search based on known sorting order */ base = AH_TABLES(ah)->ah_channels; n = AH_PRIVATE(ah)->ah_nchan; /* binary search based on known sorting order */ for (lim = n; lim != 0; lim >>= 1) { int d; cc = &base[lim >> 1]; d = c->channel - cc->channel; if (d == 0) { if ((cc->channel_flags & CHAN_FLAGS) == flags) { return cc; } d = flags - (cc->channel_flags & CHAN_FLAGS); } HALDEBUG(ah, HAL_DEBUG_DFS, "%s: channel %u/0x%x d %d\n", __func__, cc->channel, cc->channel_flags, d); if (d > 0) { base = cc + 1; lim--; } } HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no match for %u/0x%x\n", __func__, c->channel, c->channel_flags); return AH_NULL; #undef CHAN_FLAGS } /* * Check the internal channel list to see if the desired channel * is ok to release from the NOL. If not, then do nothing. If so, * mark the channel as clear and reset the internal tsf time */ void ar9300_check_dfs(struct ath_hal *ah, struct ieee80211_channel *chan) { HAL_CHANNEL_INTERNAL *ichan = AH_NULL; ichan = getchannel(ah, chan); if (ichan == AH_NULL) { return; } if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { return; } ichan->priv_flags &= ~CHANNEL_INTERFERENCE; ichan->dfs_tsf = 0; } /* * This function marks the channel as having found a dfs event * It also marks the end time that the dfs event should be cleared * If the channel is already marked, then tsf end time can only * be increased */ void ar9300_dfs_found(struct ath_hal *ah, struct ieee80211_channel *chan, u_int64_t nol_time) { HAL_CHANNEL_INTERNAL *ichan; ichan = getchannel(ah, chan); if (ichan == AH_NULL) { return; } if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { ichan->dfs_tsf = ar9300_get_tsf64(ah); } ichan->dfs_tsf += nol_time; ichan->priv_flags |= CHANNEL_INTERFERENCE; chan->priv_flags |= CHANNEL_INTERFERENCE; } #endif /* * Enable radar detection and set the radar parameters per the * values in pe */ void ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { u_int32_t val; struct ath_hal_private *ahp = AH_PRIVATE(ah); const struct ieee80211_channel *chan = ahp->ah_curchan; struct ath_hal_9300 *ah9300 = AH9300(ah); int reg_writes = 0; val = OS_REG_READ(ah, AR_PHY_RADAR_0); val |= AR_PHY_RADAR_0_FFT_ENA | AR_PHY_RADAR_0_ENA; if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_FIRPWR; val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); } if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_RRSSI; val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); } if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_HEIGHT; val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); } if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_PRSSI; if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { #if 0 if (ah->ah_use_cac_prssi) { val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); } else { #endif val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); // } } else { val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } } if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_INBAND; val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); } OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); val = OS_REG_READ(ah, AR_PHY_RADAR_1); val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK; if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_MAXLEN; val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); } if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); } if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); } OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) { val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); if (IEEE80211_IS_CHAN_HT40(chan)) { /* Enable extension channel radar detection */ OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA); } else { /* HT20 mode, disable extension channel radar detect */ OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); } } /* apply DFS postamble array from INI column 0 is register ID, column 1 is HT20 value, colum2 is HT40 value */ if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) { REG_WRITE_ARRAY(&ah9300->ah_ini_dfs, IEEE80211_IS_CHAN_HT40(chan)? 2:1, reg_writes); } #ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128 ath_hal_printf(ah, "DFS change the timing value\n"); if (AR_SREV_AR9580(ah) && IEEE80211_IS_CHAN_HT40(chan)) { OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a); } #endif } /* * Get the radar parameter values and return them in the pe * structure */ void ar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { u_int32_t val, temp; val = OS_REG_READ(ah, AR_PHY_RADAR_0); temp = MS(val, AR_PHY_RADAR_0_FIRPWR); temp |= ~(AR_PHY_RADAR_0_FIRPWR >> AR_PHY_RADAR_0_FIRPWR_S); pe->pe_firpwr = temp; pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); val = OS_REG_READ(ah, AR_PHY_RADAR_1); pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_1_RELPWR_ENA); pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); pe->pe_en_relstep_check = !! (val & AR_PHY_RADAR_1_RELSTEP_CHECK); pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); } #if 0 HAL_BOOL ar9300_radar_wait(struct ath_hal *ah, struct ieee80211_channel *chan) { struct ath_hal_private *ahp = AH_PRIVATE(ah); if (!ahp->ah_curchan) { return AH_TRUE; } /* * Rely on the upper layers to determine that we have spent * enough time waiting. */ chan->channel = ahp->ah_curchan->channel; chan->channel_flags = ahp->ah_curchan->channel_flags; chan->max_reg_tx_power = ahp->ah_curchan->max_reg_tx_power; ahp->ah_curchan->priv_flags |= CHANNEL_DFS_CLEAR; chan->priv_flags = ahp->ah_curchan->priv_flags; return AH_FALSE; } #endif 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) { struct dfs_pulse *dfs_radars = AH_NULL; switch (dfsdomain) { case HAL_DFS_FCC_DOMAIN: dfs_radars = &ar9300_fcc_radars[AR9300_FCC_RADARS_FCC_OFFSET]; *numradars = ARRAY_LENGTH(ar9300_fcc_radars) - AR9300_FCC_RADARS_FCC_OFFSET; *bin5pulses = &ar9300_bin5pulses[0]; *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_FCC_DOMAIN_9300\n", __func__); break; case HAL_DFS_ETSI_DOMAIN: dfs_radars = &ar9300_etsi_radars[0]; *numradars = ARRAY_LENGTH(ar9300_etsi_radars); *bin5pulses = &ar9300_bin5pulses[0]; *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_ETSI_DOMAIN_9300\n", __func__); break; case HAL_DFS_MKK4_DOMAIN: dfs_radars = &ar9300_fcc_radars[0]; *numradars = ARRAY_LENGTH(ar9300_fcc_radars); *bin5pulses = &ar9300_bin5pulses[0]; *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_MKK4_DOMAIN_9300\n", __func__); break; default: HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no domain\n", __func__); return AH_NULL; } /* Set the default phy parameters per chip */ pe->pe_firpwr = AR9300_DFS_FIRPWR; pe->pe_rrssi = AR9300_DFS_RRSSI; pe->pe_height = AR9300_DFS_HEIGHT; pe->pe_prssi = AR9300_DFS_PRSSI; /* we have an issue with PRSSI. For normal operation we use AR9300_DFS_PRSSI, which is set to 6. Please refer to EV91563, 94164. However, this causes problem during CAC as no radar is detected during that period with PRSSI=6. Only PRSSI= 10 seems to fix this. We use this flag to keep track of change in PRSSI. */ // ah->ah_use_cac_prssi = 0; pe->pe_inband = AR9300_DFS_INBAND; pe->pe_relpwr = AR9300_DFS_RELPWR; pe->pe_relstep = AR9300_DFS_RELSTEP; pe->pe_maxlen = AR9300_DFS_MAXLEN; return dfs_radars; } void ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val) { if (val == 0) { /* * EV 116936: * Restore the register values with that of the HAL structure. * Do not assume and overwrite these values to whatever * is in ar9300_osprey22.ini. */ struct ath_hal_9300 *ahp = AH9300(ah); HAL_TX_QUEUE_INFO *qi; int q; AH9300(ah)->ah_fccaifs = 0; HALDEBUG(ah, HAL_DEBUG_DFS, "%s: restore DIFS \n", __func__); for (q = 0; q < 4; q++) { qi = &ahp->ah_txq[q]; OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(qi->tqi_cwmin, AR_D_LCL_IFS_CWMIN) | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); } } else { /* * These are values from George Lai and are specific to * FCC domain. They are yet to be determined for other domains. */ AH9300(ah)->ah_fccaifs = 1; HALDEBUG(ah, HAL_DEBUG_DFS, "%s: set DIFS to default\n", __func__); /*printk("%s: modify DIFS\n", __func__);*/ OS_REG_WRITE(ah, AR_DLCL_IFS(0), 0x05fffc0f); OS_REG_WRITE(ah, AR_DLCL_IFS(1), 0x05f0fc0f); OS_REG_WRITE(ah, AR_DLCL_IFS(2), 0x05f03c07); OS_REG_WRITE(ah, AR_DLCL_IFS(3), 0x05f01c03); } } u_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable) { u_int32_t val; val = OS_REG_READ(ah, AR_PHY_RADAR_0); if (is_enable) { val |= AR_PHY_RADAR_0_FFT_ENA; } else { val &= ~AR_PHY_RADAR_0_FFT_ENA; } OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); val = OS_REG_READ(ah, AR_PHY_RADAR_0); return val; } /* function to adjust PRSSI value for CAC problem */ void ar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start) { u_int32_t val; if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { val = OS_REG_READ(ah, AR_PHY_RADAR_0); if (start) { val &= ~AR_PHY_RADAR_0_PRSSI; val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); } else { val &= ~AR_PHY_RADAR_0_PRSSI; val |= SM(AR9300_DFS_PRSSI, AR_PHY_RADAR_0_PRSSI); } OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); // ah->ah_use_cac_prssi = start; } } #if 0 struct ieee80211_channel * ar9300_get_extension_channel(struct ath_hal *ah) { struct ath_hal_private *ahp = AH_PRIVATE(ah); struct ath_hal_private_tables *aht = AH_TABLES(ah); int i = 0; HAL_CHANNEL_INTERNAL *ichan = AH_NULL; CHAN_CENTERS centers; ichan = ahp->ah_curchan; ar9300_get_channel_centers(ah, ichan, ¢ers); if (centers.ctl_center == centers.ext_center) { return AH_NULL; } for (i = 0; i < ahp->ah_nchan; i++) { ichan = &aht->ah_channels[i]; if (ichan->channel == centers.ext_center) { return (struct ieee80211_channel*)ichan; } } return AH_NULL; } #endif HAL_BOOL ar9300_is_fast_clock_enabled(struct ath_hal *ah) { struct ath_hal_private *ahp = AH_PRIVATE(ah); if (IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan)) { return AH_TRUE; } return AH_FALSE; } /* * This should be enabled and linked into the build once * radar support is enabled. */ #if 0 HAL_BOOL ar9300_handle_radar_bb_panic(struct ath_hal *ah) { u_int32_t status; u_int32_t val; #ifdef AH_DEBUG struct ath_hal_9300 *ahp = AH9300(ah); #endif status = AH_PRIVATE(ah)->ah_bb_panic_last_status; if ( status == 0x04000539 ) { /* recover from this BB panic without reset*/ /* set AR9300_DFS_FIRPWR to -1 */ val = OS_REG_READ(ah, AR_PHY_RADAR_0); val &= (~AR_PHY_RADAR_0_FIRPWR); val |= SM( 0x7f, AR_PHY_RADAR_0_FIRPWR); OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); OS_DELAY(1); /* set AR9300_DFS_FIRPWR to its default value */ val = OS_REG_READ(ah, AR_PHY_RADAR_0); val &= ~AR_PHY_RADAR_0_FIRPWR; val |= SM( AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR); OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); return AH_TRUE; } else if (status == 0x0400000a) { /* EV 92527 : reset required if we see this signature */ HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x0400000a\n", __func__); return AH_FALSE; } else if (status == 0x1300000a) { /* EV92527: we do not need a reset if we see this signature */ HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x1300000a\n", __func__); return AH_TRUE; - } else if (AR_SREV_WASP(ah) && (status == 0x04000409)) { + } else if ((AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) && (status == 0x04000409)) { return AH_TRUE; } else { if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK && (status & 0xff00000f) == 0x04000009 && status != 0x04000409 && status != 0x04000b09 && status != 0x04000e09 && (status & 0x0000ff00)) { /* disable RIFS Rx */ #ifdef AH_DEBUG HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: BB status=0x%08x rifs=%d - disable\n", __func__, status, ahp->ah_rifs_enabled); ar9300_set_rifs_delay(ah, AH_FALSE); } return AH_FALSE; } } #endif #endif Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c (revision 291437) @@ -1,267 +1,267 @@ /* * 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" #include "ar9300/ar9300phy.h" /* chansel table, used by Hornet and Poseidon */ static const u_int32_t ar9300_chansel_xtal_25M[] = { 0x101479e, /* Freq 2412 - (128 << 17) + 83870 */ 0x101d027, /* Freq 2417 - (128 << 17) + 118823 */ 0x10258af, /* Freq 2422 - (129 << 17) + 22703 */ 0x102e138, /* Freq 2427 - (129 << 17) + 57656 */ 0x10369c0, /* Freq 2432 - (129 << 17) + 92608 */ 0x103f249, /* Freq 2437 - (129 << 17) + 127561 */ 0x1047ad1, /* Freq 2442 - (130 << 17) + 31441 */ 0x105035a, /* Freq 2447 - (130 << 17) + 66394 */ 0x1058be2, /* Freq 2452 - (130 << 17) + 101346 */ 0x106146b, /* Freq 2457 - (131 << 17) + 5227 */ 0x1069cf3, /* Freq 2462 - (131 << 17) + 40179 */ 0x107257c, /* Freq 2467 - (131 << 17) + 75132 */ 0x107ae04, /* Freq 2472 - (131 << 17) + 110084 */ 0x108f5b2, /* Freq 2484 - (132 << 17) + 62898 */ }; static const u_int32_t ar9300_chansel_xtal_40M[] = { 0xa0ccbe, /* Freq 2412 - (80 << 17) + 52414 */ 0xa12213, /* Freq 2417 - (80 << 17) + 74259 */ 0xa17769, /* Freq 2422 - (80 << 17) + 96105 */ 0xa1ccbe, /* Freq 2427 - (80 << 17) + 117950 */ 0xa22213, /* Freq 2432 - (81 << 17) + 8723 */ 0xa27769, /* Freq 2437 - (81 << 17) + 30569 */ 0xa2ccbe, /* Freq 2442 - (81 << 17) + 52414 */ 0xa32213, /* Freq 2447 - (81 << 17) + 74259 */ 0xa37769, /* Freq 2452 - (81 << 17) + 96105 */ 0xa3ccbe, /* Freq 2457 - (81 << 17) + 117950 */ 0xa42213, /* Freq 2462 - (82 << 17) + 8723 */ 0xa47769, /* Freq 2467 - (82 << 17) + 30569 */ 0xa4ccbe, /* Freq 2472 - (82 << 17) + 52414 */ 0xa5998b, /* Freq 2484 - (82 << 17) + 104843 */ }; /* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus * * Actual Expression, * * For 2GHz channel, * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) * * For 5GHz channel, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) * (freq_ref = 40MHz/(24>>amode_ref_sel)) * * For 5GHz channels which are 5MHz spaced, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) */ static HAL_BOOL ar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0; u_int32_t freq, channel_sel, reg32; u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; CHAN_CENTERS centers; int load_synth_channel; HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); /* * Put this behind AH_DEBUG_ALQ for now until the Hornet * channel_sel code below is made to work. */ #ifdef AH_DEBUG_ALQ OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel); #endif ar9300_get_channel_centers(ah, chan, ¢ers); freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ b_mode = 1; /* 2 GHz */ if (AR_SREV_HORNET(ah)) { #if 0 u_int32_t ichan = ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags); HALASSERT(ichan > 0 && ichan <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[ichan - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[ichan - 1]; } #endif uint32_t i; i = ath_hal_mhz2ieee_2ghz(ah, ichan); HALASSERT(i > 0 && i <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[i - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[i - 1]; } } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { u_int32_t channel_frac; /* * freq_ref = (40 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; channel_sel = (channel_sel << 17) | (channel_frac); - } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { + } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { u_int32_t channel_frac; if (clk_25mhz) { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ - if (AR_SREV_SCORPION(ah)) { + if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 75; channel_frac = (((freq * 4) % 75) * 0x20000) / 75; } else { channel_sel = (freq * 2) / 75; channel_frac = (((freq * 2) % 75) * 0x20000) / 75; } } else { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ if (AR_SREV_SCORPION(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; } else { channel_sel = (freq * 2) / 120; channel_frac = (((freq * 2) % 120) * 0x20000) / 120; } } channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_2G(freq); } } else { b_mode = 0; /* 5 GHz */ if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){ u_int32_t channel_frac; /* * freq_ref = (50 / (refdiva >> amoderefsel)); * (refdiva = 1, amoderefsel = 0) * ndiv = ((chan_mhz * 2) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = freq / 75 ; channel_frac = ((freq % 75) * 0x20000) / 75; channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_5G(freq); /* Doubler is ON, so, divide channel_sel by 2. */ channel_sel >>= 1; } } /* Enable fractional mode for all channels */ frac_mode = 1; a_mode_ref_sel = 0; load_synth_channel = 0; reg32 = (b_mode << 29); OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); /* Enable Long shift Select for Synthesizer */ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); /* program synth. setting */ reg32 = (channel_sel << 2) | (a_mode_ref_sel << 28) | (frac_mode << 30) | (load_synth_channel << 31); if (IEEE80211_IS_CHAN_QUARTER(chan)) { reg32 += CHANSEL_5G_DOT5MHZ; } OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); /* Toggle Load Synth channel bit */ load_synth_channel = 1; reg32 |= load_synth_channel << 31; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE; } #if 0 static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans) { int i; for (i = 0; i < nchans; i++) { chans[i].max_tx_power = AR9300_MAX_RATE_POWER; chans[i].min_tx_power = AR9300_MAX_RATE_POWER; } return AH_TRUE; } #endif /* XXX FreeBSD */ static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah, struct ieee80211_channel *chan) { /* XXX ? */ chan->ic_minpower = 0; chan->ic_maxpower = AR9300_MAX_RATE_POWER; return AH_TRUE; } HAL_BOOL ar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status) { struct ath_hal_9300 *ahp = AH9300(ah); ahp->ah_rf_hal.set_channel = ar9300_set_channel; ahp->ah_rf_hal.get_chip_power_lim = ar9300_get_chip_power_limits; *status = HAL_OK; return AH_TRUE; } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c (revision 291437) @@ -1,342 +1,342 @@ /* * 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" /* * Get the RXDP. */ u_int32_t ar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype) { if (qtype == HAL_RX_QUEUE_HP) { return OS_REG_READ(ath, AR_HP_RXDP); } else { return OS_REG_READ(ath, AR_LP_RXDP); } } /* * Set the rx_dp. */ void ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype) { HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP)); if (qtype == HAL_RX_QUEUE_HP) { OS_REG_WRITE(ah, AR_HP_RXDP, rxdp); } else { OS_REG_WRITE(ah, AR_LP_RXDP, rxdp); } } /* * Set Receive Enable bits. */ void ar9300_enable_receive(struct ath_hal *ah) { OS_REG_WRITE(ah, AR_CR, 0); } /* * Set the RX abort bit. */ HAL_BOOL ar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set) { if (set) { /* Set the force_rx_abort bit */ OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){ /* depending upon the BB panic status, rx state may not return to 0, * so skipping the wait for BB panic reset */ OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); return AH_FALSE; } else { HAL_BOOL okay; okay = ath_hal_wait( ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0); /* Wait for Rx state to return to 0 */ if (!okay) { /* abort: chip rx failed to go idle in 10 ms */ OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); HALDEBUG(ah, HAL_DEBUG_RX, "%s: rx failed to go idle in 10 ms RXSM=0x%x\n", __func__, OS_REG_READ(ah, AR_OBS_BUS_1)); return AH_FALSE; /* failure */ } } } else { OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); } return AH_TRUE; /* success */ } /* * Stop Receive at the DMA engine */ HAL_BOOL ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout) { int wait; HAL_BOOL status, okay; u_int32_t org_value; #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ #define AH_TIME_QUANTUM 100 /* usec */ OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP); if (timeout == 0) { timeout = AH_RX_STOP_DMA_TIMEOUT; } org_value = OS_REG_READ(ah, AR_MACMISC); 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))); okay = ath_hal_wait( ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0); /* wait for Rx DMA state machine to become idle */ if (!okay) { HALDEBUG(ah, HAL_DEBUG_RX, "reg AR_DMADBG_7 is not 0, instead 0x%08x\n", OS_REG_READ(ah, AR_DMADBG_7)); } /* Set receive disable bit */ OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Wait for rx enable bit to go low */ for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) { break; } OS_DELAY(AH_TIME_QUANTUM); } if (wait == 0) { HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n" "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__, timeout / 1000, OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW)); status = AH_FALSE; } else { status = AH_TRUE; } OS_REG_WRITE(ah, AR_MACMISC, org_value); OS_MARK(ah, AH_MARK_RX_CTL, status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR); return status; #undef AH_RX_STOP_DMA_TIMEOUT #undef AH_TIME_QUANTUM } /* * Start Transmit at the PCU engine (unpause receive) */ void ar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning) { ar9300_enable_mib_counters(ah); ar9300_ani_reset(ah, is_scanning); /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */ OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); } /* * Stop Transmit at the PCU engine (pause receive) */ void ar9300_stop_pcu_receive(struct ath_hal *ah) { OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ar9300_disable_mib_counters(ah); } /* * Set multicast filter 0 (lower 32-bits) * filter 1 (upper 32-bits) */ void ar9300_set_multicast_filter( struct ath_hal *ah, u_int32_t filter0, u_int32_t filter1) { OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); } /* * Get the receive filter. */ u_int32_t ar9300_get_rx_filter(struct ath_hal *ah) { u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER); u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR); if (phybits & AR_PHY_ERR_RADAR) { bits |= HAL_RX_FILTER_PHYRADAR; } if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) { bits |= HAL_RX_FILTER_PHYERR; } return bits; } /* * Set the receive filter. */ void ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits) { u_int32_t phybits; - if (AR_SREV_SCORPION(ah)) { + if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { /* Enable Rx for 4 address frames */ bits |= AR_RX_4ADDRESS; } if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* HW fix for rx hang and corruption. */ bits |= AR_RX_CONTROL_WRAPPER; } OS_REG_WRITE(ah, AR_RX_FILTER, bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR); phybits = 0; if (bits & HAL_RX_FILTER_PHYRADAR) { phybits |= AR_PHY_ERR_RADAR; } if (bits & HAL_RX_FILTER_PHYERR) { phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; } OS_REG_WRITE(ah, AR_PHY_ERR, phybits); if (phybits) { OS_REG_WRITE(ah, AR_RXCFG, OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); } else { OS_REG_WRITE(ah, AR_RXCFG, OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); } } /* * Select to pass PLCP headr or EVM data. */ HAL_BOOL ar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query) { struct ath_hal_9300 *ahp = AH9300(ah); HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0; if (just_query) { return old_value; } if (sel_evm) { OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); } else { OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); } ahp->ah_get_plcp_hdr = !sel_evm; return old_value; } void ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable) { u_int32_t reg_val = 0; reg_val = OS_REG_READ(ah, AR_RX_FILTER); if (enable){ reg_val |= AR_RX_PROM; } else{ /*Disable promisc mode */ reg_val &= ~AR_RX_PROM; } OS_REG_WRITE(ah, AR_RX_FILTER, reg_val); } void ar9300_read_pktlog_reg( struct ath_hal *ah, u_int32_t *rxfilter_val, u_int32_t *rxcfg_val, u_int32_t *phy_err_mask_val, u_int32_t *mac_pcu_phy_err_regval) { *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER); *rxcfg_val = OS_REG_READ(ah, AR_RXCFG); *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR); *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338); HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, " "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", __func__, __LINE__, *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval); } void ar9300_write_pktlog_reg( struct ath_hal *ah, HAL_BOOL enable, u_int32_t rxfilter_val, u_int32_t rxcfg_val, u_int32_t phy_err_mask_val, u_int32_t mac_pcu_phy_err_reg_val) { if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { /* HW fix for rx hang and corruption. */ rxfilter_val |= AR_RX_CONTROL_WRAPPER; } if (enable) { /* Enable pktlog phyerr setting */ OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val); OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF); OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA); OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF); } else { /* Disable phyerr and Restore regs */ OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val); OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val); OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val); OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val); } HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, " "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", __func__, __LINE__, enable, rxfilter_val, rxcfg_val, phy_err_mask_val, mac_pcu_phy_err_reg_val); } Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c (revision 291437) @@ -1,6409 +1,6463 @@ /* * 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)) { + } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(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)) { + } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(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; + if (AR_SREV_HONEYBEE(ah)) { + pll2_divint = 0x1c; + pll2_divfrac = 0xa3d2; + refdiv = 1; + } 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); + if (AR_SREV_HONEYBEE(ah)) { + regdata = regdata | (0x1 << 22); + } else { + 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 if (AR_SREV_HONEYBEE(ah)) { + /* + * Kd=10, Ki=2, Outdiv=1, Local PLL=0, Phase Shift=4 + */ + regdata = (regdata & 0x01c00fff) | + (0x1 << 31) | (0x2 << 29) | (0xa << 25) | (0x1 << 19) | (0x6 << 12); } 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); + if (AR_SREV_HONEYBEE(ah)) { + regdata = (regdata & 0xffbfffff); + } else { + 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); + /* XXX TODO: honeybee? */ 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); HALDEBUG(ah, HAL_DEBUG_RESET, "check DDR Activity - HIGH\n"); count = 0; while (DDR_CTL_CONFIG_CLIENT_ACTIVITY_GET(data)) { // AVE_DEBUG(0,"DDR Activity - HIGH\n"); HALDEBUG(ah, HAL_DEBUG_RESET, "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); HALDEBUG(ah, HAL_DEBUG_RESET, "%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))); } + else if (AR_SREV_HONEYBEE(ah)) { + REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12))); + } #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)) { + } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(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)) { + if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(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); } } 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; + freq_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; + freq_index = 1; break; case CHANNEL_PUREG: case CHANNEL_G_HT20: case CHANNEL_B: if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 8; - } + }else if (AR_SREV_HONEYBEE(ah)){ + modes_txgaintable_index = 1; + } modes_index = 4; + freq_index = 2; break; case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: if (AR_SREV_SCORPION(ah)){ modes_txgaintable_index = 7; + }else if (AR_SREV_HONEYBEE(ah)){ + modes_txgaintable_index = 1; } modes_index = 3; + freq_index = 2; break; case CHANNEL_108G: modes_index = 5; + freq_index = 2; 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; + } else if (AR_SREV_HONEYBEE(ah)){ + modes_txgaintable_index = 1; } 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; + } else if (AR_SREV_HONEYBEE(ah)){ + modes_txgaintable_index = 1; } 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)) { + if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(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)) { + } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(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 (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 + * rx_clear 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 + u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; 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" + * where we return 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)) { 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 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; } /* FreeBSD: clear the channel survey data */ ath_hal_survey_clear(ah); /* * 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; } + + /* + * Configuring WMAC PLL values for 25/40 MHz + */ + if(AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah) || AR_SREV_SCORPION(ah) ) { + if(clk_25mhz) { + OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x17c << 1)); // 32KHz sleep clk + } else { + OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x261 << 1)); // 32KHz sleep clk + } + OS_DELAY(100); + } 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)) { + if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(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)) { + if ( AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(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))); } + } + else if (AR_SREV_HONEYBEE(ah)) { + REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x32) ); + REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) )))); } #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; } /* XXX TODO: Add AR9565 support? */ } #endif /* ATH_ANT_DIV_COMB */ Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h (revision 291436) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300reg.h (revision 291437) @@ -1,3128 +1,3148 @@ /* * 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 _DEV_ATH_AR9300REG_H #define _DEV_ATH_AR9300REG_H #include "osprey_reg_map.h" #include "wasp_reg_map.h" /****************************************************************************** * MAC Register Map ******************************************************************************/ #define AR_MAC_DMA_OFFSET(_x) offsetof(struct mac_dma_reg, _x) /* * MAC DMA Registers */ /* MAC Control Register - only write values of 1 have effect */ #define AR_CR AR_MAC_DMA_OFFSET(MAC_DMA_CR) #define AR_CR_LP_RXE 0x00000004 // Receive LPQ enable #define AR_CR_HP_RXE 0x00000008 // Receive HPQ enable #define AR_CR_RXD 0x00000020 // Receive disable #define AR_CR_SWI 0x00000040 // One-shot software interrupt #define AR_CR_RXE (AR_CR_LP_RXE|AR_CR_HP_RXE) /* MAC configuration and status register */ #define AR_CFG AR_MAC_DMA_OFFSET(MAC_DMA_CFG) #define AR_CFG_SWTD 0x00000001 // byteswap tx descriptor words #define AR_CFG_SWTB 0x00000002 // byteswap tx data buffer words #define AR_CFG_SWRD 0x00000004 // byteswap rx descriptor words #define AR_CFG_SWRB 0x00000008 // byteswap rx data buffer words #define AR_CFG_SWRG 0x00000010 // byteswap register access data words #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 // AP/adhoc indication (0-AP 1-Adhoc) #define AR_CFG_PHOK 0x00000100 // PHY OK status #define AR_CFG_CLK_GATE_DIS 0x00000400 // Clock gating disable #define AR_CFG_EEBS 0x00000200 // EEPROM busy #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 // Mask of PCI core master request queue full threshold #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 // Shift for PCI core master request queue full threshold #define AR_CFG_MISSING_TX_INTR_FIX_ENABLE 0x00080000 // See EV 61133 for details. /* Rx DMA Data Buffer Pointer Threshold - High and Low Priority register */ #define AR_RXBP_THRESH AR_MAC_DMA_OFFSET(MAC_DMA_RXBUFPTR_THRESH) #define AR_RXBP_THRESH_HP 0x0000000f #define AR_RXBP_THRESH_HP_S 0 #define AR_RXBP_THRESH_LP 0x00003f00 #define AR_RXBP_THRESH_LP_S 8 /* Tx DMA Descriptor Pointer Threshold register */ #define AR_TXDP_THRESH AR_MAC_DMA_OFFSET(MAC_DMA_TXDPPTR_THRESH) /* Mac Interrupt rate threshold register */ #define AR_MIRT AR_MAC_DMA_OFFSET(MAC_DMA_MIRT) #define AR_MIRT_VAL 0x0000ffff // in uS #define AR_MIRT_VAL_S 16 /* MAC Global Interrupt enable register */ #define AR_IER AR_MAC_DMA_OFFSET(MAC_DMA_GLOBAL_IER) #define AR_IER_ENABLE 0x00000001 // Global interrupt enable #define AR_IER_DISABLE 0x00000000 // Global interrupt disable /* Mac Tx Interrupt mitigation threshold */ #define AR_TIMT AR_MAC_DMA_OFFSET(MAC_DMA_TIMT) #define AR_TIMT_LAST 0x0000ffff // Last packet threshold #define AR_TIMT_LAST_S 0 #define AR_TIMT_FIRST 0xffff0000 // First packet threshold #define AR_TIMT_FIRST_S 16 /* Mac Rx Interrupt mitigation threshold */ #define AR_RIMT AR_MAC_DMA_OFFSET(MAC_DMA_RIMT) #define AR_RIMT_LAST 0x0000ffff // Last packet threshold #define AR_RIMT_LAST_S 0 #define AR_RIMT_FIRST 0xffff0000 // First packet threshold #define AR_RIMT_FIRST_S 16 #define AR_DMASIZE_4B 0x00000000 // DMA size 4 bytes (TXCFG + RXCFG) #define AR_DMASIZE_8B 0x00000001 // DMA size 8 bytes #define AR_DMASIZE_16B 0x00000002 // DMA size 16 bytes #define AR_DMASIZE_32B 0x00000003 // DMA size 32 bytes #define AR_DMASIZE_64B 0x00000004 // DMA size 64 bytes #define AR_DMASIZE_128B 0x00000005 // DMA size 128 bytes #define AR_DMASIZE_256B 0x00000006 // DMA size 256 bytes #define AR_DMASIZE_512B 0x00000007 // DMA size 512 bytes /* MAC Tx DMA size config register */ #define AR_TXCFG AR_MAC_DMA_OFFSET(MAC_DMA_TXCFG) #define AR_TXCFG_DMASZ_MASK 0x00000007 #define AR_TXCFG_DMASZ_4B 0 #define AR_TXCFG_DMASZ_8B 1 #define AR_TXCFG_DMASZ_16B 2 #define AR_TXCFG_DMASZ_32B 3 #define AR_TXCFG_DMASZ_64B 4 #define AR_TXCFG_DMASZ_128B 5 #define AR_TXCFG_DMASZ_256B 6 #define AR_TXCFG_DMASZ_512B 7 #define AR_FTRIG 0x000003F0 // Mask for Frame trigger level #define AR_FTRIG_S 4 // Shift for Frame trigger level #define AR_FTRIG_IMMED 0x00000000 // bytes in PCU TX FIFO before air #define AR_FTRIG_64B 0x00000010 // default #define AR_FTRIG_128B 0x00000020 #define AR_FTRIG_192B 0x00000030 #define AR_FTRIG_256B 0x00000040 // 5 bits total #define AR_FTRIG_512B 0x00000080 // 5 bits total #define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800 #define AR_TXCFG_RTS_FAIL_EXCESSIVE_RETRIES 0x00080000 #define AR_TXCFG_RTS_FAIL_EXCESSIVE_RETRIES_S 19 /* MAC Rx DMA size config register */ #define AR_RXCFG AR_MAC_DMA_OFFSET(MAC_DMA_RXCFG) #define AR_RXCFG_CHIRP 0x00000008 // Only double chirps #define AR_RXCFG_ZLFDMA 0x00000010 // Enable DMA of zero-length frame #define AR_RXCFG_DMASZ_MASK 0x00000007 #define AR_RXCFG_DMASZ_4B 0 #define AR_RXCFG_DMASZ_8B 1 #define AR_RXCFG_DMASZ_16B 2 #define AR_RXCFG_DMASZ_32B 3 #define AR_RXCFG_DMASZ_64B 4 #define AR_RXCFG_DMASZ_128B 5 #define AR_RXCFG_DMASZ_256B 6 #define AR_RXCFG_DMASZ_512B 7 /* MAC Rx jumbo descriptor last address register */ #define AR_RXJLA AR_MAC_DMA_OFFSET(MAC_DMA_RXJLA) /* MAC MIB control register */ #define AR_MIBC AR_MAC_DMA_OFFSET(MAC_DMA_MIBC) #define AR_MIBC_COW 0x00000001 // counter overflow warning #define AR_MIBC_FMC 0x00000002 // freeze MIB counters #define AR_MIBC_CMC 0x00000004 // clear MIB counters #define AR_MIBC_MCS 0x00000008 // MIB counter strobe increment all /* MAC timeout prescale count */ #define AR_TOPS AR_MAC_DMA_OFFSET(MAC_DMA_TOPS) #define AR_TOPS_MASK 0x0000FFFF // Mask for timeout prescale /* MAC no frame received timeout */ #define AR_RXNPTO AR_MAC_DMA_OFFSET(MAC_DMA_RXNPTO) #define AR_RXNPTO_MASK 0x000003FF // Mask for no frame received timeout /* MAC no frame trasmitted timeout */ #define AR_TXNPTO AR_MAC_DMA_OFFSET(MAC_DMA_TXNPTO) #define AR_TXNPTO_MASK 0x000003FF // Mask for no frame transmitted timeout #define AR_TXNPTO_QCU_MASK 0x000FFC00 // Mask indicating the set of QCUs // for which frame completions will cause // a reset of the no frame transmitted timeout /* MAC receive frame gap timeout */ #define AR_RPGTO AR_MAC_DMA_OFFSET(MAC_DMA_RPGTO) #define AR_RPGTO_MASK 0x000003FF // Mask for receive frame gap timeout /* MAC miscellaneous control/status register */ #define AR_MACMISC AR_MAC_DMA_OFFSET(MAC_DMA_MACMISC) #define AR_MACMISC_PCI_EXT_FORCE 0x00000010 //force msb to 10 to ahb #define AR_MACMISC_DMA_OBS 0x000001E0 // Mask for DMA observation bus mux select #define AR_MACMISC_DMA_OBS_S 5 // Shift for DMA observation bus mux select #define AR_MACMISC_DMA_OBS_LINE_0 0 // Observation DMA line 0 #define AR_MACMISC_DMA_OBS_LINE_1 1 // Observation DMA line 1 #define AR_MACMISC_DMA_OBS_LINE_2 2 // Observation DMA line 2 #define AR_MACMISC_DMA_OBS_LINE_3 3 // Observation DMA line 3 #define AR_MACMISC_DMA_OBS_LINE_4 4 // Observation DMA line 4 #define AR_MACMISC_DMA_OBS_LINE_5 5 // Observation DMA line 5 #define AR_MACMISC_DMA_OBS_LINE_6 6 // Observation DMA line 6 #define AR_MACMISC_DMA_OBS_LINE_7 7 // Observation DMA line 7 #define AR_MACMISC_DMA_OBS_LINE_8 8 // Observation DMA line 8 #define AR_MACMISC_MISC_OBS 0x00000E00 // Mask for MISC observation bus mux select #define AR_MACMISC_MISC_OBS_S 9 // Shift for MISC observation bus mux select #define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000 // Mask for MAC observation bus mux select (lsb) #define AR_MACMISC_MISC_OBS_BUS_LSB_S 12 // Shift for MAC observation bus mux select (lsb) #define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000 // Mask for MAC observation bus mux select (msb) #define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 // Shift for MAC observation bus mux select (msb) #define AR_MACMISC_MISC_OBS_BUS_1 1 // MAC observation bus mux select /* MAC Interrupt Config register */ #define AR_INTCFG AR_MAC_DMA_OFFSET(MAC_DMA_INTER) #define AR_INTCFG_REQ 0x00000001 // Interrupt request flag // Indicates whether the DMA engine should generate // an interrupt upon completion of the frame #define AR_INTCFG_MSI_RXOK 0x00000000 // Rx interrupt for MSI logic is RXOK #define AR_INTCFG_MSI_RXINTM 0x00000004 // Rx interrupt for MSI logic is RXINTM #define AR_INTCFG_MSI_RXMINTR 0x00000006 // Rx interrupt for MSI logic is RXMINTR #define AR_INTCFG_MSI_TXOK 0x00000000 // Rx interrupt for MSI logic is TXOK #define AR_INTCFG_MSI_TXINTM 0x00000010 // Rx interrupt for MSI logic is TXINTM #define AR_INTCFG_MSI_TXMINTR 0x00000018 // Rx interrupt for MSI logic is TXMINTR /* MAC DMA Data Buffer length, in bytes */ #define AR_DATABUF AR_MAC_DMA_OFFSET(MAC_DMA_DATABUF) #define AR_DATABUF_MASK 0x00000FFF /* MAC global transmit timeout */ #define AR_GTXTO AR_MAC_DMA_OFFSET(MAC_DMA_GTT) #define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) #define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) #define AR_GTXTO_TIMEOUT_LIMIT_S 16 // Shift for timeout limit /* MAC global transmit timeout mode */ #define AR_GTTM AR_MAC_DMA_OFFSET(MAC_DMA_GTTM) #define AR_GTTM_USEC 0x00000001 // usec strobe #define AR_GTTM_IGNORE_IDLE 0x00000002 // ignore channel idle #define AR_GTTM_RESET_IDLE 0x00000004 // reset counter on channel idle low #define AR_GTTM_CST_USEC 0x00000008 // CST usec strobe /* MAC carrier sense timeout */ #define AR_CST AR_MAC_DMA_OFFSET(MAC_DMA_CST) #define AR_CST_TIMEOUT_COUNTER 0x0000FFFF // Mask for timeout counter (in TUs) #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 // Mask for timeout limit (in TUs) #define AR_CST_TIMEOUT_LIMIT_S 16 // Shift for timeout limit /* MAC Indicates the size of High and Low priority rx_dp FIFOs */ #define AR_RXDP_SIZE AR_MAC_DMA_OFFSET(MAC_DMA_RXDP_SIZE) #define AR_RXDP_LP_SZ_MASK 0x0000007f #define AR_RXDP_LP_SZ_S 0 #define AR_RXDP_HP_SZ_MASK 0x00001f00 #define AR_RXDP_HP_SZ_S 8 /* MAC Rx High Priority Queue RXDP Pointer (lower 32 bits) */ #define AR_HP_RXDP AR_MAC_DMA_OFFSET(MAC_DMA_RX_QUEUE_HP_RXDP) /* MAC Rx Low Priority Queue RXDP Pointer (lower 32 bits) */ #define AR_LP_RXDP AR_MAC_DMA_OFFSET(MAC_DMA_RX_QUEUE_LP_RXDP) /* Primary Interrupt Status Register */ #define AR_ISR AR_MAC_DMA_OFFSET(MAC_DMA_ISR_P) #define AR_ISR_HP_RXOK 0x00000001 // At least one frame rx on high-priority queue sans errors #define AR_ISR_LP_RXOK 0x00000002 // At least one frame rx on low-priority queue sans errors #define AR_ISR_RXERR 0x00000004 // Receive error interrupt #define AR_ISR_RXNOPKT 0x00000008 // No frame received within timeout clock #define AR_ISR_RXEOL 0x00000010 // Received descriptor empty interrupt #define AR_ISR_RXORN 0x00000020 // Receive FIFO overrun interrupt #define AR_ISR_TXOK 0x00000040 // Transmit okay interrupt #define AR_ISR_TXERR 0x00000100 // Transmit error interrupt #define AR_ISR_TXNOPKT 0x00000200 // No frame transmitted interrupt #define AR_ISR_TXEOL 0x00000400 // Transmit descriptor empty interrupt #define AR_ISR_TXURN 0x00000800 // Transmit FIFO underrun interrupt #define AR_ISR_MIB 0x00001000 // MIB interrupt - see MIBC #define AR_ISR_SWI 0x00002000 // Software interrupt #define AR_ISR_RXPHY 0x00004000 // PHY receive error interrupt #define AR_ISR_RXKCM 0x00008000 // Key-cache miss interrupt #define AR_ISR_SWBA 0x00010000 // Software beacon alert interrupt #define AR_ISR_BRSSI 0x00020000 // Beacon threshold interrupt #define AR_ISR_BMISS 0x00040000 // Beacon missed interrupt #define AR_ISR_TXMINTR 0x00080000 // Maximum interrupt transmit rate #define AR_ISR_BNR 0x00100000 // Beacon not ready interrupt #define AR_ISR_RXCHIRP 0x00200000 // Phy received a 'chirp' #define AR_ISR_HCFPOLL 0x00400000 // Received directed HCF poll #define AR_ISR_BCNMISC 0x00800000 // CST, GTT, TIM, CABEND, DTIMSYNC, BCNTO, CABTO, // TSFOOR, DTIM, and TBTT_TIME bits bits from ISR_S2 #define AR_ISR_TIM 0x00800000 // TIM interrupt #define AR_ISR_RXMINTR 0x01000000 // Maximum interrupt receive rate #define AR_ISR_QCBROVF 0x02000000 // QCU CBR overflow interrupt #define AR_ISR_QCBRURN 0x04000000 // QCU CBR underrun interrupt #define AR_ISR_QTRIG 0x08000000 // QCU scheduling trigger interrupt #define AR_ISR_GENTMR 0x10000000 // OR of generic timer bits in ISR 5 #define AR_ISR_HCFTO 0x20000000 // HCF poll timeout #define AR_ISR_TXINTM 0x40000000 // Tx interrupt after mitigation #define AR_ISR_RXINTM 0x80000000 // Rx interrupt after mitigation /* MAC Secondary interrupt status register 0 */ #define AR_ISR_S0 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S0) #define AR_ISR_S0_QCU_TXOK 0x000003FF // Mask for TXOK (QCU 0-9) #define AR_ISR_S0_QCU_TXOK_S 0 // Shift for TXOK (QCU 0-9) /* MAC Secondary interrupt status register 1 */ #define AR_ISR_S1 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S1) #define AR_ISR_S1_QCU_TXERR 0x000003FF // Mask for TXERR (QCU 0-9) #define AR_ISR_S1_QCU_TXERR_S 0 // Shift for TXERR (QCU 0-9) #define AR_ISR_S1_QCU_TXEOL 0x03FF0000 // Mask for TXEOL (QCU 0-9) #define AR_ISR_S1_QCU_TXEOL_S 16 // Shift for TXEOL (QCU 0-9) /* MAC Secondary interrupt status register 2 */ #define AR_ISR_S2 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S2) #define AR_ISR_S2_QCU_TXURN 0x000003FF // Mask for TXURN (QCU 0-9) #define AR_ISR_S2_BBPANIC 0x00010000 // Panic watchdog IRQ from BB #define AR_ISR_S2_CST 0x00400000 // Carrier sense timeout #define AR_ISR_S2_GTT 0x00800000 // Global transmit timeout #define AR_ISR_S2_TIM 0x01000000 // TIM #define AR_ISR_S2_CABEND 0x02000000 // CABEND #define AR_ISR_S2_DTIMSYNC 0x04000000 // DTIMSYNC #define AR_ISR_S2_BCNTO 0x08000000 // BCNTO #define AR_ISR_S2_CABTO 0x10000000 // CABTO #define AR_ISR_S2_DTIM 0x20000000 // DTIM #define AR_ISR_S2_TSFOOR 0x40000000 // Rx TSF out of range #define AR_ISR_S2_TBTT_TIME 0x80000000 // TBTT-referenced timer /* MAC Secondary interrupt status register 3 */ #define AR_ISR_S3 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S3) #define AR_ISR_S3_QCU_QCBROVF 0x000003FF // Mask for QCBROVF (QCU 0-9) #define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 // Mask for QCBRURN (QCU 0-9) /* MAC Secondary interrupt status register 4 */ #define AR_ISR_S4 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S4) #define AR_ISR_S4_QCU_QTRIG 0x000003FF // Mask for QTRIG (QCU 0-9) #define AR_ISR_S4_RESV0 0xFFFFFC00 // Reserved /* MAC Secondary interrupt status register 5 */ #define AR_ISR_S5 AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S5) #define AR_ISR_S5_TIMER_TRIG 0x000000FF // Mask for timer trigger (0-7) #define AR_ISR_S5_TIMER_THRESH 0x0007FE00 // Mask for timer threshold(0-7) #define AR_ISR_S5_TIM_TIMER 0x00000010 // TIM Timer ISR #define AR_ISR_S5_DTIM_TIMER 0x00000020 // DTIM Timer ISR #define AR_ISR_S5_GENTIMER_TRIG 0x0000FF80 // ISR for generic timer trigger 7 #define AR_ISR_S5_GENTIMER_TRIG_S 0 #define AR_ISR_S5_GENTIMER_THRESH 0xFF800000 // ISR for generic timer threshold 7 #define AR_ISR_S5_GENTIMER_THRESH_S 16 /* Primary Interrupt Mask Register */ #define AR_IMR AR_MAC_DMA_OFFSET(MAC_DMA_IMR_P) #define AR_IMR_RXOK_HP 0x00000001 // Receive high-priority interrupt enable mask #define AR_IMR_RXOK_LP 0x00000002 // Receive low-priority interrupt enable mask #define AR_IMR_RXERR 0x00000004 // Receive error interrupt #define AR_IMR_RXNOPKT 0x00000008 // No frame received within timeout clock #define AR_IMR_RXEOL 0x00000010 // Received descriptor empty interrupt #define AR_IMR_RXORN 0x00000020 // Receive FIFO overrun interrupt #define AR_IMR_TXOK 0x00000040 // Transmit okay interrupt #define AR_IMR_TXERR 0x00000100 // Transmit error interrupt #define AR_IMR_TXNOPKT 0x00000200 // No frame transmitted interrupt #define AR_IMR_TXEOL 0x00000400 // Transmit descriptor empty interrupt #define AR_IMR_TXURN 0x00000800 // Transmit FIFO underrun interrupt #define AR_IMR_MIB 0x00001000 // MIB interrupt - see MIBC #define AR_IMR_SWI 0x00002000 // Software interrupt #define AR_IMR_RXPHY 0x00004000 // PHY receive error interrupt #define AR_IMR_RXKCM 0x00008000 // Key-cache miss interrupt #define AR_IMR_SWBA 0x00010000 // Software beacon alert interrupt #define AR_IMR_BRSSI 0x00020000 // Beacon threshold interrupt #define AR_IMR_BMISS 0x00040000 // Beacon missed interrupt #define AR_IMR_TXMINTR 0x00080000 // Maximum interrupt transmit rate #define AR_IMR_BNR 0x00100000 // BNR interrupt #define AR_IMR_RXCHIRP 0x00200000 // RXCHIRP interrupt #define AR_IMR_BCNMISC 0x00800000 // Venice: BCNMISC #define AR_IMR_TIM 0x00800000 // TIM interrupt #define AR_IMR_RXMINTR 0x01000000 // Maximum interrupt receive rate #define AR_IMR_QCBROVF 0x02000000 // QCU CBR overflow interrupt #define AR_IMR_QCBRURN 0x04000000 // QCU CBR underrun interrupt #define AR_IMR_QTRIG 0x08000000 // QCU scheduling trigger interrupt #define AR_IMR_GENTMR 0x10000000 // Generic timer interrupt #define AR_IMR_TXINTM 0x40000000 // Tx interrupt after mitigation #define AR_IMR_RXINTM 0x80000000 // Rx interrupt after mitigation /* MAC Secondary interrupt mask register 0 */ #define AR_IMR_S0 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S0) #define AR_IMR_S0_QCU_TXOK 0x000003FF // Mask for TXOK (QCU 0-9) #define AR_IMR_S0_QCU_TXOK_S 0 // Shift for TXOK (QCU 0-9) /* MAC Secondary interrupt mask register 1 */ #define AR_IMR_S1 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S1) #define AR_IMR_S1_QCU_TXERR 0x000003FF // Mask for TXERR (QCU 0-9) #define AR_IMR_S1_QCU_TXERR_S 0 // Shift for TXERR (QCU 0-9) #define AR_IMR_S1_QCU_TXEOL 0x03FF0000 // Mask for TXEOL (QCU 0-9) #define AR_IMR_S1_QCU_TXEOL_S 16 // Shift for TXEOL (QCU 0-9) /* MAC Secondary interrupt mask register 2 */ #define AR_IMR_S2 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S2) #define AR_IMR_S2_QCU_TXURN 0x000003FF // Mask for TXURN (QCU 0-9) #define AR_IMR_S2_QCU_TXURN_S 0 // Shift for TXURN (QCU 0-9) #define AR_IMR_S2_BBPANIC 0x00010000 // Panic watchdog IRQ from BB #define AR_IMR_S2_CST 0x00400000 // Carrier sense timeout #define AR_IMR_S2_GTT 0x00800000 // Global transmit timeout #define AR_IMR_S2_TIM 0x01000000 // TIM #define AR_IMR_S2_CABEND 0x02000000 // CABEND #define AR_IMR_S2_DTIMSYNC 0x04000000 // DTIMSYNC #define AR_IMR_S2_BCNTO 0x08000000 // BCNTO #define AR_IMR_S2_CABTO 0x10000000 // CABTO #define AR_IMR_S2_DTIM 0x20000000 // DTIM #define AR_IMR_S2_TSFOOR 0x40000000 // TSF out of range /* MAC Secondary interrupt mask register 3 */ #define AR_IMR_S3 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S3) #define AR_IMR_S3_QCU_QCBROVF 0x000003FF // Mask for QCBROVF (QCU 0-9) #define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 // Mask for QCBRURN (QCU 0-9) #define AR_IMR_S3_QCU_QCBRURN_S 16 // Shift for QCBRURN (QCU 0-9) /* MAC Secondary interrupt mask register 4 */ #define AR_IMR_S4 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S4) #define AR_IMR_S4_QCU_QTRIG 0x000003FF // Mask for QTRIG (QCU 0-9) #define AR_IMR_S4_RESV0 0xFFFFFC00 // Reserved /* MAC Secondary interrupt mask register 5 */ #define AR_IMR_S5 AR_MAC_DMA_OFFSET(MAC_DMA_IMR_S5) #define AR_IMR_S5_TIMER_TRIG 0x000000FF // Mask for timer trigger (0-7) #define AR_IMR_S5_TIMER_THRESH 0x0000FF00 // Mask for timer threshold(0-7) #define AR_IMR_S5_TIM_TIMER 0x00000010 // TIM Timer Mask #define AR_IMR_S5_DTIM_TIMER 0x00000020 // DTIM Timer Mask #define AR_IMR_S5_GENTIMER7 0x00000080 // Mask for timer 7 trigger #define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80 // Mask for generic timer trigger 7-15 #define AR_IMR_S5_GENTIMER_TRIG_S 0 #define AR_IMR_S5_GENTIMER_THRESH 0xFF800000 // Mask for generic timer threshold 7-15 #define AR_IMR_S5_GENTIMER_THRESH_S 16 /* Interrupt status registers (read-and-clear access secondary shadow copies) */ /* MAC Primary interrupt status register read-and-clear access */ #define AR_ISR_RAC AR_MAC_DMA_OFFSET(MAC_DMA_ISR_P_RAC) /* MAC Secondary interrupt status register 0 - shadow copy */ #define AR_ISR_S0_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S0_S) #define AR_ISR_S0_QCU_TXOK 0x000003FF // Mask for TXOK (QCU 0-9) #define AR_ISR_S0_QCU_TXOK_S 0 // Shift for TXOK (QCU 0-9) /* MAC Secondary interrupt status register 1 - shadow copy */ #define AR_ISR_S1_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S1_S) #define AR_ISR_S1_QCU_TXERR 0x000003FF // Mask for TXERR (QCU 0-9) #define AR_ISR_S1_QCU_TXERR_S 0 // Shift for TXERR (QCU 0-9) #define AR_ISR_S1_QCU_TXEOL 0x03FF0000 // Mask for TXEOL (QCU 0-9) #define AR_ISR_S1_QCU_TXEOL_S 16 // Shift for TXEOL (QCU 0-9) /* MAC Secondary interrupt status register 2 - shadow copy */ #define AR_ISR_S2_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S2_S) /* MAC Secondary interrupt status register 3 - shadow copy */ #define AR_ISR_S3_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S3_S) /* MAC Secondary interrupt status register 4 - shadow copy */ #define AR_ISR_S4_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S4_S) /* MAC Secondary interrupt status register 5 - shadow copy */ #define AR_ISR_S5_S AR_MAC_DMA_OFFSET(MAC_DMA_ISR_S5_S) /* MAC DMA Debug Registers */ #define AR_DMADBG_0 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_0) #define AR_DMADBG_1 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_1) #define AR_DMADBG_2 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_2) #define AR_DMADBG_3 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_3) #define AR_DMADBG_4 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_4) #define AR_DMADBG_5 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_5) #define AR_DMADBG_6 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_6) #define AR_DMADBG_7 AR_MAC_DMA_OFFSET(MAC_DMA_DMADBG_7) #define AR_DMATXDP_QCU_7_0 AR_MAC_DMA_OFFSET(MAC_DMA_QCU_TXDP_REMAINING_QCU_7_0) #define AR_DMATXDP_QCU_9_8 AR_MAC_DMA_OFFSET(MAC_DMA_QCU_TXDP_REMAINING_QCU_9_8) #define AR_DMADBG_RX_STATE 0x00000F00 // Mask for Rx DMA State machine /* * MAC QCU Registers */ #define AR_MAC_QCU_OFFSET(_x) offsetof(struct mac_qcu_reg, _x) #define AR_NUM_QCU 10 // Only use QCU 0-9 for forward QCU compatibility #define AR_QCU_0 0x0001 #define AR_QCU_1 0x0002 #define AR_QCU_2 0x0004 #define AR_QCU_3 0x0008 #define AR_QCU_4 0x0010 #define AR_QCU_5 0x0020 #define AR_QCU_6 0x0040 #define AR_QCU_7 0x0080 #define AR_QCU_8 0x0100 #define AR_QCU_9 0x0200 /* MAC Transmit Queue descriptor pointer */ #define AR_Q0_TXDP AR_MAC_QCU_OFFSET(MAC_QCU_TXDP) #define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) /* MAC Transmit Status Ring Start Address */ #define AR_Q_STATUS_RING_START AR_MAC_QCU_OFFSET(MAC_QCU_STATUS_RING_START) /* MAC Transmit Status Ring End Address */ #define AR_Q_STATUS_RING_END AR_MAC_QCU_OFFSET(MAC_QCU_STATUS_RING_END) /* Current Address in the Transmit Status Ring pointed to by the MAC */ #define AR_Q_STATUS_RING_CURRENT AR_MAC_QCU_OFFSET(MAC_QCU_STATUS_RING_CURRENT) /* MAC Transmit Queue enable */ #define AR_Q_TXE AR_MAC_QCU_OFFSET(MAC_QCU_TXE) #define AR_Q_TXE_M 0x000003FF // Mask for TXE (QCU 0-9) /* MAC Transmit Queue disable */ #define AR_Q_TXD AR_MAC_QCU_OFFSET(MAC_QCU_TXD) #define AR_Q_TXD_M 0x000003FF // Mask for TXD (QCU 0-9) /* MAC CBR configuration */ #define AR_Q0_CBRCFG AR_MAC_QCU_OFFSET(MAC_QCU_CBR) #define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) #define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF // Mask for CBR interval (us) #define AR_Q_CBRCFG_INTERVAL_S 0 // Shift for CBR interval (us) #define AR_Q_CBRCFG_OVF_THRESH 0xFF000000 // Mask for CBR overflow threshold #define AR_Q_CBRCFG_OVF_THRESH_S 24 // Shift for CBR overflow threshold /* MAC ready_time configuration */ #define AR_Q0_RDYTIMECFG AR_MAC_QCU_OFFSET(MAC_QCU_RDYTIME) #define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) #define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF // Mask for ready_time duration (us) #define AR_Q_RDYTIMECFG_DURATION_S 0 // Shift for ready_time duration (us) #define AR_Q_RDYTIMECFG_EN 0x01000000 // ready_time enable /* MAC OneShotArm set control */ #define AR_Q_ONESHOTARM_SC AR_MAC_QCU_OFFSET(MAC_QCU_ONESHOT_ARM_SC) #define AR_Q_ONESHOTARM_SC_M 0x000003FF // Mask for #define AR_Q_ONESHOTARM_SC (QCU 0-9) #define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00 // Reserved /* MAC OneShotArm clear control */ #define AR_Q_ONESHOTARM_CC AR_MAC_QCU_OFFSET(MAC_QCU_ONESHOT_ARM_CC) #define AR_Q_ONESHOTARM_CC_M 0x000003FF // Mask for #define AR_Q_ONESHOTARM_CC (QCU 0-9) #define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00 // Reserved /* MAC Miscellaneous QCU settings */ #define AR_Q0_MISC AR_MAC_QCU_OFFSET(MAC_QCU_MISC) #define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) #define AR_Q_MISC_FSP 0x0000000F // Mask for Frame Scheduling Policy #define AR_Q_MISC_FSP_ASAP 0 // ASAP #define AR_Q_MISC_FSP_CBR 1 // CBR #define AR_Q_MISC_FSP_DBA_GATED 2 // DMA Beacon Alert gated #define AR_Q_MISC_FSP_TIM_GATED 3 // TIM gated #define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 // Beacon-sent-gated #define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5 // Beacon-received-gated #define AR_Q_MISC_ONE_SHOT_EN 0x00000010 // OneShot enable #define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 // Disable CBR expired counter incr (empty q) #define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 // Disable CBR expired counter incr (empty beacon q) #define AR_Q_MISC_BEACON_USE 0x00000080 // Beacon use indication #define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100 // CBR expired counter limit enable #define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 // Enable TXE cleared on ready_time expired or VEOL #define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 // Reset CBR expired counter #define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 // DCU frame early termination request control #define AR_Q_MISC_RESV0 0xFFFFF000 // Reserved /* MAC Miscellaneous QCU status */ #define AR_Q0_STS AR_MAC_QCU_OFFSET(MAC_QCU_CNT) #define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) #define AR_Q_STS_PEND_FR_CNT 0x00000003 // Mask for Pending Frame Count #define AR_Q_STS_RESV0 0x000000FC // Reserved #define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 // Mask for CBR expired counter #define AR_Q_STS_RESV1 0xFFFF0000 // Reserved /* MAC ReadyTimeShutdown status */ #define AR_Q_RDYTIMESHDN AR_MAC_QCU_OFFSET(MAC_QCU_RDYTIME_SHDN) #define AR_Q_RDYTIMESHDN_M 0x000003FF // Mask for ReadyTimeShutdown status (QCU 0-9) /* MAC Descriptor CRC check */ #define AR_Q_DESC_CRCCHK AR_MAC_QCU_OFFSET(MAC_QCU_DESC_CRC_CHK) #define AR_Q_DESC_CRCCHK_EN 1 // Enable CRC check on the descriptor fetched from HOST #define AR_MAC_QCU_EOL AR_MAC_QCU_OFFSET(MAC_QCU_EOL) #define AR_MAC_QCU_EOL_DUR_CAL_EN 0x000003FF // Adjusts EOL for frame duration (QCU 0-9) #define AR_MAC_QCU_EOL_DUR_CAL_EN_S 0 /* * MAC DCU Registers */ #define AR_MAC_DCU_OFFSET(_x) offsetof(struct mac_dcu_reg, _x) #define AR_NUM_DCU 10 // Only use 10 DCU's for forward QCU/DCU compatibility #define AR_DCU_0 0x0001 #define AR_DCU_1 0x0002 #define AR_DCU_2 0x0004 #define AR_DCU_3 0x0008 #define AR_DCU_4 0x0010 #define AR_DCU_5 0x0020 #define AR_DCU_6 0x0040 #define AR_DCU_7 0x0080 #define AR_DCU_8 0x0100 #define AR_DCU_9 0x0200 /* MAC QCU Mask */ #define AR_D0_QCUMASK AR_MAC_DCU_OFFSET(MAC_DCU_QCUMASK) #define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) #define AR_D_QCUMASK 0x000003FF // Mask for QCU Mask (QCU 0-9) #define AR_D_QCUMASK_RESV0 0xFFFFFC00 // Reserved /* DCU transmit filter cmd (w/only) */ #define AR_D_TXBLK_CMD AR_MAC_DCU_OFFSET(MAC_DCU_TXFILTER_DCU0_31_0) #define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) // DCU transmit filter data /* MAC DCU-global IFS settings: SIFS duration */ #define AR_D_GBL_IFS_SIFS AR_MAC_DCU_OFFSET(MAC_DCU_GBL_IFS_SIFS) #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF // Mask for SIFS duration (core clocks) #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF // Reserved /* MAC DCU-global IFS settings: slot duration */ #define AR_D_GBL_IFS_SLOT AR_MAC_DCU_OFFSET(MAC_DCU_GBL_IFS_SLOT) #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF // Mask for Slot duration (core clocks) #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 // Reserved /* MAC Retry limits */ #define AR_D0_RETRY_LIMIT AR_MAC_DCU_OFFSET(MAC_DCU_RETRY_LIMIT) #define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) #define AR_D_RETRY_LIMIT_FR_SH 0x0000000F // Mask for frame short retry limit #define AR_D_RETRY_LIMIT_FR_SH_S 0 // Shift for frame short retry limit #define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 // Mask for station short retry limit #define AR_D_RETRY_LIMIT_STA_SH_S 8 // Shift for station short retry limit #define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 // Mask for station short retry limit #define AR_D_RETRY_LIMIT_STA_LG_S 14 // Shift for station short retry limit #define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 // Reserved /* MAC DCU-global IFS settings: EIFS duration */ #define AR_D_GBL_IFS_EIFS AR_MAC_DCU_OFFSET(MAC_DCU_GBL_IFS_EIFS) #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF // Mask for Slot duration (core clocks) #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 // Reserved /* MAC ChannelTime settings */ #define AR_D0_CHNTIME AR_MAC_DCU_OFFSET(MAC_DCU_CHANNEL_TIME) #define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) #define AR_D_CHNTIME_DUR 0x000FFFFF // Mask for ChannelTime duration (us) #define AR_D_CHNTIME_DUR_S 0 // Shift for ChannelTime duration (us) #define AR_D_CHNTIME_EN 0x00100000 // ChannelTime enable #define AR_D_CHNTIME_RESV0 0xFFE00000 // Reserved /* MAC DCU-global IFS settings: Miscellaneous */ #define AR_D_GBL_IFS_MISC AR_MAC_DCU_OFFSET(MAC_DCU_GBL_IFS_MISC) #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 // Mask forLFSR slice select #define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 // Turbo mode indication #define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 // Mask for DCU arbiter delay #define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000 // Random LSFR slice disable #define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000 // Slot transmission window length mask #define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000 // Force transmission on slot boundaries #define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000 // Ignore backoff /* MAC Miscellaneous DCU-specific settings */ #define AR_D0_MISC AR_MAC_DCU_OFFSET(MAC_DCU_MISC) #define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) #define AR_D_MISC_BKOFF_THRESH 0x0000003F // Mask for Backoff threshold setting #define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040 // End of tx series station RTS/data failure count reset policy #define AR_D_MISC_CW_RESET_EN 0x00000080 // End of tx series CW reset enable #define AR_D_MISC_FRAG_WAIT_EN 0x00000100 // Fragment Starvation Policy #define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 // Backoff during a frag burst #define AR_D_MISC_CW_BKOFF_EN 0x00001000 // Use binary exponential CW backoff #define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 // Mask for Virtual collision handling policy #define AR_D_MISC_VIR_COL_HANDLING_S 14 // Shift for Virtual collision handling policy #define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 // Normal #define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 // Ignore #define AR_D_MISC_BEACON_USE 0x00010000 // Beacon use indication #define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 // Mask for DCU arbiter lockout control #define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 // Shift for DCU arbiter lockout control #define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 // No lockout #define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 // Intra-frame #define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 // Global #define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 // DCU arbiter lockout ignore control #define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 // Sequence number increment disable #define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 // Post-frame backoff disable #define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000 // Virtual coll. handling policy #define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000 // Initiate Retry procedure on Blown IFS #define AR_D_MISC_RESV0 0xFF000000 // Reserved /* MAC Frame sequence number control/status */ #define AR_D_SEQNUM AR_MAC_DCU_OFFSET(MAC_DCU_SEQ) /* MAC DCU transmit pause control/status */ #define AR_D_TXPSE AR_MAC_DCU_OFFSET(MAC_DCU_PAUSE) #define AR_D_TXPSE_CTRL 0x000003FF // Mask of DCUs to pause (DCUs 0-9) #define AR_D_TXPSE_RESV0 0x0000FC00 // Reserved #define AR_D_TXPSE_STATUS 0x00010000 // Transmit pause status #define AR_D_TXPSE_RESV1 0xFFFE0000 // Reserved /* MAC DCU WOW Keep-Alive Config register */ #define AR_D_WOW_KACFG AR_MAC_DCU_OFFSET(MAC_DCU_WOW_KACFG) /* MAC DCU transmission slot mask */ #define AR_D_TXSLOTMASK AR_MAC_DCU_OFFSET(MAC_DCU_TXSLOT) #define AR_D_TXSLOTMASK_NUM 0x0000000F // slot numbers /* MAC DCU-specific IFS settings */ #define AR_D0_LCL_IFS AR_MAC_DCU_OFFSET(MAC_DCU_LCL_IFS) #define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) #define AR_D9_LCL_IFS AR_DLCL_IFS(9) #define AR_D_LCL_IFS_CWMIN 0x000003FF // Mask for CW_MIN #define AR_D_LCL_IFS_CWMIN_S 0 // Shift for CW_MIN #define AR_D_LCL_IFS_CWMAX 0x000FFC00 // Mask for CW_MAX #define AR_D_LCL_IFS_CWMAX_S 10 // Shift for CW_MAX #define AR_D_LCL_IFS_AIFS 0x0FF00000 // Mask for AIFS #define AR_D_LCL_IFS_AIFS_S 20 // Shift for AIFS /* * Note: even though this field is 8 bits wide the * maximum supported AIFS value is 0xfc. Setting the AIFS value * to 0xfd 0xfe or 0xff will not work correctly and will cause * the DCU to hang. */ #define AR_D_LCL_IFS_RESV0 0xF0000000 // Reserved #define AR_CFG_LED 0x1f04 /* LED control */ #define AR_CFG_SCLK_RATE_IND 0x00000003 /* sleep clock indication */ #define AR_CFG_SCLK_RATE_IND_S 0 #define AR_CFG_SCLK_32MHZ 0x00000000 /* Sleep clock rate */ #define AR_CFG_SCLK_4MHZ 0x00000001 /* Sleep clock rate */ #define AR_CFG_SCLK_1MHZ 0x00000002 /* Sleep clock rate */ #define AR_CFG_SCLK_32KHZ 0x00000003 /* Sleep clock rate */ #define AR_CFG_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode */ #define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select */ #define AR_CFG_LED_MODE_SEL 0x00000380 /* LED mode: bits 7..9 */ #define AR_CFG_LED_MODE_SEL_S 7 /* LED mode: bits 7..9 */ #define AR_CFG_LED_POWER 0x00000280 /* Power LED: bit 9=1, bit 7= */ #define AR_CFG_LED_POWER_S 7 /* LED mode: bits 7..9 */ #define AR_CFG_LED_NETWORK 0x00000300 /* Network LED: bit 9=1, bit 8= */ #define AR_CFG_LED_NETWORK_S 7 /* LED mode: bits 7..9 */ #define AR_CFG_LED_MODE_PROP 0x0 /* Blink prop to filtered tx/rx */ #define AR_CFG_LED_MODE_RPROP 0x1 /* Blink prop to unfiltered tx/rx */ #define AR_CFG_LED_MODE_SPLIT 0x2 /* Blink power for tx/net for rx */ #define AR_CFG_LED_MODE_RAND 0x3 /* Blink randomly */ #define AR_CFG_LED_MODE_POWER_OFF 0x4 /* Power LED OFF */ #define AR_CFG_LED_MODE_POWER_ON 0x5 /* Power LED ON */ #define AR_CFG_LED_MODE_NETWORK_OFF 0x4 /* Network LED OFF */ #define AR_CFG_LED_MODE_NETWORK_ON 0x6 /* Network LED ON */ #define AR_CFG_LED_ASSOC_CTL 0x00000c00 /* LED control: bits 10..11 */ #define AR_CFG_LED_ASSOC_CTL_S 10 /* LED control: bits 10..11 */ #define AR_CFG_LED_ASSOC_NONE 0x0 /* 0x00000000: STA is not associated or trying */ #define AR_CFG_LED_ASSOC_ACTIVE 0x1 /* 0x00000400: STA is associated */ #define AR_CFG_LED_ASSOC_PENDING 0x2 /* 0x00000800: STA is trying to associate */ #define AR_CFG_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode: bit 3 */ #define AR_CFG_LED_BLINK_SLOW_S 3 /* LED slowest blink rate mode: bit 3 */ #define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select: bits 4..6 */ #define AR_CFG_LED_BLINK_THRESH_SEL_S 4 /* LED blink threshold select: bits 4..6 */ #define AR_MAC_SLEEP 0x1f00 #define AR_MAC_SLEEP_MAC_AWAKE 0x00000000 // mac is now awake #define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001 // mac is now asleep /****************************************************************************** * Host Interface Register Map ******************************************************************************/ // DMA & PCI Registers in PCI space (usable during sleep) #define AR_HOSTIF_REG(_ah, _reg) (AH9300(_ah)->ah_hostifregs._reg) #define AR9300_HOSTIF_OFFSET(_x) offsetof(struct host_intf_reg, _x) #define AR9340_HOSTIF_OFFSET(_x) offsetof(struct host_intf_reg_ar9340, _x) /* Interface Reset Control Register */ #define AR_RC_AHB 0x00000001 // ahb reset #define AR_RC_APB 0x00000002 // apb reset #define AR_RC_HOSTIF 0x00000100 // host interface reset /* PCI express work-arounds */ #define AR_WA_D3_TO_L1_DISABLE (1 << 14) #define AR_WA_UNTIE_RESET_EN (1 << 15) /* Enable PCI Reset to POR (power-on-reset) */ #define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16) #define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17) #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */ #define AR_WA_ANALOG_SHIFT (1 << 20) #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */ #define AR_WA_COLD_RESET_OVERRIDE (1 << 13) /* PCI-E Cold reset override */ /* power management state */ #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 //for wow /* CXPL Debug signals which help debug Link Negotiation */ /* CXPL Debug signals which help debug Link Negotiation */ /* XXX check bit feilds */ /* Power Management Control Register */ #define AR_PCIE_PM_CTRL_ENA 0x00080000 #define AR_PMCTRL_WOW_PME_CLR 0x00200000 /* Clear WoW event */ #define AR_PMCTRL_HOST_PME_EN 0x00400000 /* Send OOB WAKE_L on WoW event */ #define AR_PMCTRL_D3COLD_VAUX 0x00800000 #define AR_PMCTRL_PWR_STATE_MASK 0x0F000000 /* Power State Mask */ #define AR_PMCTRL_PWR_STATE_D1D3 0x0F000000 /* Activate D1 and D3 */ #define AR_PMCTRL_PWR_STATE_D0 0x08000000 /* Activate D0 */ #define AR_PMCTRL_PWR_PM_CTRL_ENA 0x00008000 /* Enable power management */ #define AR_PMCTRL_AUX_PWR_DET 0x10000000 /* Puts Chip in L2 state */ /* APB and Local Bus Timeout Counters */ #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF #define AR_HOST_TIMEOUT_APB_CNTR_S 0 #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 #define AR_HOST_TIMEOUT_LCL_CNTR_S 16 /* EEPROM Control Register */ #define AR_EEPROM_ABSENT 0x00000100 #define AR_EEPROM_CORRUPT 0x00000200 #define AR_EEPROM_PROT_MASK 0x03FFFC00 #define AR_EEPROM_PROT_MASK_S 10 // Protect Bits RP is read protect WP is write protect #define EEPROM_PROTECT_RP_0_31 0x0001 #define EEPROM_PROTECT_WP_0_31 0x0002 #define EEPROM_PROTECT_RP_32_63 0x0004 #define EEPROM_PROTECT_WP_32_63 0x0008 #define EEPROM_PROTECT_RP_64_127 0x0010 #define EEPROM_PROTECT_WP_64_127 0x0020 #define EEPROM_PROTECT_RP_128_191 0x0040 #define EEPROM_PROTECT_WP_128_191 0x0080 #define EEPROM_PROTECT_RP_192_255 0x0100 #define EEPROM_PROTECT_WP_192_255 0x0200 #define EEPROM_PROTECT_RP_256_511 0x0400 #define EEPROM_PROTECT_WP_256_511 0x0800 #define EEPROM_PROTECT_RP_512_1023 0x1000 #define EEPROM_PROTECT_WP_512_1023 0x2000 #define EEPROM_PROTECT_RP_1024_2047 0x4000 #define EEPROM_PROTECT_WP_1024_2047 0x8000 /* RF silent */ #define AR_RFSILENT_FORCE 0x01 /* MAC silicon Rev ID */ #define AR_SREV_ID 0x000000FF /* Mask to read SREV info */ #define AR_SREV_VERSION 0x000000F0 /* Mask for Chip version */ #define AR_SREV_VERSION_S 4 /* Mask to shift Major Rev Info */ #define AR_SREV_REVISION 0x00000007 /* Mask for Chip revision level */ /* Sowl extension to SREV. AR_SREV_ID must be 0xFF */ #define AR_SREV_ID2 0xFFFFFFFF /* Mask to read SREV info */ #define AR_SREV_VERSION2 0xFFFC0000 /* Mask for Chip version */ #define AR_SREV_VERSION2_S 18 /* Mask to shift Major Rev Info */ #define AR_SREV_TYPE2 0x0003F000 /* Mask for Chip type */ #define AR_SREV_TYPE2_S 12 /* Mask to shift Major Rev Info */ #define AR_SREV_TYPE2_CHAIN 0x00001000 /* chain mode (1 = 3 chains, 0 = 2 chains) */ #define AR_SREV_TYPE2_HOST_MODE 0x00002000 /* host mode (1 = PCI, 0 = PCIe) */ /* Jupiter has a different TYPE2 definition. */ #define AR_SREV_TYPE2_JUPITER_CHAIN 0x00001000 /* chain (1 = 2 chains, 0 = 1 chain) */ #define AR_SREV_TYPE2_JUPITER_BAND 0x00002000 /* band (1 = dual band, 0 = single band) */ #define AR_SREV_TYPE2_JUPITER_BT 0x00004000 /* BT (1 = shared BT, 0 = no BT) */ #define AR_SREV_TYPE2_JUPITER_MODE 0x00008000 /* mode (1 = premium, 0 = standard) */ #define AR_SREV_REVISION2 0x00000F00 #define AR_SREV_REVISION2_S 8 #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 /* Fowl: 2+5G/3x3 */ #define AR_RAD2133_SREV_MAJOR 0xd0 /* Fowl: 2G/3x3 */ #define AR_RAD5122_SREV_MAJOR 0xe0 /* Fowl: 5G/2x2 */ #define AR_RAD2122_SREV_MAJOR 0xf0 /* Fowl: 2+5G/2x2 */ #if 0 #define AR_AHB_MODE 0x4024 // ahb mode for dma #define AR_AHB_EXACT_WR_EN 0x00000000 // write exact bytes #define AR_AHB_BUF_WR_EN 0x00000001 // buffer write upto cacheline #define AR_AHB_EXACT_RD_EN 0x00000000 // read exact bytes #define AR_AHB_CACHELINE_RD_EN 0x00000002 // read upto end of cacheline #define AR_AHB_PREFETCH_RD_EN 0x00000004 // prefetch upto page boundary #define AR_AHB_PAGE_SIZE_1K 0x00000000 // set page-size as 1k #define AR_AHB_PAGE_SIZE_2K 0x00000008 // set page-size as 2k #define AR_AHB_PAGE_SIZE_4K 0x00000010 // set page-size as 4k #endif #define AR_INTR_RTC_IRQ 0x00000001 // rtc in shutdown state #define AR_INTR_MAC_IRQ 0x00000002 // pending mac interrupt #if 0 /* * the following definitions might be differents for WASP so * disable them to avoid improper use */ #define AR_INTR_EEP_PROT_ACCESS 0x00000004 // eeprom protected area access #define AR_INTR_MAC_AWAKE 0x00020000 // mac is awake #define AR_INTR_MAC_ASLEEP 0x00040000 // mac is asleep #endif #define AR_INTR_SPURIOUS 0xFFFFFFFF /* TODO: fill in other values */ /* Synchronous Interrupt Cause Register */ /* Synchronous Interrupt Enable Register */ #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 // enable interrupts: bits 18..31 #define AR_INTR_SYNC_ENABLE_GPIO_S 18 // enable interrupts: bits 18..31 /* * synchronous interrupt signals */ enum { AR9300_INTR_SYNC_RTC_IRQ = 0x00000001, AR9300_INTR_SYNC_MAC_IRQ = 0x00000002, AR9300_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004, AR9300_INTR_SYNC_APB_TIMEOUT = 0x00000008, AR9300_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010, AR9300_INTR_SYNC_HOST1_FATAL = 0x00000020, AR9300_INTR_SYNC_HOST1_PERR = 0x00000040, AR9300_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080, AR9300_INTR_SYNC_RADM_CPL_EP = 0x00000100, AR9300_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200, AR9300_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400, AR9300_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800, AR9300_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000, AR9300_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000, AR9300_INTR_SYNC_PM_ACCESS = 0x00004000, AR9300_INTR_SYNC_MAC_AWAKE = 0x00008000, AR9300_INTR_SYNC_MAC_ASLEEP = 0x00010000, AR9300_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000, AR9300_INTR_SYNC_ALL = 0x0003FFFF, /* * Do not enable and turn on mask for both sync and async interrupt, since * chip can generate interrupt storm. */ AR9300_INTR_SYNC_DEF_NO_HOST1_PERR = (AR9300_INTR_SYNC_HOST1_FATAL | AR9300_INTR_SYNC_RADM_CPL_EP | AR9300_INTR_SYNC_RADM_CPL_DLLP_ABORT | AR9300_INTR_SYNC_RADM_CPL_TLP_ABORT | AR9300_INTR_SYNC_RADM_CPL_ECRC_ERR | AR9300_INTR_SYNC_RADM_CPL_TIMEOUT | AR9300_INTR_SYNC_LOCAL_TIMEOUT | AR9300_INTR_SYNC_MAC_SLEEP_ACCESS), AR9300_INTR_SYNC_DEFAULT = (AR9300_INTR_SYNC_DEF_NO_HOST1_PERR | AR9300_INTR_SYNC_HOST1_PERR), AR9300_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, /* WASP */ AR9340_INTR_SYNC_RTC_IRQ = 0x00000001, AR9340_INTR_SYNC_MAC_IRQ = 0x00000002, AR9340_INTR_SYNC_HOST1_FATAL = 0x00000004, AR9340_INTR_SYNC_HOST1_PERR = 0x00000008, AR9340_INTR_SYNC_LOCAL_TIMEOUT = 0x00000010, AR9340_INTR_SYNC_MAC_ASLEEP = 0x00000020, AR9340_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00000040, AR9340_INTR_SYNC_DEFAULT = (AR9340_INTR_SYNC_HOST1_FATAL | AR9340_INTR_SYNC_HOST1_PERR | AR9340_INTR_SYNC_LOCAL_TIMEOUT | AR9340_INTR_SYNC_MAC_SLEEP_ACCESS), AR9340_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, }; /* Asynchronous Interrupt Mask Register */ #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 // asynchronous interrupt mask: bits 18..31 #define AR_INTR_ASYNC_MASK_GPIO_S 18 // asynchronous interrupt mask: bits 18..31 #define AR_INTR_ASYNC_MASK_MCI 0x00000080 #define AR_INTR_ASYNC_MASK_MCI_S 7 /* Synchronous Interrupt Mask Register */ #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 // synchronous interrupt mask: bits 18..31 #define AR_INTR_SYNC_MASK_GPIO_S 18 // synchronous interrupt mask: bits 18..31 /* Asynchronous Interrupt Cause Register */ #define AR_INTR_ASYNC_CAUSE_GPIO 0xFFFC0000 // GPIO interrupts: bits 18..31 #define AR_INTR_ASYNC_CAUSE_MCI 0x00000080 #define AR_INTR_ASYNC_USED (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_CAUSE_GPIO | AR_INTR_ASYNC_CAUSE_MCI) /* Asynchronous Interrupt Enable Register */ #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 // enable interrupts: bits 18..31 #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 // enable interrupts: bits 18..31 #define AR_INTR_ASYNC_ENABLE_MCI 0x00000080 #define AR_INTR_ASYNC_ENABLE_MCI_S 7 /* PCIE PHY Data Register */ /* PCIE PHY Load Register */ #define AR_PCIE_PM_CTRL_ENA 0x00080000 #define AR93XX_NUM_GPIO 16 // 0 to 15 /* GPIO Output Register */ #define AR_GPIO_OUT_VAL 0x000FFFF #define AR_GPIO_OUT_VAL_S 0 /* GPIO Input Register */ #define AR_GPIO_IN_VAL 0x000FFFF #define AR_GPIO_IN_VAL_S 0 /* Host GPIO output enable bits */ #define AR_GPIO_OE_OUT_DRV 0x3 // 2 bit field mask, shifted by 2*bitpos #define AR_GPIO_OE_OUT_DRV_NO 0x0 // tristate #define AR_GPIO_OE_OUT_DRV_LOW 0x1 // drive if low #define AR_GPIO_OE_OUT_DRV_HI 0x2 // drive if high #define AR_GPIO_OE_OUT_DRV_ALL 0x3 // drive always /* Host GPIO output enable bits */ /* Host GPIO Interrupt Polarity */ #define AR_GPIO_INTR_POL_VAL 0x0001FFFF // bits 16:0 correspond to gpio 16:0 #define AR_GPIO_INTR_POL_VAL_S 0 // bits 16:0 correspond to gpio 16:0 /* Host GPIO Input Value */ #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 // default value for bt_priority_async #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 // default value for bt_frequency_async #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 // default value for bt_active_async #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 // default value for rfsilent_bb_l #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400 // 0 == set bt_priority_async to default, 1 == connect bt_prority_async to baseband #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10 #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_BB 0x00000800 // 0 == set bt_frequency_async to default, 1 == connect bt_frequency_async to baseband #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_BB_S 11 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 // 0 == set bt_active_async to default, 1 == connect bt_active_async to baseband #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 // 0 == set rfsilent_bb_l to default, 1 == connect rfsilent_bb_l to baseband #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_JTAG_DISABLE 0x00020000 // 1 == disable JTAG /* GPIO Input Mux1 */ #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 /* bits 8..11: input mux for BT priority input */ #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 /* bits 8..11: input mux for BT priority input */ #define AR_GPIO_INPUT_MUX1_BT_FREQUENCY 0x0000f000 /* bits 12..15: input mux for BT frequency input */ #define AR_GPIO_INPUT_MUX1_BT_FREQUENCY_S 12 /* bits 12..15: input mux for BT frequency input */ #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 /* bits 16..19: input mux for BT active input */ #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 /* bits 16..19: input mux for BT active input */ /* GPIO Input Mux2 */ #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f // bits 0..3: input mux for clk25 input #define AR_GPIO_INPUT_MUX2_CLK25_S 0 // bits 0..3: input mux for clk25 input #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 // bits 4..7: input mux for rfsilent_bb_l input #define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 // bits 4..7: input mux for rfsilent_bb_l input #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 // bits 8..11: input mux for RTC Reset input #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 // bits 8..11: input mux for RTC Reset input /* GPIO Output Mux1 */ /* GPIO Output Mux2 */ /* GPIO Output Mux3 */ #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 #define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 #define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 #define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA 0x16 #define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK 0x17 #define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA 0x18 #define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK 0x19 #define AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX 0x14 #define AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX 0x13 #define AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX 9 #define AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX 8 #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE 0x1d #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e #define AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0 0x1d #define AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1 0x1e #define AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2 0x1b /* The above three seems to be functional values for peacock chip. For some * reason these are continued for different boards as simple place holders. * Now continuing to use these and adding the extra definitions for Scropion */ #define AR_GPIO_OUTPUT_MUX_AS_SWCOM3 0x26 #define AR_ENABLE_SMARTANTENNA 0x00000001 /* Host GPIO Input State */ /* Host Spare */ /* Host PCIE Core Reset Enable */ /* Host CLKRUN */ /* Host EEPROM Status */ #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff #define AR_EEPROM_STATUS_DATA_VAL_S 0 #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 #define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 /* Host Observation Control */ /* Host RF Silent */ /* Host GPIO PDPU */ #define AR_GPIO_PDPU_OPTION 0x03 #define AR_GPIO_PULL_DOWN 0x02 /* Host GPIO Drive Strength */ /* Host Miscellaneous */ /* Host PCIE MSI Control Register */ #define AR_PCIE_MSI_ENABLE 0x00000001 #define AR_PCIE_MSI_HW_DBI_WR_EN 0x02000000 #define AR_PCIE_MSI_HW_INT_PENDING_ADDR 0xFFA0C1FF // bits 8..11: value must be 0x5060 #define AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64 0xFFA0C9FF // bits 8..11: value must be 0x5064 #define AR_INTR_PRIO_TX 0x00000001 #define AR_INTR_PRIO_RXLP 0x00000002 #define AR_INTR_PRIO_RXHP 0x00000004 /* OTP Interface Register */ #define AR_ENT_OTP AR9300_HOSTIF_OFFSET(HOST_INTF_OTP) #define AR_ENT_OTP_DUAL_BAND_DISABLE 0x00010000 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_5MHZ_DISABLE 0x00040000 #define AR_ENT_OTP_10MHZ_DISABLE 0x00080000 #define AR_ENT_OTP_49GHZ_DISABLE 0x00100000 #define AR_ENT_OTP_LOOPBACK_DISABLE 0x00200000 #define AR_ENT_OTP_TPC_PERF_DISABLE 0x00400000 #define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000 #define AR_ENT_OTP_SPECTRAL_PRECISION 0x03000000 /* OTP EFUSE registers */ #define AR_OTP_EFUSE_OFFSET(_x) offsetof(struct efuse_reg_WLAN, _x) #define AR_OTP_EFUSE_INTF0 AR_OTP_EFUSE_OFFSET(OTP_INTF0) #define AR_OTP_EFUSE_INTF5 AR_OTP_EFUSE_OFFSET(OTP_INTF5) #define AR_OTP_EFUSE_PGENB_SETUP_HOLD_TIME AR_OTP_EFUSE_OFFSET(OTP_PGENB_SETUP_HOLD_TIME) #define AR_OTP_EFUSE_MEM AR_OTP_EFUSE_OFFSET(OTP_MEM) /****************************************************************************** * RTC Register Map ******************************************************************************/ #define AR_RTC_OFFSET(_x) offsetof(struct rtc_reg, _x) /* Reset Control */ #define AR_RTC_RC AR_RTC_OFFSET(RESET_CONTROL) #define AR_RTC_RC_M 0x00000003 #define AR_RTC_RC_MAC_WARM 0x00000001 #define AR_RTC_RC_MAC_COLD 0x00000002 /* Crystal Control */ #define AR_RTC_XTAL_CONTROL AR_RTC_OFFSET(XTAL_CONTROL) /* Reg Control 0 */ #define AR_RTC_REG_CONTROL0 AR_RTC_OFFSET(REG_CONTROL0) /* Reg Control 1 */ #define AR_RTC_REG_CONTROL1 AR_RTC_OFFSET(REG_CONTROL1) #define AR_RTC_REG_CONTROL1_SWREG_PROGRAM 0x00000001 /* TCXO Detect */ #define AR_RTC_TCXO_DETECT AR_RTC_OFFSET(TCXO_DETECT) /* Crystal Test */ #define AR_RTC_XTAL_TEST AR_RTC_OFFSET(XTAL_TEST) /* Sets the ADC/DAC clock quadrature */ #define AR_RTC_QUADRATURE AR_RTC_OFFSET(QUADRATURE) /* PLL Control */ #define AR_RTC_PLL_CONTROL AR_RTC_OFFSET(PLL_CONTROL) #define AR_RTC_PLL_DIV 0x000003ff #define AR_RTC_PLL_DIV_S 0 #define AR_RTC_PLL_REFDIV 0x00003C00 #define AR_RTC_PLL_REFDIV_S 10 #define AR_RTC_PLL_CLKSEL 0x0000C000 #define AR_RTC_PLL_CLKSEL_S 14 #define AR_RTC_PLL_BYPASS 0x00010000 #define AR_RTC_PLL_BYPASS_S 16 /* PLL Control 2: for Hornet */ #define AR_RTC_PLL_CONTROL2 AR_RTC_OFFSET(PLL_CONTROL2) /* PLL Settle */ #define AR_RTC_PLL_SETTLE AR_RTC_OFFSET(PLL_SETTLE) /* Crystal Settle */ #define AR_RTC_XTAL_SETTLE AR_RTC_OFFSET(XTAL_SETTLE) /* Controls CLK_OUT pin clock speed */ #define AR_RTC_CLOCK_OUT AR_RTC_OFFSET(CLOCK_OUT) /* Forces bias block on at all times */ #define AR_RTC_BIAS_OVERRIDE AR_RTC_OFFSET(BIAS_OVERRIDE) /* System Sleep status bits */ #define AR_RTC_SYSTEM_SLEEP AR_RTC_OFFSET(SYSTEM_SLEEP) /* Controls sleep options for MAC */ #define AR_RTC_MAC_SLEEP_CONTROL AR_RTC_OFFSET(MAC_SLEEP_CONTROL) /* Keep Awake Timer */ #define AR_RTC_KEEP_AWAKE AR_RTC_OFFSET(KEEP_AWAKE) /* Create a 32kHz clock derived from HF */ #define AR_RTC_DERIVED_RTC_CLK AR_RTC_OFFSET(DERIVED_RTC_CLK) /****************************************************************************** * RTC SYNC Register Map ******************************************************************************/ #define AR_RTC_SYNC_OFFSET(_x) offsetof(struct rtc_sync_reg, _x) /* reset RTC */ #define AR_RTC_RESET AR_RTC_SYNC_OFFSET(RTC_SYNC_RESET) #define AR_RTC_RESET_EN 0x00000001 /* Reset RTC bit */ /* system sleep status */ #define AR_RTC_STATUS AR_RTC_SYNC_OFFSET(RTC_SYNC_STATUS) #define AR_RTC_STATUS_M 0x0000003f #define AR_RTC_STATUS_SHUTDOWN 0x00000001 #define AR_RTC_STATUS_ON 0x00000002 #define AR_RTC_STATUS_SLEEP 0x00000004 #define AR_RTC_STATUS_WAKEUP 0x00000008 #define AR_RTC_STATUS_SLEEP_ACCESS 0x00000010 #define AR_RTC_STATUS_PLL_CHANGING 0x00000020 /* RTC Derived Register */ #define AR_RTC_SLEEP_CLK AR_RTC_SYNC_OFFSET(RTC_SYNC_DERIVED) #define AR_RTC_FORCE_DERIVED_CLK 0x00000002 #define AR_RTC_FORCE_SWREG_PRD 0x00000004 #define AR_RTC_PCIE_RST_PWDN_EN 0x00000008 /* RTC Force Wake Register */ #define AR_RTC_FORCE_WAKE AR_RTC_SYNC_OFFSET(RTC_SYNC_FORCE_WAKE) #define AR_RTC_FORCE_WAKE_EN 0x00000001 /* enable force wake */ #define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 /* auto-wake on MAC interrupt */ /* RTC interrupt cause/clear */ #define AR_RTC_INTR_CAUSE AR_RTC_SYNC_OFFSET(RTC_SYNC_INTR_CAUSE) /* RTC interrupt enable */ #define AR_RTC_INTR_ENABLE AR_RTC_SYNC_OFFSET(RTC_SYNC_INTR_ENABLE) /* RTC interrupt mask */ #define AR_RTC_INTR_MASK AR_RTC_SYNC_OFFSET(RTC_SYNC_INTR_MASK) /****************************************************************************** * Analog Interface Register Map ******************************************************************************/ #define AR_AN_OFFSET(_x) offsetof(struct analog_intf_reg_csr, _x) /* XXX */ #if 1 // AR9280: rf long shift registers #define AR_AN_RF2G1_CH0 0x7810 #define AR_AN_RF2G1_CH0_OB 0x03800000 #define AR_AN_RF2G1_CH0_OB_S 23 #define AR_AN_RF2G1_CH0_DB 0x1C000000 #define AR_AN_RF2G1_CH0_DB_S 26 #define AR_AN_RF5G1_CH0 0x7818 #define AR_AN_RF5G1_CH0_OB5 0x00070000 #define AR_AN_RF5G1_CH0_OB5_S 16 #define AR_AN_RF5G1_CH0_DB5 0x00380000 #define AR_AN_RF5G1_CH0_DB5_S 19 #define AR_AN_RF2G1_CH1 0x7834 #define AR_AN_RF2G1_CH1_OB 0x03800000 #define AR_AN_RF2G1_CH1_OB_S 23 #define AR_AN_RF2G1_CH1_DB 0x1C000000 #define AR_AN_RF2G1_CH1_DB_S 26 #define AR_AN_RF5G1_CH1 0x783C #define AR_AN_RF5G1_CH1_OB5 0x00070000 #define AR_AN_RF5G1_CH1_OB5_S 16 #define AR_AN_RF5G1_CH1_DB5 0x00380000 #define AR_AN_RF5G1_CH1_DB5_S 19 #define AR_AN_TOP2 0x7894 #define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 #define AR_AN_TOP2_XPABIAS_LVL_S 30 #define AR_AN_TOP2_LOCALBIAS 0x00200000 #define AR_AN_TOP2_LOCALBIAS_S 21 #define AR_AN_TOP2_PWDCLKIND 0x00400000 #define AR_AN_TOP2_PWDCLKIND_S 22 #define AR_AN_SYNTH9 0x7868 #define AR_AN_SYNTH9_REFDIVA 0xf8000000 #define AR_AN_SYNTH9_REFDIVA_S 27 // AR9285 Analog registers #define AR9285_AN_RF2G1 0x7820 #define AR9285_AN_RF2G2 0x7824 #define AR9285_AN_RF2G3 0x7828 #define AR9285_AN_RF2G3_OB_0 0x00E00000 #define AR9285_AN_RF2G3_OB_0_S 21 #define AR9285_AN_RF2G3_OB_1 0x001C0000 #define AR9285_AN_RF2G3_OB_1_S 18 #define AR9285_AN_RF2G3_OB_2 0x00038000 #define AR9285_AN_RF2G3_OB_2_S 15 #define AR9285_AN_RF2G3_OB_3 0x00007000 #define AR9285_AN_RF2G3_OB_3_S 12 #define AR9285_AN_RF2G3_OB_4 0x00000E00 #define AR9285_AN_RF2G3_OB_4_S 9 #define AR9285_AN_RF2G3_DB1_0 0x000001C0 #define AR9285_AN_RF2G3_DB1_0_S 6 #define AR9285_AN_RF2G3_DB1_1 0x00000038 #define AR9285_AN_RF2G3_DB1_1_S 3 #define AR9285_AN_RF2G3_DB1_2 0x00000007 #define AR9285_AN_RF2G3_DB1_2_S 0 #define AR9285_AN_RF2G4 0x782C #define AR9285_AN_RF2G4_DB1_3 0xE0000000 #define AR9285_AN_RF2G4_DB1_3_S 29 #define AR9285_AN_RF2G4_DB1_4 0x1C000000 #define AR9285_AN_RF2G4_DB1_4_S 26 #define AR9285_AN_RF2G4_DB2_0 0x03800000 #define AR9285_AN_RF2G4_DB2_0_S 23 #define AR9285_AN_RF2G4_DB2_1 0x00700000 #define AR9285_AN_RF2G4_DB2_1_S 20 #define AR9285_AN_RF2G4_DB2_2 0x000E0000 #define AR9285_AN_RF2G4_DB2_2_S 17 #define AR9285_AN_RF2G4_DB2_3 0x0001C000 #define AR9285_AN_RF2G4_DB2_3_S 14 #define AR9285_AN_RF2G4_DB2_4 0x00003800 #define AR9285_AN_RF2G4_DB2_4_S 11 #define AR9285_AN_RF2G6 0x7834 #define AR9285_AN_RF2G7 0x7838 #define AR9285_AN_RF2G9 0x7840 #define AR9285_AN_RXTXBB1 0x7854 #define AR9285_AN_TOP2 0x7868 #define AR9285_AN_TOP3 0x786c #define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C #define AR9285_AN_TOP3_XPABIAS_LVL_S 2 #define AR9285_AN_TOP4 0x7870 #define AR9285_AN_TOP4_DEFAULT 0x10142c00 #endif /****************************************************************************** * MAC PCU Register Map ******************************************************************************/ #define AR_MAC_PCU_OFFSET(_x) offsetof(struct mac_pcu_reg, _x) /* MAC station ID0 - low 32 bits */ #define AR_STA_ID0 AR_MAC_PCU_OFFSET(MAC_PCU_STA_ADDR_L32) /* MAC station ID1 - upper 16 bits */ #define AR_STA_ID1 AR_MAC_PCU_OFFSET(MAC_PCU_STA_ADDR_U16) #define AR_STA_ID1_SADH_MASK 0x0000FFFF // Mask for 16 msb of MAC addr #define AR_STA_ID1_STA_AP 0x00010000 // Device is AP #define AR_STA_ID1_ADHOC 0x00020000 // Device is ad-hoc #define AR_STA_ID1_PWR_SAV 0x00040000 // Power save in generated frames #define AR_STA_ID1_KSRCHDIS 0x00080000 // Key search disable #define AR_STA_ID1_PCF 0x00100000 // Observe PCF #define AR_STA_ID1_USE_DEFANT 0x00200000 // Use default antenna #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 // Update default ant w/TX antenna #define AR_STA_ID1_RTS_USE_DEF 0x00800000 // Use default antenna to send RTS #define AR_STA_ID1_ACKCTS_6MB 0x01000000 // Use 6Mb/s rate for ACK & CTS #define AR_STA_ID1_BASE_RATE_11B 0x02000000 // Use 11b base rate for ACK & CTS #define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000 // default ant for generated frames #define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 // Enable Michael #define AR_STA_ID1_KSRCH_MODE 0x10000000 // Look-up unique key when !keyID #define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 // Don't replace seq num #define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 // IV endian-ness in CBC nonce #define AR_STA_ID1_MCAST_KSRCH 0x80000000 // Adhoc key search enable /* MAC BSSID low 32 bits */ #define AR_BSS_ID0 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID_L32) /* MAC BSSID upper 16 bits / AID */ #define AR_BSS_ID1 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID_U16) #define AR_BSS_ID1_U16 0x0000FFFF // Mask for upper 16 bits of BSSID #define AR_BSS_ID1_AID 0x07FF0000 // Mask for association ID #define AR_BSS_ID1_AID_S 16 // Shift for association ID /* * Added to support dual BSSID/TSF which are needed in the application * of Mesh networking. See bug 35189. Note that the only function added * with this BSSID2 is to receive multi/broadcast from BSSID2 as well */ /* MAC BSSID low 32 bits */ #define AR_BSS2_ID0 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID2_L32) /* MAC BSSID upper 16 bits / AID */ #define AR_BSS2_ID1 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID2_U16) /* MAC Beacon average RSSI * * This register holds the average RSSI with 1/16 dB resolution. * The RSSI is averaged over multiple beacons which matched our BSSID. * Note that AVE_VALUE is 12 bits with 4 bits below the normal 8 bits. * These lowest 4 bits provide for a resolution of 1/16 dB. * */ #define AR_BCN_RSSI_AVE AR_MAC_PCU_OFFSET(MAC_PCU_BCN_RSSI_AVE) #define AR_BCN_RSSI_AVE_VAL 0x00000FFF // Beacon RSSI value #define AR_BCN_RSSI_AVE_VAL_S 0 /* MAC ACK & CTS time-out */ #define AR_TIME_OUT AR_MAC_PCU_OFFSET(MAC_PCU_ACK_CTS_TIMEOUT) #define AR_TIME_OUT_ACK 0x00003FFF // Mask for ACK time-out #define AR_TIME_OUT_ACK_S 0 #define AR_TIME_OUT_CTS 0x3FFF0000 // Mask for CTS time-out #define AR_TIME_OUT_CTS_S 16 /* beacon RSSI warning / bmiss threshold */ #define AR_RSSI_THR AR_MAC_PCU_OFFSET(MAC_PCU_BCN_RSSI_CTL) #define AR_RSSI_THR_VAL 0x000000FF // Beacon RSSI warning threshold #define AR_RSSI_THR_VAL_S 0 #define AR_RSSI_THR_BM_THR 0x0000FF00 // Mask for Missed beacon threshold #define AR_RSSI_THR_BM_THR_S 8 // Shift for Missed beacon threshold #define AR_RSSI_BCN_WEIGHT 0x1F000000 // RSSI average weight #define AR_RSSI_BCN_WEIGHT_S 24 #define AR_RSSI_BCN_RSSI_RST 0x20000000 // Reset RSSI value /* MAC transmit latency register */ #define AR_USEC AR_MAC_PCU_OFFSET(MAC_PCU_USEC_LATENCY) #define AR_USEC_USEC 0x000000FF // Mask for clock cycles in 1 usec #define AR_USEC_USEC_S 0 // Shift for clock cycles in 1 usec #define AR_USEC_TX_LAT 0x007FC000 // tx latency to start of SIGNAL (usec) #define AR_USEC_TX_LAT_S 14 // tx latency to start of SIGNAL (usec) #define AR_USEC_RX_LAT 0x1F800000 // rx latency to start of SIGNAL (usec) #define AR_USEC_RX_LAT_S 23 // rx latency to start of SIGNAL (usec) #define AR_SLOT_HALF 13 #define AR_SLOT_QUARTER 21 #define AR_USEC_RX_LATENCY 0x1f800000 #define AR_USEC_RX_LATENCY_S 23 #define AR_RX_LATENCY_FULL 37 #define AR_RX_LATENCY_HALF 74 #define AR_RX_LATENCY_QUARTER 148 #define AR_RX_LATENCY_FULL_FAST_CLOCK 41 #define AR_RX_LATENCY_HALF_FAST_CLOCK 82 #define AR_RX_LATENCY_QUARTER_FAST_CLOCK 163 #define AR_USEC_TX_LATENCY 0x007fc000 #define AR_USEC_TX_LATENCY_S 14 #define AR_TX_LATENCY_FULL 54 #define AR_TX_LATENCY_HALF 108 #define AR_TX_LATENCY_QUARTER 216 #define AR_TX_LATENCY_FULL_FAST_CLOCK 54 #define AR_TX_LATENCY_HALF_FAST_CLOCK 119 #define AR_TX_LATENCY_QUARTER_FAST_CLOCK 238 #define AR_USEC_HALF 19 #define AR_USEC_QUARTER 9 #define AR_USEC_HALF_FAST_CLOCK 21 #define AR_USEC_QUARTER_FAST_CLOCK 10 #define AR_EIFS_HALF 175 #define AR_EIFS_QUARTER 340 #define AR_RESET_TSF AR_MAC_PCU_OFFSET(MAC_PCU_RESET_TSF) #define AR_RESET_TSF_ONCE 0x01000000 // reset tsf once ; self-clears bit #define AR_RESET_TSF2_ONCE 0x02000000 // reset tsf2 once ; self-clears bit /* MAC CFP Interval (TU/msec) */ #define AR_CFP_PERIOD 0x8024 /* MAC CFP Interval (TU/msec) */ #define AR_TIMER0 0x8028 /* MAC Next beacon time (TU/msec) */ #define AR_TIMER1 0x802c /* MAC DMA beacon alert time (1/8 TU) */ #define AR_TIMER2 0x8030 /* MAC Software beacon alert (1/8 TU) */ #define AR_TIMER3 0x8034 /* MAC ATIM window time */ /* MAC maximum CFP duration */ #define AR_MAX_CFP_DUR AR_MAC_PCU_OFFSET(MAC_PCU_MAX_CFP_DUR) #define AR_CFP_VAL 0x0000FFFF // CFP value in uS /* MAC receive filter register */ #define AR_RX_FILTER AR_MAC_PCU_OFFSET(MAC_PCU_RX_FILTER) #define AR_RX_FILTER_ALL 0x00000000 // Disallow all frames #define AR_RX_UCAST 0x00000001 // Allow unicast frames #define AR_RX_MCAST 0x00000002 // Allow multicast frames #define AR_RX_BCAST 0x00000004 // Allow broadcast frames #define AR_RX_CONTROL 0x00000008 // Allow control frames #define AR_RX_BEACON 0x00000010 // Allow beacon frames #define AR_RX_PROM 0x00000020 // Promiscuous mode all packets #define AR_RX_PROBE_REQ 0x00000080 // Any probe request frameA #define AR_RX_MY_BEACON 0x00000200 // Any beacon frame with matching BSSID #define AR_RX_COMPR_BAR 0x00000400 // Compressed directed block ack request #define AR_RX_COMPR_BA 0x00000800 // Compressed directed block ack #define AR_RX_UNCOM_BA_BAR 0x00001000 // Uncompressed directed BA or BAR #define AR_RX_HWBCNPROC_EN 0x00020000 // Enable hw beacon processing (see AR_HWBCNPROC1) #define AR_RX_CONTROL_WRAPPER 0x00080000 // Control wrapper. Jupiter only. #define AR_RX_4ADDRESS 0x00100000 // 4-Address frames #define AR_PHY_ERR_MASK_REG AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERROR_MASK_CONT) /* MAC multicast filter lower 32 bits */ #define AR_MCAST_FIL0 AR_MAC_PCU_OFFSET(MAC_PCU_MCAST_FILTER_L32) /* MAC multicast filter upper 32 bits */ #define AR_MCAST_FIL1 AR_MAC_PCU_OFFSET(MAC_PCU_MCAST_FILTER_U32) /* MAC PCU diagnostic switches */ #define AR_DIAG_SW AR_MAC_PCU_OFFSET(MAC_PCU_DIAG_SW) #define AR_DIAG_CACHE_ACK 0x00000001 // disable ACK when no valid key #define AR_DIAG_ACK_DIS 0x00000002 // disable ACK generation #define AR_DIAG_CTS_DIS 0x00000004 // disable CTS generation #define AR_DIAG_ENCRYPT_DIS 0x00000008 // disable encryption #define AR_DIAG_DECRYPT_DIS 0x00000010 // disable decryption #define AR_DIAG_RX_DIS 0x00000020 // disable receive #define AR_DIAG_LOOP_BACK 0x00000040 // enable loopback #define AR_DIAG_CORR_FCS 0x00000080 // corrupt FCS #define AR_DIAG_CHAN_INFO 0x00000100 // dump channel info #define AR_DIAG_FRAME_NV0 0x00020000 // accept w/protocol version !0 #define AR_DIAG_OBS_PT_SEL1 0x000C0000 // observation point select #define AR_DIAG_OBS_PT_SEL1_S 18 // Shift for observation point select #define AR_DIAG_FORCE_RX_CLEAR 0x00100000 // force rx_clear high #define AR_DIAG_IGNORE_VIRT_CS 0x00200000 // ignore virtual carrier sense #define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 // force channel idle high #define AR_DIAG_EIFS_CTRL_ENA 0x00800000 // use framed and ~wait_wep if 0 #define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 // dual chain channel info #define AR_DIAG_RX_ABORT 0x02000000 // abort rx #define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 // saturate cycle cnts (no shift) #define AR_DIAG_OBS_PT_SEL2 0x08000000 // Mask for observation point sel #define AR_DIAG_OBS_PT_SEL2_S 27 #define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 // force rx_clear (ctl) low (i.e. busy) #define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000 // force rx_clear (ext) low (i.e. busy) /* MAC local clock lower 32 bits */ #define AR_TSF_L32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF_L32) /* MAC local clock upper 32 bits */ #define AR_TSF_U32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF_U32) /* * Secondary TSF support added for dual BSSID/TSF * which is needed in the application of DirectConnect or * Mesh networking */ /* MAC local clock lower 32 bits */ #define AR_TSF2_L32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF2_L32) /* MAC local clock upper 32 bits */ #define AR_TSF2_U32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF2_U32) /* ADDAC test register */ #define AR_TST_ADDAC AR_MAC_PCU_OFFSET(MAC_PCU_TST_ADDAC) #define AR_TST_ADDAC_TST_MODE 0x1 #define AR_TST_ADDAC_TST_MODE_S 0 #define AR_TST_ADDAC_TST_LOOP_ENA 0x2 #define AR_TST_ADDAC_TST_LOOP_ENA_S 1 #define AR_TST_ADDAC_BEGIN_CAPTURE 0x80000 #define AR_TST_ADDAC_BEGIN_CAPTURE_S 19 /* default antenna register */ #define AR_DEF_ANTENNA AR_MAC_PCU_OFFSET(MAC_PCU_DEF_ANTENNA) /* MAC AES mute mask */ #define AR_AES_MUTE_MASK0 AR_MAC_PCU_OFFSET(MAC_PCU_AES_MUTE_MASK_0) #define AR_AES_MUTE_MASK0_FC 0x0000FFFF // frame ctrl mask bits #define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 // qos ctrl mask bits #define AR_AES_MUTE_MASK0_QOS_S 16 /* MAC AES mute mask 1 */ #define AR_AES_MUTE_MASK1 AR_MAC_PCU_OFFSET(MAC_PCU_AES_MUTE_MASK_1) #define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF // seq + frag mask bits #define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 // frame ctrl mask for mgmt frames (Sowl) #define AR_AES_MUTE_MASK1_FC_MGMT_S 16 /* control clock domain */ #define AR_GATED_CLKS AR_MAC_PCU_OFFSET(MAC_PCU_GATED_CLKS) #define AR_GATED_CLKS_TX 0x00000002 #define AR_GATED_CLKS_RX 0x00000004 #define AR_GATED_CLKS_REG 0x00000008 /* MAC PCU observation bus 2 */ #define AR_OBS_BUS_CTRL AR_MAC_PCU_OFFSET(MAC_PCU_OBS_BUS_2) #define AR_OBS_BUS_SEL_1 0x00040000 #define AR_OBS_BUS_SEL_2 0x00080000 #define AR_OBS_BUS_SEL_3 0x000C0000 #define AR_OBS_BUS_SEL_4 0x08040000 #define AR_OBS_BUS_SEL_5 0x08080000 /* MAC PCU observation bus 1 */ #define AR_OBS_BUS_1 AR_MAC_PCU_OFFSET(MAC_PCU_OBS_BUS_1) #define AR_OBS_BUS_1_PCU 0x00000001 #define AR_OBS_BUS_1_RX_END 0x00000002 #define AR_OBS_BUS_1_RX_WEP 0x00000004 #define AR_OBS_BUS_1_RX_BEACON 0x00000008 #define AR_OBS_BUS_1_RX_FILTER 0x00000010 #define AR_OBS_BUS_1_TX_HCF 0x00000020 #define AR_OBS_BUS_1_QUIET_TIME 0x00000040 #define AR_OBS_BUS_1_CHAN_IDLE 0x00000080 #define AR_OBS_BUS_1_TX_HOLD 0x00000100 #define AR_OBS_BUS_1_TX_FRAME 0x00000200 #define AR_OBS_BUS_1_RX_FRAME 0x00000400 #define AR_OBS_BUS_1_RX_CLEAR 0x00000800 #define AR_OBS_BUS_1_WEP_STATE 0x0003F000 #define AR_OBS_BUS_1_WEP_STATE_S 12 #define AR_OBS_BUS_1_RX_STATE 0x01F00000 #define AR_OBS_BUS_1_RX_STATE_S 20 #define AR_OBS_BUS_1_TX_STATE 0x7E000000 #define AR_OBS_BUS_1_TX_STATE_S 25 /* MAC PCU dynamic MIMO power save */ #define AR_PCU_SMPS AR_MAC_PCU_OFFSET(MAC_PCU_DYM_MIMO_PWR_SAVE) #define AR_PCU_SMPS_MAC_CHAINMASK 0x00000001 // Use the Rx Chainmask of MAC's setting #define AR_PCU_SMPS_HW_CTRL_EN 0x00000002 // Enable hardware control of dynamic MIMO PS #define AR_PCU_SMPS_SW_CTRL_HPWR 0x00000004 // Software controlled High power chainmask setting #define AR_PCU_SMPS_LPWR_CHNMSK 0x00000070 // Low power setting of Rx Chainmask #define AR_PCU_SMPS_LPWR_CHNMSK_S 4 #define AR_PCU_SMPS_HPWR_CHNMSK 0x00000700 // High power setting of Rx Chainmask #define AR_PCU_SMPS_HPWR_CHNMSK_S 8 #define AR_PCU_SMPS_LPWR_CHNMSK_VAL 0x1 /* MAC PCU frame start time trigger for the AP's Downlink Traffic in TDMA mode */ #define AR_TDMA_TXSTARTTRIG_LSB AR_MAC_PCU_OFFSET(MAC_PCU_TDMA_TXFRAME_START_TIME_TRIGGER_LSB) #define AR_TDMA_TXSTARTTRIG_MSB AR_MAC_PCU_OFFSET(MAC_PCU_TDMA_TXFRAME_START_TIME_TRIGGER_MSB) /* MAC Time stamp of the last beacon received */ #define AR_LAST_TSTP AR_MAC_PCU_OFFSET(MAC_PCU_LAST_BEACON_TSF) /* MAC current NAV value */ #define AR_NAV AR_MAC_PCU_OFFSET(MAC_PCU_NAV) /* MAC RTS exchange success counter */ #define AR_RTS_OK AR_MAC_PCU_OFFSET(MAC_PCU_RTS_SUCCESS_CNT) /* MAC RTS exchange failure counter */ #define AR_RTS_FAIL AR_MAC_PCU_OFFSET(MAC_PCU_RTS_FAIL_CNT) /* MAC ACK failure counter */ #define AR_ACK_FAIL AR_MAC_PCU_OFFSET(MAC_PCU_ACK_FAIL_CNT) /* MAC FCS check failure counter */ #define AR_FCS_FAIL AR_MAC_PCU_OFFSET(MAC_PCU_FCS_FAIL_CNT) /* MAC Valid beacon value */ #define AR_BEACON_CNT AR_MAC_PCU_OFFSET(MAC_PCU_BEACON_CNT) /* MAC PCU tdma slot alert control */ #define AR_TDMA_SLOT_ALERT_CNTL AR_MAC_PCU_OFFSET(MAC_PCU_TDMA_SLOT_ALERT_CNTL) /* MAC PCU Basic MCS set for MCS 0 to 31 */ #define AR_BASIC_SET AR_MAC_PCU_OFFSET(MAC_PCU_BASIC_SET) #define ALL_RATE 0xff /* MAC_PCU_ _SEQ */ #define AR_MGMT_SEQ AR_MAC_PCU_OFFSET(MAC_PCU_MGMT_SEQ) #define AR_MGMT_SEQ_MIN 0xFFF /* sequence minimum value*/ #define AR_MGMT_SEQ_MIN_S 0 #define AR_MIN_HW_SEQ 0 #define AR_MGMT_SEQ_MAX 0xFFF0000 /* sequence maximum value*/ #define AR_MGMT_SEQ_MAX_S 16 #define AR_MAX_HW_SEQ 0xFF /*MAC PCU Key Cache Antenna 1 */ #define AR_TX_ANT_1 AR_MAC_PCU_OFFSET(MAC_PCU_TX_ANT_1) /*MAC PCU Key Cache Antenna 2 */ #define AR_TX_ANT_2 AR_MAC_PCU_OFFSET(MAC_PCU_TX_ANT_2) /*MAC PCU Key Cache Antenna 3 */ #define AR_TX_ANT_3 AR_MAC_PCU_OFFSET(MAC_PCU_TX_ANT_3) /*MAC PCU Key Cache Antenna 4 */ #define AR_TX_ANT_4 AR_MAC_PCU_OFFSET(MAC_PCU_TX_ANT_4) /* Extended range mode */ #define AR_XRMODE AR_MAC_PCU_OFFSET(MAC_PCU_XRMODE) /* Extended range mode delay */ #define AR_XRDEL AR_MAC_PCU_OFFSET(MAC_PCU_XRDEL) /* Extended range mode timeout */ #define AR_XRTO AR_MAC_PCU_OFFSET(MAC_PCU_XRTO) /* Extended range mode chirp */ #define AR_XRCRP AR_MAC_PCU_OFFSET(MAC_PCU_XRCRP) /* Extended range stomp */ #define AR_XRSTMP AR_MAC_PCU_OFFSET(MAC_PCU_XRSTMP) /* Enhanced sleep control 1 */ #define AR_SLEEP1 AR_MAC_PCU_OFFSET(MAC_PCU_SLP1) #define AR_SLEEP1_ASSUME_DTIM 0x00080000 // Assume DTIM on missed beacon #define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000 // Cab timeout(TU) mask #define AR_SLEEP1_CAB_TIMEOUT_S 21 // Cab timeout(TU) shift /* Enhanced sleep control 2 */ #define AR_SLEEP2 AR_MAC_PCU_OFFSET(MAC_PCU_SLP2) #define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 // Beacon timeout(TU) mask #define AR_SLEEP2_BEACON_TIMEOUT_S 21 // Beacon timeout(TU) shift /*MAC_PCU_SELF_GEN_DEFAULT*/ #define AR_SELFGEN AR_MAC_PCU_OFFSET(MAC_PCU_SELF_GEN_DEFAULT) #define AR_MMSS 0x00000007 #define AR_MMSS_S 0 #define AR_SELFGEN_MMSS_NO RESTRICTION 0 #define AR_SELFGEN_MMSS_ONEOVER4_us 1 #define AR_SELFGEN_MMSS_ONEOVER2_us 2 #define AR_SELFGEN_MMSS_ONE_us 3 #define AR_SELFGEN_MMSS_TWO_us 4 #define AR_SELFGEN_MMSS_FOUR_us 5 #define AR_SELFGEN_MMSS_EIGHT_us 6 #define AR_SELFGEN_MMSS_SIXTEEN_us 7 #define AR_CEC 0x00000018 #define AR_CEC_S 3 /* Although in original standard 0 is for 1 stream and 1 is for 2 stream */ /* due to H/W resaon, Here should set 1 for 1 stream and 2 for 2 stream */ #define AR_SELFGEN_CEC_ONE_SPACETIMESTREAM 1 #define AR_SELFGEN_CEC_TWO_SPACETIMESTREAM 2 /* BSSID mask lower 32 bits */ #define AR_BSSMSKL AR_MAC_PCU_OFFSET(MAC_PCU_ADDR1_MASK_L32) /* BSSID mask upper 16 bits */ #define AR_BSSMSKU AR_MAC_PCU_OFFSET(MAC_PCU_ADDR1_MASK_U16) /* Transmit power control for gen frames */ #define AR_TPC AR_MAC_PCU_OFFSET(MAC_PCU_TPC) #define AR_TPC_ACK 0x0000003f // ack frames mask #define AR_TPC_ACK_S 0x00 // ack frames shift #define AR_TPC_CTS 0x00003f00 // cts frames mask #define AR_TPC_CTS_S 0x08 // cts frames shift #define AR_TPC_CHIRP 0x003f0000 // chirp frames mask #define AR_TPC_CHIRP_S 16 // chirp frames shift #define AR_TPC_RPT 0x3f000000 // rpt frames mask #define AR_TPC_RPT_S 24 // rpt frames shift /* Profile count transmit frames */ #define AR_TFCNT AR_MAC_PCU_OFFSET(MAC_PCU_TX_FRAME_CNT) /* Profile count receive frames */ #define AR_RFCNT AR_MAC_PCU_OFFSET(MAC_PCU_RX_FRAME_CNT) /* Profile count receive clear */ #define AR_RCCNT AR_MAC_PCU_OFFSET(MAC_PCU_RX_CLEAR_CNT) /* Profile count cycle counter */ #define AR_CCCNT AR_MAC_PCU_OFFSET(MAC_PCU_CYCLE_CNT) /* Quiet time programming for TGh */ #define AR_QUIET1 AR_MAC_PCU_OFFSET(MAC_PCU_QUIET_TIME_1) #define AR_QUIET1_NEXT_QUIET_S 0 // TSF of next quiet period (TU) #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff #define AR_QUIET1_QUIET_ENABLE 0x00010000 // Enable Quiet time operation #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 // ack/cts in quiet period #define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17 #define AR_QUIET2 AR_MAC_PCU_OFFSET(MAC_PCU_QUIET_TIME_2) #define AR_QUIET2_QUIET_PERIOD_S 0 // Periodicity of quiet period (TU) #define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff #define AR_QUIET2_QUIET_DUR_S 16 // quiet period (TU) #define AR_QUIET2_QUIET_DUR 0xffff0000 /* locate no_ack in qos */ #define AR_QOS_NO_ACK AR_MAC_PCU_OFFSET(MAC_PCU_QOS_NO_ACK) #define AR_QOS_NO_ACK_TWO_BIT 0x0000000f // 2 bit sentinel for no-ack #define AR_QOS_NO_ACK_TWO_BIT_S 0 #define AR_QOS_NO_ACK_BIT_OFF 0x00000070 // offset for no-ack #define AR_QOS_NO_ACK_BIT_OFF_S 4 #define AR_QOS_NO_ACK_BYTE_OFF 0x00000180 // from end of header #define AR_QOS_NO_ACK_BYTE_OFF_S 7 /* Phy errors to be filtered */ #define AR_PHY_ERR AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERROR_MASK) /* XXX validate! XXX */ #define AR_PHY_ERR_DCHIRP 0x00000008 // Bit 3 enables double chirp #define AR_PHY_ERR_RADAR 0x00000020 // Bit 5 is Radar signal #define AR_PHY_ERR_OFDM_TIMING 0x00020000 // Bit 17 is AH_FALSE detect for OFDM #define AR_PHY_ERR_CCK_TIMING 0x02000000 // Bit 25 is AH_FALSE detect for CCK /* MAC PCU extended range latency */ #define AR_XRLAT AR_MAC_PCU_OFFSET(MAC_PCU_XRLAT) /* MAC PCU Receive Buffer settings */ #define AR_RXFIFO_CFG AR_MAC_PCU_OFFSET(MAC_PCU_RXBUF) #define AR_RXFIFO_CFG_REG_RD_ENA_S 11 #define AR_RXFIFO_CFG_REG_RD_ENA (0x1 << AR_RXFIFO_CFG_REG_RD_ENA_S) /* MAC PCU QoS control */ #define AR_MIC_QOS_CONTROL AR_MAC_PCU_OFFSET(MAC_PCU_MIC_QOS_CONTROL) /* MAC PCU Michael QoS select */ #define AR_MIC_QOS_SELECT AR_MAC_PCU_OFFSET(MAC_PCU_MIC_QOS_SELECT) /* PCU Miscellaneous Mode */ #define AR_PCU_MISC AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE) #define AR_PCU_FORCE_BSSID_MATCH 0x00000001 // force bssid to match #define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 // tx/rx mic key are together #define AR_PCU_TX_ADD_TSF 0x00000008 // add tx_tsf + int_tsf #define AR_PCU_CCK_SIFS_MODE 0x00000010 // assume 11b sifs programmed #define AR_PCU_RX_ANT_UPDT 0x00000800 // KC_RX_ANT_UPDATE #define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 // enforce txop / tbtt #define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 // count bmiss's when sleeping #define AR_PCU_BUG_12306_FIX_ENA 0x00020000 // use rx_clear to count sifs #define AR_PCU_FORCE_QUIET_COLL 0x00040000 // kill xmit for channel change #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 #define AR_PCU_BT_ANT_PREVENT_RX_S 20 #define AR_PCU_TBTT_PROTECT 0x00200000 // no xmit upto tbtt + 20 uS #define AR_PCU_CLEAR_VMF 0x01000000 // clear vmf mode (fast cc) #define AR_PCU_CLEAR_BA_VALID 0x04000000 // clear ba state #define AR_PCU_SEL_EVM 0x08000000 // select EVM data or PLCP header #define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000 /* always perform key search */ /* count of filtered ofdm */ #define AR_FILT_OFDM AR_MAC_PCU_OFFSET(MAC_PCU_FILTER_OFDM_CNT) #define AR_FILT_OFDM_COUNT 0x00FFFFFF // count of filtered ofdm /* count of filtered cck */ #define AR_FILT_CCK AR_MAC_PCU_OFFSET(MAC_PCU_FILTER_CCK_CNT) #define AR_FILT_CCK_COUNT 0x00FFFFFF // count of filtered cck /* MAC PCU PHY error counter 1 */ #define AR_PHY_ERR_1 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_1) #define AR_PHY_ERR_1_COUNT 0x00FFFFFF // phy errs that pass mask_1 /* MAC PCU PHY error mask 1 */ #define AR_PHY_ERR_MASK_1 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_1_MASK) /* MAC PCU PHY error counter 2 */ #define AR_PHY_ERR_2 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_2) #define AR_PHY_ERR_2_COUNT 0x00FFFFFF // phy errs that pass mask_2 /* MAC PCU PHY error mask 2 */ #define AR_PHY_ERR_MASK_2 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_2_MASK) #define AR_PHY_COUNTMAX (3 << 22) // Max counted before intr #define AR_MIBCNT_INTRMASK (3 << 22) // Mask top 2 bits of counters /* interrupt if rx_tsf-int_tsf */ #define AR_TSFOOR_THRESHOLD AR_MAC_PCU_OFFSET(MAC_PCU_TSF_THRESHOLD) #define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF // field width /* MAC PCU PHY error counter 3 */ #define AR_PHY_ERR_3 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_3) #define AR_PHY_ERR_3_COUNT 0x00FFFFFF // phy errs that pass mask_3 /* MAC PCU PHY error mask 3 */ #define AR_PHY_ERR_MASK_3 AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_3_MASK) /* Bluetooth coexistance mode */ #define AR_BT_COEX_MODE AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_MODE) #define AR_BT_TIME_EXTEND 0x000000ff #define AR_BT_TIME_EXTEND_S 0 #define AR_BT_TXSTATE_EXTEND 0x00000100 #define AR_BT_TXSTATE_EXTEND_S 8 #define AR_BT_TX_FRAME_EXTEND 0x00000200 #define AR_BT_TX_FRAME_EXTEND_S 9 #define AR_BT_MODE 0x00000c00 #define AR_BT_MODE_S 10 #define AR_BT_QUIET 0x00001000 #define AR_BT_QUIET_S 12 #define AR_BT_QCU_THRESH 0x0001e000 #define AR_BT_QCU_THRESH_S 13 #define AR_BT_RX_CLEAR_POLARITY 0x00020000 #define AR_BT_RX_CLEAR_POLARITY_S 17 #define AR_BT_PRIORITY_TIME 0x00fc0000 #define AR_BT_PRIORITY_TIME_S 18 #define AR_BT_FIRST_SLOT_TIME 0xff000000 #define AR_BT_FIRST_SLOT_TIME_S 24 /* BlueTooth coexistance WLAN weights */ #define AR_BT_COEX_WL_WEIGHTS0 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_WL_WEIGHTS0) #define AR_BT_BT_WGHT 0x0000ffff #define AR_BT_BT_WGHT_S 0 #define AR_BT_WL_WGHT 0xffff0000 #define AR_BT_WL_WGHT_S 16 /* HCF timeout: Slotted behavior */ #define AR_HCFTO AR_MAC_PCU_OFFSET(MAC_PCU_HCF_TIMEOUT) /* BlueTooth mode 2: Slotted behavior */ #define AR_BT_COEX_MODE2 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_MODE2) #define AR_BT_BCN_MISS_THRESH 0x000000ff #define AR_BT_BCN_MISS_THRESH_S 0 #define AR_BT_BCN_MISS_CNT 0x0000ff00 #define AR_BT_BCN_MISS_CNT_S 8 #define AR_BT_HOLD_RX_CLEAR 0x00010000 #define AR_BT_HOLD_RX_CLEAR_S 16 #define AR_BT_SLEEP_ALLOW_BT 0x00020000 #define AR_BT_SLEEP_ALLOW_BT_S 17 #define AR_BT_PROTECT_AFTER_WAKE 0x00080000 #define AR_BT_PROTECT_AFTER_WAKE_S 19 #define AR_BT_DISABLE_BT_ANT 0x00100000 #define AR_BT_DISABLE_BT_ANT_S 20 #define AR_BT_QUIET_2_WIRE 0x00200000 #define AR_BT_QUIET_2_WIRE_S 21 #define AR_BT_WL_ACTIVE_MODE 0x00c00000 #define AR_BT_WL_ACTIVE_MODE_S 22 #define AR_BT_WL_TXRX_SEPARATE 0x01000000 #define AR_BT_WL_TXRX_SEPARATE_S 24 #define AR_BT_RS_DISCARD_EXTEND 0x02000000 #define AR_BT_RS_DISCARD_EXTEND_S 25 #define AR_BT_TSF_BT_ACTIVE_CTRL 0x0c000000 #define AR_BT_TSF_BT_ACTIVE_CTRL_S 26 #define AR_BT_TSF_BT_PRIORITY_CTRL 0x30000000 #define AR_BT_TSF_BT_PRIORITY_CTRL_S 28 #define AR_BT_INTERRUPT_ENABLE 0x40000000 #define AR_BT_INTERRUPT_ENABLE_S 30 #define AR_BT_PHY_ERR_BT_COLL_ENABLE 0x80000000 #define AR_BT_PHY_ERR_BT_COLL_ENABLE_S 31 /* Generic Timers 2 */ #define AR_GEN_TIMERS2_0 AR_MAC_PCU_OFFSET(MAC_PCU_GENERIC_TIMERS2) #define AR_GEN_TIMERS2_NEXT(_i) (AR_GEN_TIMERS2_0 + ((_i)<<2)) #define AR_GEN_TIMERS2_PERIOD(_i) (AR_GEN_TIMERS2_NEXT(8) + ((_i)<<2)) #define AR_GEN_TIMERS2_0_NEXT AR_GEN_TIMERS2_NEXT(0) #define AR_GEN_TIMERS2_1_NEXT AR_GEN_TIMERS2_NEXT(1) #define AR_GEN_TIMERS2_2_NEXT AR_GEN_TIMERS2_NEXT(2) #define AR_GEN_TIMERS2_3_NEXT AR_GEN_TIMERS2_NEXT(3) #define AR_GEN_TIMERS2_4_NEXT AR_GEN_TIMERS2_NEXT(4) #define AR_GEN_TIMERS2_5_NEXT AR_GEN_TIMERS2_NEXT(5) #define AR_GEN_TIMERS2_6_NEXT AR_GEN_TIMERS2_NEXT(6) #define AR_GEN_TIMERS2_7_NEXT AR_GEN_TIMERS2_NEXT(7) #define AR_GEN_TIMERS2_0_PERIOD AR_GEN_TIMERS2_PERIOD(0) #define AR_GEN_TIMERS2_1_PERIOD AR_GEN_TIMERS2_PERIOD(1) #define AR_GEN_TIMERS2_2_PERIOD AR_GEN_TIMERS2_PERIOD(2) #define AR_GEN_TIMERS2_3_PERIOD AR_GEN_TIMERS2_PERIOD(3) #define AR_GEN_TIMERS2_4_PERIOD AR_GEN_TIMERS2_PERIOD(4) #define AR_GEN_TIMERS2_5_PERIOD AR_GEN_TIMERS2_PERIOD(5) #define AR_GEN_TIMERS2_6_PERIOD AR_GEN_TIMERS2_PERIOD(6) #define AR_GEN_TIMERS2_7_PERIOD AR_GEN_TIMERS2_PERIOD(7) #define AR_GEN_TIMER_BANK_1_LEN 8 #define AR_FIRST_NDP_TIMER 7 #define AR_NUM_GEN_TIMERS 16 #define AR_GEN_TIMER_RESERVED 8 /* Generic Timers 2 Mode */ #define AR_GEN_TIMERS2_MODE AR_MAC_PCU_OFFSET(MAC_PCU_GENERIC_TIMERS2_MODE) /* BlueTooth coexistance WLAN weights 1 */ #define AR_BT_COEX_WL_WEIGHTS1 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_WL_WEIGHTS1) /* BlueTooth Coexistence TSF Snapshot for BT_ACTIVE */ #define AR_BT_TSF_ACTIVE AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_TSF_BT_ACTIVE) /* BlueTooth Coexistence TSF Snapshot for BT_PRIORITY */ #define AR_BT_TSF_PRIORITY AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_TSF_BT_PRIORITY) /* SIFS, TX latency and ACK shift */ #define AR_TXSIFS AR_MAC_PCU_OFFSET(MAC_PCU_TXSIFS) #define AR_TXSIFS_TIME 0x000000FF // uS in SIFS #define AR_TXSIFS_TX_LATENCY 0x00000F00 // uS for transmission thru bb #define AR_TXSIFS_TX_LATENCY_S 8 #define AR_TXSIFS_ACK_SHIFT 0x00007000 // chan width for ack #define AR_TXSIFS_ACK_SHIFT_S 12 /* BlueTooth mode 3 */ #define AR_BT_COEX_MODE3 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_MODE3) /* TXOP for legacy non-qos */ #define AR_TXOP_X AR_MAC_PCU_OFFSET(MAC_PCU_TXOP_X) #define AR_TXOP_X_VAL 0x000000FF /* TXOP for TID 0 to 3 */ #define AR_TXOP_0_3 AR_MAC_PCU_OFFSET(MAC_PCU_TXOP_0_3) /* TXOP for TID 4 to 7 */ #define AR_TXOP_4_7 AR_MAC_PCU_OFFSET(MAC_PCU_TXOP_4_7) /* TXOP for TID 8 to 11 */ #define AR_TXOP_8_11 AR_MAC_PCU_OFFSET(MAC_PCU_TXOP_8_11) /* TXOP for TID 12 to 15 */ #define AR_TXOP_12_15 AR_MAC_PCU_OFFSET(MAC_PCU_TXOP_12_15) /* Generic Timers */ #define AR_GEN_TIMERS_0 AR_MAC_PCU_OFFSET(MAC_PCU_GENERIC_TIMERS) #define AR_GEN_TIMERS(_i) (AR_GEN_TIMERS_0 + ((_i)<<2)) /* generic timers based on tsf - all uS */ #define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) #define AR_NEXT_DMA_BEACON_ALERT AR_GEN_TIMERS(1) #define AR_NEXT_SWBA AR_GEN_TIMERS(2) #define AR_NEXT_HCF AR_GEN_TIMERS(3) #define AR_NEXT_TIM AR_GEN_TIMERS(4) #define AR_NEXT_DTIM AR_GEN_TIMERS(5) #define AR_NEXT_QUIET_TIMER AR_GEN_TIMERS(6) #define AR_NEXT_NDP_TIMER AR_GEN_TIMERS(7) #define AR_BEACON_PERIOD AR_GEN_TIMERS(8) #define AR_DMA_BEACON_PERIOD AR_GEN_TIMERS(9) #define AR_SWBA_PERIOD AR_GEN_TIMERS(10) #define AR_HCF_PERIOD AR_GEN_TIMERS(11) #define AR_TIM_PERIOD AR_GEN_TIMERS(12) #define AR_DTIM_PERIOD AR_GEN_TIMERS(13) #define AR_QUIET_PERIOD AR_GEN_TIMERS(14) #define AR_NDP_PERIOD AR_GEN_TIMERS(15) /* Generic Timers Mode */ #define AR_TIMER_MODE AR_MAC_PCU_OFFSET(MAC_PCU_GENERIC_TIMERS_MODE) #define AR_TBTT_TIMER_EN 0x00000001 #define AR_DBA_TIMER_EN 0x00000002 #define AR_SWBA_TIMER_EN 0x00000004 #define AR_HCF_TIMER_EN 0x00000008 #define AR_TIM_TIMER_EN 0x00000010 #define AR_DTIM_TIMER_EN 0x00000020 #define AR_QUIET_TIMER_EN 0x00000040 #define AR_NDP_TIMER_EN 0x00000080 #define AR_TIMER_OVERFLOW_INDEX 0x00000700 #define AR_TIMER_OVERFLOW_INDEX_S 8 #define AR_TIMER_THRESH 0xFFFFF000 #define AR_TIMER_THRESH_S 12 #define AR_SLP32_MODE AR_MAC_PCU_OFFSET(MAC_PCU_SLP32_MODE) #define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF // rising <-> falling edge #define AR_SLP32_ENA 0x00100000 #define AR_SLP32_TSF_WRITE_STATUS 0x00200000 // tsf update in progress #define AR_SLP32_WAKE AR_MAC_PCU_OFFSET(MAC_PCU_SLP32_WAKE) #define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF // time to wake crystal #define AR_SLP32_INC AR_MAC_PCU_OFFSET(MAC_PCU_SLP32_INC) #define AR_SLP32_TST_INC 0x000FFFFF /* Sleep MIB cycle count 32kHz cycles for which mac is asleep */ #define AR_SLP_CNT AR_MAC_PCU_OFFSET(MAC_PCU_SLP_MIB1) #define AR_SLP_CYCLE_CNT 0x8254 // absolute number of 32kHz cycles /* Sleep MIB cycle count 2 */ #define AR_SLP_MIB2 AR_MAC_PCU_OFFSET(MAC_PCU_SLP_MIB2) /* Sleep MIB control status */ #define AR_SLP_MIB_CTRL AR_MAC_PCU_OFFSET(MAC_PCU_SLP_MIB3) #define AR_SLP_MIB_CLEAR 0x00000001 // clear pending #define AR_SLP_MIB_PENDING 0x00000002 // clear counters //#ifdef AR9300_EMULATION // MAC trace buffer registers (emulation only) #define AR_MAC_PCU_LOGIC_ANALYZER AR_MAC_PCU_OFFSET(MAC_PCU_LOGIC_ANALYZER) #define AR_MAC_PCU_LOGIC_ANALYZER_CTL 0x0000000F #define AR_MAC_PCU_LOGIC_ANALYZER_HOLD 0x00000001 #define AR_MAC_PCU_LOGIC_ANALYZER_CLEAR 0x00000002 #define AR_MAC_PCU_LOGIC_ANALYZER_STATE 0x00000004 #define AR_MAC_PCU_LOGIC_ANALYZER_ENABLE 0x00000008 #define AR_MAC_PCU_LOGIC_ANALYZER_QCU_SEL 0x000000F0 #define AR_MAC_PCU_LOGIC_ANALYZER_QCU_SEL_S 4 #define AR_MAC_PCU_LOGIC_ANALYZER_INT_ADDR 0x0003FF00 #define AR_MAC_PCU_LOGIC_ANALYZER_INT_ADDR_S 8 #define AR_MAC_PCU_LOGIC_ANALYZER_DIAG_MODE 0xFFFC0000 #define AR_MAC_PCU_LOGIC_ANALYZER_DIAG_MODE_S 18 #define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20614 0x00040000 #define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 #define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20803 0x40000000 #define AR_MAC_PCU_LOGIC_ANALYZER_PSTABUG75996 0x9d500010 #define AR_MAC_PCU_LOGIC_ANALYZER_VC_MODE 0x9d400010 #define AR_MAC_PCU_LOGIC_ANALYZER_32L AR_MAC_PCU_OFFSET(MAC_PCU_LOGIC_ANALYZER_32L) #define AR_MAC_PCU_LOGIC_ANALYZER_16U AR_MAC_PCU_OFFSET(MAC_PCU_LOGIC_ANALYZER_16U) #define AR_MAC_PCU_TRACE_REG_START 0xE000 #define AR_MAC_PCU_TRACE_REG_END 0xFFFC #define AR_MAC_PCU_TRACE_BUFFER_LENGTH (AR_MAC_PCU_TRACE_REG_END - AR_MAC_PCU_TRACE_REG_START + sizeof(uint32_t)) //#endif // AR9300_EMULATION /* MAC PCU global mode register */ #define AR_2040_MODE AR_MAC_PCU_OFFSET(MAC_PCU_20_40_MODE) #define AR_2040_JOINED_RX_CLEAR 0x00000001 // use ctl + ext rx_clear for cca /* MAC PCU H transfer timeout register */ #define AR_H_XFER_TIMEOUT AR_MAC_PCU_OFFSET(MAC_PCU_H_XFER_TIMEOUT) #define AR_EXBF_IMMDIATE_RESP 0x00000040 #define AR_EXBF_NOACK_NO_RPT 0x00000100 #define AR_H_XFER_TIMEOUT_COUNT 0xf #define AR_H_XFER_TIMEOUT_COUNT_S 0 /* * Additional cycle counter. See also AR_CCCNT * extension channel rx clear count * counts number of cycles rx_clear (ext) is low (i.e. busy) * when the MAC is not actively transmitting/receiving */ #define AR_EXTRCCNT AR_MAC_PCU_OFFSET(MAC_PCU_RX_CLEAR_DIFF_CNT) /* antenna mask for self generated files */ #define AR_SELFGEN_MASK AR_MAC_PCU_OFFSET(MAC_PCU_SELF_GEN_ANTENNA_MASK) /* control registers for block BA control fields */ #define AR_BA_BAR_CONTROL AR_MAC_PCU_OFFSET(MAC_PCU_BA_BAR_CONTROL) /* legacy PLCP spoof */ #define AR_LEG_PLCP_SPOOF AR_MAC_PCU_OFFSET(MAC_PCU_LEGACY_PLCP_SPOOF) /* PHY error mask and EIFS mask continued */ #define AR_PHY_ERR_MASK_CONT AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERROR_MASK_CONT) /* MAC PCU transmit timer */ #define AR_TX_TIMER AR_MAC_PCU_OFFSET(MAC_PCU_TX_TIMER) /* MAC PCU transmit buffer control */ #define AR_PCU_TXBUF_CTRL AR_MAC_PCU_OFFSET(MAC_PCU_TXBUF_CTRL) #define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF #define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 /* * MAC PCU miscellaneous mode 2 * WAR flags for various bugs, see mac_pcu_reg documentation. */ #define AR_PCU_MISC_MODE2 AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE2) #define AR_PCU_MISC_MODE2_BUG_21532_ENABLE 0x00000001 #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 /* Decrypt MGT frames using MFP method */ #define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 /* Don't decrypt MGT frames at all */ #define AR_BUG_58603_FIX_ENABLE 0x00000008 /* Enable fix for bug 58603. This allows * the use of AR_AGG_WEP_ENABLE. */ #define AR_PCU_MISC_MODE2_PROM_VC_MODE 0xa148103b /* Enable promiscous in azimuth mode */ #define AR_PCU_MISC_MODE2_RESERVED 0x00000038 #define AR_ADHOC_MCAST_KEYID_ENABLE 0x00000040 /* This bit enables the Multicast search * based on both MAC Address and Key ID. * If bit is 0, then Multicast search is * based on MAC address only. * For Merlin and above only. */ #define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080 #define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00 #define AR_PCU_MISC_MODE2_MGMT_QOS_S 8 #define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000 #define AR_AGG_WEP_ENABLE 0x00020000 /* This field enables AGG_WEP feature, * when it is enable, AGG_WEP would takes * charge of the encryption interface of * pcu_txsm. */ #define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 #define AR_PCU_MISC_MODE2_PROXY_STA 0x01000000 /* see EV 75996 */ #define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 #define AR_DECOUPLE_DECRYPTION 0x08000000 #define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000 /* MAC PCU Alternate AES QoS mute mask */ #define AR_ALT_AES_MUTE_MASK AR_MAC_PCU_OFFSET(MAC_PCU_ALT_AES_MUTE_MASK) /* Async Fifo registers - debug only */ #define AR_ASYNC_FIFO_1 AR_MAC_PCU_OFFSET(ASYNC_FIFO_REG1) #define AR_ASYNC_FIFO_2 AR_MAC_PCU_OFFSET(ASYNC_FIFO_REG2) #define AR_ASYNC_FIFO_3 AR_MAC_PCU_OFFSET(ASYNC_FIFO_REG3) /* Maps the 16 user priority TID values to Access categories */ #define AR_TID_TO_AC_MAP AR_MAC_PCU_OFFSET(MAC_PCU_TID_TO_AC) /* High Priority Queue Control */ #define AR_HP_Q_CONTROL AR_MAC_PCU_OFFSET(MAC_PCU_HP_QUEUE) /* Rx High Priority Queue Control */ #define AR_HPQ_CONTROL AR_MAC_PCU_OFFSET(MAC_PCU_HP_QUEUE) #define AR_HPQ_ENABLE 0x00000001 #define AR_HPQ_MASK_BE 0x00000002 #define AR_HPQ_MASK_BK 0x00000004 #define AR_HPQ_MASK_VI 0x00000008 #define AR_HPQ_MASK_VO 0x00000010 #define AR_HPQ_UAPSD 0x00000020 #define AR_HPQ_FRAME_FILTER_0 0x00000040 #define AR_HPQ_FRAME_BSSID_MATCH_0 0x00000080 #define AR_HPQ_UAPSD_TRIGGER_EN 0x00100000 #define AR_BT_COEX_BT_WEIGHTS0 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_BT_WEIGHTS0) #define AR_BT_COEX_BT_WEIGHTS1 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_BT_WEIGHTS1) #define AR_BT_COEX_BT_WEIGHTS2 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_BT_WEIGHTS2) #define AR_BT_COEX_BT_WEIGHTS3 AR_MAC_PCU_OFFSET(MAC_PCU_BLUETOOTH_BT_WEIGHTS3) #define AR_AGC_SATURATION_CNT0 AR_MAC_PCU_OFFSET(MAC_PCU_AGC_SATURATION_CNT0) #define AR_AGC_SATURATION_CNT1 AR_MAC_PCU_OFFSET(MAC_PCU_AGC_SATURATION_CNT1) #define AR_AGC_SATURATION_CNT2 AR_MAC_PCU_OFFSET(MAC_PCU_AGC_SATURATION_CNT2) /* Hardware beacon processing */ #define AR_HWBCNPROC1 AR_MAC_PCU_OFFSET(MAC_PCU_HW_BCN_PROC1) #define AR_HWBCNPROC1_CRC_ENABLE 0x00000001 /* Enable hw beacon processing */ #define AR_HWBCNPROC1_RESET_CRC 0x00000002 /* Reset the last beacon CRC calculated */ #define AR_HWBCNPROC1_EXCLUDE_BCN_INTVL 0x00000004 /* Exclude Beacon interval in CRC calculation */ #define AR_HWBCNPROC1_EXCLUDE_CAP_INFO 0x00000008 /* Exclude Beacon capability information in CRC calculation */ #define AR_HWBCNPROC1_EXCLUDE_TIM_ELM 0x00000010 /* Exclude Beacon TIM element in CRC calculation */ #define AR_HWBCNPROC1_EXCLUDE_ELM0 0x00000020 /* Exclude element ID ELM0 in CRC calculation */ #define AR_HWBCNPROC1_EXCLUDE_ELM1 0x00000040 /* Exclude element ID ELM1 in CRC calculation */ #define AR_HWBCNPROC1_EXCLUDE_ELM2 0x00000080 /* Exclude element ID ELM2 in CRC calculation */ #define AR_HWBCNPROC1_ELM0_ID 0x0000FF00 /* Element ID 0 */ #define AR_HWBCNPROC1_ELM0_ID_S 8 #define AR_HWBCNPROC1_ELM1_ID 0x00FF0000 /* Element ID 1 */ #define AR_HWBCNPROC1_ELM1_ID_S 16 #define AR_HWBCNPROC1_ELM2_ID 0xFF000000 /* Element ID 2 */ #define AR_HWBCNPROC1_ELM2_ID_S 24 #define AR_HWBCNPROC2 AR_MAC_PCU_OFFSET(MAC_PCU_HW_BCN_PROC2) #define AR_HWBCNPROC2_FILTER_INTERVAL_ENABLE 0x00000001 /* Enable filtering beacons based on filter interval */ #define AR_HWBCNPROC2_RESET_INTERVAL 0x00000002 /* Reset internal interval counter interval */ #define AR_HWBCNPROC2_EXCLUDE_ELM3 0x00000004 /* Exclude element ID ELM3 in CRC calculation */ #define AR_HWBCNPROC2_RSVD 0x000000F8 /* reserved */ #define AR_HWBCNPROC2_FILTER_INTERVAL 0x0000FF00 /* Filter interval for beacons */ #define AR_HWBCNPROC2_FILTER_INTERVAL_S 8 #define AR_HWBCNPROC2_ELM3_ID 0x00FF0000 /* Element ID 3 */ #define AR_HWBCNPROC2_ELM3_ID_S 16 #define AR_HWBCNPROC2_RSVD2 0xFF000000 /* reserved */ #define AR_MAC_PCU_MISC_MODE3 AR_MAC_PCU_OFFSET(MAC_PCU_MISC_MODE3) #define AR_BUG_61936_FIX_ENABLE 0x00000040 /* EV61936 - rx descriptor corruption */ #define AR_TIME_BASED_DISCARD_EN 0x80000000 #define AR_TIME_BASED_DISCARD_EN_S 31 #define AR_MAC_PCU_GEN_TIMER_TSF_SEL AR_MAC_PCU_OFFSET(MAC_PCU_GENERIC_TIMERS_TSF_SEL) #define AR_MAC_PCU_TBD_FILTER AR_MAC_PCU_OFFSET(MAC_PCU_TBD_FILTER) #define AR_MAC_PCU_USE_WBTIMER_TX_TS 0x00000001 #define AR_MAC_PCU_USE_WBTIMER_TX_TS_S 0 #define AR_MAC_PCU_USE_WBTIMER_RX_TS 0x00000002 #define AR_MAC_PCU_USE_WBTIMER_RX_TS_S 1 #define AR_TXBUF_BA AR_MAC_PCU_OFFSET(MAC_PCU_TXBUF_BA) /* MAC Key Cache */ #define AR_KEYTABLE_0 AR_MAC_PCU_OFFSET(MAC_PCU_KEY_CACHE) #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) #define AR_KEY_CACHE_SIZE 128 #define AR_RSVD_KEYTABLE_ENTRIES 4 #define AR_KEY_TYPE 0x00000007 // MAC Key Type Mask #define AR_KEYTABLE_TYPE_40 0x00000000 /* WEP 40 bit key */ #define AR_KEYTABLE_TYPE_104 0x00000001 /* WEP 104 bit key */ #define AR_KEYTABLE_TYPE_128 0x00000003 /* WEP 128 bit key */ #define AR_KEYTABLE_TYPE_TKIP 0x00000004 /* TKIP and Michael */ #define AR_KEYTABLE_TYPE_AES 0x00000005 /* AES/OCB 128 bit key */ #define AR_KEYTABLE_TYPE_CCM 0x00000006 /* AES/CCM 128 bit key */ #define AR_KEYTABLE_TYPE_CLR 0x00000007 /* no encryption */ #define AR_KEYTABLE_ANT 0x00000008 /* previous transmit antenna */ #define AR_KEYTABLE_UAPSD 0x000001E0 /* UAPSD AC mask */ #define AR_KEYTABLE_UAPSD_S 5 #define AR_KEYTABLE_PWRMGT 0x00000200 /* hw managed PowerMgt bit */ #define AR_KEYTABLE_MMSS 0x00001c00 /* remote's MMSS*/ #define AR_KEYTABLE_MMSS_S 10 #define AR_KEYTABLE_CEC 0x00006000 /* remote's CEC*/ #define AR_KEYTABLE_CEC_S 13 #define AR_KEYTABLE_STAGGED 0x00010000 /* remote's stagged sounding*/ #define AR_KEYTABLE_STAGGED_S 16 #define AR_KEYTABLE_VALID 0x00008000 /* key and MAC address valid */ #define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) /* key bit 0-31 */ #define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) /* key bit 32-47 */ #define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) /* key bit 48-79 */ #define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) /* key bit 80-95 */ #define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) /* key bit 96-127 */ #define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) /* key type */ #define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) /* MAC address 1-32 */ #define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) /* MAC address 33-47 */ #define AR_KEYTABLE_DIR_ACK_BIT 0x00000010 /* Directed ACK bit */ /* * MAC WoW Registers. */ #define AR_WOW_PATTERN_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW1) #define AR_WOW_PAT_BACKOFF 0x00000004 #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */ #define AR_WOW_MAC_INTR_EN 0x00040000 #define AR_WOW_MAGIC_EN 0x00010000 #define AR_WOW_PATTERN_EN(x) ((x & 0xff) << 0) #define AR_WOW_PATTERN_FOUND_SHIFT 8 #define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PATTERN_FOUND_SHIFT)) #define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PATTERN_FOUND_SHIFT) #define AR_WOW_MAGIC_PAT_FOUND 0x00020000 #define AR_WOW_MAC_INTR 0x00080000 #define AR_WOW_KEEP_ALIVE_FAIL 0x00100000 #define AR_WOW_BEACON_FAIL 0x00200000 #define AR_WOW_COUNT_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW2) #define AR_WOW_AIFS_CNT(x) ((x & 0xff) << 0) #define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8) #define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16) /* * Default values for Wow Configuration for backoff, aifs, slot, keep-alive, etc. * to be programmed into various registers. */ #define AR_WOW_CNT_AIFS_CNT 0x00000022 // AR_WOW_COUNT_REG #define AR_WOW_CNT_SLOT_CNT 0x00000009 // AR_WOW_COUNT_REG /* * Keepalive count applicable for Merlin 2.0 and above. */ #define AR_WOW_CNT_KA_CNT 0x00000008 // AR_WOW_COUNT_REG #define AR_WOW_BCN_EN_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW3_BEACON_FAIL) #define AR_WOW_BEACON_FAIL_EN 0x00000001 #define AR_WOW_BCN_TIMO_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW3_BEACON) #define AR_WOW_BEACON_TIMO 0x40000000 /* Valid if BCN_EN is set */ #define AR_WOW_BEACON_TIMO_MAX 0xFFFFFFFF /* Max. value for Beacon Timeout */ #define AR_WOW_KEEP_ALIVE_TIMO_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW3_KEEP_ALIVE) #define AR_WOW_KEEP_ALIVE_TIMO 0x00007A12 #define AR_WOW_KEEP_ALIVE_NEVER 0xFFFFFFFF #define AR_WOW_KEEP_ALIVE_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW_KA) #define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001 #define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002 #define AR_WOW_US_SCALAR_REG AR_MAC_PCU_OFFSET(PCU_1US) #define AR_WOW_KEEP_ALIVE_DELAY_REG AR_MAC_PCU_OFFSET(PCU_KA) #define AR_WOW_KEEP_ALIVE_DELAY 0x000003E8 // 1 msec #define AR_WOW_PATTERN_MATCH_REG AR_MAC_PCU_OFFSET(WOW_EXACT) #define AR_WOW_PAT_END_OF_PKT(x) ((x & 0xf) << 0) #define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8) #define AR_WOW_PATTERN_MATCH_REG_2 AR_MAC_PCU_OFFSET(WOW2_EXACT) #define AR_WOW_PATTERN_OFF1_REG AR_MAC_PCU_OFFSET(PCU_WOW4) /* Pattern bytes 0 -> 3 */ #define AR_WOW_PATTERN_OFF2_REG AR_MAC_PCU_OFFSET(PCU_WOW5) /* Pattern bytes 4 -> 7 */ #define AR_WOW_PATTERN_OFF3_REG AR_MAC_PCU_OFFSET(PCU_WOW6) /* Pattern bytes 8 -> 11 */ #define AR_WOW_PATTERN_OFF4_REG AR_MAC_PCU_OFFSET(PCU_WOW7) /* Pattern bytes 12 -> 15 */ /* start address of the frame in RxBUF */ #define AR_WOW_RXBUF_START_ADDR AR_MAC_PCU_OFFSET(MAC_PCU_WOW6) /* Pattern detect and enable bits */ #define AR_WOW_PATTERN_DETECT_ENABLE AR_MAC_PCU_OFFSET(MAC_PCU_WOW4) /* Rx Abort Enable */ #define AR_WOW_RX_ABORT_ENABLE AR_MAC_PCU_OFFSET(MAC_PCU_WOW5) /* PHY error counter 1, 2, and 3 mask continued */ #define AR_PHY_ERR_CNT_MASK_CONT AR_MAC_PCU_OFFSET(MAC_PCU_PHY_ERR_CNT_MASK_CONT) /* AZIMUTH mode reg can be used for proxySTA */ #define AR_AZIMUTH_MODE AR_MAC_PCU_OFFSET(MAC_PCU_AZIMUTH_MODE) #define AR_AZIMUTH_KEY_SEARCH_AD1 0x00000002 #define AR_AZIMUTH_CTS_MATCH_TX_AD2 0x00000040 #define AR_AZIMUTH_BA_USES_AD1 0x00000080 #define AR_AZIMUTH_FILTER_PASS_HOLD 0x00000200 /* Length of Pattern Match for Pattern */ #define AR_WOW_LENGTH1_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW_LENGTH1) #define AR_WOW_LENGTH2_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW_LENGTH2) #define AR_WOW_LENGTH3_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW_LENGTH3) #define AR_WOW_LENGTH4_REG AR_MAC_PCU_OFFSET(MAC_PCU_WOW_LENGTH4) #define AR_LOC_CTL_REG AR_MAC_PCU_OFFSET(MAC_PCU_LOCATION_MODE_CONTROL) #define AR_LOC_TIMER_REG AR_MAC_PCU_OFFSET(MAC_PCU_LOCATION_MODE_TIMER) #define AR_LOC_CTL_REG_FS 0x1 /* Register to enable pattern match for less than 256 bytes packets */ #define AR_WOW_PATTERN_MATCH_LT_256B_REG AR_MAC_PCU_OFFSET(WOW_PATTERN_MATCH_LESS_THAN_256_BYTES) #define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | AR_WOW_MAGIC_PAT_FOUND | \ AR_WOW_KEEP_ALIVE_FAIL | AR_WOW_BEACON_FAIL)) #define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \ AR_WOW_MAGIC_EN | AR_WOW_MAC_INTR_EN | AR_WOW_BEACON_FAIL | \ AR_WOW_KEEP_ALIVE_FAIL)) /* * Keep it long for Beacon workaround - ensures no AH_FALSE alarm */ #define AR_WOW_BMISSTHRESHOLD 0x20 /* WoW - Transmit buffer for keep alive frames */ #define AR_WOW_TRANSMIT_BUFFER AR_MAC_PCU_OFFSET(MAC_PCU_BUF) #define AR_WOW_TXBUF(_i) (AR_WOW_TRANSMIT_BUFFER + ((_i)<<2)) #define AR_WOW_KA_DESC_WORD2 AR_WOW_TXBUF(0) #define AR_WOW_KA_DESC_WORD3 AR_WOW_TXBUF(1) #define AR_WOW_KA_DESC_WORD4 AR_WOW_TXBUF(2) #define AR_WOW_KA_DESC_WORD5 AR_WOW_TXBUF(3) #define AR_WOW_KA_DESC_WORD6 AR_WOW_TXBUF(4) #define AR_WOW_KA_DESC_WORD7 AR_WOW_TXBUF(5) #define AR_WOW_KA_DESC_WORD8 AR_WOW_TXBUF(6) #define AR_WOW_KA_DESC_WORD9 AR_WOW_TXBUF(7) #define AR_WOW_KA_DESC_WORD10 AR_WOW_TXBUF(8) #define AR_WOW_KA_DESC_WORD11 AR_WOW_TXBUF(9) #define AR_WOW_KA_DESC_WORD12 AR_WOW_TXBUF(10) #define AR_WOW_KA_DESC_WORD13 AR_WOW_TXBUF(11) /* KA_DATA_WORD = 6 words. Depending on the number of * descriptor words, it can start at AR_WOW_TXBUF(12) * or AR_WOW_TXBUF(13) */ #define AR_WOW_OFFLOAD_GTK_DATA_START AR_WOW_TXBUF(19) #define AR_WOW_KA_DATA_WORD_END_JUPITER AR_WOW_TXBUF(60) #define AR_WOW_SW_NULL_PARAMETER AR_WOW_TXBUF(61) #define AR_WOW_SW_NULL_LONG_PERIOD_MASK 0x0000FFFF #define AR_WOW_SW_NULL_LONG_PERIOD_MASK_S 0 #define AR_WOW_SW_NULL_SHORT_PERIOD_MASK 0xFFFF0000 #define AR_WOW_SW_NULL_SHORT_PERIOD_MASK_S 16 #define AR_WOW_OFFLOAD_COMMAND_JUPITER AR_WOW_TXBUF(62) #define AR_WOW_OFFLOAD_ENA_GTK 0x80000000 #define AR_WOW_OFFLOAD_ENA_ACER_MAGIC 0x40000000 #define AR_WOW_OFFLOAD_ENA_STD_MAGIC 0x20000000 #define AR_WOW_OFFLOAD_ENA_SWKA 0x10000000 #define AR_WOW_OFFLOAD_ENA_ARP_OFFLOAD 0x08000000 #define AR_WOW_OFFLOAD_ENA_NS_OFFLOAD 0x04000000 #define AR_WOW_OFFLOAD_ENA_4WAY_WAKE 0x02000000 #define AR_WOW_OFFLOAD_ENA_GTK_ERROR_WAKE 0x01000000 #define AR_WOW_OFFLOAD_ENA_AP_LOSS_WAKE 0x00800000 #define AR_WOW_OFFLOAD_ENA_BT_SLEEP 0x00080000 #define AR_WOW_OFFLOAD_ENA_SW_NULL 0x00040000 #define AR_WOW_OFFLOAD_ENA_HWKA_FAIL 0x00020000 #define AR_WOW_OFFLOAD_ENA_DEVID_SWAR 0x00010000 #define AR_WOW_OFFLOAD_STATUS_JUPITER AR_WOW_TXBUF(63) /* WoW Transmit Buffer for patterns */ #define AR_WOW_TB_PATTERN0 AR_WOW_TXBUF(64) #define AR_WOW_TB_PATTERN1 AR_WOW_TXBUF(128) #define AR_WOW_TB_PATTERN2 AR_WOW_TXBUF(192) #define AR_WOW_TB_PATTERN3 AR_WOW_TXBUF(256) #define AR_WOW_TB_PATTERN4 AR_WOW_TXBUF(320) #define AR_WOW_TB_PATTERN5 AR_WOW_TXBUF(384) #define AR_WOW_TB_PATTERN6 AR_WOW_TXBUF(448) #define AR_WOW_TB_PATTERN7 AR_WOW_TXBUF(512) #define AR_WOW_TB_MASK0 AR_WOW_TXBUF(768) #define AR_WOW_TB_MASK1 AR_WOW_TXBUF(776) #define AR_WOW_TB_MASK2 AR_WOW_TXBUF(784) #define AR_WOW_TB_MASK3 AR_WOW_TXBUF(792) #define AR_WOW_TB_MASK4 AR_WOW_TXBUF(800) #define AR_WOW_TB_MASK5 AR_WOW_TXBUF(808) #define AR_WOW_TB_MASK6 AR_WOW_TXBUF(816) #define AR_WOW_TB_MASK7 AR_WOW_TXBUF(824) #define AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START AR_WOW_TXBUF(825) #define AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_START_JUPITER AR_WOW_TXBUF(832) #define AR_WOW_OFFLOAD_GTK_TXDESC_PARAM_WORDS 4 #define AR_WOW_OFFLOAD_GTK_DATA_START_JUPITER AR_WOW_TXBUF(836) #define AR_WOW_OFFLOAD_GTK_DATA_WORDS_JUPITER 20 #define AR_WOW_OFFLOAD_ACER_MAGIC_START AR_WOW_TXBUF(856) #define AR_WOW_OFFLOAD_ACER_MAGIC_WORDS 2 #define AR_WOW_OFFLOAD_ACER_KA0_START AR_WOW_TXBUF(858) #define AR_WOW_OFFLOAD_ACER_KA0_PERIOD_MS AR_WOW_TXBUF(858) #define AR_WOW_OFFLOAD_ACER_KA0_SIZE AR_WOW_TXBUF(859) #define AR_WOW_OFFLOAD_ACER_KA0_DATA AR_WOW_TXBUF(860) #define AR_WOW_OFFLOAD_ACER_KA0_DATA_WORDS 20 #define AR_WOW_OFFLOAD_ACER_KA0_WORDS 22 #define AR_WOW_OFFLOAD_ACER_KA1_START AR_WOW_TXBUF(880) #define AR_WOW_OFFLOAD_ACER_KA1_PERIOD_MS AR_WOW_TXBUF(880) #define AR_WOW_OFFLOAD_ACER_KA1_SIZE AR_WOW_TXBUF(881) #define AR_WOW_OFFLOAD_ACER_KA1_DATA AR_WOW_TXBUF(882) #define AR_WOW_OFFLOAD_ACER_KA1_DATA_WORDS 20 #define AR_WOW_OFFLOAD_ACER_KA1_WORDS 22 #define AR_WOW_OFFLOAD_ARP0_START AR_WOW_TXBUF(902) #define AR_WOW_OFFLOAD_ARP0_VALID AR_WOW_TXBUF(902) #define AR_WOW_OFFLOAD_ARP0_RMT_IP AR_WOW_TXBUF(903) #define AR_WOW_OFFLOAD_ARP0_HOST_IP AR_WOW_TXBUF(904) #define AR_WOW_OFFLOAD_ARP0_MAC_L AR_WOW_TXBUF(905) #define AR_WOW_OFFLOAD_ARP0_MAC_H AR_WOW_TXBUF(906) #define AR_WOW_OFFLOAD_ARP0_WORDS 5 #define AR_WOW_OFFLOAD_ARP1_START AR_WOW_TXBUF(907) #define AR_WOW_OFFLOAD_ARP1_VALID AR_WOW_TXBUF(907) #define AR_WOW_OFFLOAD_ARP1_RMT_IP AR_WOW_TXBUF(908) #define AR_WOW_OFFLOAD_ARP1_HOST_IP AR_WOW_TXBUF(909) #define AR_WOW_OFFLOAD_ARP1_MAC_L AR_WOW_TXBUF(910) #define AR_WOW_OFFLOAD_ARP1_MAC_H AR_WOW_TXBUF(911) #define AR_WOW_OFFLOAD_ARP1_WORDS 5 #define AR_WOW_OFFLOAD_NS0_START AR_WOW_TXBUF(912) #define AR_WOW_OFFLOAD_NS0_VALID AR_WOW_TXBUF(912) #define AR_WOW_OFFLOAD_NS0_RMT_IPV6 AR_WOW_TXBUF(913) #define AR_WOW_OFFLOAD_NS0_SOLICIT_IPV6 AR_WOW_TXBUF(917) #define AR_WOW_OFFLOAD_NS0_MAC_L AR_WOW_TXBUF(921) #define AR_WOW_OFFLOAD_NS0_MAC_H AR_WOW_TXBUF(922) #define AR_WOW_OFFLOAD_NS0_TGT0_IPV6 AR_WOW_TXBUF(923) #define AR_WOW_OFFLOAD_NS0_TGT1_IPV6 AR_WOW_TXBUF(927) #define AR_WOW_OFFLOAD_NS0_WORDS 19 #define AR_WOW_OFFLOAD_NS1_START AR_WOW_TXBUF(931) #define AR_WOW_OFFLOAD_NS1_VALID AR_WOW_TXBUF(931) #define AR_WOW_OFFLOAD_NS1_RMT_IPV6 AR_WOW_TXBUF(932) #define AR_WOW_OFFLOAD_NS1_SOLICIT_IPV6 AR_WOW_TXBUF(936) #define AR_WOW_OFFLOAD_NS1_MAC_L AR_WOW_TXBUF(940) #define AR_WOW_OFFLOAD_NS1_MAC_H AR_WOW_TXBUF(941) #define AR_WOW_OFFLOAD_NS1_TGT0_IPV6 AR_WOW_TXBUF(942) #define AR_WOW_OFFLOAD_NS1_TGT1_IPV6 AR_WOW_TXBUF(946) #define AR_WOW_OFFLOAD_NS1_WORDS 19 #define AR_WOW_OFFLOAD_WLAN_REGSET_START AR_WOW_TXBUF(950) #define AR_WOW_OFFLOAD_WLAN_REGSET_NUM AR_WOW_TXBUF(950) #define AR_WOW_OFFLOAD_WLAN_REGSET_REGVAL AR_WOW_TXBUF(951) #define AR_WOW_OFFLOAD_WLAN_REGSET_MAX_PAIR 32 #define AR_WOW_OFFLOAD_WLAN_REGSET_WORDS 65 //(1 + AR_WOW_OFFLOAD_WLAN_REGSET_MAX_PAIR * 2) /* Currently Pattern 0-7 are supported - so bit 0-7 are set */ #define AR_WOW_PATTERN_SUPPORTED 0xFF #define AR_WOW_LENGTH_MAX 0xFF #define AR_WOW_LENGTH1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LENGTH1_SHIFT(_i)) #define AR_WOW_LENGTH2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3) #define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LENGTH2_SHIFT(_i)) /* * MAC Direct Connect registers * * Added to support dual BSSID/TSF which are needed in the application * of Mesh networking or Direct Connect. */ /* * Note that the only function added with this BSSID2 is to receive * multi/broadcast from BSSID2 as well */ /* MAC BSSID low 32 bits */ #define AR_BSS2_ID0 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID2_L32) /* MAC BSSID upper 16 bits / AID */ #define AR_BSS2_ID1 AR_MAC_PCU_OFFSET(MAC_PCU_BSSID2_U16) /* * Secondary TSF support added for dual BSSID/TSF */ /* MAC local clock lower 32 bits */ #define AR_TSF2_L32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF2_L32) /* MAC local clock upper 32 bits */ #define AR_TSF2_U32 AR_MAC_PCU_OFFSET(MAC_PCU_TSF2_U32) /* MAC Direct Connect Control */ #define AR_DIRECT_CONNECT AR_MAC_PCU_OFFSET(MAC_PCU_DIRECT_CONNECT) #define AR_DC_AP_STA_EN 0x00000001 #define AR_DC_AP_STA_EN_S 0 /* * tx_bf Register */ #define AR_SVD_OFFSET(_x) offsetof(struct svd_reg, _x) #define AR_TXBF_DBG AR_SVD_OFFSET(TXBF_DBG) #define AR_TXBF AR_SVD_OFFSET(TXBF) #define AR_TXBF_CB_TX 0x00000003 #define AR_TXBF_CB_TX_S 0 #define AR_TXBF_PSI_1_PHI_3 0 #define AR_TXBF_PSI_2_PHI_4 1 #define AR_TXBF_PSI_3_PHI_5 2 #define AR_TXBF_PSI_4_PHI_6 3 #define AR_TXBF_NB_TX 0x0000000C #define AR_TXBF_NB_TX_S 2 #define AR_TXBF_NUMBEROFBIT_4 0 #define AR_TXBF_NUMBEROFBIT_2 1 #define AR_TXBF_NUMBEROFBIT_6 2 #define AR_TXBF_NUMBEROFBIT_8 3 #define AR_TXBF_NG_RPT_TX 0x00000030 #define AR_TXBF_NG_RPT_TX_S 4 #define AR_TXBF_No_GROUP 0 #define AR_TXBF_TWO_GROUP 1 #define AR_TXBF_FOUR_GROUP 2 #define AR_TXBF_NG_CVCACHE 0x000000C0 #define AR_TXBF_NG_CVCACHE_S 6 #define AR_TXBF_FOUR_CLIENTS 0 #define AR_TXBF_EIGHT_CLIENTS 1 #define AR_TXBF_SIXTEEN_CLIENTS 2 #define AR_TXBF_TXCV_BFWEIGHT_METHOD 0x00000600 #define AR_TXBF_TXCV_BFWEIGHT_METHOD_S 9 #define AR_TXBF_NO_WEIGHTING 0 #define AR_TXBF_MAX_POWER 1 #define AR_TXBF_KEEP_RATIO 2 #define AR_TXBF_RLR_EN 0x00000800 #define AR_TXBF_RC_20_U_DONE 0x00001000 #define AR_TXBF_RC_20_L_DONE 0x00002000 #define AR_TXBF_RC_40_DONE 0x00004000 #define AR_TXBF_FORCE_UPDATE_V2BB 0x00008000 #define AR_TXBF_TIMER AR_SVD_OFFSET(TXBF_TIMER) #define AR_TXBF_TIMER_TIMEOUT 0x000000FF #define AR_TXBF_TIMER_TIMEOUT_S 0 #define AR_TXBF_TIMER_ATIMEOU 0x0000FF00 #define AR_TXBF_TIMER_ATIMEOUT_S 8 /* for SVD cache update */ #define AR_TXBF_SW AR_SVD_OFFSET(TXBF_SW) #define AR_LRU_ACK 0x00000001 #define AR_LRU_ADDR 0x000003FE #define AR_LRU_ADDR_S 1 #define AR_LRU_EN 0x00000800 #define AR_LRU_EN_S 11 #define AR_DEST_IDX 0x0007f000 #define AR_DEST_IDX_S 12 #define AR_LRU_WR_ACK 0x00080000 #define AR_LRU_WR_ACK_S 19 #define AR_LRU_RD_ACK 0x00100000 #define AR_LRU_RD_ACK_S 20 #define AR_RC0_0 AR_SVD_OFFSET(RC0) #define AR_RC0(_idx) (AR_RC0_0+(_idx)) #define AR_RC1_0 AR_SVD_OFFSET(RC1) #define AR_RC1(_idx) (AR_RC1_0+(_idx)) #define AR_CVCACHE_0 AR_SVD_OFFSET(CVCACHE) #define AR_CVCACHE(_idx) (AR_CVCACHE_0+(_idx)) /* for CV CACHE Header */ #define AR_CVCACHE_Ng_IDX 0x0000C000 #define AR_CVCACHE_Ng_IDX_S 14 #define AR_CVCACHE_BW40 0x00010000 #define AR_CVCACHE_BW40_S 16 #define AR_CVCACHE_IMPLICIT 0x00020000 #define AR_CVCACHE_IMPLICIT_S 17 #define AR_CVCACHE_DEST_IDX 0x01FC0000 #define AR_CVCACHE_DEST_IDX_S 18 #define AR_CVCACHE_Nc_IDX 0x06000000 #define AR_CVCACHE_Nc_IDX_S 25 #define AR_CVCACHE_Nr_IDX 0x18000000 #define AR_CVCACHE_Nr_IDX_S 27 #define AR_CVCACHE_EXPIRED 0x20000000 #define AR_CVCACHE_EXPIRED_S 29 #define AR_CVCACHE_WRITE 0x80000000 /* for CV cache data*/ #define AR_CVCACHE_RD_EN 0x40000000 #define AR_CVCACHE_DATA 0x3fffffff /* * ANT DIV setting */ #define ANT_DIV_CONTROL_ALL (0x7e000000) #define ANT_DIV_CONTROL_ALL_S (25) #define ANT_DIV_ENABLE (0x1000000) #define ANT_DIV_ENABLE_S (24) #define FAST_DIV_ENABLE (0x2000) #define FAST_DIV_ENABLE_S (13) /* Global register */ #define AR_GLB_REG_OFFSET(_x) offsetof(struct wlan_bt_glb_reg_pcie, _x) #define AR_MBOX_CTRL_STATUS AR_GLB_REG_OFFSET(GLB_MBOX_CONTROL_STATUS) #define AR_MBOX_INT_EMB_CPU 0x0001 #define AR_MBOX_INT_WLAN 0x0002 #define AR_MBOX_RESET 0x0004 #define AR_MBOX_RAM_REQ_MASK 0x0018 #define AR_MBOX_RAM_REQ_NO_RAM 0x0000 #define AR_MBOX_RAM_REQ_USB 0x0008 #define AR_MBOX_RAM_REQ_WLAN_BUF 0x0010 #define AR_MBOX_RAM_REQ_PATCH_REAPPY 0x0018 #define AR_MBOX_RAM_CONF 0x0020 #define AR_MBOX_WLAN_BUF 0x0040 #define AR_MBOX_WOW_REQ 0x0080 #define AR_MBOX_WOW_CONF 0x0100 #define AR_MBOX_WOW_ERROR_MASK 0x1e00 #define AR_MBOX_WOW_ERROR_NONE 0x0000 #define AR_MBOX_WOW_ERROR_INVALID_MSG 0x0200 #define AR_MBOX_WOW_ERROR_MALFORMED_MSG 0x0400 #define AR_MBOX_WOW_ERROR_INVALID_RAM_IMAGE 0x0600 #define AR_WLAN_WOW_STATUS AR_GLB_REG_OFFSET(GLB_WLAN_WOW_STATUS) #define AR_WLAN_WOW_ENABLE AR_GLB_REG_OFFSET(GLB_WLAN_WOW_ENABLE) #define AR_EMB_CPU_WOW_STATUS AR_GLB_REG_OFFSET(GLB_EMB_CPU_WOW_STATUS) #define AR_EMB_CPU_WOW_STATUS_KEEP_ALIVE_FAIL 0x1 #define AR_EMB_CPU_WOW_STATUS_BEACON_MISS 0x2 #define AR_EMB_CPU_WOW_STATUS_PATTERN_MATCH 0x4 #define AR_EMB_CPU_WOW_STATUS_MAGIC_PATTERN 0x8 #define AR_EMB_CPU_WOW_ENABLE AR_GLB_REG_OFFSET(GLB_EMB_CPU_WOW_ENABLE) #define AR_EMB_CPU_WOW_ENABLE_KEEP_ALIVE_FAIL 0x1 #define AR_EMB_CPU_WOW_ENABLE_BEACON_MISS 0x2 #define AR_EMB_CPU_WOW_ENABLE_PATTERN_MATCH 0x4 #define AR_EMB_CPU_WOW_ENABLE_MAGIC_PATTERN 0x8 #define AR_SW_WOW_CONTROL AR_GLB_REG_OFFSET(GLB_SW_WOW_CONTROL) #define AR_SW_WOW_ENABLE 0x1 #define AR_SWITCH_TO_REFCLK 0x2 #define AR_RESET_CONTROL 0x4 #define AR_RESET_VALUE_MASK 0x8 #define AR_HW_WOW_DISABLE 0x10 #define AR_CLR_MAC_INTERRUPT 0x20 #define AR_CLR_KA_INTERRUPT 0x40 /* * WLAN coex registers */ #define AR_WLAN_COEX_OFFSET(_x) offsetof(struct wlan_coex_reg, _x) #define AR_MCI_COMMAND0 AR_WLAN_COEX_OFFSET(MCI_COMMAND0) #define AR_MCI_COMMAND0_HEADER 0xFF #define AR_MCI_COMMAND0_HEADER_S 0 #define AR_MCI_COMMAND0_LEN 0x1f00 #define AR_MCI_COMMAND0_LEN_S 8 #define AR_MCI_COMMAND0_DISABLE_TIMESTAMP 0x2000 #define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S 13 #define AR_MCI_COMMAND1 AR_WLAN_COEX_OFFSET(MCI_COMMAND1) #define AR_MCI_COMMAND2 AR_WLAN_COEX_OFFSET(MCI_COMMAND2) #define AR_MCI_COMMAND2_RESET_TX 0x01 #define AR_MCI_COMMAND2_RESET_TX_S 0 #define AR_MCI_COMMAND2_RESET_RX 0x02 #define AR_MCI_COMMAND2_RESET_RX_S 1 #define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES 0x3FC #define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S 2 #define AR_MCI_COMMAND2_RESET_REQ_WAKEUP 0x400 #define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S 10 #define AR_MCI_RX_CTRL AR_WLAN_COEX_OFFSET(MCI_RX_CTRL) #define AR_MCI_TX_CTRL AR_WLAN_COEX_OFFSET(MCI_TX_CTRL) /* 0 = no division, 1 = divide by 2, 2 = divide by 4, 3 = divide by 8 */ #define AR_MCI_TX_CTRL_CLK_DIV 0x03 #define AR_MCI_TX_CTRL_CLK_DIV_S 0 #define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE 0x04 #define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S 2 #define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ 0xFFFFF8 #define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S 3 #define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM 0xF000000 #define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S 24 #define AR_MCI_MSG_ATTRIBUTES_TABLE AR_WLAN_COEX_OFFSET(MCI_MSG_ATTRIBUTES_TABLE) #define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM 0xFFFF #define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S 0 #define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR 0xFFFF0000 #define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S 16 #define AR_MCI_SCHD_TABLE_0 AR_WLAN_COEX_OFFSET(MCI_SCHD_TABLE_0) #define AR_MCI_SCHD_TABLE_1 AR_WLAN_COEX_OFFSET(MCI_SCHD_TABLE_1) #define AR_MCI_GPM_0 AR_WLAN_COEX_OFFSET(MCI_GPM_0) #define AR_MCI_GPM_1 AR_WLAN_COEX_OFFSET(MCI_GPM_1) #define AR_MCI_GPM_WRITE_PTR 0xFFFF0000 #define AR_MCI_GPM_WRITE_PTR_S 16 #define AR_MCI_GPM_BUF_LEN 0x0000FFFF #define AR_MCI_GPM_BUF_LEN_S 0 #define AR_MCI_INTERRUPT_RAW AR_WLAN_COEX_OFFSET(MCI_INTERRUPT_RAW) #define AR_MCI_INTERRUPT_EN AR_WLAN_COEX_OFFSET(MCI_INTERRUPT_EN) #define AR_MCI_INTERRUPT_SW_MSG_DONE 0x00000001 #define AR_MCI_INTERRUPT_SW_MSG_DONE_S 0 #define AR_MCI_INTERRUPT_CPU_INT_MSG 0x00000002 #define AR_MCI_INTERRUPT_CPU_INT_MSG_S 1 #define AR_MCI_INTERRUPT_RX_CKSUM_FAIL 0x00000004 #define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S 2 #define AR_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008 #define AR_MCI_INTERRUPT_RX_INVALID_HDR_S 3 #define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010 #define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S 4 #define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020 #define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S 5 #define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080 #define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S 7 #define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100 #define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S 8 #define AR_MCI_INTERRUPT_RX_MSG 0x00000200 #define AR_MCI_INTERRUPT_RX_MSG_S 9 #define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400 #define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S 10 #define AR_MCI_INTERRUPT_BT_PRI 0x07fff800 #define AR_MCI_INTERRUPT_BT_PRI_S 11 #define AR_MCI_INTERRUPT_BT_PRI_THRESH 0x08000000 #define AR_MCI_INTERRUPT_BT_PRI_THRESH_S 27 #define AR_MCI_INTERRUPT_BT_FREQ 0x10000000 #define AR_MCI_INTERRUPT_BT_FREQ_S 28 #define AR_MCI_INTERRUPT_BT_STOMP 0x20000000 #define AR_MCI_INTERRUPT_BT_STOMP_S 29 #define AR_MCI_INTERRUPT_BB_AIC_IRQ 0x40000000 #define AR_MCI_INTERRUPT_BB_AIC_IRQ_S 30 #define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000 #define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S 31 #define AR_MCI_INTERRUPT_MSG_FAIL_MASK ( AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ AR_MCI_INTERRUPT_TX_SW_MSG_FAIL ) #define AR_MCI_INTERRUPT_DEFAULT ( AR_MCI_INTERRUPT_SW_MSG_DONE | \ AR_MCI_INTERRUPT_RX_INVALID_HDR | \ AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ AR_MCI_INTERRUPT_TX_SW_MSG_FAIL | \ AR_MCI_INTERRUPT_RX_MSG | \ AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \ AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT ) #define AR_MCI_REMOTE_CPU_INT AR_WLAN_COEX_OFFSET(MCI_REMOTE_CPU_INT) #define AR_MCI_REMOTE_CPU_INT_EN AR_WLAN_COEX_OFFSET(MCI_REMOTE_CPU_INT_EN) #define AR_MCI_INTERRUPT_RX_MSG_RAW AR_WLAN_COEX_OFFSET(MCI_INTERRUPT_RX_MSG_RAW) #define AR_MCI_INTERRUPT_RX_MSG_EN AR_WLAN_COEX_OFFSET(MCI_INTERRUPT_RX_MSG_EN) #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0 #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1 #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2 #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3 #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4 #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5 #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6 #define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 #define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8 #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9 #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10 #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11 #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12 #ifdef AH_DEBUG #define AR_MCI_INTERRUPT_RX_MSG_DEFAULT ( AR_MCI_INTERRUPT_RX_MSG_GPM | \ AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | \ AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | \ AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE ) #else #define AR_MCI_INTERRUPT_RX_MSG_DEFAULT ( AR_MCI_INTERRUPT_RX_MSG_GPM | \ AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | \ AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | \ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE ) #endif #define AR_MCI_INTERRUPT_RX_HW_MSG_MASK ( AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_RST ) #define AR_MCI_CPU_INT AR_WLAN_COEX_OFFSET(MCI_CPU_INT) #define AR_MCI_RX_STATUS AR_WLAN_COEX_OFFSET(MCI_RX_STATUS) #define AR_MCI_RX_LAST_SCHD_MSG_INDEX 0x00000F00 #define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S 8 #define AR_MCI_RX_REMOTE_SLEEP 0x00001000 #define AR_MCI_RX_REMOTE_SLEEP_S 12 #define AR_MCI_RX_MCI_CLK_REQ 0x00002000 #define AR_MCI_RX_MCI_CLK_REQ_S 13 #define AR_MCI_CONT_STATUS AR_WLAN_COEX_OFFSET(MCI_CONT_STATUS) #define AR_MCI_CONT_RSSI_POWER 0x000000FF #define AR_MCI_CONT_RSSI_POWER_S 0 #define AR_MCI_CONT_RRIORITY 0x0000FF00 #define AR_MCI_CONT_RRIORITY_S 8 #define AR_MCI_CONT_TXRX 0x00010000 #define AR_MCI_CONT_TXRX_S 16 #define AR_MCI_BT_PRI0 AR_WLAN_COEX_OFFSET(MCI_BT_PRI0) #define AR_MCI_BT_PRI1 AR_WLAN_COEX_OFFSET(MCI_BT_PRI1) #define AR_MCI_BT_PRI2 AR_WLAN_COEX_OFFSET(MCI_BT_PRI2) #define AR_MCI_BT_PRI3 AR_WLAN_COEX_OFFSET(MCI_BT_PRI3) #define AR_MCI_BT_PRI AR_WLAN_COEX_OFFSET(MCI_BT_PRI) #define AR_MCI_WL_FREQ0 AR_WLAN_COEX_OFFSET(MCI_WL_FREQ0) #define AR_MCI_WL_FREQ1 AR_WLAN_COEX_OFFSET(MCI_WL_FREQ1) #define AR_MCI_WL_FREQ2 AR_WLAN_COEX_OFFSET(MCI_WL_FREQ2) #define AR_MCI_GAIN AR_WLAN_COEX_OFFSET(MCI_GAIN) #define AR_MCI_WBTIMER1 AR_WLAN_COEX_OFFSET(MCI_WBTIMER1) #define AR_MCI_WBTIMER2 AR_WLAN_COEX_OFFSET(MCI_WBTIMER2) #define AR_MCI_WBTIMER3 AR_WLAN_COEX_OFFSET(MCI_WBTIMER3) #define AR_MCI_WBTIMER4 AR_WLAN_COEX_OFFSET(MCI_WBTIMER4) #define AR_MCI_MAXGAIN AR_WLAN_COEX_OFFSET(MCI_MAXGAIN) #define AR_MCI_HW_SCHD_TBL_CTL AR_WLAN_COEX_OFFSET(MCI_HW_SCHD_TBL_CTL) #define AR_MCI_HW_SCHD_TBL_D0 AR_WLAN_COEX_OFFSET(MCI_HW_SCHD_TBL_D0) #define AR_MCI_HW_SCHD_TBL_D1 AR_WLAN_COEX_OFFSET(MCI_HW_SCHD_TBL_D1) #define AR_MCI_HW_SCHD_TBL_D2 AR_WLAN_COEX_OFFSET(MCI_HW_SCHD_TBL_D2) #define AR_MCI_HW_SCHD_TBL_D3 AR_WLAN_COEX_OFFSET(MCI_HW_SCHD_TBL_D3) #define AR_MCI_TX_PAYLOAD0 AR_WLAN_COEX_OFFSET(MCI_TX_PAYLOAD0) #define AR_MCI_TX_PAYLOAD1 AR_WLAN_COEX_OFFSET(MCI_TX_PAYLOAD1) #define AR_MCI_TX_PAYLOAD2 AR_WLAN_COEX_OFFSET(MCI_TX_PAYLOAD2) #define AR_MCI_TX_PAYLOAD3 AR_WLAN_COEX_OFFSET(MCI_TX_PAYLOAD3) #define AR_BTCOEX_WBTIMER AR_WLAN_COEX_OFFSET(BTCOEX_WBTIMER) #define AR_BTCOEX_CTRL AR_WLAN_COEX_OFFSET(BTCOEX_CTRL) #define AR_BTCOEX_CTRL_JUPITER_MODE 0x00000001 #define AR_BTCOEX_CTRL_JUPITER_MODE_S 0 #define AR_BTCOEX_CTRL_WBTIMER_EN 0x00000002 #define AR_BTCOEX_CTRL_WBTIMER_EN_S 1 #define AR_BTCOEX_CTRL_MCI_MODE_EN 0x00000004 #define AR_BTCOEX_CTRL_MCI_MODE_EN_S 2 #define AR_BTCOEX_CTRL_LNA_SHARED 0x00000008 #define AR_BTCOEX_CTRL_LNA_SHARED_S 3 #define AR_BTCOEX_CTRL_PA_SHARED 0x00000010 #define AR_BTCOEX_CTRL_PA_SHARED_S 4 #define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN 0x00000020 #define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S 5 #define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN 0x00000040 #define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S 6 #define AR_BTCOEX_CTRL_NUM_ANTENNAS 0x00000180 #define AR_BTCOEX_CTRL_NUM_ANTENNAS_S 7 #define AR_BTCOEX_CTRL_RX_CHAIN_MASK 0x00000E00 #define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S 9 #define AR_BTCOEX_CTRL_AGGR_THRESH 0x00007000 #define AR_BTCOEX_CTRL_AGGR_THRESH_S 12 #define AR_BTCOEX_CTRL_1_CHAIN_BCN 0x00080000 #define AR_BTCOEX_CTRL_1_CHAIN_BCN_S 19 #define AR_BTCOEX_CTRL_1_CHAIN_ACK 0x00100000 #define AR_BTCOEX_CTRL_1_CHAIN_ACK_S 20 #define AR_BTCOEX_CTRL_WAIT_BA_MARGIN 0x1FE00000 #define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S 28 #define AR_BTCOEX_CTRL_REDUCE_TXPWR 0x20000000 #define AR_BTCOEX_CTRL_REDUCE_TXPWR_S 29 #define AR_BTCOEX_CTRL_SPDT_ENABLE_10 0x40000000 #define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S 30 #define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 #define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 #define AR_BTCOEX_WL_WEIGHTS0 AR_WLAN_COEX_OFFSET(BTCOEX_WL_WEIGHTS0) #define AR_BTCOEX_WL_WEIGHTS1 AR_WLAN_COEX_OFFSET(BTCOEX_WL_WEIGHTS1) #define AR_BTCOEX_WL_WEIGHTS2 AR_WLAN_COEX_OFFSET(BTCOEX_WL_WEIGHTS2) #define AR_BTCOEX_WL_WEIGHTS3 AR_WLAN_COEX_OFFSET(BTCOEX_WL_WEIGHTS3) #define AR_BTCOEX_MAX_TXPWR(_x) (AR_WLAN_COEX_OFFSET(BTCOEX_MAX_TXPWR) + ((_x) << 2)) #define AR_BTCOEX_WL_LNA AR_WLAN_COEX_OFFSET(BTCOEX_WL_LNA) #define AR_BTCOEX_RFGAIN_CTRL AR_WLAN_COEX_OFFSET(BTCOEX_RFGAIN_CTRL) #define AR_BTCOEX_CTRL2 AR_WLAN_COEX_OFFSET(BTCOEX_CTRL2) #define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 #define AR_BTCOEX_CTRL2_TXPWR_THRESH_S 11 #define AR_BTCOEX_CTRL2_TX_CHAIN_MASK 0x00380000 #define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S 19 #define AR_BTCOEX_CTRL2_RX_DEWEIGHT 0x00400000 #define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S 22 #define AR_BTCOEX_CTRL2_GPIO_OBS_SEL 0x00800000 #define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S 23 #define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL 0x01000000 #define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S 24 #define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE 0x02000000 #define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S 25 #define AR_BTCOEX_RC AR_WLAN_COEX_OFFSET(BTCOEX_RC) #define AR_BTCOEX_MAX_RFGAIN(_x) AR_WLAN_COEX_OFFSET(BTCOEX_MAX_RFGAIN[_x]) #define AR_BTCOEX_DBG AR_WLAN_COEX_OFFSET(BTCOEX_DBG) #define AR_MCI_LAST_HW_MSG_HDR AR_WLAN_COEX_OFFSET(MCI_LAST_HW_MSG_HDR) #define AR_MCI_LAST_HW_MSG_BDY AR_WLAN_COEX_OFFSET(MCI_LAST_HW_MSG_BDY) #define AR_MCI_SCHD_TABLE_2 AR_WLAN_COEX_OFFSET(MCI_SCHD_TABLE_2) #define AR_MCI_SCHD_TABLE_2_MEM_BASED 0x00000001 #define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0 #define AR_MCI_SCHD_TABLE_2_HW_BASED 0x00000002 #define AR_MCI_SCHD_TABLE_2_HW_BASED_S 1 #define AR_BTCOEX_CTRL3 AR_WLAN_COEX_OFFSET(BTCOEX_CTRL3) #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000FFF #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 /****************************************************************************** * WLAN BT Global Register Map ******************************************************************************/ #define AR_WLAN_BT_GLB_OFFSET(_x) offsetof(struct wlan_bt_glb_reg_pcie, _x) /* * WLAN BT Global Registers */ #define AR_GLB_GPIO_CONTROL AR_WLAN_BT_GLB_OFFSET(GLB_GPIO_CONTROL) #define AR_GLB_WLAN_WOW_STATUS AR_WLAN_BT_GLB_OFFSET(GLB_WLAN_WOW_STATUS) #define AR_GLB_WLAN_WOW_ENABLE AR_WLAN_BT_GLB_OFFSET(GLB_WLAN_WOW_ENABLE) #define AR_GLB_EMB_CPU_WOW_STATUS AR_WLAN_BT_GLB_OFFSET(GLB_EMB_CPU_WOW_STATUS) #define AR_GLB_EMB_CPU_WOW_ENABLE AR_WLAN_BT_GLB_OFFSET(GLB_EMB_CPU_WOW_ENABLE) #define AR_GLB_MBOX_CONTROL_STATUS AR_WLAN_BT_GLB_OFFSET(GLB_MBOX_CONTROL_STATUS) #define AR_GLB_SW_WOW_CLK_CONTROL AR_WLAN_BT_GLB_OFFSET(GLB_SW_WOW_CLK_CONTROL) #define AR_GLB_APB_TIMEOUT AR_WLAN_BT_GLB_OFFSET(GLB_APB_TIMEOUT) #define AR_GLB_OTP_LDO_CONTROL AR_WLAN_BT_GLB_OFFSET(GLB_OTP_LDO_CONTROL) #define AR_GLB_OTP_LDO_POWER_GOOD AR_WLAN_BT_GLB_OFFSET(GLB_OTP_LDO_POWER_GOOD) #define AR_GLB_OTP_LDO_STATUS AR_WLAN_BT_GLB_OFFSET(GLB_OTP_LDO_STATUS) #define AR_GLB_SWREG_DISCONT_MODE AR_WLAN_BT_GLB_OFFSET(GLB_SWREG_DISCONT_MODE) #define AR_GLB_BT_GPIO_REMAP_OUT_CONTROL0 AR_WLAN_BT_GLB_OFFSET(GLB_BT_GPIO_REMAP_OUT_CONTROL0) #define AR_GLB_BT_GPIO_REMAP_OUT_CONTROL1 AR_WLAN_BT_GLB_OFFSET(GLB_BT_GPIO_REMAP_OUT_CONTROL1) #define AR_GLB_BT_GPIO_REMAP_IN_CONTROL0 AR_WLAN_BT_GLB_OFFSET(GLB_BT_GPIO_REMAP_IN_CONTROL0) #define AR_GLB_BT_GPIO_REMAP_IN_CONTROL1 AR_WLAN_BT_GLB_OFFSET(GLB_BT_GPIO_REMAP_IN_CONTROL1) #define AR_GLB_BT_GPIO_REMAP_IN_CONTROL2 AR_WLAN_BT_GLB_OFFSET(GLB_BT_GPIO_REMAP_IN_CONTROL2) #define AR_GLB_SCRATCH(_ah) \ (AR_SREV_APHRODITE(_ah)? \ AR_WLAN_BT_GLB_OFFSET(overlay_0x20044.Aphrodite_10.GLB_SCRATCH) : \ (AR_SREV_JUPITER_20(_ah) ? \ AR_WLAN_BT_GLB_OFFSET(overlay_0x20044.Jupiter_20.GLB_SCRATCH) : \ AR_WLAN_BT_GLB_OFFSET(overlay_0x20044.Jupiter_10.GLB_SCRATCH))) #define AR_GLB_CONTROL AR_WLAN_BT_GLB_OFFSET(overlay_0x20044.Jupiter_20.GLB_CONTROL) #define AR_BTCOEX_CTRL_SPDT_ENABLE 0x00000001 #define AR_BTCOEX_CTRL_SPDT_ENABLE_S 0 #define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL 0x00000002 #define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S 1 #define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT 0x00000004 #define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2 #define AR_GLB_WLAN_UART_INTF_EN 0x00020000 #define AR_GLB_WLAN_UART_INTF_EN_S 17 #define AR_GLB_DS_JTAG_DISABLE 0x00040000 #define AR_GLB_DS_JTAG_DISABLE_S 18 #define AR_GLB_STATUS AR_WLAN_BT_GLB_OFFSET(overlay_0x20044.Jupiter_20.GLB_STATUS) /* * MAC Version and Revision */ #define AR_SREV_VERSION_OSPREY 0x1C0 #define AR_SREV_VERSION_AR9580 0x1C0 #define AR_SREV_VERSION_JUPITER 0x280 #define AR_SREV_VERSION_HORNET 0x200 #define AR_SREV_VERSION_WASP 0x300 /* XXX: Check Wasp version number */ #define AR_SREV_VERSION_SCORPION 0x400 #define AR_SREV_VERSION_POSEIDON 0x240 +#define AR_SREV_VERSION_HONEYBEE 0x500 #define AR_SREV_VERSION_APHRODITE 0x2C0 #define AR_SREV_REVISION_OSPREY_10 0 /* Osprey 1.0 */ #define AR_SREV_REVISION_OSPREY_20 2 /* Osprey 2.0/2.1 */ #define AR_SREV_REVISION_OSPREY_22 3 /* Osprey 2.2 */ #define AR_SREV_REVISION_AR9580_10 4 /* AR9580/Peacock 1.0 */ #define AR_SREV_REVISION_HORNET_10 0 /* Hornet 1.0 */ #define AR_SREV_REVISION_HORNET_11 1 /* Hornet 1.1 */ #define AR_SREV_REVISION_HORNET_12 2 /* Hornet 1.2 */ #define AR_SREV_REVISION_HORNET_11_MASK 0xf /* Hornet 1.1 revision mask */ #define AR_SREV_REVISION_POSEIDON_10 0 /* Poseidon 1.0 */ #define AR_SREV_REVISION_POSEIDON_11 1 /* Poseidon 1.1 */ #define AR_SREV_REVISION_WASP_10 0 /* Wasp 1.0 */ #define AR_SREV_REVISION_WASP_11 1 /* Wasp 1.1 */ #define AR_SREV_REVISION_WASP_12 2 /* Wasp 1.2 */ #define AR_SREV_REVISION_WASP_13 3 /* Wasp 1.3 */ #define AR_SREV_REVISION_WASP_MASK 0xf /* Wasp revision mask */ #define AR_SREV_REVISION_WASP_MINOR_MINOR_MASK 0x10000 /* Wasp minor minor revision mask */ #define AR_SREV_REVISION_WASP_MINOR_MINOR_SHIFT 16 /* Wasp minor minor revision shift */ #define AR_SREV_REVISION_JUPITER_10 0 /* Jupiter 1.0 */ #define AR_SREV_REVISION_JUPITER_20 2 /* Jupiter 2.0 */ #define AR_SREV_REVISION_JUPITER_21 3 /* Jupiter 2.1 */ +#define AR_SREV_REVISION_HONEYBEE_10 0 /* Honeybee 1.0 */ +#define AR_SREV_REVISION_HONEYBEE_11 1 /* Honeybee 1.1 */ +#define AR_SREV_REVISION_HONEYBEE_MASK 0xf /* Honeybee revision mask */ + #define AR_SREV_REVISION_APHRODITE_10 0 /* Aphrodite 1.0 */ #if defined(AH_SUPPORT_OSPREY) #define AR_SREV_OSPREY(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_OSPREY)) #define AR_SREV_OSPREY_22(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_OSPREY) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_OSPREY_22)) #else #define AR_SREV_OSPREY(_ah) 0 #define AR_SREV_OSPREY_10(_ah) 0 #define AR_SREV_OSPREY_20(_ah) 0 #define AR_SREV_OSPREY_22(_ah) 0 #define AR_SREV_OSPREY_20_OR_LATER(_ah) 0 #define AR_SREV_OSPREY_22_OR_LATER(_ah) 0 #endif /* #if defined(AH_SUPPORT_OSPREY) */ #define AR_SREV_AR9580(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_AR9580) && \ (AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_AR9580_10)) #define AR_SREV_AR9580_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_AR9580) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_AR9580_10)) /* NOTE: When adding chips newer than Peacock, add chip check here. */ #define AR_SREV_AR9580_10_OR_LATER(_ah) \ - (AR_SREV_AR9580(_ah)) + (AR_SREV_AR9580(_ah) || AR_SREV_SCORPION(_ah) || AR_SREV_HONEYBEE(_ah)) #define AR_SREV_JUPITER(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER)) #define AR_SREV_JUPITER_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_JUPITER_10)) #define AR_SREV_JUPITER_20(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_JUPITER_20)) #define AR_SREV_JUPITER_21(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_JUPITER_21)) #define AR_SREV_JUPITER_20_OR_LATER(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER) && \ (AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_JUPITER_20)) #define AR_SREV_JUPITER_21_OR_LATER(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_JUPITER) && \ (AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_JUPITER_21)) #define AR_SREV_APHRODITE(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_APHRODITE)) #define AR_SREV_APHRODITE_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_APHRODITE) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_APHRODITE_10)) #if defined(AH_SUPPORT_HORNET) #define AR_SREV_HORNET_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HORNET) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_HORNET_10)) #define AR_SREV_HORNET_11(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HORNET) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_HORNET_11)) #define AR_SREV_HORNET_12(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HORNET) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_HORNET_12)) #define AR_SREV_HORNET(_ah) \ ( AR_SREV_HORNET_10(_ah) || AR_SREV_HORNET_11(_ah) || AR_SREV_HORNET_12(_ah) ) #else #define AR_SREV_HORNET_10(_ah) 0 #define AR_SREV_HORNET_11(_ah) 0 #define AR_SREV_HORNET_12(_ah) 0 #define AR_SREV_HORNET(_ah) 0 #endif /* #if defined(AH_SUPPORT_HORNET) */ #if defined(AH_SUPPORT_WASP) #define AR_SREV_WASP(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_WASP)) #else #define AR_SREV_WASP(_ah) 0 #endif /* #if defined(AH_SUPPORT_WASP) */ +#if defined(AH_SUPPORT_HONEYBEE) +#define AR_SREV_HONEYBEE(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HONEYBEE)) +#define AR_SREV_HONEYBEE_10(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HONEYBEE) && \ + (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_HONEYBEE_10)) +#define AR_SREV_HONEYBEE_11(_ah) \ + ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_HONEYBEE) && \ + (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_HONEYBEE_11)) +#else +#define AR_SREV_HONEYBEE(_ah) 0 +#define AR_SREV_HONEYBEE_10(_ah) 0 +#define AR_SREV_HONEYBEE_11(_ah) 0 +#endif /* #if defined(AH_SUPPORT_HONEYBEE) */ + #define AR_SREV_WASP_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_WASP) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_WASP_10)) #define AR_SREV_WASP_11(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_WASP) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_WASP_11)) #define AR_SREV_WASP_12(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_WASP) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_WASP_12)) #if defined(AH_SUPPORT_SCORPION) #define AR_SREV_SCORPION(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_SCORPION)) #else #define AR_SREV_SCORPION(_ah) 0 #endif /* #if defined(AH_SUPPORT_SCORPION) */ #if defined(AH_SUPPORT_POSEIDON) #define AR_SREV_POSEIDON(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_POSEIDON)) #define AR_SREV_POSEIDON_10(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_POSEIDON) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_POSEIDON_10)) #define AR_SREV_POSEIDON_11(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_POSEIDON) && \ (AH_PRIVATE((_ah))->ah_macRev == AR_SREV_REVISION_POSEIDON_11)) #else #define AR_SREV_POSEIDON(_ah) 0 #define AR_SREV_POSEIDON_10(_ah) 0 #define AR_SREV_POSEIDON_11(_ah) 0 #endif /* #if defined(AH_SUPPORT_POSEIDON) */ #define AR_SREV_POSEIDON_11_OR_LATER(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_SREV_VERSION_POSEIDON) && \ (AH_PRIVATE((_ah))->ah_macRev >= AR_SREV_REVISION_POSEIDON_11)) #define AR_SREV_POSEIDON_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_SREV_VERSION_POSEIDON) -#define AR_SREV_SOC(_ah) (AR_SREV_HORNET(_ah) || AR_SREV_POSEIDON(_ah) || AR_SREV_WASP(_ah)) +#define AR_SREV_SOC(_ah) (AR_SREV_HORNET(_ah) || AR_SREV_POSEIDON(_ah) || AR_SREV_WASP(_ah) || AR_SREV_HONEYBEE(_ah)) /* * Mask used to construct AAD for CCMP-AES * Cisco spec defined bits 0-3 as mask * IEEE802.11w defined as bit 4. */ #define AR_MFP_QOS_MASK_IEEE 0x10 #define AR_MFP_QOS_MASK_CISCO 0xf /* * frame control field mask: * 0 0 0 0 0 0 0 0 * | | | | | | | | _ Order bit * | | | | | | | _ _ Protected Frame bit * | | | | | | _ _ _ More data bit * | | | | | _ _ _ _ Power management bit * | | | | _ _ _ _ _ Retry bit * | | | _ _ _ _ _ _ More fragments bit * | | _ _ _ _ _ _ _ FromDS bit * | _ _ _ _ _ _ _ _ ToDS bit */ #define AR_AES_MUTE_MASK1_FC_MGMT_MFP 0xC7FF #endif