162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2010-2011 Atheros Communications Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci#include <linux/export.h>
1762306a36Sopenharmony_ci#include "hw.h"
1862306a36Sopenharmony_ci#include "ar9003_mac.h"
1962306a36Sopenharmony_ci#include "ar9003_mci.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic void ar9003_hw_rx_enable(struct ath_hw *hw)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	REG_WRITE(hw, AR_CR, 0);
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic void
2762306a36Sopenharmony_ciar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct ar9003_txc *ads = ds;
3062306a36Sopenharmony_ci	int checksum = 0;
3162306a36Sopenharmony_ci	u32 val, ctl12, ctl17;
3262306a36Sopenharmony_ci	u8 desc_len;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	desc_len = ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x18 : 0x17);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
3762306a36Sopenharmony_ci	      (1 << AR_TxRxDesc_S) |
3862306a36Sopenharmony_ci	      (1 << AR_CtrlStat_S) |
3962306a36Sopenharmony_ci	      (i->qcu << AR_TxQcuNum_S) | desc_len;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	checksum += val;
4262306a36Sopenharmony_ci	WRITE_ONCE(ads->info, val);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	checksum += i->link;
4562306a36Sopenharmony_ci	WRITE_ONCE(ads->link, i->link);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	checksum += i->buf_addr[0];
4862306a36Sopenharmony_ci	WRITE_ONCE(ads->data0, i->buf_addr[0]);
4962306a36Sopenharmony_ci	checksum += i->buf_addr[1];
5062306a36Sopenharmony_ci	WRITE_ONCE(ads->data1, i->buf_addr[1]);
5162306a36Sopenharmony_ci	checksum += i->buf_addr[2];
5262306a36Sopenharmony_ci	WRITE_ONCE(ads->data2, i->buf_addr[2]);
5362306a36Sopenharmony_ci	checksum += i->buf_addr[3];
5462306a36Sopenharmony_ci	WRITE_ONCE(ads->data3, i->buf_addr[3]);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
5762306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl3, val);
5862306a36Sopenharmony_ci	checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
5962306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl5, val);
6062306a36Sopenharmony_ci	checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
6162306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl7, val);
6262306a36Sopenharmony_ci	checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
6362306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl9, val);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
6662306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl10, checksum);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (i->is_first || i->is_last) {
6962306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl13, set11nTries(i->rates, 0)
7062306a36Sopenharmony_ci			| set11nTries(i->rates, 1)
7162306a36Sopenharmony_ci			| set11nTries(i->rates, 2)
7262306a36Sopenharmony_ci			| set11nTries(i->rates, 3)
7362306a36Sopenharmony_ci			| (i->dur_update ? AR_DurUpdateEna : 0)
7462306a36Sopenharmony_ci			| SM(0, AR_BurstDur));
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl14, set11nRate(i->rates, 0)
7762306a36Sopenharmony_ci			| set11nRate(i->rates, 1)
7862306a36Sopenharmony_ci			| set11nRate(i->rates, 2)
7962306a36Sopenharmony_ci			| set11nRate(i->rates, 3));
8062306a36Sopenharmony_ci	} else {
8162306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl13, 0);
8262306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl14, 0);
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ads->ctl20 = 0;
8662306a36Sopenharmony_ci	ads->ctl21 = 0;
8762306a36Sopenharmony_ci	ads->ctl22 = 0;
8862306a36Sopenharmony_ci	ads->ctl23 = 0;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	ctl17 = SM(i->keytype, AR_EncrType);
9162306a36Sopenharmony_ci	if (!i->is_first) {
9262306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl11, 0);
9362306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl12, i->is_last ? 0 : AR_TxMore);
9462306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl15, 0);
9562306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl16, 0);
9662306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl17, ctl17);
9762306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl18, 0);
9862306a36Sopenharmony_ci		WRITE_ONCE(ads->ctl19, 0);
9962306a36Sopenharmony_ci		return;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl11, (i->pkt_len & AR_FrameLen)
10362306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
10462306a36Sopenharmony_ci		| SM(i->txpower[0], AR_XmitPower0)
10562306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
10662306a36Sopenharmony_ci		| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
10762306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
10862306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
10962306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
11062306a36Sopenharmony_ci		   (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)));
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
11362306a36Sopenharmony_ci		 SM(i->keyix, AR_DestIdx) : 0)
11462306a36Sopenharmony_ci		| SM(i->type, AR_FrameType)
11562306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
11662306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
11762306a36Sopenharmony_ci		| (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
12062306a36Sopenharmony_ci	switch (i->aggr) {
12162306a36Sopenharmony_ci	case AGGR_BUF_FIRST:
12262306a36Sopenharmony_ci		ctl17 |= SM(i->aggr_len, AR_AggrLen);
12362306a36Sopenharmony_ci		fallthrough;
12462306a36Sopenharmony_ci	case AGGR_BUF_MIDDLE:
12562306a36Sopenharmony_ci		ctl12 |= AR_IsAggr | AR_MoreAggr;
12662306a36Sopenharmony_ci		ctl17 |= SM(i->ndelim, AR_PadDelim);
12762306a36Sopenharmony_ci		break;
12862306a36Sopenharmony_ci	case AGGR_BUF_LAST:
12962306a36Sopenharmony_ci		ctl12 |= AR_IsAggr;
13062306a36Sopenharmony_ci		break;
13162306a36Sopenharmony_ci	case AGGR_BUF_NONE:
13262306a36Sopenharmony_ci		break;
13362306a36Sopenharmony_ci	}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
13662306a36Sopenharmony_ci	ctl12 |= SM(val, AR_PAPRDChainMask);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl12, ctl12);
13962306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl17, ctl17);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl15, set11nPktDurRTSCTS(i->rates, 0)
14262306a36Sopenharmony_ci		| set11nPktDurRTSCTS(i->rates, 1));
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2)
14562306a36Sopenharmony_ci		| set11nPktDurRTSCTS(i->rates, 3));
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl18,
14862306a36Sopenharmony_ci		  set11nRateFlags(i->rates, 0) | set11nChainSel(i->rates, 0)
14962306a36Sopenharmony_ci		| set11nRateFlags(i->rates, 1) | set11nChainSel(i->rates, 1)
15062306a36Sopenharmony_ci		| set11nRateFlags(i->rates, 2) | set11nChainSel(i->rates, 2)
15162306a36Sopenharmony_ci		| set11nRateFlags(i->rates, 3) | set11nChainSel(i->rates, 3)
15262306a36Sopenharmony_ci		| SM(i->rtscts_rate, AR_RTSCTSRate));
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl19, AR_Not_Sounding);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl20, SM(i->txpower[1], AR_XmitPower1));
15762306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl21, SM(i->txpower[2], AR_XmitPower2));
15862306a36Sopenharmony_ci	WRITE_ONCE(ads->ctl22, SM(i->txpower[3], AR_XmitPower3));
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	int checksum;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	checksum = ads->info + ads->link
16662306a36Sopenharmony_ci		+ ads->data0 + ads->ctl3
16762306a36Sopenharmony_ci		+ ads->data1 + ads->ctl5
16862306a36Sopenharmony_ci		+ ads->data2 + ads->ctl7
16962306a36Sopenharmony_ci		+ ads->data3 + ads->ctl9;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	struct ar9003_txc *ads = ds;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	ads->link = ds_link;
17962306a36Sopenharmony_ci	ads->ctl10 &= ~AR_TxPtrChkSum;
18062306a36Sopenharmony_ci	ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
18462306a36Sopenharmony_ci			      u32 *sync_cause_p)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	u32 isr = 0;
18762306a36Sopenharmony_ci	u32 mask2 = 0;
18862306a36Sopenharmony_ci	struct ath9k_hw_capabilities *pCap = &ah->caps;
18962306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
19062306a36Sopenharmony_ci	u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ;
19162306a36Sopenharmony_ci	bool fatal_int;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (ath9k_hw_mci_is_enabled(ah))
19462306a36Sopenharmony_ci		async_mask |= AR_INTR_ASYNC_MASK_MCI;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE(ah));
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	if (async_cause & async_mask) {
19962306a36Sopenharmony_ci		if ((REG_READ(ah, AR_RTC_STATUS(ah)) & AR_RTC_STATUS_M(ah))
20062306a36Sopenharmony_ci				== AR_RTC_STATUS_ON)
20162306a36Sopenharmony_ci			isr = REG_READ(ah, AR_ISR);
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE(ah)) & AR_INTR_SYNC_DEFAULT;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	*masked = 0;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (!isr && !sync_cause && !async_cause)
21062306a36Sopenharmony_ci		return false;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if (isr) {
21362306a36Sopenharmony_ci		if (isr & AR_ISR_BCNMISC) {
21462306a36Sopenharmony_ci			u32 isr2;
21562306a36Sopenharmony_ci			isr2 = REG_READ(ah, AR_ISR_S2);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
21862306a36Sopenharmony_ci				  MAP_ISR_S2_TIM);
21962306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
22062306a36Sopenharmony_ci				  MAP_ISR_S2_DTIM);
22162306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
22262306a36Sopenharmony_ci				  MAP_ISR_S2_DTIMSYNC);
22362306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
22462306a36Sopenharmony_ci				  MAP_ISR_S2_CABEND);
22562306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
22662306a36Sopenharmony_ci				  MAP_ISR_S2_GTT);
22762306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_CST) <<
22862306a36Sopenharmony_ci				  MAP_ISR_S2_CST);
22962306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
23062306a36Sopenharmony_ci				  MAP_ISR_S2_TSFOOR);
23162306a36Sopenharmony_ci			mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
23262306a36Sopenharmony_ci				  MAP_ISR_S2_BB_WATCHDOG);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
23562306a36Sopenharmony_ci				REG_WRITE(ah, AR_ISR_S2, isr2);
23662306a36Sopenharmony_ci				isr &= ~AR_ISR_BCNMISC;
23762306a36Sopenharmony_ci			}
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
24162306a36Sopenharmony_ci			isr = REG_READ(ah, AR_ISR_RAC);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci		if (isr == 0xffffffff) {
24462306a36Sopenharmony_ci			*masked = 0;
24562306a36Sopenharmony_ci			return false;
24662306a36Sopenharmony_ci		}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci		*masked = isr & ATH9K_INT_COMMON;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci		if (ah->config.rx_intr_mitigation)
25162306a36Sopenharmony_ci			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
25262306a36Sopenharmony_ci				*masked |= ATH9K_INT_RXLP;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		if (ah->config.tx_intr_mitigation)
25562306a36Sopenharmony_ci			if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
25662306a36Sopenharmony_ci				*masked |= ATH9K_INT_TX;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci		if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
25962306a36Sopenharmony_ci			*masked |= ATH9K_INT_RXLP;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		if (isr & AR_ISR_HP_RXOK)
26262306a36Sopenharmony_ci			*masked |= ATH9K_INT_RXHP;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci		if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
26562306a36Sopenharmony_ci			*masked |= ATH9K_INT_TX;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
26862306a36Sopenharmony_ci				u32 s0, s1;
26962306a36Sopenharmony_ci				s0 = REG_READ(ah, AR_ISR_S0);
27062306a36Sopenharmony_ci				REG_WRITE(ah, AR_ISR_S0, s0);
27162306a36Sopenharmony_ci				s1 = REG_READ(ah, AR_ISR_S1);
27262306a36Sopenharmony_ci				REG_WRITE(ah, AR_ISR_S1, s1);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci				isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
27562306a36Sopenharmony_ci					 AR_ISR_TXEOL);
27662306a36Sopenharmony_ci			}
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		if (isr & AR_ISR_GENTMR) {
28062306a36Sopenharmony_ci			u32 s5;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci			if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
28362306a36Sopenharmony_ci				s5 = REG_READ(ah, AR_ISR_S5_S(ah));
28462306a36Sopenharmony_ci			else
28562306a36Sopenharmony_ci				s5 = REG_READ(ah, AR_ISR_S5);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci			ah->intr_gen_timer_trigger =
28862306a36Sopenharmony_ci				MS(s5, AR_ISR_S5_GENTIMER_TRIG);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci			ah->intr_gen_timer_thresh =
29162306a36Sopenharmony_ci				MS(s5, AR_ISR_S5_GENTIMER_THRESH);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci			if (ah->intr_gen_timer_trigger)
29462306a36Sopenharmony_ci				*masked |= ATH9K_INT_GENTIMER;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
29762306a36Sopenharmony_ci				REG_WRITE(ah, AR_ISR_S5, s5);
29862306a36Sopenharmony_ci				isr &= ~AR_ISR_GENTMR;
29962306a36Sopenharmony_ci			}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci		}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci		*masked |= mask2;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci		if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
30662306a36Sopenharmony_ci			REG_WRITE(ah, AR_ISR, isr);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci			(void) REG_READ(ah, AR_ISR);
30962306a36Sopenharmony_ci		}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci		if (*masked & ATH9K_INT_BB_WATCHDOG)
31262306a36Sopenharmony_ci			ar9003_hw_bb_watchdog_read(ah);
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (async_cause & AR_INTR_ASYNC_MASK_MCI)
31662306a36Sopenharmony_ci		ar9003_mci_get_isr(ah, masked);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (sync_cause) {
31962306a36Sopenharmony_ci		if (sync_cause_p)
32062306a36Sopenharmony_ci			*sync_cause_p = sync_cause;
32162306a36Sopenharmony_ci		fatal_int =
32262306a36Sopenharmony_ci			(sync_cause &
32362306a36Sopenharmony_ci			 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
32462306a36Sopenharmony_ci			? true : false;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci		if (fatal_int) {
32762306a36Sopenharmony_ci			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
32862306a36Sopenharmony_ci				ath_dbg(common, ANY,
32962306a36Sopenharmony_ci					"received PCI FATAL interrupt\n");
33062306a36Sopenharmony_ci			}
33162306a36Sopenharmony_ci			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
33262306a36Sopenharmony_ci				ath_dbg(common, ANY,
33362306a36Sopenharmony_ci					"received PCI PERR interrupt\n");
33462306a36Sopenharmony_ci			}
33562306a36Sopenharmony_ci			*masked |= ATH9K_INT_FATAL;
33662306a36Sopenharmony_ci		}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
33962306a36Sopenharmony_ci			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
34062306a36Sopenharmony_ci			REG_WRITE(ah, AR_RC, 0);
34162306a36Sopenharmony_ci			*masked |= ATH9K_INT_FATAL;
34262306a36Sopenharmony_ci		}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
34562306a36Sopenharmony_ci			ath_dbg(common, INTERRUPT,
34662306a36Sopenharmony_ci				"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR(ah), sync_cause);
34962306a36Sopenharmony_ci		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR(ah));
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci	return true;
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cistatic int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
35662306a36Sopenharmony_ci				 struct ath_tx_status *ts)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	struct ar9003_txs *ads;
35962306a36Sopenharmony_ci	u32 status;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	ads = &ah->ts_ring[ah->ts_tail];
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	status = READ_ONCE(ads->status8);
36462306a36Sopenharmony_ci	if ((status & AR_TxDone) == 0)
36562306a36Sopenharmony_ci		return -EINPROGRESS;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
37062306a36Sopenharmony_ci	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
37162306a36Sopenharmony_ci		ath_dbg(ath9k_hw_common(ah), XMIT,
37262306a36Sopenharmony_ci			"Tx Descriptor error %x\n", ads->ds_info);
37362306a36Sopenharmony_ci		memset(ads, 0, sizeof(*ads));
37462306a36Sopenharmony_ci		return -EIO;
37562306a36Sopenharmony_ci	}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	ts->ts_rateindex = MS(status, AR_FinalTxIdx);
37862306a36Sopenharmony_ci	ts->ts_seqnum = MS(status, AR_SeqNum);
37962306a36Sopenharmony_ci	ts->tid = MS(status, AR_TxTid);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
38262306a36Sopenharmony_ci	ts->desc_id = MS(ads->status1, AR_TxDescId);
38362306a36Sopenharmony_ci	ts->ts_tstamp = ads->status4;
38462306a36Sopenharmony_ci	ts->ts_status = 0;
38562306a36Sopenharmony_ci	ts->ts_flags  = 0;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (status & AR_TxOpExceeded)
38862306a36Sopenharmony_ci		ts->ts_status |= ATH9K_TXERR_XTXOP;
38962306a36Sopenharmony_ci	status = READ_ONCE(ads->status2);
39062306a36Sopenharmony_ci	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
39162306a36Sopenharmony_ci	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
39262306a36Sopenharmony_ci	ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
39362306a36Sopenharmony_ci	if (status & AR_TxBaStatus) {
39462306a36Sopenharmony_ci		ts->ts_flags |= ATH9K_TX_BA;
39562306a36Sopenharmony_ci		ts->ba_low = ads->status5;
39662306a36Sopenharmony_ci		ts->ba_high = ads->status6;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	status = READ_ONCE(ads->status3);
40062306a36Sopenharmony_ci	if (status & AR_ExcessiveRetries)
40162306a36Sopenharmony_ci		ts->ts_status |= ATH9K_TXERR_XRETRY;
40262306a36Sopenharmony_ci	if (status & AR_Filtered)
40362306a36Sopenharmony_ci		ts->ts_status |= ATH9K_TXERR_FILT;
40462306a36Sopenharmony_ci	if (status & AR_FIFOUnderrun) {
40562306a36Sopenharmony_ci		ts->ts_status |= ATH9K_TXERR_FIFO;
40662306a36Sopenharmony_ci		ath9k_hw_updatetxtriglevel(ah, true);
40762306a36Sopenharmony_ci	}
40862306a36Sopenharmony_ci	if (status & AR_TxTimerExpired)
40962306a36Sopenharmony_ci		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
41062306a36Sopenharmony_ci	if (status & AR_DescCfgErr)
41162306a36Sopenharmony_ci		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
41262306a36Sopenharmony_ci	if (status & AR_TxDataUnderrun) {
41362306a36Sopenharmony_ci		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
41462306a36Sopenharmony_ci		ath9k_hw_updatetxtriglevel(ah, true);
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci	if (status & AR_TxDelimUnderrun) {
41762306a36Sopenharmony_ci		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
41862306a36Sopenharmony_ci		ath9k_hw_updatetxtriglevel(ah, true);
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci	ts->ts_shortretry = MS(status, AR_RTSFailCnt);
42162306a36Sopenharmony_ci	ts->ts_longretry = MS(status, AR_DataFailCnt);
42262306a36Sopenharmony_ci	ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	status = READ_ONCE(ads->status7);
42562306a36Sopenharmony_ci	ts->ts_rssi = MS(status, AR_TxRSSICombined);
42662306a36Sopenharmony_ci	ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
42762306a36Sopenharmony_ci	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
42862306a36Sopenharmony_ci	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	memset(ads, 0, sizeof(*ads));
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	return 0;
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
43662306a36Sopenharmony_ci{
43762306a36Sopenharmony_ci	const struct ar9003_txc *adc = ds;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	switch (index) {
44062306a36Sopenharmony_ci	case 0:
44162306a36Sopenharmony_ci		return MS(READ_ONCE(adc->ctl15), AR_PacketDur0);
44262306a36Sopenharmony_ci	case 1:
44362306a36Sopenharmony_ci		return MS(READ_ONCE(adc->ctl15), AR_PacketDur1);
44462306a36Sopenharmony_ci	case 2:
44562306a36Sopenharmony_ci		return MS(READ_ONCE(adc->ctl16), AR_PacketDur2);
44662306a36Sopenharmony_ci	case 3:
44762306a36Sopenharmony_ci		return MS(READ_ONCE(adc->ctl16), AR_PacketDur3);
44862306a36Sopenharmony_ci	default:
44962306a36Sopenharmony_ci		return 0;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_civoid ar9003_hw_attach_mac_ops(struct ath_hw *hw)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	struct ath_hw_ops *ops = ath9k_hw_ops(hw);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	ops->rx_enable = ar9003_hw_rx_enable;
45862306a36Sopenharmony_ci	ops->set_desc_link = ar9003_hw_set_desc_link;
45962306a36Sopenharmony_ci	ops->get_isr = ar9003_hw_get_isr;
46062306a36Sopenharmony_ci	ops->set_txdesc = ar9003_set_txdesc;
46162306a36Sopenharmony_ci	ops->proc_txdesc = ar9003_hw_proc_txdesc;
46262306a36Sopenharmony_ci	ops->get_duration = ar9003_hw_get_duration;
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_civoid ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK);
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_rx_bufsize);
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_civoid ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
47262306a36Sopenharmony_ci			    enum ath9k_rx_qtype qtype)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	if (qtype == ATH9K_RX_QUEUE_HP)
47562306a36Sopenharmony_ci		REG_WRITE(ah, AR_HP_RXDP, rxdp);
47662306a36Sopenharmony_ci	else
47762306a36Sopenharmony_ci		REG_WRITE(ah, AR_LP_RXDP, rxdp);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_addrxbuf_edma);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ciint ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
48262306a36Sopenharmony_ci				 void *buf_addr)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci	struct ar9003_rxs *rxsp = buf_addr;
48562306a36Sopenharmony_ci	unsigned int phyerr;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	if ((rxsp->status11 & AR_RxDone) == 0)
48862306a36Sopenharmony_ci		return -EINPROGRESS;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
49162306a36Sopenharmony_ci		return -EINVAL;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
49462306a36Sopenharmony_ci		return -EINPROGRESS;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	rxs->rs_status = 0;
49762306a36Sopenharmony_ci	rxs->rs_flags =  0;
49862306a36Sopenharmony_ci	rxs->enc_flags = 0;
49962306a36Sopenharmony_ci	rxs->bw = RATE_INFO_BW_20;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	rxs->rs_datalen = rxsp->status2 & AR_DataLen;
50262306a36Sopenharmony_ci	rxs->rs_tstamp =  rxsp->status3;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* XXX: Keycache */
50562306a36Sopenharmony_ci	rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
50662306a36Sopenharmony_ci	rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
50762306a36Sopenharmony_ci	rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
50862306a36Sopenharmony_ci	rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
50962306a36Sopenharmony_ci	rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
51062306a36Sopenharmony_ci	rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
51162306a36Sopenharmony_ci	rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	if (rxsp->status11 & AR_RxKeyIdxValid)
51462306a36Sopenharmony_ci		rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
51562306a36Sopenharmony_ci	else
51662306a36Sopenharmony_ci		rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	rxs->rs_rate = MS(rxsp->status1, AR_RxRate);
51962306a36Sopenharmony_ci	rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	rxs->rs_firstaggr = (rxsp->status11 & AR_RxFirstAggr) ? 1 : 0;
52262306a36Sopenharmony_ci	rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0;
52362306a36Sopenharmony_ci	rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
52462306a36Sopenharmony_ci	rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
52562306a36Sopenharmony_ci	rxs->enc_flags |= (rxsp->status4 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0;
52662306a36Sopenharmony_ci	rxs->enc_flags |=
52762306a36Sopenharmony_ci		(rxsp->status4 & AR_STBC) ? (1 << RX_ENC_FLAG_STBC_SHIFT) : 0;
52862306a36Sopenharmony_ci	rxs->bw = (rxsp->status4 & AR_2040) ? RATE_INFO_BW_40 : RATE_INFO_BW_20;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	rxs->evm0 = rxsp->status6;
53162306a36Sopenharmony_ci	rxs->evm1 = rxsp->status7;
53262306a36Sopenharmony_ci	rxs->evm2 = rxsp->status8;
53362306a36Sopenharmony_ci	rxs->evm3 = rxsp->status9;
53462306a36Sopenharmony_ci	rxs->evm4 = (rxsp->status10 & 0xffff);
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (rxsp->status11 & AR_PreDelimCRCErr)
53762306a36Sopenharmony_ci		rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	if (rxsp->status11 & AR_PostDelimCRCErr)
54062306a36Sopenharmony_ci		rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (rxsp->status11 & AR_DecryptBusyErr)
54362306a36Sopenharmony_ci		rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	if ((rxsp->status11 & AR_RxFrameOK) == 0) {
54662306a36Sopenharmony_ci		/*
54762306a36Sopenharmony_ci		 * AR_CRCErr will bet set to true if we're on the last
54862306a36Sopenharmony_ci		 * subframe and the AR_PostDelimCRCErr is caught.
54962306a36Sopenharmony_ci		 * In a way this also gives us a guarantee that when
55062306a36Sopenharmony_ci		 * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
55162306a36Sopenharmony_ci		 * possibly be reviewing the last subframe. AR_CRCErr
55262306a36Sopenharmony_ci		 * is the CRC of the actual data.
55362306a36Sopenharmony_ci		 */
55462306a36Sopenharmony_ci		if (rxsp->status11 & AR_CRCErr)
55562306a36Sopenharmony_ci			rxs->rs_status |= ATH9K_RXERR_CRC;
55662306a36Sopenharmony_ci		else if (rxsp->status11 & AR_DecryptCRCErr)
55762306a36Sopenharmony_ci			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
55862306a36Sopenharmony_ci		else if (rxsp->status11 & AR_MichaelErr)
55962306a36Sopenharmony_ci			rxs->rs_status |= ATH9K_RXERR_MIC;
56062306a36Sopenharmony_ci		if (rxsp->status11 & AR_PHYErr) {
56162306a36Sopenharmony_ci			phyerr = MS(rxsp->status11, AR_PHYErrCode);
56262306a36Sopenharmony_ci			/*
56362306a36Sopenharmony_ci			 * If we reach a point here where AR_PostDelimCRCErr is
56462306a36Sopenharmony_ci			 * true it implies we're *not* on the last subframe. In
56562306a36Sopenharmony_ci			 * in that case that we know already that the CRC of
56662306a36Sopenharmony_ci			 * the frame was OK, and MAC would send an ACK for that
56762306a36Sopenharmony_ci			 * subframe, even if we did get a phy error of type
56862306a36Sopenharmony_ci			 * ATH9K_PHYERR_OFDM_RESTART. This is only applicable
56962306a36Sopenharmony_ci			 * to frame that are prior to the last subframe.
57062306a36Sopenharmony_ci			 * The AR_PostDelimCRCErr is the CRC for the MPDU
57162306a36Sopenharmony_ci			 * delimiter, which contains the 4 reserved bits,
57262306a36Sopenharmony_ci			 * the MPDU length (12 bits), and follows the MPDU
57362306a36Sopenharmony_ci			 * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
57462306a36Sopenharmony_ci			 */
57562306a36Sopenharmony_ci			if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
57662306a36Sopenharmony_ci			    (rxsp->status11 & AR_PostDelimCRCErr)) {
57762306a36Sopenharmony_ci				rxs->rs_phyerr = 0;
57862306a36Sopenharmony_ci			} else {
57962306a36Sopenharmony_ci				rxs->rs_status |= ATH9K_RXERR_PHY;
58062306a36Sopenharmony_ci				rxs->rs_phyerr = phyerr;
58162306a36Sopenharmony_ci			}
58262306a36Sopenharmony_ci		}
58362306a36Sopenharmony_ci	}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	if (rxsp->status11 & AR_KeyMiss)
58662306a36Sopenharmony_ci		rxs->rs_status |= ATH9K_RXERR_KEYMISS;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	return 0;
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_civoid ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	ah->ts_tail = 0;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	memset((void *) ah->ts_ring, 0,
59762306a36Sopenharmony_ci		ah->ts_size * sizeof(struct ar9003_txs));
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	ath_dbg(ath9k_hw_common(ah), XMIT,
60062306a36Sopenharmony_ci		"TS Start 0x%x End 0x%x Virt %p, Size %d\n",
60162306a36Sopenharmony_ci		ah->ts_paddr_start, ah->ts_paddr_end,
60262306a36Sopenharmony_ci		ah->ts_ring, ah->ts_size);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
60562306a36Sopenharmony_ci	REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_civoid ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
60962306a36Sopenharmony_ci			       u32 ts_paddr_start,
61062306a36Sopenharmony_ci			       u16 size)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	ah->ts_paddr_start = ts_paddr_start;
61462306a36Sopenharmony_ci	ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs));
61562306a36Sopenharmony_ci	ah->ts_size = size;
61662306a36Sopenharmony_ci	ah->ts_ring = ts_start;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	ath9k_hw_reset_txstatus_ring(ah);
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setup_statusring);
621