162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
362306a36Sopenharmony_ci * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
462306a36Sopenharmony_ci * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any
762306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
862306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1162306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1262306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1362306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1462306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1562306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1662306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/**************\
2162306a36Sopenharmony_ci* Capabilities *
2262306a36Sopenharmony_ci\**************/
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "ath5k.h"
2562306a36Sopenharmony_ci#include "reg.h"
2662306a36Sopenharmony_ci#include "debug.h"
2762306a36Sopenharmony_ci#include "../regd.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Fill the capabilities struct
3162306a36Sopenharmony_ci * TODO: Merge this with EEPROM code when we are done with it
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ciint ath5k_hw_set_capabilities(struct ath5k_hw *ah)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	struct ath5k_capabilities *caps = &ah->ah_capabilities;
3662306a36Sopenharmony_ci	u16 ee_header;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* Capabilities stored in the EEPROM */
3962306a36Sopenharmony_ci	ee_header = caps->cap_eeprom.ee_header;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (ah->ah_version == AR5K_AR5210) {
4262306a36Sopenharmony_ci		/*
4362306a36Sopenharmony_ci		 * Set radio capabilities
4462306a36Sopenharmony_ci		 * (The AR5110 only supports the middle 5GHz band)
4562306a36Sopenharmony_ci		 */
4662306a36Sopenharmony_ci		caps->cap_range.range_5ghz_min = 5120;
4762306a36Sopenharmony_ci		caps->cap_range.range_5ghz_max = 5430;
4862306a36Sopenharmony_ci		caps->cap_range.range_2ghz_min = 0;
4962306a36Sopenharmony_ci		caps->cap_range.range_2ghz_max = 0;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci		/* Set supported modes */
5262306a36Sopenharmony_ci		__set_bit(AR5K_MODE_11A, caps->cap_mode);
5362306a36Sopenharmony_ci	} else {
5462306a36Sopenharmony_ci		/*
5562306a36Sopenharmony_ci		 * XXX The transceiver supports frequencies from 4920 to 6100MHz
5662306a36Sopenharmony_ci		 * XXX and from 2312 to 2732MHz. There are problems with the
5762306a36Sopenharmony_ci		 * XXX current ieee80211 implementation because the IEEE
5862306a36Sopenharmony_ci		 * XXX channel mapping does not support negative channel
5962306a36Sopenharmony_ci		 * XXX numbers (2312MHz is channel -19). Of course, this
6062306a36Sopenharmony_ci		 * XXX doesn't matter because these channels are out of the
6162306a36Sopenharmony_ci		 * XXX legal range.
6262306a36Sopenharmony_ci		 */
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		/*
6562306a36Sopenharmony_ci		 * Set radio capabilities
6662306a36Sopenharmony_ci		 */
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		if (AR5K_EEPROM_HDR_11A(ee_header)) {
6962306a36Sopenharmony_ci			if (ath_is_49ghz_allowed(caps->cap_eeprom.ee_regdomain))
7062306a36Sopenharmony_ci				caps->cap_range.range_5ghz_min = 4920;
7162306a36Sopenharmony_ci			else
7262306a36Sopenharmony_ci				caps->cap_range.range_5ghz_min = 5005;
7362306a36Sopenharmony_ci			caps->cap_range.range_5ghz_max = 6100;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci			/* Set supported modes */
7662306a36Sopenharmony_ci			__set_bit(AR5K_MODE_11A, caps->cap_mode);
7762306a36Sopenharmony_ci		}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
8062306a36Sopenharmony_ci		 * connected */
8162306a36Sopenharmony_ci		if (AR5K_EEPROM_HDR_11B(ee_header) ||
8262306a36Sopenharmony_ci		    (AR5K_EEPROM_HDR_11G(ee_header) &&
8362306a36Sopenharmony_ci		     ah->ah_version != AR5K_AR5211)) {
8462306a36Sopenharmony_ci			/* 2312 */
8562306a36Sopenharmony_ci			caps->cap_range.range_2ghz_min = 2412;
8662306a36Sopenharmony_ci			caps->cap_range.range_2ghz_max = 2732;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci			/* Override 2GHz modes on SoCs that need it
8962306a36Sopenharmony_ci			 * NOTE: cap_needs_2GHz_ovr gets set from
9062306a36Sopenharmony_ci			 * ath_ahb_probe */
9162306a36Sopenharmony_ci			if (!caps->cap_needs_2GHz_ovr) {
9262306a36Sopenharmony_ci				if (AR5K_EEPROM_HDR_11B(ee_header))
9362306a36Sopenharmony_ci					__set_bit(AR5K_MODE_11B,
9462306a36Sopenharmony_ci							caps->cap_mode);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci				if (AR5K_EEPROM_HDR_11G(ee_header) &&
9762306a36Sopenharmony_ci				ah->ah_version != AR5K_AR5211)
9862306a36Sopenharmony_ci					__set_bit(AR5K_MODE_11G,
9962306a36Sopenharmony_ci							caps->cap_mode);
10062306a36Sopenharmony_ci			}
10162306a36Sopenharmony_ci		}
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
10562306a36Sopenharmony_ci		__clear_bit(AR5K_MODE_11A, caps->cap_mode);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* Set number of supported TX queues */
10862306a36Sopenharmony_ci	if (ah->ah_version == AR5K_AR5210)
10962306a36Sopenharmony_ci		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
11062306a36Sopenharmony_ci	else
11162306a36Sopenharmony_ci		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* Newer hardware has PHY error counters */
11462306a36Sopenharmony_ci	if (ah->ah_mac_srev >= AR5K_SREV_AR5213A)
11562306a36Sopenharmony_ci		caps->cap_has_phyerr_counters = true;
11662306a36Sopenharmony_ci	else
11762306a36Sopenharmony_ci		caps->cap_has_phyerr_counters = false;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	/* MACs since AR5212 have MRR support */
12062306a36Sopenharmony_ci	if (ah->ah_version == AR5K_AR5212)
12162306a36Sopenharmony_ci		caps->cap_has_mrr_support = true;
12262306a36Sopenharmony_ci	else
12362306a36Sopenharmony_ci		caps->cap_has_mrr_support = false;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return 0;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * TODO: Following functions should be part of a new function
13062306a36Sopenharmony_ci * set_capability
13162306a36Sopenharmony_ci */
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ciint ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
13462306a36Sopenharmony_ci		u16 assoc_id)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	if (ah->ah_version == AR5K_AR5210) {
13762306a36Sopenharmony_ci		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
13862306a36Sopenharmony_ci			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
13962306a36Sopenharmony_ci		return 0;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return -EIO;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ciint ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	if (ah->ah_version == AR5K_AR5210) {
14862306a36Sopenharmony_ci		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
14962306a36Sopenharmony_ci			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
15062306a36Sopenharmony_ci		return 0;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	return -EIO;
15462306a36Sopenharmony_ci}
155