/* * Copyright (c) 2004-2008 Reyk Floeter <[email protected]> * Copyright (c) 2006-2008 Nick Kossifidis <[email protected]> * Copyright (c) 2007-2008 Luis Rodriguez <[email protected]> * Copyright (c) 2007-2008 Pavel Roskin <[email protected]> * Copyright (c) 2007-2008 Jiri Slaby <[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. * */ /****************************\ Reset function and helpers \****************************/ #define pr_fmt(fmt) … #include <asm/unaligned.h> #include <linux/pci.h> /* To determine if a card is pci-e */ #include <linux/log2.h> #include <linux/platform_device.h> #include "ath5k.h" #include "reg.h" #include "debug.h" /** * DOC: Reset function and helpers * * Here we implement the main reset routine, used to bring the card * to a working state and ready to receive. We also handle routines * that don't fit on other places such as clock, sleep and power control */ /******************\ * Helper functions * \******************/ /** * ath5k_hw_register_timeout() - Poll a register for a flag/field change * @ah: The &struct ath5k_hw * @reg: The register to read * @flag: The flag/field to check on the register * @val: The field value we expect (if we check a field) * @is_set: Instead of checking if the flag got cleared, check if it got set * * Some registers contain flags that indicate that an operation is * running. We use this function to poll these registers and check * if these flags get cleared. We also use it to poll a register * field (containing multiple flags) until it gets a specific value. * * Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0 */ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set) { … } /*************************\ * Clock related functions * \*************************/ /** * ath5k_hw_htoclock() - Translate usec to hw clock units * @ah: The &struct ath5k_hw * @usec: value in microseconds * * Translate usecs to hw clock units based on the current * hw clock rate. * * Returns number of clock units */ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) { … } /** * ath5k_hw_clocktoh() - Translate hw clock units to usec * @ah: The &struct ath5k_hw * @clock: value in hw clock units * * Translate hw clock units to usecs based on the current * hw clock rate. * * Returns number of usecs */ unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) { … } /** * ath5k_hw_init_core_clock() - Initialize core clock * @ah: The &struct ath5k_hw * * Initialize core clock parameters (usec, usec32, latencies etc), * based on current bwmode and chipset properties. */ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) { … } /** * ath5k_hw_set_sleep_clock() - Setup sleep clock operation * @ah: The &struct ath5k_hw * @enable: Enable sleep clock operation (false to disable) * * If there is an external 32KHz crystal available, use it * as ref. clock instead of 32/40MHz clock and baseband clocks * to save power during sleep or restore normal 32/40MHz * operation. * * NOTE: When operating on 32KHz certain PHY registers (27 - 31, * 123 - 127) require delay on access. */ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) { … } /*********************\ * Reset/Sleep control * \*********************/ /** * ath5k_hw_nic_reset() - Reset the various chipset units * @ah: The &struct ath5k_hw * @val: Mask to indicate what units to reset * * To reset the various chipset units we need to write * the mask to AR5K_RESET_CTL and poll the register until * all flags are cleared. * * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) */ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) { … } /** * ath5k_hw_wisoc_reset() - Reset AHB chipset * @ah: The &struct ath5k_hw * @flags: Mask to indicate what units to reset * * Same as ath5k_hw_nic_reset but for AHB based devices * * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) */ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) { … } /** * ath5k_hw_set_power_mode() - Set power mode * @ah: The &struct ath5k_hw * @mode: One of enum ath5k_power_mode * @set_chip: Set to true to write sleep control register * @sleep_duration: How much time the device is allowed to sleep * when sleep logic is enabled (in 128 microsecond increments). * * This function is used to configure sleep policy and allowed * sleep modes. For more information check out the sleep control * register on reg.h and STA_ID1. * * Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid * mode is requested. */ static int ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration) { … } /** * ath5k_hw_on_hold() - Put device on hold * @ah: The &struct ath5k_hw * * Put MAC and Baseband on warm reset and keep that state * (don't clean sleep control register). After this MAC * and Baseband are disabled and a full reset is needed * to come back. This way we save as much power as possible * without putting the card on full sleep. * * Returns 0 on success or -EIO on error */ int ath5k_hw_on_hold(struct ath5k_hw *ah) { … } /** * ath5k_hw_nic_wakeup() - Force card out of sleep * @ah: The &struct ath5k_hw * @channel: The &struct ieee80211_channel * * Bring up MAC + PHY Chips and program PLL * NOTE: Channel is NULL for the initial wakeup. * * Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) { … } /**************************************\ * Post-initvals register modifications * \**************************************/ /** * ath5k_hw_tweak_initval_settings() - Tweak initial settings * @ah: The &struct ath5k_hw * @channel: The &struct ieee80211_channel * * Some settings are not handled on initvals, e.g. bwmode * settings, some phy settings, workarounds etc that in general * don't fit anywhere else or are too small to introduce a separate * function for each one. So we have this function to handle * them all during reset and complete card's initialization. */ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) { … } /** * ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM * @ah: The &struct ath5k_hw * @channel: The &struct ieee80211_channel * * Use settings stored on EEPROM to properly initialize the card * based on various infos and per-mode calibration data. */ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) { … } /*********************\ * Main reset function * \*********************/ /** * ath5k_hw_reset() - The main reset function * @ah: The &struct ath5k_hw * @op_mode: One of enum nl80211_iftype * @channel: The &struct ieee80211_channel * @fast: Enable fast channel switching * @skip_pcu: Skip pcu initialization * * This is the function we call each time we want to (re)initialize the * card and pass new settings to hw. We also call it when hw runs into * trouble to make it come back to a working state. * * Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO * on failure. */ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool fast, bool skip_pcu) { … }