2 * Copyright (c) 2008-2011 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <linux/export.h>
20 #define AR_BufLen 0x00000fff
22 static void ar9002_hw_rx_enable(struct ath_hw
*ah
)
24 REG_WRITE(ah
, AR_CR
, AR_CR_RXE
);
27 static void ar9002_hw_set_desc_link(void *ds
, u32 ds_link
)
29 ((struct ath_desc
*) ds
)->ds_link
= ds_link
;
32 static bool ar9002_hw_get_isr(struct ath_hw
*ah
, enum ath9k_int
*masked
)
36 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
38 bool fatal_int
= false;
39 struct ath_common
*common
= ath9k_hw_common(ah
);
41 if (!AR_SREV_9100(ah
)) {
42 if (REG_READ(ah
, AR_INTR_ASYNC_CAUSE
) & AR_INTR_MAC_IRQ
) {
43 if ((REG_READ(ah
, AR_RTC_STATUS
) & AR_RTC_STATUS_M
)
44 == AR_RTC_STATUS_ON
) {
45 isr
= REG_READ(ah
, AR_ISR
);
49 sync_cause
= REG_READ(ah
, AR_INTR_SYNC_CAUSE
) &
54 if (!isr
&& !sync_cause
)
58 isr
= REG_READ(ah
, AR_ISR
);
62 if (isr
& AR_ISR_BCNMISC
) {
64 isr2
= REG_READ(ah
, AR_ISR_S2
);
65 if (isr2
& AR_ISR_S2_TIM
)
66 mask2
|= ATH9K_INT_TIM
;
67 if (isr2
& AR_ISR_S2_DTIM
)
68 mask2
|= ATH9K_INT_DTIM
;
69 if (isr2
& AR_ISR_S2_DTIMSYNC
)
70 mask2
|= ATH9K_INT_DTIMSYNC
;
71 if (isr2
& (AR_ISR_S2_CABEND
))
72 mask2
|= ATH9K_INT_CABEND
;
73 if (isr2
& AR_ISR_S2_GTT
)
74 mask2
|= ATH9K_INT_GTT
;
75 if (isr2
& AR_ISR_S2_CST
)
76 mask2
|= ATH9K_INT_CST
;
77 if (isr2
& AR_ISR_S2_TSFOOR
)
78 mask2
|= ATH9K_INT_TSFOOR
;
81 isr
= REG_READ(ah
, AR_ISR_RAC
);
82 if (isr
== 0xffffffff) {
87 *masked
= isr
& ATH9K_INT_COMMON
;
89 if (isr
& (AR_ISR_RXMINTR
| AR_ISR_RXINTM
|
90 AR_ISR_RXOK
| AR_ISR_RXERR
))
91 *masked
|= ATH9K_INT_RX
;
94 (AR_ISR_TXOK
| AR_ISR_TXDESC
| AR_ISR_TXERR
|
98 *masked
|= ATH9K_INT_TX
;
100 s0_s
= REG_READ(ah
, AR_ISR_S0_S
);
101 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXOK
);
102 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXDESC
);
104 s1_s
= REG_READ(ah
, AR_ISR_S1_S
);
105 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXERR
);
106 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXEOL
);
109 if (isr
& AR_ISR_RXORN
) {
110 ath_dbg(common
, INTERRUPT
,
111 "receive FIFO overrun interrupt\n");
117 if (AR_SREV_9100(ah
))
120 if (isr
& AR_ISR_GENTMR
) {
123 s5_s
= REG_READ(ah
, AR_ISR_S5_S
);
124 ah
->intr_gen_timer_trigger
=
125 MS(s5_s
, AR_ISR_S5_GENTIMER_TRIG
);
127 ah
->intr_gen_timer_thresh
=
128 MS(s5_s
, AR_ISR_S5_GENTIMER_THRESH
);
130 if (ah
->intr_gen_timer_trigger
)
131 *masked
|= ATH9K_INT_GENTIMER
;
133 if ((s5_s
& AR_ISR_S5_TIM_TIMER
) &&
134 !(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
135 *masked
|= ATH9K_INT_TIM_TIMER
;
141 (AR_INTR_SYNC_HOST1_FATAL
| AR_INTR_SYNC_HOST1_PERR
))
145 if (sync_cause
& AR_INTR_SYNC_HOST1_FATAL
) {
147 "received PCI FATAL interrupt\n");
149 if (sync_cause
& AR_INTR_SYNC_HOST1_PERR
) {
151 "received PCI PERR interrupt\n");
153 *masked
|= ATH9K_INT_FATAL
;
155 if (sync_cause
& AR_INTR_SYNC_RADM_CPL_TIMEOUT
) {
156 ath_dbg(common
, INTERRUPT
,
157 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
158 REG_WRITE(ah
, AR_RC
, AR_RC_HOSTIF
);
159 REG_WRITE(ah
, AR_RC
, 0);
160 *masked
|= ATH9K_INT_FATAL
;
162 if (sync_cause
& AR_INTR_SYNC_LOCAL_TIMEOUT
) {
163 ath_dbg(common
, INTERRUPT
,
164 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
167 REG_WRITE(ah
, AR_INTR_SYNC_CAUSE_CLR
, sync_cause
);
168 (void) REG_READ(ah
, AR_INTR_SYNC_CAUSE_CLR
);
175 ar9002_set_txdesc(struct ath_hw
*ah
, void *ds
, struct ath_tx_info
*i
)
177 struct ar5416_desc
*ads
= AR5416DESC(ds
);
180 ads
->ds_txstatus0
= ads
->ds_txstatus1
= 0;
181 ads
->ds_txstatus2
= ads
->ds_txstatus3
= 0;
182 ads
->ds_txstatus4
= ads
->ds_txstatus5
= 0;
183 ads
->ds_txstatus6
= ads
->ds_txstatus7
= 0;
184 ads
->ds_txstatus8
= ads
->ds_txstatus9
= 0;
186 ACCESS_ONCE(ads
->ds_link
) = i
->link
;
187 ACCESS_ONCE(ads
->ds_data
) = i
->buf_addr
[0];
189 ctl1
= i
->buf_len
[0] | (i
->is_last
? 0 : AR_TxMore
);
190 ctl6
= SM(i
->keytype
, AR_EncrType
);
192 if (AR_SREV_9285(ah
)) {
199 if ((i
->is_first
|| i
->is_last
) &&
200 i
->aggr
!= AGGR_BUF_MIDDLE
&& i
->aggr
!= AGGR_BUF_LAST
) {
201 ACCESS_ONCE(ads
->ds_ctl2
) = set11nTries(i
->rates
, 0)
202 | set11nTries(i
->rates
, 1)
203 | set11nTries(i
->rates
, 2)
204 | set11nTries(i
->rates
, 3)
205 | (i
->dur_update
? AR_DurUpdateEna
: 0)
206 | SM(0, AR_BurstDur
);
208 ACCESS_ONCE(ads
->ds_ctl3
) = set11nRate(i
->rates
, 0)
209 | set11nRate(i
->rates
, 1)
210 | set11nRate(i
->rates
, 2)
211 | set11nRate(i
->rates
, 3);
213 ACCESS_ONCE(ads
->ds_ctl2
) = 0;
214 ACCESS_ONCE(ads
->ds_ctl3
) = 0;
218 ACCESS_ONCE(ads
->ds_ctl0
) = 0;
219 ACCESS_ONCE(ads
->ds_ctl1
) = ctl1
;
220 ACCESS_ONCE(ads
->ds_ctl6
) = ctl6
;
224 ctl1
|= (i
->keyix
!= ATH9K_TXKEYIX_INVALID
? SM(i
->keyix
, AR_DestIdx
) : 0)
225 | SM(i
->type
, AR_FrameType
)
226 | (i
->flags
& ATH9K_TXDESC_NOACK
? AR_NoAck
: 0)
227 | (i
->flags
& ATH9K_TXDESC_EXT_ONLY
? AR_ExtOnly
: 0)
228 | (i
->flags
& ATH9K_TXDESC_EXT_AND_CTL
? AR_ExtAndCtl
: 0);
232 ctl6
|= SM(i
->aggr_len
, AR_AggrLen
);
234 case AGGR_BUF_MIDDLE
:
235 ctl1
|= AR_IsAggr
| AR_MoreAggr
;
236 ctl6
|= SM(i
->ndelim
, AR_PadDelim
);
245 ACCESS_ONCE(ads
->ds_ctl0
) = (i
->pkt_len
& AR_FrameLen
)
246 | (i
->flags
& ATH9K_TXDESC_VMF
? AR_VirtMoreFrag
: 0)
247 | SM(i
->txpower
, AR_XmitPower
)
248 | (i
->flags
& ATH9K_TXDESC_VEOL
? AR_VEOL
: 0)
249 | (i
->flags
& ATH9K_TXDESC_INTREQ
? AR_TxIntrReq
: 0)
250 | (i
->keyix
!= ATH9K_TXKEYIX_INVALID
? AR_DestIdxValid
: 0)
251 | (i
->flags
& ATH9K_TXDESC_CLRDMASK
? AR_ClrDestMask
: 0)
252 | (i
->flags
& ATH9K_TXDESC_RTSENA
? AR_RTSEnable
:
253 (i
->flags
& ATH9K_TXDESC_CTSENA
? AR_CTSEnable
: 0));
255 ACCESS_ONCE(ads
->ds_ctl1
) = ctl1
;
256 ACCESS_ONCE(ads
->ds_ctl6
) = ctl6
;
258 if (i
->aggr
== AGGR_BUF_MIDDLE
|| i
->aggr
== AGGR_BUF_LAST
)
261 ACCESS_ONCE(ads
->ds_ctl4
) = set11nPktDurRTSCTS(i
->rates
, 0)
262 | set11nPktDurRTSCTS(i
->rates
, 1);
264 ACCESS_ONCE(ads
->ds_ctl5
) = set11nPktDurRTSCTS(i
->rates
, 2)
265 | set11nPktDurRTSCTS(i
->rates
, 3);
267 ACCESS_ONCE(ads
->ds_ctl7
) = set11nRateFlags(i
->rates
, 0)
268 | set11nRateFlags(i
->rates
, 1)
269 | set11nRateFlags(i
->rates
, 2)
270 | set11nRateFlags(i
->rates
, 3)
271 | SM(i
->rtscts_rate
, AR_RTSCTSRate
);
274 static int ar9002_hw_proc_txdesc(struct ath_hw
*ah
, void *ds
,
275 struct ath_tx_status
*ts
)
277 struct ar5416_desc
*ads
= AR5416DESC(ds
);
280 status
= ACCESS_ONCE(ads
->ds_txstatus9
);
281 if ((status
& AR_TxDone
) == 0)
284 ts
->ts_tstamp
= ads
->AR_SendTimestamp
;
288 if (status
& AR_TxOpExceeded
)
289 ts
->ts_status
|= ATH9K_TXERR_XTXOP
;
290 ts
->tid
= MS(status
, AR_TxTid
);
291 ts
->ts_rateindex
= MS(status
, AR_FinalTxIdx
);
292 ts
->ts_seqnum
= MS(status
, AR_SeqNum
);
294 status
= ACCESS_ONCE(ads
->ds_txstatus0
);
295 ts
->ts_rssi_ctl0
= MS(status
, AR_TxRSSIAnt00
);
296 ts
->ts_rssi_ctl1
= MS(status
, AR_TxRSSIAnt01
);
297 ts
->ts_rssi_ctl2
= MS(status
, AR_TxRSSIAnt02
);
298 if (status
& AR_TxBaStatus
) {
299 ts
->ts_flags
|= ATH9K_TX_BA
;
300 ts
->ba_low
= ads
->AR_BaBitmapLow
;
301 ts
->ba_high
= ads
->AR_BaBitmapHigh
;
304 status
= ACCESS_ONCE(ads
->ds_txstatus1
);
305 if (status
& AR_FrmXmitOK
)
306 ts
->ts_status
|= ATH9K_TX_ACKED
;
308 if (status
& AR_ExcessiveRetries
)
309 ts
->ts_status
|= ATH9K_TXERR_XRETRY
;
310 if (status
& AR_Filtered
)
311 ts
->ts_status
|= ATH9K_TXERR_FILT
;
312 if (status
& AR_FIFOUnderrun
) {
313 ts
->ts_status
|= ATH9K_TXERR_FIFO
;
314 ath9k_hw_updatetxtriglevel(ah
, true);
317 if (status
& AR_TxTimerExpired
)
318 ts
->ts_status
|= ATH9K_TXERR_TIMER_EXPIRED
;
319 if (status
& AR_DescCfgErr
)
320 ts
->ts_flags
|= ATH9K_TX_DESC_CFG_ERR
;
321 if (status
& AR_TxDataUnderrun
) {
322 ts
->ts_flags
|= ATH9K_TX_DATA_UNDERRUN
;
323 ath9k_hw_updatetxtriglevel(ah
, true);
325 if (status
& AR_TxDelimUnderrun
) {
326 ts
->ts_flags
|= ATH9K_TX_DELIM_UNDERRUN
;
327 ath9k_hw_updatetxtriglevel(ah
, true);
329 ts
->ts_shortretry
= MS(status
, AR_RTSFailCnt
);
330 ts
->ts_longretry
= MS(status
, AR_DataFailCnt
);
331 ts
->ts_virtcol
= MS(status
, AR_VirtRetryCnt
);
333 status
= ACCESS_ONCE(ads
->ds_txstatus5
);
334 ts
->ts_rssi
= MS(status
, AR_TxRSSICombined
);
335 ts
->ts_rssi_ext0
= MS(status
, AR_TxRSSIAnt10
);
336 ts
->ts_rssi_ext1
= MS(status
, AR_TxRSSIAnt11
);
337 ts
->ts_rssi_ext2
= MS(status
, AR_TxRSSIAnt12
);
339 ts
->evm0
= ads
->AR_TxEVM0
;
340 ts
->evm1
= ads
->AR_TxEVM1
;
341 ts
->evm2
= ads
->AR_TxEVM2
;
346 void ath9k_hw_setuprxdesc(struct ath_hw
*ah
, struct ath_desc
*ds
,
349 struct ar5416_desc
*ads
= AR5416DESC(ds
);
350 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
352 ads
->ds_ctl1
= size
& AR_BufLen
;
353 if (flags
& ATH9K_RXDESC_INTREQ
)
354 ads
->ds_ctl1
|= AR_RxIntrReq
;
356 ads
->ds_rxstatus8
&= ~AR_RxDone
;
357 if (!(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
358 memset(&(ads
->u
), 0, sizeof(ads
->u
));
360 EXPORT_SYMBOL(ath9k_hw_setuprxdesc
);
362 void ar9002_hw_attach_mac_ops(struct ath_hw
*ah
)
364 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
366 ops
->rx_enable
= ar9002_hw_rx_enable
;
367 ops
->set_desc_link
= ar9002_hw_set_desc_link
;
368 ops
->get_isr
= ar9002_hw_get_isr
;
369 ops
->set_txdesc
= ar9002_set_txdesc
;
370 ops
->proc_txdesc
= ar9002_hw_proc_txdesc
;