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
;
139 ath9k_debug_sync_cause(common
, sync_cause
);
142 (AR_INTR_SYNC_HOST1_FATAL
| AR_INTR_SYNC_HOST1_PERR
))
146 if (sync_cause
& AR_INTR_SYNC_HOST1_FATAL
) {
148 "received PCI FATAL interrupt\n");
150 if (sync_cause
& AR_INTR_SYNC_HOST1_PERR
) {
152 "received PCI PERR interrupt\n");
154 *masked
|= ATH9K_INT_FATAL
;
156 if (sync_cause
& AR_INTR_SYNC_RADM_CPL_TIMEOUT
) {
157 ath_dbg(common
, INTERRUPT
,
158 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
159 REG_WRITE(ah
, AR_RC
, AR_RC_HOSTIF
);
160 REG_WRITE(ah
, AR_RC
, 0);
161 *masked
|= ATH9K_INT_FATAL
;
163 if (sync_cause
& AR_INTR_SYNC_LOCAL_TIMEOUT
) {
164 ath_dbg(common
, INTERRUPT
,
165 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
168 REG_WRITE(ah
, AR_INTR_SYNC_CAUSE_CLR
, sync_cause
);
169 (void) REG_READ(ah
, AR_INTR_SYNC_CAUSE_CLR
);
176 ar9002_set_txdesc(struct ath_hw
*ah
, void *ds
, struct ath_tx_info
*i
)
178 struct ar5416_desc
*ads
= AR5416DESC(ds
);
181 ads
->ds_txstatus0
= ads
->ds_txstatus1
= 0;
182 ads
->ds_txstatus2
= ads
->ds_txstatus3
= 0;
183 ads
->ds_txstatus4
= ads
->ds_txstatus5
= 0;
184 ads
->ds_txstatus6
= ads
->ds_txstatus7
= 0;
185 ads
->ds_txstatus8
= ads
->ds_txstatus9
= 0;
187 ACCESS_ONCE(ads
->ds_link
) = i
->link
;
188 ACCESS_ONCE(ads
->ds_data
) = i
->buf_addr
[0];
190 ctl1
= i
->buf_len
[0] | (i
->is_last
? 0 : AR_TxMore
);
191 ctl6
= SM(i
->keytype
, AR_EncrType
);
193 if (AR_SREV_9285(ah
)) {
200 if ((i
->is_first
|| i
->is_last
) &&
201 i
->aggr
!= AGGR_BUF_MIDDLE
&& i
->aggr
!= AGGR_BUF_LAST
) {
202 ACCESS_ONCE(ads
->ds_ctl2
) = set11nTries(i
->rates
, 0)
203 | set11nTries(i
->rates
, 1)
204 | set11nTries(i
->rates
, 2)
205 | set11nTries(i
->rates
, 3)
206 | (i
->dur_update
? AR_DurUpdateEna
: 0)
207 | SM(0, AR_BurstDur
);
209 ACCESS_ONCE(ads
->ds_ctl3
) = set11nRate(i
->rates
, 0)
210 | set11nRate(i
->rates
, 1)
211 | set11nRate(i
->rates
, 2)
212 | set11nRate(i
->rates
, 3);
214 ACCESS_ONCE(ads
->ds_ctl2
) = 0;
215 ACCESS_ONCE(ads
->ds_ctl3
) = 0;
219 ACCESS_ONCE(ads
->ds_ctl0
) = 0;
220 ACCESS_ONCE(ads
->ds_ctl1
) = ctl1
;
221 ACCESS_ONCE(ads
->ds_ctl6
) = ctl6
;
225 ctl1
|= (i
->keyix
!= ATH9K_TXKEYIX_INVALID
? SM(i
->keyix
, AR_DestIdx
) : 0)
226 | SM(i
->type
, AR_FrameType
)
227 | (i
->flags
& ATH9K_TXDESC_NOACK
? AR_NoAck
: 0)
228 | (i
->flags
& ATH9K_TXDESC_EXT_ONLY
? AR_ExtOnly
: 0)
229 | (i
->flags
& ATH9K_TXDESC_EXT_AND_CTL
? AR_ExtAndCtl
: 0);
233 ctl6
|= SM(i
->aggr_len
, AR_AggrLen
);
235 case AGGR_BUF_MIDDLE
:
236 ctl1
|= AR_IsAggr
| AR_MoreAggr
;
237 ctl6
|= SM(i
->ndelim
, AR_PadDelim
);
246 ACCESS_ONCE(ads
->ds_ctl0
) = (i
->pkt_len
& AR_FrameLen
)
247 | (i
->flags
& ATH9K_TXDESC_VMF
? AR_VirtMoreFrag
: 0)
248 | SM(i
->txpower
, AR_XmitPower
)
249 | (i
->flags
& ATH9K_TXDESC_VEOL
? AR_VEOL
: 0)
250 | (i
->flags
& ATH9K_TXDESC_INTREQ
? AR_TxIntrReq
: 0)
251 | (i
->keyix
!= ATH9K_TXKEYIX_INVALID
? AR_DestIdxValid
: 0)
252 | (i
->flags
& ATH9K_TXDESC_CLRDMASK
? AR_ClrDestMask
: 0)
253 | (i
->flags
& ATH9K_TXDESC_RTSENA
? AR_RTSEnable
:
254 (i
->flags
& ATH9K_TXDESC_CTSENA
? AR_CTSEnable
: 0));
256 ACCESS_ONCE(ads
->ds_ctl1
) = ctl1
;
257 ACCESS_ONCE(ads
->ds_ctl6
) = ctl6
;
259 if (i
->aggr
== AGGR_BUF_MIDDLE
|| i
->aggr
== AGGR_BUF_LAST
)
262 ACCESS_ONCE(ads
->ds_ctl4
) = set11nPktDurRTSCTS(i
->rates
, 0)
263 | set11nPktDurRTSCTS(i
->rates
, 1);
265 ACCESS_ONCE(ads
->ds_ctl5
) = set11nPktDurRTSCTS(i
->rates
, 2)
266 | set11nPktDurRTSCTS(i
->rates
, 3);
268 ACCESS_ONCE(ads
->ds_ctl7
) = set11nRateFlags(i
->rates
, 0)
269 | set11nRateFlags(i
->rates
, 1)
270 | set11nRateFlags(i
->rates
, 2)
271 | set11nRateFlags(i
->rates
, 3)
272 | SM(i
->rtscts_rate
, AR_RTSCTSRate
);
275 static int ar9002_hw_proc_txdesc(struct ath_hw
*ah
, void *ds
,
276 struct ath_tx_status
*ts
)
278 struct ar5416_desc
*ads
= AR5416DESC(ds
);
281 status
= ACCESS_ONCE(ads
->ds_txstatus9
);
282 if ((status
& AR_TxDone
) == 0)
285 ts
->ts_tstamp
= ads
->AR_SendTimestamp
;
289 if (status
& AR_TxOpExceeded
)
290 ts
->ts_status
|= ATH9K_TXERR_XTXOP
;
291 ts
->tid
= MS(status
, AR_TxTid
);
292 ts
->ts_rateindex
= MS(status
, AR_FinalTxIdx
);
293 ts
->ts_seqnum
= MS(status
, AR_SeqNum
);
295 status
= ACCESS_ONCE(ads
->ds_txstatus0
);
296 ts
->ts_rssi_ctl0
= MS(status
, AR_TxRSSIAnt00
);
297 ts
->ts_rssi_ctl1
= MS(status
, AR_TxRSSIAnt01
);
298 ts
->ts_rssi_ctl2
= MS(status
, AR_TxRSSIAnt02
);
299 if (status
& AR_TxBaStatus
) {
300 ts
->ts_flags
|= ATH9K_TX_BA
;
301 ts
->ba_low
= ads
->AR_BaBitmapLow
;
302 ts
->ba_high
= ads
->AR_BaBitmapHigh
;
305 status
= ACCESS_ONCE(ads
->ds_txstatus1
);
306 if (status
& AR_FrmXmitOK
)
307 ts
->ts_status
|= ATH9K_TX_ACKED
;
309 if (status
& AR_ExcessiveRetries
)
310 ts
->ts_status
|= ATH9K_TXERR_XRETRY
;
311 if (status
& AR_Filtered
)
312 ts
->ts_status
|= ATH9K_TXERR_FILT
;
313 if (status
& AR_FIFOUnderrun
) {
314 ts
->ts_status
|= ATH9K_TXERR_FIFO
;
315 ath9k_hw_updatetxtriglevel(ah
, true);
318 if (status
& AR_TxTimerExpired
)
319 ts
->ts_status
|= ATH9K_TXERR_TIMER_EXPIRED
;
320 if (status
& AR_DescCfgErr
)
321 ts
->ts_flags
|= ATH9K_TX_DESC_CFG_ERR
;
322 if (status
& AR_TxDataUnderrun
) {
323 ts
->ts_flags
|= ATH9K_TX_DATA_UNDERRUN
;
324 ath9k_hw_updatetxtriglevel(ah
, true);
326 if (status
& AR_TxDelimUnderrun
) {
327 ts
->ts_flags
|= ATH9K_TX_DELIM_UNDERRUN
;
328 ath9k_hw_updatetxtriglevel(ah
, true);
330 ts
->ts_shortretry
= MS(status
, AR_RTSFailCnt
);
331 ts
->ts_longretry
= MS(status
, AR_DataFailCnt
);
332 ts
->ts_virtcol
= MS(status
, AR_VirtRetryCnt
);
334 status
= ACCESS_ONCE(ads
->ds_txstatus5
);
335 ts
->ts_rssi
= MS(status
, AR_TxRSSICombined
);
336 ts
->ts_rssi_ext0
= MS(status
, AR_TxRSSIAnt10
);
337 ts
->ts_rssi_ext1
= MS(status
, AR_TxRSSIAnt11
);
338 ts
->ts_rssi_ext2
= MS(status
, AR_TxRSSIAnt12
);
340 ts
->evm0
= ads
->AR_TxEVM0
;
341 ts
->evm1
= ads
->AR_TxEVM1
;
342 ts
->evm2
= ads
->AR_TxEVM2
;
347 void ath9k_hw_setuprxdesc(struct ath_hw
*ah
, struct ath_desc
*ds
,
350 struct ar5416_desc
*ads
= AR5416DESC(ds
);
352 ads
->ds_ctl1
= size
& AR_BufLen
;
353 if (flags
& ATH9K_RXDESC_INTREQ
)
354 ads
->ds_ctl1
|= AR_RxIntrReq
;
356 memset(&ads
->u
.rx
, 0, sizeof(ads
->u
.rx
));
358 EXPORT_SYMBOL(ath9k_hw_setuprxdesc
);
360 void ar9002_hw_attach_mac_ops(struct ath_hw
*ah
)
362 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
364 ops
->rx_enable
= ar9002_hw_rx_enable
;
365 ops
->set_desc_link
= ar9002_hw_set_desc_link
;
366 ops
->get_isr
= ar9002_hw_get_isr
;
367 ops
->set_txdesc
= ar9002_set_txdesc
;
368 ops
->proc_txdesc
= ar9002_hw_proc_txdesc
;