aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2013-04-28 00:45:58 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2013-04-28 00:45:58 +0000
commite1f316220bf375804e3bee6a4a7b1e3a68564141 (patch)
tree76ef5fb364e59adedfa008103c91f00d08984ec8
downloadsrc-vendor/qcamain_open_hal.tar.gz
src-vendor/qcamain_open_hal.zip
Source: https://github.com/qca/qcamain_open_hal_public Revision: 60390a9f9ac6a20db168fbbc01a4ad4e01c395ce Thankyou to QCA for this release.
Notes
Notes: svn path=/vendor/qcamain_open_hal/dist/; revision=250003 svn path=/vendor/qcamain_open_hal/60390a9f9ac6a20db168fbbc01a4ad4e01c395ce/; revision=250005; tag=vendor/qcamain_open_hal/60390a9f9ac6a20db168fbbc01a4ad4e01c395ce
-rw-r--r--LICENCE.TXT13
-rw-r--r--NOTICE.TXT72
-rw-r--r--README23
-rw-r--r--hal/ar9300/ar9300.h1641
-rw-r--r--hal/ar9300/ar9300_aic.c727
-rw-r--r--hal/ar9300/ar9300_ani.c1277
-rw-r--r--hal/ar9300/ar9300_aphrodite10.ini1536
-rw-r--r--hal/ar9300/ar9300_attach.c3965
-rw-r--r--hal/ar9300/ar9300_beacon.c198
-rw-r--r--hal/ar9300/ar9300_eeprom.c4522
-rw-r--r--hal/ar9300/ar9300_gpio.c652
-rw-r--r--hal/ar9300/ar9300_interrupts.c767
-rw-r--r--hal/ar9300/ar9300_jupiter10.ini1894
-rw-r--r--hal/ar9300/ar9300_jupiter20.ini2010
-rw-r--r--hal/ar9300/ar9300_keycache.c421
-rw-r--r--hal/ar9300/ar9300_mci.c1892
-rw-r--r--hal/ar9300/ar9300_misc.c3714
-rw-r--r--hal/ar9300/ar9300_osprey22.ini2188
-rw-r--r--hal/ar9300/ar9300_osprey22_scoemu.ini2147
-rw-r--r--hal/ar9300/ar9300_paprd.c2443
-rw-r--r--hal/ar9300/ar9300_phy.c1215
-rw-r--r--hal/ar9300/ar9300_power.c1559
-rw-r--r--hal/ar9300/ar9300_radar.c593
-rw-r--r--hal/ar9300/ar9300_radio.c238
-rw-r--r--hal/ar9300/ar9300_raw_adc_capture.c47
-rw-r--r--hal/ar9300/ar9300_recv.c341
-rw-r--r--hal/ar9300/ar9300_recv_ds.c201
-rw-r--r--hal/ar9300/ar9300_reset.c6072
-rw-r--r--hal/ar9300/ar9300_rtt.c32
-rw-r--r--hal/ar9300/ar9300_sim.c18
-rw-r--r--hal/ar9300/ar9300_sim.h21
-rw-r--r--hal/ar9300/ar9300_spectral.c588
-rw-r--r--hal/ar9300/ar9300_timer.c185
-rw-r--r--hal/ar9300/ar9300_tx99_tgt.c525
-rw-r--r--hal/ar9300/ar9300_txbf.c30
-rw-r--r--hal/ar9300/ar9300_txbf.h19
-rw-r--r--hal/ar9300/ar9300_txbf_cal.c25
-rw-r--r--hal/ar9300/ar9300_xmit.c910
-rw-r--r--hal/ar9300/ar9300_xmit_ds.c947
-rw-r--r--hal/ar9300/ar9300desc.h591
-rw-r--r--hal/ar9300/ar9300eep.h699
-rw-r--r--hal/ar9300/ar9300paprd.h54
-rw-r--r--hal/ar9300/ar9300phy.h1955
-rw-r--r--hal/ar9300/ar9300radar.h45
-rw-r--r--hal/ar9300/ar9300reg.h3119
-rw-r--r--hal/ar9300/ar9300template_ap121.h748
-rw-r--r--hal/ar9300/ar9300template_aphrodite.h749
-rw-r--r--hal/ar9300/ar9300template_cus157.h737
-rw-r--r--hal/ar9300/ar9300template_generic.h748
-rw-r--r--hal/ar9300/ar9300template_hb112.h751
-rw-r--r--hal/ar9300/ar9300template_hb116.h751
-rw-r--r--hal/ar9300/ar9300template_osprey_k31.h751
-rw-r--r--hal/ar9300/ar9300template_wasp_2.h747
-rw-r--r--hal/ar9300/ar9300template_wasp_k31.h748
-rw-r--r--hal/ar9300/ar9300template_xb112.h750
-rw-r--r--hal/ar9300/ar9300template_xb113.h750
-rw-r--r--hal/ar9300/ar9330_11.ini1356
-rwxr-xr-xhal/ar9300/ar9330_12.ini1289
-rw-r--r--hal/ar9300/ar9340.ini4330
-rw-r--r--hal/ar9300/ar9485.ini1419
-rw-r--r--hal/ar9300/ar9485_1_1.ini1292
-rw-r--r--hal/ar9300/ar955x.ini1684
-rw-r--r--hal/ar9300/ar9580.ini2219
-rw-r--r--hal/ar9300/eeprom.diff281
-rw-r--r--hal/ar9300/osprey_reg_map.h3193
-rw-r--r--hal/ar9300/osprey_reg_map_macro.h83644
-rw-r--r--hal/ar9300/poseidon_reg_map_macro.h4334
-rw-r--r--hal/ar9300/scorpion_reg_map.h1356
-rw-r--r--hal/ar9300/scorpion_reg_map_macro.h66519
-rw-r--r--hal/ar9300/sources81
-rw-r--r--hal/ar9300/wasp_reg_map.h71
71 files changed, 233429 insertions, 0 deletions
diff --git a/LICENCE.TXT b/LICENCE.TXT
new file mode 100644
index 000000000000..16d1c6c4b012
--- /dev/null
+++ b/LICENCE.TXT
@@ -0,0 +1,13 @@
+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.
diff --git a/NOTICE.TXT b/NOTICE.TXT
new file mode 100644
index 000000000000..b94d2f3129cc
--- /dev/null
+++ b/NOTICE.TXT
@@ -0,0 +1,72 @@
+This NOTICE.TXT file contains certain notices of software components included
+with the software that QUALCOMM ATHEROS Incorporated ('Qualcomm Atheros') is
+required to provide you. Notwithstanding anything in the notices in this file,
+your use of these software components together with the Qualcomm Atheros
+software (Qualcomm Atheros software hereinafter referred to as 'Software') is
+subject to the terms of your license from Qualcomm Atheros. Compliance with
+all copyright laws and software license agreements included in the notice
+section of this file are the responsibility of the user. Except as may be
+granted by separate express written agreement, this file provides no license
+to any Qualcomm Atheros patents, trademarks, copyrights, or other intellectual
+property.
+
+Copyright (c) 2013 QUALCOMM ATHEROS Incorporated. All rights reserved.
+
+QUALCOMM ATHEROS® is a registered trademark and registered service mark of
+QUALCOMM ATHEROS Incorporated. All other trademarks and service marks are
+the property of their respective owners.
+
+NOTICES:
+
+/*
+ * Copyright (c) 2005-2012 Atheros Communications 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.
+ */
+
+/*
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2005 Atheros Communications, Inc.
+ * Copyright (c) 2008-2010, Atheros Communications Inc.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. The materials contained herein are unmodified and are used
+ * unmodified.
+ * 2. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following NO
+ * ''WARRANTY'' disclaimer below (''Disclaimer''), without
+ * modification.
+ * 3. Redistributions in binary form must reproduce at minimum a
+ * disclaimer similar to the Disclaimer below and any redistribution
+ * must be conditioned upon including a substantially similar
+ * Disclaimer requirement for further binary redistribution.
+ * 4. Neither the names of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote
+ * product derived from this software without specific prior written
+ * permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
+ * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
diff --git a/README b/README
new file mode 100644
index 000000000000..d822dfd54c6e
--- /dev/null
+++ b/README
@@ -0,0 +1,23 @@
+This is a public version of the AR9300 HAL, suitable for open source
+development.
+
+
+What is this?
+-------------
+
+This is a public version of the QCA mainline (10.x) development HAL.
+It has a few notable changes:
+
+* The boolean types have been converted back to the HAL types
+ (HAL_BOOL, AH_TRUE / AH_FALSE) to aid integration into the existing
+ open source Atheros HAL drivers;
+
+* Some features have been removed from this HAL.
+
+However, this is essentially the same HAL which is used in QCA development
+and forms the basis for public releases from the 10.x mainline.
+
+Subsequent HAL releases will be committed on top of this release in order
+to provide developers with a simple change history they can use when
+doing branch merging.
+
diff --git a/hal/ar9300/ar9300.h b/hal/ar9300/ar9300.h
new file mode 100644
index 000000000000..c8add05fa4bc
--- /dev/null
+++ b/hal/ar9300/ar9300.h
@@ -0,0 +1,1641 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ATH_AR9300_H_
+#define _ATH_AR9300_H_
+
+#include "ah_internal.h"
+#include "ah_eeprom.h"
+#include "ah_devid.h"
+#include "ar9300eep.h" /* For Eeprom definitions */
+#include "asf_amem.h"
+
+
+#define AR9300_MAGIC 0x19741014
+
+
+/* MAC register values */
+
+#define INIT_CONFIG_STATUS 0x00000000
+#define INIT_RSSI_THR 0x7 /* Missed beacon counter initialized to 0x7 (max is 0xff) */
+#define INIT_RSSI_BEACON_WEIGHT 8 /* ave beacon rssi weight (0-16) */
+
+/*
+ * Various fifo fill before Tx start, in 64-byte units
+ * i.e. put the frame in the air while still DMAing
+ */
+#define MIN_TX_FIFO_THRESHOLD 0x1
+#define MAX_TX_FIFO_THRESHOLD (( 4096 / 64) - 1)
+#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
+
+ #define CHANSEL_DIV 15
+ #define FCLK 40
+
+#define COEFF ((FCLK * 5) / 2)
+#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
+#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)
+#define CHANSEL_5G_DOT5MHZ 2188
+
+/*
+ * Receive Queue Fifo depth.
+ */
+enum RX_FIFO_DEPTH {
+ HAL_HP_RXFIFO_DEPTH = 16,
+ HAL_LP_RXFIFO_DEPTH = 128,
+};
+
+/*
+ * Gain support.
+ */
+#define NUM_CORNER_FIX_BITS_2133 7
+#define CCK_OFDM_GAIN_DELTA 15
+
+enum GAIN_PARAMS {
+ GP_TXCLIP,
+ GP_PD90,
+ GP_PD84,
+ GP_GSEL
+};
+
+enum GAIN_PARAMS_2133 {
+ GP_MIXGAIN_OVR,
+ GP_PWD_138,
+ GP_PWD_137,
+ GP_PWD_136,
+ GP_PWD_132,
+ GP_PWD_131,
+ GP_PWD_130,
+};
+
+enum {
+ HAL_RESET_POWER_ON,
+ HAL_RESET_WARM,
+ HAL_RESET_COLD,
+};
+
+typedef struct _gain_opt_step {
+ int16_t paramVal[NUM_CORNER_FIX_BITS_2133];
+ int32_t stepGain;
+ int8_t stepName[16];
+} GAIN_OPTIMIZATION_STEP;
+
+typedef struct {
+ u_int32_t numStepsInLadder;
+ u_int32_t defaultStepNum;
+ GAIN_OPTIMIZATION_STEP optStep[10];
+} GAIN_OPTIMIZATION_LADDER;
+
+typedef struct {
+ u_int32_t currStepNum;
+ u_int32_t currGain;
+ u_int32_t targetGain;
+ u_int32_t loTrig;
+ u_int32_t hiTrig;
+ u_int32_t gainFCorrection;
+ u_int32_t active;
+ GAIN_OPTIMIZATION_STEP *curr_step;
+} GAIN_VALUES;
+
+typedef struct {
+ u_int16_t synth_center;
+ u_int16_t ctl_center;
+ u_int16_t ext_center;
+} CHAN_CENTERS;
+
+/* RF HAL structures */
+typedef struct rf_hal_funcs {
+ HAL_BOOL (*set_channel)(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+ HAL_BOOL (*get_chip_power_lim)(struct ath_hal *ah, HAL_CHANNEL *chans,
+ u_int32_t nchancs);
+} RF_HAL_FUNCS;
+
+struct ar9300_ani_default {
+ u_int16_t m1_thresh_low;
+ u_int16_t m2_thresh_low;
+ u_int16_t m1_thresh;
+ u_int16_t m2_thresh;
+ u_int16_t m2_count_thr;
+ u_int16_t m2_count_thr_low;
+ u_int16_t m1_thresh_low_ext;
+ u_int16_t m2_thresh_low_ext;
+ u_int16_t m1_thresh_ext;
+ u_int16_t m2_thresh_ext;
+ u_int16_t firstep;
+ u_int16_t firstep_low;
+ u_int16_t cycpwr_thr1;
+ u_int16_t cycpwr_thr1_ext;
+};
+
+/*
+ * Per-channel ANI state private to the driver.
+ */
+struct ar9300_ani_state {
+ HAL_CHANNEL c;
+ HAL_BOOL must_restore;
+ HAL_BOOL ofdms_turn;
+ u_int8_t ofdm_noise_immunity_level;
+ u_int8_t cck_noise_immunity_level;
+ u_int8_t spur_immunity_level;
+ u_int8_t firstep_level;
+ u_int8_t ofdm_weak_sig_detect_off;
+ u_int8_t mrc_cck_off;
+
+ /* Thresholds */
+ u_int32_t listen_time;
+ u_int32_t ofdm_trig_high;
+ u_int32_t ofdm_trig_low;
+ int32_t cck_trig_high;
+ int32_t cck_trig_low;
+ int32_t rssi_thr_low;
+ int32_t rssi_thr_high;
+
+ int32_t rssi; /* The current RSSI */
+ u_int32_t tx_frame_count; /* Last tx_frame_count */
+ u_int32_t rx_frame_count; /* Last rx Frame count */
+ u_int32_t cycle_count; /* Last cycle_count (can detect wrap-around) */
+ u_int32_t ofdm_phy_err_count;/* OFDM err count since last reset */
+ u_int32_t cck_phy_err_count; /* CCK err count since last reset */
+
+ struct ar9300_ani_default ini_def; /* INI default values for ANI registers */
+ HAL_BOOL phy_noise_spur; /* based on OFDM/CCK Phy errors */
+};
+
+#define AR9300_ANI_POLLINTERVAL 1000 /* 1000 milliseconds between ANI poll */
+
+#define AR9300_CHANNEL_SWITCH_TIME_USEC 1000 /* 1 millisecond needed to change channels */
+
+#define HAL_PROCESS_ANI 0x00000001 /* ANI state setup */
+#define HAL_RADAR_EN 0x80000000 /* Radar detect is capable */
+#define HAL_AR_EN 0x40000000 /* AR detect is capable */
+
+#define DO_ANI(ah) \
+ ((AH9300(ah)->ah_proc_phy_err & HAL_PROCESS_ANI))
+
+struct ar9300_stats {
+ u_int32_t ast_ani_niup; /* ANI increased noise immunity */
+ u_int32_t ast_ani_nidown; /* ANI decreased noise immunity */
+ u_int32_t ast_ani_spurup; /* ANI increased spur immunity */
+ u_int32_t ast_ani_spurdown;/* ANI descreased spur immunity */
+ u_int32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */
+ u_int32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */
+ u_int32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */
+ u_int32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */
+ u_int32_t ast_ani_stepup; /* ANI increased first step level */
+ u_int32_t ast_ani_stepdown;/* ANI decreased first step level */
+ u_int32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */
+ u_int32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */
+ u_int32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */
+ u_int32_t ast_ani_lzero; /* ANI listen time forced to zero */
+ u_int32_t ast_ani_lneg; /* ANI listen time calculated < 0 */
+ HAL_MIB_STATS ast_mibstats; /* MIB counter stats */
+ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */
+};
+
+struct ar9300_rad_reader {
+ u_int16_t rd_index;
+ u_int16_t rd_expSeq;
+ u_int32_t rd_resetVal;
+ u_int8_t rd_start;
+};
+
+struct ar9300_rad_writer {
+ u_int16_t wr_index;
+ u_int16_t wr_seq;
+};
+
+struct ar9300_radar_event {
+ u_int32_t re_ts; /* 32 bit time stamp */
+ u_int8_t re_rssi; /* rssi of radar event */
+ u_int8_t re_dur; /* duration of radar pulse */
+ u_int8_t re_chanIndex; /* Channel of event */
+};
+
+struct ar9300_radar_q_elem {
+ u_int32_t rq_seqNum;
+ u_int32_t rq_busy; /* 32 bit to insure atomic read/write */
+ struct ar9300_radar_event rq_event; /* Radar event */
+};
+
+struct ar9300_radar_q_info {
+ u_int16_t ri_qsize; /* q size */
+ u_int16_t ri_seqSize; /* Size of sequence ring */
+ struct ar9300_rad_reader ri_reader; /* State for the q reader */
+ struct ar9300_rad_writer ri_writer; /* state for the q writer */
+};
+
+#define HAL_MAX_ACK_RADAR_DUR 511
+#define HAL_MAX_NUM_PEAKS 3
+#define HAL_ARQ_SIZE 4096 /* 8K AR events for buffer size */
+#define HAL_ARQ_SEQSIZE 4097 /* Sequence counter wrap for AR */
+#define HAL_RADARQ_SIZE 1024 /* 1K radar events for buffer size */
+#define HAL_RADARQ_SEQSIZE 1025 /* Sequence counter wrap for radar */
+#define HAL_NUMRADAR_STATES 64 /* Number of radar channels we keep state for */
+
+struct ar9300_ar_state {
+ u_int16_t ar_prev_time_stamp;
+ u_int32_t ar_prev_width;
+ u_int32_t ar_phy_err_count[HAL_MAX_ACK_RADAR_DUR];
+ u_int32_t ar_ack_sum;
+ u_int16_t ar_peak_list[HAL_MAX_NUM_PEAKS];
+ u_int32_t ar_packet_threshold; /* Thresh to determine traffic load */
+ u_int32_t ar_par_threshold; /* Thresh to determine peak */
+ u_int32_t ar_radar_rssi; /* Rssi threshold for AR event */
+};
+
+struct ar9300_radar_state {
+ HAL_CHANNEL_INTERNAL *rs_chan; /* Channel info */
+ u_int8_t rs_chan_index; /* Channel index in radar structure */
+ u_int32_t rs_num_radar_events; /* Number of radar events */
+ int32_t rs_firpwr; /* Thresh to check radar sig is gone */
+ u_int32_t rs_radar_rssi; /* Thresh to start radar det (dB) */
+ u_int32_t rs_height; /* Thresh for pulse height (dB)*/
+ u_int32_t rs_pulse_rssi; /* Thresh to check if pulse is gone (dB) */
+ u_int32_t rs_inband; /* Thresh to check if pusle is inband (0.5 dB) */
+};
+typedef struct {
+ u_int8_t uc_receiver_errors;
+ u_int8_t uc_bad_tlp_errors;
+ u_int8_t uc_bad_dllp_errors;
+ u_int8_t uc_replay_timeout_errors;
+ u_int8_t uc_replay_number_rollover_errors;
+} ar_pcie_error_moniter_counters;
+
+#define AR9300_OPFLAGS_11A 0x01 /* if set, allow 11a */
+#define AR9300_OPFLAGS_11G 0x02 /* if set, allow 11g */
+#define AR9300_OPFLAGS_N_5G_HT40 0x04 /* if set, disable 5G HT40 */
+#define AR9300_OPFLAGS_N_2G_HT40 0x08 /* if set, disable 2G HT40 */
+#define AR9300_OPFLAGS_N_5G_HT20 0x10 /* if set, disable 5G HT20 */
+#define AR9300_OPFLAGS_N_2G_HT20 0x20 /* if set, disable 2G HT20 */
+
+/*
+ * For Kite and later chipsets, the following bits are not being programmed in EEPROM
+ * and so need to be enabled always.
+ * Bit 0: en_fcc_mid, Bit 1: en_jap_mid, Bit 2: en_fcc_dfs_ht40
+ * Bit 3: en_jap_ht40, Bit 4: en_jap_dfs_ht40
+ */
+#define AR9300_RDEXT_DEFAULT 0x1F
+
+#define AR9300_MAX_CHAINS 3
+#define AR9300_NUM_CHAINS(chainmask) \
+ (((chainmask >> 2) & 1) + ((chainmask >> 1) & 1) + (chainmask & 1))
+#define AR9300_CHAIN0_MASK 0x1
+#define AR9300_CHAIN1_MASK 0x2
+#define AR9300_CHAIN2_MASK 0x4
+
+/* Support for multiple INIs */
+struct ar9300_ini_array {
+ u_int32_t *ia_array;
+ u_int32_t ia_rows;
+ u_int32_t ia_columns;
+};
+#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
+ (iniarray)->ia_array = (u_int32_t *)(array); \
+ (iniarray)->ia_rows = (rows); \
+ (iniarray)->ia_columns = (columns); \
+} while (0)
+#define INI_RA(iniarray, row, column) (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)])
+
+#define INIT_CAL(_perCal) \
+ (_perCal)->cal_state = CAL_WAITING; \
+ (_perCal)->cal_next = AH_NULL;
+
+#define INSERT_CAL(_ahp, _perCal) \
+do { \
+ if ((_ahp)->ah_cal_list_last == AH_NULL) { \
+ (_ahp)->ah_cal_list = (_ahp)->ah_cal_list_last = (_perCal); \
+ ((_ahp)->ah_cal_list_last)->cal_next = (_perCal); \
+ } else { \
+ ((_ahp)->ah_cal_list_last)->cal_next = (_perCal); \
+ (_ahp)->ah_cal_list_last = (_perCal); \
+ (_perCal)->cal_next = (_ahp)->ah_cal_list; \
+ } \
+} while (0)
+
+typedef enum cal_types {
+ IQ_MISMATCH_CAL = 0x1,
+ TEMP_COMP_CAL = 0x2,
+} HAL_CAL_TYPES;
+
+typedef enum cal_state {
+ CAL_INACTIVE,
+ CAL_WAITING,
+ CAL_RUNNING,
+ CAL_DONE
+} HAL_CAL_STATE; /* Calibrate state */
+
+#define MIN_CAL_SAMPLES 1
+#define MAX_CAL_SAMPLES 64
+#define INIT_LOG_COUNT 5
+#define PER_MIN_LOG_COUNT 2
+#define PER_MAX_LOG_COUNT 10
+
+#define AR9300_NUM_BT_WEIGHTS 4
+#define AR9300_NUM_WLAN_WEIGHTS 4
+
+/* Per Calibration data structure */
+typedef struct per_cal_data {
+ HAL_CAL_TYPES cal_type; // Type of calibration
+ u_int32_t cal_num_samples; // Number of SW samples to collect
+ u_int32_t cal_count_max; // Number of HW samples to collect
+ void (*cal_collect)(struct ath_hal *, u_int8_t); // Accumulator func
+ void (*cal_post_proc)(struct ath_hal *, u_int8_t); // Post-processing func
+} HAL_PERCAL_DATA;
+
+/* List structure for calibration data */
+typedef struct cal_list {
+ const HAL_PERCAL_DATA *cal_data;
+ HAL_CAL_STATE cal_state;
+ struct cal_list *cal_next;
+} HAL_CAL_LIST;
+
+#define AR9300_NUM_CAL_TYPES 2
+#define AR9300_PAPRD_TABLE_SZ 24
+#define AR9300_PAPRD_GAIN_TABLE_SZ 32
+#define AR9382_MAX_GPIO_PIN_NUM (16)
+#define AR9382_GPIO_PIN_8_RESERVED (8)
+#define AR9382_GPIO_9_INPUT_ONLY (9)
+#define AR9382_MAX_GPIO_INPUT_PIN_NUM (13)
+#define AR9382_GPIO_PIN_11_RESERVED (11)
+#define AR9382_MAX_JTAG_GPIO_PIN_NUM (3)
+
+/* Paprd tx power adjust data structure */
+struct ar9300_paprd_pwr_adjust {
+ u_int32_t target_rate; // rate index
+ u_int32_t reg_addr; // register offset
+ u_int32_t reg_mask; // mask of register
+ u_int32_t reg_mask_offset; // mask offset of register
+ u_int32_t sub_db; // offset value unit of dB
+};
+
+#define AR9300_MAX_RATES 36 /* legacy(4) + ofdm(8) + HTSS(8) + HTDS(8) + HTTS(8)*/
+struct ath_hal_9300 {
+ struct ath_hal_private_tables ah_priv; /* base class */
+
+ /*
+ * Information retrieved from EEPROM.
+ */
+ ar9300_eeprom_t ah_eeprom;
+
+ GAIN_VALUES ah_gain_values;
+
+ u_int8_t ah_macaddr[IEEE80211_ADDR_LEN];
+ u_int8_t ah_bssid[IEEE80211_ADDR_LEN];
+ u_int8_t ah_bssid_mask[IEEE80211_ADDR_LEN];
+ u_int16_t ah_assoc_id;
+
+ /*
+ * Runtime state.
+ */
+ u_int32_t ah_mask_reg; /* copy of AR_IMR */
+ u_int32_t ah_mask2Reg; /* copy of AR_IMR_S2 */
+ u_int32_t ah_msi_reg; /* copy of AR_PCIE_MSI */
+ os_atomic_t ah_ier_ref_count; /* reference count for enabling interrupts */
+ struct ar9300_stats ah_stats; /* various statistics */
+ RF_HAL_FUNCS ah_rf_hal;
+ u_int32_t ah_tx_desc_mask; /* mask for TXDESC */
+ u_int32_t ah_tx_ok_interrupt_mask;
+ u_int32_t ah_tx_err_interrupt_mask;
+ u_int32_t ah_tx_desc_interrupt_mask;
+ u_int32_t ah_tx_eol_interrupt_mask;
+ u_int32_t ah_tx_urn_interrupt_mask;
+ HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES];
+ HAL_SMPS_MODE ah_sm_power_mode;
+ HAL_BOOL ah_chip_full_sleep;
+ u_int32_t ah_atim_window;
+ HAL_ANT_SETTING ah_diversity_control; /* antenna setting */
+ u_int16_t ah_antenna_switch_swap; /* Controls mapping of OID request */
+ u_int8_t ah_tx_chainmask_cfg; /* chain mask config */
+ u_int8_t ah_rx_chainmask_cfg;
+ u_int32_t ah_beacon_rssi_threshold; /* cache beacon rssi threshold */
+ /* Calibration related fields */
+ HAL_CAL_TYPES ah_supp_cals;
+ HAL_CAL_LIST ah_iq_cal_data; /* IQ Cal Data */
+ HAL_CAL_LIST ah_temp_comp_cal_data; /* Temperature Compensation Cal Data */
+ HAL_CAL_LIST *ah_cal_list; /* ptr to first cal in list */
+ HAL_CAL_LIST *ah_cal_list_last; /* ptr to last cal in list */
+ HAL_CAL_LIST *ah_cal_list_curr; /* ptr to current cal */
+// IQ Cal aliases
+#define ah_total_power_meas_i ah_meas0.unsign
+#define ah_total_power_meas_q ah_meas1.unsign
+#define ah_total_iq_corr_meas ah_meas2.sign
+ union {
+ u_int32_t unsign[AR9300_MAX_CHAINS];
+ int32_t sign[AR9300_MAX_CHAINS];
+ } ah_meas0;
+ union {
+ u_int32_t unsign[AR9300_MAX_CHAINS];
+ int32_t sign[AR9300_MAX_CHAINS];
+ } ah_meas1;
+ union {
+ u_int32_t unsign[AR9300_MAX_CHAINS];
+ int32_t sign[AR9300_MAX_CHAINS];
+ } ah_meas2;
+ union {
+ u_int32_t unsign[AR9300_MAX_CHAINS];
+ int32_t sign[AR9300_MAX_CHAINS];
+ } ah_meas3;
+ u_int16_t ah_cal_samples;
+ /* end - Calibration related fields */
+ u_int32_t ah_tx6_power_in_half_dbm; /* power output for 6Mb tx */
+ u_int32_t ah_sta_id1_defaults; /* STA_ID1 default settings */
+ u_int32_t ah_misc_mode; /* MISC_MODE settings */
+ HAL_BOOL ah_get_plcp_hdr; /* setting about MISC_SEL_EVM */
+ enum {
+ AUTO_32KHZ, /* use it if 32kHz crystal present */
+ USE_32KHZ, /* do it regardless */
+ DONT_USE_32KHZ, /* don't use it regardless */
+ } ah_enable32k_hz_clock; /* whether to sleep at 32kHz */
+
+ u_int32_t ah_ofdm_tx_power;
+ int16_t ah_tx_power_index_offset;
+
+ u_int ah_slot_time; /* user-specified slot time */
+ u_int ah_ack_timeout; /* user-specified ack timeout */
+ /*
+ * XXX
+ * 11g-specific stuff; belongs in the driver.
+ */
+ u_int8_t ah_g_beacon_rate; /* fixed rate for G beacons */
+ u_int32_t ah_gpio_mask; /* copy of enabled GPIO mask */
+ u_int32_t ah_gpio_cause; /* copy of GPIO cause (sync and async) */
+ /*
+ * RF Silent handling; setup according to the EEPROM.
+ */
+ u_int32_t ah_gpio_select; /* GPIO pin to use */
+ u_int32_t ah_polarity; /* polarity to disable RF */
+ u_int32_t ah_gpio_bit; /* after init, prev value */
+ HAL_BOOL ah_eep_enabled; /* EEPROM bit for capability */
+
+#ifdef ATH_BT_COEX
+ /*
+ * Bluetooth coexistence static setup according to the registry
+ */
+ HAL_BT_MODULE ah_bt_module; /* Bluetooth module identifier */
+ u_int8_t ah_bt_coex_config_type; /* BT coex configuration */
+ u_int8_t ah_bt_active_gpio_select; /* GPIO pin for BT_ACTIVE */
+ u_int8_t ah_bt_priority_gpio_select; /* GPIO pin for BT_PRIORITY */
+ u_int8_t ah_wlan_active_gpio_select; /* GPIO pin for WLAN_ACTIVE */
+ u_int8_t ah_bt_active_polarity; /* Polarity of BT_ACTIVE */
+ HAL_BOOL ah_bt_coex_single_ant; /* Single or dual antenna configuration */
+ u_int8_t ah_bt_wlan_isolation; /* Isolation between BT and WLAN in dB */
+ /*
+ * Bluetooth coexistence runtime settings
+ */
+ HAL_BOOL ah_bt_coex_enabled; /* If Bluetooth coexistence is enabled */
+ u_int32_t ah_bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
+ u_int32_t ah_bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; /* Register setting for AR_BT_COEX_WEIGHT */
+ u_int32_t ah_bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; /* Register setting for AR_BT_COEX_WEIGHT */
+ u_int32_t ah_bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
+ u_int32_t ah_bt_coex_flag; /* Special tuning flags for BT coex */
+#endif
+
+ /*
+ * Generic timer support
+ */
+ u_int32_t ah_avail_gen_timers; /* mask of available timers */
+ u_int32_t ah_intr_gen_timer_trigger; /* generic timer trigger interrupt state */
+ u_int32_t ah_intr_gen_timer_thresh; /* generic timer trigger interrupt state */
+ HAL_BOOL ah_enable_tsf2; /* enable TSF2 for gen timer 8-15. */
+
+ /*
+ * ANI & Radar support.
+ */
+ u_int32_t ah_proc_phy_err; /* Process Phy errs */
+ u_int32_t ah_ani_period; /* ani update list period */
+ struct ar9300_ani_state *ah_curani; /* cached last reference */
+ struct ar9300_ani_state ah_ani[255]; /* per-channel state */
+ struct ar9300_radar_state ah_radar[HAL_NUMRADAR_STATES]; /* Per-Channel Radar detector state */
+ struct ar9300_radar_q_elem *ah_radarq; /* radar event queue */
+ struct ar9300_radar_q_info ah_radarq_info; /* radar event q read/write state */
+ struct ar9300_ar_state ah_ar; /* AR detector state */
+ struct ar9300_radar_q_elem *ah_arq; /* AR event queue */
+ struct ar9300_radar_q_info ah_arq_info; /* AR event q read/write state */
+
+ /*
+ * Transmit power state. Note these are maintained
+ * here so they can be retrieved by diagnostic tools.
+ */
+ u_int16_t ah_rates_array[16];
+
+ /*
+ * Tx queue interrupt state.
+ */
+ u_int32_t ah_intr_txqs;
+
+ HAL_BOOL ah_intr_mitigation_rx; /* rx Interrupt Mitigation Settings */
+ HAL_BOOL ah_intr_mitigation_tx; /* tx Interrupt Mitigation Settings */
+
+ /*
+ * Extension Channel Rx Clear State
+ */
+ u_int32_t ah_cycle_count;
+ u_int32_t ah_ctl_busy;
+ u_int32_t ah_ext_busy;
+
+ /* HT CWM state */
+ HAL_HT_EXTPROTSPACING ah_ext_prot_spacing;
+ u_int8_t ah_tx_chainmask; /* tx chain mask */
+ u_int8_t ah_rx_chainmask; /* rx chain mask */
+
+ u_int8_t ah_tx_cal_chainmask; /* tx cal chain mask */
+ u_int8_t ah_rx_cal_chainmask; /* rx cal chain mask */
+
+ int ah_hwp;
+ void *ah_cal_mem;
+ HAL_BOOL ah_emu_eeprom;
+
+ HAL_ANI_CMD ah_ani_function;
+ HAL_BOOL ah_rifs_enabled;
+ u_int32_t ah_rifs_reg[11];
+ u_int32_t ah_rifs_sec_cnt;
+
+ /* open-loop power control */
+ u_int32_t original_gain[22];
+ int32_t init_pdadc;
+ int32_t pdadc_delta;
+
+ /* cycle counts for beacon stuck diagnostics */
+ u_int32_t ah_cycles;
+ u_int32_t ah_rx_clear;
+ u_int32_t ah_rx_frame;
+ u_int32_t ah_tx_frame;
+
+#define BB_HANG_SIG1 0
+#define BB_HANG_SIG2 1
+#define BB_HANG_SIG3 2
+#define BB_HANG_SIG4 3
+#define MAC_HANG_SIG1 4
+#define MAC_HANG_SIG2 5
+ /* bb hang detection */
+ int ah_hang[6];
+ hal_hw_hangs_t ah_hang_wars;
+ /*
+ * Support for ar9300 multiple INIs
+ */
+ struct ar9300_ini_array ah_ini_pcie_serdes;
+ struct ar9300_ini_array ah_ini_pcie_serdes_low_power;
+ struct ar9300_ini_array ah_ini_modes_additional;
+ struct ar9300_ini_array ah_ini_modes_additional_40mhz;
+ struct ar9300_ini_array ah_ini_modes_rxgain;
+ struct ar9300_ini_array ah_ini_modes_rxgain_bounds;
+ struct ar9300_ini_array ah_ini_modes_txgain;
+ struct ar9300_ini_array ah_ini_japan2484;
+ struct ar9300_ini_array ah_ini_radio_post_sys2ant;
+ struct ar9300_ini_array ah_ini_BTCOEX_MAX_TXPWR;
+ /*
+ * New INI format starting with Osprey 2.0 INI.
+ * Pre, core, post arrays for each sub-system (mac, bb, radio, soc)
+ */
+ #define ATH_INI_PRE 0
+ #define ATH_INI_CORE 1
+ #define ATH_INI_POST 2
+ #define ATH_INI_NUM_SPLIT (ATH_INI_POST + 1)
+ struct ar9300_ini_array ah_ini_mac[ATH_INI_NUM_SPLIT]; /* New INI format */
+ struct ar9300_ini_array ah_ini_bb[ATH_INI_NUM_SPLIT]; /* New INI format */
+ struct ar9300_ini_array ah_ini_radio[ATH_INI_NUM_SPLIT]; /* New INI format */
+ struct ar9300_ini_array ah_ini_soc[ATH_INI_NUM_SPLIT]; /* New INI format */
+
+ /*
+ * Added to support DFS postamble array in INI that we need to apply
+ * in DFS channels
+ */
+
+ struct ar9300_ini_array ah_ini_dfs;
+
+#if ATH_WOW
+ struct ar9300_ini_array ah_ini_pcie_serdes_wow; /* SerDes values during WOW sleep */
+#endif
+
+ /* To indicate EEPROM mapping used */
+ u_int32_t ah_immunity_vals[6];
+ HAL_BOOL ah_immunity_on;
+ /*
+ * snap shot of counter register for debug purposes
+ */
+#ifdef AH_DEBUG
+ u_int32_t last_tf;
+ u_int32_t last_rf;
+ u_int32_t last_rc;
+ u_int32_t last_cc;
+#endif
+ HAL_BOOL ah_dma_stuck; /* Set to AH_TRUE when RX/TX DMA failed to stop. */
+ u_int32_t nf_tsf32; /* timestamp for NF calibration duration */
+
+ u_int32_t reg_dmn; /* Regulatory Domain */
+ int16_t twice_antenna_gain; /* Antenna Gain */
+ u_int16_t twice_antenna_reduction; /* Antenna Gain Allowed */
+
+ /*
+ * Upper limit after factoring in the regulatory max, antenna gain and
+ * multichain factor. No TxBF, CDD or STBC gain factored
+ */
+ int16_t upper_limit[AR9300_MAX_CHAINS];
+
+ /* adjusted power for descriptor-based TPC for 1, 2, or 3 chains */
+ int16_t txpower[AR9300_MAX_RATES][AR9300_MAX_CHAINS];
+
+
+ /* adjusted power for descriptor-based TPC for 1, 2, or 3 chains with STBC*/
+ int16_t txpower_stbc[AR9300_MAX_RATES][AR9300_MAX_CHAINS];
+
+ /* Transmit Status ring support */
+ struct ar9300_txs *ts_ring;
+ u_int16_t ts_tail;
+ u_int16_t ts_size;
+ u_int32_t ts_paddr_start;
+ u_int32_t ts_paddr_end;
+
+ /* Receive Buffer size */
+#define HAL_RXBUFSIZE_DEFAULT 0xfff
+ u_int16_t rx_buf_size;
+
+ u_int32_t ah_wa_reg_val; // Store the permanent value of Reg 0x4004 so we dont have to R/M/W. (We should not be reading this register when in sleep states).
+
+ /* Indicate the PLL source clock rate is 25Mhz or not.
+ * clk_25mhz = 0 by default.
+ */
+ u_int8_t clk_25mhz;
+ /* For PAPRD uses */
+ u_int16_t small_signal_gain[AH_MAX_CHAINS];
+ u_int32_t pa_table[AH_MAX_CHAINS][AR9300_PAPRD_TABLE_SZ];
+ u_int32_t paprd_gain_table_entries[AR9300_PAPRD_GAIN_TABLE_SZ];
+ u_int32_t paprd_gain_table_index[AR9300_PAPRD_GAIN_TABLE_SZ];
+ u_int32_t ah_2g_paprd_rate_mask_ht20; /* Copy of eep->modal_header_2g.paprd_rate_mask_ht20 */
+ u_int32_t ah_2g_paprd_rate_mask_ht40; /* Copy of eep->modal_header_2g.paprd_rate_mask_ht40 */
+ u_int32_t ah_5g_paprd_rate_mask_ht20; /* Copy of eep->modal_header_5g.paprd_rate_mask_ht20 */
+ u_int32_t ah_5g_paprd_rate_mask_ht40; /* Copy of eep->modal_header_5g.paprd_rate_mask_ht40 */
+ u_int32_t paprd_training_power;
+ /* For GreenTx use to store the default tx power */
+ u_int8_t ah_default_tx_power[ar9300_rate_size];
+ HAL_BOOL ah_paprd_broken;
+
+ /* To store offsets of host interface registers */
+ struct {
+ u_int32_t AR_RC;
+ u_int32_t AR_WA;
+ u_int32_t AR_PM_STATE;
+ u_int32_t AR_H_INFOL;
+ u_int32_t AR_H_INFOH;
+ u_int32_t AR_PCIE_PM_CTRL;
+ u_int32_t AR_HOST_TIMEOUT;
+ u_int32_t AR_EEPROM;
+ u_int32_t AR_SREV;
+ u_int32_t AR_INTR_SYNC_CAUSE;
+ u_int32_t AR_INTR_SYNC_CAUSE_CLR;
+ u_int32_t AR_INTR_SYNC_ENABLE;
+ u_int32_t AR_INTR_ASYNC_MASK;
+ u_int32_t AR_INTR_SYNC_MASK;
+ u_int32_t AR_INTR_ASYNC_CAUSE_CLR;
+ u_int32_t AR_INTR_ASYNC_CAUSE;
+ u_int32_t AR_INTR_ASYNC_ENABLE;
+ u_int32_t AR_PCIE_SERDES;
+ u_int32_t AR_PCIE_SERDES2;
+ u_int32_t AR_GPIO_OUT;
+ u_int32_t AR_GPIO_IN;
+ u_int32_t AR_GPIO_OE_OUT;
+ u_int32_t AR_GPIO_OE1_OUT;
+ u_int32_t AR_GPIO_INTR_POL;
+ u_int32_t AR_GPIO_INPUT_EN_VAL;
+ u_int32_t AR_GPIO_INPUT_MUX1;
+ u_int32_t AR_GPIO_INPUT_MUX2;
+ u_int32_t AR_GPIO_OUTPUT_MUX1;
+ u_int32_t AR_GPIO_OUTPUT_MUX2;
+ u_int32_t AR_GPIO_OUTPUT_MUX3;
+ u_int32_t AR_INPUT_STATE;
+ u_int32_t AR_SPARE;
+ u_int32_t AR_PCIE_CORE_RESET_EN;
+ u_int32_t AR_CLKRUN;
+ u_int32_t AR_EEPROM_STATUS_DATA;
+ u_int32_t AR_OBS;
+ u_int32_t AR_RFSILENT;
+ u_int32_t AR_GPIO_PDPU;
+ u_int32_t AR_GPIO_DS;
+ u_int32_t AR_MISC;
+ u_int32_t AR_PCIE_MSI;
+ u_int32_t AR_TSF_SNAPSHOT_BT_ACTIVE;
+ u_int32_t AR_TSF_SNAPSHOT_BT_PRIORITY;
+ u_int32_t AR_TSF_SNAPSHOT_BT_CNTL;
+ u_int32_t AR_PCIE_PHY_LATENCY_NFTS_ADJ;
+ u_int32_t AR_TDMA_CCA_CNTL;
+ u_int32_t AR_TXAPSYNC;
+ u_int32_t AR_TXSYNC_INIT_SYNC_TMR;
+ u_int32_t AR_INTR_PRIO_SYNC_CAUSE;
+ u_int32_t AR_INTR_PRIO_SYNC_ENABLE;
+ u_int32_t AR_INTR_PRIO_ASYNC_MASK;
+ u_int32_t AR_INTR_PRIO_SYNC_MASK;
+ u_int32_t AR_INTR_PRIO_ASYNC_CAUSE;
+ u_int32_t AR_INTR_PRIO_ASYNC_ENABLE;
+ } ah_hostifregs;
+
+ u_int32_t ah_enterprise_mode;
+ u_int32_t ah_radar1;
+ u_int32_t ah_dc_offset;
+ HAL_BOOL ah_hw_green_tx_enable; /* 1:enalbe H/W Green Tx */
+ HAL_BOOL ah_smartantenna_enable; /* 1:enalbe H/W */
+ u_int32_t ah_disable_cck;
+ HAL_BOOL ah_lna_div_use_bt_ant_enable; /* 1:enable Rx(LNA) Diversity */
+
+
+ /*
+ * Different types of memory where the calibration data might be stored.
+ * All types are searched in Ar9300EepromRestore() in the order flash, eeprom, otp.
+ * To disable searching a type, set its parameter to 0.
+ */
+ int try_dram;
+ int try_flash;
+ int try_eeprom;
+ int try_otp;
+#ifdef ATH_CAL_NAND_FLASH
+ int try_nand;
+#endif
+ /*
+ * This is where we found the calibration data.
+ */
+ int calibration_data_source;
+ int calibration_data_source_address;
+ /*
+ * This is where we look for the calibration data. must be set before ath_attach() is called
+ */
+ int calibration_data_try;
+ int calibration_data_try_address;
+ u_int8_t
+ tx_iq_cal_enable : 1,
+ tx_iq_cal_during_agc_cal : 1,
+ tx_cl_cal_enable : 1;
+
+#if ATH_SUPPORT_MCI
+ /* For MCI */
+ HAL_BOOL ah_mci_ready;
+ u_int32_t ah_mci_int_raw;
+ u_int32_t ah_mci_int_rx_msg;
+ u_int32_t ah_mci_rx_status;
+ u_int32_t ah_mci_cont_status;
+ u_int8_t ah_mci_bt_state;
+ u_int32_t ah_mci_gpm_addr;
+ u_int8_t *ah_mci_gpm_buf;
+ u_int32_t ah_mci_gpm_len;
+ u_int32_t ah_mci_gpm_idx;
+ u_int32_t ah_mci_sched_addr;
+ u_int8_t *ah_mci_sched_buf;
+ u_int8_t ah_mci_coex_major_version_wlan;
+ u_int8_t ah_mci_coex_minor_version_wlan;
+ u_int8_t ah_mci_coex_major_version_bt;
+ u_int8_t ah_mci_coex_minor_version_bt;
+ HAL_BOOL ah_mci_coex_bt_version_known;
+ HAL_BOOL ah_mci_coex_wlan_channels_update;
+ u_int32_t ah_mci_coex_wlan_channels[4];
+ HAL_BOOL ah_mci_coex_2g5g_update;
+ HAL_BOOL ah_mci_coex_is_2g;
+ HAL_BOOL ah_mci_query_bt;
+ HAL_BOOL ah_mci_unhalt_bt_gpm; /* need send UNHALT */
+ HAL_BOOL ah_mci_halted_bt_gpm; /* HALT sent */
+ HAL_BOOL ah_mci_need_flush_btinfo;
+ HAL_BOOL ah_mci_concur_tx_en;
+ u_int8_t ah_mci_stomp_low_tx_pri;
+ u_int8_t ah_mci_stomp_all_tx_pri;
+ u_int8_t ah_mci_stomp_none_tx_pri;
+ u_int32_t ah_mci_wlan_cal_seq;
+ u_int32_t ah_mci_wlan_cal_done;
+#if ATH_SUPPORT_AIC
+ HAL_BOOL ah_aic_enabled;
+ u_int32_t ah_aic_sram[ATH_AIC_MAX_BT_CHANNEL];
+#endif
+#endif /* ATH_SUPPORT_MCI */
+ u_int8_t ah_cac_quiet_enabled;
+#if ATH_WOW_OFFLOAD
+ u_int32_t ah_mcast_filter_l32_set;
+ u_int32_t ah_mcast_filter_u32_set;
+#endif
+ HAL_BOOL ah_reduced_self_gen_mask;
+};
+
+#define AH9300(_ah) ((struct ath_hal_9300 *)(_ah))
+
+#define IS_9300_EMU(ah) \
+ (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_EMU_PCIE)
+
+#define ar9300_eep_data_in_flash(_ah) \
+ (!(AH_PRIVATE(_ah)->ah_flags & AH_USE_EEPROM))
+
+#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c) \
+ (IS_CHAN_5GHZ(_c) && \
+ ((AH_PRIVATE(_ah))->ah_config.ath_hal_fastClockEnable))
+
+#if notyet
+// Need these additional conditions for IS_5GHZ_FAST_CLOCK_EN when we have valid eeprom contents.
+&& \
+ ((ar9300_eeprom_get(AH9300(_ah), EEP_MINOR_REV) <= AR9300_EEP_MINOR_VER_16) || \
+ (ar9300_eeprom_get(AH9300(_ah), EEP_FSTCLK_5G))))
+#endif
+
+/*
+ * WAR for bug 6773. OS_DELAY() does a PIO READ on the PCI bus which allows
+ * other cards' DMA reads to complete in the middle of our reset.
+ */
+#define WAR_6773(x) do { \
+ if ((++(x) % 64) == 0) \
+ OS_DELAY(1); \
+} while (0)
+
+#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \
+ int r; \
+ for (r = 0; r < ((iniarray)->ia_rows); r++) { \
+ OS_REG_WRITE(ah, INI_RA((iniarray), (r), 0), INI_RA((iniarray), r, (column)));\
+ WAR_6773(regWr); \
+ } \
+} while (0)
+
+#define UPPER_5G_SUB_BANDSTART 5700
+#define MID_5G_SUB_BANDSTART 5400
+#define TRAINPOWER_DB_OFFSET 6
+
+#define AH_PAPRD_GET_SCALE_FACTOR(_scale, _eep, _is2G, _channel) do{ if(_is2G) { _scale = (_eep->modal_header_2g.paprd_rate_mask_ht20>>25)&0x7; \
+ } else { \
+ if(_channel >= UPPER_5G_SUB_BANDSTART){ _scale = (_eep->modal_header_5g.paprd_rate_mask_ht20>>25)&0x7;} \
+ else if((UPPER_5G_SUB_BANDSTART < _channel) && (_channel >= MID_5G_SUB_BANDSTART)) \
+ { _scale = (_eep->modal_header_5g.paprd_rate_mask_ht40>>28)&0x7;} \
+ else { _scale = (_eep->modal_header_5g.paprd_rate_mask_ht40>>25)&0x7;} } }while(0)
+
+#ifdef AH_ASSERT
+ #define ar9300FeatureNotSupported(feature, ah, func) \
+ ath_hal_printf(ah, # feature \
+ " not supported but called from %s\n", (func)), \
+ hal_assert(0)
+#else
+ #define ar9300FeatureNotSupported(feature, ah, func) \
+ ath_hal_printf(ah, # feature \
+ " not supported but called from %s\n", (func))
+#endif /* AH_ASSERT */
+
+extern void ar9300_detach(struct ath_hal *ah);
+extern void ar9300_get_desc_info(struct ath_hal *ah, HAL_DESC_INFO *desc_info);
+
+/*
+ * Green Tx, Based on different RSSI of Received Beacon thresholds,
+ * using different tx power by modified register tx power related values.
+ * The thresholds are decided by system team.
+ */
+#define WB225_SW_GREEN_TX_THRES1_DB 56 /* in dB */
+#define WB225_SW_GREEN_TX_THRES2_DB 41 /* in dB */
+#define WB225_OB_CALIBRATION_VALUE 5 /* For Green Tx OLPC Delta
+ Calibration Offset */
+#define WB225_OB_GREEN_TX_SHORT_VALUE 1 /* For Green Tx OB value
+ in short distance*/
+#define WB225_OB_GREEN_TX_MIDDLE_VALUE 3 /* For Green Tx OB value
+ in middle distance */
+#define WB225_OB_GREEN_TX_LONG_VALUE 5 /* For Green Tx OB value
+ in long distance */
+#define WB225_BBPWRTXRATE9_SW_GREEN_TX_SHORT_VALUE 0x06060606 /* For SwGreen Tx
+ BB_powertx_rate9 reg
+ value in short
+ distance */
+#define WB225_BBPWRTXRATE9_SW_GREEN_TX_MIDDLE_VALUE 0x0E0E0E0E /* For SwGreen Tx
+ BB_powertx_rate9 reg
+ value in middle
+ distance */
+
+
+/* Tx power for short distacnce in SwGreenTx.*/
+static const u_int8_t wb225_sw_gtx_tp_distance_short[ar9300_rate_size] = {
+ 6, /*ALL_TARGET_LEGACY_6_24*/
+ 6, /*ALL_TARGET_LEGACY_36*/
+ 6, /*ALL_TARGET_LEGACY_48*/
+ 4, /*ALL_TARGET_LEGACY_54*/
+ 6, /*ALL_TARGET_LEGACY_1L_5L*/
+ 6, /*ALL_TARGET_LEGACY_5S*/
+ 6, /*ALL_TARGET_LEGACY_11L*/
+ 6, /*ALL_TARGET_LEGACY_11S*/
+ 6, /*ALL_TARGET_HT20_0_8_16*/
+ 6, /*ALL_TARGET_HT20_1_3_9_11_17_19*/
+ 4, /*ALL_TARGET_HT20_4*/
+ 4, /*ALL_TARGET_HT20_5*/
+ 4, /*ALL_TARGET_HT20_6*/
+ 2, /*ALL_TARGET_HT20_7*/
+ 0, /*ALL_TARGET_HT20_12*/
+ 0, /*ALL_TARGET_HT20_13*/
+ 0, /*ALL_TARGET_HT20_14*/
+ 0, /*ALL_TARGET_HT20_15*/
+ 0, /*ALL_TARGET_HT20_20*/
+ 0, /*ALL_TARGET_HT20_21*/
+ 0, /*ALL_TARGET_HT20_22*/
+ 0, /*ALL_TARGET_HT20_23*/
+ 6, /*ALL_TARGET_HT40_0_8_16*/
+ 6, /*ALL_TARGET_HT40_1_3_9_11_17_19*/
+ 4, /*ALL_TARGET_HT40_4*/
+ 4, /*ALL_TARGET_HT40_5*/
+ 4, /*ALL_TARGET_HT40_6*/
+ 2, /*ALL_TARGET_HT40_7*/
+ 0, /*ALL_TARGET_HT40_12*/
+ 0, /*ALL_TARGET_HT40_13*/
+ 0, /*ALL_TARGET_HT40_14*/
+ 0, /*ALL_TARGET_HT40_15*/
+ 0, /*ALL_TARGET_HT40_20*/
+ 0, /*ALL_TARGET_HT40_21*/
+ 0, /*ALL_TARGET_HT40_22*/
+ 0 /*ALL_TARGET_HT40_23*/
+};
+
+/* Tx power for middle distacnce in SwGreenTx.*/
+static const u_int8_t wb225_sw_gtx_tp_distance_middle[ar9300_rate_size] = {
+ 14, /*ALL_TARGET_LEGACY_6_24*/
+ 14, /*ALL_TARGET_LEGACY_36*/
+ 14, /*ALL_TARGET_LEGACY_48*/
+ 12, /*ALL_TARGET_LEGACY_54*/
+ 14, /*ALL_TARGET_LEGACY_1L_5L*/
+ 14, /*ALL_TARGET_LEGACY_5S*/
+ 14, /*ALL_TARGET_LEGACY_11L*/
+ 14, /*ALL_TARGET_LEGACY_11S*/
+ 14, /*ALL_TARGET_HT20_0_8_16*/
+ 14, /*ALL_TARGET_HT20_1_3_9_11_17_19*/
+ 14, /*ALL_TARGET_HT20_4*/
+ 14, /*ALL_TARGET_HT20_5*/
+ 12, /*ALL_TARGET_HT20_6*/
+ 10, /*ALL_TARGET_HT20_7*/
+ 0, /*ALL_TARGET_HT20_12*/
+ 0, /*ALL_TARGET_HT20_13*/
+ 0, /*ALL_TARGET_HT20_14*/
+ 0, /*ALL_TARGET_HT20_15*/
+ 0, /*ALL_TARGET_HT20_20*/
+ 0, /*ALL_TARGET_HT20_21*/
+ 0, /*ALL_TARGET_HT20_22*/
+ 0, /*ALL_TARGET_HT20_23*/
+ 14, /*ALL_TARGET_HT40_0_8_16*/
+ 14, /*ALL_TARGET_HT40_1_3_9_11_17_19*/
+ 14, /*ALL_TARGET_HT40_4*/
+ 14, /*ALL_TARGET_HT40_5*/
+ 12, /*ALL_TARGET_HT40_6*/
+ 10, /*ALL_TARGET_HT40_7*/
+ 0, /*ALL_TARGET_HT40_12*/
+ 0, /*ALL_TARGET_HT40_13*/
+ 0, /*ALL_TARGET_HT40_14*/
+ 0, /*ALL_TARGET_HT40_15*/
+ 0, /*ALL_TARGET_HT40_20*/
+ 0, /*ALL_TARGET_HT40_21*/
+ 0, /*ALL_TARGET_HT40_22*/
+ 0 /*ALL_TARGET_HT40_23*/
+};
+
+/* OLPC DeltaCalibration Offset unit in half dB.*/
+static const u_int8_t wb225_gtx_olpc_cal_offset[6] = {
+ 0, /* OB0*/
+ 16, /* OB1*/
+ 9, /* OB2*/
+ 5, /* OB3*/
+ 2, /* OB4*/
+ 0, /* OB5*/
+};
+
+/*
+ * Definitions for HwGreenTx
+ */
+#define AR9485_HW_GREEN_TX_THRES1_DB 56 /* in dB */
+#define AR9485_HW_GREEN_TX_THRES2_DB 41 /* in dB */
+#define AR9485_BBPWRTXRATE9_HW_GREEN_TX_SHORT_VALUE 0x0C0C0A0A /* For HwGreen Tx
+ BB_powertx_rate9 reg
+ value in short
+ distance */
+#define AR9485_BBPWRTXRATE9_HW_GREEN_TX_MIDDLE_VALUE 0x10100E0E /* For HwGreenTx
+ BB_powertx_rate9 reg
+ value in middle
+ distance */
+
+/* Tx power for short distacnce in HwGreenTx.*/
+static const u_int8_t ar9485_hw_gtx_tp_distance_short[ar9300_rate_size] = {
+ 14, /*ALL_TARGET_LEGACY_6_24*/
+ 14, /*ALL_TARGET_LEGACY_36*/
+ 8, /*ALL_TARGET_LEGACY_48*/
+ 2, /*ALL_TARGET_LEGACY_54*/
+ 14, /*ALL_TARGET_LEGACY_1L_5L*/
+ 14, /*ALL_TARGET_LEGACY_5S*/
+ 14, /*ALL_TARGET_LEGACY_11L*/
+ 14, /*ALL_TARGET_LEGACY_11S*/
+ 12, /*ALL_TARGET_HT20_0_8_16*/
+ 12, /*ALL_TARGET_HT20_1_3_9_11_17_19*/
+ 12, /*ALL_TARGET_HT20_4*/
+ 12, /*ALL_TARGET_HT20_5*/
+ 8, /*ALL_TARGET_HT20_6*/
+ 2, /*ALL_TARGET_HT20_7*/
+ 0, /*ALL_TARGET_HT20_12*/
+ 0, /*ALL_TARGET_HT20_13*/
+ 0, /*ALL_TARGET_HT20_14*/
+ 0, /*ALL_TARGET_HT20_15*/
+ 0, /*ALL_TARGET_HT20_20*/
+ 0, /*ALL_TARGET_HT20_21*/
+ 0, /*ALL_TARGET_HT20_22*/
+ 0, /*ALL_TARGET_HT20_23*/
+ 10, /*ALL_TARGET_HT40_0_8_16*/
+ 10, /*ALL_TARGET_HT40_1_3_9_11_17_19*/
+ 10, /*ALL_TARGET_HT40_4*/
+ 10, /*ALL_TARGET_HT40_5*/
+ 6, /*ALL_TARGET_HT40_6*/
+ 2, /*ALL_TARGET_HT40_7*/
+ 0, /*ALL_TARGET_HT40_12*/
+ 0, /*ALL_TARGET_HT40_13*/
+ 0, /*ALL_TARGET_HT40_14*/
+ 0, /*ALL_TARGET_HT40_15*/
+ 0, /*ALL_TARGET_HT40_20*/
+ 0, /*ALL_TARGET_HT40_21*/
+ 0, /*ALL_TARGET_HT40_22*/
+ 0 /*ALL_TARGET_HT40_23*/
+};
+
+/* Tx power for middle distacnce in HwGreenTx.*/
+static const u_int8_t ar9485_hw_gtx_tp_distance_middle[ar9300_rate_size] = {
+ 18, /*ALL_TARGET_LEGACY_6_24*/
+ 18, /*ALL_TARGET_LEGACY_36*/
+ 14, /*ALL_TARGET_LEGACY_48*/
+ 12, /*ALL_TARGET_LEGACY_54*/
+ 18, /*ALL_TARGET_LEGACY_1L_5L*/
+ 18, /*ALL_TARGET_LEGACY_5S*/
+ 18, /*ALL_TARGET_LEGACY_11L*/
+ 18, /*ALL_TARGET_LEGACY_11S*/
+ 16, /*ALL_TARGET_HT20_0_8_16*/
+ 16, /*ALL_TARGET_HT20_1_3_9_11_17_19*/
+ 16, /*ALL_TARGET_HT20_4*/
+ 16, /*ALL_TARGET_HT20_5*/
+ 14, /*ALL_TARGET_HT20_6*/
+ 12, /*ALL_TARGET_HT20_7*/
+ 0, /*ALL_TARGET_HT20_12*/
+ 0, /*ALL_TARGET_HT20_13*/
+ 0, /*ALL_TARGET_HT20_14*/
+ 0, /*ALL_TARGET_HT20_15*/
+ 0, /*ALL_TARGET_HT20_20*/
+ 0, /*ALL_TARGET_HT20_21*/
+ 0, /*ALL_TARGET_HT20_22*/
+ 0, /*ALL_TARGET_HT20_23*/
+ 14, /*ALL_TARGET_HT40_0_8_16*/
+ 14, /*ALL_TARGET_HT40_1_3_9_11_17_19*/
+ 14, /*ALL_TARGET_HT40_4*/
+ 14, /*ALL_TARGET_HT40_5*/
+ 14, /*ALL_TARGET_HT40_6*/
+ 12, /*ALL_TARGET_HT40_7*/
+ 0, /*ALL_TARGET_HT40_12*/
+ 0, /*ALL_TARGET_HT40_13*/
+ 0, /*ALL_TARGET_HT40_14*/
+ 0, /*ALL_TARGET_HT40_15*/
+ 0, /*ALL_TARGET_HT40_20*/
+ 0, /*ALL_TARGET_HT40_21*/
+ 0, /*ALL_TARGET_HT40_22*/
+ 0 /*ALL_TARGET_HT40_23*/
+};
+
+/* MIMO Modes used in TPC calculations */
+typedef enum {
+ AR9300_DEF_MODE = 0, /* Could be CDD or Direct */
+ AR9300_TXBF_MODE,
+ AR9300_STBC_MODE
+} AR9300_TXMODES;
+typedef enum {
+ POSEIDON_STORED_REG_OBDB = 0, /* default OB/DB setting from ini */
+ POSEIDON_STORED_REG_TPC = 1, /* default txpower value in TPC reg */
+ POSEIDON_STORED_REG_BB_PWRTX_RATE9 = 2, /* default txpower value in
+ * BB_powertx_rate9 reg
+ */
+ POSEIDON_STORED_REG_SZ /* Can not add anymore */
+} POSEIDON_STORED_REGS;
+
+typedef enum {
+ POSEIDON_STORED_REG_G2_OLPC_OFFSET = 0,/* default OB/DB setting from ini */
+ POSEIDON_STORED_REG_G2_SZ /* should not exceed 3 */
+} POSEIDON_STORED_REGS_G2;
+
+#if AH_NEED_TX_DATA_SWAP
+#if AH_NEED_RX_DATA_SWAP
+#define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB | AR_CFG_SWRB,0)
+#else
+#define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB,0)
+#endif
+#elif AH_NEED_RX_DATA_SWAP
+#define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWRB,0)
+#else
+#define ar9300_init_cfg_reg(ah) OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD,0)
+#endif
+
+extern HAL_BOOL ar9300_rf_attach(struct ath_hal *, HAL_STATUS *);
+
+struct ath_hal;
+
+extern struct ath_hal_9300 * ar9300_new_state(u_int16_t devid,
+ HAL_ADAPTER_HANDLE osdev, HAL_SOFTC sc,
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_BUS_TYPE bustype,
+ asf_amem_instance_handle amem_handle,
+ struct hal_reg_parm *hal_conf_parm, HAL_STATUS *status);
+extern struct ath_hal * ar9300_attach(u_int16_t devid,
+ HAL_ADAPTER_HANDLE osdev, HAL_SOFTC sc,
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_BUS_TYPE bustype,
+ asf_amem_instance_handle amem_handle,
+ struct hal_reg_parm *hal_conf_parm,
+ HAL_STATUS *status);
+extern void ar9300_detach(struct ath_hal *ah);
+extern void ar9300_read_revisions(struct ath_hal *ah);
+extern HAL_BOOL ar9300_chip_test(struct ath_hal *ah);
+extern HAL_BOOL ar9300_get_channel_edges(struct ath_hal *ah,
+ u_int16_t flags, u_int16_t *low, u_int16_t *high);
+extern HAL_BOOL ar9300_fill_capability_info(struct ath_hal *ah);
+
+extern void ar9300_beacon_init(struct ath_hal *ah,
+ u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode);
+extern void ar9300_set_sta_beacon_timers(struct ath_hal *ah,
+ const HAL_BEACON_STATE *);
+
+extern HAL_BOOL ar9300_is_interrupt_pending(struct ath_hal *ah);
+extern HAL_BOOL ar9300_get_pending_interrupts(struct ath_hal *ah, HAL_INT *, HAL_INT_TYPE, u_int8_t, HAL_BOOL);
+extern HAL_INT ar9300_get_interrupts(struct ath_hal *ah);
+extern HAL_INT ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL);
+extern void ar9300_set_intr_mitigation_timer(struct ath_hal* ah,
+ HAL_INT_MITIGATION reg, u_int32_t value);
+extern u_int32_t ar9300_get_intr_mitigation_timer(struct ath_hal* ah,
+ HAL_INT_MITIGATION reg);
+extern u_int32_t ar9300_get_key_cache_size(struct ath_hal *);
+extern HAL_BOOL ar9300_is_key_cache_entry_valid(struct ath_hal *, u_int16_t entry);
+extern HAL_BOOL ar9300_reset_key_cache_entry(struct ath_hal *ah, u_int16_t entry);
+extern HAL_BOOL ar9300_set_key_cache_entry_mac(struct ath_hal *,
+ u_int16_t entry, const u_int8_t *mac);
+extern HAL_BOOL ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
+ const HAL_KEYVAL *k, const u_int8_t *mac, int xor_key);
+extern HAL_BOOL ar9300_print_keycache(struct ath_hal *ah);
+
+extern void ar9300_get_mac_address(struct ath_hal *ah, u_int8_t *mac);
+extern HAL_BOOL ar9300_set_mac_address(struct ath_hal *ah, const u_int8_t *);
+extern void ar9300_get_bss_id_mask(struct ath_hal *ah, u_int8_t *mac);
+extern HAL_BOOL ar9300_set_bss_id_mask(struct ath_hal *, const u_int8_t *);
+extern HAL_STATUS ar9300_select_ant_config(struct ath_hal *ah, u_int32_t cfg);
+extern u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz);
+extern HAL_BOOL ar9300_set_regulatory_domain(struct ath_hal *ah,
+ u_int16_t reg_domain, HAL_STATUS *stats);
+extern u_int ar9300_get_wireless_modes(struct ath_hal *ah);
+extern void ar9300_enable_rf_kill(struct ath_hal *);
+extern HAL_BOOL ar9300_gpio_cfg_output(struct ath_hal *, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE signalType);
+extern HAL_BOOL ar9300_gpio_cfg_output_led_off(struct ath_hal *, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE signalType);
+extern HAL_BOOL ar9300_gpio_cfg_input(struct ath_hal *, u_int32_t gpio);
+extern HAL_BOOL ar9300_gpio_set(struct ath_hal *, u_int32_t gpio, u_int32_t val);
+extern u_int32_t ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio);
+extern u_int32_t ar9300_gpio_get_intr(struct ath_hal *ah);
+extern void ar9300_gpio_set_intr(struct ath_hal *ah, u_int, u_int32_t ilevel);
+extern u_int32_t ar9300_gpio_get_polarity(struct ath_hal *ah);
+extern void ar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t, u_int32_t);
+extern u_int32_t ar9300_gpio_get_mask(struct ath_hal *ah);
+extern int ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map);
+extern void ar9300_set_led_state(struct ath_hal *ah, HAL_LED_STATE state);
+extern void ar9300_set_power_led_state(struct ath_hal *ah, u_int8_t enable);
+extern void ar9300_set_network_led_state(struct ath_hal *ah, u_int8_t enable);
+extern void ar9300_write_associd(struct ath_hal *ah, const u_int8_t *bssid,
+ u_int16_t assoc_id);
+extern u_int32_t ar9300_ppm_get_rssi_dump(struct ath_hal *);
+extern u_int32_t ar9300_ppm_arm_trigger(struct ath_hal *);
+extern int ar9300_ppm_get_trigger(struct ath_hal *);
+extern u_int32_t ar9300_ppm_force(struct ath_hal *);
+extern void ar9300_ppm_un_force(struct ath_hal *);
+extern u_int32_t ar9300_ppm_get_force_state(struct ath_hal *);
+extern u_int32_t ar9300_ppm_get_force_state(struct ath_hal *);
+extern void ar9300_set_dcs_mode(struct ath_hal *ah, u_int32_t);
+extern u_int32_t ar9300_get_dcs_mode(struct ath_hal *ah);
+extern u_int32_t ar9300_get_tsf32(struct ath_hal *ah);
+extern u_int64_t ar9300_get_tsf64(struct ath_hal *ah);
+extern u_int32_t ar9300_get_tsf2_32(struct ath_hal *ah);
+extern void ar9300_set_tsf64(struct ath_hal *ah, u_int64_t tsf);
+extern void ar9300_reset_tsf(struct ath_hal *ah);
+extern void ar9300_set_basic_rate(struct ath_hal *ah, HAL_RATE_SET *pSet);
+extern u_int32_t ar9300_get_random_seed(struct ath_hal *ah);
+extern HAL_BOOL ar9300_detect_card_present(struct ath_hal *ah);
+extern void ar9300_update_mib_mac_stats(struct ath_hal *ah);
+extern void ar9300_get_mib_mac_stats(struct ath_hal *ah, HAL_MIB_STATS* stats);
+extern HAL_BOOL ar9300_is_japan_channel_spread_supported(struct ath_hal *ah);
+extern u_int32_t ar9300_get_cur_rssi(struct ath_hal *ah);
+extern u_int32_t ar9300_get_rssi_chain0(struct ath_hal *ah);
+extern u_int ar9300_get_def_antenna(struct ath_hal *ah);
+extern void ar9300_set_def_antenna(struct ath_hal *ah, u_int antenna);
+extern HAL_BOOL ar9300_set_antenna_switch(struct ath_hal *ah,
+ HAL_ANT_SETTING settings, HAL_CHANNEL *chan, u_int8_t *, u_int8_t *, u_int8_t *);
+extern HAL_BOOL ar9300_is_sleep_after_beacon_broken(struct ath_hal *ah);
+extern HAL_BOOL ar9300_set_slot_time(struct ath_hal *, u_int);
+extern HAL_BOOL ar9300_set_ack_timeout(struct ath_hal *, u_int);
+extern u_int ar9300_get_ack_timeout(struct ath_hal *);
+extern HAL_STATUS ar9300_set_quiet(struct ath_hal *ah, u_int32_t period, u_int32_t duration,
+ u_int32_t next_start, HAL_QUIET_FLAG flag);
+extern void ar9300_set_pcu_config(struct ath_hal *);
+extern HAL_STATUS ar9300_get_capability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+ u_int32_t, u_int32_t *);
+extern HAL_BOOL ar9300_set_capability(struct ath_hal *, HAL_CAPABILITY_TYPE,
+ u_int32_t, u_int32_t, HAL_STATUS *);
+extern HAL_BOOL ar9300_get_diag_state(struct ath_hal *ah, int request,
+ const void *args, u_int32_t argsize,
+ void **result, u_int32_t *resultsize);
+extern void ar9300_get_desc_info(struct ath_hal *ah, HAL_DESC_INFO *desc_info);
+extern int8_t ar9300_get_11n_ext_busy(struct ath_hal *ah);
+extern void ar9300_set_11n_mac2040(struct ath_hal *ah, HAL_HT_MACMODE mode);
+extern HAL_HT_RXCLEAR ar9300_get_11n_rx_clear(struct ath_hal *ah);
+extern void ar9300_set_11n_rx_clear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear);
+extern HAL_BOOL ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode,
+ int set_chip);
+extern HAL_POWER_MODE ar9300_get_power_mode(struct ath_hal *ah);
+extern HAL_BOOL ar9300_set_power_mode_awake(struct ath_hal *ah, int set_chip);
+extern void ar9300_set_sm_power_mode(struct ath_hal *ah, HAL_SMPS_MODE mode);
+
+extern void ar9300_config_pci_power_save(struct ath_hal *ah, int restore, int power_off);
+
+extern void ar9300_force_tsf_sync(struct ath_hal *ah, const u_int8_t *bssid,
+ u_int16_t assoc_id);
+
+
+#if ATH_WOW
+extern void ar9300_wow_apply_pattern(struct ath_hal *ah, u_int8_t *p_ath_pattern,
+ u_int8_t *p_ath_mask, int32_t pattern_count, u_int32_t ath_pattern_len);
+//extern u_int32_t ar9300_wow_wake_up(struct ath_hal *ah,u_int8_t *chipPatternBytes);
+extern u_int32_t ar9300_wow_wake_up(struct ath_hal *ah, HAL_BOOL offloadEnable);
+extern HAL_BOOL ar9300_wow_enable(struct ath_hal *ah, u_int32_t pattern_enable, u_int32_t timeout_in_seconds, int clearbssid,
+ HAL_BOOL offloadEnable);
+#if ATH_WOW_OFFLOAD
+/* ARP offload */
+#define WOW_OFFLOAD_ARP_INFO_MAX 2
+
+struct hal_wow_offload_arp_info {
+ u_int32_t valid;
+ u_int32_t id;
+
+ u_int32_t Flags;
+ union {
+ u_int8_t u8[4];
+ u_int32_t u32;
+ } RemoteIPv4Address;
+ union {
+ u_int8_t u8[4];
+ u_int32_t u32;
+ } HostIPv4Address;
+ union {
+ u_int8_t u8[6];
+ u_int32_t u32[2];
+ } MacAddress;
+};
+
+/* NS offload */
+#define WOW_OFFLOAD_NS_INFO_MAX 2
+
+struct hal_wow_offload_ns_info {
+ u_int32_t valid;
+ u_int32_t id;
+
+ u_int32_t Flags;
+ union {
+ u_int8_t u8[16];
+ u_int32_t u32[4];
+ } RemoteIPv6Address;
+ union {
+ u_int8_t u8[16];
+ u_int32_t u32[4];
+ } SolicitedNodeIPv6Address;
+ union {
+ u_int8_t u8[6];
+ u_int32_t u32[2];
+ } MacAddress;
+ union {
+ u_int8_t u8[16];
+ u_int32_t u32[4];
+ } TargetIPv6Addresses[2];
+};
+
+extern void ar9300_wowoffload_prep(struct ath_hal *ah);
+extern void ar9300_wowoffload_post(struct ath_hal *ah);
+extern u_int32_t ar9300_wowoffload_download_rekey_data(struct ath_hal *ah, u_int32_t *data, u_int32_t size);
+extern void ar9300_wowoffload_retrieve_data(struct ath_hal *ah, void *buf, u_int32_t param);
+extern void ar9300_wowoffload_download_acer_magic(struct ath_hal *ah, HAL_BOOL valid, u_int8_t* datap, u_int32_t bytes);
+extern void ar9300_wowoffload_download_acer_swka(struct ath_hal *ah, u_int32_t id, HAL_BOOL valid, u_int32_t period, u_int32_t size, u_int32_t* datap);
+extern void ar9300_wowoffload_download_arp_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data);
+extern void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id, u_int32_t *data);
+#endif /* ATH_WOW_OFFLOAD */
+#endif
+
+extern HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode,
+ HAL_CHANNEL *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask,
+ u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing,
+ HAL_BOOL b_channel_change, HAL_STATUS *status, int is_scan);
+extern HAL_BOOL ar9300_lean_channel_change(struct ath_hal *ah, HAL_OPMODE opmode, HAL_CHANNEL *chan,
+ HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask);
+extern HAL_BOOL ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type);
+extern void ar9300_init_pll(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern void ar9300_green_ap_ps_on_off( struct ath_hal *ah, u_int16_t rxMask);
+extern u_int16_t ar9300_is_single_ant_power_save_possible(struct ath_hal *ah);
+extern void ar9300_set_operating_mode(struct ath_hal *ah, int opmode);
+extern HAL_BOOL ar9300_phy_disable(struct ath_hal *ah);
+extern HAL_BOOL ar9300_disable(struct ath_hal *ah);
+extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, HAL_CHANNEL *);
+extern HAL_BOOL ar9300_calibration(struct ath_hal *ah, HAL_CHANNEL *chan,
+ u_int8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isIQdone, int is_scan, u_int32_t *sched_cals);
+extern void ar9300_reset_cal_valid(struct ath_hal *ah, HAL_CHANNEL *chan,
+ HAL_BOOL *isIQdone, u_int32_t cal_type);
+extern void ar9300_iq_cal_collect(struct ath_hal *ah, u_int8_t num_chains);
+extern void ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains);
+extern void ar9300_temp_comp_cal_collect(struct ath_hal *ah);
+extern void ar9300_temp_comp_calibration(struct ath_hal *ah, u_int8_t num_chains);
+extern int16_t ar9300_get_min_cca_pwr(struct ath_hal *ah);
+extern void ar9300_upload_noise_floor(struct ath_hal *ah, int is2G, int16_t nfarray[]);
+
+extern HAL_BOOL ar9300_set_tx_power_limit(struct ath_hal *ah, u_int32_t limit,
+ u_int16_t extra_txpow, u_int16_t tpc_in_db);
+extern void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf,
+ HAL_CHANNEL *chan, int is_scan);
+extern HAL_BOOL ar9300_load_nf(struct ath_hal *ah, int16_t nf[]);
+
+extern HAL_RFGAIN ar9300_get_rfgain(struct ath_hal *ah);
+extern const HAL_RATE_TABLE *ar9300_get_rate_table(struct ath_hal *, u_int mode);
+extern int16_t ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode,
+ u_int8_t rate_index, u_int8_t chainmask, u_int8_t mimo_mode);
+extern void ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode,
+ HAL_CHANNEL_INTERNAL *chan,
+ u_int8_t powerPerRate[],
+ u_int8_t chainmask);
+extern void ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah,
+ u_int8_t powerPerRate[]);
+extern void ar9300_reset_tx_status_ring(struct ath_hal *ah);
+extern void ar9300_enable_mib_counters(struct ath_hal *);
+extern void ar9300_disable_mib_counters(struct ath_hal *);
+extern void ar9300_ani_attach(struct ath_hal *);
+extern void ar9300_ani_detach(struct ath_hal *);
+extern struct ar9300_ani_state *ar9300_ani_get_current_state(struct ath_hal *);
+extern struct ar9300_stats *ar9300_ani_get_current_stats(struct ath_hal *);
+extern HAL_BOOL ar9300_ani_control(struct ath_hal *, HAL_ANI_CMD cmd, int param);
+struct ath_rx_status;
+
+extern void ar9300_process_mib_intr(struct ath_hal *, const HAL_NODE_STATS *);
+extern void ar9300_ani_ar_poll(struct ath_hal *, const HAL_NODE_STATS *,
+ HAL_CHANNEL *, HAL_ANISTATS *);
+extern void ar9300_ani_reset(struct ath_hal *, HAL_BOOL is_scanning);
+extern void ar9300_ani_init_defaults(struct ath_hal *ah, HAL_HT_MACMODE macmode);
+extern void ar9300_enable_tpc(struct ath_hal *);
+
+extern HAL_BOOL ar9300_rf_gain_cap_apply(struct ath_hal *ah, int is2GHz);
+extern void ar9300_rx_gain_table_apply(struct ath_hal *ah);
+extern void ar9300_tx_gain_table_apply(struct ath_hal *ah);
+extern void ar9300_mat_enable(struct ath_hal *ah, int enable);
+extern void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry);
+extern HAL_BOOL ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal * ah, HAL_BOOL enable, HAL_CHANNEL * chan);
+
+#ifdef AH_SUPPORT_AR9300
+/* BB Panic Watchdog declarations */
+#define HAL_BB_PANIC_WD_TMO 25 /* in ms, 0 to disable */
+#define HAL_BB_PANIC_WD_TMO_HORNET 85
+extern void ar9300_config_bb_panic_watchdog(struct ath_hal *);
+extern void ar9300_handle_bb_panic(struct ath_hal *);
+extern int ar9300_get_bb_panic_info(struct ath_hal *ah, struct hal_bb_panic_info *bb_panic);
+extern HAL_BOOL ar9300_handle_radar_bb_panic(struct ath_hal *ah);
+#endif
+extern void ar9300_set_hal_reset_reason(struct ath_hal *ah, u_int8_t resetreason);
+
+/* DFS declarations */
+#ifdef ATH_SUPPORT_DFS
+extern void ar9300_check_dfs(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern void ar9300_dfs_found(struct ath_hal *ah, HAL_CHANNEL *chan,
+ u_int64_t nolTime);
+extern void ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
+extern void ar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
+extern HAL_BOOL ar9300_radar_wait(struct ath_hal *ah, HAL_CHANNEL *chan);
+extern struct dfs_pulse * ar9300_get_dfs_radars(struct ath_hal *ah,
+ u_int32_t dfsdomain, int *numradars, struct dfs_bin5pulse **bin5pulses,
+ int *numb5radars, HAL_PHYERR_PARAM *pe);
+extern void ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val);
+extern u_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable);
+extern void ar9300_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL enable);
+extern void ar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start);
+#endif
+
+extern HAL_CHANNEL * ar9300_get_extension_channel(struct ath_hal *ah);
+extern HAL_BOOL ar9300_is_fast_clock_enabled(struct ath_hal *ah);
+
+
+extern void ar9300_mark_phy_inactive(struct ath_hal *ah);
+
+/* Spectral scan declarations */
+extern void ar9300_configure_spectral_scan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss);
+extern void ar9300_set_cca_threshold(struct ath_hal *ah, u_int8_t thresh62);
+extern void ar9300_get_spectral_params(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss);
+extern HAL_BOOL ar9300_is_spectral_active(struct ath_hal *ah);
+extern HAL_BOOL ar9300_is_spectral_enabled(struct ath_hal *ah);
+extern void ar9300_start_spectral_scan(struct ath_hal *ah);
+extern void ar9300_stop_spectral_scan(struct ath_hal *ah);
+extern u_int32_t ar9300_get_spectral_config(struct ath_hal *ah);
+extern void ar9300_restore_spectral_config(struct ath_hal *ah, u_int32_t restoreval);
+int16_t ar9300_get_ctl_chan_nf(struct ath_hal *ah);
+int16_t ar9300_get_ext_chan_nf(struct ath_hal *ah);
+/* End spectral scan declarations */
+
+/* Raw ADC capture functions */
+extern void ar9300_enable_test_addac_mode(struct ath_hal *ah);
+extern void ar9300_disable_test_addac_mode(struct ath_hal *ah);
+extern void ar9300_begin_adc_capture(struct ath_hal *ah, int auto_agc_gain);
+extern HAL_STATUS ar9300_retrieve_capture_data(struct ath_hal *ah, u_int16_t chain_mask, int disable_dc_filter, void *sample_buf, u_int32_t *max_samples);
+extern HAL_STATUS ar9300_calc_adc_ref_powers(struct ath_hal *ah, int freq_mhz, int16_t *sample_min, int16_t *sample_max, int32_t *chain_ref_pwr, int num_chain_ref_pwr);
+extern HAL_STATUS ar9300_get_min_agc_gain(struct ath_hal *ah, int freq_mhz, int32_t *chain_gain, int num_chain_gain);
+
+extern HAL_BOOL ar9300_reset_11n(struct ath_hal *ah, HAL_OPMODE opmode,
+ HAL_CHANNEL *chan, HAL_BOOL b_channel_change, HAL_STATUS *status);
+extern void ar9300_set_coverage_class(struct ath_hal *ah, u_int8_t coverageclass, int now);
+
+extern void ar9300_get_channel_centers(struct ath_hal *ah,
+ HAL_CHANNEL_INTERNAL *chan,
+ CHAN_CENTERS *centers);
+extern u_int16_t ar9300_get_ctl_center(struct ath_hal *ah,
+ HAL_CHANNEL_INTERNAL *chan);
+extern u_int16_t ar9300_get_ext_center(struct ath_hal *ah,
+ HAL_CHANNEL_INTERNAL *chan);
+extern u_int32_t ar9300_get_mib_cycle_counts_pct(struct ath_hal *, u_int32_t*, u_int32_t*, u_int32_t*);
+
+extern void ar9300_dma_reg_dump(struct ath_hal *);
+extern HAL_BOOL ar9300_set_11n_rx_rifs(struct ath_hal *ah, HAL_BOOL enable);
+extern HAL_BOOL ar9300_set_rifs_delay(struct ath_hal *ah, HAL_BOOL enable);
+extern HAL_BOOL ar9300_set_smart_antenna(struct ath_hal *ah, HAL_BOOL enable);
+extern HAL_BOOL ar9300_detect_bb_hang(struct ath_hal *ah);
+extern HAL_BOOL ar9300_detect_mac_hang(struct ath_hal *ah);
+
+#ifdef ATH_BT_COEX
+extern void ar9300_set_bt_coex_info(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo);
+extern void ar9300_bt_coex_config(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf);
+extern void ar9300_bt_coex_set_qcu_thresh(struct ath_hal *ah, int qnum);
+extern void ar9300_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type);
+extern void ar9300_bt_coex_setup_bmiss_thresh(struct ath_hal *ah, u_int32_t thresh);
+extern void ar9300_bt_coex_set_parameter(struct ath_hal *ah, u_int32_t type, u_int32_t value);
+extern void ar9300_bt_coex_disable(struct ath_hal *ah);
+extern int ar9300_bt_coex_enable(struct ath_hal *ah);
+extern void ar9300_init_bt_coex(struct ath_hal *ah);
+extern u_int32_t ar9300_get_bt_active_gpio(struct ath_hal *ah, u_int32_t reg);
+extern u_int32_t ar9300_get_wlan_active_gpio(struct ath_hal *ah, u_int32_t reg,u_int32_t bOn);
+#endif
+extern int ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf);
+extern void ar9300_free_generic_timer(struct ath_hal *ah, int index);
+extern void ar9300_start_generic_timer(struct ath_hal *ah, int index, u_int32_t timer_next,
+ u_int32_t timer_period);
+extern void ar9300_stop_generic_timer(struct ath_hal *ah, int index);
+extern void ar9300_get_gen_timer_interrupts(struct ath_hal *ah, u_int32_t *trigger,
+ u_int32_t *thresh);
+extern void ar9300_start_tsf2(struct ath_hal *ah);
+
+extern void ar9300_chk_rssi_update_tx_pwr(struct ath_hal *ah, int rssi);
+extern HAL_BOOL ar9300_is_skip_paprd_by_greentx(struct ath_hal *ah);
+extern void ar9300_control_signals_for_green_tx_mode(struct ath_hal *ah);
+extern void ar9300_hwgreentx_set_pal_spare(struct ath_hal *ah, int value);
+extern void ar9300_reset_hw_beacon_proc_crc(struct ath_hal *ah);
+extern int32_t ar9300_get_hw_beacon_rssi(struct ath_hal *ah);
+extern void ar9300_set_hw_beacon_rssi_threshold(struct ath_hal *ah,
+ u_int32_t rssi_threshold);
+extern void ar9300_reset_hw_beacon_rssi(struct ath_hal *ah);
+extern void ar9300_set_hw_beacon_proc(struct ath_hal *ah, HAL_BOOL on);
+extern HAL_BOOL ar9300_is_ani_noise_spur(struct ath_hal *ah);
+extern void ar9300_get_vow_stats(struct ath_hal *ah, HAL_VOWSTATS *p_stats,
+ u_int8_t);
+
+extern int ar9300_get_spur_info(struct ath_hal * ah, int *enable, int len, u_int16_t *freq);
+extern int ar9300_set_spur_info(struct ath_hal * ah, int enable, int len, u_int16_t *freq);
+extern void ar9300_wow_set_gpio_reset_low(struct ath_hal * ah);
+extern void ar9300_get_mib_cycle_counts(struct ath_hal *, HAL_COUNTERS*);
+extern void ar9300_clear_mib_counters(struct ath_hal *ah);
+
+/* EEPROM interface functions */
+/* Common Interface functions */
+extern HAL_STATUS ar9300_eeprom_attach(struct ath_hal *);
+extern u_int32_t ar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param);
+
+extern u_int32_t ar9300_ini_fixup(struct ath_hal *ah,
+ ar9300_eeprom_t *p_eep_data,
+ u_int32_t reg,
+ u_int32_t val);
+
+extern HAL_STATUS ar9300_eeprom_set_transmit_power(struct ath_hal *ah,
+ ar9300_eeprom_t *p_eep_data, HAL_CHANNEL_INTERNAL *chan,
+ u_int16_t cfg_ctl, u_int16_t twice_antenna_reduction,
+ u_int16_t twice_max_regulatory_power, u_int16_t power_limit);
+extern void ar9300_eeprom_set_addac(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar9300_eeprom_set_param(struct ath_hal *ah, EEPROM_PARAM param, u_int32_t value);
+extern HAL_BOOL ar9300_eeprom_set_board_values(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+extern HAL_BOOL ar9300_eeprom_read_word(struct ath_hal *, u_int off, u_int16_t *data);
+extern HAL_BOOL ar9300_eeprom_read(struct ath_hal *ah, long address, u_int8_t *buffer, int many);
+extern HAL_BOOL ar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi);
+
+extern HAL_BOOL ar9300_flash_read(struct ath_hal *, u_int off, u_int16_t *data);
+extern HAL_BOOL ar9300_flash_write(struct ath_hal *, u_int off, u_int16_t data);
+extern u_int ar9300_eeprom_dump_support(struct ath_hal *ah, void **pp_e);
+extern u_int8_t ar9300_eeprom_get_num_ant_config(struct ath_hal_9300 *ahp, HAL_FREQ_BAND freq_band);
+extern HAL_STATUS ar9300_eeprom_get_ant_cfg(struct ath_hal_9300 *ahp, HAL_CHANNEL_INTERNAL *chan,
+ u_int8_t index, u_int16_t *config);
+extern u_int8_t* ar9300_eeprom_get_cust_data(struct ath_hal_9300 *ahp);
+extern u_int8_t *ar9300_eeprom_get_spur_chans_ptr(struct ath_hal *ah, HAL_BOOL is_2ghz);
+extern HAL_BOOL ar9300_interference_is_present(struct ath_hal *ah);
+extern HAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah);
+extern void ar9300_disp_tpc_tables(struct ath_hal *ah);
+extern u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah);
+extern u_int8_t ar9300_eeprom_set_tx_gain_cap(struct ath_hal *ah, int *tx_gain_max);
+extern u_int8_t ar9300_eeprom_tx_gain_table_index_max_apply(struct ath_hal *ah, u_int16_t channel);
+
+/* Common EEPROM Help function */
+extern void ar9300_set_immunity(struct ath_hal *ah, HAL_BOOL enable);
+extern void ar9300_get_hw_hangs(struct ath_hal *ah, hal_hw_hangs_t *hangs);
+
+extern u_int ar9300_mac_to_clks(struct ath_hal *ah, u_int clks);
+
+/* tx_bf interface */
+#define ar9300_init_txbf(ah)
+#define ar9300_set_11n_txbf_sounding(ah, ds, series, cec, opt)
+#define ar9300_set_11n_txbf_cal(ah, ds, cal_pos, code_rate, cec, opt)
+#define ar9300_txbf_save_cv_from_compress( \
+ ah, key_idx, mimo_control, compress_rpt) \
+ false
+#define ar9300_txbf_save_cv_from_non_compress( \
+ ah, key_idx, mimo_control, non_compress_rpt) \
+ false
+#define ar9300_txbf_rc_update( \
+ ah, rx_status, local_h, csi_frame, ness_a, ness_b, bw) \
+ false
+#define ar9300_fill_csi_frame( \
+ ah, rx_status, bandwidth, local_h, csi_frame_body) \
+ 0
+#define ar9300_fill_txbf_capabilities(ah)
+#define ar9300_get_txbf_capabilities(ah) NULL
+#define ar9300_txbf_set_key( \
+ ah, entry, rx_staggered_sounding, channel_estimation_cap, mmss)
+#define ar9300_read_key_cache_mac(ah, entry, mac) false
+#define ar9300_txbf_get_cv_cache_nr(ah, key_idx, nr)
+#define ar9300_set_selfgenrate_limit(ah, ts_ratecode)
+#define ar9300_reset_lowest_txrate(ah)
+#define ar9300_txbf_set_basic_set(ah)
+
+extern void ar9300_crdc_rx_notify(struct ath_hal *ah, struct ath_rx_status *rxs);
+extern void ar9300_chain_rssi_diff_compensation(struct ath_hal *ah);
+
+
+
+#if ATH_SUPPORT_MCI
+extern void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type);
+extern void ar9300_mci_bt_coex_disable(struct ath_hal *ah);
+extern int ar9300_mci_bt_coex_enable(struct ath_hal *ah);
+extern void ar9300_mci_setup (struct ath_hal *ah, u_int32_t gpm_addr,
+ void *gpm_buf, u_int16_t len,
+ u_int32_t sched_addr);
+extern void ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done);
+extern void ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done);
+extern void ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done);
+extern HAL_BOOL ar9300_mci_send_message (struct ath_hal *ah, u_int8_t header,
+ u_int32_t flag, u_int32_t *payload, u_int8_t len,
+ HAL_BOOL wait_done, HAL_BOOL check_bt);
+extern u_int32_t ar9300_mci_get_interrupt (struct ath_hal *ah,
+ u_int32_t *mci_int,
+ u_int32_t *mci_int_rx_msg);
+extern u_int32_t ar9300_mci_state (struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data);
+extern void ar9300_mci_reset (struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g, HAL_BOOL is_full_sleep);
+extern void ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah, HAL_BOOL halt, HAL_BOOL wait_done);
+extern void ar9300_mci_mute_bt(struct ath_hal *ah);
+extern u_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type, u_int8_t gpm_opcode, int32_t time_out);
+extern void ar9300_mci_enable_interrupt(struct ath_hal *ah);
+extern void ar9300_mci_disable_interrupt(struct ath_hal *ah);
+extern void ar9300_mci_detach (struct ath_hal *ah);
+extern u_int32_t ar9300_mci_check_int (struct ath_hal *ah, u_int32_t ints);
+extern void ar9300_mci_sync_bt_state (struct ath_hal *ah);
+extern void ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g);
+extern void ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done);
+#if ATH_SUPPORT_AIC
+extern u_int32_t ar9300_aic_calibration (struct ath_hal *ah);
+extern u_int32_t ar9300_aic_start_normal (struct ath_hal *ah);
+#endif
+#endif
+
+extern HAL_STATUS ar9300_set_proxy_sta(struct ath_hal *ah, HAL_BOOL enable);
+
+extern HAL_BOOL ar9300_regulatory_domain_override(
+ struct ath_hal *ah, u_int16_t regdmn);
+#if ATH_ANT_DIV_COMB
+extern void ar9300_ant_div_comb_get_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG* div_comb_conf);
+extern void ar9300_ant_div_comb_set_config(struct ath_hal *ah, HAL_ANT_COMB_CONFIG* div_comb_conf);
+#endif /* ATH_ANT_DIV_COMB */
+extern void ar9300_disable_phy_restart(struct ath_hal *ah,
+ int disable_phy_restart);
+extern void ar9300_enable_keysearch_always(struct ath_hal *ah, int enable);
+extern HAL_BOOL ar9300ForceVCS( struct ath_hal *ah);
+extern HAL_BOOL ar9300SetDfs3StreamFix(struct ath_hal *ah, u_int32_t val);
+extern HAL_BOOL ar9300Get3StreamSignature( struct ath_hal *ah);
+
+#ifdef ATH_TX99_DIAG
+#ifndef ATH_SUPPORT_HTC
+extern void ar9300_tx99_channel_pwr_update(struct ath_hal *ah, HAL_CHANNEL *c, u_int32_t txpower);
+extern void ar9300_tx99_chainmsk_setup(struct ath_hal *ah, int tx_chainmask);
+extern void ar9300_tx99_set_single_carrier(struct ath_hal *ah, int tx_chain_mask, int chtype);
+extern void ar9300_tx99_start(struct ath_hal *ah, u_int8_t *data);
+extern void ar9300_tx99_stop(struct ath_hal *ah);
+#endif /* ATH_SUPPORT_HTC */
+#endif /* ATH_TX99_DIAG */
+
+enum {
+ AR9300_COEFF_TX_TYPE = 0,
+ AR9300_COEFF_RX_TYPE
+};
+
+#endif /* _ATH_AR9300_H_ */
diff --git a/hal/ar9300/ar9300_aic.c b/hal/ar9300/ar9300_aic.c
new file mode 100644
index 000000000000..e35d76c56fec
--- /dev/null
+++ b/hal/ar9300/ar9300_aic.c
@@ -0,0 +1,727 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar9300/ar9300.h"
+#include "ar9300/ar9300reg.h"
+#include "ar9300/ar9300phy.h"
+
+#if ATH_SUPPORT_AIC
+
+#define ATH_AIC_TEST_PATTERN 1
+
+struct ath_aic_sram_info {
+ HAL_BOOL valid;
+ u_int8_t rot_quad_att_db;
+ HAL_BOOL vga_quad_sign;
+ u_int8_t rot_dir_att_db;
+ HAL_BOOL vga_dir_sign;
+ u_int8_t com_att_6db;
+ };
+
+struct ath_aic_out_info {
+ int16_t dir_path_gain_lin;
+ int16_t quad_path_gain_lin;
+ struct ath_aic_sram_info sram;
+ };
+
+#define ATH_AIC_MAX_COM_ATT_DB_TABLE 6
+#define ATH_AIC_MAX_AIC_LIN_TABLE 69
+#define ATH_AIC_MIN_ROT_DIR_ATT_DB 0
+#define ATH_AIC_MIN_ROT_QUAD_ATT_DB 0
+#define ATH_AIC_MAX_ROT_DIR_ATT_DB 37
+#define ATH_AIC_MAX_ROT_QUAD_ATT_DB 37
+#define ATH_AIC_SRAM_AUTO_INCREMENT 0x80000000
+#define ATH_AIC_SRAM_GAIN_TABLE_OFFSET 0x280
+#define ATH_AIC_SRAM_CAL_OFFSET 0x140
+#define ATH_AIC_MAX_CAL_COUNT 5
+#define ATH_AIC_MEAS_MAG_THRESH 20
+#define ATH_AIC_BT_JUPITER_CTRL 0x66820
+#define ATH_AIC_BT_AIC_ENABLE 0x02
+
+
+static const u_int8_t com_att_db_table[ATH_AIC_MAX_COM_ATT_DB_TABLE] = {
+ 0, 3, 9, 15, 21, 27};
+
+static const u_int16_t aic_lin_table[ATH_AIC_MAX_AIC_LIN_TABLE] = {
+ 8191, 7300, 6506, 5799, 5168, 4606, 4105, 3659,
+ 3261, 2906, 2590, 2309, 2057, 1834, 1634, 1457,
+ 1298, 1157, 1031, 919, 819, 730, 651, 580,
+ 517, 461, 411, 366, 326, 291, 259, 231,
+ 206, 183, 163, 146, 130, 116, 103, 92,
+ 82, 73, 65, 58, 52, 46, 41, 37,
+ 33, 29, 26, 23, 21, 18, 16, 15,
+ 13, 12, 10, 9, 8, 7, 7, 6,
+ 5, 5, 4, 4, 3};
+
+#if ATH_AIC_TEST_PATTERN
+static const u_int32_t aic_test_pattern[ATH_AIC_MAX_BT_CHANNEL] = {
+0x00000, // 0
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x1918d,
+0x1938d, // 10
+0x00000,
+0x1978d,
+0x19e8d,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000, // 20
+0x00000,
+0x00000,
+0x1ce8f,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x1ca93,
+0x1c995,
+0x00000, // 30
+0x1c897,
+0x1c899,
+0x00000,
+0x00000,
+0x1c79f,
+0x00000,
+0x1c7a5,
+0x1c6ab,
+0x00000,
+0x00000, // 40
+0x00000,
+0x00000,
+0x1c63f,
+0x00000,
+0x1c52b,
+0x1c525,
+0x1c523,
+0x00000,
+0x00000,
+0x00000, // 50
+0x00000,
+0x00000,
+0x1c617,
+0x00000,
+0x1c615,
+0x1c613,
+0x00000,
+0x00000,
+0x00000,
+0x00000, // 60
+0x1c80f,
+0x1c90f,
+0x1c90f,
+0x1ca0f,
+0x1ca0d,
+0x1cb0d,
+0x00000,
+0x00000,
+0x00000,
+0x00000, // 70
+0x1d00d,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000,
+0x00000
+};
+#endif
+
+static void
+ar9300_aic_gain_table(struct ath_hal *ah)
+{
+ u_int32_t aic_atten_word[19], i;
+
+ /* Program gain table */
+ aic_atten_word[0] = (0x1 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x0 & 0xf)<<5 |
+ (0x1f & 0x1f); // -01 dB: 4'd1, 5'd31, 00 dB: 4'd0, 5'd31;
+ aic_atten_word[1] = (0x3 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0x1f & 0x1f); // -03 dB: 4'd3, 5'd31, -02 dB: 4'd2, 5'd31;
+ aic_atten_word[2] = (0x5 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0x1f & 0x1f); // -05 dB: 4'd5, 5'd31, -04 dB: 4'd4, 5'd31;
+ aic_atten_word[3] = (0x1 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x0 & 0xf)<<5 |
+ (0x1e & 0x1f); // -07 dB: 4'd1, 5'd30, -06 dB: 4'd0, 5'd30;
+ aic_atten_word[4] = (0x3 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0x1e & 0x1f); // -09 dB: 4'd3, 5'd30, -08 dB: 4'd2, 5'd30;
+ aic_atten_word[5] = (0x5 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0x1e & 0x1f); // -11 dB: 4'd5, 5'd30, -10 dB: 4'd4, 5'd30;
+ aic_atten_word[6] = (0x1 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x0 & 0xf)<<5 |
+ (0xf & 0x1f); // -13 dB: 4'd1, 5'd15, -12 dB: 4'd0, 5'd15;
+ aic_atten_word[7] = (0x3 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0xf & 0x1f); // -15 dB: 4'd3, 5'd15, -14 dB: 4'd2, 5'd15;
+ aic_atten_word[8] = (0x5 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0xf & 0x1f); // -17 dB: 4'd5, 5'd15, -16 dB: 4'd4, 5'd15;
+ aic_atten_word[9] = (0x1 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x0 & 0xf)<<5 |
+ (0x7 & 0x1f); // -19 dB: 4'd1, 5'd07, -18 dB: 4'd0, 5'd07;
+ aic_atten_word[10] =(0x3 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0x7 & 0x1f); // -21 dB: 4'd3, 5'd07, -20 dB: 4'd2, 5'd07;
+ aic_atten_word[11] =(0x5 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0x7 & 0x1f); // -23 dB: 4'd5, 5'd07, -22 dB: 4'd4, 5'd07;
+ aic_atten_word[12] =(0x7 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x6 & 0xf)<<5 |
+ (0x7 & 0x1f); // -25 dB: 4'd7, 5'd07, -24 dB: 4'd6, 5'd07;
+ aic_atten_word[13] =(0x3 & 0xf)<<14 | (0x3 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0x3 & 0x1f); // -27 dB: 4'd3, 5'd03, -26 dB: 4'd2, 5'd03;
+ aic_atten_word[14] =(0x5 & 0xf)<<14 | (0x3 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0x3 & 0x1f); // -29 dB: 4'd5, 5'd03, -28 dB: 4'd4, 5'd03;
+ aic_atten_word[15] =(0x1 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x0 & 0xf)<<5 |
+ (0x1 & 0x1f); // -31 dB: 4'd1, 5'd01, -30 dB: 4'd0, 5'd01;
+ aic_atten_word[16] =(0x3 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
+ (0x1 & 0x1f); // -33 dB: 4'd3, 5'd01, -32 dB: 4'd2, 5'd01;
+ aic_atten_word[17] =(0x5 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
+ (0x1 & 0x1f); // -35 dB: 4'd5, 5'd01, -34 dB: 4'd4, 5'd01;
+ aic_atten_word[18] =(0x7 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x6 & 0xf)<<5 |
+ (0x1 & 0x1f); // -37 dB: 4'd7, 5'd01, -36 dB: 4'd6, 5'd01;
+
+ /* Write to Gain table with auto increment enabled. */
+ OS_REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000),
+ (ATH_AIC_SRAM_AUTO_INCREMENT |
+ ATH_AIC_SRAM_GAIN_TABLE_OFFSET));
+
+ for (i = 0; i < 19; i++) {
+ OS_REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000),
+ aic_atten_word[i]);
+ }
+
+}
+
+static int16_t
+ar9300_aic_find_valid (struct ath_aic_sram_info *cal_sram,
+ HAL_BOOL dir,
+ u_int8_t index)
+{
+ int16_t i;
+
+ if (dir) {
+ /* search forward */
+ for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ if (cal_sram[i].valid) {
+ break;
+ }
+ }
+ }
+ else {
+ /* search backword */
+ for (i = index - 1; i >= 0; i--) {
+ if (cal_sram[i].valid) {
+ break;
+ }
+ }
+ }
+ if ((i >= ATH_AIC_MAX_BT_CHANNEL) || (i < 0)) {
+ i = -1;
+ }
+
+ return i;
+}
+
+static int16_t
+ar9300_aic_find_index (u_int8_t type, int16_t value)
+{
+ int16_t i = -1;
+
+ /*
+ * type 0: aic_lin_table, 1: com_att_db_table
+ */
+
+ if (type == 0) {
+ /* Find in aic_lin_table */
+ for (i = ATH_AIC_MAX_AIC_LIN_TABLE - 1; i >= 0; i--) {
+ if (aic_lin_table[i] >= value) {
+ break;
+ }
+ }
+ }
+ else if (type == 1) {
+ /* find in com_att_db_table */
+ for (i = 0; i < ATH_AIC_MAX_COM_ATT_DB_TABLE; i++) {
+ if (com_att_db_table[i] > value) {
+ i--;
+ break;
+ }
+ }
+ if (i >= ATH_AIC_MAX_COM_ATT_DB_TABLE) {
+ i = -1;
+ }
+ }
+
+ return i;
+}
+
+static HAL_BOOL
+ar9300_aic_cal_post_process (struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ath_aic_sram_info cal_sram[ATH_AIC_MAX_BT_CHANNEL];
+ struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL];
+ u_int32_t dir_path_gain_idx, quad_path_gain_idx, value;
+ u_int32_t fixed_com_att_db;
+ int8_t dir_path_sign, quad_path_sign;
+ int16_t i;
+ HAL_BOOL ret = AH_TRUE;
+
+ /* Read CAL_SRAM and get valid values. */
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) CAL_SRAM:\n");
+
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1,
+ (ATH_AIC_SRAM_CAL_OFFSET + i*4));
+#if ATH_AIC_TEST_PATTERN
+ value = aic_test_pattern[i];
+#else
+ value = OS_REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1);
+#endif
+ cal_sram[i].valid = MS(value, AR_PHY_AIC_SRAM_VALID);
+ cal_sram[i].rot_quad_att_db = MS(value,
+ AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB);
+ cal_sram[i].vga_quad_sign = MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN);
+ cal_sram[i].rot_dir_att_db = MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB);
+ cal_sram[i].vga_dir_sign = MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN);
+ cal_sram[i].com_att_6db = MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB);
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) %2d %2d %2d %2d %2d %2d %2d 0x%05x\n",
+ i, cal_sram[i].vga_quad_sign,
+ cal_sram[i].vga_dir_sign,
+ cal_sram[i].rot_dir_att_db,
+ cal_sram[i].rot_quad_att_db,
+ cal_sram[i].com_att_6db,
+ cal_sram[i].valid,
+ value);
+
+ if (cal_sram[i].valid) {
+ dir_path_gain_idx = cal_sram[i].rot_dir_att_db +
+ com_att_db_table[cal_sram[i].com_att_6db];
+ quad_path_gain_idx = cal_sram[i].rot_quad_att_db +
+ com_att_db_table[cal_sram[i].com_att_6db];
+ dir_path_sign = (cal_sram[i].vga_dir_sign) ? 1 : -1;
+ quad_path_sign = (cal_sram[i].vga_quad_sign) ? 1 : -1;
+ aic_sram[i].dir_path_gain_lin = dir_path_sign *
+ aic_lin_table[dir_path_gain_idx];
+ aic_sram[i].quad_path_gain_lin = quad_path_sign *
+ aic_lin_table[quad_path_gain_idx];
+ }
+ }
+
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ int16_t start_idx, end_idx;
+
+ if (cal_sram[i].valid) {
+ continue;
+ }
+
+ start_idx = ar9300_aic_find_valid(cal_sram, 0, i);
+ end_idx = ar9300_aic_find_valid(cal_sram, 1, i);
+
+ if (start_idx < 0)
+ {
+ /* extrapolation */
+ start_idx = end_idx;
+ end_idx = ar9300_aic_find_valid(cal_sram, 1, start_idx);
+
+ if (end_idx < 0) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) Error (1): i = %d, start_idx = %d \n",
+ i, start_idx);
+ ret = AH_FALSE;
+ break;
+ }
+ aic_sram[i].dir_path_gain_lin =
+ ((aic_sram[start_idx].dir_path_gain_lin -
+ aic_sram[end_idx].dir_path_gain_lin) *
+ (start_idx - i) + ((end_idx - i) >> 1)) /
+ (end_idx - i) +
+ aic_sram[start_idx].dir_path_gain_lin;
+ aic_sram[i].quad_path_gain_lin =
+ ((aic_sram[start_idx].quad_path_gain_lin -
+ aic_sram[end_idx].quad_path_gain_lin) *
+ (start_idx - i) + ((end_idx - i) >> 1)) /
+ (end_idx - i) +
+ aic_sram[start_idx].quad_path_gain_lin;
+ }
+ if (end_idx < 0)
+ {
+ /* extrapolation */
+ end_idx = ar9300_aic_find_valid(cal_sram, 0, start_idx);
+
+ if (end_idx < 0) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) Error (2): i = %d, start_idx = %d\n",
+ i, start_idx);
+ ret = AH_FALSE;
+ break;
+ }
+ aic_sram[i].dir_path_gain_lin =
+ ((aic_sram[start_idx].dir_path_gain_lin -
+ aic_sram[end_idx].dir_path_gain_lin) *
+ (i - start_idx) + ((start_idx - end_idx) >> 1)) /
+ (start_idx - end_idx) +
+ aic_sram[start_idx].dir_path_gain_lin;
+ aic_sram[i].quad_path_gain_lin =
+ ((aic_sram[start_idx].quad_path_gain_lin -
+ aic_sram[end_idx].quad_path_gain_lin) *
+ (i - start_idx) + ((start_idx - end_idx) >> 1)) /
+ (start_idx - end_idx) +
+ aic_sram[start_idx].quad_path_gain_lin;
+
+ }
+ else {
+ /* interpolation */
+ aic_sram[i].dir_path_gain_lin =
+ (((end_idx - i) * aic_sram[start_idx].dir_path_gain_lin) +
+ ((i - start_idx) * aic_sram[end_idx].dir_path_gain_lin) +
+ ((end_idx - start_idx) >> 1)) /
+ (end_idx - start_idx);
+ aic_sram[i].quad_path_gain_lin =
+ (((end_idx - i) * aic_sram[start_idx].quad_path_gain_lin) +
+ ((i - start_idx) * aic_sram[end_idx].quad_path_gain_lin) +
+ ((end_idx - start_idx) >> 1))/
+ (end_idx - start_idx);
+ }
+ }
+
+ /* From dir/quad_path_gain_lin to sram. */
+ i = ar9300_aic_find_valid(cal_sram, 1, 0);
+ if (i < 0) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) Error (3): can't find valid. Force it to 0.\n");
+ i = 0;
+ ret = AH_FALSE;
+ }
+ fixed_com_att_db = com_att_db_table[cal_sram[i].com_att_6db];
+
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ int16_t rot_dir_path_att_db, rot_quad_path_att_db;
+
+ aic_sram[i].sram.vga_dir_sign = (aic_sram[i].dir_path_gain_lin >= 0)
+ ? 1 : 0;
+ aic_sram[i].sram.vga_quad_sign= (aic_sram[i].quad_path_gain_lin >= 0)
+ ? 1 : 0;
+
+ rot_dir_path_att_db =
+ ar9300_aic_find_index(0, abs(aic_sram[i].dir_path_gain_lin)) -
+ fixed_com_att_db;
+ rot_quad_path_att_db =
+ ar9300_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) -
+ fixed_com_att_db;
+
+ aic_sram[i].sram.com_att_6db = ar9300_aic_find_index(1,
+ fixed_com_att_db);
+
+ aic_sram[i].sram.valid = 1;
+ aic_sram[i].sram.rot_dir_att_db =
+ MIN(MAX(rot_dir_path_att_db, ATH_AIC_MIN_ROT_DIR_ATT_DB),
+ ATH_AIC_MAX_ROT_DIR_ATT_DB);
+ aic_sram[i].sram.rot_quad_att_db =
+ MIN(MAX(rot_quad_path_att_db, ATH_AIC_MIN_ROT_QUAD_ATT_DB),
+ ATH_AIC_MAX_ROT_QUAD_ATT_DB);
+ }
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Post processing results:\n");
+
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ ahp->ah_aic_sram[i] = (SM(aic_sram[i].sram.vga_dir_sign,
+ AR_PHY_AIC_SRAM_VGA_DIR_SIGN) |
+ SM(aic_sram[i].sram.vga_quad_sign,
+ AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) |
+ SM(aic_sram[i].sram.com_att_6db,
+ AR_PHY_AIC_SRAM_COM_ATT_6DB) |
+ SM(aic_sram[i].sram.valid,
+ AR_PHY_AIC_SRAM_VALID) |
+ SM(aic_sram[i].sram.rot_dir_att_db,
+ AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) |
+ SM(aic_sram[i].sram.rot_quad_att_db,
+ AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB));
+
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) ch%02d 0x%05x %2d %2d %2d %2d %2d %2d %d %d\n",
+ i,
+ ahp->ah_aic_sram[i],
+ aic_sram[i].sram.vga_quad_sign,
+ aic_sram[i].sram.vga_dir_sign,
+ aic_sram[i].sram.rot_dir_att_db,
+ aic_sram[i].sram.rot_quad_att_db,
+ aic_sram[i].sram.com_att_6db,
+ aic_sram[i].sram.valid,
+ aic_sram[i].dir_path_gain_lin,
+ aic_sram[i].quad_path_gain_lin);
+ }
+
+ return ret;
+}
+
+u_int32_t
+ar9300_aic_calibration(struct ath_hal *ah)
+{
+ u_int32_t aic_ctrl_b0[5], aic_ctrl_b1[5];
+ u_int32_t aic_stat_b0[2], aic_stat_b1[2];
+ u_int32_t aic_stat, value;
+ u_int32_t i, cal_count = ATH_AIC_MAX_CAL_COUNT;
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ if (AR_SREV_JUPITER_10(ah)) {
+ aic_ctrl_b0[0] = AR_PHY_AIC_CTRL_0_B0_10;
+ aic_ctrl_b0[1] = AR_PHY_AIC_CTRL_1_B0_10;
+ aic_ctrl_b0[2] = AR_PHY_AIC_CTRL_2_B0_10;
+ aic_ctrl_b0[3] = AR_PHY_AIC_CTRL_3_B0_10;
+ aic_ctrl_b1[0] = AR_PHY_AIC_CTRL_0_B1_10;
+ aic_ctrl_b1[1] = AR_PHY_AIC_CTRL_1_B1_10;
+ aic_stat_b0[0] = AR_PHY_AIC_STAT_0_B0_10;
+ aic_stat_b0[1] = AR_PHY_AIC_STAT_1_B0_10;
+ aic_stat_b1[0] = AR_PHY_AIC_STAT_0_B1_10;
+ aic_stat_b1[1] = AR_PHY_AIC_STAT_1_B1_10;
+ }
+ else {
+ aic_ctrl_b0[0] = AR_PHY_AIC_CTRL_0_B0_20;
+ aic_ctrl_b0[1] = AR_PHY_AIC_CTRL_1_B0_20;
+ aic_ctrl_b0[2] = AR_PHY_AIC_CTRL_2_B0_20;
+ aic_ctrl_b0[3] = AR_PHY_AIC_CTRL_3_B0_20;
+ aic_ctrl_b0[4] = AR_PHY_AIC_CTRL_4_B0_20;
+ aic_ctrl_b1[0] = AR_PHY_AIC_CTRL_0_B1_20;
+ aic_ctrl_b1[1] = AR_PHY_AIC_CTRL_1_B1_20;
+ aic_ctrl_b1[4] = AR_PHY_AIC_CTRL_4_B1_20;
+ aic_stat_b0[0] = AR_PHY_AIC_STAT_0_B0_20;
+ aic_stat_b0[1] = AR_PHY_AIC_STAT_1_B0_20;
+ aic_stat_b1[0] = AR_PHY_AIC_STAT_0_B1_20;
+ aic_stat_b1[1] = AR_PHY_AIC_STAT_1_B1_20;
+ }
+
+ /* Config LNA gain difference */
+ OS_REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x22180600);
+ OS_REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x52443a2e);
+
+ OS_REG_WRITE(ah, aic_ctrl_b0[0],
+ (SM(0, AR_PHY_AIC_MON_ENABLE) |
+ SM(40, AR_PHY_AIC_CAL_MAX_HOP_COUNT) |
+ SM(1, AR_PHY_AIC_CAL_MIN_VALID_COUNT) | //26
+ SM(37, AR_PHY_AIC_F_WLAN) |
+ SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
+ SM(0, AR_PHY_AIC_CAL_ENABLE) |
+ SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
+ SM(0, AR_PHY_AIC_ENABLE)));
+
+ OS_REG_WRITE(ah, aic_ctrl_b1[0],
+ (SM(0, AR_PHY_AIC_MON_ENABLE) |
+ SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
+ SM(0, AR_PHY_AIC_CAL_ENABLE) |
+ SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
+ SM(0, AR_PHY_AIC_ENABLE)));
+
+ OS_REG_WRITE(ah, aic_ctrl_b0[1],
+ (SM(8, AR_PHY_AIC_CAL_BT_REF_DELAY) |
+ SM(6, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
+ SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
+ SM(0, AR_PHY_AIC_BT_IDLE_CFG) |
+ SM(1, AR_PHY_AIC_STDBY_COND) |
+ SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) |
+ SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) |
+ SM(15, AR_PHY_AIC_RSSI_MAX) |
+ SM(0, AR_PHY_AIC_RSSI_MIN)));
+
+ OS_REG_WRITE(ah, aic_ctrl_b1[1],
+ (SM(6, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
+ SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
+ SM(15, AR_PHY_AIC_RSSI_MAX) |
+ SM(0, AR_PHY_AIC_RSSI_MIN)));
+
+ OS_REG_WRITE(ah, aic_ctrl_b0[2],
+ (SM(44, AR_PHY_AIC_RADIO_DELAY) |
+ SM(7, AR_PHY_AIC_CAL_STEP_SIZE_CORR) |
+ SM(12, AR_PHY_AIC_CAL_ROT_IDX_CORR) |
+ SM(2, AR_PHY_AIC_CAL_CONV_CHECK_FACTOR) |
+ SM(5, AR_PHY_AIC_ROT_IDX_COUNT_MAX) |
+ SM(1, AR_PHY_AIC_CAL_SYNTH_TOGGLE) |
+ SM(1, AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX) |
+ SM(200, AR_PHY_AIC_CAL_SYNTH_SETTLING)));
+
+ OS_REG_WRITE(ah, aic_ctrl_b0[3],
+ (SM(20, AR_PHY_AIC_MON_MAX_HOP_COUNT) |
+ SM(10, AR_PHY_AIC_MON_MIN_STALE_COUNT) |
+ SM(1, AR_PHY_AIC_MON_PWR_EST_LONG) |
+ SM(2, AR_PHY_AIC_MON_PD_TALLY_SCALING) |
+ SM(18, AR_PHY_AIC_MON_PERF_THR) |
+ SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED) |
+ SM(2, AR_PHY_AIC_CAL_TARGET_MAG_SETTING) |
+ SM(3, AR_PHY_AIC_CAL_PERF_CHECK_FACTOR) |
+ SM(1, AR_PHY_AIC_CAL_PWR_EST_LONG)));
+
+ ar9300_aic_gain_table(ah);
+
+ /* Need to enable AIC reference signal in BT modem. */
+ OS_REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
+ (OS_REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) |
+ ATH_AIC_BT_AIC_ENABLE));
+
+ while (cal_count)
+ {
+ /* Start calibration */
+ OS_REG_CLR_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_ENABLE);
+ OS_REG_SET_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_CH_VALID_RESET);
+ OS_REG_SET_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_ENABLE);
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Start calibration #%d\n",
+ (ATH_AIC_MAX_CAL_COUNT - cal_count));
+
+ /* Wait until calibration is completed. */
+ for (i = 0; i < 10000; i++) {
+ /*
+ * Use AR_PHY_AIC_CAL_ENABLE bit instead of AR_PHY_AIC_CAL_DONE.
+ * Sometimes CAL_DONE bit is not asserted.
+ */
+ if ((OS_REG_READ(ah, aic_ctrl_b1[0]) & AR_PHY_AIC_CAL_ENABLE) == 0)
+ {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Cal is done at #%d\n", i);
+ break;
+ }
+ OS_DELAY(1);
+ }
+
+ /* print out status registers */
+ aic_stat = OS_REG_READ(ah, aic_stat_b1[0]);
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) CAL_DONE = %d, CAL_ACTIVE = %d, MEAS_COUNT = %d\n",
+ MS(aic_stat, AR_PHY_AIC_CAL_DONE),
+ MS(aic_stat, AR_PHY_AIC_CAL_ACTIVE),
+ MS(aic_stat, AR_PHY_AIC_MEAS_COUNT));
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) ANT_ISO = %d, HOP_COUNT = %d, VALID_COUNT = %d\n",
+ MS(aic_stat, AR_PHY_AIC_CAL_ANT_ISO_EST),
+ MS(aic_stat, AR_PHY_AIC_CAL_HOP_COUNT),
+ MS(aic_stat, AR_PHY_AIC_CAL_VALID_COUNT));
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) BT_WEAK = %d, BT_STRONG = %d, , \n",
+ MS(aic_stat, AR_PHY_AIC_CAL_BT_TOO_WEAK_ERR),
+ MS(aic_stat, AR_PHY_AIC_CAL_BT_TOO_STRONG_ERR));
+
+ aic_stat = OS_REG_READ(ah, aic_stat_b1[1]);
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) MEAS_MAG_MIN = %d, CAL_AIC_SM = %d, AIC_SM = %d\n",
+ MS(aic_stat, AR_PHY_AIC_MEAS_MAG_MIN),
+ MS(aic_stat, AR_PHY_AIC_CAL_AIC_SM),
+ MS(aic_stat, AR_PHY_AIC_SM));
+
+ if (i >= 10000) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Calibration failed.\n");
+ break;
+ }
+
+ /* print out calibration result */
+ if (MS(aic_stat, AR_PHY_AIC_MEAS_MAG_MIN) < ATH_AIC_MEAS_MAG_THRESH) {
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1,
+ (ATH_AIC_SRAM_CAL_OFFSET + i*4));
+ value = OS_REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1);
+ if (value & 0x01) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(AIC) BT chan %02d: 0x%08x\n", i, value);
+ }
+ }
+ break;
+ }
+ cal_count--;
+ }
+
+ if (!cal_count) {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Calibration failed2.\n");
+ }
+
+ /* Disable AIC reference signal in BT modem. */
+ OS_REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
+ (OS_REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) &
+ ~ATH_AIC_BT_AIC_ENABLE));
+
+ ahp->ah_aic_enabled = ar9300_aic_cal_post_process(ah) ? AH_TRUE : AH_FALSE;
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) ah_aic_enable = %d\n",
+ ahp->ah_aic_enabled);
+ return 0;
+}
+
+
+u_int32_t
+ar9300_aic_start_normal (struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ u_int32_t aic_ctrl0_b1, aic_ctrl1_b0, aic_ctrl1_b1;
+ int16_t i;
+
+ /* Config LNA gain difference */
+ OS_REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x22180600);
+ OS_REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x52443a2e);
+
+ ar9300_aic_gain_table(ah);
+
+ OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1, ATH_AIC_SRAM_AUTO_INCREMENT);
+
+ for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
+ OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_DATA_B1, ahp->ah_aic_sram[i]);
+ }
+
+ if (AR_SREV_JUPITER_10(ah)) {
+ aic_ctrl0_b1 = AR_PHY_AIC_CTRL_0_B1_10;
+ aic_ctrl1_b0 = AR_PHY_AIC_CTRL_1_B0_10;
+ aic_ctrl1_b1 = AR_PHY_AIC_CTRL_1_B1_10;
+ }
+ else {
+ aic_ctrl0_b1 = AR_PHY_AIC_CTRL_0_B1_20;
+ aic_ctrl1_b0 = AR_PHY_AIC_CTRL_1_B0_20;
+ aic_ctrl1_b1 = AR_PHY_AIC_CTRL_1_B1_20;
+ }
+
+ OS_REG_WRITE(ah, aic_ctrl1_b0,
+ (SM(0, AR_PHY_AIC_BT_IDLE_CFG) |
+ SM(1, AR_PHY_AIC_STDBY_COND) |
+ SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) |
+ SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) |
+ SM(15, AR_PHY_AIC_RSSI_MAX) |
+ SM(0, AR_PHY_AIC_RSSI_MIN)));
+
+ OS_REG_WRITE(ah, aic_ctrl1_b1,
+ (SM(15, AR_PHY_AIC_RSSI_MAX) |
+ SM(0, AR_PHY_AIC_RSSI_MIN)));
+
+ OS_REG_WRITE(ah, aic_ctrl0_b1,
+ (SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
+ SM(1, AR_PHY_AIC_ENABLE)));
+
+ ahp->ah_aic_enabled = AH_TRUE;
+
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Start normal operation mode.\n");
+ return 0;
+}
+#endif
+
+#endif
+
+
diff --git a/hal/ar9300/ar9300_ani.c b/hal/ar9300/ar9300_ani.c
new file mode 100644
index 000000000000..e23841d54fe4
--- /dev/null
+++ b/hal/ar9300/ar9300_ani.c
@@ -0,0 +1,1277 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_desc.h"
+#include "ah_pktlog.h"
+
+#include "ar9300/ar9300.h"
+#include "ar9300/ar9300reg.h"
+#include "ar9300/ar9300phy.h"
+
+extern void ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits);
+extern u_int32_t ar9300_get_rx_filter(struct ath_hal *ah);
+
+#define HAL_ANI_DEBUG 0
+
+/*
+ * Anti noise immunity support. We track phy errors and react
+ * to excessive errors by adjusting the noise immunity parameters.
+ */
+
+/******************************************************************************
+ *
+ * New Ani Algorithm for Station side only
+ *
+ *****************************************************************************/
+
+#define HAL_ANI_OFDM_TRIG_HIGH 1000 /* units are errors per second */
+#define HAL_ANI_OFDM_TRIG_LOW 400 /* units are errors per second */
+#define HAL_ANI_CCK_TRIG_HIGH 600 /* units are errors per second */
+#define HAL_ANI_CCK_TRIG_LOW 300 /* units are errors per second */
+#define HAL_ANI_USE_OFDM_WEAK_SIG true
+#define HAL_ANI_ENABLE_MRC_CCK AH_TRUE /* default is enabled */
+#define HAL_ANI_DEF_SPUR_IMMUNE_LVL 3
+#define HAL_ANI_DEF_FIRSTEP_LVL 2
+#define HAL_ANI_RSSI_THR_HIGH 40
+#define HAL_ANI_RSSI_THR_LOW 7
+#define HAL_ANI_PERIOD 1000
+
+#define HAL_NOISE_DETECT_PERIOD 100
+#define HAL_NOISE_RECOVER_PERIOD 5000
+
+#define HAL_SIG_FIRSTEP_SETTING_MIN 0
+#define HAL_SIG_FIRSTEP_SETTING_MAX 20
+#define HAL_SIG_SPUR_IMM_SETTING_MIN 0
+#define HAL_SIG_SPUR_IMM_SETTING_MAX 22
+
+#define HAL_EP_RND(x, mul) \
+ ((((x) % (mul)) >= ((mul) / 2)) ? ((x) + ((mul) - 1)) / (mul) : (x) / (mul))
+#define BEACON_RSSI(ahp) \
+ HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
+ HAL_RSSI_EP_MULTIPLIER)
+
+typedef int TABLE[];
+/*
+ * level: 0 1 2 3 4 5 6 7 8
+ * firstep_table: lvl 0-8, default 2
+ */
+static const TABLE firstep_table = { -4, -2, 0, 2, 4, 6, 8, 10, 12};
+/* cycpwr_thr1_table: lvl 0-7, default 3 */
+static const TABLE cycpwr_thr1_table = { -6, -4, -2, 0, 2, 4, 6, 8 };
+/* values here are relative to the INI */
+
+typedef struct _HAL_ANI_OFDM_LEVEL_ENTRY {
+ int spur_immunity_level;
+ int fir_step_level;
+ int ofdm_weak_signal_on;
+} HAL_ANI_OFDM_LEVEL_ENTRY;
+static const HAL_ANI_OFDM_LEVEL_ENTRY ofdm_level_table[] = {
+/* SI FS WS */
+ { 0, 0, 1 }, /* lvl 0 */
+ { 1, 1, 1 }, /* lvl 1 */
+ { 2, 2, 1 }, /* lvl 2 */
+ { 3, 2, 1 }, /* lvl 3 (default) */
+ { 4, 3, 1 }, /* lvl 4 */
+ { 5, 4, 1 }, /* lvl 5 */
+ { 6, 5, 1 }, /* lvl 6 */
+ { 7, 6, 1 }, /* lvl 7 */
+ { 7, 7, 1 }, /* lvl 8 */
+ { 7, 8, 0 } /* lvl 9 */
+};
+#define HAL_ANI_OFDM_NUM_LEVEL \
+ (sizeof(ofdm_level_table) / sizeof(ofdm_level_table[0]))
+#define HAL_ANI_OFDM_MAX_LEVEL (HAL_ANI_OFDM_NUM_LEVEL - 1)
+#define HAL_ANI_OFDM_DEF_LEVEL 3 /* default level - matches the INI settings */
+
+typedef struct _HAL_ANI_CCK_LEVEL_ENTRY {
+ int fir_step_level;
+ int mrc_cck_on;
+} HAL_ANI_CCK_LEVEL_ENTRY;
+
+static const HAL_ANI_CCK_LEVEL_ENTRY cck_level_table[] = {
+/* FS MRC-CCK */
+ { 0, 1 }, /* lvl 0 */
+ { 1, 1 }, /* lvl 1 */
+ { 2, 1 }, /* lvl 2 (default) */
+ { 3, 1 }, /* lvl 3 */
+ { 4, 0 }, /* lvl 4 */
+ { 5, 0 }, /* lvl 5 */
+ { 6, 0 }, /* lvl 6 */
+ { 7, 0 }, /* lvl 7 (only for high rssi) */
+ { 8, 0 } /* lvl 8 (only for high rssi) */
+};
+#define HAL_ANI_CCK_NUM_LEVEL \
+ (sizeof(cck_level_table) / sizeof(cck_level_table[0]))
+#define HAL_ANI_CCK_MAX_LEVEL (HAL_ANI_CCK_NUM_LEVEL - 1)
+#define HAL_ANI_CCK_MAX_LEVEL_LOW_RSSI (HAL_ANI_CCK_NUM_LEVEL - 3)
+#define HAL_ANI_CCK_DEF_LEVEL 2 /* default level - matches the INI settings */
+
+/*
+ * register values to turn OFDM weak signal detection OFF
+ */
+static const int m1_thresh_low_off = 127;
+static const int m2_thresh_low_off = 127;
+static const int m1_thresh_off = 127;
+static const int m2_thresh_off = 127;
+static const int m2_count_thr_off = 31;
+static const int m2_count_thr_low_off = 63;
+static const int m1_thresh_low_ext_off = 127;
+static const int m2_thresh_low_ext_off = 127;
+static const int m1_thresh_ext_off = 127;
+static const int m2_thresh_ext_off = 127;
+
+void
+ar9300_enable_mib_counters(struct ath_hal *ah)
+{
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Enable MIB counters\n", __func__);
+ /* Clear the mib counters and save them in the stats */
+ ar9300_update_mib_mac_stats(ah);
+
+ OS_REG_WRITE(ah, AR_FILT_OFDM, 0);
+ OS_REG_WRITE(ah, AR_FILT_CCK, 0);
+ OS_REG_WRITE(ah, AR_MIBC,
+ ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+}
+
+void
+ar9300_disable_mib_counters(struct ath_hal *ah)
+{
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Disabling MIB counters\n", __func__);
+
+ OS_REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
+
+ /* Clear the mib counters and save them in the stats */
+ ar9300_update_mib_mac_stats(ah);
+
+ OS_REG_WRITE(ah, AR_FILT_OFDM, 0);
+ OS_REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+
+/*
+ * This routine returns the index into the ani_state array that
+ * corresponds to the channel in *chan. If no match is found and the
+ * array is still not fully utilized, a new entry is created for the
+ * channel. We assume the attach function has already initialized the
+ * ah_ani values and only the channel field needs to be set.
+ */
+static int
+ar9300_get_ani_channel_index(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ int i;
+
+ for (i = 0; i < ARRAY_LENGTH(ahp->ah_ani); i++) {
+ if (ahp->ah_ani[i].c.channel == chan->channel) {
+ return i;
+ }
+ if (ahp->ah_ani[i].c.channel == 0) {
+ ahp->ah_ani[i].c.channel = chan->channel;
+ ahp->ah_ani[i].c.channel_flags = chan->channel_flags;
+ return i;
+ }
+ }
+ /* XXX statistic */
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: No more channel states left. Using channel 0\n", __func__);
+ return 0; /* XXX gotta return something valid */
+}
+
+/*
+ * Return the current ANI state of the channel we're on
+ */
+struct ar9300_ani_state *
+ar9300_ani_get_current_state(struct ath_hal *ah)
+{
+ return AH9300(ah)->ah_curani;
+}
+
+/*
+ * Return the current statistics.
+ */
+struct ar9300_stats *
+ar9300_ani_get_current_stats(struct ath_hal *ah)
+{
+ return &AH9300(ah)->ah_stats;
+}
+
+/*
+ * Setup ANI handling. Sets all thresholds and levels to default level AND
+ * resets the channel statistics
+ */
+
+void
+ar9300_ani_attach(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ int i;
+
+ OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
+ for (i = 0; i < ARRAY_LENGTH(ahp->ah_ani); i++) {
+ ahp->ah_ani[i].ofdm_trig_high = HAL_ANI_OFDM_TRIG_HIGH;
+ ahp->ah_ani[i].ofdm_trig_low = HAL_ANI_OFDM_TRIG_LOW;
+ ahp->ah_ani[i].cck_trig_high = HAL_ANI_CCK_TRIG_HIGH;
+ ahp->ah_ani[i].cck_trig_low = HAL_ANI_CCK_TRIG_LOW;
+ ahp->ah_ani[i].rssi_thr_high = HAL_ANI_RSSI_THR_HIGH;
+ ahp->ah_ani[i].rssi_thr_low = HAL_ANI_RSSI_THR_LOW;
+ ahp->ah_ani[i].ofdm_noise_immunity_level = HAL_ANI_OFDM_DEF_LEVEL;
+ ahp->ah_ani[i].cck_noise_immunity_level = HAL_ANI_CCK_DEF_LEVEL;
+ ahp->ah_ani[i].ofdm_weak_sig_detect_off = !HAL_ANI_USE_OFDM_WEAK_SIG;
+ ahp->ah_ani[i].spur_immunity_level = HAL_ANI_DEF_SPUR_IMMUNE_LVL;
+ ahp->ah_ani[i].firstep_level = HAL_ANI_DEF_FIRSTEP_LVL;
+ ahp->ah_ani[i].mrc_cck_off = !HAL_ANI_ENABLE_MRC_CCK;
+ ahp->ah_ani[i].ofdms_turn = AH_TRUE;
+ ahp->ah_ani[i].must_restore = AH_FALSE;
+ }
+
+ /*
+ * Since we expect some ongoing maintenance on the tables,
+ * let's sanity check here.
+ * The default level should not modify INI setting.
+ */
+ HALASSERT(firstep_table[HAL_ANI_DEF_FIRSTEP_LVL] == 0);
+ HALASSERT(cycpwr_thr1_table[HAL_ANI_DEF_SPUR_IMMUNE_LVL] == 0);
+ HALASSERT(
+ ofdm_level_table[HAL_ANI_OFDM_DEF_LEVEL].fir_step_level ==
+ HAL_ANI_DEF_FIRSTEP_LVL);
+ HALASSERT(
+ ofdm_level_table[HAL_ANI_OFDM_DEF_LEVEL].spur_immunity_level ==
+ HAL_ANI_DEF_SPUR_IMMUNE_LVL);
+ HALASSERT(
+ cck_level_table[HAL_ANI_CCK_DEF_LEVEL].fir_step_level ==
+ HAL_ANI_DEF_FIRSTEP_LVL);
+
+ /* Initialize and enable MIB Counters */
+ OS_REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ OS_REG_WRITE(ah, AR_PHY_ERR_2, 0);
+ ar9300_enable_mib_counters(ah);
+
+ ahp->ah_ani_period = HAL_ANI_PERIOD;
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_enable_ani) {
+ ahp->ah_proc_phy_err |= HAL_PROCESS_ANI;
+ }
+}
+
+/*
+ * Cleanup any ANI state setup.
+ */
+void
+ar9300_ani_detach(struct ath_hal *ah)
+{
+ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Detaching Ani\n", __func__);
+ ar9300_disable_mib_counters(ah);
+ OS_REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ OS_REG_WRITE(ah, AR_PHY_ERR_2, 0);
+}
+
+/*
+ * Initialize the ANI register values with default (ini) values.
+ * This routine is called during a (full) hardware reset after
+ * all the registers are initialised from the INI.
+ */
+void
+ar9300_ani_init_defaults(struct ath_hal *ah, HAL_HT_MACMODE macmode)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+ HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+ int index;
+ u_int32_t val;
+
+ HALASSERT(chan != AH_NULL);
+ index = ar9300_get_ani_channel_index(ah, chan);
+ ani_state = &ahp->ah_ani[index];
+ ahp->ah_curani = ani_state;
+
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ver %d.%d opmode %u chan %d Mhz/0x%x macmode %d\n",
+ __func__, AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev,
+ AH_PRIVATE(ah)->ah_opmode, chan->channel, chan->channel_flags, macmode);
+
+ val = OS_REG_READ(ah, AR_PHY_SFCORR);
+ ani_state->ini_def.m1_thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+ ani_state->ini_def.m2_thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
+ ani_state->ini_def.m2_count_thr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
+
+ val = OS_REG_READ(ah, AR_PHY_SFCORR_LOW);
+ ani_state->ini_def.m1_thresh_low =
+ MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
+ ani_state->ini_def.m2_thresh_low =
+ MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
+ ani_state->ini_def.m2_count_thr_low =
+ MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
+
+ val = OS_REG_READ(ah, AR_PHY_SFCORR_EXT);
+ ani_state->ini_def.m1_thresh_ext = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
+ ani_state->ini_def.m2_thresh_ext = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
+ ani_state->ini_def.m1_thresh_low_ext =
+ MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
+ ani_state->ini_def.m2_thresh_low_ext =
+ MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
+
+ ani_state->ini_def.firstep =
+ OS_REG_READ_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP);
+ ani_state->ini_def.firstep_low =
+ OS_REG_READ_FIELD(
+ ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW);
+ ani_state->ini_def.cycpwr_thr1 =
+ OS_REG_READ_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_CYCPWR_THR1);
+ ani_state->ini_def.cycpwr_thr1_ext =
+ OS_REG_READ_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CYCPWR_THR1);
+
+ /* these levels just got reset to defaults by the INI */
+ ani_state->spur_immunity_level = HAL_ANI_DEF_SPUR_IMMUNE_LVL;
+ ani_state->firstep_level = HAL_ANI_DEF_FIRSTEP_LVL;
+ ani_state->ofdm_weak_sig_detect_off = !HAL_ANI_USE_OFDM_WEAK_SIG;
+ ani_state->mrc_cck_off = !HAL_ANI_ENABLE_MRC_CCK;
+
+ ani_state->cycle_count = 0;
+}
+
+/*
+ * Set the ANI settings to match an OFDM level.
+ */
+static void
+ar9300_ani_set_odfm_noise_immunity_level(struct ath_hal *ah,
+ u_int8_t ofdm_noise_immunity_level)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state = ahp->ah_curani;
+
+ ani_state->rssi = BEACON_RSSI(ahp);
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "**** %s: ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", __func__,
+ ani_state->ofdm_noise_immunity_level, ofdm_noise_immunity_level,
+ ani_state->rssi, ani_state->rssi_thr_low, ani_state->rssi_thr_high);
+
+ ani_state->ofdm_noise_immunity_level = ofdm_noise_immunity_level;
+
+ if (ani_state->spur_immunity_level !=
+ ofdm_level_table[ofdm_noise_immunity_level].spur_immunity_level)
+ {
+ ar9300_ani_control(
+ ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+ ofdm_level_table[ofdm_noise_immunity_level].spur_immunity_level);
+ }
+
+ if (ani_state->firstep_level !=
+ ofdm_level_table[ofdm_noise_immunity_level].fir_step_level &&
+ ofdm_level_table[ofdm_noise_immunity_level].fir_step_level >=
+ cck_level_table[ani_state->cck_noise_immunity_level].fir_step_level)
+ {
+ ar9300_ani_control(
+ ah, HAL_ANI_FIRSTEP_LEVEL,
+ ofdm_level_table[ofdm_noise_immunity_level].fir_step_level);
+ }
+
+ if ((AH_PRIVATE(ah)->ah_opmode != HAL_M_STA ||
+ ani_state->rssi <= ani_state->rssi_thr_high))
+ {
+ if (ani_state->ofdm_weak_sig_detect_off) {
+ /*
+ * force on ofdm weak sig detect.
+ */
+ ar9300_ani_control(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_TRUE);
+ }
+ } else if (ani_state->ofdm_weak_sig_detect_off ==
+ ofdm_level_table[ofdm_noise_immunity_level].ofdm_weak_signal_on)
+ {
+ ar9300_ani_control(
+ ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ ofdm_level_table[ofdm_noise_immunity_level].ofdm_weak_signal_on);
+ }
+}
+
+/*
+ * Set the ANI settings to match a CCK level.
+ */
+static void
+ar9300_ani_set_cck_noise_immunity_level(struct ath_hal *ah,
+ u_int8_t cck_noise_immunity_level)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state = ahp->ah_curani;
+ int level;
+
+ ani_state->rssi = BEACON_RSSI(ahp);
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "**** %s: ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+ __func__, ani_state->cck_noise_immunity_level, cck_noise_immunity_level,
+ ani_state->rssi, ani_state->rssi_thr_low, ani_state->rssi_thr_high);
+
+ if (AH_PRIVATE(ah)->ah_opmode == HAL_M_STA &&
+ ani_state->rssi <= ani_state->rssi_thr_low &&
+ cck_noise_immunity_level > HAL_ANI_CCK_MAX_LEVEL_LOW_RSSI)
+ {
+ cck_noise_immunity_level = HAL_ANI_CCK_MAX_LEVEL_LOW_RSSI;
+ }
+
+ ani_state->cck_noise_immunity_level = cck_noise_immunity_level;
+
+ level = ani_state->ofdm_noise_immunity_level;
+ if (ani_state->firstep_level !=
+ cck_level_table[cck_noise_immunity_level].fir_step_level &&
+ cck_level_table[cck_noise_immunity_level].fir_step_level >=
+ ofdm_level_table[level].fir_step_level)
+ {
+ ar9300_ani_control(
+ ah, HAL_ANI_FIRSTEP_LEVEL,
+ cck_level_table[cck_noise_immunity_level].fir_step_level);
+ }
+
+ if (ani_state->mrc_cck_off ==
+ cck_level_table[cck_noise_immunity_level].mrc_cck_on)
+ {
+ ar9300_ani_control(
+ ah, HAL_ANI_MRC_CCK,
+ cck_level_table[cck_noise_immunity_level].mrc_cck_on);
+ }
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+HAL_BOOL
+ar9300_ani_control(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state = ahp->ah_curani;
+ HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+ int32_t value, value2;
+ u_int level = param;
+ u_int is_on;
+
+ if (chan == NULL && cmd != HAL_ANI_MODE) {
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: ignoring cmd 0x%02x - no channel\n", __func__, cmd);
+ return AH_FALSE;
+ }
+
+ switch (cmd & ahp->ah_ani_function) {
+ case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
+ {
+ int m1_thresh_low, m2_thresh_low;
+ int m1_thresh, m2_thresh;
+ int m2_count_thr, m2_count_thr_low;
+ int m1_thresh_low_ext, m2_thresh_low_ext;
+ int m1_thresh_ext, m2_thresh_ext;
+ /*
+ * is_on == 1 means ofdm weak signal detection is ON
+ * (default, less noise imm)
+ * is_on == 0 means ofdm weak signal detection is OFF
+ * (more noise imm)
+ */
+ is_on = param ? 1 : 0;
+
+ /*
+ * make register setting for default (weak sig detect ON)
+ * come from INI file
+ */
+ m1_thresh_low = is_on ?
+ ani_state->ini_def.m1_thresh_low : m1_thresh_low_off;
+ m2_thresh_low = is_on ?
+ ani_state->ini_def.m2_thresh_low : m2_thresh_low_off;
+ m1_thresh = is_on ?
+ ani_state->ini_def.m1_thresh : m1_thresh_off;
+ m2_thresh = is_on ?
+ ani_state->ini_def.m2_thresh : m2_thresh_off;
+ m2_count_thr = is_on ?
+ ani_state->ini_def.m2_count_thr : m2_count_thr_off;
+ m2_count_thr_low = is_on ?
+ ani_state->ini_def.m2_count_thr_low : m2_count_thr_low_off;
+ m1_thresh_low_ext = is_on ?
+ ani_state->ini_def.m1_thresh_low_ext : m1_thresh_low_ext_off;
+ m2_thresh_low_ext = is_on ?
+ ani_state->ini_def.m2_thresh_low_ext : m2_thresh_low_ext_off;
+ m1_thresh_ext = is_on ?
+ ani_state->ini_def.m1_thresh_ext : m1_thresh_ext_off;
+ m2_thresh_ext = is_on ?
+ ani_state->ini_def.m2_thresh_ext : m2_thresh_ext_off;
+ 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_ext);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2_thresh_low_ext);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH,
+ m1_thresh_ext);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH,
+ m2_thresh_ext);
+ if (is_on) {
+ 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);
+ }
+ if (!is_on != ani_state->ofdm_weak_sig_detect_off) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: ofdm weak signal: %s=>%s\n",
+ __func__, chan->channel,
+ !ani_state->ofdm_weak_sig_detect_off ? "on" : "off",
+ is_on ? "on" : "off");
+ if (is_on) {
+ ahp->ah_stats.ast_ani_ofdmon++;
+ } else {
+ ahp->ah_stats.ast_ani_ofdmoff++;
+ }
+ ani_state->ofdm_weak_sig_detect_off = !is_on;
+ }
+ break;
+ }
+ case HAL_ANI_FIRSTEP_LEVEL:
+ if (level >= ARRAY_LENGTH(firstep_table)) {
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: HAL_ANI_FIRSTEP_LEVEL level out of range (%u > %u)\n",
+ __func__, level, (unsigned) ARRAY_LENGTH(firstep_table));
+ return AH_FALSE;
+ }
+ /*
+ * make register setting relative to default
+ * from INI file & cap value
+ */
+ value =
+ firstep_table[level] -
+ firstep_table[HAL_ANI_DEF_FIRSTEP_LVL] +
+ ani_state->ini_def.firstep;
+ if (value < HAL_SIG_FIRSTEP_SETTING_MIN) {
+ value = HAL_SIG_FIRSTEP_SETTING_MIN;
+ }
+ if (value > HAL_SIG_FIRSTEP_SETTING_MAX) {
+ value = HAL_SIG_FIRSTEP_SETTING_MAX;
+ }
+ OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP, value);
+ /*
+ * we need to set first step low register too
+ * make register setting relative to default from INI file & cap value
+ */
+ value2 =
+ firstep_table[level] -
+ firstep_table[HAL_ANI_DEF_FIRSTEP_LVL] +
+ ani_state->ini_def.firstep_low;
+ if (value2 < HAL_SIG_FIRSTEP_SETTING_MIN) {
+ value2 = HAL_SIG_FIRSTEP_SETTING_MIN;
+ }
+ if (value2 > HAL_SIG_FIRSTEP_SETTING_MAX) {
+ value2 = HAL_SIG_FIRSTEP_SETTING_MAX;
+ }
+ OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
+
+ if (level != ani_state->firstep_level) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
+ __func__, chan->channel, ani_state->firstep_level, level,
+ HAL_ANI_DEF_FIRSTEP_LVL, value, ani_state->ini_def.firstep);
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: level %d=>%d[def:%d] "
+ "firstep_low[level]=%d ini=%d\n",
+ __func__, chan->channel, ani_state->firstep_level, level,
+ HAL_ANI_DEF_FIRSTEP_LVL, value2,
+ ani_state->ini_def.firstep_low);
+ if (level > ani_state->firstep_level) {
+ ahp->ah_stats.ast_ani_stepup++;
+ } else if (level < ani_state->firstep_level) {
+ ahp->ah_stats.ast_ani_stepdown++;
+ }
+ ani_state->firstep_level = level;
+ }
+ break;
+ case HAL_ANI_SPUR_IMMUNITY_LEVEL:
+ if (level >= ARRAY_LENGTH(cycpwr_thr1_table)) {
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL level "
+ "out of range (%u > %u)\n",
+ __func__, level, (unsigned) ARRAY_LENGTH(cycpwr_thr1_table));
+ return AH_FALSE;
+ }
+ /*
+ * make register setting relative to default from INI file & cap value
+ */
+ value =
+ cycpwr_thr1_table[level] -
+ cycpwr_thr1_table[HAL_ANI_DEF_SPUR_IMMUNE_LVL] +
+ ani_state->ini_def.cycpwr_thr1;
+ if (value < HAL_SIG_SPUR_IMM_SETTING_MIN) {
+ value = HAL_SIG_SPUR_IMM_SETTING_MIN;
+ }
+ if (value > HAL_SIG_SPUR_IMM_SETTING_MAX) {
+ value = HAL_SIG_SPUR_IMM_SETTING_MAX;
+ }
+ OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_CYCPWR_THR1, value);
+
+ /*
+ * set AR_PHY_EXT_CCA for extension channel
+ * make register setting relative to default from INI file & cap value
+ */
+ value2 =
+ cycpwr_thr1_table[level] -
+ cycpwr_thr1_table[HAL_ANI_DEF_SPUR_IMMUNE_LVL] +
+ ani_state->ini_def.cycpwr_thr1_ext;
+ if (value2 < HAL_SIG_SPUR_IMM_SETTING_MIN) {
+ value2 = HAL_SIG_SPUR_IMM_SETTING_MIN;
+ }
+ if (value2 > HAL_SIG_SPUR_IMM_SETTING_MAX) {
+ value2 = HAL_SIG_SPUR_IMM_SETTING_MAX;
+ }
+ OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CYCPWR_THR1, value2);
+
+ if (level != ani_state->spur_immunity_level) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: level %d=>%d[def:%d] "
+ "cycpwr_thr1[level]=%d ini=%d\n",
+ __func__, chan->channel, ani_state->spur_immunity_level, level,
+ HAL_ANI_DEF_SPUR_IMMUNE_LVL, value,
+ ani_state->ini_def.cycpwr_thr1);
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: level %d=>%d[def:%d] "
+ "cycpwr_thr1_ext[level]=%d ini=%d\n",
+ __func__, chan->channel, ani_state->spur_immunity_level, level,
+ HAL_ANI_DEF_SPUR_IMMUNE_LVL, value2,
+ ani_state->ini_def.cycpwr_thr1_ext);
+ if (level > ani_state->spur_immunity_level) {
+ ahp->ah_stats.ast_ani_spurup++;
+ } else if (level < ani_state->spur_immunity_level) {
+ ahp->ah_stats.ast_ani_spurdown++;
+ }
+ ani_state->spur_immunity_level = level;
+ }
+ break;
+ case HAL_ANI_MRC_CCK:
+ /*
+ * is_on == 1 means MRC CCK ON (default, less noise imm)
+ * is_on == 0 means MRC CCK is OFF (more noise imm)
+ */
+ is_on = param ? 1 : 0;
+ if (!AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+ AR_PHY_MRC_CCK_ENABLE, is_on);
+ OS_REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
+ AR_PHY_MRC_CCK_MUX_REG, is_on);
+ }
+ if (!is_on != ani_state->mrc_cck_off) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ** ch %d: MRC CCK: %s=>%s\n", __func__, chan->channel,
+ !ani_state->mrc_cck_off ? "on" : "off", is_on ? "on" : "off");
+ if (is_on) {
+ ahp->ah_stats.ast_ani_ccklow++;
+ } else {
+ ahp->ah_stats.ast_ani_cckhigh++;
+ }
+ ani_state->mrc_cck_off = !is_on;
+ }
+ break;
+ case HAL_ANI_PRESENT:
+ break;
+#ifdef AH_PRIVATE_DIAG
+ case HAL_ANI_MODE:
+ if (param == 0) {
+ ahp->ah_proc_phy_err &= ~HAL_PROCESS_ANI;
+ /* Turn off HW counters if we have them */
+ ar9300_ani_detach(ah);
+ if (AH_PRIVATE(ah)->ah_curchan == NULL) {
+ return AH_TRUE;
+ }
+ /* if we're turning off ANI, reset regs back to INI settings */
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_enable_ani) {
+ HAL_ANI_CMD savefunc = ahp->ah_ani_function;
+ /* temporarly allow all functions so we can reset */
+ ahp->ah_ani_function = HAL_ANI_ALL;
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: disable all ANI functions\n", __func__);
+ ar9300_ani_set_odfm_noise_immunity_level(
+ ah, HAL_ANI_OFDM_DEF_LEVEL);
+ ar9300_ani_set_cck_noise_immunity_level(
+ ah, HAL_ANI_CCK_DEF_LEVEL);
+ ahp->ah_ani_function = savefunc;
+ }
+ } else { /* normal/auto mode */
+ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: enabled\n", __func__);
+ ahp->ah_proc_phy_err |= HAL_PROCESS_ANI;
+ if (AH_PRIVATE(ah)->ah_curchan == NULL) {
+ return AH_TRUE;
+ }
+ ar9300_enable_mib_counters(ah);
+ ar9300_ani_reset(ah, AH_FALSE);
+ ani_state = ahp->ah_curani;
+ }
+ HALDEBUG(ah, HAL_DEBUG_ANI, "5 ANC: ahp->ah_proc_phy_err %x \n",
+ ahp->ah_proc_phy_err);
+ break;
+ case HAL_ANI_PHYERR_RESET:
+ ahp->ah_stats.ast_ani_ofdmerrs = 0;
+ ahp->ah_stats.ast_ani_cckerrs = 0;
+ break;
+#endif /* AH_PRIVATE_DIAG */
+ default:
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: invalid cmd 0x%02x (allowed=0x%02x)\n",
+ __func__, cmd, ahp->ah_ani_function);
+#endif
+ return AH_FALSE;
+ }
+
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: ANI parameters: SI=%d, ofdm_ws=%s FS=%d MRCcck=%s listen_time=%d "
+ "CC=%d listen=%d ofdm_errs=%d cck_errs=%d\n",
+ __func__, ani_state->spur_immunity_level,
+ !ani_state->ofdm_weak_sig_detect_off ? "on" : "off",
+ ani_state->firstep_level, !ani_state->mrc_cck_off ? "on" : "off",
+ ani_state->listen_time, ani_state->cycle_count,
+ ani_state->listen_time, ani_state->ofdm_phy_err_count,
+ ani_state->cck_phy_err_count);
+#endif
+
+#ifndef REMOVE_PKT_LOG
+ /* do pktlog */
+ {
+ struct log_ani log_data;
+
+ /* Populate the ani log record */
+ log_data.phy_stats_disable = DO_ANI(ah);
+ log_data.noise_immun_lvl = ani_state->ofdm_noise_immunity_level;
+ log_data.spur_immun_lvl = ani_state->spur_immunity_level;
+ log_data.ofdm_weak_det = ani_state->ofdm_weak_sig_detect_off;
+ log_data.cck_weak_thr = ani_state->cck_noise_immunity_level;
+ log_data.fir_lvl = ani_state->firstep_level;
+ log_data.listen_time = ani_state->listen_time;
+ log_data.cycle_count = ani_state->cycle_count;
+ /* express ofdm_phy_err_count as errors/second */
+ log_data.ofdm_phy_err_count = ani_state->listen_time ?
+ ani_state->ofdm_phy_err_count * 1000 / ani_state->listen_time : 0;
+ /* express cck_phy_err_count as errors/second */
+ log_data.cck_phy_err_count = ani_state->listen_time ?
+ ani_state->cck_phy_err_count * 1000 / ani_state->listen_time : 0;
+ log_data.rssi = ani_state->rssi;
+
+ /* clear interrupt context flag */
+ ath_hal_log_ani(AH_PRIVATE(ah)->ah_sc, &log_data, 0);
+ }
+#endif
+
+ return AH_TRUE;
+}
+
+static void
+ar9300_ani_restart(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+
+ if (!DO_ANI(ah)) {
+ return;
+ }
+
+ ani_state = ahp->ah_curani;
+
+ ani_state->listen_time = 0;
+
+ OS_REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ OS_REG_WRITE(ah, AR_PHY_ERR_2, 0);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ /* Clear the mib counters and save them in the stats */
+ ar9300_update_mib_mac_stats(ah);
+
+ ani_state->ofdm_phy_err_count = 0;
+ ani_state->cck_phy_err_count = 0;
+}
+
+static void
+ar9300_ani_ofdm_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+
+ if (!DO_ANI(ah)) {
+ return;
+ }
+
+ ani_state = ahp->ah_curani;
+
+ if (ani_state->ofdm_noise_immunity_level < HAL_ANI_OFDM_MAX_LEVEL) {
+ ar9300_ani_set_odfm_noise_immunity_level(
+ ah, ani_state->ofdm_noise_immunity_level + 1);
+ }
+}
+
+static void
+ar9300_ani_cck_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+
+ if (!DO_ANI(ah)) {
+ return;
+ }
+
+ ani_state = ahp->ah_curani;
+
+ if (ani_state->cck_noise_immunity_level < HAL_ANI_CCK_MAX_LEVEL) {
+ ar9300_ani_set_cck_noise_immunity_level(
+ ah, ani_state->cck_noise_immunity_level + 1);
+ }
+}
+
+/*
+ * Restore the ANI parameters in the HAL and reset the statistics.
+ * This routine should be called for every hardware reset and for
+ * every channel change.
+ */
+void
+ar9300_ani_reset(struct ath_hal *ah, HAL_BOOL is_scanning)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+ HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
+ int index;
+
+ HALASSERT(chan != AH_NULL);
+
+ if (!DO_ANI(ah)) {
+ return;
+ }
+
+ /*
+ * we need to re-point to the correct ANI state since the channel
+ * may have changed due to a fast channel change
+ */
+ index = ar9300_get_ani_channel_index(ah, chan);
+ ani_state = &ahp->ah_ani[index];
+ HALASSERT(ani_state != AH_NULL);
+ ahp->ah_curani = ani_state;
+
+ ahp->ah_stats.ast_ani_reset++;
+
+ ani_state->phy_noise_spur = 0;
+
+ /* only allow a subset of functions in AP mode */
+ if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ahp->ah_ani_function = (HAL_ANI_SPUR_IMMUNITY_LEVEL |
+ HAL_ANI_FIRSTEP_LEVEL |
+ HAL_ANI_MRC_CCK);
+ } else {
+ ahp->ah_ani_function = 0;
+ }
+ }
+ /* always allow mode (on/off) to be controlled */
+ ahp->ah_ani_function |= HAL_ANI_MODE;
+
+ if (is_scanning ||
+ (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA &&
+ AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS))
+ {
+ /*
+ * If we're scanning or in AP mode, the defaults (ini) should be
+ * in place.
+ * For an AP we assume the historical levels for this channel are
+ * probably outdated so start from defaults instead.
+ */
+ if (ani_state->ofdm_noise_immunity_level != HAL_ANI_OFDM_DEF_LEVEL ||
+ ani_state->cck_noise_immunity_level != HAL_ANI_CCK_DEF_LEVEL)
+ {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: Restore defaults: opmode %u chan %d Mhz/0x%x "
+ "is_scanning=%d restore=%d ofdm:%d cck:%d\n",
+ __func__, AH_PRIVATE(ah)->ah_opmode, chan->channel,
+ chan->channel_flags, is_scanning, ani_state->must_restore,
+ ani_state->ofdm_noise_immunity_level,
+ ani_state->cck_noise_immunity_level);
+ /*
+ * for STA/IBSS, we want to restore the historical values later
+ * (when we're not scanning)
+ */
+ if (AH_PRIVATE(ah)->ah_opmode == HAL_M_STA ||
+ AH_PRIVATE(ah)->ah_opmode == HAL_M_IBSS)
+ {
+ ar9300_ani_control(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
+ HAL_ANI_DEF_SPUR_IMMUNE_LVL);
+ ar9300_ani_control(
+ ah, HAL_ANI_FIRSTEP_LEVEL, HAL_ANI_DEF_FIRSTEP_LVL);
+ ar9300_ani_control(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ HAL_ANI_USE_OFDM_WEAK_SIG);
+ ar9300_ani_control(ah, HAL_ANI_MRC_CCK, HAL_ANI_ENABLE_MRC_CCK);
+ ani_state->must_restore = AH_TRUE;
+ } else {
+ ar9300_ani_set_odfm_noise_immunity_level(
+ ah, HAL_ANI_OFDM_DEF_LEVEL);
+ ar9300_ani_set_cck_noise_immunity_level(
+ ah, HAL_ANI_CCK_DEF_LEVEL);
+ }
+ }
+ } else {
+ /*
+ * restore historical levels for this channel
+ */
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d "
+ "restore=%d ofdm:%d cck:%d\n",
+ __func__, AH_PRIVATE(ah)->ah_opmode, chan->channel,
+ chan->channel_flags, is_scanning, ani_state->must_restore,
+ ani_state->ofdm_noise_immunity_level,
+ ani_state->cck_noise_immunity_level);
+ ar9300_ani_set_odfm_noise_immunity_level(
+ ah, ani_state->ofdm_noise_immunity_level);
+ ar9300_ani_set_cck_noise_immunity_level(
+ ah, ani_state->cck_noise_immunity_level);
+ ani_state->must_restore = AH_FALSE;
+ }
+
+ /* enable phy counters */
+ ar9300_ani_restart(ah);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+/*
+ * Process a MIB interrupt. We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void
+ar9300_process_mib_intr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ u_int32_t phy_cnt1, phy_cnt2;
+
+#if 0
+ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Processing Mib Intr\n", __func__);
+#endif
+
+ /* Reset these counters regardless */
+ OS_REG_WRITE(ah, AR_FILT_OFDM, 0);
+ OS_REG_WRITE(ah, AR_FILT_CCK, 0);
+ if (!(OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) {
+ OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+ }
+
+ /* Clear the mib counters and save them in the stats */
+ ar9300_update_mib_mac_stats(ah);
+ ahp->ah_stats.ast_nodestats = *stats;
+
+ if (!DO_ANI(ah)) {
+ /*
+ * We must always clear the interrupt cause by resetting
+ * the phy error regs.
+ */
+ OS_REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ OS_REG_WRITE(ah, AR_PHY_ERR_2, 0);
+ return;
+ }
+
+ /* NB: these are not reset-on-read */
+ phy_cnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
+ phy_cnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: Errors: OFDM=0x%08x-0x0=%d CCK=0x%08x-0x0=%d\n",
+ __func__, phy_cnt1, phy_cnt1, phy_cnt2, phy_cnt2);
+#endif
+ if (((phy_cnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+ ((phy_cnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+ /* NB: always restart to insure the h/w counters are reset */
+ ar9300_ani_restart(ah);
+ }
+}
+
+
+static void
+ar9300_ani_lower_immunity(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state = ahp->ah_curani;
+
+ if (ani_state->ofdm_noise_immunity_level > 0 &&
+ (ani_state->ofdms_turn || ani_state->cck_noise_immunity_level == 0)) {
+ /*
+ * lower OFDM noise immunity
+ */
+ ar9300_ani_set_odfm_noise_immunity_level(
+ ah, ani_state->ofdm_noise_immunity_level - 1);
+
+ /*
+ * only lower either OFDM or CCK errors per turn
+ * we lower the other one next time
+ */
+ return;
+ }
+
+ if (ani_state->cck_noise_immunity_level > 0) {
+ /*
+ * lower CCK noise immunity
+ */
+ ar9300_ani_set_cck_noise_immunity_level(
+ ah, ani_state->cck_noise_immunity_level - 1);
+ }
+}
+
+/* convert HW counter values to ms using mode specifix clock rate */
+#define CLOCK_RATE(_ah) (ath_hal_chan_2_clock_rate_mhz(_ah) * 1000)
+
+/*
+ * Return an approximation of the time spent ``listening'' by
+ * deducting the cycles spent tx'ing and rx'ing from the total
+ * cycle count since our last call. A return value <0 indicates
+ * an invalid/inconsistent time.
+ */
+static int32_t
+ar9300_ani_get_listen_time(struct ath_hal *ah, HAL_ANISTATS *ani_stats)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+ u_int32_t tx_frame_count, rx_frame_count, cycle_count;
+ int32_t listen_time;
+
+ tx_frame_count = OS_REG_READ(ah, AR_TFCNT);
+ rx_frame_count = OS_REG_READ(ah, AR_RFCNT);
+ cycle_count = OS_REG_READ(ah, AR_CCCNT);
+
+ ani_state = ahp->ah_curani;
+ if (ani_state->cycle_count == 0 || ani_state->cycle_count > cycle_count) {
+ /*
+ * Cycle counter wrap (or initial call); it's not possible
+ * to accurately calculate a value because the registers
+ * right shift rather than wrap--so punt and return 0.
+ */
+ listen_time = 0;
+ ahp->ah_stats.ast_ani_lzero++;
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: 1st call: ani_state->cycle_count=%d\n",
+ __func__, ani_state->cycle_count);
+#endif
+ } else {
+ int32_t ccdelta = cycle_count - ani_state->cycle_count;
+ int32_t rfdelta = rx_frame_count - ani_state->rx_frame_count;
+ int32_t tfdelta = tx_frame_count - ani_state->tx_frame_count;
+ listen_time = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE(ah);
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: cyclecount=%d, rfcount=%d, tfcount=%d, listen_time=%d "
+ "CLOCK_RATE=%d\n",
+ __func__, ccdelta, rfdelta, tfdelta, listen_time, CLOCK_RATE(ah));
+#endif
+ }
+ ani_state->cycle_count = cycle_count;
+ ani_state->tx_frame_count = tx_frame_count;
+ ani_state->rx_frame_count = rx_frame_count;
+ return listen_time;
+}
+
+/*
+ * Do periodic processing. This routine is called from a timer
+ */
+void
+ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
+ HAL_CHANNEL *chan, HAL_ANISTATS *ani_stats)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+ int32_t listen_time;
+ u_int32_t ofdm_phy_err_rate, cck_phy_err_rate;
+ u_int32_t ofdm_phy_err_cnt, cck_phy_err_cnt;
+ HAL_BOOL old_phy_noise_spur;
+
+ ani_state = ahp->ah_curani;
+ ahp->ah_stats.ast_nodestats = *stats; /* XXX optimize? */
+
+ if (ani_state == NULL) {
+ /* should not happen */
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: can't poll - no ANI not initialized for this channel\n",
+ __func__);
+ return;
+ }
+
+ /*
+ * ar9300_ani_ar_poll is never called while scanning but we may have been
+ * scanning and now just restarted polling. In this case we need to
+ * restore historical values.
+ */
+ if (ani_state->must_restore) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: must restore - calling ar9300_ani_restart\n", __func__);
+ ar9300_ani_reset(ah, AH_FALSE);
+ return;
+ }
+
+ listen_time = ar9300_ani_get_listen_time(ah, ani_stats);
+ if (listen_time <= 0) {
+ ahp->ah_stats.ast_ani_lneg++;
+ /* restart ANI period if listen_time is invalid */
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: listen_time=%d - calling ar9300_ani_restart\n",
+ __func__, listen_time);
+ ar9300_ani_restart(ah);
+ return;
+ }
+ /* XXX beware of overflow? */
+ ani_state->listen_time += listen_time;
+
+ /* Clear the mib counters and save them in the stats */
+ ar9300_update_mib_mac_stats(ah);
+ /* NB: these are not reset-on-read */
+ ofdm_phy_err_cnt = OS_REG_READ(ah, AR_PHY_ERR_1);
+ cck_phy_err_cnt = OS_REG_READ(ah, AR_PHY_ERR_2);
+
+
+
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+ ahp->ah_stats.ast_ani_ofdmerrs +=
+ ofdm_phy_err_cnt - ani_state->ofdm_phy_err_count;
+ ani_state->ofdm_phy_err_count = ofdm_phy_err_cnt;
+
+ ahp->ah_stats.ast_ani_cckerrs +=
+ cck_phy_err_cnt - ani_state->cck_phy_err_count;
+ ani_state->cck_phy_err_count = cck_phy_err_cnt;
+
+#if HAL_ANI_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: Errors: OFDM=0x%08x-0x0=%d CCK=0x%08x-0x0=%d\n",
+ __func__, ofdm_phy_err_cnt, ofdm_phy_err_cnt,
+ cck_phy_err_cnt, cck_phy_err_cnt);
+#endif
+
+ /*
+ * If ani is not enabled, return after we've collected
+ * statistics
+ */
+ if (!DO_ANI(ah)) {
+ return;
+ }
+
+ ofdm_phy_err_rate =
+ ani_state->ofdm_phy_err_count * 1000 / ani_state->listen_time;
+ cck_phy_err_rate =
+ ani_state->cck_phy_err_count * 1000 / ani_state->listen_time;
+
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: listen_time=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
+ __func__, listen_time,
+ ani_state->ofdm_noise_immunity_level, ofdm_phy_err_rate,
+ ani_state->cck_noise_immunity_level, cck_phy_err_rate,
+ ani_state->ofdms_turn);
+
+ if (ani_state->listen_time >= HAL_NOISE_DETECT_PERIOD) {
+ old_phy_noise_spur = ani_state->phy_noise_spur;
+ if (ofdm_phy_err_rate <= ani_state->ofdm_trig_low &&
+ cck_phy_err_rate <= ani_state->cck_trig_low) {
+ if (ani_state->listen_time >= HAL_NOISE_RECOVER_PERIOD) {
+ ani_state->phy_noise_spur = 0;
+ }
+ } else {
+ ani_state->phy_noise_spur = 1;
+ }
+ if (old_phy_noise_spur != ani_state->phy_noise_spur) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: enviroment change from %d to %d\n",
+ __func__, old_phy_noise_spur, ani_state->phy_noise_spur);
+ }
+ }
+
+ if (ani_state->listen_time > 5 * ahp->ah_ani_period) {
+ /*
+ * Check to see if need to lower immunity if
+ * 5 ani_periods have passed
+ */
+ if (ofdm_phy_err_rate <= ani_state->ofdm_trig_low &&
+ cck_phy_err_rate <= ani_state->cck_trig_low)
+ {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: 1. listen_time=%d OFDM:%d errs=%d/s(<%d) "
+ "CCK:%d errs=%d/s(<%d) -> ar9300_ani_lower_immunity\n",
+ __func__, ani_state->listen_time,
+ ani_state->ofdm_noise_immunity_level, ofdm_phy_err_rate,
+ ani_state->ofdm_trig_low, ani_state->cck_noise_immunity_level,
+ cck_phy_err_rate, ani_state->cck_trig_low);
+ ar9300_ani_lower_immunity(ah);
+ ani_state->ofdms_turn = !ani_state->ofdms_turn;
+ }
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: 1 listen_time=%d ofdm=%d/s cck=%d/s - "
+ "calling ar9300_ani_restart\n",
+ __func__, ani_state->listen_time,
+ ofdm_phy_err_rate, cck_phy_err_rate);
+ ar9300_ani_restart(ah);
+ } else if (ani_state->listen_time > ahp->ah_ani_period) {
+ /* check to see if need to raise immunity */
+ if (ofdm_phy_err_rate > ani_state->ofdm_trig_high &&
+ (cck_phy_err_rate <= ani_state->cck_trig_high ||
+ ani_state->ofdms_turn))
+ {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: 2 listen_time=%d OFDM:%d errs=%d/s(>%d) -> "
+ "ar9300_ani_ofdm_err_trigger\n",
+ __func__, ani_state->listen_time,
+ ani_state->ofdm_noise_immunity_level, ofdm_phy_err_rate,
+ ani_state->ofdm_trig_high);
+ ar9300_ani_ofdm_err_trigger(ah);
+ ar9300_ani_restart(ah);
+ ani_state->ofdms_turn = AH_FALSE;
+ } else if (cck_phy_err_rate > ani_state->cck_trig_high) {
+ HALDEBUG(ah, HAL_DEBUG_ANI,
+ "%s: 3 listen_time=%d CCK:%d errs=%d/s(>%d) -> "
+ "ar9300_ani_cck_err_trigger\n",
+ __func__, ani_state->listen_time,
+ ani_state->cck_noise_immunity_level, cck_phy_err_rate,
+ ani_state->cck_trig_high);
+ ar9300_ani_cck_err_trigger(ah);
+ ar9300_ani_restart(ah);
+ ani_state->ofdms_turn = AH_TRUE;
+ }
+ }
+}
+
+/*
+ * The poll function above calculates short noise spurs, caused by non-80211
+ * devices, based on OFDM/CCK Phy errs.
+ * If the noise is short enough, we don't want our ratectrl Algo to stop probing
+ * higher rates, due to bad PER.
+ */
+HAL_BOOL
+ar9300_is_ani_noise_spur(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani_state;
+
+ ani_state = ahp->ah_curani;
+
+ return ani_state->phy_noise_spur;
+}
+
+#endif /* AH_SUPPORT_AR9300 */
diff --git a/hal/ar9300/ar9300_aphrodite10.ini b/hal/ar9300/ar9300_aphrodite10.ini
new file mode 100644
index 000000000000..da2dc7d3f71d
--- /dev/null
+++ b/hal/ar9300/ar9300_aphrodite10.ini
@@ -0,0 +1,1536 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static const u_int32_t ar956X_aphrodite_1p0_tx_gain_table_baseband_postamble_emulation[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x0000a410 , 0x000000d5 , 0x000000d5 , 0x000000d5 , 0x000000d5 },
+ { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x0000a504 , 0x00004002 , 0x00004002 , 0x00004002 , 0x00004002 },
+ { 0x0000a508 , 0x00008004 , 0x00008004 , 0x00008004 , 0x00008004 },
+ { 0x0000a510 , 0x0001000c , 0x0001000c , 0x0001000c , 0x0001000c },
+ { 0x0000a514 , 0x0001420b , 0x0001420b , 0x0001420b , 0x0001420b },
+ { 0x0000a518 , 0x0001824a , 0x0001824a , 0x0001824a , 0x0001824a },
+ { 0x0000a51c , 0x0001c44a , 0x0001c44a , 0x0001c44a , 0x0001c44a },
+ { 0x0000a520 , 0x0002064a , 0x0002064a , 0x0002064a , 0x0002064a },
+ { 0x0000a524 , 0x0002484a , 0x0002484a , 0x0002484a , 0x0002484a },
+ { 0x0000a528 , 0x00028a4a , 0x00028a4a , 0x00028a4a , 0x00028a4a },
+ { 0x0000a52c , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a , 0x0002cc4a },
+ { 0x0000a530 , 0x00030e4a , 0x00030e4a , 0x00030e4a , 0x00030e4a },
+ { 0x0000a534 , 0x00034e8a , 0x00034e8a , 0x00034e8a , 0x00034e8a },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_baseband_core[][2] = {
+/* Addr allmodes */
+ { 0x00009800 , 0xafe68e30 },
+ { 0x00009804 , 0xfd14e000 },
+ { 0x00009808 , 0x9c0a8f6b },
+ { 0x0000980c , 0x04800000 },
+ { 0x00009814 , 0x9280c00a },
+ { 0x00009818 , 0x00000000 },
+ { 0x0000981c , 0x00020028 },
+ { 0x00009834 , 0x5f3ca3de },
+ { 0x00009838 , 0x0108ecff },
+ { 0x0000983c , 0x14750600 },
+ { 0x00009880 , 0x201fff00 },
+ { 0x00009884 , 0x00001042 },
+ { 0x000098a4 , 0x00200400 },
+ { 0x000098b0 , 0x52440bbe },
+ { 0x000098d0 , 0x004b6a8e },
+ { 0x000098d4 , 0x00000820 },
+ { 0x000098dc , 0x00000000 },
+ { 0x000098f0 , 0x00000000 },
+ { 0x000098f4 , 0x00000000 },
+ { 0x00009c04 , 0xff55ff55 },
+ { 0x00009c08 , 0x0320ff55 },
+ { 0x00009c0c , 0x00000000 },
+ { 0x00009c10 , 0x00000000 },
+ { 0x00009c14 , 0x00046384 },
+ { 0x00009c18 , 0x05b6b440 },
+ { 0x00009c1c , 0x00b6b440 },
+ { 0x00009d00 , 0xc080a333 },
+ { 0x00009d04 , 0x40206c10 },
+ { 0x00009d08 , 0x009c4060 },
+ { 0x00009d0c , 0x1883800a },
+ { 0x00009d10 , 0x01834061 },
+ { 0x00009d14 , 0x00c00400 },
+ { 0x00009d18 , 0x00000000 },
+ { 0x00009e08 , 0x0038233c },
+ { 0x00009e24 , 0x990bb515 },
+ { 0x00009e28 , 0x126f0000 },
+ { 0x00009e30 , 0x06336f77 },
+ { 0x00009e34 , 0x6af6532f },
+ { 0x00009e38 , 0x0cc80c00 },
+ { 0x00009e3c , 0xcf946222 },
+ { 0x00009e40 , 0x0d261820 },
+ { 0x00009e4c , 0x00001004 },
+ { 0x00009e50 , 0x00ff03f1 },
+ { 0x00009fc0 , 0x80be4788 },
+ { 0x00009fc4 , 0x0001efb5 },
+ { 0x00009fcc , 0x40000014 },
+ { 0x0000a20c , 0x00000000 },
+ { 0x0000a220 , 0x00000000 },
+ { 0x0000a224 , 0x00000000 },
+ { 0x0000a228 , 0x10002310 },
+ { 0x0000a22c , 0x0103702f },
+ { 0x0000a234 , 0x10000fff },
+ { 0x0000a23c , 0x00000000 },
+ { 0x0000a244 , 0x0c000000 },
+ { 0x0000a2a0 , 0x00000001 },
+ { 0x0000a2c0 , 0x00000001 },
+ { 0x0000a2c8 , 0x00000000 },
+ { 0x0000a2cc , 0x18c43433 },
+ { 0x0000a2d4 , 0x00000000 },
+ { 0x0000a2dc , 0x00000000 },
+ { 0x0000a2e0 , 0x00000000 },
+ { 0x0000a2e4 , 0x00000000 },
+ { 0x0000a2e8 , 0x00000000 },
+ { 0x0000a2ec , 0x00000000 },
+ { 0x0000a2f0 , 0x00000000 },
+ { 0x0000a2f4 , 0x00000000 },
+ { 0x0000a2f8 , 0x00000000 },
+ { 0x0000a344 , 0x00000000 },
+ { 0x0000a34c , 0x00000000 },
+ { 0x0000a350 , 0x0000a000 },
+ { 0x0000a364 , 0x00000000 },
+ { 0x0000a370 , 0x00000000 },
+ { 0x0000a390 , 0x00000001 },
+ { 0x0000a394 , 0x00000444 },
+ { 0x0000a398 , 0x001f0e0f },
+ { 0x0000a39c , 0x0075393f },
+ { 0x0000a3a0 , 0xb79f6427 },
+ { 0x0000a3a4 , 0x00000000 },
+ { 0x0000a3a8 , 0xaaaaaaaa },
+ { 0x0000a3ac , 0x3c466478 },
+ { 0x0000a3c0 , 0x20202020 },
+ { 0x0000a3c4 , 0x22222220 },
+ { 0x0000a3c8 , 0x20200020 },
+ { 0x0000a3cc , 0x20202020 },
+ { 0x0000a3d0 , 0x20202020 },
+ { 0x0000a3d4 , 0x20202020 },
+ { 0x0000a3d8 , 0x20202020 },
+ { 0x0000a3dc , 0x20202020 },
+ { 0x0000a3e0 , 0x20202020 },
+ { 0x0000a3e4 , 0x20202020 },
+ { 0x0000a3e8 , 0x20202020 },
+ { 0x0000a3ec , 0x20202020 },
+ { 0x0000a3f0 , 0x00000000 },
+ { 0x0000a3f4 , 0x00000006 },
+ { 0x0000a3f8 , 0x0cdbd380 },
+ { 0x0000a3fc , 0x000f0f01 },
+ { 0x0000a400 , 0x8fa91f01 },
+ { 0x0000a404 , 0x00000000 },
+ { 0x0000a408 , 0x0e79e5c6 },
+ { 0x0000a40c , 0x00820820 },
+ { 0x0000a414 , 0x1ce739ce },
+ { 0x0000a418 , 0x2d001dce },
+ { 0x0000a41c , 0x1ce739ce },
+ { 0x0000a420 , 0x000001ce },
+ { 0x0000a424 , 0x1ce739ce },
+ { 0x0000a428 , 0x000001ce },
+ { 0x0000a42c , 0x1ce739ce },
+ { 0x0000a430 , 0x1ce739ce },
+ { 0x0000a434 , 0x00000000 },
+ { 0x0000a438 , 0x00001801 },
+ { 0x0000a43c , 0x00000000 },
+ { 0x0000a440 , 0x00000000 },
+ { 0x0000a444 , 0x00000000 },
+ { 0x0000a448 , 0x07000000 },
+ { 0x0000a44c , 0x00000001 },
+ { 0x0000a450 , 0x00010000 },
+ { 0x0000a458 , 0x00000000 },
+ { 0x0000a600 , 0x00000000 },
+ { 0x0000a604 , 0x00000000 },
+ { 0x0000a608 , 0x00000000 },
+ { 0x0000a60c , 0x00000000 },
+ { 0x0000a610 , 0x00000000 },
+ { 0x0000a614 , 0x00000000 },
+ { 0x0000a618 , 0x00000000 },
+ { 0x0000a61c , 0x00000000 },
+ { 0x0000a620 , 0x00000000 },
+ { 0x0000a624 , 0x00000000 },
+ { 0x0000a628 , 0x00000000 },
+ { 0x0000a62c , 0x00000000 },
+ { 0x0000a630 , 0x00000000 },
+ { 0x0000a634 , 0x00000000 },
+ { 0x0000a638 , 0x00000000 },
+ { 0x0000a63c , 0x00000000 },
+ { 0x0000a644 , 0x3ffd9d74 },
+ { 0x0000a648 , 0x0048060a },
+ { 0x0000a64c , 0x00000637 },
+ { 0x0000a670 , 0x03020100 },
+ { 0x0000a674 , 0x09080504 },
+ { 0x0000a678 , 0x0d0c0b0a },
+ { 0x0000a67c , 0x13121110 },
+ { 0x0000a680 , 0x31301514 },
+ { 0x0000a684 , 0x35343332 },
+ { 0x0000a688 , 0x00000036 },
+ { 0x0000a690 , 0x00000838 },
+ { 0x0000a7c0 , 0x00000000 },
+ { 0x0000a7c4 , 0xfffffffc },
+ { 0x0000a7c8 , 0x00000000 },
+ { 0x0000a7cc , 0x00000000 },
+ { 0x0000a7d0 , 0x00000000 },
+ { 0x0000a7d4 , 0x00000004 },
+ { 0x0000a7dc , 0x00000001 },
+};
+
+static const u_int32_t ar956XModes_fast_clock_aphrodite_1p0[][3] = {
+/* Addr 5G_HT20 5G_HT40 */
+ { 0x00001030 , 0x00000268 , 0x000004d0 },
+ { 0x00001070 , 0x0000018c , 0x00000318 },
+ { 0x000010b0 , 0x00000fd0 , 0x00001fa0 },
+ { 0x00008014 , 0x044c044c , 0x08980898 },
+ { 0x0000801c , 0x148ec02b , 0x148ec057 },
+ { 0x00008318 , 0x000044c0 , 0x00008980 },
+ { 0x00009e00 , 0x03721821 , 0x03721821 },
+ { 0x0000a230 , 0x0000000b , 0x00000016 },
+ { 0x0000a254 , 0x00000898 , 0x00001130 },
+};
+
+static const u_int32_t ar956XCommon_wo_xlna_rx_gain_table_aphrodite_1p0[][2] = {
+/* Addr allmodes */
+ { 0x0000a000 , 0x00010000 },
+ { 0x0000a004 , 0x00030002 },
+ { 0x0000a008 , 0x00050004 },
+ { 0x0000a00c , 0x00810080 },
+ { 0x0000a010 , 0x00830082 },
+ { 0x0000a014 , 0x01810180 },
+ { 0x0000a018 , 0x01830182 },
+ { 0x0000a01c , 0x01850184 },
+ { 0x0000a020 , 0x01890188 },
+ { 0x0000a024 , 0x018b018a },
+ { 0x0000a028 , 0x018d018c },
+ { 0x0000a02c , 0x03820190 },
+ { 0x0000a030 , 0x03840383 },
+ { 0x0000a034 , 0x03880385 },
+ { 0x0000a038 , 0x038a0389 },
+ { 0x0000a03c , 0x038c038b },
+ { 0x0000a040 , 0x0390038d },
+ { 0x0000a044 , 0x03920391 },
+ { 0x0000a048 , 0x03940393 },
+ { 0x0000a04c , 0x03960395 },
+ { 0x0000a050 , 0x00000000 },
+ { 0x0000a054 , 0x00000000 },
+ { 0x0000a058 , 0x00000000 },
+ { 0x0000a05c , 0x00000000 },
+ { 0x0000a060 , 0x00000000 },
+ { 0x0000a064 , 0x00000000 },
+ { 0x0000a068 , 0x00000000 },
+ { 0x0000a06c , 0x00000000 },
+ { 0x0000a070 , 0x00000000 },
+ { 0x0000a074 , 0x00000000 },
+ { 0x0000a078 , 0x00000000 },
+ { 0x0000a07c , 0x00000000 },
+ { 0x0000a080 , 0x29292929 },
+ { 0x0000a084 , 0x29292929 },
+ { 0x0000a088 , 0x29292929 },
+ { 0x0000a08c , 0x29292929 },
+ { 0x0000a090 , 0x22292929 },
+ { 0x0000a094 , 0x1d1d2222 },
+ { 0x0000a098 , 0x0c111117 },
+ { 0x0000a09c , 0x00030303 },
+ { 0x0000a0a0 , 0x00000000 },
+ { 0x0000a0a4 , 0x00000000 },
+ { 0x0000a0a8 , 0x00000000 },
+ { 0x0000a0ac , 0x00000000 },
+ { 0x0000a0b0 , 0x00000000 },
+ { 0x0000a0b4 , 0x00000000 },
+ { 0x0000a0b8 , 0x00000000 },
+ { 0x0000a0bc , 0x00000000 },
+ { 0x0000a0c0 , 0x001f0000 },
+ { 0x0000a0c4 , 0x01000101 },
+ { 0x0000a0c8 , 0x011e011f },
+ { 0x0000a0cc , 0x011c011d },
+ { 0x0000a0d0 , 0x02030204 },
+ { 0x0000a0d4 , 0x02010202 },
+ { 0x0000a0d8 , 0x021f0200 },
+ { 0x0000a0dc , 0x0302021e },
+ { 0x0000a0e0 , 0x03000301 },
+ { 0x0000a0e4 , 0x031e031f },
+ { 0x0000a0e8 , 0x0402031d },
+ { 0x0000a0ec , 0x04000401 },
+ { 0x0000a0f0 , 0x041e041f },
+ { 0x0000a0f4 , 0x0502041d },
+ { 0x0000a0f8 , 0x05000501 },
+ { 0x0000a0fc , 0x051e051f },
+ { 0x0000a100 , 0x06010602 },
+ { 0x0000a104 , 0x061f0600 },
+ { 0x0000a108 , 0x061d061e },
+ { 0x0000a10c , 0x07020703 },
+ { 0x0000a110 , 0x07000701 },
+ { 0x0000a114 , 0x00000000 },
+ { 0x0000a118 , 0x00000000 },
+ { 0x0000a11c , 0x00000000 },
+ { 0x0000a120 , 0x00000000 },
+ { 0x0000a124 , 0x00000000 },
+ { 0x0000a128 , 0x00000000 },
+ { 0x0000a12c , 0x00000000 },
+ { 0x0000a130 , 0x00000000 },
+ { 0x0000a134 , 0x00000000 },
+ { 0x0000a138 , 0x00000000 },
+ { 0x0000a13c , 0x00000000 },
+ { 0x0000a140 , 0x001f0000 },
+ { 0x0000a144 , 0x01000101 },
+ { 0x0000a148 , 0x011e011f },
+ { 0x0000a14c , 0x011c011d },
+ { 0x0000a150 , 0x02030204 },
+ { 0x0000a154 , 0x02010202 },
+ { 0x0000a158 , 0x021f0200 },
+ { 0x0000a15c , 0x0302021e },
+ { 0x0000a160 , 0x03000301 },
+ { 0x0000a164 , 0x031e031f },
+ { 0x0000a168 , 0x0402031d },
+ { 0x0000a16c , 0x04000401 },
+ { 0x0000a170 , 0x041e041f },
+ { 0x0000a174 , 0x0502041d },
+ { 0x0000a178 , 0x05000501 },
+ { 0x0000a17c , 0x051e051f },
+ { 0x0000a180 , 0x06010602 },
+ { 0x0000a184 , 0x061f0600 },
+ { 0x0000a188 , 0x061d061e },
+ { 0x0000a18c , 0x07020703 },
+ { 0x0000a190 , 0x07000701 },
+ { 0x0000a194 , 0x00000000 },
+ { 0x0000a198 , 0x00000000 },
+ { 0x0000a19c , 0x00000000 },
+ { 0x0000a1a0 , 0x00000000 },
+ { 0x0000a1a4 , 0x00000000 },
+ { 0x0000a1a8 , 0x00000000 },
+ { 0x0000a1ac , 0x00000000 },
+ { 0x0000a1b0 , 0x00000000 },
+ { 0x0000a1b4 , 0x00000000 },
+ { 0x0000a1b8 , 0x00000000 },
+ { 0x0000a1bc , 0x00000000 },
+ { 0x0000a1c0 , 0x00000000 },
+ { 0x0000a1c4 , 0x00000000 },
+ { 0x0000a1c8 , 0x00000000 },
+ { 0x0000a1cc , 0x00000000 },
+ { 0x0000a1d0 , 0x00000000 },
+ { 0x0000a1d4 , 0x00000000 },
+ { 0x0000a1d8 , 0x00000000 },
+ { 0x0000a1dc , 0x00000000 },
+ { 0x0000a1e0 , 0x00000000 },
+ { 0x0000a1e4 , 0x00000000 },
+ { 0x0000a1e8 , 0x00000000 },
+ { 0x0000a1ec , 0x00000000 },
+ { 0x0000a1f0 , 0x00000396 },
+ { 0x0000a1f4 , 0x00000396 },
+ { 0x0000a1f8 , 0x00000396 },
+ { 0x0000a1fc , 0x00000196 },
+ { 0x0000b000 , 0x00010000 },
+ { 0x0000b004 , 0x00030002 },
+ { 0x0000b008 , 0x00050004 },
+ { 0x0000b00c , 0x00810080 },
+ { 0x0000b010 , 0x00830082 },
+ { 0x0000b014 , 0x01810180 },
+ { 0x0000b018 , 0x01830182 },
+ { 0x0000b01c , 0x01850184 },
+ { 0x0000b020 , 0x02810280 },
+ { 0x0000b024 , 0x02830282 },
+ { 0x0000b028 , 0x02850284 },
+ { 0x0000b02c , 0x02890288 },
+ { 0x0000b030 , 0x028b028a },
+ { 0x0000b034 , 0x0388028c },
+ { 0x0000b038 , 0x038a0389 },
+ { 0x0000b03c , 0x038c038b },
+ { 0x0000b040 , 0x0390038d },
+ { 0x0000b044 , 0x03920391 },
+ { 0x0000b048 , 0x03940393 },
+ { 0x0000b04c , 0x03960395 },
+ { 0x0000b050 , 0x00000000 },
+ { 0x0000b054 , 0x00000000 },
+ { 0x0000b058 , 0x00000000 },
+ { 0x0000b05c , 0x00000000 },
+ { 0x0000b060 , 0x00000000 },
+ { 0x0000b064 , 0x00000000 },
+ { 0x0000b068 , 0x00000000 },
+ { 0x0000b06c , 0x00000000 },
+ { 0x0000b070 , 0x00000000 },
+ { 0x0000b074 , 0x00000000 },
+ { 0x0000b078 , 0x00000000 },
+ { 0x0000b07c , 0x00000000 },
+ { 0x0000b080 , 0x32323232 },
+ { 0x0000b084 , 0x2f2f3232 },
+ { 0x0000b088 , 0x23282a2d },
+ { 0x0000b08c , 0x1c1e2123 },
+ { 0x0000b090 , 0x14171919 },
+ { 0x0000b094 , 0x0e0e1214 },
+ { 0x0000b098 , 0x03050707 },
+ { 0x0000b09c , 0x00030303 },
+ { 0x0000b0a0 , 0x00000000 },
+ { 0x0000b0a4 , 0x00000000 },
+ { 0x0000b0a8 , 0x00000000 },
+ { 0x0000b0ac , 0x00000000 },
+ { 0x0000b0b0 , 0x00000000 },
+ { 0x0000b0b4 , 0x00000000 },
+ { 0x0000b0b8 , 0x00000000 },
+ { 0x0000b0bc , 0x00000000 },
+ { 0x0000b0c0 , 0x003f0020 },
+ { 0x0000b0c4 , 0x00400041 },
+ { 0x0000b0c8 , 0x0140005f },
+ { 0x0000b0cc , 0x0160015f },
+ { 0x0000b0d0 , 0x017e017f },
+ { 0x0000b0d4 , 0x02410242 },
+ { 0x0000b0d8 , 0x025f0240 },
+ { 0x0000b0dc , 0x027f0260 },
+ { 0x0000b0e0 , 0x0341027e },
+ { 0x0000b0e4 , 0x035f0340 },
+ { 0x0000b0e8 , 0x037f0360 },
+ { 0x0000b0ec , 0x04400441 },
+ { 0x0000b0f0 , 0x0460045f },
+ { 0x0000b0f4 , 0x0541047f },
+ { 0x0000b0f8 , 0x055f0540 },
+ { 0x0000b0fc , 0x057f0560 },
+ { 0x0000b100 , 0x06400641 },
+ { 0x0000b104 , 0x0660065f },
+ { 0x0000b108 , 0x067e067f },
+ { 0x0000b10c , 0x07410742 },
+ { 0x0000b110 , 0x075f0740 },
+ { 0x0000b114 , 0x077f0760 },
+ { 0x0000b118 , 0x07800781 },
+ { 0x0000b11c , 0x07a0079f },
+ { 0x0000b120 , 0x07c107bf },
+ { 0x0000b124 , 0x000007c0 },
+ { 0x0000b128 , 0x00000000 },
+ { 0x0000b12c , 0x00000000 },
+ { 0x0000b130 , 0x00000000 },
+ { 0x0000b134 , 0x00000000 },
+ { 0x0000b138 , 0x00000000 },
+ { 0x0000b13c , 0x00000000 },
+ { 0x0000b140 , 0x003f0020 },
+ { 0x0000b144 , 0x00400041 },
+ { 0x0000b148 , 0x0140005f },
+ { 0x0000b14c , 0x0160015f },
+ { 0x0000b150 , 0x017e017f },
+ { 0x0000b154 , 0x02410242 },
+ { 0x0000b158 , 0x025f0240 },
+ { 0x0000b15c , 0x027f0260 },
+ { 0x0000b160 , 0x0341027e },
+ { 0x0000b164 , 0x035f0340 },
+ { 0x0000b168 , 0x037f0360 },
+ { 0x0000b16c , 0x04400441 },
+ { 0x0000b170 , 0x0460045f },
+ { 0x0000b174 , 0x0541047f },
+ { 0x0000b178 , 0x055f0540 },
+ { 0x0000b17c , 0x057f0560 },
+ { 0x0000b180 , 0x06400641 },
+ { 0x0000b184 , 0x0660065f },
+ { 0x0000b188 , 0x067e067f },
+ { 0x0000b18c , 0x07410742 },
+ { 0x0000b190 , 0x075f0740 },
+ { 0x0000b194 , 0x077f0760 },
+ { 0x0000b198 , 0x07800781 },
+ { 0x0000b19c , 0x07a0079f },
+ { 0x0000b1a0 , 0x07c107bf },
+ { 0x0000b1a4 , 0x000007c0 },
+ { 0x0000b1a8 , 0x00000000 },
+ { 0x0000b1ac , 0x00000000 },
+ { 0x0000b1b0 , 0x00000000 },
+ { 0x0000b1b4 , 0x00000000 },
+ { 0x0000b1b8 , 0x00000000 },
+ { 0x0000b1bc , 0x00000000 },
+ { 0x0000b1c0 , 0x00000000 },
+ { 0x0000b1c4 , 0x00000000 },
+ { 0x0000b1c8 , 0x00000000 },
+ { 0x0000b1cc , 0x00000000 },
+ { 0x0000b1d0 , 0x00000000 },
+ { 0x0000b1d4 , 0x00000000 },
+ { 0x0000b1d8 , 0x00000000 },
+ { 0x0000b1dc , 0x00000000 },
+ { 0x0000b1e0 , 0x00000000 },
+ { 0x0000b1e4 , 0x00000000 },
+ { 0x0000b1e8 , 0x00000000 },
+ { 0x0000b1ec , 0x00000000 },
+ { 0x0000b1f0 , 0x00000396 },
+ { 0x0000b1f4 , 0x00000396 },
+ { 0x0000b1f8 , 0x00000396 },
+ { 0x0000b1fc , 0x00000196 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_mac_core_emulation[][2] = {
+/* Addr allmodes */
+ { 0x00000030 , 0x000a0085 },
+ { 0x00000044 , 0x00000008 },
+ { 0x0000805c , 0xffffc7ff },
+ { 0x00008344 , 0xaa4a105b },
+};
+
+static const u_int32_t ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 },
+ { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 },
+ { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 },
+ { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 },
+ { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 },
+ { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 },
+ { 0x0000a518 , 0x21020220 , 0x21020220 , 0x16000402 , 0x16000402 },
+ { 0x0000a51c , 0x27020223 , 0x27020223 , 0x19000404 , 0x19000404 },
+ { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 },
+ { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 },
+ { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 },
+ { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 },
+ { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 },
+ { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 },
+ { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 },
+ { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 },
+ { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 },
+ { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 },
+ { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 },
+ { 0x0000a54c , 0x5c04286b , 0x5c04286b , 0x47001a83 , 0x47001a83 },
+ { 0x0000a550 , 0x61042a6c , 0x61042a6c , 0x4a001c84 , 0x4a001c84 },
+ { 0x0000a554 , 0x66062a6c , 0x66062a6c , 0x4e001ce3 , 0x4e001ce3 },
+ { 0x0000a558 , 0x6b062e6c , 0x6b062e6c , 0x52001ce5 , 0x52001ce5 },
+ { 0x0000a55c , 0x7006308c , 0x7006308c , 0x56001ce9 , 0x56001ce9 },
+ { 0x0000a560 , 0x730a308a , 0x730a308a , 0x5a001ceb , 0x5a001ceb },
+ { 0x0000a564 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a568 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a56c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a570 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a574 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a578 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a57c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+};
+
+static const u_int32_t ar956XModes_lowest_ob_db_tx_gain_table_aphrodite_1p0[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 },
+ { 0x0000a500 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x0000a504 , 0x06000003 , 0x06000003 , 0x04000002 , 0x04000002 },
+ { 0x0000a508 , 0x0a000020 , 0x0a000020 , 0x08000004 , 0x08000004 },
+ { 0x0000a50c , 0x10000023 , 0x10000023 , 0x0b000200 , 0x0b000200 },
+ { 0x0000a510 , 0x16000220 , 0x16000220 , 0x0f000202 , 0x0f000202 },
+ { 0x0000a514 , 0x1c000223 , 0x1c000223 , 0x12000400 , 0x12000400 },
+ { 0x0000a518 , 0x21020220 , 0x21020220 , 0x16000402 , 0x16000402 },
+ { 0x0000a51c , 0x27020223 , 0x27020223 , 0x19000404 , 0x19000404 },
+ { 0x0000a520 , 0x2b022220 , 0x2b022220 , 0x1c000603 , 0x1c000603 },
+ { 0x0000a524 , 0x2f022222 , 0x2f022222 , 0x21000a02 , 0x21000a02 },
+ { 0x0000a528 , 0x34022225 , 0x34022225 , 0x25000a04 , 0x25000a04 },
+ { 0x0000a52c , 0x3a02222a , 0x3a02222a , 0x28000a20 , 0x28000a20 },
+ { 0x0000a530 , 0x3e02222c , 0x3e02222c , 0x2c000e20 , 0x2c000e20 },
+ { 0x0000a534 , 0x4202242a , 0x4202242a , 0x30000e22 , 0x30000e22 },
+ { 0x0000a538 , 0x4702244a , 0x4702244a , 0x34000e24 , 0x34000e24 },
+ { 0x0000a53c , 0x4b02244c , 0x4b02244c , 0x38001640 , 0x38001640 },
+ { 0x0000a540 , 0x4e02246c , 0x4e02246c , 0x3c001660 , 0x3c001660 },
+ { 0x0000a544 , 0x5302266c , 0x5302266c , 0x3f001861 , 0x3f001861 },
+ { 0x0000a548 , 0x5702286c , 0x5702286c , 0x43001a81 , 0x43001a81 },
+ { 0x0000a54c , 0x5c04286b , 0x5c04286b , 0x47001a83 , 0x47001a83 },
+ { 0x0000a550 , 0x61042a6c , 0x61042a6c , 0x4a001c84 , 0x4a001c84 },
+ { 0x0000a554 , 0x66062a6c , 0x66062a6c , 0x4e001ce3 , 0x4e001ce3 },
+ { 0x0000a558 , 0x6b062e6c , 0x6b062e6c , 0x52001ce5 , 0x52001ce5 },
+ { 0x0000a55c , 0x7006308c , 0x7006308c , 0x56001ce9 , 0x56001ce9 },
+ { 0x0000a560 , 0x730a308a , 0x730a308a , 0x5a001ceb , 0x5a001ceb },
+ { 0x0000a564 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a568 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a56c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a570 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a574 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a578 , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+ { 0x0000a57c , 0x770a308c , 0x770a308c , 0x5d001eec , 0x5d001eec },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_mac_core[][2] = {
+/* Addr allmodes */
+ { 0x00000008 , 0x00000000 },
+ { 0x00000030 , 0x000a0085 },
+ { 0x00000034 , 0x00000005 },
+ { 0x00000040 , 0x00000000 },
+ { 0x00000044 , 0x00000000 },
+ { 0x00000048 , 0x00000008 },
+ { 0x0000004c , 0x00000010 },
+ { 0x00000050 , 0x00000000 },
+ { 0x00001040 , 0x002ffc0f },
+ { 0x00001044 , 0x002ffc0f },
+ { 0x00001048 , 0x002ffc0f },
+ { 0x0000104c , 0x002ffc0f },
+ { 0x00001050 , 0x002ffc0f },
+ { 0x00001054 , 0x002ffc0f },
+ { 0x00001058 , 0x002ffc0f },
+ { 0x0000105c , 0x002ffc0f },
+ { 0x00001060 , 0x002ffc0f },
+ { 0x00001064 , 0x002ffc0f },
+ { 0x000010f0 , 0x00000100 },
+ { 0x00001270 , 0x00000000 },
+ { 0x000012b0 , 0x00000000 },
+ { 0x000012f0 , 0x00000000 },
+ { 0x0000143c , 0x00000000 },
+ { 0x0000147c , 0x00000000 },
+ { 0x00008000 , 0x00000000 },
+ { 0x00008004 , 0x00000000 },
+ { 0x00008008 , 0x00000000 },
+ { 0x0000800c , 0x00000000 },
+ { 0x00008018 , 0x00000000 },
+ { 0x00008020 , 0x00000000 },
+ { 0x00008038 , 0x00000000 },
+ { 0x0000803c , 0x00000000 },
+ { 0x00008040 , 0x00000000 },
+ { 0x00008044 , 0x00000000 },
+ { 0x00008048 , 0x00000000 },
+ { 0x0000804c , 0xffffffff },
+ { 0x00008050 , 0xffffffff },
+ { 0x00008054 , 0x00000000 },
+ { 0x00008058 , 0x00000000 },
+ { 0x0000805c , 0x000fc78f },
+ { 0x00008060 , 0x0000000f },
+ { 0x00008064 , 0x00000000 },
+ { 0x00008070 , 0x00000310 },
+ { 0x00008074 , 0x00000020 },
+ { 0x00008078 , 0x00000000 },
+ { 0x0000809c , 0x0000000f },
+ { 0x000080a0 , 0x00000000 },
+ { 0x000080a4 , 0x02ff0000 },
+ { 0x000080a8 , 0x0e070605 },
+ { 0x000080ac , 0x0000000d },
+ { 0x000080b0 , 0x00000000 },
+ { 0x000080b4 , 0x00000000 },
+ { 0x000080b8 , 0x00000000 },
+ { 0x000080bc , 0x00000000 },
+ { 0x000080c0 , 0x2a800000 },
+ { 0x000080c4 , 0x06900168 },
+ { 0x000080c8 , 0x13881c20 },
+ { 0x000080cc , 0x01f40000 },
+ { 0x000080d0 , 0x00252500 },
+ { 0x000080d4 , 0x00b00005 },
+ { 0x000080d8 , 0x00400002 },
+ { 0x000080dc , 0x00000000 },
+ { 0x000080e0 , 0xffffffff },
+ { 0x000080e4 , 0x0000ffff },
+ { 0x000080e8 , 0x3f3f3f3f },
+ { 0x000080ec , 0x00000000 },
+ { 0x000080f0 , 0x00000000 },
+ { 0x000080f4 , 0x00000000 },
+ { 0x000080fc , 0x00020000 },
+ { 0x00008100 , 0x00000000 },
+ { 0x00008108 , 0x00000052 },
+ { 0x0000810c , 0x00000000 },
+ { 0x00008110 , 0x00000000 },
+ { 0x00008114 , 0x000007ff },
+ { 0x00008118 , 0x000000aa },
+ { 0x0000811c , 0x00003210 },
+ { 0x00008124 , 0x00000000 },
+ { 0x00008128 , 0x00000000 },
+ { 0x0000812c , 0x00000000 },
+ { 0x00008130 , 0x00000000 },
+ { 0x00008134 , 0x00000000 },
+ { 0x00008138 , 0x00000000 },
+ { 0x0000813c , 0x0000ffff },
+ { 0x00008144 , 0xffffffff },
+ { 0x00008168 , 0x00000000 },
+ { 0x0000816c , 0x00000000 },
+#ifdef AR956X_EMULATION
+ //This is workaround in emulation.Because it cause tx dma stop. We must find out soluction.
+ { 0x00008170 , 0x18486E00 },
+#else
+ { 0x00008170 , 0x18486200 },
+#endif
+ { 0x00008174 , 0x33332210 },
+ { 0x00008178 , 0x00000000 },
+ { 0x0000817c , 0x00020000 },
+ { 0x000081c4 , 0x33332210 },
+ { 0x000081c8 , 0x00000000 },
+ { 0x000081cc , 0x00000000 },
+ { 0x000081d4 , 0x00000000 },
+ { 0x000081ec , 0x00000000 },
+ { 0x000081f0 , 0x00000000 },
+ { 0x000081f4 , 0x00000000 },
+ { 0x000081f8 , 0x00000000 },
+ { 0x000081fc , 0x00000000 },
+ { 0x00008240 , 0x00100000 },
+ { 0x00008244 , 0x0010f424 },
+ { 0x00008248 , 0x00000800 },
+ { 0x0000824c , 0x0001e848 },
+ { 0x00008250 , 0x00000000 },
+ { 0x00008254 , 0x00000000 },
+ { 0x00008258 , 0x00000000 },
+ { 0x0000825c , 0x40000000 },
+ { 0x00008260 , 0x00080922 },
+ { 0x00008264 , 0x98a00010 },
+ { 0x00008268 , 0xffffffff },
+ { 0x0000826c , 0x0000ffff },
+ { 0x00008270 , 0x00000000 },
+ { 0x00008274 , 0x40000000 },
+ { 0x00008278 , 0x003e4180 },
+ { 0x0000827c , 0x00000004 },
+ { 0x00008284 , 0x0000002c },
+ { 0x00008288 , 0x0000002c },
+ { 0x0000828c , 0x000000ff },
+ { 0x00008294 , 0x00000000 },
+ { 0x00008298 , 0x00000000 },
+ { 0x0000829c , 0x00000000 },
+ { 0x00008300 , 0x00000140 },
+ { 0x00008314 , 0x00000000 },
+ { 0x0000831c , 0x0000010d },
+ { 0x00008328 , 0x00000000 },
+ { 0x0000832c , 0x0000001f },
+ { 0x00008330 , 0x00000302 },
+ { 0x00008334 , 0x00000700 },
+ { 0x00008338 , 0xffff0000 },
+ { 0x0000833c , 0x02400000 },
+ { 0x00008340 , 0x000107ff },
+ { 0x00008344 , 0xaa48105b },
+ { 0x00008348 , 0x008f0000 },
+ { 0x0000835c , 0x00000000 },
+ { 0x00008360 , 0xffffffff },
+ { 0x00008364 , 0xffffffff },
+ { 0x00008368 , 0x00000000 },
+ { 0x00008370 , 0x00000000 },
+ { 0x00008374 , 0x000000ff },
+ { 0x00008378 , 0x00000000 },
+ { 0x0000837c , 0x00000000 },
+ { 0x00008380 , 0xffffffff },
+ { 0x00008384 , 0xffffffff },
+ { 0x00008390 , 0xffffffff },
+ { 0x00008394 , 0xffffffff },
+ { 0x00008398 , 0x00000000 },
+ { 0x0000839c , 0x00000000 },
+ { 0x000083a4 , 0x0000fa14 },
+ { 0x000083a8 , 0x000f0c00 },
+ { 0x000083ac , 0x33332210 },
+ { 0x000083b0 , 0x33332210 },
+ { 0x000083b4 , 0x33332210 },
+ { 0x000083b8 , 0x33332210 },
+ { 0x000083bc , 0x00000000 },
+ { 0x000083c0 , 0x00000000 },
+ { 0x000083c4 , 0x00000000 },
+ { 0x000083c8 , 0x00000000 },
+ { 0x000083cc , 0x00000200 },
+ { 0x000083d0 , 0x800301ff },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_mac_postamble_emulation[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00008014 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 , 0x10f810f8 },
+ { 0x0000801c , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 , 0x0e8d8017 },
+};
+
+static const u_int32_t ar956XModes_high_power_tx_gain_table_aphrodite_1p0[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 },
+ { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 },
+ { 0x0000a504 , 0x06002223 , 0x06002223 , 0x04000002 , 0x04000002 },
+ { 0x0000a508 , 0x0a022220 , 0x0a022220 , 0x08000004 , 0x08000004 },
+ { 0x0000a50c , 0x0f022223 , 0x0f022223 , 0x0b000200 , 0x0b000200 },
+ { 0x0000a510 , 0x14022620 , 0x14022620 , 0x0f000202 , 0x0f000202 },
+ { 0x0000a514 , 0x18022622 , 0x18022622 , 0x11000400 , 0x11000400 },
+ { 0x0000a518 , 0x1b022822 , 0x1b022822 , 0x15000402 , 0x15000402 },
+ { 0x0000a51c , 0x20022842 , 0x20022842 , 0x19000404 , 0x19000404 },
+ { 0x0000a520 , 0x22022c41 , 0x22022c41 , 0x1b000603 , 0x1b000603 },
+ { 0x0000a524 , 0x28023042 , 0x28023042 , 0x1f000a02 , 0x1f000a02 },
+ { 0x0000a528 , 0x2c023044 , 0x2c023044 , 0x23000a04 , 0x23000a04 },
+ { 0x0000a52c , 0x2f023644 , 0x2f023644 , 0x26000a20 , 0x26000a20 },
+ { 0x0000a530 , 0x34025643 , 0x34025643 , 0x2a000e20 , 0x2a000e20 },
+ { 0x0000a534 , 0x38025a44 , 0x38025a44 , 0x2e000e22 , 0x2e000e22 },
+ { 0x0000a538 , 0x3b025e45 , 0x3b025e45 , 0x31000e24 , 0x31000e24 },
+ { 0x0000a53c , 0x41025e4a , 0x41025e4a , 0x34001640 , 0x34001640 },
+ { 0x0000a540 , 0x48025e6c , 0x48025e6c , 0x38001660 , 0x38001660 },
+ { 0x0000a544 , 0x4e025e8e , 0x4e025e8e , 0x3b001861 , 0x3b001861 },
+ { 0x0000a548 , 0x53025eb2 , 0x53025eb2 , 0x3e001a81 , 0x3e001a81 },
+ { 0x0000a54c , 0x59025eb5 , 0x59025eb5 , 0x42001a83 , 0x42001a83 },
+ { 0x0000a550 , 0x5f025ef6 , 0x5f025ef6 , 0x44001c84 , 0x44001c84 },
+ { 0x0000a554 , 0x62025f56 , 0x62025f56 , 0x48001ce3 , 0x48001ce3 },
+ { 0x0000a558 , 0x66027f56 , 0x66027f56 , 0x4c001ce5 , 0x4c001ce5 },
+ { 0x0000a55c , 0x6a029f56 , 0x6a029f56 , 0x50001ce9 , 0x50001ce9 },
+ { 0x0000a560 , 0x70049f56 , 0x70049f56 , 0x54001ceb , 0x54001ceb },
+ { 0x0000a564 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a568 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a56c , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a570 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a574 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a578 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a57c , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+};
+
+static const u_int32_t ar956XModes_high_ob_db_tx_gain_table_aphrodite_1p0[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x0000a410 , 0x000050d9 , 0x000050d9 , 0x000050d9 , 0x000050d9 },
+ { 0x0000a500 , 0x00002220 , 0x00002220 , 0x00000000 , 0x00000000 },
+ { 0x0000a504 , 0x06002223 , 0x06002223 , 0x04000002 , 0x04000002 },
+ { 0x0000a508 , 0x0a022220 , 0x0a022220 , 0x08000004 , 0x08000004 },
+ { 0x0000a50c , 0x0f022223 , 0x0f022223 , 0x0b000200 , 0x0b000200 },
+ { 0x0000a510 , 0x14022620 , 0x14022620 , 0x0f000202 , 0x0f000202 },
+ { 0x0000a514 , 0x18022622 , 0x18022622 , 0x11000400 , 0x11000400 },
+ { 0x0000a518 , 0x1b022822 , 0x1b022822 , 0x15000402 , 0x15000402 },
+ { 0x0000a51c , 0x20022842 , 0x20022842 , 0x19000404 , 0x19000404 },
+ { 0x0000a520 , 0x22022c41 , 0x22022c41 , 0x1b000603 , 0x1b000603 },
+ { 0x0000a524 , 0x28023042 , 0x28023042 , 0x1f000a02 , 0x1f000a02 },
+ { 0x0000a528 , 0x2c023044 , 0x2c023044 , 0x23000a04 , 0x23000a04 },
+ { 0x0000a52c , 0x2f023644 , 0x2f023644 , 0x26000a20 , 0x26000a20 },
+ { 0x0000a530 , 0x34025643 , 0x34025643 , 0x2a000e20 , 0x2a000e20 },
+ { 0x0000a534 , 0x38025a44 , 0x38025a44 , 0x2e000e22 , 0x2e000e22 },
+ { 0x0000a538 , 0x3b025e45 , 0x3b025e45 , 0x31000e24 , 0x31000e24 },
+ { 0x0000a53c , 0x41025e4a , 0x41025e4a , 0x34001640 , 0x34001640 },
+ { 0x0000a540 , 0x48025e6c , 0x48025e6c , 0x38001660 , 0x38001660 },
+ { 0x0000a544 , 0x4e025e8e , 0x4e025e8e , 0x3b001861 , 0x3b001861 },
+ { 0x0000a548 , 0x53025eb2 , 0x53025eb2 , 0x3e001a81 , 0x3e001a81 },
+ { 0x0000a54c , 0x59025eb5 , 0x59025eb5 , 0x42001a83 , 0x42001a83 },
+ { 0x0000a550 , 0x5f025ef6 , 0x5f025ef6 , 0x44001c84 , 0x44001c84 },
+ { 0x0000a554 , 0x62025f56 , 0x62025f56 , 0x48001ce3 , 0x48001ce3 },
+ { 0x0000a558 , 0x66027f56 , 0x66027f56 , 0x4c001ce5 , 0x4c001ce5 },
+ { 0x0000a55c , 0x6a029f56 , 0x6a029f56 , 0x50001ce9 , 0x50001ce9 },
+ { 0x0000a560 , 0x70049f56 , 0x70049f56 , 0x54001ceb , 0x54001ceb },
+ { 0x0000a564 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a568 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a56c , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a570 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a574 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a578 , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+ { 0x0000a57c , 0x7504ff56 , 0x7504ff56 , 0x56001eec , 0x56001eec },
+};
+
+static const u_int32_t ar9200_merlin_2p0_aphrodite_radio_core[][2] = {
+/* Addr common */
+ { 0x00007800 , 0x00040000 },
+ { 0x00007804 , 0xdb005012 },
+ { 0x00007808 , 0x04924914 },
+ { 0x0000780c , 0x21084210 },
+ { 0x00007810 , 0x6d801300 },
+ { 0x00007814 , 0x0019beff },
+ { 0x00007818 , 0x07e41000 },
+ { 0x0000781c , 0x00392000 },
+ { 0x00007820 , 0x92592480 },
+ { 0x00007824 , 0x00040000 },
+ { 0x00007828 , 0xdb005012 },
+ { 0x0000782c , 0x04924914 },
+ { 0x00007830 , 0x21084210 },
+ { 0x00007834 , 0x6d801300 },
+ { 0x00007838 , 0x0019beff },
+ { 0x0000783c , 0x07e40000 },
+ { 0x00007840 , 0x00392000 },
+ { 0x00007844 , 0x92592480 },
+ { 0x00007848 , 0x00100000 },
+ { 0x0000784c , 0x773f0567 },
+ { 0x00007850 , 0x54214514 },
+ { 0x00007854 , 0x12035828 },
+ { 0x00007858 , 0x92592692 },
+ { 0x0000785c , 0x00000000 },
+ { 0x00007860 , 0x56400000 },
+ { 0x00007864 , 0x0a8e370e },
+ { 0x00007868 , 0xc0102850 },
+ { 0x0000786c , 0x812d4000 },
+ { 0x00007870 , 0x807ec400 },
+ { 0x00007874 , 0x001b6db0 },
+ { 0x00007878 , 0x00376b63 },
+ { 0x0000787c , 0x06db6db6 },
+ { 0x00007880 , 0x006d8000 },
+ { 0x00007884 , 0xffeffffe },
+ { 0x00007888 , 0xffeffffe },
+ { 0x0000788c , 0x00010000 },
+ { 0x00007890 , 0x02060aeb },
+ { 0x00007894 , 0x5a108000 },
+};
+
+static const u_int32_t ar956XCommon_rx_gain_table_merlin_2p0[][2] = {
+/* Addr allmodes */
+ { 0x0000a000 , 0x02000101 },
+ { 0x0000a004 , 0x02000102 },
+ { 0x0000a008 , 0x02000103 },
+ { 0x0000a00c , 0x02000104 },
+ { 0x0000a010 , 0x02000200 },
+ { 0x0000a014 , 0x02000201 },
+ { 0x0000a018 , 0x02000202 },
+ { 0x0000a01c , 0x02000203 },
+ { 0x0000a020 , 0x02000204 },
+ { 0x0000a024 , 0x02000205 },
+ { 0x0000a028 , 0x02000208 },
+ { 0x0000a02c , 0x02000302 },
+ { 0x0000a030 , 0x02000303 },
+ { 0x0000a034 , 0x02000304 },
+ { 0x0000a038 , 0x02000400 },
+ { 0x0000a03c , 0x02010300 },
+ { 0x0000a040 , 0x02010301 },
+ { 0x0000a044 , 0x02010302 },
+ { 0x0000a048 , 0x02000500 },
+ { 0x0000a04c , 0x02010400 },
+ { 0x0000a050 , 0x02020300 },
+ { 0x0000a054 , 0x02020301 },
+ { 0x0000a058 , 0x02020302 },
+ { 0x0000a05c , 0x02020303 },
+ { 0x0000a060 , 0x02020400 },
+ { 0x0000a064 , 0x02030300 },
+ { 0x0000a068 , 0x02030301 },
+ { 0x0000a06c , 0x02030302 },
+ { 0x0000a070 , 0x02030303 },
+ { 0x0000a074 , 0x02030400 },
+ { 0x0000a078 , 0x02040300 },
+ { 0x0000a07c , 0x02040301 },
+ { 0x0000a080 , 0x02040302 },
+ { 0x0000a084 , 0x02040303 },
+ { 0x0000a088 , 0x02030500 },
+ { 0x0000a08c , 0x02040400 },
+ { 0x0000a090 , 0x02050203 },
+ { 0x0000a094 , 0x02050204 },
+ { 0x0000a098 , 0x02050205 },
+ { 0x0000a09c , 0x02040500 },
+ { 0x0000a0a0 , 0x02050301 },
+ { 0x0000a0a4 , 0x02050302 },
+ { 0x0000a0a8 , 0x02050303 },
+ { 0x0000a0ac , 0x02050400 },
+ { 0x0000a0b0 , 0x02050401 },
+ { 0x0000a0b4 , 0x02050402 },
+ { 0x0000a0b8 , 0x02050403 },
+ { 0x0000a0bc , 0x02050500 },
+ { 0x0000a0c0 , 0x02050501 },
+ { 0x0000a0c4 , 0x02050502 },
+ { 0x0000a0c8 , 0x02050503 },
+ { 0x0000a0cc , 0x02050504 },
+ { 0x0000a0d0 , 0x02050600 },
+ { 0x0000a0d4 , 0x02050601 },
+ { 0x0000a0d8 , 0x02050602 },
+ { 0x0000a0dc , 0x02050603 },
+ { 0x0000a0e0 , 0x02050604 },
+ { 0x0000a0e4 , 0x02050700 },
+ { 0x0000a0e8 , 0x02050701 },
+ { 0x0000a0ec , 0x02050702 },
+ { 0x0000a0f0 , 0x02050703 },
+ { 0x0000a0f4 , 0x02050704 },
+ { 0x0000a0f8 , 0x02050705 },
+ { 0x0000a0fc , 0x02050708 },
+ { 0x0000a100 , 0x02050709 },
+ { 0x0000a104 , 0x0205070a },
+ { 0x0000a108 , 0x0205070b },
+ { 0x0000a10c , 0x0205070c },
+ { 0x0000a110 , 0x0205070d },
+ { 0x0000a114 , 0x02050710 },
+ { 0x0000a118 , 0x02050711 },
+ { 0x0000a11c , 0x02050712 },
+ { 0x0000a120 , 0x02050713 },
+ { 0x0000a124 , 0x02050714 },
+ { 0x0000a128 , 0x02050715 },
+ { 0x0000a12c , 0x02050730 },
+ { 0x0000a130 , 0x02050731 },
+ { 0x0000a134 , 0x02050732 },
+ { 0x0000a138 , 0x02050733 },
+ { 0x0000a13c , 0x02050734 },
+ { 0x0000a140 , 0x02050735 },
+ { 0x0000a144 , 0x02050750 },
+ { 0x0000a148 , 0x02050751 },
+ { 0x0000a14c , 0x02050752 },
+ { 0x0000a150 , 0x02050753 },
+ { 0x0000a154 , 0x02050754 },
+ { 0x0000a158 , 0x02050755 },
+ { 0x0000a15c , 0x02050770 },
+ { 0x0000a160 , 0x02050771 },
+ { 0x0000a164 , 0x02050772 },
+ { 0x0000a168 , 0x02050773 },
+ { 0x0000a16c , 0x02050774 },
+ { 0x0000a170 , 0x02050775 },
+ { 0x0000a174 , 0x00000776 },
+ { 0x0000a178 , 0x00000776 },
+ { 0x0000a17c , 0x00000776 },
+ { 0x0000a180 , 0x00000776 },
+ { 0x0000a184 , 0x00000776 },
+ { 0x0000a188 , 0x00000776 },
+ { 0x0000a18c , 0x00000776 },
+ { 0x0000a190 , 0x00000776 },
+ { 0x0000a194 , 0x00000776 },
+ { 0x0000a198 , 0x00000776 },
+ { 0x0000a19c , 0x00000776 },
+ { 0x0000a1a0 , 0x00000776 },
+ { 0x0000a1a4 , 0x00000776 },
+ { 0x0000a1a8 , 0x00000776 },
+ { 0x0000a1ac , 0x00000776 },
+ { 0x0000a1b0 , 0x00000776 },
+ { 0x0000a1b4 , 0x00000776 },
+ { 0x0000a1b8 , 0x00000776 },
+ { 0x0000a1bc , 0x00000776 },
+ { 0x0000a1c0 , 0x00000776 },
+ { 0x0000a1c4 , 0x00000776 },
+ { 0x0000a1c8 , 0x00000776 },
+ { 0x0000a1cc , 0x00000776 },
+ { 0x0000a1d0 , 0x00000776 },
+ { 0x0000a1d4 , 0x00000776 },
+ { 0x0000a1d8 , 0x00000776 },
+ { 0x0000a1dc , 0x00000776 },
+ { 0x0000a1e0 , 0x00000776 },
+ { 0x0000a1e4 , 0x00000776 },
+ { 0x0000a1e8 , 0x00000776 },
+ { 0x0000a1ec , 0x00000776 },
+ { 0x0000a1f0 , 0x00000776 },
+ { 0x0000a1f4 , 0x00000776 },
+ { 0x0000a1f8 , 0x00000776 },
+ { 0x0000a1fc , 0x00000776 },
+ { 0x0000b000 , 0x02000101 },
+ { 0x0000b004 , 0x02000102 },
+ { 0x0000b008 , 0x02000103 },
+ { 0x0000b00c , 0x02000104 },
+ { 0x0000b010 , 0x02000200 },
+ { 0x0000b014 , 0x02000201 },
+ { 0x0000b018 , 0x02000202 },
+ { 0x0000b01c , 0x02000203 },
+ { 0x0000b020 , 0x02000204 },
+ { 0x0000b024 , 0x02000205 },
+ { 0x0000b028 , 0x02000208 },
+ { 0x0000b02c , 0x02000302 },
+ { 0x0000b030 , 0x02000303 },
+ { 0x0000b034 , 0x02000304 },
+ { 0x0000b038 , 0x02000400 },
+ { 0x0000b03c , 0x02010300 },
+ { 0x0000b040 , 0x02010301 },
+ { 0x0000b044 , 0x02010302 },
+ { 0x0000b048 , 0x02000500 },
+ { 0x0000b04c , 0x02010400 },
+ { 0x0000b050 , 0x02020300 },
+ { 0x0000b054 , 0x02020301 },
+ { 0x0000b058 , 0x02020302 },
+ { 0x0000b05c , 0x02020303 },
+ { 0x0000b060 , 0x02020400 },
+ { 0x0000b064 , 0x02030300 },
+ { 0x0000b068 , 0x02030301 },
+ { 0x0000b06c , 0x02030302 },
+ { 0x0000b070 , 0x02030303 },
+ { 0x0000b074 , 0x02030400 },
+ { 0x0000b078 , 0x02040300 },
+ { 0x0000b07c , 0x02040301 },
+ { 0x0000b080 , 0x02040302 },
+ { 0x0000b084 , 0x02040303 },
+ { 0x0000b088 , 0x02030500 },
+ { 0x0000b08c , 0x02040400 },
+ { 0x0000b090 , 0x02050203 },
+ { 0x0000b094 , 0x02050204 },
+ { 0x0000b098 , 0x02050205 },
+ { 0x0000b09c , 0x02040500 },
+ { 0x0000b0a0 , 0x02050301 },
+ { 0x0000b0a4 , 0x02050302 },
+ { 0x0000b0a8 , 0x02050303 },
+ { 0x0000b0ac , 0x02050400 },
+ { 0x0000b0b0 , 0x02050401 },
+ { 0x0000b0b4 , 0x02050402 },
+ { 0x0000b0b8 , 0x02050403 },
+ { 0x0000b0bc , 0x02050500 },
+ { 0x0000b0c0 , 0x02050501 },
+ { 0x0000b0c4 , 0x02050502 },
+ { 0x0000b0c8 , 0x02050503 },
+ { 0x0000b0cc , 0x02050504 },
+ { 0x0000b0d0 , 0x02050600 },
+ { 0x0000b0d4 , 0x02050601 },
+ { 0x0000b0d8 , 0x02050602 },
+ { 0x0000b0dc , 0x02050603 },
+ { 0x0000b0e0 , 0x02050604 },
+ { 0x0000b0e4 , 0x02050700 },
+ { 0x0000b0e8 , 0x02050701 },
+ { 0x0000b0ec , 0x02050702 },
+ { 0x0000b0f0 , 0x02050703 },
+ { 0x0000b0f4 , 0x02050704 },
+ { 0x0000b0f8 , 0x02050705 },
+ { 0x0000b0fc , 0x02050708 },
+ { 0x0000b100 , 0x02050709 },
+ { 0x0000b104 , 0x0205070a },
+ { 0x0000b108 , 0x0205070b },
+ { 0x0000b10c , 0x0205070c },
+ { 0x0000b110 , 0x0205070d },
+ { 0x0000b114 , 0x02050710 },
+ { 0x0000b118 , 0x02050711 },
+ { 0x0000b11c , 0x02050712 },
+ { 0x0000b120 , 0x02050713 },
+ { 0x0000b124 , 0x02050714 },
+ { 0x0000b128 , 0x02050715 },
+ { 0x0000b12c , 0x02050730 },
+ { 0x0000b130 , 0x02050731 },
+ { 0x0000b134 , 0x02050732 },
+ { 0x0000b138 , 0x02050733 },
+ { 0x0000b13c , 0x02050734 },
+ { 0x0000b140 , 0x02050735 },
+ { 0x0000b144 , 0x02050750 },
+ { 0x0000b148 , 0x02050751 },
+ { 0x0000b14c , 0x02050752 },
+ { 0x0000b150 , 0x02050753 },
+ { 0x0000b154 , 0x02050754 },
+ { 0x0000b158 , 0x02050755 },
+ { 0x0000b15c , 0x02050770 },
+ { 0x0000b160 , 0x02050771 },
+ { 0x0000b164 , 0x02050772 },
+ { 0x0000b168 , 0x02050773 },
+ { 0x0000b16c , 0x02050774 },
+ { 0x0000b170 , 0x02050775 },
+ { 0x0000b174 , 0x00000776 },
+ { 0x0000b178 , 0x00000776 },
+ { 0x0000b17c , 0x00000776 },
+ { 0x0000b180 , 0x00000776 },
+ { 0x0000b184 , 0x00000776 },
+ { 0x0000b188 , 0x00000776 },
+ { 0x0000b18c , 0x00000776 },
+ { 0x0000b190 , 0x00000776 },
+ { 0x0000b194 , 0x00000776 },
+ { 0x0000b198 , 0x00000776 },
+ { 0x0000b19c , 0x00000776 },
+ { 0x0000b1a0 , 0x00000776 },
+ { 0x0000b1a4 , 0x00000776 },
+ { 0x0000b1a8 , 0x00000776 },
+ { 0x0000b1ac , 0x00000776 },
+ { 0x0000b1b0 , 0x00000776 },
+ { 0x0000b1b4 , 0x00000776 },
+ { 0x0000b1b8 , 0x00000776 },
+ { 0x0000b1bc , 0x00000776 },
+ { 0x0000b1c0 , 0x00000776 },
+ { 0x0000b1c4 , 0x00000776 },
+ { 0x0000b1c8 , 0x00000776 },
+ { 0x0000b1cc , 0x00000776 },
+ { 0x0000b1d0 , 0x00000776 },
+ { 0x0000b1d4 , 0x00000776 },
+ { 0x0000b1d8 , 0x00000776 },
+ { 0x0000b1dc , 0x00000776 },
+ { 0x0000b1e0 , 0x00000776 },
+ { 0x0000b1e4 , 0x00000776 },
+ { 0x0000b1e8 , 0x00000776 },
+ { 0x0000b1ec , 0x00000776 },
+ { 0x0000b1f0 , 0x00000776 },
+ { 0x0000b1f4 , 0x00000776 },
+ { 0x0000b1f8 , 0x00000776 },
+ { 0x0000b1fc , 0x00000776 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_baseband_core_emulation[][2] = {
+/* Addr allmodes */
+ { 0x00009800 , 0xafe68e30 },
+ { 0x00009884 , 0x00001042 },
+ { 0x00009c04 , 0x00000000 },
+ { 0x00009c08 , 0x03200000 },
+ { 0x00009e3c , 0xcf946221 },
+ { 0x00009e50 , 0x00ff03f1 },
+ { 0x00009fcc , 0x40000014 },
+ { 0x0000a344 , 0x00000010 },
+ { 0x0000a398 , 0x001f0e0f },
+ { 0x0000a39c , 0x0075393f },
+ { 0x0000a3a0 , 0xb79f6427 },
+ { 0x0000a3c0 , 0x20202020 },
+ { 0x0000a3c4 , 0x22222220 },
+ { 0x0000a404 , 0x00418a11 },
+ { 0x0000a418 , 0x7d001dce },
+ { 0x0000a438 , 0x00001801 },
+ { 0x0000a458 , 0x00404442 },
+ { 0x0000a690 , 0x00000838 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_soc_preamble[][2] = {
+/* Addr allmodes */
+ { 0x00004014 , 0xba280400 },
+ { 0x00004078 , 0x00000002 },
+ { 0x000040a4 , 0x00a0c9c9 },
+ { 0x00007010 , 0x00000022 },
+ { 0x00007020 , 0x00000000 },
+ { 0x00007034 , 0x00000002 },
+ { 0x00007038 , 0x000004c2 },
+ { 0x00007048 , 0x00000002 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_soc_postamble[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00007010 , 0x00002233 , 0x00002233 , 0x00002233 , 0x00002233 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_mac_postamble[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00001030 , 0x00000230 , 0x00000460 , 0x000002c0 , 0x00000160 },
+ { 0x00001070 , 0x00000168 , 0x000002d0 , 0x00000318 , 0x0000018c },
+ { 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 },
+ { 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 },
+ { 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b },
+ { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 },
+ { 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a },
+ { 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 },
+};
+
+static const u_int32_t ar956XCommon_rx_gain_table_aphrodite_1p0[][2] = {
+/* Addr allmodes */
+ { 0x0000a000 , 0x00010000 },
+ { 0x0000a004 , 0x00030002 },
+ { 0x0000a008 , 0x00050004 },
+ { 0x0000a00c , 0x00810080 },
+ { 0x0000a010 , 0x00830082 },
+ { 0x0000a014 , 0x01810180 },
+ { 0x0000a018 , 0x01830182 },
+ { 0x0000a01c , 0x01850184 },
+ { 0x0000a020 , 0x01890188 },
+ { 0x0000a024 , 0x018b018a },
+ { 0x0000a028 , 0x018d018c },
+ { 0x0000a02c , 0x01910190 },
+ { 0x0000a030 , 0x01930192 },
+ { 0x0000a034 , 0x01950194 },
+ { 0x0000a038 , 0x038a0196 },
+ { 0x0000a03c , 0x038c038b },
+ { 0x0000a040 , 0x0390038d },
+ { 0x0000a044 , 0x03920391 },
+ { 0x0000a048 , 0x03940393 },
+ { 0x0000a04c , 0x03960395 },
+ { 0x0000a050 , 0x00000000 },
+ { 0x0000a054 , 0x00000000 },
+ { 0x0000a058 , 0x00000000 },
+ { 0x0000a05c , 0x00000000 },
+ { 0x0000a060 , 0x00000000 },
+ { 0x0000a064 , 0x00000000 },
+ { 0x0000a068 , 0x00000000 },
+ { 0x0000a06c , 0x00000000 },
+ { 0x0000a070 , 0x00000000 },
+ { 0x0000a074 , 0x00000000 },
+ { 0x0000a078 , 0x00000000 },
+ { 0x0000a07c , 0x00000000 },
+ { 0x0000a080 , 0x22222229 },
+ { 0x0000a084 , 0x1d1d1d1d },
+ { 0x0000a088 , 0x1d1d1d1d },
+ { 0x0000a08c , 0x1d1d1d1d },
+ { 0x0000a090 , 0x171d1d1d },
+ { 0x0000a094 , 0x11111717 },
+ { 0x0000a098 , 0x00030311 },
+ { 0x0000a09c , 0x00000000 },
+ { 0x0000a0a0 , 0x00000000 },
+ { 0x0000a0a4 , 0x00000000 },
+ { 0x0000a0a8 , 0x00000000 },
+ { 0x0000a0ac , 0x00000000 },
+ { 0x0000a0b0 , 0x00000000 },
+ { 0x0000a0b4 , 0x00000000 },
+ { 0x0000a0b8 , 0x00000000 },
+ { 0x0000a0bc , 0x00000000 },
+ { 0x0000a0c0 , 0x001f0000 },
+ { 0x0000a0c4 , 0x01000101 },
+ { 0x0000a0c8 , 0x011e011f },
+ { 0x0000a0cc , 0x011c011d },
+ { 0x0000a0d0 , 0x02030204 },
+ { 0x0000a0d4 , 0x02010202 },
+ { 0x0000a0d8 , 0x021f0200 },
+ { 0x0000a0dc , 0x0302021e },
+ { 0x0000a0e0 , 0x03000301 },
+ { 0x0000a0e4 , 0x031e031f },
+ { 0x0000a0e8 , 0x0402031d },
+ { 0x0000a0ec , 0x04000401 },
+ { 0x0000a0f0 , 0x041e041f },
+ { 0x0000a0f4 , 0x0502041d },
+ { 0x0000a0f8 , 0x05000501 },
+ { 0x0000a0fc , 0x051e051f },
+ { 0x0000a100 , 0x06010602 },
+ { 0x0000a104 , 0x061f0600 },
+ { 0x0000a108 , 0x061d061e },
+ { 0x0000a10c , 0x07020703 },
+ { 0x0000a110 , 0x07000701 },
+ { 0x0000a114 , 0x00000000 },
+ { 0x0000a118 , 0x00000000 },
+ { 0x0000a11c , 0x00000000 },
+ { 0x0000a120 , 0x00000000 },
+ { 0x0000a124 , 0x00000000 },
+ { 0x0000a128 , 0x00000000 },
+ { 0x0000a12c , 0x00000000 },
+ { 0x0000a130 , 0x00000000 },
+ { 0x0000a134 , 0x00000000 },
+ { 0x0000a138 , 0x00000000 },
+ { 0x0000a13c , 0x00000000 },
+ { 0x0000a140 , 0x001f0000 },
+ { 0x0000a144 , 0x01000101 },
+ { 0x0000a148 , 0x011e011f },
+ { 0x0000a14c , 0x011c011d },
+ { 0x0000a150 , 0x02030204 },
+ { 0x0000a154 , 0x02010202 },
+ { 0x0000a158 , 0x021f0200 },
+ { 0x0000a15c , 0x0302021e },
+ { 0x0000a160 , 0x03000301 },
+ { 0x0000a164 , 0x031e031f },
+ { 0x0000a168 , 0x0402031d },
+ { 0x0000a16c , 0x04000401 },
+ { 0x0000a170 , 0x041e041f },
+ { 0x0000a174 , 0x0502041d },
+ { 0x0000a178 , 0x05000501 },
+ { 0x0000a17c , 0x051e051f },
+ { 0x0000a180 , 0x06010602 },
+ { 0x0000a184 , 0x061f0600 },
+ { 0x0000a188 , 0x061d061e },
+ { 0x0000a18c , 0x07020703 },
+ { 0x0000a190 , 0x07000701 },
+ { 0x0000a194 , 0x00000000 },
+ { 0x0000a198 , 0x00000000 },
+ { 0x0000a19c , 0x00000000 },
+ { 0x0000a1a0 , 0x00000000 },
+ { 0x0000a1a4 , 0x00000000 },
+ { 0x0000a1a8 , 0x00000000 },
+ { 0x0000a1ac , 0x00000000 },
+ { 0x0000a1b0 , 0x00000000 },
+ { 0x0000a1b4 , 0x00000000 },
+ { 0x0000a1b8 , 0x00000000 },
+ { 0x0000a1bc , 0x00000000 },
+ { 0x0000a1c0 , 0x00000000 },
+ { 0x0000a1c4 , 0x00000000 },
+ { 0x0000a1c8 , 0x00000000 },
+ { 0x0000a1cc , 0x00000000 },
+ { 0x0000a1d0 , 0x00000000 },
+ { 0x0000a1d4 , 0x00000000 },
+ { 0x0000a1d8 , 0x00000000 },
+ { 0x0000a1dc , 0x00000000 },
+ { 0x0000a1e0 , 0x00000000 },
+ { 0x0000a1e4 , 0x00000000 },
+ { 0x0000a1e8 , 0x00000000 },
+ { 0x0000a1ec , 0x00000000 },
+ { 0x0000a1f0 , 0x00000396 },
+ { 0x0000a1f4 , 0x00000396 },
+ { 0x0000a1f8 , 0x00000396 },
+ { 0x0000a1fc , 0x00000196 },
+ { 0x0000b000 , 0x00010000 },
+ { 0x0000b004 , 0x00030002 },
+ { 0x0000b008 , 0x00050004 },
+ { 0x0000b00c , 0x00810080 },
+ { 0x0000b010 , 0x00830082 },
+ { 0x0000b014 , 0x01810180 },
+ { 0x0000b018 , 0x01830182 },
+ { 0x0000b01c , 0x01850184 },
+ { 0x0000b020 , 0x02810280 },
+ { 0x0000b024 , 0x02830282 },
+ { 0x0000b028 , 0x02850284 },
+ { 0x0000b02c , 0x02890288 },
+ { 0x0000b030 , 0x028b028a },
+ { 0x0000b034 , 0x0388028c },
+ { 0x0000b038 , 0x038a0389 },
+ { 0x0000b03c , 0x038c038b },
+ { 0x0000b040 , 0x0390038d },
+ { 0x0000b044 , 0x03920391 },
+ { 0x0000b048 , 0x03940393 },
+ { 0x0000b04c , 0x03960395 },
+ { 0x0000b050 , 0x00000000 },
+ { 0x0000b054 , 0x00000000 },
+ { 0x0000b058 , 0x00000000 },
+ { 0x0000b05c , 0x00000000 },
+ { 0x0000b060 , 0x00000000 },
+ { 0x0000b064 , 0x00000000 },
+ { 0x0000b068 , 0x00000000 },
+ { 0x0000b06c , 0x00000000 },
+ { 0x0000b070 , 0x00000000 },
+ { 0x0000b074 , 0x00000000 },
+ { 0x0000b078 , 0x00000000 },
+ { 0x0000b07c , 0x00000000 },
+ { 0x0000b080 , 0x32323232 },
+ { 0x0000b084 , 0x2f2f3232 },
+ { 0x0000b088 , 0x23282a2d },
+ { 0x0000b08c , 0x1c1e2123 },
+ { 0x0000b090 , 0x14171919 },
+ { 0x0000b094 , 0x0e0e1214 },
+ { 0x0000b098 , 0x03050707 },
+ { 0x0000b09c , 0x00030303 },
+ { 0x0000b0a0 , 0x00000000 },
+ { 0x0000b0a4 , 0x00000000 },
+ { 0x0000b0a8 , 0x00000000 },
+ { 0x0000b0ac , 0x00000000 },
+ { 0x0000b0b0 , 0x00000000 },
+ { 0x0000b0b4 , 0x00000000 },
+ { 0x0000b0b8 , 0x00000000 },
+ { 0x0000b0bc , 0x00000000 },
+ { 0x0000b0c0 , 0x003f0020 },
+ { 0x0000b0c4 , 0x00400041 },
+ { 0x0000b0c8 , 0x0140005f },
+ { 0x0000b0cc , 0x0160015f },
+ { 0x0000b0d0 , 0x017e017f },
+ { 0x0000b0d4 , 0x02410242 },
+ { 0x0000b0d8 , 0x025f0240 },
+ { 0x0000b0dc , 0x027f0260 },
+ { 0x0000b0e0 , 0x0341027e },
+ { 0x0000b0e4 , 0x035f0340 },
+ { 0x0000b0e8 , 0x037f0360 },
+ { 0x0000b0ec , 0x04400441 },
+ { 0x0000b0f0 , 0x0460045f },
+ { 0x0000b0f4 , 0x0541047f },
+ { 0x0000b0f8 , 0x055f0540 },
+ { 0x0000b0fc , 0x057f0560 },
+ { 0x0000b100 , 0x06400641 },
+ { 0x0000b104 , 0x0660065f },
+ { 0x0000b108 , 0x067e067f },
+ { 0x0000b10c , 0x07410742 },
+ { 0x0000b110 , 0x075f0740 },
+ { 0x0000b114 , 0x077f0760 },
+ { 0x0000b118 , 0x07800781 },
+ { 0x0000b11c , 0x07a0079f },
+ { 0x0000b120 , 0x07c107bf },
+ { 0x0000b124 , 0x000007c0 },
+ { 0x0000b128 , 0x00000000 },
+ { 0x0000b12c , 0x00000000 },
+ { 0x0000b130 , 0x00000000 },
+ { 0x0000b134 , 0x00000000 },
+ { 0x0000b138 , 0x00000000 },
+ { 0x0000b13c , 0x00000000 },
+ { 0x0000b140 , 0x003f0020 },
+ { 0x0000b144 , 0x00400041 },
+ { 0x0000b148 , 0x0140005f },
+ { 0x0000b14c , 0x0160015f },
+ { 0x0000b150 , 0x017e017f },
+ { 0x0000b154 , 0x02410242 },
+ { 0x0000b158 , 0x025f0240 },
+ { 0x0000b15c , 0x027f0260 },
+ { 0x0000b160 , 0x0341027e },
+ { 0x0000b164 , 0x035f0340 },
+ { 0x0000b168 , 0x037f0360 },
+ { 0x0000b16c , 0x04400441 },
+ { 0x0000b170 , 0x0460045f },
+ { 0x0000b174 , 0x0541047f },
+ { 0x0000b178 , 0x055f0540 },
+ { 0x0000b17c , 0x057f0560 },
+ { 0x0000b180 , 0x06400641 },
+ { 0x0000b184 , 0x0660065f },
+ { 0x0000b188 , 0x067e067f },
+ { 0x0000b18c , 0x07410742 },
+ { 0x0000b190 , 0x075f0740 },
+ { 0x0000b194 , 0x077f0760 },
+ { 0x0000b198 , 0x07800781 },
+ { 0x0000b19c , 0x07a0079f },
+ { 0x0000b1a0 , 0x07c107bf },
+ { 0x0000b1a4 , 0x000007c0 },
+ { 0x0000b1a8 , 0x00000000 },
+ { 0x0000b1ac , 0x00000000 },
+ { 0x0000b1b0 , 0x00000000 },
+ { 0x0000b1b4 , 0x00000000 },
+ { 0x0000b1b8 , 0x00000000 },
+ { 0x0000b1bc , 0x00000000 },
+ { 0x0000b1c0 , 0x00000000 },
+ { 0x0000b1c4 , 0x00000000 },
+ { 0x0000b1c8 , 0x00000000 },
+ { 0x0000b1cc , 0x00000000 },
+ { 0x0000b1d0 , 0x00000000 },
+ { 0x0000b1d4 , 0x00000000 },
+ { 0x0000b1d8 , 0x00000000 },
+ { 0x0000b1dc , 0x00000000 },
+ { 0x0000b1e0 , 0x00000000 },
+ { 0x0000b1e4 , 0x00000000 },
+ { 0x0000b1e8 , 0x00000000 },
+ { 0x0000b1ec , 0x00000000 },
+ { 0x0000b1f0 , 0x00000396 },
+ { 0x0000b1f4 , 0x00000396 },
+ { 0x0000b1f8 , 0x00000396 },
+ { 0x0000b1fc , 0x00000196 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_baseband_postamble_emulation[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x00009e44 , 0xfc500000 , 0xfc500000 , 0xfc500000 , 0xfc500000 },
+ { 0x0000a258 , 0x02020002 , 0x02020002 , 0x02020002 , 0x02020002 },
+ { 0x0000a25c , 0x01000e0e , 0x01000e0e , 0x01000e0e , 0x01000e0e },
+ { 0x0000a28c , 0x00022222 , 0x00022222 , 0x00022222 , 0x00022222 },
+ { 0x0000a2c4 , 0x00158d18 , 0x00158d18 , 0x00158d18 , 0x00158d18 },
+ { 0x0000a2d8 , 0x7999a800 , 0x7999a800 , 0x7999a80c , 0x7999a80c },
+ { 0x0000a50c , 0x0000c00a , 0x0000c00a , 0x0000c00a , 0x0000c00a },
+ { 0x0000a538 , 0x00038e8c , 0x00038e8c , 0x00038e8c , 0x00038e8c },
+ { 0x0000a53c , 0x0003cecc , 0x0003cecc , 0x0003cecc , 0x0003cecc },
+ { 0x0000a540 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 },
+ { 0x0000a544 , 0x00044edc , 0x00044edc , 0x00044edc , 0x00044edc },
+ { 0x0000a548 , 0x00048ede , 0x00048ede , 0x00048ede , 0x00048ede },
+ { 0x0000a54c , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e },
+ { 0x0000a550 , 0x00050f5e , 0x00050f5e , 0x00050f5e , 0x00050f5e },
+ { 0x0000a554 , 0x00054f9e , 0x00054f9e , 0x00054f9e , 0x00054f9e },
+ { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+};
+
+static const u_int32_t ar956X_aphrodite_1p0_baseband_postamble[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00009810 , 0xd00a8005 , 0xd00a8005 , 0xd00a8005 , 0xd00a8005 },
+ { 0x00009820 , 0x206a022e , 0x206a022e , 0x206a012e , 0x206a012e },
+ { 0x00009824 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 , 0x5ac640d0 },
+ { 0x00009828 , 0x06903081 , 0x06903081 , 0x06903881 , 0x06903881 },
+ { 0x0000982c , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 , 0x05eea6d4 },
+ { 0x00009830 , 0x0000059c , 0x0000059c , 0x0000059c , 0x0000059c },
+ { 0x00009c00 , 0x00000044 , 0x000000c4 , 0x000000c4 , 0x00000044 },
+ { 0x00009e00 , 0x0372161e , 0x0372161e , 0x037216a0 , 0x037216a0 },
+ { 0x00009e04 , 0x00802020 , 0x00802020 , 0x00802020 , 0x00802020 },
+ { 0x00009e0c , 0x6c4000e2 , 0x6d4000e2 , 0x6d4000e2 , 0x6c4000e2 },
+ { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec84d2e , 0x7ec84d2e },
+ { 0x00009e14 , 0x31395d5e , 0x3139605e , 0x3139605e , 0x31395d5e },
+ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c },
+ { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce },
+ { 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 },
+ { 0x00009e44 , 0xfe321e27 , 0xfe321e27 , 0xfe291e27 , 0xfe291e27 },
+ { 0x00009e48 , 0x5030201a , 0x5030201a , 0x50302010 , 0x50302010 },
+ { 0x00009fc8 , 0x0003f000 , 0x0003f000 , 0x0001a000 , 0x0001a000 },
+ { 0x0000a204 , 0x033007c0 , 0x033007c4 , 0x033007c4 , 0x033007c0 },
+ { 0x0000a208 , 0x00000104 , 0x00000104 , 0x00000004 , 0x00000004 },
+ { 0x0000a230 , 0x0000400a , 0x00004014 , 0x00004016 , 0x0000400b },
+ { 0x0000a238 , 0xffb81018 , 0xffb81018 , 0xffb81018 , 0xffb81018 },
+ { 0x0000a250 , 0x00000000 , 0x00000000 , 0x00000210 , 0x00000108 },
+ { 0x0000a254 , 0x000007d0 , 0x00000fa0 , 0x00001130 , 0x00000898 },
+ { 0x0000a258 , 0x02020002 , 0x02020002 , 0x02020002 , 0x02020002 },
+ { 0x0000a25c , 0x01000e0e , 0x01000e0e , 0x01000e0e , 0x01000e0e },
+ { 0x0000a260 , 0x0a021501 , 0x0a021501 , 0x3a021501 , 0x3a021501 },
+ { 0x0000a264 , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e },
+ { 0x0000a280 , 0x00000007 , 0x00000007 , 0x0000000b , 0x0000000b },
+ { 0x0000a284 , 0x00000000 , 0x00000000 , 0x00000150 , 0x00000150 },
+ { 0x0000a288 , 0x00000110 , 0x00000110 , 0x00000110 , 0x00000110 },
+ { 0x0000a28c , 0x00022222 , 0x00022222 , 0x00022222 , 0x00022222 },
+ { 0x0000a2c4 , 0x00158d18 , 0x00158d18 , 0x00158d18 , 0x00158d18 },
+ { 0x0000a2d0 , 0x00071981 , 0x00071981 , 0x00071981 , 0x00071981 },
+ { 0x0000a2d8 , 0xf999a83a , 0xf999a83a , 0xf999a83a , 0xf999a83a },
+ { 0x0000a358 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x0000ae04 , 0x00800000 , 0x00800000 , 0x00800000 , 0x00800000 },
+ { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+};
+
diff --git a/hal/ar9300/ar9300_attach.c b/hal/ar9300/ar9300_attach.c
new file mode 100644
index 000000000000..9de27610c088
--- /dev/null
+++ b/hal/ar9300/ar9300_attach.c
@@ -0,0 +1,3965 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#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"
+
+
+/* Add static register initialization vectors */
+#include "ar9300/ar9300_osprey22.ini"
+#include "ar9300/ar9330_11.ini"
+#include "ar9300/ar9330_12.ini"
+#include "ar9300/ar9340.ini"
+#include "ar9300/ar9485.ini"
+#include "ar9300/ar9485_1_1.ini"
+#include "ar9300/ar9300_jupiter10.ini"
+#include "ar9300/ar9300_jupiter20.ini"
+#include "ar9300/ar9580.ini"
+#include "ar9300/ar955x.ini"
+#include "ar9300/ar9300_aphrodite10.ini"
+
+
+static HAL_BOOL ar9300_get_chip_power_limits(struct ath_hal *ah,
+ HAL_CHANNEL *chans, u_int32_t nchans);
+
+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);
+int ar9300_get_cal_intervals(struct ath_hal *ah, HAL_CALIBRATION_TIMER **timerp,
+ HAL_CAL_QUERY query);
+#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};
+
+static HAL_CALIBRATION_TIMER ar9300_cals[] =
+ { {IQ_MISMATCH_CAL, /* Cal type */
+ 1200000, /* Cal interval */
+ 0 /* Cal timestamp */
+ },
+ {TEMP_COMP_CAL,
+ 5000,
+ 0
+ },
+ };
+
+#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 */
+
+/* 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_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 */
+
+ /* 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 */
+
+ /* Beacon Functions */
+ ar9300_beacon_init, /* ah_beacon_init */
+ ar9300_set_sta_beacon_timers, /* ah_set_station_beacon_timers */
+
+ /* Interrupt Functions */
+ ar9300_is_interrupt_pending, /* ah_is_interrupt_pending */
+ ar9300_get_pending_interrupts, /* ah_get_pending_interrupts */
+ ar9300_get_interrupts, /* ah_get_interrupts */
+ ar9300_set_interrupts, /* ah_set_interrupts */
+ ar9300_set_intr_mitigation_timer, /* ah_set_intr_mitigation_timer */
+ ar9300_get_intr_mitigation_timer, /* ah_get_intr_mitigation_timer */
+ ar9300ForceVCS,
+ ar9300SetDfs3StreamFix,
+ ar9300Get3StreamSignature,
+
+ /* 11n specific functions (NOT applicable to ar9300) */
+ ar9300_set_11n_tx_desc, /* ah_set_11n_tx_desc */
+ /* Update rxchain */
+ ar9300_set_rx_chainmask, /*ah_set_rx_chainmask*/
+ /*Updating locationing register */
+ ar9300_update_loc_ctl_reg, /*ah_update_loc_ctl_reg*/
+ /* Start PAPRD functions */
+ ar9300_set_paprd_tx_desc, /* ah_set_paprd_tx_desc */
+ ar9300_paprd_init_table, /* ah_paprd_init_table */
+ ar9300_paprd_setup_gain_table, /* ah_paprd_setup_gain_table */
+ ar9300_paprd_create_curve, /* ah_paprd_create_curve */
+ ar9300_paprd_is_done, /* ah_paprd_is_done */
+ ar9300_enable_paprd, /* ah_PAPRDEnable */
+ ar9300_populate_paprd_single_table,/* ah_paprd_populate_table */
+ ar9300_is_tx_done, /* ah_is_tx_done */
+ ar9300_paprd_dec_tx_pwr, /* ah_paprd_dec_tx_pwr*/
+ ar9300_paprd_thermal_send, /* ah_paprd_thermal_send */
+ /* End PAPRD functions */
+ ar9300_set_11n_rate_scenario, /* ah_set_11n_rate_scenario */
+ ar9300_set_11n_aggr_first, /* ah_set_11n_aggr_first */
+ ar9300_set_11n_aggr_middle, /* ah_set_11n_aggr_middle */
+ ar9300_set_11n_aggr_last, /* ah_set_11n_aggr_last */
+ ar9300_clr_11n_aggr, /* ah_clr_11n_aggr */
+ ar9300_set_11n_rifs_burst_middle, /* ah_set_11n_rifs_burst_middle */
+ ar9300_set_11n_rifs_burst_last, /* ah_set_11n_rifs_burst_last */
+ ar9300_clr_11n_rifs_burst, /* ah_clr_11n_rifs_burst */
+ ar9300_set_11n_aggr_rifs_burst, /* ah_set_11n_aggr_rifs_burst */
+ ar9300_set_11n_rx_rifs, /* ah_set_11n_rx_rifs */
+ ar9300_set_smart_antenna, /* ah_setSmartAntenna */
+ ar9300_detect_bb_hang, /* ah_detect_bb_hang */
+ ar9300_detect_mac_hang, /* ah_detect_mac_hang */
+ ar9300_set_immunity, /* ah_immunity */
+ ar9300_get_hw_hangs, /* ah_get_hang_types */
+ ar9300_set_11n_burst_duration, /* ah_set_11n_burst_duration */
+ ar9300_set_11n_virtual_more_frag, /* ah_set_11n_virtual_more_frag */
+ ar9300_get_11n_ext_busy, /* ah_get_11n_ext_busy */
+ ar9300_set_11n_mac2040, /* ah_set_11n_mac2040 */
+ ar9300_get_11n_rx_clear, /* ah_get_11n_rx_clear */
+ ar9300_set_11n_rx_clear, /* ah_set_11n_rx_clear */
+ ar9300_get_mib_cycle_counts_pct, /* ah_get_mib_cycle_counts_pct */
+ ar9300_dma_reg_dump, /* ah_dma_reg_dump */
+
+ /* force_ppm specific functions */
+ ar9300_ppm_get_rssi_dump, /* ah_ppm_get_rssi_dump */
+ ar9300_ppm_arm_trigger, /* ah_ppm_arm_trigger */
+ ar9300_ppm_get_trigger, /* ah_ppm_get_trigger */
+ ar9300_ppm_force, /* ah_ppm_force */
+ ar9300_ppm_un_force, /* ah_ppm_un_force */
+ ar9300_ppm_get_force_state, /* ah_ppm_get_force_state */
+
+ ar9300_get_spur_info, /* ah_get_spur_info */
+ ar9300_set_spur_info, /* ah_get_spur_info */
+
+ ar9300_get_min_cca_pwr, /* ah_ar_get_noise_floor_val */
+
+ ar9300_green_ap_ps_on_off, /* ah_set_rx_green_ap_ps_on_off */
+ ar9300_is_single_ant_power_save_possible, /* ah_is_single_ant_power_save_possible */
+
+ /* radio measurement specific functions */
+ ar9300_get_mib_cycle_counts, /* ah_get_mib_cycle_counts */
+ ar9300_get_vow_stats, /* ah_get_vow_stats */
+ ar9300_clear_mib_counters, /* ah_clear_mib_counters */
+#if ATH_GEN_RANDOMNESS
+ ar9300_get_rssi_chain0, /* ah_get_rssi_chain0 */
+#endif
+#ifdef ATH_BT_COEX
+ /* Bluetooth Coexistence functions */
+ ar9300_set_bt_coex_info, /* ah_set_bt_coex_info */
+ ar9300_bt_coex_config, /* ah_bt_coex_config */
+ ar9300_bt_coex_set_qcu_thresh, /* ah_bt_coex_set_qcu_thresh */
+ ar9300_bt_coex_set_weights, /* ah_bt_coex_set_weights */
+ ar9300_bt_coex_setup_bmiss_thresh, /* ah_bt_coex_set_bmiss_thresh */
+ ar9300_bt_coex_set_parameter, /* ah_bt_coex_set_parameter */
+ ar9300_bt_coex_disable, /* ah_bt_coex_disable */
+ ar9300_bt_coex_enable, /* ah_bt_coex_enable */
+ ar9300_get_bt_active_gpio, /* ah_bt_coex_info*/
+ ar9300_get_wlan_active_gpio, /* ah__coex_wlan_info*/
+#endif
+ /* Generic Timer functions */
+ ar9300_alloc_generic_timer, /* ah_gentimer_alloc */
+ ar9300_free_generic_timer, /* ah_gentimer_free */
+ ar9300_start_generic_timer, /* ah_gentimer_start */
+ ar9300_stop_generic_timer, /* ah_gentimer_stop */
+ ar9300_get_gen_timer_interrupts, /* ah_gentimer_get_intr */
+
+ ar9300_set_dcs_mode, /* ah_set_dcs_mode */
+ ar9300_get_dcs_mode, /* ah_get_dcs_mode */
+
+#if ATH_ANT_DIV_COMB
+ ar9300_ant_div_comb_get_config, /* ah_get_ant_dvi_comb_conf */
+ ar9300_ant_div_comb_set_config, /* ah_set_ant_dvi_comb_conf */
+#endif
+
+ ar9300_get_bb_panic_info, /* ah_get_bb_panic_info */
+ ar9300_handle_radar_bb_panic, /* ah_handle_radar_bb_panic */
+ ar9300_set_hal_reset_reason, /* ah_set_hal_reset_reason */
+
+#if ATH_PCIE_ERROR_MONITOR
+ ar9300_start_pcie_error_monitor, /* ah_start_pcie_error_monitor */
+ ar9300_read_pcie_error_monitor, /* ah_read_pcie_error_monitor*/
+ ar9300_stop_pcie_error_monitor, /* ah_stop_pcie_error_monitor*/
+#endif /* ATH_PCIE_ERROR_MONITOR */
+
+#if ATH_SUPPORT_SPECTRAL
+ /* Spectral scan */
+ ar9300_configure_spectral_scan, /* ah_ar_configure_spectral */
+ ar9300_get_spectral_params, /* ah_ar_get_spectral_config */
+ ar9300_start_spectral_scan, /* ah_ar_start_spectral_scan */
+ ar9300_stop_spectral_scan, /* ah_ar_stop_spectral_scan */
+ ar9300_is_spectral_enabled, /* ah_ar_is_spectral_enabled */
+ ar9300_is_spectral_active, /* ah_ar_is_spectral_active */
+ ar9300_get_ctl_chan_nf, /* ah_ar_get_ctl_nf */
+ ar9300_get_ext_chan_nf, /* ah_ar_get_ext_nf */
+#endif /* ATH_SUPPORT_SPECTRAL */
+
+
+ ar9300_promisc_mode, /* ah_promisc_mode */
+ ar9300_read_pktlog_reg, /* ah_read_pktlog_reg */
+ ar9300_write_pktlog_reg, /* ah_write_pktlog_reg */
+ ar9300_set_proxy_sta, /* ah_set_proxy_sta */
+ ar9300_get_cal_intervals, /* ah_get_cal_intervals */
+#if ATH_TRAFFIC_FAST_RECOVER
+ ar9300_get_pll3_sqsum_dvc, /* ah_get_pll3_sqsum_dvc */
+#endif
+#ifdef ATH_SUPPORT_HTC
+ AH_NULL,
+#endif
+
+#ifdef ATH_TX99_DIAG
+ /* Tx99 functions */
+#ifdef ATH_SUPPORT_HTC
+ AH_NULL,
+ AH_NULL,
+ AH_NULL,
+ AH_NULL,
+ AH_NULL,
+ AH_NULL,
+ AH_NULL,
+#else
+ AH_NULL,
+ AH_NULL,
+ ar9300TX99TgtChannelPwrUpdate, /* ah_tx99channelpwrupdate */
+ ar9300TX99TgtStart, /* ah_tx99start */
+ ar9300TX99TgtStop, /* ah_tx99stop */
+ ar9300TX99TgtChainmskSetup, /* ah_tx99_chainmsk_setup */
+ ar9300TX99SetSingleCarrier, /* ah_tx99_set_single_carrier */
+#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_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 */
+};
+
+/*
+ * 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_AR955X) {
+ /* XXX: AR_SREV register in Scorpion reads 0 */
+ AH_PRIVATE(ah)->ah_macVersion = AR_SREV_VERSION_SCORPION;
+ } else {
+ /*
+ * Include 6-bit Chip Type (masked to 0)
+ * to differentiate from pre-Sowl versions
+ */
+ AH_PRIVATE(ah)->ah_macVersion =
+ (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+ }
+
+
+
+
+
+#ifdef AH_SUPPORT_HORNET
+ /*
+ * EV74984, due to Hornet 1.1 didn't update WMAC revision,
+ * so that have to read SoC's revision ID instead
+ */
+ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_HORNET) {
+#define AR_SOC_RST_REVISION_ID 0xB8060090
+#define REG_READ(_reg) *((volatile u_int32_t *)(_reg))
+ if ((REG_READ(AR_SOC_RST_REVISION_ID) & AR_SREV_REVISION_HORNET_11_MASK)
+ == AR_SREV_REVISION_HORNET_11)
+ {
+ AH_PRIVATE(ah)->ah_macRev = AR_SREV_REVISION_HORNET_11;
+ } else {
+ AH_PRIVATE(ah)->ah_macRev = MS(val, AR_SREV_REVISION2);
+ }
+#undef REG_READ
+#undef AR_SOC_RST_REVISION_ID
+ } else
+#endif
+ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_WASP)
+ {
+#define AR_SOC_RST_REVISION_ID 0xB8060090
+#define REG_READ(_reg) *((volatile u_int32_t *)(_reg))
+
+ AH_PRIVATE(ah)->ah_macRev =
+ REG_READ(AR_SOC_RST_REVISION_ID) & AR_SREV_REVISION_WASP_MASK;
+#undef REG_READ
+#undef AR_SOC_RST_REVISION_ID
+ }
+ else
+ AH_PRIVATE(ah)->ah_macRev = MS(val, AR_SREV_REVISION2);
+
+ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
+ AH_PRIVATE(ah)->ah_is_pci_express = AH_TRUE;
+ }
+ else {
+ AH_PRIVATE(ah)->ah_is_pci_express =
+ (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+ }
+
+}
+
+/*
+ * Attach for an AR9300 part.
+ */
+struct ath_hal *
+ar9300_attach(u_int16_t devid, HAL_ADAPTER_HANDLE osdev, HAL_SOFTC sc,
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_BUS_TYPE bustype,
+ asf_amem_instance_handle amem_handle,
+ struct hal_reg_parm *hal_conf_parm, 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, osdev, sc, st, sh, bustype, amem_handle, hal_conf_parm, status);
+ if (ahp == AH_NULL) {
+ return AH_NULL;
+ }
+ ah = &ahp->ah_priv.priv.h;
+ ar9300_init_offsets(ah, devid);
+ ahpriv = AH_PRIVATE(ah);
+ AH_PRIVATE(ah)->ah_bustype = bustype;
+
+
+ /* interrupt mitigation */
+#ifdef AR5416_INT_MITIGATION
+ if (ahpriv->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;
+ ahpriv->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
+ ahpriv->ah_config.ath_hal_intr_mitigation_rx = 0;
+#endif
+ }
+#endif
+
+ if (ahpriv->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)) {
+ 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;
+ ahp->ah_mci_ready = AH_FALSE;
+ ahp->ah_mci_bt_state = MCI_BT_SLEEP;
+ ahp->ah_mci_coex_major_version_wlan = MCI_GPM_COEX_MAJOR_VERSION_WLAN;
+ ahp->ah_mci_coex_minor_version_wlan = MCI_GPM_COEX_MINOR_VERSION_WLAN;
+ ahp->ah_mci_coex_major_version_bt = MCI_GPM_COEX_MAJOR_VERSION_DEFAULT;
+ ahp->ah_mci_coex_minor_version_bt = MCI_GPM_COEX_MINOR_VERSION_DEFAULT;
+ ahp->ah_mci_coex_bt_version_known = AH_FALSE;
+ ahp->ah_mci_coex_2g5g_update = AH_TRUE; /* track if 2g5g status sent */
+ /* will be updated before boot up sequence */
+ ahp->ah_mci_coex_is_2g = AH_TRUE;
+ ahp->ah_mci_coex_wlan_channels_update = AH_FALSE;
+ ahp->ah_mci_coex_wlan_channels[0] = 0x00000000;
+ ahp->ah_mci_coex_wlan_channels[1] = 0xffffffff;
+ ahp->ah_mci_coex_wlan_channels[2] = 0xffffffff;
+ ahp->ah_mci_coex_wlan_channels[3] = 0x7fffffff;
+ ahp->ah_mci_query_bt = AH_TRUE; /* In case WLAN start after BT */
+ ahp->ah_mci_unhalt_bt_gpm = AH_TRUE; /* Send UNHALT at beginning */
+ ahp->ah_mci_halted_bt_gpm = AH_FALSE; /* Allow first HALT */
+ ahp->ah_mci_need_flush_btinfo = AH_FALSE;
+ ahp->ah_mci_wlan_cal_seq = 0;
+ ahp->ah_mci_wlan_cal_done = 0;
+ }
+#endif /* ATH_SUPPORT_MCI */
+
+#if ATH_WOW_OFFLOAD
+ ahp->ah_mcast_filter_l32_set = 0;
+ ahp->ah_mcast_filter_u32_set = 0;
+#endif
+
+ if (AR_SREV_HORNET(ah)) {
+#ifdef AH_SUPPORT_HORNET
+ if (!AR_SREV_HORNET_11(ah)) {
+ /*
+ * Do not check bootstrap register, which cannot be trusted
+ * due to s26 switch issue on CUS164/AP121.
+ */
+ ahp->clk_25mhz = 1;
+ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 25MHz\n");
+ } else {
+ /* check bootstrap clock setting */
+#define AR_SOC_SEL_25M_40M 0xB80600AC
+#define REG_WRITE(_reg, _val) *((volatile u_int32_t *)(_reg)) = (_val);
+#define REG_READ(_reg) (*((volatile u_int32_t *)(_reg)))
+ if (REG_READ(AR_SOC_SEL_25M_40M) & 0x1) {
+ ahp->clk_25mhz = 0;
+ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
+ "Bootstrap clock 40MHz\n");
+ } else {
+ ahp->clk_25mhz = 1;
+ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
+ "Bootstrap clock 25MHz\n");
+ }
+#undef REG_READ
+#undef REG_WRITE
+#undef AR_SOC_SEL_25M_40M
+ }
+#endif /* AH_SUPPORT_HORNET */
+ }
+
+ if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
+ /* check bootstrap clock setting */
+#define AR9340_SOC_SEL_25M_40M 0xB80600B0
+#define AR9340_REF_CLK_40 (1 << 4) /* 0 - 25MHz 1 - 40 MHz */
+#define REG_READ(_reg) (*((volatile u_int32_t *)(_reg)))
+ if (REG_READ(AR9340_SOC_SEL_25M_40M) & AR9340_REF_CLK_40) {
+ ahp->clk_25mhz = 0;
+ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 40MHz\n");
+ } else {
+ ahp->clk_25mhz = 1;
+ HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "Bootstrap clock 25MHz\n");
+ }
+#undef REG_READ
+#undef AR9340_SOC_SEL_25M_40M
+#undef AR9340_REF_CLK_40
+ }
+ ar9300_init_pll(ah, AH_NULL);
+
+ if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: couldn't wakeup chip\n", __func__);
+ ecode = HAL_EIO;
+ goto bad;
+ }
+
+ /* No serialization of Register Accesses needed. */
+ ahpriv->ah_config.ath_hal_serialize_reg_mode = SER_REG_MODE_OFF;
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: ath_hal_serialize_reg_mode is %d\n",
+ __func__, ahpriv->ah_config.ath_hal_serialize_reg_mode);
+
+ /*
+ * Add mac revision check when needed.
+ * - Osprey 1.0 and 2.0 no longer supported.
+ */
+ if (((ahpriv->ah_macVersion == AR_SREV_VERSION_OSPREY) &&
+ (ahpriv->ah_macRev <= AR_SREV_REVISION_OSPREY_20)) ||
+ (ahpriv->ah_macVersion != AR_SREV_VERSION_OSPREY &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_WASP &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_HORNET &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_POSEIDON &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_SCORPION &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_JUPITER &&
+ ahpriv->ah_macVersion != AR_SREV_VERSION_APHRODITE) ) {
+ HALDEBUG(ah, HAL_DEBUG_RESET,
+ "%s: Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
+ __func__,
+ ahpriv->ah_macVersion,
+ ahpriv->ah_macRev);
+ ecode = HAL_ENOTSUPP;
+ goto bad;
+ }
+
+ ahpriv->ah_phy_rev = 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;
+
+ 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);
+
+ ahpriv->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);
+
+ ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ /* Pci-e Clock Request = 1 */
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save
+ & AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Sleep Setting */
+ if (ahpriv->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 (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save
+ & AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Sleep Setting */
+ if (ahpriv->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 (ahpriv->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 */
+ //ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ /* Pci-e Clock Request = 1 */
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save
+ & AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Sleep Setting */
+ if (ahpriv->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 (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save
+ & AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Sleep Setting */
+ if (ahpriv->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 (ahpriv->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 */
+ /*ahpriv->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);
+
+ ahpriv->ah_config.ath_hal_pcie_power_save_enable = 0;
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional,
+ ar9340Modes_fast_clock_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_fast_clock_wasp_1p0), 3);
+
+ /* Additional setttings for 40Mhz */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional_40mhz,
+ ar9340_wasp_1p0_radio_core_40M,
+ ARRAY_LENGTH(ar9340_wasp_1p0_radio_core_40M), 2);
+
+ /* DFS */
+ INIT_INI_ARRAY(&ahp->ah_ini_dfs,
+ ar9340_wasp_1p0_baseband_postamble_dfs_channel,
+ ARRAY_LENGTH(ar9340_wasp_1p0_baseband_postamble_dfs_channel), 3);
+ } else if (AR_SREV_SCORPION(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE],
+ ar955x_scorpion_1p0_mac_core,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST],
+ ar955x_scorpion_1p0_mac_postamble,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE],
+ ar955x_scorpion_1p0_baseband_core,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST],
+ ar955x_scorpion_1p0_baseband_postamble,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE],
+ ar955x_scorpion_1p0_radio_core,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST],
+ ar955x_scorpion_1p0_radio_postamble,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE],
+ ar955x_scorpion_1p0_soc_preamble,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST],
+ ar955x_scorpion_1p0_soc_postamble,
+ ARRAY_LENGTH(ar955x_scorpion_1p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds,
+ ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0), 5);
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar955xModes_no_xpa_tx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xModes_no_xpa_tx_gain_table_scorpion_1p0), 5);
+
+ /*ath_hal_pciePowerSaveEnable should be 2 for OWL/Condor and 0 for merlin */
+ ahpriv->ah_config.ath_hal_pcie_power_save_enable = 0;
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional,
+ ar955xModes_fast_clock_scorpion_1p0,
+ ARRAY_LENGTH(ar955xModes_fast_clock_scorpion_1p0), 3);
+
+ /* Additional setttings for 40Mhz */
+ //INIT_INI_ARRAY(&ahp->ah_ini_modes_additional_40M,
+ // ar955x_scorpion_1p0_radio_core_40M,
+ // ARRAY_LENGTH(ar955x_scorpion_1p0_radio_core_40M), 2);
+ } else if (AR_SREV_JUPITER_10(ah)) {
+ /* Jupiter: new INI format (pre, core, post arrays per subsystem) */
+
+ /* mac */
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE],
+ ar9300_jupiter_1p0_mac_core,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST],
+ ar9300_jupiter_1p0_mac_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE],
+ ar9300_jupiter_1p0_baseband_core,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST],
+ ar9300_jupiter_1p0_baseband_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE],
+ ar9300_jupiter_1p0_radio_core,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST],
+ ar9300_jupiter_1p0_radio_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE],
+ ar9300_jupiter_1p0_soc_preamble,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST],
+ ar9300_jupiter_1p0_soc_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_1p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_rx_gain_table_jupiter_1p0,
+ ARRAY_LENGTH(ar9300_common_rx_gain_table_jupiter_1p0), 2);
+
+ /* Load PCIE SERDES settings from INI */
+ if (ahpriv->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.
+ */
+ ahpriv->ah_config.ath_hal_pll_pwr_save = 0;
+ /* Pci-e Clock Request = 0 */
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Awake -> Sleep Setting */
+ if (ahpriv->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 (ahpriv->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
+ */
+ ahpriv->ah_config.ath_hal_pcie_power_save_enable = 0;
+
+#if 0 // ATH_WOW
+ /* SerDes values during WOW sleep */
+ INIT_INI_ARRAY(&ahp->ah_ini_pcie_serdes_wow, ar9300_pcie_phy_AWOW,
+ ARRAY_LENGTH(ar9300_pcie_phy_AWOW), 2);
+#endif
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_additional,
+ ar9300_modes_fast_clock_jupiter_1p0,
+ ARRAY_LENGTH(ar9300_modes_fast_clock_jupiter_1p0), 3);
+ INIT_INI_ARRAY(&ahp->ah_ini_japan2484,
+ ar9300_jupiter_1p0_baseband_core_txfir_coeff_japan_2484,
+ ARRAY_LENGTH(
+ ar9300_jupiter_1p0_baseband_core_txfir_coeff_japan_2484), 2);
+
+ }
+ else if (AR_SREV_JUPITER_20(ah)) {
+ /* Jupiter: new INI format (pre, core, post arrays per subsystem) */
+
+ /* mac */
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_CORE],
+ ar9300_jupiter_2p0_mac_core,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_mac_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_mac[ATH_INI_POST],
+ ar9300_jupiter_2p0_mac_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_CORE],
+ ar9300_jupiter_2p0_baseband_core,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_bb[ATH_INI_POST],
+ ar9300_jupiter_2p0_baseband_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_CORE],
+ ar9300_jupiter_2p0_radio_core,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_radio_core), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio[ATH_INI_POST],
+ ar9300_jupiter_2p0_radio_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_radio_postamble), 5);
+ INIT_INI_ARRAY(&ahp->ah_ini_radio_post_sys2ant,
+ ar9300_jupiter_2p0_radio_postamble_sys2ant,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_radio_postamble_sys2ant), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_PRE],
+ ar9300_jupiter_2p0_soc_preamble,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ahp->ah_ini_soc[ATH_INI_POST],
+ ar9300_jupiter_2p0_soc_postamble,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300Common_rx_gain_table_jupiter_2p0,
+ ARRAY_LENGTH(ar9300Common_rx_gain_table_jupiter_2p0), 2);
+
+ /* BTCOEX */
+ INIT_INI_ARRAY(&ahp->ah_ini_BTCOEX_MAX_TXPWR,
+ ar9300_jupiter_2p0_BTCOEX_MAX_TXPWR_table,
+ ARRAY_LENGTH(ar9300_jupiter_2p0_BTCOEX_MAX_TXPWR_table), 2);
+
+ /* Load PCIE SERDES settings from INI */
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {
+ /* Awake -> Sleep Setting */
+ if (ahpriv->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 (ahpriv->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
+ */
+ ahpriv->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
+ */
+ ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {//registry control
+ if (ahpriv->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);
+ }
+ }
+
+ ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pcie_clock_req) {
+ if (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ { //registry control
+ if (ahpriv->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 (ahpriv->ah_config.ath_hal_pll_pwr_save &
+ AR_PCIE_PLL_PWRSAVE_CONTROL)
+ {//registry control
+ if (ahpriv->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);
+ }
+ }
+
+ ahpriv->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 */
+ ahpriv->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_is_pci_express) {
+ ar9300_config_pci_power_save(ah, 0, 0);
+ } else {
+ ar9300_disable_pcie_phy(ah);
+ }
+ 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.
+ */
+ ahpriv->ah_tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
+
+ if (AR_SREV_HORNET(ah)) {
+ ahpriv->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_HORNET_2GHZ;
+ ahpriv->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ;
+ ahpriv->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_2GHZ;
+ ahpriv->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ;
+ ahpriv->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ;
+ ahpriv->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_5GHZ;
+ ahpriv->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA;
+ } else if(AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)){
+ ahpriv->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_JUPITER_2GHZ;
+ ahpriv->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ;
+ ahpriv->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_JUPITER_2GHZ;
+ ahpriv->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_JUPITER_5GHZ;
+ ahpriv->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ;
+ ahpriv->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_JUPITER_5GHZ;
+ ahpriv->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA;
+ } else {
+ ahpriv->nf_2GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_2GHZ;
+ ahpriv->nf_2GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ;
+ ahpriv->nf_2GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_2GHZ;
+ if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
+ ahpriv->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_PEACOCK_5GHZ;
+ } else {
+ ahpriv->nf_5GHz.nominal = AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ;
+ }
+ ahpriv->nf_5GHz.max = AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_5GHZ;
+ ahpriv->nf_5GHz.min = AR_PHY_CCA_MIN_GOOD_VAL_OSPREY_5GHZ;
+ ahpriv->nf_cw_int_delta = AR_PHY_CCA_CW_INT_DELTA;
+ }
+
+
+
+
+ /* init BB Panic Watchdog timeout */
+ if (AR_SREV_HORNET(ah)) {
+ ahpriv->ah_bb_panic_timeout_ms = HAL_BB_PANIC_WD_TMO_HORNET;
+ } else {
+ ahpriv->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_PRIVATE(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);
+ ath_hal_free(ah, ah);
+}
+
+struct ath_hal_9300 *
+ar9300_new_state(u_int16_t devid, HAL_ADAPTER_HANDLE osdev, HAL_SOFTC sc,
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_BUS_TYPE bustype,
+ asf_amem_instance_handle amem_handle,
+ struct hal_reg_parm *hal_conf_parm, 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 = amalloc_adv(
+ amem_handle, sizeof(struct ath_hal_9300), adf_os_mem_zero_outline);
+ 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.priv.h;
+ /* set initial values */
+
+ /* Attach Osprey structure as default hal structure */
+ OS_MEMCPY(&ahp->ah_priv.priv, &ar9300hal, sizeof(ahp->ah_priv.priv));
+
+ AH_PRIVATE(ah)->amem_handle = amem_handle;
+ AH_PRIVATE(ah)->ah_osdev = osdev;
+ AH_PRIVATE(ah)->ah_sc = sc;
+ AH_PRIVATE(ah)->ah_st = st;
+ AH_PRIVATE(ah)->ah_sh = sh;
+
+ AH_PRIVATE(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);
+
+ if (!hal_conf_parm->calInFlash) {
+ 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
+
+ AH_PRIVATE(ah)->ah_power_limit = MAX_RATE_POWER;
+ AH_PRIVATE(ah)->ah_tp_scale = HAL_TP_SCALE_MAX; /* no scaling */
+
+ ahp->ah_atim_window = 0; /* [0..1000] */
+ ahp->ah_diversity_control =
+ AH_PRIVATE(ah)->ah_config.ath_hal_diversity_control;
+ ahp->ah_antenna_switch_swap =
+ AH_PRIVATE(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_REG_IO,
+ "%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_REG_IO,
+ "%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 & CHANNEL_5GHZ) {
+ *low = p_cap->hal_low_5ghz_chan;
+ *high = p_cap->hal_high_5ghz_chan;
+ return AH_TRUE;
+ }
+ if ((flags & CHANNEL_2GHZ)) {
+ *low = p_cap->hal_low_2ghz_chan;
+ *high = p_cap->hal_high_2ghz_chan;
+
+ return AH_TRUE;
+ }
+ return AH_FALSE;
+}
+
+HAL_BOOL
+ar9300_regulatory_domain_override(struct ath_hal *ah, u_int16_t regdmn)
+{
+ AH_PRIVATE(ah)->ah_current_rd = 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_current_rd = eeval;
+
+ p_cap->halintr_mitigation = AH_TRUE;
+ eeval = ar9300_eeprom_get(ahp, EEP_REG_1);
+ AH_PRIVATE(ah)->ah_current_rd_ext = 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->hal_wireless_modes = 0;
+ eeval = ar9300_eeprom_get(ahp, EEP_OP_MODE);
+
+ if (eeval & AR9300_OPFLAGS_11A) {
+ p_cap->hal_wireless_modes |= HAL_MODE_11A |
+ ((!ahpriv->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->hal_wireless_modes |= HAL_MODE_11B | HAL_MODE_11G |
+ ((!ahpriv->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->hal_tx_chain_mask = ar9300_eeprom_get(ahp, EEP_TX_MASK);
+ p_cap->hal_rx_chain_mask = ar9300_eeprom_get(ahp, EEP_RX_MASK);
+
+
+ /*
+ * This being a newer chip supports TKIP non-splitmic mode.
+ *
+ */
+ ahp->ah_misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+
+ p_cap->hal_low_2ghz_chan = 2312;
+ p_cap->hal_high_2ghz_chan = 2732;
+
+ p_cap->hal_low_5ghz_chan = 4920;
+ p_cap->hal_high_5ghz_chan = 6100;
+
+ p_cap->hal_cipher_ckip_support = AH_FALSE;
+ p_cap->hal_cipher_tkip_support = AH_TRUE;
+ p_cap->hal_cipher_aes_ccm_support = AH_TRUE;
+
+ p_cap->hal_mic_ckip_support = AH_FALSE;
+ p_cap->hal_mic_tkip_support = AH_TRUE;
+ p_cap->hal_mic_aes_ccm_support = AH_TRUE;
+
+ p_cap->hal_chan_spread_support = AH_TRUE;
+ p_cap->hal_sleep_after_beacon_broken = AH_TRUE;
+
+ p_cap->hal_burst_support = AH_TRUE;
+ p_cap->hal_chap_tuning_support = AH_TRUE;
+ p_cap->hal_turbo_prime_support = AH_TRUE;
+ p_cap->hal_fast_frames_support = AH_FALSE;
+
+ p_cap->hal_turbo_g_support = p_cap->hal_wireless_modes & HAL_MODE_108G;
+
+ p_cap->hal_xr_support = AH_FALSE;
+
+ p_cap->hal_ht_support =
+ ahpriv->ah_config.ath_hal_ht_enable ? AH_TRUE : AH_FALSE;
+ p_cap->hal_gtt_support = AH_TRUE;
+ p_cap->hal_ps_poll_broken = AH_TRUE; /* XXX fixed in later revs? */
+ p_cap->hal_ht20_sgi_support = AH_TRUE;
+ p_cap->hal_veol_support = AH_TRUE;
+ p_cap->hal_bss_id_mask_support = AH_TRUE;
+ /* Bug 26802, fixed in later revs? */
+ p_cap->hal_mcast_key_srch_support = AH_TRUE;
+ p_cap->hal_tsf_add_support = AH_TRUE;
+
+ if (cap_field & AR_EEPROM_EEPCAP_MAXQCU) {
+ p_cap->hal_total_queues = MS(cap_field, AR_EEPROM_EEPCAP_MAXQCU);
+ } else {
+ p_cap->hal_total_queues = HAL_NUM_TX_QUEUES;
+ }
+
+ if (cap_field & AR_EEPROM_EEPCAP_KC_ENTRIES) {
+ p_cap->hal_key_cache_size =
+ 1 << MS(cap_field, AR_EEPROM_EEPCAP_KC_ENTRIES);
+ } else {
+ p_cap->hal_key_cache_size = AR_KEYTABLE_SIZE;
+ }
+ p_cap->hal_fast_cc_support = AH_TRUE;
+ p_cap->hal_num_mr_retries = 4;
+ p_cap->hal_tx_trig_level_max = MAX_TX_FIFO_THRESHOLD;
+
+ p_cap->hal_num_gpio_pins = AR9382_MAX_GPIO_PIN_NUM;
+
+#if 0
+ /* XXX Verify support in Osprey */
+ if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+ p_cap->hal_wow_support = 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->hal_wow_support = AH_FALSE;
+ p_cap->hal_wow_match_pattern_exact = AH_FALSE;
+ }
+#endif
+ p_cap->hal_wow_support = AH_TRUE;
+ p_cap->hal_wow_match_pattern_exact = AH_TRUE;
+ if (AR_SREV_POSEIDON(ah)) {
+ p_cap->hal_wow_match_pattern_exact = AH_TRUE;
+ }
+
+ p_cap->hal_cst_support = AH_TRUE;
+
+ p_cap->hal_rifs_rx_support = AH_TRUE;
+ p_cap->hal_rifs_tx_support = AH_TRUE;
+
+ p_cap->hal_rts_aggr_limit = IEEE80211_AMPDU_LIMIT_MAX;
+
+ p_cap->hal_mfp_support = ahpriv->ah_config.ath_hal_mfp_support;
+
+ p_cap->halforce_ppm_support = AH_TRUE;
+ p_cap->hal_hw_beacon_proc_support = 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->hal_hw_uapsd_trig = AH_FALSE;
+
+ /* Number of buffers that can be help in a single TxD */
+ p_cap->hal_num_tx_maps = 4;
+
+ p_cap->hal_tx_desc_len = sizeof(struct ar9300_txc);
+ p_cap->hal_tx_status_len = sizeof(struct ar9300_txs);
+ p_cap->hal_rx_status_len = sizeof(struct ar9300_rxs);
+
+ p_cap->hal_rx_hp_depth = HAL_HP_RXFIFO_DEPTH;
+ p_cap->hal_rx_lp_depth = HAL_LP_RXFIFO_DEPTH;
+
+ /* Enable extension channel DFS support */
+ p_cap->hal_use_combined_radar_rssi = AH_TRUE;
+ p_cap->hal_ext_chan_dfs_support = AH_TRUE;
+#if ATH_SUPPORT_SPECTRAL
+ p_cap->hal_spectral_scan = 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->hal_rf_silent_support = AH_TRUE;
+ }
+
+ /* XXX */
+ p_cap->hal_wps_push_button = AH_FALSE;
+
+#ifdef ATH_BT_COEX
+ p_cap->hal_bt_coex_support = AH_TRUE;
+ p_cap->hal_bt_coex_aspm_war = AH_FALSE;
+#endif
+
+ p_cap->hal_gen_timer_support = 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 (ahpriv->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_DISABLE_MCI)
+ {
+ p_cap->hal_mci_support = AH_FALSE;
+ }
+ else
+#endif
+ {
+ p_cap->hal_mci_support = (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->hal_mci_support);
+ }
+ else {
+ p_cap->hal_mci_support = AH_FALSE;
+ }
+
+ if (AR_SREV_JUPITER_20(ah)) {
+ p_cap->hal_radio_retention_support = AH_TRUE;
+ } else {
+ p_cap->hal_radio_retention_support = AH_FALSE;
+ }
+
+ p_cap->hal_auto_sleep_support = AH_TRUE;
+
+ p_cap->hal_mbssid_aggr_support = AH_TRUE;
+ p_cap->hal_proxy_sta_support = AH_TRUE;
+
+ /* XXX Mark it AH_TRUE after it is verfied as fixed */
+ p_cap->hal4kb_split_trans_support = AH_FALSE;
+
+ /* Read regulatory domain flag */
+ if (AH_PRIVATE(ah)->ah_current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
+ /*
+ * If REG_EXT_JAPAN_MIDBAND is set, turn on U1 EVEN, U2, and MIDBAND.
+ */
+ p_cap->hal_reg_cap =
+ 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->hal_reg_cap =
+ 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->hal_reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
+
+ p_cap->hal_num_ant_cfg_5ghz =
+ ar9300_eeprom_get_num_ant_config(ahp, HAL_FREQ_BAND_5GHZ);
+ p_cap->hal_num_ant_cfg_2ghz =
+ ar9300_eeprom_get_num_ant_config(ahp, HAL_FREQ_BAND_2GHZ);
+
+ /* STBC supported */
+ p_cap->hal_rx_stbc_support = 1; /* number of streams for STBC recieve. */
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
+ p_cap->hal_tx_stbc_support = 0;
+ } else {
+ p_cap->hal_tx_stbc_support = 1;
+ }
+
+ p_cap->hal_enhanced_dma_support = AH_TRUE;
+#ifdef ATH_SUPPORT_DFS
+ p_cap->hal_enhanced_dfs_support = AH_TRUE;
+#endif
+
+ /*
+ * EV61133 (missing interrupts due to AR_ISR_RAC).
+ * Fixed in Osprey 2.0.
+ */
+ p_cap->hal_isr_rac_support = AH_TRUE;
+
+ 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 */
+ p_cap->hal_cfend_fix_support = AH_FALSE;
+ p_cap->hal_aggr_extra_delim_war = AH_FALSE;
+ p_cap->hal_rx_desc_timestamp_bits = 32;
+ p_cap->hal_rx_tx_abort_support = 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->hal_paprd_enabled = ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED);
+ p_cap->hal_chan_half_rate =
+ !(ahp->ah_enterprise_mode & AR_ENT_OTP_10MHZ_DISABLE);
+ p_cap->hal_chan_quarter_rate =
+ !(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->hal49Ghz = 1;
+ } else {
+ p_cap->hal49Ghz = !(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->hal_ldpc_support = 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->hal_ldpc_support = AH_TRUE;
+ }
+
+ p_cap->hal_enable_apm = 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->hal_ant_div_comb_support = AH_TRUE;
+ }
+ p_cap->hal_ant_div_comb_support_org = p_cap->hal_ant_div_comb_support;
+ }
+ }
+#endif /* ATH_ANT_DIV_COMB */
+
+
+#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
+}
+
+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);
+}
+
+/*
+ * 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_is_pci_express != 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_PRIVATE(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_PRIVATE(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_PRIVATE(ah)->ah_config.ath_hal_pcie_waen) {
+ OS_REG_WRITE(ah,
+ AR_HOSTIF_REG(ah, AR_WA),
+ AH_PRIVATE(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_PRIVATE(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_REG_IO,
+ "%s: hardware self-test failed\n", __func__);
+ return HAL_ESELFTEST;
+ }
+
+ ecode = ar9300_eeprom_attach(ah);
+ 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);
+ }
+}
+
+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;
+}
+
+#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);
+ xlan_gpio_cfg = ahpriv->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_gpio_cfg_output(ah, i,
+ HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
+ }
+ }
+ }
+
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9485Common_wo_xlna_rx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Common_wo_xlna_rx_gain_poseidon1_0), 2);
+ } else if (AR_SREV_JUPITER_10(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_rx_gain_table_jupiter_1p0,
+ ARRAY_LENGTH(ar9300_common_rx_gain_table_jupiter_1p0), 2);
+ } else if (AR_SREV_JUPITER_20(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300Common_rx_gain_table_jupiter_2p0,
+ ARRAY_LENGTH(ar9300Common_rx_gain_table_jupiter_2p0), 2);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_rx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300_common_rx_gain_table_ar9580_1p0), 2);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9340Common_rx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Common_rx_gain_table_wasp_1p0), 2);
+ } else if (AR_SREV_SCORPION(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar955xCommon_rx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_rx_gain_table_scorpion_1p0), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds,
+ ar955xCommon_rx_gain_bounds_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_rx_gain_bounds_scorpion_1p0), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_rx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300_common_rx_gain_table_osprey_2p2), 2);
+ }
+ break;
+ case 1:
+ if (AR_SREV_HORNET_12(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9331_common_wo_xlna_rx_gain_hornet1_2,
+ ARRAY_LENGTH(ar9331_common_wo_xlna_rx_gain_hornet1_2), 2);
+ } else if (AR_SREV_HORNET_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9331_common_wo_xlna_rx_gain_hornet1_1,
+ ARRAY_LENGTH(ar9331_common_wo_xlna_rx_gain_hornet1_1), 2);
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9485_common_wo_xlna_rx_gain_poseidon1_1,
+ ARRAY_LENGTH(ar9485_common_wo_xlna_rx_gain_poseidon1_1), 2);
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9485Common_wo_xlna_rx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Common_wo_xlna_rx_gain_poseidon1_0), 2);
+ } else if (AR_SREV_JUPITER_10(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_wo_xlna_rx_gain_table_jupiter_1p0,
+ ARRAY_LENGTH(ar9300_common_wo_xlna_rx_gain_table_jupiter_1p0),
+ 2);
+ } else if (AR_SREV_JUPITER_20(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300Common_wo_xlna_rx_gain_table_jupiter_2p0,
+ ARRAY_LENGTH(ar9300Common_wo_xlna_rx_gain_table_jupiter_2p0),
+ 2);
+ } else if (AR_SREV_APHRODITE(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar956XCommon_wo_xlna_rx_gain_table_aphrodite_1p0,
+ ARRAY_LENGTH(ar956XCommon_wo_xlna_rx_gain_table_aphrodite_1p0),
+ 2);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300_common_wo_xlna_rx_gain_table_ar9580_1p0), 2);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9340Common_wo_xlna_rx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Common_wo_xlna_rx_gain_table_wasp_1p0), 2);
+ } else if (AR_SREV_SCORPION(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_table_scorpion_1p0), 2);
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain_bounds,
+ ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0,
+ ARRAY_LENGTH(ar955xCommon_wo_xlna_rx_gain_bounds_scorpion_1p0), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_rxgain,
+ ar9300Common_wo_xlna_rx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300Common_wo_xlna_rx_gain_table_osprey_2p2), 2);
+ }
+ break;
+ }
+}
+
+void ar9300_tx_gain_table_apply(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ switch (ar9300_tx_gain_index_get(ah))
+ {
+ case 0:
+ default:
+ if (AR_SREV_HORNET_12(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_lowest_ob_db_tx_gain_hornet1_2,
+ ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_2), 5);
+ } else if (AR_SREV_HORNET_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_lowest_ob_db_tx_gain_hornet1_1,
+ ARRAY_LENGTH(ar9331_modes_lowest_ob_db_tx_gain_hornet1_1), 5);
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1,
+ ARRAY_LENGTH(ar9485_modes_lowest_ob_db_tx_gain_poseidon1_1), 5);
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Modes_lowest_ob_db_tx_gain_poseidon1_0), 5);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300Modes_lowest_ob_db_tx_gain_table_ar9580_1p0),
+ 5);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0),
+ 5);
+ } else if (AR_SREV_SCORPION(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar955xModes_xpa_tx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xModes_xpa_tx_gain_table_scorpion_1p0),
+ 9);
+ } else if (AR_SREV_JUPITER_10(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_low_ob_db_tx_gain_table_jupiter_1p0,
+ ARRAY_LENGTH(ar9300_modes_low_ob_db_tx_gain_table_jupiter_1p0),
+ 5);
+ } else if (AR_SREV_JUPITER_20(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_low_ob_db_tx_gain_table_jupiter_2p0,
+ ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_jupiter_2p0),
+ 5);
+ } else if (AR_SREV_APHRODITE(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0,
+ ARRAY_LENGTH(ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0),
+ 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300_modes_lowest_ob_db_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 1:
+ if (AR_SREV_HORNET_12(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_high_ob_db_tx_gain_hornet1_2,
+ ARRAY_LENGTH(ar9331_modes_high_ob_db_tx_gain_hornet1_2), 5);
+ } else if (AR_SREV_HORNET_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_high_ob_db_tx_gain_hornet1_1,
+ ARRAY_LENGTH(ar9331_modes_high_ob_db_tx_gain_hornet1_1), 5);
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_high_ob_db_tx_gain_poseidon1_1,
+ ARRAY_LENGTH(ar9485_modes_high_ob_db_tx_gain_poseidon1_1), 5);
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485Modes_high_ob_db_tx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Modes_high_ob_db_tx_gain_poseidon1_0), 5);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_high_ob_db_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300Modes_high_ob_db_tx_gain_table_ar9580_1p0),
+ 5);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_high_ob_db_tx_gain_table_wasp_1p0), 5);
+ } else if (AR_SREV_SCORPION(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar955xModes_no_xpa_tx_gain_table_scorpion_1p0,
+ ARRAY_LENGTH(ar955xModes_no_xpa_tx_gain_table_scorpion_1p0), 9);
+ } else if (AR_SREV_JUPITER_10(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_high_ob_db_tx_gain_table_jupiter_1p0,
+ ARRAY_LENGTH(
+ ar9300_modes_high_ob_db_tx_gain_table_jupiter_1p0), 5);
+ } else if (AR_SREV_JUPITER_20(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p0,
+ ARRAY_LENGTH(
+ ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p0), 5);
+ } else if (AR_SREV_APHRODITE(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar956XModes_high_ob_db_tx_gain_table_aphrodite_1p0,
+ ARRAY_LENGTH(
+ ar956XModes_high_ob_db_tx_gain_table_aphrodite_1p0), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_high_ob_db_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300Modes_high_ob_db_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 2:
+ if (AR_SREV_HORNET_12(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_low_ob_db_tx_gain_hornet1_2,
+ ARRAY_LENGTH(ar9331_modes_low_ob_db_tx_gain_hornet1_2), 5);
+ } else if (AR_SREV_HORNET_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_low_ob_db_tx_gain_hornet1_1,
+ ARRAY_LENGTH(ar9331_modes_low_ob_db_tx_gain_hornet1_1), 5);
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_low_ob_db_tx_gain_poseidon1_1,
+ ARRAY_LENGTH(ar9485_modes_low_ob_db_tx_gain_poseidon1_1), 5);
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485Modes_low_ob_db_tx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Modes_low_ob_db_tx_gain_poseidon1_0), 5);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_low_ob_db_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_ar9580_1p0),
+ 5);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_low_ob_db_tx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_low_ob_db_tx_gain_table_wasp_1p0), 5);
+ } else if (AR_SREV_APHRODITE(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0,
+ ARRAY_LENGTH(ar956XModes_low_ob_db_tx_gain_table_aphrodite_1p0), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_low_ob_db_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300Modes_low_ob_db_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 3:
+ if (AR_SREV_HORNET_12(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_high_power_tx_gain_hornet1_2,
+ ARRAY_LENGTH(ar9331_modes_high_power_tx_gain_hornet1_2), 5);
+ } else if (AR_SREV_HORNET_11(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9331_modes_high_power_tx_gain_hornet1_1,
+ ARRAY_LENGTH(ar9331_modes_high_power_tx_gain_hornet1_1), 5);
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_high_power_tx_gain_poseidon1_1,
+ ARRAY_LENGTH(ar9485_modes_high_power_tx_gain_poseidon1_1), 5);
+ } else if (AR_SREV_POSEIDON(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485Modes_high_power_tx_gain_poseidon1_0,
+ ARRAY_LENGTH(ar9485Modes_high_power_tx_gain_poseidon1_0), 5);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_high_power_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300Modes_high_power_tx_gain_table_ar9580_1p0),
+ 5);
+ } else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_high_power_tx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_high_power_tx_gain_table_wasp_1p0),
+ 5);
+ } else if (AR_SREV_APHRODITE(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar956XModes_high_power_tx_gain_table_aphrodite_1p0,
+ ARRAY_LENGTH(ar956XModes_high_power_tx_gain_table_aphrodite_1p0), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_high_power_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300Modes_high_power_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 4:
+ if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_mixed_ob_db_tx_gain_table_wasp_1p0,
+ ARRAY_LENGTH(ar9340Modes_mixed_ob_db_tx_gain_table_wasp_1p0),
+ 5);
+ } else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_mixed_ob_db_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH(ar9300_modes_mixed_ob_db_tx_gain_table_ar9580_1p0),
+ 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300Modes_mixed_ob_db_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH(ar9300Modes_mixed_ob_db_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 5:
+ /* HW Green TX */
+ if (AR_SREV_POSEIDON(ah)) {
+ if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_green_ob_db_tx_gain_poseidon1_1,
+ sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_1) /
+ sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_1[0]), 5);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_green_ob_db_tx_gain_poseidon1_0,
+ sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_0) /
+ sizeof(ar9485_modes_green_ob_db_tx_gain_poseidon1_0[0]), 5);
+ }
+ ahp->ah_hw_green_tx_enable = 1;
+ }
+ else if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340_modes_ub124_tx_gain_table_wasp_1p0,
+ sizeof(ar9340_modes_ub124_tx_gain_table_wasp_1p0) /
+ sizeof(ar9340_modes_ub124_tx_gain_table_wasp_1p0[0]), 5);
+ }
+ else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_type5_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH( ar9300_modes_type5_tx_gain_table_ar9580_1p0),
+ 5);
+ }
+ else if (AR_SREV_OSPREY_22(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_number_5_tx_gain_table_osprey_2p2,
+ ARRAY_LENGTH( ar9300_modes_number_5_tx_gain_table_osprey_2p2),
+ 5);
+ }
+ break;
+ case 6:
+ if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0,
+ sizeof(ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0) /
+ sizeof(ar9340_modes_low_ob_db_and_spur_tx_gain_table_wasp_1p0[0]), 5);
+ }
+ /* HW Green TX */
+ else if (AR_SREV_POSEIDON(ah)) {
+ if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1,
+ sizeof(ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1) /
+ sizeof(ar9485_modes_green_spur_ob_db_tx_gain_poseidon1_1[0]),
+ 5);
+ }
+ ahp->ah_hw_green_tx_enable = 1;
+ }
+ else if (AR_SREV_AR9580(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9300_modes_type6_tx_gain_table_ar9580_1p0,
+ ARRAY_LENGTH( ar9300_modes_type6_tx_gain_table_ar9580_1p0),
+ 5);
+ }
+ break;
+ case 7:
+ if (AR_SREV_WASP(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_ini_modes_txgain,
+ ar9340Modes_cus227_tx_gain_table_wasp_1p0,
+ sizeof(ar9340Modes_cus227_tx_gain_table_wasp_1p0) /
+ sizeof(ar9340Modes_cus227_tx_gain_table_wasp_1p0[0]), 5);
+ }
+ break;
+ }
+}
+
+#if ATH_ANT_DIV_COMB
+void
+ar9300_ant_div_comb_get_config(struct ath_hal *ah,
+ HAL_ANT_COMB_CONFIG *div_comb_conf)
+{
+ u_int32_t reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ div_comb_conf->main_lna_conf =
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__READ(reg_val);
+ div_comb_conf->alt_lna_conf =
+ MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__READ(reg_val);
+ div_comb_conf->fast_div_bias =
+ MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__READ(reg_val);
+ if (AR_SREV_HORNET_11(ah)) {
+ div_comb_conf->antdiv_configgroup = HAL_ANTDIV_CONFIG_GROUP_1;
+ } else if (AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ div_comb_conf->antdiv_configgroup = HAL_ANTDIV_CONFIG_GROUP_2;
+ } else {
+ div_comb_conf->antdiv_configgroup = DEFAULT_ANTDIV_CONFIG_GROUP;
+ }
+}
+
+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;
+}
+
+#endif /* AH_SUPPORT_AR9300 */
diff --git a/hal/ar9300/ar9300_beacon.c b/hal/ar9300/ar9300_beacon.c
new file mode 100644
index 000000000000..66ce172241d1
--- /dev/null
+++ b/hal/ar9300/ar9300_beacon.c
@@ -0,0 +1,198 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar9300/ar9300.h"
+#include "ar9300/ar9300reg.h"
+
+#define TU_TO_USEC(_tu) ((_tu) << 10)
+
+extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q);
+
+/*
+ * Initializes all of the hardware registers used to
+ * send beacons. Note that for station operation the
+ * driver calls ar9300_set_sta_beacon_timers instead.
+ */
+void
+ar9300_beacon_init(struct ath_hal *ah,
+ u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode)
+{
+ struct ath_hal_private *ap = AH_PRIVATE(ah);
+ u_int32_t beacon_period_usec;
+
+ HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP);
+ if (opmode == HAL_M_IBSS) {
+ OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+ }
+ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, ONE_EIGHTH_TU_TO_USEC(next_beacon));
+ OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
+ (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
+ ap->ah_config.ath_hal_dma_beacon_response_time));
+ OS_REG_WRITE(ah, AR_NEXT_SWBA,
+ (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
+ ap->ah_config.ath_hal_sw_beacon_response_time));
+
+ beacon_period_usec =
+ ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8);
+ OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec);
+ OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec);
+ OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec);
+
+ /* reset TSF if required */
+ if (beacon_period & HAL_BEACON_RESET_TSF) {
+ ar9300_reset_tsf(ah);
+ }
+
+ /* enable timers */
+ OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+ AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN);
+}
+
+/*
+ * Set all the beacon related bits on the h/w for stations
+ * i.e. initializes the corresponding h/w timers;
+ */
+void
+ar9300_set_sta_beacon_timers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
+{
+ u_int32_t next_tbtt, beaconintval, dtimperiod, beacontimeout;
+ HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
+
+ HALASSERT(bs->bs_intval != 0);
+
+ /* no cfp setting since h/w automatically takes care */
+ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
+
+ /*
+ * Start the beacon timers by setting the BEACON register
+ * to the beacon interval; no need to write tim offset since
+ * h/w parses IEs.
+ */
+ OS_REG_WRITE(ah, AR_BEACON_PERIOD,
+ TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+ OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
+ TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
+ /*
+ * Configure the BMISS interrupt. Note that we
+ * assume the caller blocks interrupts while enabling
+ * the threshold.
+ */
+ HALASSERT(bs->bs_bmissthreshold <=
+ (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
+ OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
+ AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+ /*
+ * Program the sleep registers to correlate with the beacon setup.
+ */
+
+ /*
+ * Current implementation assumes sw processing of beacons -
+ * assuming an interrupt is generated every beacon which
+ * causes the hardware to become awake until the sw tells
+ * it to go to sleep again; beacon timeout is to allow for
+ * beacon jitter; cab timeout is max time to wait for cab
+ * after seeing the last DTIM or MORE CAB bit
+ */
+#define CAB_TIMEOUT_VAL 10 /* in TU */
+#define BEACON_TIMEOUT_VAL 10 /* in TU */
+#define MIN_BEACON_TIMEOUT_VAL 1 /* in 1/8 TU */
+#define SLEEP_SLOP 3 /* in TU */
+
+ /*
+ * For max powersave mode we may want to sleep for longer than a
+ * beacon period and not want to receive all beacons; modify the
+ * timers accordingly; make sure to align the next TIM to the
+ * next DTIM if we decide to wake for DTIMs only
+ */
+ beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
+ HALASSERT(beaconintval != 0);
+ if (bs->bs_sleepduration > beaconintval) {
+ HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
+ bs->bs_sleepduration);
+ beaconintval = bs->bs_sleepduration;
+ }
+ dtimperiod = bs->bs_dtimperiod;
+ if (bs->bs_sleepduration > dtimperiod) {
+ HALASSERT(dtimperiod == 0 ||
+ roundup(bs->bs_sleepduration, dtimperiod) ==
+ bs->bs_sleepduration);
+ dtimperiod = bs->bs_sleepduration;
+ }
+ HALASSERT(beaconintval <= dtimperiod);
+ if (beaconintval == dtimperiod) {
+ next_tbtt = bs->bs_nextdtim;
+ } else {
+ next_tbtt = bs->bs_nexttbtt;
+ }
+
+ HALDEBUG(ah, HAL_DEBUG_BEACON,
+ "%s: next DTIM %d\n", __func__, bs->bs_nextdtim);
+ HALDEBUG(ah, HAL_DEBUG_BEACON,
+ "%s: next beacon %d\n", __func__, next_tbtt);
+ HALDEBUG(ah, HAL_DEBUG_BEACON,
+ "%s: beacon period %d\n", __func__, beaconintval);
+ HALDEBUG(ah, HAL_DEBUG_BEACON,
+ "%s: DTIM period %d\n", __func__, dtimperiod);
+
+ OS_REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+ OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(next_tbtt - SLEEP_SLOP));
+
+ /* cab timeout is now in 1/8 TU */
+ OS_REG_WRITE(ah, AR_SLEEP1,
+ SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
+ | AR_SLEEP1_ASSUME_DTIM);
+
+ /* beacon timeout is now in 1/8 TU */
+ if (p_cap->hal_auto_sleep_support) {
+ beacontimeout = (BEACON_TIMEOUT_VAL << 3);
+ } else {
+ /*
+ * Use a very small value to make sure the timeout occurs before
+ * the TBTT. In this case the chip will not go back to sleep
+ * automatically, instead it will wait for the SW to explicitly
+ * set it to that mode.
+ */
+ beacontimeout = MIN_BEACON_TIMEOUT_VAL;
+ }
+
+ OS_REG_WRITE(ah, AR_SLEEP2,
+ SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
+
+ OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+ OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+
+ /* clear HOST AP related timers first */
+ OS_REG_CLR_BIT(ah, AR_TIMER_MODE, (AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN));
+
+ OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN
+ | AR_DTIM_TIMER_EN);
+
+ /* TSF out of range threshold */
+ OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
+
+#undef CAB_TIMEOUT_VAL
+#undef BEACON_TIMEOUT_VAL
+#undef SLEEP_SLOP
+}
+#endif /* AH_SUPPORT_AR9300 */
diff --git a/hal/ar9300/ar9300_eeprom.c b/hal/ar9300/ar9300_eeprom.c
new file mode 100644
index 000000000000..63a5a43acd18
--- /dev/null
+++ b/hal/ar9300/ar9300_eeprom.c
@@ -0,0 +1,4522 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#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,
+ u_int16_t 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, AH_WAIT_TIMEOUT))
+ {
+ return AH_FALSE;
+ }
+ *data = MS(OS_REG_READ(ah,
+ AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA)), AR_EEPROM_STATUS_DATA_VAL);
+ return AH_TRUE;
+ }
+ else
+ {
+ *data = 0;
+ return AH_FALSE;
+ }
+}
+
+
+HAL_BOOL
+ar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi)
+{
+ int time_out = 1000;
+ int status = 0;
+ u_int32_t addr;
+
+ addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah))?
+ OTP_MEM_START_ADDRESS_WASP : OTP_MEM_START_ADDRESS;
+ if (!is_wifi) {
+ addr = BTOTP_MEM_START_ADDRESS;
+ }
+ addr += off * 4; /* OTP is 32 bit addressable */
+ (void) OS_REG_READ(ah, addr);
+
+ addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ?
+ OTP_STATUS0_OTP_SM_BUSY_WASP : OTP_STATUS0_OTP_SM_BUSY;
+ if (!is_wifi) {
+ addr = BTOTP_STATUS0_OTP_SM_BUSY;
+ }
+ while ((time_out > 0) && (!status)) { /* wait for access complete */
+ /* Read data valid, access not busy, sm not busy */
+ status = ((OS_REG_READ(ah, addr) & 0x7) == 0x4) ? 1 : 0;
+ time_out--;
+ }
+ if (time_out == 0) {
+ HALDEBUG(ah, HAL_DEBUG_EEPROM,
+ "%s: Timed out during OTP Status0 validation\n", __func__);
+ return AH_FALSE;
+ }
+
+ addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ?
+ OTP_STATUS1_EFUSE_READ_DATA_WASP : OTP_STATUS1_EFUSE_READ_DATA;
+ if (!is_wifi) {
+ addr = BTOTP_STATUS1_EFUSE_READ_DATA;
+ }
+ *data = OS_REG_READ(ah, addr);
+ return AH_TRUE;
+}
+
+
+
+
+static HAL_STATUS
+ar9300_flash_map(struct ath_hal *ah)
+{
+ 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;
+ }
+ 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;
+}
+
+#ifdef UNUSED
+#endif
+
+HAL_STATUS
+ar9300_eeprom_attach(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ ahp->try_dram = 1;
+ ahp->try_eeprom = 1;
+ ahp->try_otp = 1;
+#ifdef ATH_CAL_NAND_FLASH
+ ahp->try_nand = 1;
+#else
+ ahp->try_flash = 1;
+#endif
+ ahp->calibration_data_source = calibration_data_none;
+ ahp->calibration_data_source_address = 0;
+ ahp->calibration_data_try = calibration_data_try;
+ ahp->calibration_data_try_address = 0;
+
+ /*
+ * In case flash will be used for EEPROM. Otherwise ahp->ah_cal_mem
+ * must be set to NULL or the real EEPROM address.
+ */
+ ar9300_flash_map(ah);
+ /*
+ * ###### This function always return NO SPUR.
+ * This is not AH_TRUE for many board designs.
+ * Does anyone use this?
+ */
+ AH_PRIVATE(ah)->ah_eeprom_get_spur_chan = ar9300_eeprom_get_spur_chan;
+
+#ifdef OLDCODE
+ /* XXX Needs to be moved for dynamic selection */
+ ahp->ah_eeprom = *(default9300[ar9300_eeprom_template_default]);
+
+
+ if (AR_SREV_HORNET(ah)) {
+ /* Set default values for Hornet. */
+ ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags =
+ AR9300_OPFLAGS_11G;
+ ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11;
+ } else if (AR_SREV_POSEIDON(ah)) {
+ /* Set default values for Poseidon. */
+ ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags =
+ AR9300_OPFLAGS_11G;
+ ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11;
+ }
+
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_skip_eeprom_read) {
+ ahp->ah_emu_eeprom = 1;
+ return HAL_OK;
+ }
+
+ ahp->ah_emu_eeprom = 1;
+
+#ifdef UNUSED
+#endif
+
+ if (!ar9300_fill_eeprom(ah)) {
+ return HAL_EIO;
+ }
+
+ return HAL_OK;
+ /* return ar9300_check_eeprom(ah); */
+#else
+ ahp->ah_emu_eeprom = 1;
+
+#if 0
+/*#ifdef MDK_AP*/ /* MDK_AP is defined only in NART AP build */
+ u_int8_t buffer[10];
+ int caldata_check = 0;
+
+ ar9300_calibration_data_read_flash(
+ ah, FLASH_BASE_CALDATA_OFFSET, buffer, 4);
+ printf("flash caldata:: %x\n", buffer[0]);
+ if (buffer[0] != 0xff) {
+ caldata_check = 1;
+ }
+ if (!caldata_check) {
+ ar9300_eeprom_t *mptr;
+ int mdata_size;
+ if (AR_SREV_HORNET(ah)) {
+ /* XXX: For initial testing */
+ mptr = &ahp->ah_eeprom;
+ mdata_size = ar9300_eeprom_struct_size();
+ ahp->ah_eeprom = ar9300_template_ap121;
+ ahp->ah_emu_eeprom = 1;
+ /* need it to let art save in to flash ????? */
+ calibration_data_source = calibration_data_flash;
+ } else if (AR_SREV_WASP(ah)) {
+ /* XXX: For initial testing */
+ ath_hal_printf(ah, " wasp eep attach\n");
+ mptr = &ahp->ah_eeprom;
+ mdata_size = ar9300_eeprom_struct_size();
+ ahp->ah_eeprom = ar9300_template_generic;
+ ahp->ah_eeprom.mac_addr[0] = 0x00;
+ ahp->ah_eeprom.mac_addr[1] = 0x03;
+ ahp->ah_eeprom.mac_addr[2] = 0x7F;
+ ahp->ah_eeprom.mac_addr[3] = 0xBA;
+ ahp->ah_eeprom.mac_addr[4] = 0xD0;
+ ahp->ah_eeprom.mac_addr[5] = 0x00;
+ ahp->ah_emu_eeprom = 1;
+ ahp->ah_eeprom.base_eep_header.txrx_mask = 0x33;
+ ahp->ah_eeprom.base_eep_header.txrxgain = 0x10;
+ /* need it to let art save in to flash ????? */
+ calibration_data_source = calibration_data_flash;
+ }
+ return HAL_OK;
+ }
+#endif
+ if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
+ ahp->try_eeprom = 0;
+ }
+
+ if (!ar9300_eeprom_restore(ah)) {
+ return HAL_EIO;
+ }
+ return HAL_OK;
+#endif
+}
+
+u_int32_t
+ar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param)
+{
+ ar9300_eeprom_t *eep = &ahp->ah_eeprom;
+ OSPREY_BASE_EEP_HEADER *p_base = &eep->base_eep_header;
+ OSPREY_BASE_EXTENSION_1 *base_ext1 = &eep->base_ext1;
+
+ switch (param) {
+#if 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;
+#if 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;
+#if 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, HAL_CHANNEL_INTERNAL *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 (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;
+}
+
+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, &reg_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;
+}
+
+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 = ahpriv->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_gpio_cfg_output(ah, i,
+ HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
+ }
+ }
+ }
+ }
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_JUPITER_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_JUPITER_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SCORPION_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_SCORPION_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
+ value = ar9300_ant_ctrl_common_get(ah, is_2ghz);
+ if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
+ if (AR_SREV_JUPITER_10(ah)) {
+ /* Force SPDT setting for Jupiter 1.0 chips. */
+ value &= ~AR_SWITCH_TABLE_COM_SPDT;
+ value |= 0x00100000;
+ }
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_JUPITER_ALL, value);
+ }
+ else if (AR_SREV_SCORPION(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_SCORPION_ALL, value);
+ }
+ else {
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL, value);
+ }
+/*
+* Jupiter2.0 defines new switch table for BT/WLAN,
+* here's new field name in WB222.ref for both 2G and 5G.
+* Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
+* 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX SWITCH_TABLE_COM_SPDT_WLAN_RX
+* 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX SWITCH_TABLE_COM_SPDT_WLAN_TX
+* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+*/
+#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
+ if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
+ value = ar9300_switch_com_spdt_get(ah, is_2ghz);
+ OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL,
+ AR_SWITCH_TABLE_COM_SPDT_ALL, value);
+
+ OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
+ AR_BTCOEX_CTRL_SPDT_ENABLE);
+ //OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
+ // AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
+ }
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+ value = ar9300_ant_ctrl_common2_get(ah, is_2ghz);
+#if ATH_ANT_DIV_COMB
+ if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
+ value &= ~AR_SWITCH_TABLE_COM2_ALL;
+ value |= ahpriv->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
+ }
+#endif /* ATH_ANT_DIV_COMB */
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+ value = ar9300_ant_ctrl_chain_get(ah, 0, is_2ghz);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
+
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) {
+ value = ar9300_ant_ctrl_chain_get(ah, 1, is_2ghz);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
+
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ value = ar9300_ant_ctrl_chain_get(ah, 2, is_2ghz);
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
+ }
+ }
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
+ value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
+ /* main_lnaconf, alt_lnaconf, main_tb, alt_tb */
+ regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
+ regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */
+ regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S;
+ /* enable_lnadiv */
+ regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK);
+ regval |= ((value >> 6) & 0x1) <<
+ MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT;
+#if ATH_ANT_DIV_COMB
+ if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
+ regval |= ANT_DIV_ENABLE;
+ }
+#endif /* ATH_ANT_DIV_COMB */
+ OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
+
+ /* enable fast_div */
+ regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
+ regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK);
+ regval |= ((value >> 7) & 0x1) <<
+ BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT;
+#if ATH_ANT_DIV_COMB
+ if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
+ regval |= FAST_DIV_ENABLE;
+ }
+#endif /* ATH_ANT_DIV_COMB */
+ OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
+ }
+
+#if ATH_ANT_DIV_COMB
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) {
+ if (pcap->hal_ant_div_comb_support) {
+ /* 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.
+ */
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL,
+ ahpriv->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;
+}
+
+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
+ && ahpriv->ah_config.ath_hal_ext_atten_margin_cfg)
+ {
+ value = 5;
+ }
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
+
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ value = ar9300_attenuation_chain_get(ah, 1, channel);
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+ value = ar9300_attenuation_margin_chain_get(ah, 1, channel);
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ value = ar9300_attenuation_chain_get(ah, 2, channel);
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+ value = ar9300_attenuation_margin_chain_get(ah, 2, channel);
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+ }
+ }
+ return 0;
+}
+
+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)
+{
+ 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 */
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_sta_update_tx_pwr_enable) {
+ if (AR_SREV_POSEIDON(ah)) {
+ /* Get calibrated OLPC gain delta value for GreenTx */
+ AH_PRIVATE(ah)->ah_db2[POSEIDON_STORED_REG_G2_OLPC_OFFSET] =
+ (u_int32_t) correction[0];
+ }
+ }
+
+ ar9300_power_control_override(
+ ah, frequency, correction, voltage, temperature);
+ HALDEBUG(ah, HAL_DEBUG_EEPROM,
+ "%s: for frequency=%d, calibration correction = %d %d %d\n",
+ __func__, frequency, correction[0], correction[1], correction[2]);
+
+ return 0;
+}
+
+int
+ar9300_power_control_override(struct ath_hal *ah, int frequency,
+ int *correction, int *voltage, int *temperature)
+{
+ int temp_slope = 0;
+ int temp_slope_1 = 0;
+ int temp_slope_2 = 0;
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ int32_t f[8], t[8],t1[3], t2[3];
+ int i;
+
+ OS_REG_RMW(ah, AR_PHY_TPC_11_B0,
+ (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+ if (!AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW(ah, AR_PHY_TPC_11_B1,
+ (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW(ah, AR_PHY_TPC_11_B2,
+ (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
+ AR_PHY_TPC_OLPC_GAIN_DELTA);
+ }
+ }
+ /*
+ * enable open loop power control on chip
+ */
+ OS_REG_RMW(ah, AR_PHY_TPC_6_B0,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE);
+ if (!AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW(ah, AR_PHY_TPC_6_B1,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW(ah, AR_PHY_TPC_6_B2,
+ (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
+ AR_PHY_TPC_6_ERROR_EST_MODE);
+ }
+ }
+
+ /*
+ * Enable temperature compensation
+ * Need to use register names
+ */
+ if (frequency < 4000) {
+ temp_slope = eep->modal_header_2g.temp_slope;
+ } else {
+ if ((eep->base_eep_header.misc_configuration & 0x20) != 0)
+ {
+ for(i=0;i<8;i++)
+ {
+ t[i]=eep->base_ext1.tempslopextension[i];
+ f[i]=FBIN2FREQ(eep->cal_freq_pier_5g[i], 0);
+ }
+ temp_slope=interpolate(frequency,f,t,8);
+ }
+ else
+ {
+ if(!AR_SREV_SCORPION(ah)) {
+ if (eep->base_ext2.temp_slope_low != 0) {
+ t[0] = eep->base_ext2.temp_slope_low;
+ f[0] = 5180;
+ t[1] = eep->modal_header_5g.temp_slope;
+ f[1] = 5500;
+ t[2] = eep->base_ext2.temp_slope_high;
+ f[2] = 5785;
+ temp_slope = interpolate(frequency, f, t, 3);
+ } else {
+ temp_slope = eep->modal_header_5g.temp_slope;
+ }
+ } else {
+ /*
+ * Scorpion has individual chain tempslope values
+ */
+ t[0] = eep->base_ext1.tempslopextension[2];
+ t1[0]= eep->base_ext1.tempslopextension[3];
+ t2[0]= eep->base_ext1.tempslopextension[4];
+ f[0] = 5180;
+ t[1] = eep->modal_header_5g.temp_slope;
+ t1[1]= eep->base_ext1.tempslopextension[0];
+ t2[1]= eep->base_ext1.tempslopextension[1];
+ f[1] = 5500;
+ t[2] = eep->base_ext1.tempslopextension[5];
+ t1[2]= eep->base_ext1.tempslopextension[6];
+ t2[2]= eep->base_ext1.tempslopextension[7];
+ f[2] = 5785;
+ temp_slope = interpolate(frequency, f, t, 3);
+ temp_slope_1=interpolate(frequency, f, t1,3);
+ temp_slope_2=interpolate(frequency, f, t2,3);
+ }
+ }
+ }
+
+ if (!AR_SREV_SCORPION(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope);
+ } else {
+ /*Scorpion has tempSlope register for each chain*/
+ /*Check whether temp_compensation feature is enabled or not*/
+ if (eep->base_eep_header.feature_enable & 0x1){
+ if(frequency < 4000) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM,
+ eep->base_ext2.temp_slope_low);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM,
+ temp_slope);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM,
+ eep->base_ext2.temp_slope_high);
+ } else {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM,
+ temp_slope);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM,
+ temp_slope_1);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM,
+ temp_slope_2);
+ }
+ }else {
+ /* If temp compensation is not enabled, set all registers to 0*/
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 0);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 0);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 0);
+ }
+ }
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, temperature[0]);
+
+ return 0;
+}
+
+/**************************************************************
+ * ar9300_eep_def_get_max_edge_power
+ *
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static inline u_int16_t
+ar9300_eep_def_get_max_edge_power(ar9300_eeprom_t *p_eep_data, u_int16_t freq,
+ int idx, HAL_BOOL is_2ghz)
+{
+ u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER;
+ u_int8_t *ctl_freqbin = is_2ghz ?
+ &p_eep_data->ctl_freqbin_2G[idx][0] :
+ &p_eep_data->ctl_freqbin_5G[idx][0];
+ u_int16_t num_edges = is_2ghz ?
+ OSPREY_NUM_BAND_EDGES_2G : OSPREY_NUM_BAND_EDGES_5G;
+ int i;
+
+ /* Get the edge power */
+ for (i = 0; (i < num_edges) && (ctl_freqbin[i] != AR9300_BCHAN_UNUSED); i++)
+ {
+ /*
+ * If there's an exact channel match or an inband flag set
+ * on the lower channel use the given rd_edge_power
+ */
+ if (freq == fbin2freq(ctl_freqbin[i], is_2ghz)) {
+ if (is_2ghz) {
+ twice_max_edge_power =
+ p_eep_data->ctl_power_data_2g[idx].ctl_edges[i].t_power;
+ } else {
+ twice_max_edge_power =
+ p_eep_data->ctl_power_data_5g[idx].ctl_edges[i].t_power;
+ }
+ break;
+ } else if ((i > 0) && (freq < fbin2freq(ctl_freqbin[i], is_2ghz))) {
+ if (is_2ghz) {
+ if (fbin2freq(ctl_freqbin[i - 1], 1) < freq &&
+ p_eep_data->ctl_power_data_2g[idx].ctl_edges[i - 1].flag)
+ {
+ twice_max_edge_power =
+ p_eep_data->ctl_power_data_2g[idx].
+ ctl_edges[i - 1].t_power;
+ }
+ } else {
+ if (fbin2freq(ctl_freqbin[i - 1], 0) < freq &&
+ p_eep_data->ctl_power_data_5g[idx].ctl_edges[i - 1].flag)
+ {
+ twice_max_edge_power =
+ p_eep_data->ctl_power_data_5g[idx].
+ ctl_edges[i - 1].t_power;
+ }
+ }
+ /*
+ * Leave loop - no more affecting edges possible
+ * in this monotonic increasing list
+ */
+ break;
+ }
+ }
+ /*
+ * EV89475: EEPROM might contain 0 txpower in CTL table for certain
+ * 2.4GHz channels. We workaround it by overwriting 60 (30 dBm) here.
+ */
+ if (is_2ghz && (twice_max_edge_power == 0)) {
+ twice_max_edge_power = 60;
+ }
+
+ HALASSERT(twice_max_edge_power > 0);
+ return twice_max_edge_power;
+}
+
+HAL_BOOL
+ar9300_eeprom_set_power_per_rate_table(
+ struct ath_hal *ah,
+ ar9300_eeprom_t *p_eep_data,
+ HAL_CHANNEL_INTERNAL *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;
+
+ tx_chainmask = chainmask ? chainmask : ahp->ah_tx_chainmask;
+
+ ar9300_get_channel_centers(ah, chan, &centers);
+
+ if (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;
+ }
+
+ /* 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_tp_scale != HAL_TP_SCALE_MAX) {
+ max_reg_allowed_power -=
+ (tp_scale_reduction_table[(AH_PRIVATE(ah)->ah_tp_scale)] * 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 (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 (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 (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 (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],
+ chan->channel, chan->conformance_test_limit);
+
+ /*
+ * 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, 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, 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, HAL_CHANNEL_INTERNAL *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;
+
+ 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__, chan->channel, cfg_ctl,
+ antenna_reduction, twice_max_regulatory_power, power_limit);
+ ar9300_set_target_power_from_eeprom(ah, chan->channel, target_power_val_t2);
+
+ if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) {
+ if (IS_CHAN_2GHZ(chan)) {
+ if (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 (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, IS_CHAN_2GHZ(chan), chan->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 (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 (!chan->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__,
+ chan->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 = chan->conformance_test_limit;
+
+ /*
+ * 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)) {
+ 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__, chan->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_PRIVATE(ah)->ah_config.ath_hal_sta_update_tx_pwr_enable ||
+ AH_PRIVATE(ah)->ah_caps.hal_paprd_enabled)
+ {
+ 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 */
+ AH_PRIVATE(ah)->ah_ob_db1[POSEIDON_STORED_REG_OBDB] =
+ OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF2);
+ /* Record TPC settting */
+ AH_PRIVATE(ah)->ah_ob_db1[POSEIDON_STORED_REG_TPC] =
+ OS_REG_READ(ah, AR_TPC);
+ /* Record BB_powertx_rate9 setting */
+ AH_PRIVATE(ah)->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 (IS_CHAN_HT40(chan)) {
+ i = ALL_TARGET_HT40_0_8_16; /* ht40 */
+ } else if (IS_CHAN_HT20(chan)) {
+ i = ALL_TARGET_HT20_0_8_16; /* ht20 */
+ }
+ max_power_level = target_power_val_t2[i];
+ /* Adjusting the ah_max_power_level based on chains and antennaGain*/
+ switch (ar9300_get_ntxchains(ahp->ah_tx_chainmask))
+ {
+ 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_max_power_level = (int8_t)max_power_level;
+
+ ar9300_calibration_apply(ah, chan->channel);
+#undef ABS
+
+ /* Handle per packet TPC initializations */
+ if (AH_PRIVATE(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",
+ chan->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, HAL_CHANNEL_INTERNAL *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[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, &centers);
+
+ reset_freq_bin = FREQ2FBIN(centers.synth_center, 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 (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, HAL_CHANNEL_INTERNAL *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[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, u_int16_t 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;
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ 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 (!ahp->ah_priv.priv.ah_eeprom_read(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);
+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;
+
+ /* check if LMAC sent DRAM address is valid */
+ if (!(uintptr_t)(AH_PRIVATE(ah)->ah_st)) {
+ return -1;
+ }
+
+ /* When calibration data is from host, Host will copy the
+ compressed data to the predefined DRAM location saved at ah->ah_st */
+ 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);
+ 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)
+ {
+ 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
+ */
+ 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)
+ {
+ 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)
+ {
+ 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<<AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S)
+
+ if (thermometer < 0) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
+ AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
+ }
+ }
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ }
+ }
+ } else {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
+ AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
+ }
+ }
+ if (thermometer == 0) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
+ AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ }
+ }
+ } else if (thermometer == 1) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
+ AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ }
+ }
+ } else if (thermometer == 2) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
+ if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)) {
+ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
+ AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
+ }
+ }
+ }
+ }
+ return AH_TRUE;
+}
+
+static int32_t ar9300_tuning_caps_params_get(struct ath_hal *ah)
+{
+ int tuning_caps_params;
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ tuning_caps_params = eep->base_eep_header.params_for_tuning_caps[0];
+ return tuning_caps_params;
+}
+
+/*
+ * Read the tuning caps params from eeprom and set to correct register.
+ * To regulation the frequency accuracy.
+ */
+HAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah)
+{
+ int tuning_caps_params;
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ tuning_caps_params = ar9300_tuning_caps_params_get(ah);
+ if ((eep->base_eep_header.feature_enable & 0x40) >> 6) {
+ tuning_caps_params &= 0x7f;
+
+ if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) {
+ return AH_TRUE;
+ } else if (AR_SREV_SCORPION(ah)) {
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC,
+ tuning_caps_params);
+ OS_REG_RMW_FIELD(ah,
+ AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC,
+ tuning_caps_params);
+ } else {
+ OS_REG_RMW_FIELD(ah,
+ AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC,
+ tuning_caps_params);
+ OS_REG_RMW_FIELD(ah,
+ AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC,
+ tuning_caps_params);
+ }
+
+ }
+ return AH_TRUE;
+}
+
+/*
+ * Read the tx_frame_to_xpa_on param from eeprom and apply the value to
+ * correct register.
+ */
+HAL_BOOL ar9300_xpa_timing_control_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
+{
+ u_int8_t xpa_timing_control;
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ if ((eep->base_eep_header.feature_enable & 0x80) >> 7) {
+ if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) {
+ if (is_2ghz) {
+ xpa_timing_control = eep->modal_header_2g.tx_frame_to_xpa_on;
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON,
+ xpa_timing_control);
+ } else {
+ xpa_timing_control = eep->modal_header_5g.tx_frame_to_xpa_on;
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON,
+ xpa_timing_control);
+ }
+ }
+ }
+ return AH_TRUE;
+}
+
+
+/*
+ * Read the xLNA_bias_strength param from eeprom and apply the value to
+ * correct register.
+ */
+HAL_BOOL ar9300_x_lNA_bias_strength_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
+{
+ u_int8_t x_lNABias;
+ u_int32_t value = 0;
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+
+ if ((eep->base_eep_header.misc_configuration & 0x40) >> 6) {
+ if (AR_SREV_OSPREY(ah)) {
+ if (is_2ghz) {
+ x_lNABias = eep->modal_header_2g.xLNA_bias_strength;
+ } else {
+ x_lNABias = eep->modal_header_5g.xLNA_bias_strength;
+ }
+ value = x_lNABias & ( 0x03 ); // bit0,1 for chain0
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
+ value = (x_lNABias >> 2) & ( 0x03 ); // bit2,3 for chain1
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
+ value = (x_lNABias >> 4) & ( 0x03 ); // bit4,5 for chain2
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
+ }
+ }
+ return AH_TRUE;
+}
+
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+HAL_BOOL
+ar9300_eeprom_set_board_values(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
+{
+ ar9300_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
+
+ ar9300_xpa_timing_control_apply(ah, IS_CHAN_2GHZ(chan));
+
+ ar9300_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
+ ar9300_drive_strength_apply(ah);
+
+ ar9300_x_lNA_bias_strength_apply(ah, IS_CHAN_2GHZ(chan));
+
+ /* wait for Poseidon internal regular turnning */
+ /* for Hornet we move it before initPLL to avoid an access issue */
+ /* Function not used when EMULATION. */
+ if (!AR_SREV_HORNET(ah) && !AR_SREV_WASP(ah)) {
+ ar9300_internal_regulator_apply(ah);
+ }
+
+ ar9300_attenuation_apply(ah, chan->channel);
+ ar9300_quick_drop_apply(ah, chan->channel);
+ ar9300_thermometer_apply(ah);
+ if(!AR_SREV_WASP(ah))
+ {
+ ar9300_tuning_caps_apply(ah);
+ }
+
+ ar9300_tx_end_to_xpab_off_apply(ah, chan->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;
+}
+
+#endif /* AH_SUPPORT_AR9300 */
diff --git a/hal/ar9300/ar9300_gpio.c b/hal/ar9300/ar9300_gpio.c
new file mode 100644
index 000000000000..edbdf1ab5894
--- /dev/null
+++ b/hal/ar9300/ar9300_gpio.c
@@ -0,0 +1,652 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#ifdef AH_DEBUG
+#include "ah_desc.h" /* NB: for HAL_PHYERR* */
+#endif
+
+#include "ar9300/ar9300.h"
+#include "ar9300/ar9300reg.h"
+#include "ar9300/ar9300phy.h"
+
+#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
+
+/*
+ * Configure GPIO Output Mux control
+ */
+#ifdef UMAC_SUPPORT_SMARTANTENNA
+static void ar9340_soc_gpio_cfg_output_mux(
+ struct ath_hal *ah,
+ u_int32_t gpio,
+ u_int32_t ah_signal_type)
+{
+#define ADDR_READ(addr) (*((volatile u_int32_t *)(addr)))
+#define ADDR_WRITE(addr, b) (void)((*(volatile u_int32_t *) (addr)) = (b))
+#define AR9340_SOC_GPIO_FUN0 0xB804002c
+#define AR9340_SOC_GPIO_OE 0xB8040000
+#if ATH_SMARTANTENNA_DISABLE_JTAG
+#define AR9340_SOC_GPIO_FUNCTION (volatile u_int32_t*) 0xB804006c
+#define WASP_DISABLE_JTAG 0x2
+#define MAX_JTAG_GPIO_PIN 1
+#endif
+ u_int8_t out_func, shift;
+ u_int32_t flags;
+ volatile u_int32_t* address;
+
+ if (!ah_signal_type){
+ return;
+ }
+#if ATH_SMARTANTENNA_DISABLE_JTAG
+/*
+ * To use GPIO pins 0 and 1 for controling antennas, JTAG needs to disabled.
+ */
+ if (gpio <= MAX_JTAG_GPIO_PIN) {
+ flags = ADDR_READ(AR9340_SOC_GPIO_FUNCTION);
+ flags |= WASP_DISABLE_JTAG;
+ ADDR_WRITE(AR9340_SOC_GPIO_FUNCTION, flags);
+ }
+#endif
+ out_func = gpio / 4;
+ shift = (gpio % 4);
+ address = (volatile u_int32_t *)(AR9340_SOC_GPIO_FUN0 + (out_func*4));
+
+ flags = ADDR_READ(address);
+ flags |= ah_signal_type << (8*shift);
+ ADDR_WRITE(address, flags);
+ flags = ADDR_READ(AR9340_SOC_GPIO_OE);
+ flags &= ~(1 << gpio);
+ ADDR_WRITE(AR9340_SOC_GPIO_OE, flags);
+
+}
+#endif
+
+static void
+ar9300_gpio_cfg_output_mux(struct ath_hal *ah, u_int32_t gpio, u_int32_t type)
+{
+ int addr;
+ u_int32_t gpio_shift;
+
+ /* each MUX controls 6 GPIO pins */
+ if (gpio > 11) {
+ addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3);
+ } else if (gpio > 5) {
+ addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2);
+ } else {
+ addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1);
+ }
+
+ /*
+ * 5 bits per GPIO pin.
+ * Bits 0..4 for 1st pin in that mux,
+ * bits 5..9 for 2nd pin, etc.
+ */
+ gpio_shift = (gpio % 6) * 5;
+
+ OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift));
+}
+
+/*
+ * Configure GPIO Output lines
+ */
+HAL_BOOL
+ar9300_gpio_cfg_output(
+ struct ath_hal *ah,
+ u_int32_t gpio,
+ HAL_GPIO_OUTPUT_MUX_TYPE hal_signal_type)
+{
+ u_int32_t ah_signal_type;
+ u_int32_t gpio_shift;
+ u_int8_t smart_ant = 0;
+ static const u_int32_t mux_signal_conversion_table[] = {
+ /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT */
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
+ /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
+ AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED */
+ AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED */
+ AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED */
+ AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE */
+ AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
+ /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME */
+ AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX */
+ AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX */
+ AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX */
+ AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX */
+ AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE */
+ AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
+ /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA */
+ AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
+ /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0 */
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
+ /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1 */
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
+ /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2 */
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2,
+ /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_SWCOM3 */
+ AR_GPIO_OUTPUT_MUX_AS_SWCOM3,
+ };
+
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+ if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
+ (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
+ (gpio == AR9382_GPIO_9_INPUT_ONLY))
+ {
+ return AH_FALSE;
+ }
+
+ /* Convert HAL signal type definitions to hardware-specific values. */
+ if (hal_signal_type < ARRAY_LENGTH(mux_signal_conversion_table))
+ {
+ ah_signal_type = mux_signal_conversion_table[hal_signal_type];
+ } else {
+ return AH_FALSE;
+ }
+
+ if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
+ OS_REG_SET_BIT(ah,
+ AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
+ }
+
+#if UMAC_SUPPORT_SMARTANTENNA
+ /* Get the pin and func values for smart antenna */
+ switch (ah_signal_type)
+ {
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
+ gpio = ATH_GPIOPIN_ANTCHAIN0;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
+ smart_ant = 1;
+ break;
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
+ gpio = ATH_GPIOPIN_ANTCHAIN1;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
+ smart_ant = 1;
+ break;
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
+ gpio = ATH_GPIOPIN_ANTCHAIN2;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
+ smart_ant = 1;
+ break;
+#if ATH_SMARTANTENNA_ROUTE_SWCOM_TO_GPIO
+ case AR_GPIO_OUTPUT_MUX_AS_SWCOM3:
+ gpio = ATH_GPIOPIN_ROUTE_SWCOM3;
+ ah_signal_type = ATH_GPIOFUNC_ROUTE_SWCOM3;
+ smart_ant = 1;
+ break;
+#endif
+ default:
+ break;
+ }
+#endif
+
+ if (smart_ant && (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)))
+ {
+#ifdef UMAC_SUPPORT_SMARTANTENNA
+ ar9340_soc_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+#endif
+ return AH_TRUE;
+ } else
+ {
+ /* Configure the MUX */
+ ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+ }
+
+ /* 2 bits per output mode */
+ gpio_shift = 2 * gpio;
+
+ OS_REG_RMW(ah,
+ AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
+ (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+ return AH_TRUE;
+}
+
+/*
+ * Configure GPIO Output lines -LED off
+ */
+HAL_BOOL
+ar9300_gpio_cfg_output_led_off(
+ struct ath_hal *ah,
+ u_int32_t gpio,
+ HAL_GPIO_OUTPUT_MUX_TYPE halSignalType)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ u_int32_t ah_signal_type;
+ u_int32_t gpio_shift;
+ u_int8_t smart_ant = 0;
+
+ static const u_int32_t mux_signal_conversion_table[] = {
+ /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT */
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
+ /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
+ AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED */
+ AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED */
+ AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED */
+ AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE */
+ AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
+ /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME */
+ AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
+ /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK */
+ AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX */
+ AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX */
+ AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX */
+ AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
+ /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX */
+ AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
+ AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
+ AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
+ AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2
+ };
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+
+ /* Convert HAL signal type definitions to hardware-specific values. */
+ if (halSignalType < ARRAY_LENGTH(mux_signal_conversion_table))
+ {
+ ah_signal_type = mux_signal_conversion_table[halSignalType];
+ } else {
+ return AH_FALSE;
+ }
+#if UMAC_SUPPORT_SMARTANTENNA
+ /* Get the pin and func values for smart antenna */
+ switch (halSignalType)
+ {
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
+ gpio = ATH_GPIOPIN_ANTCHAIN0;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
+ smart_ant = 1;
+ break;
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
+ gpio = ATH_GPIOPIN_ANTCHAIN1;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
+ smart_ant = 1;
+ break;
+ case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
+ gpio = ATH_GPIOPIN_ANTCHAIN2;
+ ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
+ smart_ant = 1;
+ break;
+ default:
+ break;
+ }
+#endif
+
+ if (smart_ant && AR_SREV_WASP(ah))
+ {
+ return AH_FALSE;
+ }
+
+ // Configure the MUX
+ ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+
+ // 2 bits per output mode
+ gpio_shift = 2*gpio;
+
+ OS_REG_RMW(ah,
+ AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+
+ return AH_TRUE;
+#undef N
+}
+
+/*
+ * Configure GPIO Input lines
+ */
+HAL_BOOL
+ar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio)
+{
+ u_int32_t gpio_shift;
+
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+ if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
+ (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
+ (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
+ {
+ return AH_FALSE;
+ }
+
+ if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
+ OS_REG_SET_BIT(ah,
+ AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
+ }
+ /* TODO: configure input mux for AR9300 */
+ /* If configured as input, set output to tristate */
+ gpio_shift = 2 * gpio;
+
+ OS_REG_RMW(ah,
+ AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
+ return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - set output lines
+ * output the level of GPio PIN without care work mode
+ */
+HAL_BOOL
+ar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val)
+{
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+ if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
+ (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
+ (gpio == AR9382_GPIO_9_INPUT_ONLY))
+ {
+ return AH_FALSE;
+ }
+ OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT),
+ ((val & 1) << gpio), AR_GPIO_BIT(gpio));
+
+ return AH_TRUE;
+}
+
+/*
+ * Once configured for I/O - get input lines
+ */
+u_int32_t
+ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio)
+{
+ u_int32_t gpio_in;
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+ if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
+ (gpio == AR9382_GPIO_PIN_11_RESERVED))
+ {
+ return 0xffffffff;
+ }
+
+ gpio_in = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN));
+ OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN),
+ (1 << gpio), AR_GPIO_BIT(gpio));
+ return (MS(gpio_in, AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
+}
+
+u_int32_t
+ar9300_gpio_get_intr(struct ath_hal *ah)
+{
+ unsigned int mask = 0;
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ mask = ahp->ah_gpio_cause;
+ return mask;
+}
+
+/*
+ * Set the GPIO Interrupt
+ * Sync and Async interrupts are both set/cleared.
+ * Async GPIO interrupts may not be raised when the chip is put to sleep.
+ */
+void
+ar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel)
+{
+
+
+ int i, reg_bit;
+ u_int32_t reg_val;
+ u_int32_t regs[2], shifts[2];
+
+#ifdef AH_ASSERT
+ u_int32_t gpio_mask;
+ u_int32_t old_field_val = 0, field_val = 0;
+#endif
+
+#ifdef ATH_GPIO_USE_ASYNC_CAUSE
+ regs[0] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE);
+ regs[1] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK);
+ shifts[0] = AR_INTR_ASYNC_ENABLE_GPIO_S;
+ shifts[1] = AR_INTR_ASYNC_MASK_GPIO_S;
+#else
+ regs[0] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE);
+ regs[1] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK);
+ shifts[0] = AR_INTR_SYNC_ENABLE_GPIO_S;
+ shifts[1] = AR_INTR_SYNC_MASK_GPIO_S;
+#endif
+
+ HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
+
+ if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
+ (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
+ (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
+ {
+ return;
+ }
+
+#ifdef AH_ASSERT
+ gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins) - 1;
+#endif
+
+ if (ilevel == HAL_GPIO_INTR_DISABLE) {
+ /* clear this GPIO's bit in the interrupt registers */
+ for (i = 0; i < ARRAY_LENGTH(regs); i++) {
+ reg_val = OS_REG_READ(ah, regs[i]);
+ reg_bit = shifts[i] + gpio;
+ reg_val &= ~(1 << reg_bit);
+ OS_REG_WRITE(ah, regs[i], reg_val);
+
+ /* check that each register has same GPIOs enabled */
+#ifdef AH_ASSERT
+ field_val = (reg_val >> shifts[i]) & gpio_mask;
+ HALASSERT(i == 0 || old_field_val == field_val);
+ old_field_val = field_val;
+#endif
+ }
+
+ } else {
+ reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
+ reg_bit = gpio;
+ if (ilevel == HAL_GPIO_INTR_HIGH) {
+ /* 0 == interrupt on pin high */
+ reg_val &= ~(1 << reg_bit);
+ } else if (ilevel == HAL_GPIO_INTR_LOW) {
+ /* 1 == interrupt on pin low */
+ reg_val |= (1 << reg_bit);
+ }
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), reg_val);
+
+ /* set this GPIO's bit in the interrupt registers */
+ for (i = 0; i < ARRAY_LENGTH(regs); i++) {
+ reg_val = OS_REG_READ(ah, regs[i]);
+ reg_bit = shifts[i] + gpio;
+ reg_val |= (1 << reg_bit);
+ OS_REG_WRITE(ah, regs[i], reg_val);
+
+ /* check that each register has same GPIOs enabled */
+#ifdef AH_ASSERT
+ field_val = (reg_val >> shifts[i]) & gpio_mask;
+ HALASSERT(i == 0 || old_field_val == field_val);
+ old_field_val = field_val;
+#endif
+ }
+ }
+}
+
+u_int32_t
+ar9300_gpio_get_polarity(struct ath_hal *ah)
+{
+ return OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
+
+}
+
+void
+ar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t pol_map,
+ u_int32_t changed_mask)
+{
+ u_int32_t gpio_mask;
+
+ gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins) - 1;
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), gpio_mask & pol_map);
+
+#ifndef ATH_GPIO_USE_ASYNC_CAUSE
+ /*
+ * For SYNC_CAUSE type interrupts, we need to clear the cause register
+ * explicitly. Otherwise an interrupt with the original polarity setting
+ * will come up immediately (if there is already an interrupt source),
+ * which is not what we want usually.
+ */
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR),
+ changed_mask << AR_INTR_SYNC_ENABLE_GPIO_S);
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
+#endif
+}
+
+/*
+ * get the GPIO input pin mask
+ * gpio0 - gpio13
+ * gpio8, gpio11, regard as reserved by the chip ar9382
+ */
+
+u_int32_t
+ar9300_gpio_get_mask(struct ath_hal *ah)
+{
+ u_int32_t mask = (1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1) ) - 1;
+
+ if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
+ mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1;
+ mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED |
+ 1 << AR9382_GPIO_PIN_11_RESERVED);
+ }
+ return mask;
+}
+
+int
+ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map)
+{
+ u_int32_t invalid = ~((1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1)) - 1);
+
+ if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
+ invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1);
+ invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED |
+ 1 << AR9382_GPIO_PIN_11_RESERVED;
+ }
+ if (mask & invalid) {
+ ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask);
+ return -1;
+ }
+ AH9300(ah)->ah_gpio_mask = mask;
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), mask & pol_map);
+
+ return 0;
+}
+
+#ifdef AH_DEBUG
+void ar9300_gpio_show(struct ath_hal *ah);
+void ar9300_gpio_show(struct ath_hal *ah)
+{
+ ath_hal_printf(ah, "--- 9382 GPIOs ---(ah=%p)\n", ah );
+ ath_hal_printf(ah,
+ "AH9300(_ah)->ah_hostifregs:%p\r\n", &(AH9300(ah)->ah_hostifregs));
+ ath_hal_printf(ah,
+ "GPIO_OUT: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT)));
+ ath_hal_printf(ah,
+ "GPIO_IN: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN)));
+ ath_hal_printf(ah,
+ "GPIO_OE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)));
+ ath_hal_printf(ah,
+ "GPIO_OE1_OUT: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT)));
+ ath_hal_printf(ah,
+ "GPIO_INTR_POLAR: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)));
+ ath_hal_printf(ah,
+ "GPIO_INPUT_VALUE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL)));
+ ath_hal_printf(ah,
+ "GPIO_INPUT_MUX1: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1)));
+ ath_hal_printf(ah,
+ "GPIO_INPUT_MUX2: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2)));
+ ath_hal_printf(ah,
+ "GPIO_OUTPUT_MUX1: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1)));
+ ath_hal_printf(ah,
+ "GPIO_OUTPUT_MUX2: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2)));
+ ath_hal_printf(ah,
+ "GPIO_OUTPUT_MUX3: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3)));
+ ath_hal_printf(ah,
+ "GPIO_INPUT_STATE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INPUT_STATE)));
+ ath_hal_printf(ah,
+ "GPIO_PDPU: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU)));
+ ath_hal_printf(ah,
+ "GPIO_DS: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_DS)));
+ ath_hal_printf(ah,
+ "AR_INTR_ASYNC_ENABLE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE)));
+ ath_hal_printf(ah,
+ "AR_INTR_ASYNC_MASK: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK)));
+ ath_hal_printf(ah,
+ "AR_INTR_SYNC_ENABLE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE)));
+ ath_hal_printf(ah,
+ "AR_INTR_SYNC_MASK: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK)));
+ ath_hal_printf(ah,
+ "AR_INTR_ASYNC_CAUSE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE)));
+ ath_hal_printf(ah,
+ "AR_INTR_SYNC_CAUSE: 0x%08X\n",
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)));
+
+}
+#endif /*AH_DEBUG*/
+
+#endif /* AH_SUPPORT_AR9300 */
diff --git a/hal/ar9300/ar9300_interrupts.c b/hal/ar9300/ar9300_interrupts.c
new file mode 100644
index 000000000000..cbd83c679773
--- /dev/null
+++ b/hal/ar9300/ar9300_interrupts.c
@@ -0,0 +1,767 @@
+/*
+ * 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"
+
+#ifdef AH_SUPPORT_AR9300
+
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ar9300/ar9300.h"
+#include "ar9300/ar9300reg.h"
+#include "ar9300/ar9300phy.h"
+
+/*
+ * Checks to see if an interrupt is pending on our NIC
+ *
+ * Returns: TRUE if an interrupt is pending
+ * FALSE if not
+ */
+HAL_BOOL
+ar9300_is_interrupt_pending(struct ath_hal *ah)
+{
+ u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
+ u_int32_t host_isr;
+
+ /*
+ * Some platforms trigger our ISR before applying power to
+ * the card, so make sure.
+ */
+ host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
+ if ((host_isr & AR_INTR_ASYNC_USED) && (host_isr != AR_INTR_SPURIOUS)) {
+ return AH_TRUE;
+ }
+
+ host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
+ 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;
+ }
+
+ if ((host_isr & (sync_en_def | AR_INTR_SYNC_MASK_GPIO)) &&
+ (host_isr != AR_INTR_SPURIOUS)) {
+ return AH_TRUE;
+ }
+
+ return AH_FALSE;
+}
+
+/*
+ * Reads the Interrupt Status Register value from the NIC, thus deasserting
+ * the interrupt line, and returns both the masked and unmasked mapped ISR
+ * values. The value returned is mapped to abstract the hw-specific bit
+ * locations in the Interrupt Status Register.
+ *
+ * Returns: A hardware-abstracted bitmap of all non-masked-out
+ * interrupts pending, as well as an unmasked value
+ */
+#define MAP_ISR_S2_HAL_CST 6 /* Carrier sense timeout */
+#define MAP_ISR_S2_HAL_GTT 6 /* Global transmit timeout */
+#define MAP_ISR_S2_HAL_TIM 3 /* TIM */
+#define MAP_ISR_S2_HAL_CABEND 0 /* CABEND */
+#define MAP_ISR_S2_HAL_DTIMSYNC 7 /* DTIMSYNC */
+#define MAP_ISR_S2_HAL_DTIM 7 /* DTIM */
+#define MAP_ISR_S2_HAL_TSFOOR 4 /* Rx TSF out of range */
+#define MAP_ISR_S2_HAL_BBPANIC 6 /* Panic watchdog IRQ from BB */
+HAL_BOOL
+ar9300_get_pending_interrupts(
+ struct ath_hal *ah,
+ HAL_INT *masked,
+ HAL_INT_TYPE type,
+ u_int8_t msi,
+ HAL_BOOL nortc)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ HAL_BOOL ret_val = AH_TRUE;
+ u_int32_t isr = 0;
+ u_int32_t mask2 = 0;
+ u_int32_t sync_cause = 0;
+ u_int32_t async_cause;
+ u_int32_t msi_pend_addr_mask = 0;
+ u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
+ HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
+
+ *masked = 0;
+
+ if (!nortc) {
+ if (HAL_INT_MSI == type) {
+ if (msi == HAL_MSIVEC_RXHP) {
+ OS_REG_WRITE(ah, AR_ISR, AR_ISR_HP_RXOK);
+ *masked = HAL_INT_RXHP;
+ goto end;
+ } else if (msi == HAL_MSIVEC_RXLP) {
+ OS_REG_WRITE(ah, AR_ISR,
+ (AR_ISR_LP_RXOK | AR_ISR_RXMINTR | AR_ISR_RXINTM));
+ *masked = HAL_INT_RXLP;
+ goto end;
+ } else if (msi == HAL_MSIVEC_TX) {
+ OS_REG_WRITE(ah, AR_ISR, AR_ISR_TXOK);
+ *masked = HAL_INT_TX;
+ goto end;
+ } else if (msi == HAL_MSIVEC_MISC) {
+ /*
+ * For the misc MSI event fall through and determine the cause.
+ */
+ }
+ }
+ }
+
+ /* Make sure mac interrupt is pending in async interrupt cause register */
+ async_cause = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
+ if (async_cause & AR_INTR_ASYNC_USED) {
+ /*
+ * RTC may not be on since it runs on a slow 32khz clock
+ * so check its status to be sure
+ */
+ if (!nortc &&
+ (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
+ AR_RTC_STATUS_ON)
+ {
+ isr = OS_REG_READ(ah, AR_ISR);
+ }
+ }
+
+ 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;
+ }
+
+ sync_cause =
+ OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &
+ (sync_en_def | AR_INTR_SYNC_MASK_GPIO);
+
+ if (!isr && !sync_cause && !async_cause) {
+ ret_val = AH_FALSE;
+ goto end;
+ }
+
+ if (isr) {
+ if (isr & AR_ISR_BCNMISC) {
+ u_int32_t isr2;
+ isr2 = OS_REG_READ(ah, AR_ISR_S2);
+
+ /* Translate ISR bits to HAL values */
+ mask2 |= ((isr2 & AR_ISR_S2_TIM) >> MAP_ISR_S2_HAL_TIM);
+ mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> MAP_ISR_S2_HAL_DTIM);
+ mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> MAP_ISR_S2_HAL_DTIMSYNC);
+ mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> MAP_ISR_S2_HAL_CABEND);
+ mask2 |= ((isr2 & AR_ISR_S2_GTT) << MAP_ISR_S2_HAL_GTT);
+ mask2 |= ((isr2 & AR_ISR_S2_CST) << MAP_ISR_S2_HAL_CST);
+ mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_HAL_TSFOOR);
+ mask2 |= ((isr2 & AR_ISR_S2_BBPANIC) >> MAP_ISR_S2_HAL_BBPANIC);
+
+ if (!p_cap->hal_isr_rac_support) {
+ /*
+ * EV61133 (missing interrupts due to ISR_RAC):
+ * If not using ISR_RAC, clear interrupts by writing to ISR_S2.
+ * This avoids a race condition where a new BCNMISC interrupt
+ * could come in between reading the ISR and clearing the
+ * interrupt via the primary ISR. We therefore clear the
+ * interrupt via the secondary, which avoids this race.
+ */
+ OS_REG_WRITE(ah, AR_ISR_S2, isr2);
+ isr &= ~AR_ISR_BCNMISC;
+ }
+ }
+
+ /* Use AR_ISR_RAC only if chip supports it.
+ * See EV61133 (missing interrupts due to ISR_RAC)
+ */
+ if (p_cap->hal_isr_rac_support) {
+ isr = OS_REG_READ(ah, AR_ISR_RAC);
+ }
+ if (isr == 0xffffffff) {
+ *masked = 0;
+ ret_val = AH_FALSE;
+ goto end;
+ }
+
+ *masked = isr & HAL_INT_COMMON;
+
+ /*
+ * When interrupt mitigation is switched on, we fake a normal RX or TX
+ * interrupt when we received a mitigated interrupt. This way, the upper
+ * layer do not need to know about feature.
+ */
+ if (ahp->ah_intr_mitigation_rx) {
+ /* Only Rx interrupt mitigation. No Tx intr. mitigation. */
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) {
+ *masked |= HAL_INT_RXLP;
+ }
+ }
+ if (ahp->ah_intr_mitigation_tx) {
+ if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) {
+ *masked |= HAL_INT_TX;
+ }
+ }
+
+ if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) {
+ *masked |= HAL_INT_RXLP;
+ }
+ if (isr & AR_ISR_HP_RXOK) {
+ *masked |= HAL_INT_RXHP;
+ }
+ if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+ *masked |= HAL_INT_TX;
+
+ if (!p_cap->hal_isr_rac_support) {
+ u_int32_t s0, s1;
+ /*
+ * EV61133 (missing interrupts due to ISR_RAC):
+ * If not using ISR_RAC, clear interrupts by writing to
+ * ISR_S0/S1.
+ * This avoids a race condition where a new interrupt
+ * could come in between reading the ISR and clearing the
+ * interrupt via the primary ISR. We therefore clear the
+ * interrupt via the secondary, which avoids this race.
+ */
+ s0 = OS_REG_READ(ah, AR_ISR_S0);
+ OS_REG_WRITE(ah, AR_ISR_S0, s0);
+ s1 = OS_REG_READ(ah, AR_ISR_S1);
+ OS_REG_WRITE(ah, AR_ISR_S1, s1);
+
+ isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL);
+ }
+ }
+
+ /*
+ * Do not treat receive overflows as fatal for owl.
+ */
+ if (isr & AR_ISR_RXORN) {
+#if __PKT_SERIOUS_ERRORS__
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: receive FIFO overrun interrupt\n", __func__);
+#endif
+ }
+
+#if 0
+ /* XXX Verify if this is fixed for Osprey */
+ if (!p_cap->hal_auto_sleep_support) {
+ u_int32_t isr5 = OS_REG_READ(ah, AR_ISR_S5_S);
+ if (isr5 & AR_ISR_S5_TIM_TIMER) {
+ *masked |= HAL_INT_TIM_TIMER;
+ }
+ }
+#endif
+ if (isr & AR_ISR_GENTMR) {
+ u_int32_t s5;
+
+ if (p_cap->hal_isr_rac_support) {
+ /* Use secondary shadow registers if using ISR_RAC */
+ s5 = OS_REG_READ(ah, AR_ISR_S5_S);
+ } else {
+ s5 = OS_REG_READ(ah, AR_ISR_S5);
+ }
+ if (isr & AR_ISR_GENTMR) {
+
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: GENTIMER, ISR_RAC=0x%x ISR_S2_S=0x%x\n", __func__,
+ isr, s5);
+ ahp->ah_intr_gen_timer_trigger =
+ MS(s5, AR_ISR_S5_GENTIMER_TRIG);
+ ahp->ah_intr_gen_timer_thresh =
+ MS(s5, AR_ISR_S5_GENTIMER_THRESH);
+ if (ahp->ah_intr_gen_timer_trigger) {
+ *masked |= HAL_INT_GENTIMER;
+ }
+ }
+ if (!p_cap->hal_isr_rac_support) {
+ /*
+ * EV61133 (missing interrupts due to ISR_RAC):
+ * If not using ISR_RAC, clear interrupts by writing to ISR_S5.
+ * This avoids a race condition where a new interrupt
+ * could come in between reading the ISR and clearing the
+ * interrupt via the primary ISR. We therefore clear the
+ * interrupt via the secondary, which avoids this race.
+ */
+ OS_REG_WRITE(ah, AR_ISR_S5, s5);
+ isr &= ~AR_ISR_GENTMR;
+ }
+ }
+
+ *masked |= mask2;
+
+ if (!p_cap->hal_isr_rac_support) {
+ /*
+ * EV61133 (missing interrupts due to ISR_RAC):
+ * If not using ISR_RAC, clear the interrupts we've read by
+ * writing back ones in these locations to the primary ISR
+ * (except for interrupts that have a secondary isr register -
+ * see above).
+ */
+ OS_REG_WRITE(ah, AR_ISR, isr);
+
+ /* Flush prior write */
+ (void) OS_REG_READ(ah, AR_ISR);
+ }
+
+#ifdef AH_SUPPORT_AR9300
+ if (*masked & HAL_INT_BBPANIC) {
+ ar9300_handle_bb_panic(ah);
+ }
+#endif
+ }
+
+ if (async_cause) {
+ if (nortc) {
+ OS_REG_WRITE(ah,
+ AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR), async_cause);
+ /* Flush prior write */
+ (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR));
+ } else {
+#ifdef ATH_GPIO_USE_ASYNC_CAUSE
+ if (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) {
+ ahp->ah_gpio_cause = (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) >>
+ AR_INTR_ASYNC_ENABLE_GPIO_S;
+ *masked |= HAL_INT_GPIO;
+ }
+#endif
+ }
+
+#if ATH_SUPPORT_MCI
+ if ((async_cause & AR_INTR_ASYNC_CAUSE_MCI) &&
+ p_cap->hal_mci_support)
+ {
+ u_int32_t int_raw, int_rx_msg;
+
+ int_rx_msg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
+ int_raw = OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW);
+
+ if ((int_raw == 0xdeadbeef) || (int_rx_msg == 0xdeadbeef))
+ {
+ HALDEBUG(ah, HAL_DEBUG_BT_COEX,
+ "(MCI) Get 0xdeadbeef during MCI int processing"
+ "new int_raw=0x%08x, new rx_msg_raw=0x%08x, "
+ "int_raw=0x%08x, rx_msg_raw=0x%08x\n",
+ int_raw, int_rx_msg, ahp->ah_mci_int_raw,
+ ahp->ah_mci_int_rx_msg);
+ }
+ else {
+ if (ahp->ah_mci_int_raw || ahp->ah_mci_int_rx_msg) {
+ ahp->ah_mci_int_rx_msg |= int_rx_msg;
+ ahp->ah_mci_int_raw |= int_raw;
+ }
+ else {
+ ahp->ah_mci_int_rx_msg = int_rx_msg;
+ ahp->ah_mci_int_raw = int_raw;
+ }
+
+ *masked |= HAL_INT_MCI;
+ ahp->ah_mci_rx_status = OS_REG_READ(ah, AR_MCI_RX_STATUS);
+ if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
+ ahp->ah_mci_cont_status =
+ OS_REG_READ(ah, AR_MCI_CONT_STATUS);
+ }
+ OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+ int_rx_msg);
+ OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, int_raw);
+
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s:AR_INTR_SYNC_MCI\n", __func__);
+ }
+ }
+#endif
+ }
+
+ if (sync_cause) {
+ int host1_fatal, host1_perr, radm_cpl_timeout, local_timeout;
+
+ host1_fatal = AR_SREV_WASP(ah) ?
+ AR9340_INTR_SYNC_HOST1_FATAL : AR9300_INTR_SYNC_HOST1_FATAL;
+ host1_perr = AR_SREV_WASP(ah) ?
+ AR9340_INTR_SYNC_HOST1_PERR : AR9300_INTR_SYNC_HOST1_PERR;
+ radm_cpl_timeout = AR_SREV_WASP(ah) ?
+ 0x0 : AR9300_INTR_SYNC_RADM_CPL_TIMEOUT;
+ local_timeout = AR_SREV_WASP(ah) ?
+ AR9340_INTR_SYNC_LOCAL_TIMEOUT : AR9300_INTR_SYNC_LOCAL_TIMEOUT;
+
+ if (sync_cause & host1_fatal) {
+#if __PKT_SERIOUS_ERRORS__
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: received PCI FATAL interrupt\n", __func__);
+#endif
+ *masked |= HAL_INT_FATAL; /* Set FATAL INT flag here;*/
+ }
+ if (sync_cause & host1_perr) {
+#if __PKT_SERIOUS_ERRORS__
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: received PCI PERR interrupt\n", __func__);
+#endif
+ }
+
+ if (sync_cause & radm_cpl_timeout) {
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
+ __func__);
+
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);
+ *masked |= HAL_INT_FATAL;
+ }
+ if (sync_cause & local_timeout) {
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
+ __func__);
+ }
+
+#ifndef ATH_GPIO_USE_ASYNC_CAUSE
+ if (sync_cause & AR_INTR_SYNC_MASK_GPIO) {
+ ahp->ah_gpio_cause = (sync_cause & AR_INTR_SYNC_MASK_GPIO) >>
+ AR_INTR_SYNC_ENABLE_GPIO_S;
+ *masked |= HAL_INT_GPIO;
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: AR_INTR_SYNC_GPIO\n", __func__);
+ }
+#endif
+
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), sync_cause);
+ /* Flush prior write */
+ (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
+ }
+
+end:
+ if (HAL_INT_MSI == type) {
+ /*
+ * WAR for Bug EV#75887
+ * In normal case, SW read HOST_INTF_PCIE_MSI (0x40A4) and write
+ * into ah_msi_reg. Then use value of ah_msi_reg to set bit#25
+ * when want to enable HW write the cfg_msi_pending.
+ * Sometimes, driver get MSI interrupt before read 0x40a4 and
+ * ah_msi_reg is initialization value (0x0).
+ * We don't know why "MSI interrupt earlier than driver read" now...
+ */
+ if (!ahp->ah_msi_reg) {
+ ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));
+ }
+ if (AR_SREV_POSEIDON(ah)) {
+ msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
+ } else {
+ msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
+ }
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
+ ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
+
+ }
+
+ return ret_val;
+}
+
+HAL_INT
+ar9300_get_interrupts(struct ath_hal *ah)
+{
+ return AH9300(ah)->ah_mask_reg;
+}
+
+/*
+ * Atomically enables NIC interrupts. Interrupts are passed in
+ * via the enumerated bitmask in ints.
+ */
+HAL_INT
+ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL nortc)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ u_int32_t omask = ahp->ah_mask_reg;
+ u_int32_t mask, mask2, msi_mask = 0;
+ u_int32_t msi_pend_addr_mask = 0;
+ u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
+ HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
+
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: 0x%x => 0x%x\n", __func__, omask, ints);
+
+ if (omask & HAL_INT_GLOBAL) {
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
+
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_enable_msi) {
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);
+ /* flush write to HW */
+ (void)OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE));
+ }
+
+ if (!nortc) {
+ OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+ (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */
+ }
+
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
+ /* flush write to HW */
+ (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE));
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), 0);
+ /* flush write to HW */
+ (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE));
+ }
+
+ if (!nortc) {
+ /* reference count for global IER */
+ if (ints & HAL_INT_GLOBAL) {
+#ifdef AH_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: Request HAL_INT_GLOBAL ENABLED\n", __func__);
+ if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0) {
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s: WARNING: ah_ier_ref_count is 0 "
+ "and attempting to enable IER\n",
+ __func__);
+ }
+#endif
+ if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) > 0) {
+ OS_ATOMIC_DEC(&ahp->ah_ier_ref_count);
+ }
+ } else {
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: Request HAL_INT_GLOBAL DISABLED\n", __func__);
+ OS_ATOMIC_INC(&ahp->ah_ier_ref_count);
+ }
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: ah_ier_ref_count = %d\n", __func__, ahp->ah_ier_ref_count);
+
+ mask = ints & HAL_INT_COMMON;
+ mask2 = 0;
+ msi_mask = 0;
+
+ if (ints & HAL_INT_TX) {
+ if (ahp->ah_intr_mitigation_tx) {
+ mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
+ } else if (ahp->ah_tx_ok_interrupt_mask) {
+ mask |= AR_IMR_TXOK;
+ }
+ msi_mask |= AR_INTR_PRIO_TX;
+ if (ahp->ah_tx_err_interrupt_mask) {
+ mask |= AR_IMR_TXERR;
+ }
+ if (ahp->ah_tx_eol_interrupt_mask) {
+ mask |= AR_IMR_TXEOL;
+ }
+ }
+ if (ints & HAL_INT_RX) {
+ mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
+ if (ahp->ah_intr_mitigation_rx) {
+ mask &= ~(AR_IMR_RXOK_LP);
+ mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+ } else {
+ mask |= AR_IMR_RXOK_LP;
+ }
+ msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;
+ if (! p_cap->hal_auto_sleep_support) {
+ mask |= AR_IMR_GENTMR;
+ }
+ }
+
+ if (ints & (HAL_INT_BMISC)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & HAL_INT_TIM) {
+ mask2 |= AR_IMR_S2_TIM;
+ }
+ if (ints & HAL_INT_DTIM) {
+ mask2 |= AR_IMR_S2_DTIM;
+ }
+ if (ints & HAL_INT_DTIMSYNC) {
+ mask2 |= AR_IMR_S2_DTIMSYNC;
+ }
+ if (ints & HAL_INT_CABEND) {
+ mask2 |= (AR_IMR_S2_CABEND);
+ }
+ if (ints & HAL_INT_TSFOOR) {
+ mask2 |= AR_IMR_S2_TSFOOR;
+ }
+ }
+
+ if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
+ mask |= AR_IMR_BCNMISC;
+ if (ints & HAL_INT_GTT) {
+ mask2 |= AR_IMR_S2_GTT;
+ }
+ if (ints & HAL_INT_CST) {
+ mask2 |= AR_IMR_S2_CST;
+ }
+ }
+
+ if (ints & HAL_INT_BBPANIC) {
+ /* EV92527 - MAC secondary interrupt must enable AR_IMR_BCNMISC */
+ mask |= AR_IMR_BCNMISC;
+ mask2 |= AR_IMR_S2_BBPANIC;
+ }
+
+ if (ints & HAL_INT_GENTIMER) {
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "%s: enabling gen timer\n", __func__);
+ mask |= AR_IMR_GENTMR;
+ }
+
+ /* Write the new IMR and store off our SW copy. */
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
+ OS_REG_WRITE(ah, AR_IMR, mask);
+ ahp->ah_mask2Reg &= ~(AR_IMR_S2_TIM |
+ AR_IMR_S2_DTIM |
+ AR_IMR_S2_DTIMSYNC |
+ AR_IMR_S2_CABEND |
+ AR_IMR_S2_CABTO |
+ AR_IMR_S2_TSFOOR |
+ AR_IMR_S2_GTT |
+ AR_IMR_S2_CST |
+ AR_IMR_S2_BBPANIC);
+ ahp->ah_mask2Reg |= mask2;
+ OS_REG_WRITE(ah, AR_IMR_S2, ahp->ah_mask2Reg );
+ ahp->ah_mask_reg = ints;
+
+ if (! p_cap->hal_auto_sleep_support) {
+ if (ints & HAL_INT_TIM_TIMER) {
+ OS_REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ }
+ else {
+ OS_REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+ }
+ }
+ }
+
+ /* Re-enable interrupts if they were enabled before. */
+#if HAL_INTR_REFCOUNT_DISABLE
+ if ((ints & HAL_INT_GLOBAL)) {
+#else
+ if ((ints & HAL_INT_GLOBAL) && (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0)) {
+#endif
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
+
+ if (!nortc) {
+ OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+ }
+
+ mask = AR_INTR_MAC_IRQ;
+#ifdef ATH_GPIO_USE_ASYNC_CAUSE
+ if (ints & HAL_INT_GPIO) {
+ if (ahp->ah_gpio_mask) {
+ mask |= SM(ahp->ah_gpio_mask, AR_INTR_ASYNC_MASK_GPIO);
+ }
+ }
+#endif
+
+#if ATH_SUPPORT_MCI
+ if (ints & HAL_INT_MCI) {
+ mask |= AR_INTR_ASYNC_MASK_MCI;
+ }
+#endif
+
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), mask);
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK), mask);
+
+ if (AH_PRIVATE(ah)->ah_config.ath_hal_enable_msi) {
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE),
+ msi_mask);
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK),
+ msi_mask);
+ if (AR_SREV_POSEIDON(ah)) {
+ msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
+ } else {
+ msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
+ }
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
+ ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
+ }
+
+ /*
+ * debug - enable to see all synchronous interrupts status
+ * Enable synchronous GPIO interrupts as well, since some async
+ * GPIO interrupts don't wake the chip up.
+ */
+ mask = 0;
+#ifndef ATH_GPIO_USE_ASYNC_CAUSE
+ if (ints & HAL_INT_GPIO) {
+ mask |= SM(ahp->ah_gpio_mask, AR_INTR_SYNC_MASK_GPIO);
+ }
+#endif
+ 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 | mask));
+ OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK),
+ (sync_en_def | mask));
+
+ HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
+ "AR_IMR 0x%x IER 0x%x\n",
+ OS_REG_READ(ah, AR_IMR), OS_REG_READ(ah, AR_IER));
+ }
+
+ return omask;
+}
+
+void
+ar9300_set_intr_mitigation_timer(
+ struct ath_hal* ah,
+ HAL_INT_MITIGATION reg,
+ u_int32_t value)
+{
+#ifdef AR5416_INT_MITIGATION
+ switch (reg) {
+ case HAL_INT_THRESHOLD:
+ OS_REG_WRITE(ah, AR_MIRT, 0);
+ break;
+ case HAL_INT_RX_LASTPKT:
+ OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, value);
+ break;
+ case HAL_INT_RX_FIRSTPKT:
+ OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, value);
+ break;
+ case HAL_INT_TX_LASTPKT:
+ OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, value);
+ break;
+ case HAL_INT_TX_FIRSTPKT:
+ OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, value);
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
+u_int32_t
+ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg)
+{
+ u_int32_t val = 0;
+#ifdef AR5416_INT_MITIGATION
+ switch (reg) {
+ case HAL_INT_THRESHOLD:
+ val = OS_REG_READ(ah, AR_MIRT);
+ break;
+ case HAL_INT_RX_LASTPKT:
+ val = OS_REG_READ(ah, AR_RIMT) & 0xFFFF;
+ break;
+ case HAL_INT_RX_FIRSTPKT:
+ val = OS_REG_READ(ah, AR_RIMT) >> 16;
+ break;
+ case HAL_INT_TX_LASTPKT:
+ val = OS_REG_READ(ah, AR_TIMT) & 0xFFFF;
+ break;
+ case HAL_INT_TX_FIRSTPKT:
+ val = OS_REG_READ(ah, AR_TIMT) >> 16;
+ break;
+ default:
+ break;
+ }
+#endif
+ return val;
+}
+
+#endif /* AH_SUPPORT_AR9300 */
+
diff --git a/hal/ar9300/ar9300_jupiter10.ini b/hal/ar9300/ar9300_jupiter10.ini
new file mode 100644
index 000000000000..24b9785ab52e
--- /dev/null
+++ b/hal/ar9300/ar9300_jupiter10.ini
@@ -0,0 +1,1894 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static const u_int32_t ar9300_jupiter_1p0_mac_core[][2] = {
+/* Addr allmodes */
+ { 0x00000008 , 0x00000000 },
+ { 0x00000030 , 0x00060085 },
+ { 0x00000034 , 0x00000005 },
+ { 0x00000040 , 0x00000000 },
+ { 0x00000044 , 0x00000000 },
+ { 0x00000048 , 0x00000008 },
+ { 0x0000004c , 0x00000010 },
+ { 0x00000050 , 0x00000000 },
+ { 0x00001040 , 0x002ffc0f },
+ { 0x00001044 , 0x002ffc0f },
+ { 0x00001048 , 0x002ffc0f },
+ { 0x0000104c , 0x002ffc0f },
+ { 0x00001050 , 0x002ffc0f },
+ { 0x00001054 , 0x002ffc0f },
+ { 0x00001058 , 0x002ffc0f },
+ { 0x0000105c , 0x002ffc0f },
+ { 0x00001060 , 0x002ffc0f },
+ { 0x00001064 , 0x002ffc0f },
+ { 0x000010f0 , 0x00000100 },
+ { 0x00001270 , 0x00000000 },
+ { 0x000012b0 , 0x00000000 },
+ { 0x000012f0 , 0x00000000 },
+ { 0x0000143c , 0x00000000 },
+ { 0x0000147c , 0x00000000 },
+ { 0x00001810 , 0x0f000003 },
+ { 0x00008000 , 0x00000000 },
+ { 0x00008004 , 0x00000000 },
+ { 0x00008008 , 0x00000000 },
+ { 0x0000800c , 0x00000000 },
+ { 0x00008018 , 0x00000000 },
+ { 0x00008020 , 0x00000000 },
+ { 0x00008038 , 0x00000000 },
+ { 0x0000803c , 0x00080000 },
+ { 0x00008040 , 0x00000000 },
+ { 0x00008044 , 0x00000000 },
+ { 0x00008048 , 0x00000000 },
+ { 0x0000804c , 0xffffffff },
+ { 0x00008050 , 0xffffffff },
+ { 0x00008054 , 0x00000000 },
+ { 0x00008058 , 0x00000000 },
+ { 0x0000805c , 0x000fc78f },
+ { 0x00008060 , 0x0000000f },
+ { 0x00008064 , 0x00000000 },
+ { 0x00008070 , 0x00000310 },
+ { 0x00008074 , 0x00000020 },
+ { 0x00008078 , 0x00000000 },
+ { 0x0000809c , 0x0000000f },
+ { 0x000080a0 , 0x00000000 },
+ { 0x000080a4 , 0x02ff0000 },
+ { 0x000080a8 , 0x0e070605 },
+ { 0x000080ac , 0x0000000d },
+ { 0x000080b0 , 0x00000000 },
+ { 0x000080b4 , 0x00000000 },
+ { 0x000080b8 , 0x00000000 },
+ { 0x000080bc , 0x00000000 },
+ { 0x000080c0 , 0x2a800000 },
+ { 0x000080c4 , 0x06900168 },
+ { 0x000080c8 , 0x13881c20 },
+ { 0x000080cc , 0x01f40000 },
+ { 0x000080d0 , 0x00252500 },
+ { 0x000080d4 , 0x00a00005 },
+ { 0x000080d8 , 0x00400002 },
+ { 0x000080dc , 0x00000000 },
+ { 0x000080e0 , 0xffffffff },
+ { 0x000080e4 , 0x0000ffff },
+ { 0x000080e8 , 0x3f3f3f3f },
+ { 0x000080ec , 0x00000000 },
+ { 0x000080f0 , 0x00000000 },
+ { 0x000080f4 , 0x00000000 },
+ { 0x000080fc , 0x00020000 },
+ { 0x00008100 , 0x00000000 },
+ { 0x00008108 , 0x00000052 },
+ { 0x0000810c , 0x00000000 },
+ { 0x00008110 , 0x00000000 },
+ { 0x00008114 , 0x000007ff },
+ { 0x00008118 , 0x000000aa },
+ { 0x0000811c , 0x00003210 },
+ { 0x00008124 , 0x00000000 },
+ { 0x00008128 , 0x00000000 },
+ { 0x0000812c , 0x00000000 },
+ { 0x00008130 , 0x00000000 },
+ { 0x00008134 , 0x00000000 },
+ { 0x00008138 , 0x00000000 },
+ { 0x0000813c , 0x0000ffff },
+ { 0x00008144 , 0xffffffff },
+ { 0x00008168 , 0x00000000 },
+ { 0x0000816c , 0x00000000 },
+ { 0x00008170 , 0x18486e00 },
+ { 0x00008174 , 0x33332210 },
+ { 0x00008178 , 0x00000000 },
+ { 0x0000817c , 0x00020000 },
+ { 0x000081c4 , 0x33332210 },
+ { 0x000081c8 , 0x00000000 },
+ { 0x000081cc , 0x00000000 },
+ { 0x000081d4 , 0x00000000 },
+ { 0x000081ec , 0x00000000 },
+ { 0x000081f0 , 0x00000000 },
+ { 0x000081f4 , 0x00000000 },
+ { 0x000081f8 , 0x00000000 },
+ { 0x000081fc , 0x00000000 },
+ { 0x00008240 , 0x00100000 },
+ { 0x00008244 , 0x0010f400 },
+ { 0x00008248 , 0x00000800 },
+ { 0x0000824c , 0x0001e800 },
+ { 0x00008250 , 0x00000000 },
+ { 0x00008254 , 0x00000000 },
+ { 0x00008258 , 0x00000000 },
+ { 0x0000825c , 0x40000000 },
+ { 0x00008260 , 0x00080922 },
+ { 0x00008264 , 0x99c00010 },
+ { 0x00008268 , 0xffffffff },
+ { 0x0000826c , 0x0000ffff },
+ { 0x00008270 , 0x00000000 },
+ { 0x00008274 , 0x40000000 },
+ { 0x00008278 , 0x003e4180 },
+ { 0x0000827c , 0x00000004 },
+ { 0x00008284 , 0x0000002c },
+ { 0x00008288 , 0x0000002c },
+ { 0x0000828c , 0x000000ff },
+ { 0x00008294 , 0x00000000 },
+ { 0x00008298 , 0x00000000 },
+ { 0x0000829c , 0x00000000 },
+ { 0x00008300 , 0x00000140 },
+ { 0x00008314 , 0x00000000 },
+ { 0x0000831c , 0x0000010d },
+ { 0x00008328 , 0x00000000 },
+ { 0x0000832c , 0x0000001f },
+ { 0x00008330 , 0x00000302 },
+ { 0x00008334 , 0x00000700 },
+ { 0x00008338 , 0xffff0000 },
+ { 0x0000833c , 0x02400000 },
+ { 0x00008340 , 0x000107ff },
+ { 0x00008344 , 0xaa48105b },
+ { 0x00008348 , 0x008f0000 },
+ { 0x0000835c , 0x00000000 },
+ { 0x00008360 , 0xffffffff },
+ { 0x00008364 , 0xffffffff },
+ { 0x00008368 , 0x00000000 },
+ { 0x00008370 , 0x00000000 },
+ { 0x00008374 , 0x000000ff },
+ { 0x00008378 , 0x00000000 },
+ { 0x0000837c , 0x00000000 },
+ { 0x00008380 , 0xffffffff },
+ { 0x00008384 , 0xffffffff },
+ { 0x00008390 , 0xffffffff },
+ { 0x00008394 , 0xffffffff },
+ { 0x00008398 , 0x00000000 },
+ { 0x0000839c , 0x00000000 },
+ { 0x000083a4 , 0x0000fa14 },
+ { 0x000083a8 , 0x000f0c00 },
+ { 0x000083ac , 0x33332210 },
+ { 0x000083b0 , 0x33332210 },
+ { 0x000083b4 , 0x33332210 },
+ { 0x000083b8 , 0x33332210 },
+ { 0x000083bc , 0x00000000 },
+ { 0x000083c0 , 0x00000000 },
+ { 0x000083c4 , 0x00000000 },
+ { 0x000083c8 , 0x00000000 },
+ { 0x000083cc , 0x00000200 },
+ { 0x000083d0 , 0x000301ff },
+};
+
+static const u_int32_t ar9300_jupiter_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+/* Addr allmodes */
+ { 0x0000a398 , 0x00000000 },
+ { 0x0000a39c , 0x6f7f0301 },
+ { 0x0000a3a0 , 0xca9228ee },
+};
+
+static const u_int32_t ar9300_jupiter_1p0_sys3ant[][2] = {
+/* Addr allmodes */
+ { 0x00063280 , 0x00040807 },
+ { 0x00063284 , 0x104ccccc },
+};
+
+static const u_int32_t ar9300_pcie_phy_clkreq_enable_L1_jupiter_1p0[][2] = {
+/* Addr allmodes */
+ { 0x00018c00 , 0x10053e5e },
+ { 0x00018c04 , 0x000801d8 },
+ { 0x00018c08 , 0x0000580c },
+};
+
+static const u_int32_t ar9300_jupiter_1p0_mac_core_emulation[][2] = {
+/* Addr allmodes */
+ { 0x00000030 , 0x00060085 },
+ { 0x00000044 , 0x00000008 },
+ { 0x0000805c , 0xffffc7ff },
+ { 0x00008344 , 0xaa4a105b },
+};
+
+static const u_int32_t ar9300Common_rx_gain_table_merlin_2p0_jupiter_1p0[][2] = {
+/* Addr allmodes */
+ { 0x0000a000 , 0x02000101 },
+ { 0x0000a004 , 0x02000102 },
+ { 0x0000a008 , 0x02000103 },
+ { 0x0000a00c , 0x02000104 },
+ { 0x0000a010 , 0x02000200 },
+ { 0x0000a014 , 0x02000201 },
+ { 0x0000a018 , 0x02000202 },
+ { 0x0000a01c , 0x02000203 },
+ { 0x0000a020 , 0x02000204 },
+ { 0x0000a024 , 0x02000205 },
+ { 0x0000a028 , 0x02000208 },
+ { 0x0000a02c , 0x02000302 },
+ { 0x0000a030 , 0x02000303 },
+ { 0x0000a034 , 0x02000304 },
+ { 0x0000a038 , 0x02000400 },
+ { 0x0000a03c , 0x02010300 },
+ { 0x0000a040 , 0x02010301 },
+ { 0x0000a044 , 0x02010302 },
+ { 0x0000a048 , 0x02000500 },
+ { 0x0000a04c , 0x02010400 },
+ { 0x0000a050 , 0x02020300 },
+ { 0x0000a054 , 0x02020301 },
+ { 0x0000a058 , 0x02020302 },
+ { 0x0000a05c , 0x02020303 },
+ { 0x0000a060 , 0x02020400 },
+ { 0x0000a064 , 0x02030300 },
+ { 0x0000a068 , 0x02030301 },
+ { 0x0000a06c , 0x02030302 },
+ { 0x0000a070 , 0x02030303 },
+ { 0x0000a074 , 0x02030400 },
+ { 0x0000a078 , 0x02040300 },
+ { 0x0000a07c , 0x02040301 },
+ { 0x0000a080 , 0x02040302 },
+ { 0x0000a084 , 0x02040303 },
+ { 0x0000a088 , 0x02030500 },
+ { 0x0000a08c , 0x02040400 },
+ { 0x0000a090 , 0x02050203 },
+ { 0x0000a094 , 0x02050204 },
+ { 0x0000a098 , 0x02050205 },
+ { 0x0000a09c , 0x02040500 },
+ { 0x0000a0a0 , 0x02050301 },
+ { 0x0000a0a4 , 0x02050302 },
+ { 0x0000a0a8 , 0x02050303 },
+ { 0x0000a0ac , 0x02050400 },
+ { 0x0000a0b0 , 0x02050401 },
+ { 0x0000a0b4 , 0x02050402 },
+ { 0x0000a0b8 , 0x02050403 },
+ { 0x0000a0bc , 0x02050500 },
+ { 0x0000a0c0 , 0x02050501 },
+ { 0x0000a0c4 , 0x02050502 },
+ { 0x0000a0c8 , 0x02050503 },
+ { 0x0000a0cc , 0x02050504 },
+ { 0x0000a0d0 , 0x02050600 },
+ { 0x0000a0d4 , 0x02050601 },
+ { 0x0000a0d8 , 0x02050602 },
+ { 0x0000a0dc , 0x02050603 },
+ { 0x0000a0e0 , 0x02050604 },
+ { 0x0000a0e4 , 0x02050700 },
+ { 0x0000a0e8 , 0x02050701 },
+ { 0x0000a0ec , 0x02050702 },
+ { 0x0000a0f0 , 0x02050703 },
+ { 0x0000a0f4 , 0x02050704 },
+ { 0x0000a0f8 , 0x02050705 },
+ { 0x0000a0fc , 0x02050708 },
+ { 0x0000a100 , 0x02050709 },
+ { 0x0000a104 , 0x0205070a },
+ { 0x0000a108 , 0x0205070b },
+ { 0x0000a10c , 0x0205070c },
+ { 0x0000a110 , 0x0205070d },
+ { 0x0000a114 , 0x02050710 },
+ { 0x0000a118 , 0x02050711 },
+ { 0x0000a11c , 0x02050712 },
+ { 0x0000a120 , 0x02050713 },
+ { 0x0000a124 , 0x02050714 },
+ { 0x0000a128 , 0x02050715 },
+ { 0x0000a12c , 0x02050730 },
+ { 0x0000a130 , 0x02050731 },
+ { 0x0000a134 , 0x02050732 },
+ { 0x0000a138 , 0x02050733 },
+ { 0x0000a13c , 0x02050734 },
+ { 0x0000a140 , 0x02050735 },
+ { 0x0000a144 , 0x02050750 },
+ { 0x0000a148 , 0x02050751 },
+ { 0x0000a14c , 0x02050752 },
+ { 0x0000a150 , 0x02050753 },
+ { 0x0000a154 , 0x02050754 },
+ { 0x0000a158 , 0x02050755 },
+ { 0x0000a15c , 0x02050770 },
+ { 0x0000a160 , 0x02050771 },
+ { 0x0000a164 , 0x02050772 },
+ { 0x0000a168 , 0x02050773 },
+ { 0x0000a16c , 0x02050774 },
+ { 0x0000a170 , 0x02050775 },
+ { 0x0000a174 , 0x00000776 },
+ { 0x0000a178 , 0x00000776 },
+ { 0x0000a17c , 0x00000776 },
+ { 0x0000a180 , 0x00000776 },
+ { 0x0000a184 , 0x00000776 },
+ { 0x0000a188 , 0x00000776 },
+ { 0x0000a18c , 0x00000776 },
+ { 0x0000a190 , 0x00000776 },
+ { 0x0000a194 , 0x00000776 },
+ { 0x0000a198 , 0x00000776 },
+ { 0x0000a19c , 0x00000776 },
+ { 0x0000a1a0 , 0x00000776 },
+ { 0x0000a1a4 , 0x00000776 },
+ { 0x0000a1a8 , 0x00000776 },
+ { 0x0000a1ac , 0x00000776 },
+ { 0x0000a1b0 , 0x00000776 },
+ { 0x0000a1b4 , 0x00000776 },
+ { 0x0000a1b8 , 0x00000776 },
+ { 0x0000a1bc , 0x00000776 },
+ { 0x0000a1c0 , 0x00000776 },
+ { 0x0000a1c4 , 0x00000776 },
+ { 0x0000a1c8 , 0x00000776 },
+ { 0x0000a1cc , 0x00000776 },
+ { 0x0000a1d0 , 0x00000776 },
+ { 0x0000a1d4 , 0x00000776 },
+ { 0x0000a1d8 , 0x00000776 },
+ { 0x0000a1dc , 0x00000776 },
+ { 0x0000a1e0 , 0x00000776 },
+ { 0x0000a1e4 , 0x00000776 },
+ { 0x0000a1e8 , 0x00000776 },
+ { 0x0000a1ec , 0x00000776 },
+ { 0x0000a1f0 , 0x00000776 },
+ { 0x0000a1f4 , 0x00000776 },
+ { 0x0000a1f8 , 0x00000776 },
+ { 0x0000a1fc , 0x00000776 },
+ { 0x0000b000 , 0x02000101 },
+ { 0x0000b004 , 0x02000102 },
+ { 0x0000b008 , 0x02000103 },
+ { 0x0000b00c , 0x02000104 },
+ { 0x0000b010 , 0x02000200 },
+ { 0x0000b014 , 0x02000201 },
+ { 0x0000b018 , 0x02000202 },
+ { 0x0000b01c , 0x02000203 },
+ { 0x0000b020 , 0x02000204 },
+ { 0x0000b024 , 0x02000205 },
+ { 0x0000b028 , 0x02000208 },
+ { 0x0000b02c , 0x02000302 },
+ { 0x0000b030 , 0x02000303 },
+ { 0x0000b034 , 0x02000304 },
+ { 0x0000b038 , 0x02000400 },
+ { 0x0000b03c , 0x02010300 },
+ { 0x0000b040 , 0x02010301 },
+ { 0x0000b044 , 0x02010302 },
+ { 0x0000b048 , 0x02000500 },
+ { 0x0000b04c , 0x02010400 },
+ { 0x0000b050 , 0x02020300 },
+ { 0x0000b054 , 0x02020301 },
+ { 0x0000b058 , 0x02020302 },
+ { 0x0000b05c , 0x02020303 },
+ { 0x0000b060 , 0x02020400 },
+ { 0x0000b064 , 0x02030300 },
+ { 0x0000b068 , 0x02030301 },
+ { 0x0000b06c , 0x02030302 },
+ { 0x0000b070 , 0x02030303 },
+ { 0x0000b074 , 0x02030400 },
+ { 0x0000b078 , 0x02040300 },
+ { 0x0000b07c , 0x02040301 },
+ { 0x0000b080 , 0x02040302 },
+ { 0x0000b084 , 0x02040303 },
+ { 0x0000b088 , 0x02030500 },
+ { 0x0000b08c , 0x02040400 },
+ { 0x0000b090 , 0x02050203 },
+ { 0x0000b094 , 0x02050204 },
+ { 0x0000b098 , 0x02050205 },
+ { 0x0000b09c , 0x02040500 },
+ { 0x0000b0a0 , 0x02050301 },
+ { 0x0000b0a4 , 0x02050302 },
+ { 0x0000b0a8 , 0x02050303 },
+ { 0x0000b0ac , 0x02050400 },
+ { 0x0000b0b0 , 0x02050401 },
+ { 0x0000b0b4 , 0x02050402 },
+ { 0x0000b0b8 , 0x02050403 },
+ { 0x0000b0bc , 0x02050500 },
+ { 0x0000b0c0 , 0x02050501 },
+ { 0x0000b0c4 , 0x02050502 },
+ { 0x0000b0c8 , 0x02050503 },
+ { 0x0000b0cc , 0x02050504 },
+ { 0x0000b0d0 , 0x02050600 },
+ { 0x0000b0d4 , 0x02050601 },
+ { 0x0000b0d8 , 0x02050602 },
+ { 0x0000b0dc , 0x02050603 },
+ { 0x0000b0e0 , 0x02050604 },
+ { 0x0000b0e4 , 0x02050700 },
+ { 0x0000b0e8 , 0x02050701 },
+ { 0x0000b0ec , 0x02050702 },
+ { 0x0000b0f0 , 0x02050703 },
+ { 0x0000b0f4 , 0x02050704 },
+ { 0x0000b0f8 , 0x02050705 },
+ { 0x0000b0fc , 0x02050708 },
+ { 0x0000b100 , 0x02050709 },
+ { 0x0000b104 , 0x0205070a },
+ { 0x0000b108 , 0x0205070b },
+ { 0x0000b10c , 0x0205070c },
+ { 0x0000b110 , 0x0205070d },
+ { 0x0000b114 , 0x02050710 },
+ { 0x0000b118 , 0x02050711 },
+ { 0x0000b11c , 0x02050712 },
+ { 0x0000b120 , 0x02050713 },
+ { 0x0000b124 , 0x02050714 },
+ { 0x0000b128 , 0x02050715 },
+ { 0x0000b12c , 0x02050730 },
+ { 0x0000b130 , 0x02050731 },
+ { 0x0000b134 , 0x02050732 },
+ { 0x0000b138 , 0x02050733 },
+ { 0x0000b13c , 0x02050734 },
+ { 0x0000b140 , 0x02050735 },
+ { 0x0000b144 , 0x02050750 },
+ { 0x0000b148 , 0x02050751 },
+ { 0x0000b14c , 0x02050752 },
+ { 0x0000b150 , 0x02050753 },
+ { 0x0000b154 , 0x02050754 },
+ { 0x0000b158 , 0x02050755 },
+ { 0x0000b15c , 0x02050770 },
+ { 0x0000b160 , 0x02050771 },
+ { 0x0000b164 , 0x02050772 },
+ { 0x0000b168 , 0x02050773 },
+ { 0x0000b16c , 0x02050774 },
+ { 0x0000b170 , 0x02050775 },
+ { 0x0000b174 , 0x00000776 },
+ { 0x0000b178 , 0x00000776 },
+ { 0x0000b17c , 0x00000776 },
+ { 0x0000b180 , 0x00000776 },
+ { 0x0000b184 , 0x00000776 },
+ { 0x0000b188 , 0x00000776 },
+ { 0x0000b18c , 0x00000776 },
+ { 0x0000b190 , 0x00000776 },
+ { 0x0000b194 , 0x00000776 },
+ { 0x0000b198 , 0x00000776 },
+ { 0x0000b19c , 0x00000776 },
+ { 0x0000b1a0 , 0x00000776 },
+ { 0x0000b1a4 , 0x00000776 },
+ { 0x0000b1a8 , 0x00000776 },
+ { 0x0000b1ac , 0x00000776 },
+ { 0x0000b1b0 , 0x00000776 },
+ { 0x0000b1b4 , 0x00000776 },
+ { 0x0000b1b8 , 0x00000776 },
+ { 0x0000b1bc , 0x00000776 },
+ { 0x0000b1c0 , 0x00000776 },
+ { 0x0000b1c4 , 0x00000776 },
+ { 0x0000b1c8 , 0x00000776 },
+ { 0x0000b1cc , 0x00000776 },
+ { 0x0000b1d0 , 0x00000776 },
+ { 0x0000b1d4 , 0x00000776 },
+ { 0x0000b1d8 , 0x00000776 },
+ { 0x0000b1dc , 0x00000776 },
+ { 0x0000b1e0 , 0x00000776 },
+ { 0x0000b1e4 , 0x00000776 },
+ { 0x0000b1e8 , 0x00000776 },
+ { 0x0000b1ec , 0x00000776 },
+ { 0x0000b1f0 , 0x00000776 },
+ { 0x0000b1f4 , 0x00000776 },
+ { 0x0000b1f8 , 0x00000776 },
+ { 0x0000b1fc , 0x00000776 },
+};
+
+static const u_int32_t ar9200_merlin_2p0_radio_core_jupiter_1p0[][2] = {
+/* Addr common */
+ { 0x00007800 , 0x00040000 },
+ { 0x00007804 , 0xdb005012 },
+ { 0x00007808 , 0x04924914 },
+ { 0x0000780c , 0x21084210 },
+ { 0x00007810 , 0x6d801300 },
+ { 0x00007814 , 0x0019beff },
+ { 0x00007818 , 0x07e41000 },
+ { 0x0000781c , 0x00392000 },
+ { 0x00007820 , 0x92592480 },
+ { 0x00007824 , 0x00040000 },
+ { 0x00007828 , 0xdb005012 },
+ { 0x0000782c , 0x04924914 },
+ { 0x00007830 , 0x21084210 },
+ { 0x00007834 , 0x6d801300 },
+ { 0x00007838 , 0x0019beff },
+ { 0x0000783c , 0x07e40000 },
+ { 0x00007840 , 0x00392000 },
+ { 0x00007844 , 0x92592480 },
+ { 0x00007848 , 0x00100000 },
+ { 0x0000784c , 0x773f0567 },
+ { 0x00007850 , 0x54214514 },
+ { 0x00007854 , 0x12035828 },
+ { 0x00007858 , 0x92592692 },
+ { 0x0000785c , 0x00000000 },
+ { 0x00007860 , 0x56400000 },
+ { 0x00007864 , 0x0a8e370e },
+ { 0x00007868 , 0xc0102850 },
+ { 0x0000786c , 0x812d4000 },
+ { 0x00007870 , 0x807ec400 },
+ { 0x00007874 , 0x001b6db0 },
+ { 0x00007878 , 0x00376b63 },
+ { 0x0000787c , 0x06db6db6 },
+ { 0x00007880 , 0x006d8000 },
+ { 0x00007884 , 0xffeffffe },
+ { 0x00007888 , 0xffeffffe },
+ { 0x0000788c , 0x00010000 },
+ { 0x00007890 , 0x02060aeb },
+ { 0x00007894 , 0x5a108000 },
+};
+
+static const u_int32_t ar9300_jupiter_1p0_baseband_postamble_emulation[][5] = {
+/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+ { 0x00009e3c , 0xcf946221 , 0xcf946221 , 0xcf946221 , 0xcf946221 },
+ { 0x00009e44 , 0x005c0000 , 0x005c0000 , 0x005c0000 , 0x005c0000 },
+ { 0x0000a258 , 0x02020200 , 0x02020200 , 0x02020200 , 0x02020200 },
+ { 0x0000a25c , 0x00000e0e , 0x00000e0e , 0x00000e0e , 0x00000e0e },
+ { 0x0000a28c , 0x00011111 , 0x00011111 , 0x00011111 , 0x00011111 },
+ { 0x0000a2c4 , 0x00148d18 , 0x00148d18 , 0x00148d20 , 0x00148d20 },
+ { 0x0000a2d8 , 0xf999a800 , 0xf999a800 , 0xf999a80c , 0xf999a80c },
+ { 0x0000a50c , 0x0000c00a , 0x0000c00a , 0x0000c00a , 0x0000c00a },
+ { 0x0000a538 , 0x00038e8c , 0x00038e8c , 0x00038e8c , 0x00038e8c },
+ { 0x0000a53c , 0x0003cecc , 0x0003cecc , 0x0003cecc , 0x0003cecc },
+ { 0x0000a540 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 , 0x00040ed4 },
+ { 0x0000a544 , 0x00044edc , 0x00044edc , 0x00044edc , 0x00044edc },
+ { 0x0000a548 , 0x00048ede , 0x00048ede , 0x00048ede , 0x00048ede },
+ { 0x0000a54c , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e , 0x0004cf1e },
+ { 0x0000a550 , 0x00050f5e , 0x00050f5e , 0x00050f5e , 0x00050f5e },
+ { 0x0000a554 , 0x00054f9e , 0x00054f9e , 0x00054f9e , 0x00054f9e },
+ { 0x0000ae18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
+};
+
+static const u_int32_t ar9300_pcie_phy_pll_on_clkreq_disable_L1_jupiter_1p0[][2] = {
+/* Addr allmodes */
+ { 0x00018c00 , 0x10012e5e },
+ { 0x00018c04 , 0x000801d8 },
+ { 0x00018c08 , 0x0000580c },
+};
+
+static const u_int32_t ar9300_common_rx_gain_table_jupiter_1p0[][2] = {
+/* Addr allmodes */
+ { 0x0000a000 , 0x00010000 },
+ { 0x0000a004 , 0x00030002 },
+ { 0x0000a008 , 0x00050004 },
+ { 0x0000a00c , 0x00810080 },
+ { 0x0000a010 , 0x00830082 },
+ { 0x0000a014 , 0x01810180 },
+ { 0x0000a018 , 0x01830182 },
+ { 0x0000a01c , 0x01850184 },
+ { 0x0000a020 , 0x01890188 },
+ { 0x0000a024 , 0x018b018a },
+ { 0x0000a028 , 0x018d018c },
+ { 0x0000a02c , 0x01910190 },
+ { 0x0000a030 , 0x01930192 },
+ { 0x0000a034 , 0x01950194 },
+ { 0x0000a038 , 0x038a0196 },
+ { 0x0000a03c , 0x038c038b },
+ { 0x0000a040 , 0x0390038d },
+ { 0x0000a044 , 0x03920391 },
+ { 0x0000a048 , 0x03940393 },
+ { 0x0000a04c , 0x03960395 },
+ { 0x0000a050 , 0x00000000 },
+ { 0x0000a054 , 0x00000000 },
+ { 0x0000a058 , 0x00000000 },
+ { 0x0000a05c , 0x00000000 },
+ { 0x0000a060 , 0x00000000 },
+ { 0x0000a064 , 0x00000000 },
+ { 0x0000a068 , 0x00000000 },
+ { 0x0000a06c , 0x00000000 },
+ { 0x0000a070 , 0x00000000 },
+ { 0x0000a074 , 0x00000000 },
+ { 0x0000a078 , 0x00000000 },
+ { 0x0000a07c , 0x00000000 },
+ { 0x0000a080 , 0x22222229 },
+ { 0x0000a084 , 0x1d1d1d1d },
+ { 0x0000a088 , 0x1d1d1d1d },
+ { 0x0000a08c , 0x1d1d1d1d },
+ { 0x0000a090 , 0x171d1d1d },
+ { 0x0000a094 , 0x11111717 },
+ { 0x0000a098 , 0x00030311 },
+ { 0x0000a09c , 0x00000000 },
+ { 0x0000a0a0 , 0x00000000 },
+ { 0x0000a0a4 , 0x00000000 },
+ { 0x0000a0a8 , 0x00000000 },
+ { 0x0000a0ac , 0x00000000 },
+ { 0x0000a0b0 , 0x00000000 },
+ { 0x0000a0b4 , 0x00000000 },
+ { 0x0000a0b8 , 0x00000000 },
+ { 0x0000a0bc , 0x00000000 },
+ { 0x0000a0c0 , 0x001f0000 },
+ { 0x0000a0c4 , 0x01000101 },
+ { 0x0000a0c8 , 0x011e011f },
+ { 0x0000a0cc , 0x011c011d },
+ { 0x0000a0d0 , 0x02030204 },
+ { 0x0000a0d4 , 0x02010202 },
+ { 0x0000a0d8 , 0x021f0200 },
+ { 0x0000a0dc , 0x0302021e },
+ { 0x0000a0e0 , 0x03000301 },
+ { 0x0000a0e4 , 0x031e031f },
+ { 0x0000a0e8 , 0x0402031d },
+ { 0x0000a0ec , 0x04000401 },
+ { 0x0000a0f0 , 0x041e041f },
+ { 0x0000a0f4 , 0x0502041d },
+ { 0x0000a0f8 , 0x05000501 },
+ { 0x0000a0fc , 0x051e051f },
+ { 0x0000a100 , 0x06010602 },
+ { 0x0000a104 , 0x061f0600 },
+ { 0x0000a108 , 0x061d061e },
+ { 0x0000a10c , 0x07020703 },
+ { 0x0000a110 , 0x07000701 },
+ { 0x0000a114 , 0x00000000 },
+ { 0x0000a118 , 0x00000000 },
+ { 0x0000a11c , 0x00000000 },
+ { 0x0000a120 , 0x00000000 },
+ { 0x0000a124 , 0x00000000 },
+ { 0x0000a128 , 0x00000000 },
+ { 0x0000a12c , 0x00000000 },
+ { 0x0000a130 , 0x00000000 },
+ { 0x0000a134 , 0x00000000 },
+ { 0x0000a138 , 0x00000000 },
+ { 0x0000a13c , 0x00000000 },
+ { 0x0000a140 , 0x001f0000 },
+ { 0x0000a144 , 0x01000101 },
+ { 0x0000a148 , 0x011e011f },
+ { 0x0000a14c , 0x011c011d },
+ { 0x0000a150 , 0x02030204 },
+ { 0x0000a154 , 0x02010202 },
+ { 0x0000a158 , 0x021f0200 },
+ { 0x0000a15c , 0x0302021e },
+ { 0x0000a160 , 0x03000301 },
+ { 0x0000a164 , 0x031e031f },
+ { 0x0000a168 , 0x0402031d },
+ { 0x0000a16c , 0x04000401 },
+ { 0x0000a170 , 0x041e041f },
+ { 0x0000a174 , 0x0502041d },
+ { 0x0000a178 , 0x05000501 },
+ { 0x0000a17c , 0x051e051f },
+ { 0x0000a180 , 0x06010602 },
+ { 0x0000a184 , 0x061f0600 },
+ { 0x0000a188 , 0x061d061e },
+ { 0x0000a18c , 0x07020703 },
+ { 0x0000a190 , 0x07000701 },
+ { 0x0000a194 , 0x00000000 },
+ { 0x0000a198 , 0x00000000 },
+ { 0x0000a19c , 0x00000000 },
+ { 0x0000a1a0 , 0x00000000 },
+ { 0x0000a1a4 , 0x00000000 },
+ { 0x0000a1a8 , 0x00000000 },
+ { 0x0000a1ac , 0x00000000 },
+ { 0x0000a1b0 , 0x00000000 },
+ { 0x0000a1b4 , 0x00000000 },
+ { 0x0000a1b8 , 0x00000000 },
+ { 0x0000a1bc , 0x00000000 },
+ { 0x0000a1c0 , 0x00000000 },
+ { 0x0000a1c4 , 0x00000000 },
+ { 0x0000a1c8 , 0x00000000 },
+ { 0x0000a1cc , 0x00000000 },
+ { 0x0000a1d0 , 0x00000000 },
+ { 0x0000a1d4 , 0x00000000 },
+ { 0x0000a1d8 , 0x00000000 },
+ { 0x0000a1dc , 0x00000000 },
+ { 0x0000a1e0 , 0x00000000 },
+ { 0x0000a1e4 , 0x00000000 },
+ { 0x0000a1e8 , 0x00000000 },
+ { 0x0000a1ec , 0x00000000 },
+ { 0x0000a1f0 , 0x00000396 },
+ { 0x0000a1f4 , 0x00000396 },
+ { 0x0000a1f8 , 0x00000396 },
+ { 0x0000a1fc , 0x00000196 },
+ { 0x0000b000 , 0x00010000 },
+ { 0x0000b004 , 0x00030002 },
+ { 0x0000b008 , 0x00050004 },
+ { 0x0000b00c , 0x00810080 },
+ { 0x0000b010 , 0x00830082 },
+ { 0x0000b014 , 0x01810180 },
+ { 0x0000b018 , 0x01830182 },
+ { 0x0000b01c , 0x01850184 },
+ { 0x0000b020 , 0x02810280 },
+ { 0x0000b024 , 0x02830282 },
+ { 0x0000b028 , 0x02850284 },
+ { 0x0000b02c , 0x02890288 },
+ { 0x0000b030 , 0x028b028a },
+ { 0x0000b034 , 0x0388028c },
+ { 0x0000b038 , 0x038a0389 },
+ { 0x0000b03c , 0x038c038b },
+ { 0x0000b040 , 0x0390038d },
+ { 0x0000b044 , 0x03920391 },
+ { 0x0000b048 , 0x03940393 },
+ { 0x0000b04c , 0x03960395 },
+ { 0x0000b050 , 0x00000000 },
+ { 0x0000b054 , 0x00000000 },
+ { 0x0000b058 , 0x00000000 },
+ { 0x0000b05c , 0x00000000 },
+ { 0x0000b060 , 0x00000000 },
+ { 0x0000b064 , 0x00000000 },
+ { 0x0000b068 , 0x00000000 },
+ { 0x0000b06c , 0x00000000 },
+ { 0x0000b070 , 0x00000000 },
+ { 0x0000b074 , 0x00000000 },