| /* |
| * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| /* |
| * Copyright (c) 2008, Intel Corporation |
| * All rights reserved. |
| */ |
| |
| /* |
| * Sun elects to have this file available under and governed by the BSD |
| * license (see below for full license text). However, the following |
| * notice accompanied the original version of this file: |
| */ |
| |
| /* |
| * This file is provided under a dual BSD/GPLv2 license. When using or |
| * redistributing this file, you may do so under either license. |
| * |
| * GPL LICENSE SUMMARY |
| * |
| * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU Geeral Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
| * USA |
| * |
| * The full GNU General Public License is included in this distribution |
| * in the file called LICENSE.GPL. |
| * |
| * Contact Information: |
| * James P. Ketrenos <ipw2100-admin@linux.intel.com> |
| * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
| * |
| * BSD LICENSE |
| * |
| * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Intel Corporation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * 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 MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * 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 DAMAGE. |
| */ |
| |
| |
| #ifndef _IWK_CALIBRATION_H_ |
| #define _IWK_CALIBRATION_H_ |
| |
| /* |
| * Most Tx and Rx calibration is done by uCode during the initialization |
| * phase of uCode boot. Driver must calibrate only: |
| * |
| * 1) Tx power (depends on temperature) |
| * 2) Receiver gain balance (and detect disconnected antennas) |
| * 3) Receiver sensitivity (to optimize signal detection) |
| */ |
| |
| /* START TEMPERATURE */ |
| |
| /* |
| * 4965 temperature calculation. |
| * |
| * The driver must calculate the device temperature before calculating |
| * a txpower setting (amplifier gain is temperature dependent). The |
| * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration |
| * values used for the life of the driver, and one of which (R4) is the |
| * real-time temperature indicator. |
| * |
| * uCode provides all 4 values to the driver via the "initialize alive" |
| * notification (see struct iwk_init_alive_resp). After the runtime uCode |
| * image loads, uCode updates the R4 value via statistics notifications |
| * (see STATISTICS_NOTIFICATION), which occur after each received beacon |
| * when associated, or can be requested via REPLY_STATISTICS_CMD. |
| * |
| * NOTE: uCode provides the R4 value as a 23-bit signed value. Driver |
| * must sign-extend to 32 bits before applying formula below. |
| * |
| * Formula: |
| * |
| * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8 |
| * |
| * NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is |
| * an additional correction, which should be centered around 0 degrees |
| * Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for |
| * centering the 97/100 correction around 0 degrees K. |
| * |
| * Add 273 to Kelvin value to find degrees Celsius, for comparing current |
| * temperature with factory-measured temperatures when calculating txpower |
| * settings. |
| */ |
| |
| /* END TEMPERATURE */ |
| |
| /* START TXPOWER */ |
| |
| /* |
| * 4965 txpower calculations rely on information from three sources: |
| * |
| * 1) EEPROM |
| * 2) "initialize" alive notification |
| * 3) statistics notifications |
| * |
| * EEPROM data consists of: |
| * |
| * 1) Regulatory information (max txpower and channel usage flags) is provided |
| * separately for each channel that can possibly supported by 4965. |
| * 40 MHz wide (.11n fat) channels are listed separately from 20 MHz |
| * (legacy) channels. |
| * |
| * See struct iwk_eep_channel for format, and struct iwk_eep for |
| * locations in EEPROM. |
| * |
| * 2) Factory txpower calibration information is provided separately for |
| * sub-bands of contiguous channels. 2.4GHz has just one sub-band, |
| * but 5 GHz has several sub-bands. |
| * |
| * In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided. |
| * |
| * See struct iwk_eep_calib_info (and the tree of structures contained |
| * within it) for format, and struct iwk_eep for locations in EEPROM. |
| * |
| * "Initialization alive" notification (see struct iwk_init_alive_resp) |
| * consists of: |
| * |
| * 1) Temperature calculation parameters. |
| * |
| * 2) Power supply voltage measurement. |
| * |
| * 3) Tx gain compensation to balance 2 transmitters for MIMO use. |
| * |
| * Statistics notifications deliver: |
| * |
| * 1) Current values for temperature param R4. |
| */ |
| |
| /* |
| * To calculate a txpower setting for a given desired target txpower, channel, |
| * modulation bit rate, and transmitter chain (4965 has 2 transmitters to |
| * support MIMO and transmit diversity), driver must do the following: |
| * |
| * 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel. |
| * Do not exceed regulatory limit; reduce target txpower if necessary. |
| * |
| * If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), |
| * 2 transmitters will be used simultaneously; driver must reduce the |
| * regulatory limit by 3 dB (half-power) for each transmitter, so the |
| * combined total output of the 2 transmitters is within regulatory limits. |
| * |
| * |
| * 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by |
| * backoff for this bit rate*. Do not exceed (saturation - backoff[rate]); |
| * reduce target txpower if necessary. |
| * |
| * Backoff values below are in 1/2 dB units (equivalent to steps in |
| * txpower gain tables): |
| * |
| * OFDM 6 - 36 MBit: 10 steps (5 dB) |
| * OFDM 48 MBit: 15 steps (7.5 dB) |
| * OFDM 54 MBit: 17 steps (8.5 dB) |
| * OFDM 60 MBit: 20 steps (10 dB) |
| * CCK all rates: 10 steps (5 dB) |
| * |
| * Backoff values apply to saturation txpower on a per-transmitter basis; |
| * when using MIMO (2 transmitters), each transmitter uses the same |
| * saturation level provided in EEPROM, and the same backoff values; |
| * no reduction (such as with regulatory txpower limits) is required. |
| * |
| * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel |
| * widths and 40 Mhz (.11n fat) channel widths; there is no separate |
| * factory measurement for fat channels. |
| * |
| * The result of this step is the final target txpower. The rest of |
| * the steps figure out the proper settings for the device. |
| * |
| * |
| * 3) Determine (EEPROM) calibration subband for the target channel, by |
| * comparing against first and last channels in each subband |
| * (see struct iwk_eep_calib_subband_info). |
| * |
| * |
| * 4) Linearly interpolate (EEPROM) factory calibration measurement sets, |
| * referencing the 2 factory-measured (sample) channels within the subband. |
| * |
| * Interpolation is based on difference between target channel's frequency |
| * and the sample channels' frequencies. Since channel numbers are based |
| * on frequency (5 MHz between each channel number), this is equivalent |
| * to interpolating based on channel number differences. |
| * |
| * Note that the sample channels may or may not be the channels at the |
| * edges of the subband. The target channel may be "outside" of the |
| * span of the sampled channels. |
| * |
| * Driver may choose the pair (for 2 Tx chains) of measurements (see |
| * struct iwk_eep_calib_channel_info) for which the actual measured |
| * txpower comes closest to the desired txpower. Usually, though, |
| * the middle set of measurements is closest to the regulatory limits, |
| * and is therefore a good choice for all txpower calculations. |
| * |
| * Driver should interpolate both members of the chosen measurement pair, |
| * i.e. for both Tx chains (radio transmitters), unless the driver knows |
| * that only one of the chains will be used (e.g. only one tx antenna |
| * connected, but this should be unusual). |
| * |
| * Driver should interpolate factory values for temperature, gain table |
| * index, and actual power. The power amplifier detector values are |
| * not used by the driver. |
| * |
| * If the target channel happens to be one of the sample channels, the |
| * results should agree with the sample channel's measurements! |
| * |
| * |
| * 5) Find difference between desired txpower and (interpolated) |
| * factory-measured txpower. Using (interpolated) factory gain table index |
| * as a starting point, adjust this index lower to increase txpower, |
| * or higher to decrease txpower, until the target txpower is reached. |
| * Each step in the gain table is 1/2 dB. |
| * |
| * For example, if factory measured txpower is 16 dBm, and target txpower |
| * is 13 dBm, add 6 steps to the factory gain index to reduce txpower |
| * by 3 dB. |
| * |
| * |
| * 6) Find difference between current device temperature and (interpolated) |
| * factory-measured temperature for sub-band. Factory values are in |
| * degrees Celsius. To calculate current temperature, see comments for |
| * "4965 temperature calculation". |
| * |
| * If current temperature is higher than factory temperature, driver must |
| * increase gain (lower gain table index), and vice versa. |
| * |
| * Temperature affects gain differently for different channels: |
| * |
| * 2.4 GHz all channels: 3.5 degrees per half-dB step |
| * 5 GHz channels 34-43: 4.5 degrees per half-dB step |
| * 5 GHz channels >= 44: 4.0 degrees per half-dB step |
| * |
| * NOTE: Temperature can increase rapidly when transmitting, especially |
| * with heavy traffic at high txpowers. Driver should update |
| * temperature calculations often under these conditions to |
| * maintain strong txpower in the face of rising temperature. |
| * |
| * |
| * 7) Find difference between current power supply voltage indicator |
| * (from "initialize alive") and factory-measured power supply voltage |
| * indicator (EEPROM). |
| * |
| * If the current voltage is higher (indicator is lower) than factory |
| * voltage, gain should be reduced (gain table index increased) by: |
| * |
| * (eeprom - current) / 7 |
| * |
| * If the current voltage is lower (indicator is higher) than factory |
| * voltage, gain should be increased (gain table index decreased) by: |
| * |
| * 2 * (current - eeprom) / 7 |
| * |
| * If number of index steps in either direction turns out to be > 2, |
| * something is wrong ... just use 0. |
| * |
| * NOTE: Voltage compensation is independent of band/channel. |
| * |
| * NOTE: "Initialize" uCode measures current voltage, which is assumed |
| * to be constant after this initial measurement. Voltage |
| * compensation for txpower (number of steps in gain table) |
| * may be calculated once and used until the next uCode bootload. |
| * |
| * |
| * 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), |
| * adjust txpower for each transmitter chain, so txpower is balanced |
| * between the two chains. There are 5 pairs of tx_atten[group][chain] |
| * values in "initialize alive", one pair for each of 5 channel ranges: |
| * |
| * Group 0: 5 GHz channel 34-43 |
| * Group 1: 5 GHz channel 44-70 |
| * Group 2: 5 GHz channel 71-124 |
| * Group 3: 5 GHz channel 125-200 |
| * Group 4: 2.4 GHz all channels |
| * |
| * Add the tx_atten[group][chain] value to the index for the target chain. |
| * The values are signed, but are in pairs of 0 and a non-negative number, |
| * so as to reduce gain (if necessary) of the "hotter" channel. This |
| * avoids any need to double-check for regulatory compliance after |
| * this step. |
| * |
| * |
| * 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation |
| * value to the index: |
| * |
| * Hardware rev B: 9 steps (4.5 dB) |
| * Hardware rev C: 5 steps (2.5 dB) |
| * |
| * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, |
| * bits [3:2], 1 = B, 2 = C. |
| * |
| * NOTE: This compensation is in addition to any saturation backoff that |
| * might have been applied in an earlier step. |
| * |
| * |
| * 10) Select the gain table, based on band (2.4 vs 5 GHz). |
| * |
| * Limit the adjusted index to stay within the table! |
| * |
| * |
| * 11) Read gain table entries for DSP and radio gain, place into appropriate |
| * location(s) in command. |
| */ |
| |
| /* Temperature calibration offset is 3% 0C in Kelvin */ |
| #define TEMPERATURE_CALIB_KELVIN_OFFSET 8 |
| #define TEMPERATURE_CALIB_A_VAL 259 |
| |
| #define KELVIN_TO_CELSIUS(x) ((x)-273) |
| #define CELSIUS_TO_KELVIN(x) ((x)+273) |
| |
| /* First and last channels of all groups */ |
| #define CALIB_IWK_TX_ATTEN_GR1_FCH 34 |
| #define CALIB_IWK_TX_ATTEN_GR1_LCH 43 |
| #define CALIB_IWK_TX_ATTEN_GR2_FCH 44 |
| #define CALIB_IWK_TX_ATTEN_GR2_LCH 70 |
| #define CALIB_IWK_TX_ATTEN_GR3_FCH 71 |
| #define CALIB_IWK_TX_ATTEN_GR3_LCH 124 |
| #define CALIB_IWK_TX_ATTEN_GR4_FCH 125 |
| #define CALIB_IWK_TX_ATTEN_GR4_LCH 200 |
| #define CALIB_IWK_TX_ATTEN_GR5_FCH 1 |
| #define CALIB_IWK_TX_ATTEN_GR5_LCH 20 |
| |
| /* Limit range of txpower output target to be between these values */ |
| #define IWK_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ |
| #define IWK_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ |
| |
| #define TX_POWER_IWK_ILLEGAL_VOLTAGE (-10000) |
| |
| /* |
| * 4965 power supply voltage compensation |
| */ |
| #define TX_POWER_IWK_VOLTAGE_CODES_PER_03V (7) |
| |
| /* Limit range of calculated temperature to be between these Kelvin values */ |
| #define IWK_TX_POWER_TEMPERATURE_MIN (263) |
| #define IWK_TX_POWER_TEMPERATURE_MAX (410) |
| |
| union iwk_tx_power_dual_stream { |
| struct { |
| uint8_t radio_tx_gain[2]; |
| uint8_t dsp_predis_atten[2]; |
| } s; |
| uint32_t dw; |
| }; |
| |
| #define POWER_TABLE_NUM_ENTRIES (33) |
| #define POWER_TABLE_CCK_ENTRY (32) |
| |
| /* |
| * When MIMO is used (2 transmitters operating simultaneously), driver should |
| * limit each transmitter to deliver a max of 3 dB below the regulatory limit |
| * for the device. That is, half power for each transmitter, so total power |
| * is within regulatory limits. |
| * |
| * The value "6" represents number of steps in gain table to reduce power. |
| * Each step is 1/2 dB. |
| */ |
| #define IWK_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) |
| |
| /* |
| * CCK gain compensation. |
| * |
| * When calculating txpowers for CCK, after making sure that the target power |
| * is within regulatory and saturation limits, driver must additionally |
| * back off gain by adding these values to the gain table index. |
| */ |
| #define IWK_TX_POWER_CCK_COMPENSATION_C_STEP (5) |
| |
| /* |
| * Gain tables. |
| * |
| * The following tables contain pair of values for setting txpower, i.e. |
| * gain settings for the output of the device's digital signal processor (DSP), |
| * and for the analog gain structure of the transmitter. |
| * |
| * Each entry in the gain tables represents a step of 1/2 dB. Note that these |
| * are *relative* steps, not indications of absolute output power. Output |
| * power varies with temperature, voltage, and channel frequency, and also |
| * requires consideration of average power (to satisfy regulatory constraints), |
| * and peak power (to avoid distortion of the output signal). |
| * |
| * Each entry contains two values: |
| * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained |
| * linear value that multiplies the output of the digital signal processor, |
| * before being sent to the analog radio. |
| * 2) Radio gain. This sets the analog gain of the radio Tx path. |
| * It is a coarser setting, and behaves in a logarithmic (dB) fashion. |
| * |
| * EEPROM contains factory calibration data for txpower. This maps actual |
| * measured txpower levels to gain settings in the "well known" tables |
| * below ("well-known" means here that both factory calibration *and* the |
| * driver work with the same table). |
| * |
| * There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table |
| * has an extension (into negative indexes), in case the driver needs to |
| * boost power setting for high device temperatures (higher than would be |
| * present during factory calibration). A 5 Ghz EEPROM index of "40" |
| * corresponds to the 49th entry in the table used by the driver. |
| */ |
| #define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */ |
| #define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */ |
| |
| struct gain_entry { |
| uint8_t dsp; |
| uint8_t radio; |
| }; |
| |
| static const struct gain_entry gains_table[2][108] = { |
| /* 5.2GHz power gain index table */ |
| { |
| {123, 0x3F}, /* highest txpower */ |
| {117, 0x3F}, |
| {110, 0x3F}, |
| {104, 0x3F}, |
| {98, 0x3F}, |
| {110, 0x3E}, |
| {104, 0x3E}, |
| {98, 0x3E}, |
| {110, 0x3D}, |
| {104, 0x3D}, |
| {98, 0x3D}, |
| {110, 0x3C}, |
| {104, 0x3C}, |
| {98, 0x3C}, |
| {110, 0x3B}, |
| {104, 0x3B}, |
| {98, 0x3B}, |
| {110, 0x3A}, |
| {104, 0x3A}, |
| {98, 0x3A}, |
| {110, 0x39}, |
| {104, 0x39}, |
| {98, 0x39}, |
| {110, 0x38}, |
| {104, 0x38}, |
| {98, 0x38}, |
| {110, 0x37}, |
| {104, 0x37}, |
| {98, 0x37}, |
| {110, 0x36}, |
| {104, 0x36}, |
| {98, 0x36}, |
| {110, 0x35}, |
| {104, 0x35}, |
| {98, 0x35}, |
| {110, 0x34}, |
| {104, 0x34}, |
| {98, 0x34}, |
| {110, 0x33}, |
| {104, 0x33}, |
| {98, 0x33}, |
| {110, 0x32}, |
| {104, 0x32}, |
| {98, 0x32}, |
| {110, 0x31}, |
| {104, 0x31}, |
| {98, 0x31}, |
| {110, 0x30}, |
| {104, 0x30}, |
| {98, 0x30}, |
| {110, 0x25}, |
| {104, 0x25}, |
| {98, 0x25}, |
| {110, 0x24}, |
| {104, 0x24}, |
| {98, 0x24}, |
| {110, 0x23}, |
| {104, 0x23}, |
| {98, 0x23}, |
| {110, 0x22}, |
| {104, 0x18}, |
| {98, 0x18}, |
| {110, 0x17}, |
| {104, 0x17}, |
| {98, 0x17}, |
| {110, 0x16}, |
| {104, 0x16}, |
| {98, 0x16}, |
| {110, 0x15}, |
| {104, 0x15}, |
| {98, 0x15}, |
| {110, 0x14}, |
| {104, 0x14}, |
| {98, 0x14}, |
| {110, 0x13}, |
| {104, 0x13}, |
| {98, 0x13}, |
| {110, 0x12}, |
| {104, 0x08}, |
| {98, 0x08}, |
| {110, 0x07}, |
| {104, 0x07}, |
| {98, 0x07}, |
| {110, 0x06}, |
| {104, 0x06}, |
| {98, 0x06}, |
| {110, 0x05}, |
| {104, 0x05}, |
| {98, 0x05}, |
| {110, 0x04}, |
| {104, 0x04}, |
| {98, 0x04}, |
| {110, 0x03}, |
| {104, 0x03}, |
| {98, 0x03}, |
| {110, 0x02}, |
| {104, 0x02}, |
| {98, 0x02}, |
| {110, 0x01}, |
| {104, 0x01}, |
| {98, 0x01}, |
| {110, 0x00}, |
| {104, 0x00}, |
| {98, 0x00}, |
| {93, 0x00}, |
| {88, 0x00}, |
| {83, 0x00}, |
| {78, 0x00}, |
| }, |
| /* 2.4GHz power gain index table */ |
| { |
| {110, 0x3f}, /* highest txpower */ |
| {104, 0x3f}, |
| {98, 0x3f}, |
| {110, 0x3e}, |
| {104, 0x3e}, |
| {98, 0x3e}, |
| {110, 0x3d}, |
| {104, 0x3d}, |
| {98, 0x3d}, |
| {110, 0x3c}, |
| {104, 0x3c}, |
| {98, 0x3c}, |
| {110, 0x3b}, |
| {104, 0x3b}, |
| {98, 0x3b}, |
| {110, 0x3a}, |
| {104, 0x3a}, |
| {98, 0x3a}, |
| {110, 0x39}, |
| {104, 0x39}, |
| {98, 0x39}, |
| {110, 0x38}, |
| {104, 0x38}, |
| {98, 0x38}, |
| {110, 0x37}, |
| {104, 0x37}, |
| {98, 0x37}, |
| {110, 0x36}, |
| {104, 0x36}, |
| {98, 0x36}, |
| {110, 0x35}, |
| {104, 0x35}, |
| {98, 0x35}, |
| {110, 0x34}, |
| {104, 0x34}, |
| {98, 0x34}, |
| {110, 0x33}, |
| {104, 0x33}, |
| {98, 0x33}, |
| {110, 0x32}, |
| {104, 0x32}, |
| {98, 0x32}, |
| {110, 0x31}, |
| {104, 0x31}, |
| {98, 0x31}, |
| {110, 0x30}, |
| {104, 0x30}, |
| {98, 0x30}, |
| {110, 0x6}, |
| {104, 0x6}, |
| {98, 0x6}, |
| {110, 0x5}, |
| {104, 0x5}, |
| {98, 0x5}, |
| {110, 0x4}, |
| {104, 0x4}, |
| {98, 0x4}, |
| {110, 0x3}, |
| {104, 0x3}, |
| {98, 0x3}, |
| {110, 0x2}, |
| {104, 0x2}, |
| {98, 0x2}, |
| {110, 0x1}, |
| {104, 0x1}, |
| {98, 0x1}, |
| {110, 0x0}, |
| {104, 0x0}, |
| {98, 0x0}, |
| {97, 0}, |
| {96, 0}, |
| {95, 0}, |
| {94, 0}, |
| {93, 0}, |
| {92, 0}, |
| {91, 0}, |
| {90, 0}, |
| {89, 0}, |
| {88, 0}, |
| {87, 0}, |
| {86, 0}, |
| {85, 0}, |
| {84, 0}, |
| {83, 0}, |
| {82, 0}, |
| {81, 0}, |
| {80, 0}, |
| {79, 0}, |
| {78, 0}, |
| {77, 0}, |
| {76, 0}, |
| {75, 0}, |
| {74, 0}, |
| {73, 0}, |
| {72, 0}, |
| {71, 0}, |
| {70, 0}, |
| {69, 0}, |
| {68, 0}, |
| {67, 0}, |
| {66, 0}, |
| {65, 0}, |
| {64, 0}, |
| {63, 0}, |
| {62, 0}, |
| {61, 0}, |
| {60, 0}, |
| {59, 0}, |
| } |
| }; |
| |
| /* END TXPOWER */ |
| |
| struct statistics_div { |
| uint32_t tx_on_a; |
| uint32_t tx_on_b; |
| uint32_t exec_time; |
| uint32_t probe_time; |
| uint32_t reserved1; |
| uint32_t reserved2; |
| }; |
| |
| struct statistics_dbg { |
| uint32_t burst_check; |
| uint32_t burst_count; |
| uint32_t reserved[4]; |
| }; |
| |
| |
| struct statistics_general { |
| uint32_t temperature; |
| uint32_t temperature_m; |
| struct statistics_dbg dbg; |
| uint32_t sleep_time; |
| uint32_t slots_out; |
| uint32_t slots_idle; |
| uint32_t ttl_timestamp; |
| struct statistics_div div; |
| uint32_t rx_enable_counter; |
| uint32_t reserved1; |
| uint32_t reserved2; |
| uint32_t reserved3; |
| }; |
| |
| |
| struct statistics_tx_non_phy_agg { |
| uint32_t ba_timeout; |
| uint32_t ba_reschedule_frames; |
| uint32_t scd_query_agg_frame_cnt; |
| uint32_t scd_query_no_agg; |
| uint32_t scd_query_agg; |
| uint32_t scd_query_mismatch; |
| uint32_t frame_not_ready; |
| uint32_t underrun; |
| uint32_t bt_prio_kill; |
| uint32_t rx_ba_rsp_cnt; |
| uint32_t reserved2; |
| uint32_t reserved3; |
| }; |
| |
| |
| struct statistics_tx { |
| uint32_t preamble_cnt; |
| uint32_t rx_detected_cnt; |
| uint32_t bt_prio_defer_cnt; |
| uint32_t bt_prio_kill_cnt; |
| uint32_t few_bytes_cnt; |
| uint32_t cts_timeout; |
| uint32_t ack_timeout; |
| uint32_t expected_ack_cnt; |
| uint32_t actual_ack_cnt; |
| uint32_t dump_msdu_cnt; |
| uint32_t burst_abort_next_frame_mismatch_cnt; |
| uint32_t burst_abort_missing_next_frame_cnt; |
| uint32_t cts_timeout_collision; |
| uint32_t ack_or_ba_timeout_collision; |
| struct statistics_tx_non_phy_agg agg; |
| }; |
| |
| |
| struct statistics_rx_ht_phy { |
| uint32_t plcp_err; |
| uint32_t overrun_err; |
| uint32_t early_overrun_err; |
| uint32_t crc32_good; |
| uint32_t crc32_err; |
| uint32_t mh_format_err; |
| uint32_t agg_crc32_good; |
| uint32_t agg_mpdu_cnt; |
| uint32_t agg_cnt; |
| uint32_t reserved2; |
| }; |
| |
| struct statistics_rx_non_phy { |
| uint32_t bogus_cts; /* CTS received when not expecting CTS */ |
| uint32_t bogus_ack; /* ACK received when not expecting ACK */ |
| uint32_t non_bssid_frames; /* number of frames with BSSID that */ |
| /* doesn't belong to the STA BSSID */ |
| uint32_t filtered_frames; /* count frames that were dumped in the */ |
| /* filtering process */ |
| uint32_t non_channel_beacons; /* beacons with our bss id but not on */ |
| /* our serving channel */ |
| uint32_t channel_beacons; /* beacons with our bss id and in our */ |
| /* serving channel */ |
| uint32_t num_missed_bcon; /* number of missed beacons */ |
| uint32_t adc_rx_saturation_time; /* count in 0.8us units the time */ |
| /* the ADC was in saturation */ |
| uint32_t ina_detection_search_time; /* total time (in 0.8us) */ |
| /* searched for INA */ |
| uint32_t beacon_silence_rssi_a; /* RSSI silence after beacon frame */ |
| uint32_t beacon_silence_rssi_b; /* RSSI silence after beacon frame */ |
| uint32_t beacon_silence_rssi_c; /* RSSI silence after beacon frame */ |
| uint32_t interference_data_flag; /* flag for interference data */ |
| /* availability. 1 when data is */ |
| /* available. */ |
| uint32_t channel_load; /* counts RX Enable time */ |
| uint32_t dsp_false_alarms; /* DSP false alarm (both OFDM */ |
| /* and CCK) counter */ |
| uint32_t beacon_rssi_a; |
| uint32_t beacon_rssi_b; |
| uint32_t beacon_rssi_c; |
| uint32_t beacon_energy_a; |
| uint32_t beacon_energy_b; |
| uint32_t beacon_energy_c; |
| }; |
| |
| struct statistics_rx_phy { |
| uint32_t ina_cnt; |
| uint32_t fina_cnt; |
| uint32_t plcp_err; |
| uint32_t crc32_err; |
| uint32_t overrun_err; |
| uint32_t early_overrun_err; |
| uint32_t crc32_good; |
| uint32_t false_alarm_cnt; |
| uint32_t fina_sync_err_cnt; |
| uint32_t sfd_timeout; |
| uint32_t fina_timeout; |
| uint32_t unresponded_rts; |
| uint32_t rxe_frame_limit_overrun; |
| uint32_t sent_ack_cnt; |
| uint32_t sent_cts_cnt; |
| uint32_t sent_ba_rsp_cnt; |
| uint32_t dsp_self_kill; |
| uint32_t mh_format_err; |
| uint32_t re_acq_main_rssi_sum; |
| uint32_t reserved3; |
| }; |
| |
| struct statistics_rx { |
| struct statistics_rx_phy ofdm; |
| struct statistics_rx_phy cck; |
| struct statistics_rx_non_phy general; |
| struct statistics_rx_ht_phy ofdm_ht; |
| }; |
| |
| struct iwk_notif_statistics { |
| uint32_t flag; |
| struct statistics_rx rx; |
| struct statistics_tx tx; |
| struct statistics_general general; |
| }; |
| |
| /* START Receiver gain balance */ |
| |
| /* |
| * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) |
| * |
| * This command sets the relative gains of 4965's 3 radio receiver chains. |
| * |
| * After the first association, driver should accumulate signal and noise |
| * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20 |
| * beacons from the associated network (don't collect statistics that come |
| * in from scanning, or any other non-network source). |
| * |
| * DISCONNECTED ANTENNA: |
| * |
| * Driver should determine which antennas are actually connected, by comparing |
| * average beacon signal levels for the 3 Rx chains. Accumulate (add) the |
| * following values over 20 beacons, one accumulator for each of the chains |
| * a/b/c, from struct statistics_rx_non_phy: |
| * |
| * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB) |
| * |
| * Find the strongest signal from among a/b/c. Compare the other two to the |
| * strongest. If any signal is more than 15 dB (times 20, unless you |
| * divide the accumulated values by 20) below the strongest, the driver |
| * considers that antenna to be disconnected, and should not try to use that |
| * antenna/chain for Rx or Tx. If both A and B seem to be disconnected, |
| * driver should declare the stronger one as connected, and attempt to use it |
| * (A and B are the only 2 Tx chains!). |
| * |
| * |
| * RX BALANCE: |
| * |
| * Driver should balance the 3 receivers (but just the ones that are connected |
| * to antennas, see above) for gain, by comparing the average signal levels |
| * detected during the silence after each beacon (background noise). |
| * Accumulate (add) the following values over 20 beacons, one accumulator for |
| * each of the chains a/b/c, from struct statistics_rx_non_phy: |
| * |
| * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB) |
| * |
| * Find the weakest background noise level from among a/b/c. This Rx chain |
| * will be the reference, with 0 gain adjustment. Attenuate other channels by |
| * finding noise difference: |
| * |
| * (accum_noise[i] - accum_noise[reference]) / 30 |
| * |
| * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB. |
| * For use in diff_gain_[abc] fields of struct iwk_calibration_cmd, the |
| * driver should limit the difference results to a range of 0-3 (0-4.5 dB), |
| * and set bit 2 to indicate "reduce gain". The value for the reference |
| * (weakest) chain should be "0". |
| * |
| * diff_gain_[abc] bit fields: |
| * 2: (1) reduce gain, (0) increase gain |
| * 1-0: amount of gain, units of 1.5 dB |
| */ |
| |
| #define RX_CHAINS_NUM (3) |
| #define CHAIN_GAIN_DIFF_INIT_VAL (4) |
| |
| #define IWK_GAIN_DIFF_ALIVE (0) |
| #define IWK_GAIN_DIFF_ACCUMULATE (1) |
| #define IWK_GAIN_DIFF_CALIBRATED (2) |
| |
| #define INTERFERENCE_DATA_AVAILABLE (1) |
| #define BEACON_NUM_20 (20) |
| #define MAX_ALLOWED_DIFF (15) |
| |
| struct iwk_rx_gain_diff { |
| uint8_t state; |
| uint16_t beacon_count; |
| uint8_t gain_diff_send; |
| uint32_t beacon_stren_a; |
| uint32_t beacon_stren_b; |
| uint32_t beacon_stren_c; |
| uint32_t noise_stren_a; |
| uint32_t noise_stren_b; |
| uint32_t noise_stren_c; |
| uint8_t disconnect_chain[RX_CHAINS_NUM]; |
| uint8_t connected_chains; |
| uint8_t gain_diff_chain[RX_CHAINS_NUM]; |
| }; |
| |
| /* END Receiver gain balance */ |
| |
| /* START Receiver sensitivity */ |
| |
| /* |
| * SENSITIVITY_CMD = 0xa8 |
| * |
| * This command sets up the Rx signal detector for a sensitivity level that |
| * is high enough to lock onto all signals within the associated network, |
| * but low enough to ignore signals that are below a certain threshold, so as |
| * not to have too many "false alarms". False alarms are signals that the |
| * Rx DSP tries to lock onto, but then discards after determining that they |
| * are noise. |
| * |
| * The optimum number of false alarms is between 5 and 50 per 200 TUs |
| * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e. |
| * time listening, not transmitting). Driver must adjust sensitivity so that |
| * the ratio of actual false alarms to actual Rx time falls within this range. |
| * |
| * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each |
| * received beacon. These provide information to the driver to analyze the |
| * sensitivity. Don't analyze statistics that come in from scanning, or any |
| * other non-associated-network source. Pertinent statistics include: |
| * |
| * From "general" statistics (struct statistics_rx_non_phy): |
| * |
| * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level) |
| * Measure of energy of desired signal. Used for establishing a level |
| * below which the device does not detect signals. |
| * |
| * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB) |
| * Measure of background noise in silent period after beacon. |
| * |
| * channel_load |
| * uSecs of actual Rx time during beacon period (varies according to |
| * how much time was spent transmitting). |
| * |
| * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately: |
| * |
| * false_alarm_cnt |
| * Signal locks abandoned early (before phy-level header). |
| * |
| * plcp_err |
| * Signal locks abandoned late (during phy-level header). |
| * |
| * NOTE: Both false_alarm_cnt and plcp_err increment monotonically from |
| * beacon to beacon, i.e. each value is an accumulation of all errors |
| * before and including the latest beacon. Values will wrap around to 0 |
| * after counting up to 2^32 - 1. Driver must differentiate vs. |
| * previous beacon's values to determine # false alarms in the current |
| * beacon period. |
| * |
| * Total number of false alarms = false_alarms + plcp_errs |
| * |
| * For OFDM, adjust the following table entries in struct iwk_rx_sensitivity_cmd |
| * (notice that the start points for OFDM are at or close to settings for |
| * maximum sensitivity): |
| * |
| * START / MIN / MAX |
| * HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX 90 / 85 / 120 |
| * HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX 170 / 170 / 210 |
| * HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX 105 / 105 / 140 |
| * HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX 220 / 220 / 270 |
| * |
| * If actual rate of OFDM false alarms (+ plcp_errors) is too high |
| * (greater than 50 for each 204.8 msecs listening), reduce sensitivity |
| * by *adding* 1 to all 4 of the table entries above, up to the max for |
| * each entry. Conversely, if false alarm rate is too low (less than 5 |
| * for each 204.8 msecs listening), *subtract* 1 from each entry to |
| * increase sensitivity. |
| * |
| * For CCK sensitivity, keep track of the following: |
| * |
| * 1). 20-beacon history of maximum background noise, indicated by |
| * (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the |
| * 3 receivers. For any given beacon, the "silence reference" is |
| * the maximum of last 60 samples (20 beacons * 3 receivers). |
| * |
| * 2). 10-beacon history of strongest signal level, as indicated |
| * by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers, |
| * i.e. the strength of the signal through the best receiver at the |
| * moment. These measurements are "upside down", with lower values |
| * for stronger signals, so max energy will be *minimum* value. |
| * |
| * Then for any given beacon, the driver must determine the *weakest* |
| * of the strongest signals; this is the minimum level that needs to be |
| * successfully detected, when using the best receiver at the moment. |
| * "Max cck energy" is the maximum (higher value means lower energy!) |
| * of the last 10 minima. Once this is determined, driver must add |
| * a little margin by adding "6" to it. |
| * |
| * 3). Number of consecutive beacon periods with too few false alarms. |
| * Reset this to 0 at the first beacon period that falls within the |
| * "good" range (5 to 50 false alarms per 204.8 milliseconds rx). |
| * |
| * Then, adjust the following CCK table entries in struct iwk_rx_sensitivity_cmd |
| * (notice that the start points for CCK are at maximum sensitivity): |
| * |
| * START / MIN / MAX |
| * HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX 125 / 125 / 200 |
| * HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX 200 / 200 / 400 |
| * HD_MIN_ENERGY_CCK_DET_INDEX 100 / 0 / 100 |
| * |
| * If actual rate of CCK false alarms (+ plcp_errors) is too high |
| * (greater than 50 for each 204.8 msecs listening), method for reducing |
| * sensitivity is: |
| * |
| * 1) *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, |
| * up to max 400. |
| * |
| * 2) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160, |
| * sensitivity has been reduced a significant amount; bring it up to |
| * a moderate 161. Otherwise, *add* 3, up to max 200. |
| * |
| * 3) a) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160, |
| * sensitivity has been reduced only a moderate or small amount; |
| * *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX, |
| * down to min 0. Otherwise (if gain has been significantly reduced), |
| * don't change the HD_MIN_ENERGY_CCK_DET_INDEX value. |
| * |
| * b) Save a snapshot of the "silence reference". |
| * |
| * If actual rate of CCK false alarms (+ plcp_errors) is too low |
| * (less than 5 for each 204.8 msecs listening), method for increasing |
| * sensitivity is used only if: |
| * |
| * 1a) Previous beacon did not have too many false alarms |
| * 1b) AND difference between previous "silence reference" and current |
| * "silence reference" (prev - current) is 2 or more, |
| * OR 2) 100 or more consecutive beacon periods have had rate of |
| * less than 5 false alarms per 204.8 milliseconds rx time. |
| * |
| * Method for increasing sensitivity: |
| * |
| * 1) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX, |
| * down to min 125. |
| * |
| * 2) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, |
| * down to min 200. |
| * |
| * 3) *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100. |
| * |
| * If actual rate of CCK false alarms (+ plcp_errors) is within good range |
| * (between 5 and 50 for each 204.8 msecs listening): |
| * |
| * 1) Save a snapshot of the silence reference. |
| * |
| * 2) If previous beacon had too many CCK false alarms (+ plcp_errors), |
| * give some extra margin to energy threshold by *subtracting* 8 |
| * from value in HD_MIN_ENERGY_CCK_DET_INDEX. |
| * |
| * For all cases (too few, too many, good range), make sure that the CCK |
| * detection threshold (energy) is below the energy level for robust |
| * detection over the past 10 beacon periods, the "Max cck energy". |
| * Lower values mean higher energy; this means making sure that the value |
| * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". |
| * |
| * Driver should set the following entries to fixed values: |
| * |
| * HD_MIN_ENERGY_OFDM_DET_INDEX 100 |
| * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190 |
| * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390 |
| * HD_OFDM_ENERGY_TH_IN_INDEX 62 |
| */ |
| |
| #define IWK_SENSITIVITY_CALIB_ALLOW_MSK (1 << 0) |
| #define IWK_SENSITIVITY_OFDM_UPDATE_MSK (1 << 1) |
| #define IWK_SENSITIVITY_CCK_UPDATE_MSK (1 << 2) |
| |
| #define MIN_ENERGY_CCK_DET_IDX (0) |
| #define MIN_ENERGY_OFDM_DET_IDX (1) |
| #define AUTO_CORR32_X1_TH_ADD_MIN_IDX (2) |
| #define AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX (3) |
| #define AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX (4) |
| #define AUTO_CORR32_X4_TH_ADD_MIN_IDX (5) |
| #define AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX (6) |
| #define BARKER_CORR_TH_ADD_MIN_IDX (7) |
| #define BARKER_CORR_TH_ADD_MIN_MRC_IDX (8) |
| #define AUTO_CORR40_X4_TH_ADD_MIN_IDX (9) |
| #define PTAM_ENERGY_TH_IDX (10) |
| |
| #define IWK_GOOD_RANGE_FALSE_ALARM (0) |
| #define IWK_TOO_MANY_FALSE_ALARM (1) |
| #define IWK_TOO_FEW_FALSE_ALARM (2) |
| |
| #define IWK_SENSITIVITY_CONTROL_DEFAULT_TABLE (0) |
| #define IWK_SENSITIVITY_CONTROL_WORK_TABLE (1) |
| |
| struct iwk_rx_sensitivity_cmd { |
| uint16_t control; |
| uint16_t table[11]; |
| }; |
| |
| struct iwk_rx_sensitivity { |
| uint16_t auto_corr_ofdm_x4; |
| uint16_t auto_corr_mrc_ofdm_x4; |
| uint16_t auto_corr_ofdm_x1; |
| uint16_t auto_corr_mrc_ofdm_x1; |
| |
| uint16_t auto_corr_cck_x4; |
| uint16_t auto_corr_mrc_cck_x4; |
| uint16_t min_energy_det_cck; |
| |
| uint16_t flags; |
| |
| uint32_t last_bad_plcp_cnt_ofdm; |
| uint32_t last_false_alarm_cnt_ofdm; |
| uint32_t last_bad_plcp_cnt_cck; |
| uint32_t last_false_alarm_cnt_cck; |
| |
| uint32_t cck_curr_state; |
| uint32_t cck_prev_state; |
| uint32_t cck_beacon_min[10]; |
| uint32_t cck_beacon_idx; |
| uint8_t cck_noise_max[20]; |
| uint32_t cck_noise_ref; |
| uint32_t cck_noise_idx; |
| int32_t cck_noise_diff; |
| uint32_t cck_no_false_alarm_num; |
| }; |
| |
| /* END Receiver sensitivity */ |
| |
| #endif /* _IWK_CALIBRATION_H_ */ |