/*
* Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
* Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
* Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
* Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
*
* 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) KBUILD_MODNAME ": " 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)
{
int i;
u32 data;
for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
data = ath5k_hw_reg_read(ah, reg);
if (is_set && (data & flag))
break;
else if ((data & flag) == val)
break;
udelay(15);
}
return (i <= 0) ? -EAGAIN : 0;
}
/*************************\
* 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