/* * Copyright (c) 2004-2008 Reyk Floeter <[email protected]> * Copyright (c) 2006-2009 Nick Kossifidis <[email protected]> * Copyright (c) 2008-2009 Felix Fietkau <[email protected]> * * Permission to use, copy, modify, and 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. * */ /*************************************\ * EEPROM access functions and helpers * \*************************************/ #define pr_fmt(fmt) … #include <linux/slab.h> #include "ath5k.h" #include "reg.h" #include "debug.h" /******************\ * Helper functions * \******************/ /* * Translate binary channel representation in EEPROM to frequency */ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, unsigned int mode) { … } /*********\ * Parsers * \*********/ /* * Initialize eeprom & capabilities structs */ static int ath5k_eeprom_init_header(struct ath5k_hw *ah) { … } /* * Read antenna infos from eeprom */ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, unsigned int mode) { … } /* * Read supported modes and some mode-specific calibration data * from eeprom */ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, unsigned int mode) { … } /* Read mode-specific data (except power calibration data) */ static int ath5k_eeprom_init_modes(struct ath5k_hw *ah) { … } /* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff * frequency mask) */ static inline int ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, struct ath5k_chan_pcal_info *pc, unsigned int mode) { … } /* Read frequency piers for 802.11a */ static int ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) { … } /* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ static inline int ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) { … } /* * Read power calibration for RF5111 chips * * For RF5111 we have an XPD -eXternal Power Detector- curve * for each calibrated channel. Each curve has 0,5dB Power steps * on x axis and PCDAC steps (offsets) on y axis and looks like an * exponential function. To recreate the curve we read 11 points * here and interpolate later. */ /* Used to match PCDAC steps with power values on RF5111 chips * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC * steps that match with the power values we read from eeprom. On * older eeprom versions (< 3.2) these steps are equally spaced at * 10% of the pcdac curve -until the curve reaches its maximum- * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) * these 11 steps are spaced in a different way. This function returns * the pcdac steps based on eeprom version and curve min/max so that we * can have pcdac/pwr points. */ static inline void ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) { … } static int ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) { … } /* Convert RF5111 specific data to generic raw data * used by interpolation code */ static int ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, struct ath5k_chan_pcal_info *chinfo) { … } /* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) { … } /* * Read power calibration for RF5112 chips * * For RF5112 we have 4 XPD -eXternal Power Detector- curves * for each calibrated channel on 0, -6, -12 and -18dBm but we only * use the higher (3) and the lower (0) curves. Each curve has 0.5dB * power steps on x axis and PCDAC steps on y axis and looks like a * linear function. To recreate the curve and pass the power values * on hw, we read 4 points for xpd 0 (lower gain -> max power) * and 3 points for xpd 3 (higher gain -> lower power) here and * interpolate later. * * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. */ /* Convert RF5112 specific data to generic raw data * used by interpolation code */ static int ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, struct ath5k_chan_pcal_info *chinfo) { … } /* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) { … } /* * Read power calibration for RF2413 chips * * For RF2413 we have a Power to PDDAC table (Power Detector) * instead of a PCDAC and 4 pd gain curves for each calibrated channel. * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y * axis and looks like an exponential function like the RF5111 curve. * * To recreate the curves we read here the points and interpolate * later. Note that in most cases only 2 (higher and lower) curves are * used (like RF5112) but vendors have the opportunity to include all * 4 curves on eeprom. The final curve (higher power) has an extra * point for better accuracy like RF5112. */ /* For RF2413 power calibration data doesn't start on a fixed location and * if a mode is not supported, its section is missing -not zeroed-. * So we need to calculate the starting offset for each section by using * these two functions */ /* Return the size of each section based on the mode and the number of pd * gains available (maximum 4). */ static inline unsigned int ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) { … } /* Return the starting offset for a section based on the modes supported * and each section's size. */ static unsigned int ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) { … } /* Convert RF2413 specific data to generic raw data * used by interpolation code */ static int ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, struct ath5k_chan_pcal_info *chinfo) { … } /* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) { … } /* * Read per rate target power (this is the maximum tx power * supported by the card). This info is used when setting * tx power, no matter the channel. * * This also works for v5 EEPROMs. */ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) { … } /* * Read per channel calibration info from EEPROM * * This info is used to calibrate the baseband power table. Imagine * that for each channel there is a power curve that's hw specific * (depends on amplifier etc) and we try to "correct" this curve using * offsets we pass on to phy chip (baseband -> before amplifier) so that * it can use accurate power values when setting tx power (takes amplifier's * performance on each channel into account). * * EEPROM provides us with the offsets for some pre-calibrated channels * and we have to interpolate to create the full table for these channels and * also the table for any channel. */ static int ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) { … } /* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) { … } static int ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) { … } /***********************\ * Init/Detach functions * \***********************/ /* * Initialize eeprom data structure */ int ath5k_eeprom_init(struct ath5k_hw *ah) { … } void ath5k_eeprom_detach(struct ath5k_hw *ah) { … } int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { … }