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.
19 #define AR_BufLen 0x00000fff
21 static void ar9002_hw_rx_enable(struct ath_hw
*ah
)
23 REG_WRITE(ah
, AR_CR
, AR_CR_RXE
);
26 static void ar9002_hw_set_desc_link(void *ds
, u32 ds_link
)
28 ((struct ath_desc
*) ds
)->ds_link
= ds_link
;
31 static bool ar9002_hw_get_isr(struct ath_hw
*ah
, enum ath9k_int
*masked
)
35 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
37 bool fatal_int
= false;
38 struct ath_common
*common
= ath9k_hw_common(ah
);
40 if (!AR_SREV_9100(ah
)) {
41 if (REG_READ(ah
, AR_INTR_ASYNC_CAUSE
) & AR_INTR_MAC_IRQ
) {
42 if ((REG_READ(ah
, AR_RTC_STATUS
) & AR_RTC_STATUS_M
)
43 == AR_RTC_STATUS_ON
) {
44 isr
= REG_READ(ah
, AR_ISR
);
48 sync_cause
= REG_READ(ah
, AR_INTR_SYNC_CAUSE
) &
53 if (!isr
&& !sync_cause
)
57 isr
= REG_READ(ah
, AR_ISR
);
61 if (isr
& AR_ISR_BCNMISC
) {
63 isr2
= REG_READ(ah
, AR_ISR_S2
);
64 if (isr2
& AR_ISR_S2_TIM
)
65 mask2
|= ATH9K_INT_TIM
;
66 if (isr2
& AR_ISR_S2_DTIM
)
67 mask2
|= ATH9K_INT_DTIM
;
68 if (isr2
& AR_ISR_S2_DTIMSYNC
)
69 mask2
|= ATH9K_INT_DTIMSYNC
;
70 if (isr2
& (AR_ISR_S2_CABEND
))
71 mask2
|= ATH9K_INT_CABEND
;
72 if (isr2
& AR_ISR_S2_GTT
)
73 mask2
|= ATH9K_INT_GTT
;
74 if (isr2
& AR_ISR_S2_CST
)
75 mask2
|= ATH9K_INT_CST
;
76 if (isr2
& AR_ISR_S2_TSFOOR
)
77 mask2
|= ATH9K_INT_TSFOOR
;
80 isr
= REG_READ(ah
, AR_ISR_RAC
);
81 if (isr
== 0xffffffff) {
86 *masked
= isr
& ATH9K_INT_COMMON
;
88 if (isr
& (AR_ISR_RXMINTR
| AR_ISR_RXINTM
|
89 AR_ISR_RXOK
| AR_ISR_RXERR
))
90 *masked
|= ATH9K_INT_RX
;
93 (AR_ISR_TXOK
| AR_ISR_TXDESC
| AR_ISR_TXERR
|
97 *masked
|= ATH9K_INT_TX
;
99 s0_s
= REG_READ(ah
, AR_ISR_S0_S
);
100 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXOK
);
101 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXDESC
);
103 s1_s
= REG_READ(ah
, AR_ISR_S1_S
);
104 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXERR
);
105 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXEOL
);
108 if (isr
& AR_ISR_RXORN
) {
109 ath_dbg(common
, ATH_DBG_INTERRUPT
,
110 "receive FIFO overrun interrupt\n");
116 if (AR_SREV_9100(ah
))
119 if (isr
& AR_ISR_GENTMR
) {
122 s5_s
= REG_READ(ah
, AR_ISR_S5_S
);
123 ah
->intr_gen_timer_trigger
=
124 MS(s5_s
, AR_ISR_S5_GENTIMER_TRIG
);
126 ah
->intr_gen_timer_thresh
=
127 MS(s5_s
, AR_ISR_S5_GENTIMER_THRESH
);
129 if (ah
->intr_gen_timer_trigger
)
130 *masked
|= ATH9K_INT_GENTIMER
;
132 if ((s5_s
& AR_ISR_S5_TIM_TIMER
) &&
133 !(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
134 *masked
|= ATH9K_INT_TIM_TIMER
;
140 (AR_INTR_SYNC_HOST1_FATAL
| AR_INTR_SYNC_HOST1_PERR
))
144 if (sync_cause
& AR_INTR_SYNC_HOST1_FATAL
) {
145 ath_dbg(common
, ATH_DBG_ANY
,
146 "received PCI FATAL interrupt\n");
148 if (sync_cause
& AR_INTR_SYNC_HOST1_PERR
) {
149 ath_dbg(common
, ATH_DBG_ANY
,
150 "received PCI PERR interrupt\n");
152 *masked
|= ATH9K_INT_FATAL
;
154 if (sync_cause
& AR_INTR_SYNC_RADM_CPL_TIMEOUT
) {
155 ath_dbg(common
, ATH_DBG_INTERRUPT
,
156 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
157 REG_WRITE(ah
, AR_RC
, AR_RC_HOSTIF
);
158 REG_WRITE(ah
, AR_RC
, 0);
159 *masked
|= ATH9K_INT_FATAL
;
161 if (sync_cause
& AR_INTR_SYNC_LOCAL_TIMEOUT
) {
162 ath_dbg(common
, ATH_DBG_INTERRUPT
,
163 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
166 REG_WRITE(ah
, AR_INTR_SYNC_CAUSE_CLR
, sync_cause
);
167 (void) REG_READ(ah
, AR_INTR_SYNC_CAUSE_CLR
);
173 static void ar9002_hw_fill_txdesc(struct ath_hw
*ah
, void *ds
, u32 seglen
,
174 bool is_firstseg
, bool is_lastseg
,
175 const void *ds0
, dma_addr_t buf_addr
,
178 struct ar5416_desc
*ads
= AR5416DESC(ds
);
180 ads
->ds_data
= buf_addr
;
183 ads
->ds_ctl1
|= seglen
| (is_lastseg
? 0 : AR_TxMore
);
184 } else if (is_lastseg
) {
186 ads
->ds_ctl1
= seglen
;
187 ads
->ds_ctl2
= AR5416DESC_CONST(ds0
)->ds_ctl2
;
188 ads
->ds_ctl3
= AR5416DESC_CONST(ds0
)->ds_ctl3
;
191 ads
->ds_ctl1
= seglen
| AR_TxMore
;
195 ads
->ds_txstatus0
= ads
->ds_txstatus1
= 0;
196 ads
->ds_txstatus2
= ads
->ds_txstatus3
= 0;
197 ads
->ds_txstatus4
= ads
->ds_txstatus5
= 0;
198 ads
->ds_txstatus6
= ads
->ds_txstatus7
= 0;
199 ads
->ds_txstatus8
= ads
->ds_txstatus9
= 0;
202 static int ar9002_hw_proc_txdesc(struct ath_hw
*ah
, void *ds
,
203 struct ath_tx_status
*ts
)
205 struct ar5416_desc
*ads
= AR5416DESC(ds
);
208 status
= ACCESS_ONCE(ads
->ds_txstatus9
);
209 if ((status
& AR_TxDone
) == 0)
212 ts
->ts_tstamp
= ads
->AR_SendTimestamp
;
216 if (status
& AR_TxOpExceeded
)
217 ts
->ts_status
|= ATH9K_TXERR_XTXOP
;
218 ts
->tid
= MS(status
, AR_TxTid
);
219 ts
->ts_rateindex
= MS(status
, AR_FinalTxIdx
);
220 ts
->ts_seqnum
= MS(status
, AR_SeqNum
);
222 status
= ACCESS_ONCE(ads
->ds_txstatus0
);
223 ts
->ts_rssi_ctl0
= MS(status
, AR_TxRSSIAnt00
);
224 ts
->ts_rssi_ctl1
= MS(status
, AR_TxRSSIAnt01
);
225 ts
->ts_rssi_ctl2
= MS(status
, AR_TxRSSIAnt02
);
226 if (status
& AR_TxBaStatus
) {
227 ts
->ts_flags
|= ATH9K_TX_BA
;
228 ts
->ba_low
= ads
->AR_BaBitmapLow
;
229 ts
->ba_high
= ads
->AR_BaBitmapHigh
;
232 status
= ACCESS_ONCE(ads
->ds_txstatus1
);
233 if (status
& AR_FrmXmitOK
)
234 ts
->ts_status
|= ATH9K_TX_ACKED
;
236 if (status
& AR_ExcessiveRetries
)
237 ts
->ts_status
|= ATH9K_TXERR_XRETRY
;
238 if (status
& AR_Filtered
)
239 ts
->ts_status
|= ATH9K_TXERR_FILT
;
240 if (status
& AR_FIFOUnderrun
) {
241 ts
->ts_status
|= ATH9K_TXERR_FIFO
;
242 ath9k_hw_updatetxtriglevel(ah
, true);
245 if (status
& AR_TxTimerExpired
)
246 ts
->ts_status
|= ATH9K_TXERR_TIMER_EXPIRED
;
247 if (status
& AR_DescCfgErr
)
248 ts
->ts_flags
|= ATH9K_TX_DESC_CFG_ERR
;
249 if (status
& AR_TxDataUnderrun
) {
250 ts
->ts_flags
|= ATH9K_TX_DATA_UNDERRUN
;
251 ath9k_hw_updatetxtriglevel(ah
, true);
253 if (status
& AR_TxDelimUnderrun
) {
254 ts
->ts_flags
|= ATH9K_TX_DELIM_UNDERRUN
;
255 ath9k_hw_updatetxtriglevel(ah
, true);
257 ts
->ts_shortretry
= MS(status
, AR_RTSFailCnt
);
258 ts
->ts_longretry
= MS(status
, AR_DataFailCnt
);
259 ts
->ts_virtcol
= MS(status
, AR_VirtRetryCnt
);
261 status
= ACCESS_ONCE(ads
->ds_txstatus5
);
262 ts
->ts_rssi
= MS(status
, AR_TxRSSICombined
);
263 ts
->ts_rssi_ext0
= MS(status
, AR_TxRSSIAnt10
);
264 ts
->ts_rssi_ext1
= MS(status
, AR_TxRSSIAnt11
);
265 ts
->ts_rssi_ext2
= MS(status
, AR_TxRSSIAnt12
);
267 ts
->evm0
= ads
->AR_TxEVM0
;
268 ts
->evm1
= ads
->AR_TxEVM1
;
269 ts
->evm2
= ads
->AR_TxEVM2
;
274 static void ar9002_hw_set11n_txdesc(struct ath_hw
*ah
, void *ds
,
275 u32 pktLen
, enum ath9k_pkt_type type
,
276 u32 txPower
, u32 keyIx
,
277 enum ath9k_key_type keyType
, u32 flags
)
279 struct ar5416_desc
*ads
= AR5416DESC(ds
);
284 ads
->ds_ctl0
= (pktLen
& AR_FrameLen
)
285 | (flags
& ATH9K_TXDESC_VMF
? AR_VirtMoreFrag
: 0)
286 | SM(txPower
, AR_XmitPower
)
287 | (flags
& ATH9K_TXDESC_VEOL
? AR_VEOL
: 0)
288 | (flags
& ATH9K_TXDESC_INTREQ
? AR_TxIntrReq
: 0)
289 | (keyIx
!= ATH9K_TXKEYIX_INVALID
? AR_DestIdxValid
: 0);
292 (keyIx
!= ATH9K_TXKEYIX_INVALID
? SM(keyIx
, AR_DestIdx
) : 0)
293 | SM(type
, AR_FrameType
)
294 | (flags
& ATH9K_TXDESC_NOACK
? AR_NoAck
: 0)
295 | (flags
& ATH9K_TXDESC_EXT_ONLY
? AR_ExtOnly
: 0)
296 | (flags
& ATH9K_TXDESC_EXT_AND_CTL
? AR_ExtAndCtl
: 0);
298 ads
->ds_ctl6
= SM(keyType
, AR_EncrType
);
300 if (AR_SREV_9285(ah
) || AR_SREV_9271(ah
)) {
308 static void ar9002_hw_set_clrdmask(struct ath_hw
*ah
, void *ds
, bool val
)
310 struct ar5416_desc
*ads
= AR5416DESC(ds
);
313 ads
->ds_ctl0
|= AR_ClrDestMask
;
315 ads
->ds_ctl0
&= ~AR_ClrDestMask
;
318 static void ar9002_hw_set11n_ratescenario(struct ath_hw
*ah
, void *ds
,
320 u32 durUpdateEn
, u32 rtsctsRate
,
322 struct ath9k_11n_rate_series series
[],
323 u32 nseries
, u32 flags
)
325 struct ar5416_desc
*ads
= AR5416DESC(ds
);
326 struct ar5416_desc
*last_ads
= AR5416DESC(lastds
);
329 if (flags
& (ATH9K_TXDESC_RTSENA
| ATH9K_TXDESC_CTSENA
)) {
330 ds_ctl0
= ads
->ds_ctl0
;
332 if (flags
& ATH9K_TXDESC_RTSENA
) {
333 ds_ctl0
&= ~AR_CTSEnable
;
334 ds_ctl0
|= AR_RTSEnable
;
336 ds_ctl0
&= ~AR_RTSEnable
;
337 ds_ctl0
|= AR_CTSEnable
;
340 ads
->ds_ctl0
= ds_ctl0
;
343 (ads
->ds_ctl0
& ~(AR_RTSEnable
| AR_CTSEnable
));
346 ads
->ds_ctl2
= set11nTries(series
, 0)
347 | set11nTries(series
, 1)
348 | set11nTries(series
, 2)
349 | set11nTries(series
, 3)
350 | (durUpdateEn
? AR_DurUpdateEna
: 0)
351 | SM(0, AR_BurstDur
);
353 ads
->ds_ctl3
= set11nRate(series
, 0)
354 | set11nRate(series
, 1)
355 | set11nRate(series
, 2)
356 | set11nRate(series
, 3);
358 ads
->ds_ctl4
= set11nPktDurRTSCTS(series
, 0)
359 | set11nPktDurRTSCTS(series
, 1);
361 ads
->ds_ctl5
= set11nPktDurRTSCTS(series
, 2)
362 | set11nPktDurRTSCTS(series
, 3);
364 ads
->ds_ctl7
= set11nRateFlags(series
, 0)
365 | set11nRateFlags(series
, 1)
366 | set11nRateFlags(series
, 2)
367 | set11nRateFlags(series
, 3)
368 | SM(rtsctsRate
, AR_RTSCTSRate
);
369 last_ads
->ds_ctl2
= ads
->ds_ctl2
;
370 last_ads
->ds_ctl3
= ads
->ds_ctl3
;
373 static void ar9002_hw_set11n_aggr_first(struct ath_hw
*ah
, void *ds
,
376 struct ar5416_desc
*ads
= AR5416DESC(ds
);
378 ads
->ds_ctl1
|= (AR_IsAggr
| AR_MoreAggr
);
379 ads
->ds_ctl6
&= ~AR_AggrLen
;
380 ads
->ds_ctl6
|= SM(aggrLen
, AR_AggrLen
);
383 static void ar9002_hw_set11n_aggr_middle(struct ath_hw
*ah
, void *ds
,
386 struct ar5416_desc
*ads
= AR5416DESC(ds
);
389 ads
->ds_ctl1
|= (AR_IsAggr
| AR_MoreAggr
);
392 ctl6
&= ~AR_PadDelim
;
393 ctl6
|= SM(numDelims
, AR_PadDelim
);
397 static void ar9002_hw_set11n_aggr_last(struct ath_hw
*ah
, void *ds
)
399 struct ar5416_desc
*ads
= AR5416DESC(ds
);
401 ads
->ds_ctl1
|= AR_IsAggr
;
402 ads
->ds_ctl1
&= ~AR_MoreAggr
;
403 ads
->ds_ctl6
&= ~AR_PadDelim
;
406 static void ar9002_hw_clr11n_aggr(struct ath_hw
*ah
, void *ds
)
408 struct ar5416_desc
*ads
= AR5416DESC(ds
);
410 ads
->ds_ctl1
&= (~AR_IsAggr
& ~AR_MoreAggr
);
413 void ath9k_hw_setuprxdesc(struct ath_hw
*ah
, struct ath_desc
*ds
,
416 struct ar5416_desc
*ads
= AR5416DESC(ds
);
417 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
419 ads
->ds_ctl1
= size
& AR_BufLen
;
420 if (flags
& ATH9K_RXDESC_INTREQ
)
421 ads
->ds_ctl1
|= AR_RxIntrReq
;
423 ads
->ds_rxstatus8
&= ~AR_RxDone
;
424 if (!(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
425 memset(&(ads
->u
), 0, sizeof(ads
->u
));
427 EXPORT_SYMBOL(ath9k_hw_setuprxdesc
);
429 void ar9002_hw_attach_mac_ops(struct ath_hw
*ah
)
431 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
433 ops
->rx_enable
= ar9002_hw_rx_enable
;
434 ops
->set_desc_link
= ar9002_hw_set_desc_link
;
435 ops
->get_isr
= ar9002_hw_get_isr
;
436 ops
->fill_txdesc
= ar9002_hw_fill_txdesc
;
437 ops
->proc_txdesc
= ar9002_hw_proc_txdesc
;
438 ops
->set11n_txdesc
= ar9002_hw_set11n_txdesc
;
439 ops
->set11n_ratescenario
= ar9002_hw_set11n_ratescenario
;
440 ops
->set11n_aggr_first
= ar9002_hw_set11n_aggr_first
;
441 ops
->set11n_aggr_middle
= ar9002_hw_set11n_aggr_middle
;
442 ops
->set11n_aggr_last
= ar9002_hw_set11n_aggr_last
;
443 ops
->clr11n_aggr
= ar9002_hw_clr11n_aggr
;
444 ops
->set_clrdmask
= ar9002_hw_set_clrdmask
;