2 * Copyright (c) 2008-2009 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 void ar9002_hw_get_desc_link(void *ds
, u32
**ds_link
)
33 *ds_link
= &((struct ath_desc
*)ds
)->ds_link
;
36 static bool ar9002_hw_get_isr(struct ath_hw
*ah
, enum ath9k_int
*masked
)
40 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
42 bool fatal_int
= false;
43 struct ath_common
*common
= ath9k_hw_common(ah
);
45 if (!AR_SREV_9100(ah
)) {
46 if (REG_READ(ah
, AR_INTR_ASYNC_CAUSE
) & AR_INTR_MAC_IRQ
) {
47 if ((REG_READ(ah
, AR_RTC_STATUS
) & AR_RTC_STATUS_M
)
48 == AR_RTC_STATUS_ON
) {
49 isr
= REG_READ(ah
, AR_ISR
);
53 sync_cause
= REG_READ(ah
, AR_INTR_SYNC_CAUSE
) &
58 if (!isr
&& !sync_cause
)
62 isr
= REG_READ(ah
, AR_ISR
);
66 if (isr
& AR_ISR_BCNMISC
) {
68 isr2
= REG_READ(ah
, AR_ISR_S2
);
69 if (isr2
& AR_ISR_S2_TIM
)
70 mask2
|= ATH9K_INT_TIM
;
71 if (isr2
& AR_ISR_S2_DTIM
)
72 mask2
|= ATH9K_INT_DTIM
;
73 if (isr2
& AR_ISR_S2_DTIMSYNC
)
74 mask2
|= ATH9K_INT_DTIMSYNC
;
75 if (isr2
& (AR_ISR_S2_CABEND
))
76 mask2
|= ATH9K_INT_CABEND
;
77 if (isr2
& AR_ISR_S2_GTT
)
78 mask2
|= ATH9K_INT_GTT
;
79 if (isr2
& AR_ISR_S2_CST
)
80 mask2
|= ATH9K_INT_CST
;
81 if (isr2
& AR_ISR_S2_TSFOOR
)
82 mask2
|= ATH9K_INT_TSFOOR
;
85 isr
= REG_READ(ah
, AR_ISR_RAC
);
86 if (isr
== 0xffffffff) {
91 *masked
= isr
& ATH9K_INT_COMMON
;
93 if (isr
& (AR_ISR_RXMINTR
| AR_ISR_RXINTM
|
94 AR_ISR_RXOK
| AR_ISR_RXERR
))
95 *masked
|= ATH9K_INT_RX
;
98 (AR_ISR_TXOK
| AR_ISR_TXDESC
| AR_ISR_TXERR
|
102 *masked
|= ATH9K_INT_TX
;
104 s0_s
= REG_READ(ah
, AR_ISR_S0_S
);
105 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXOK
);
106 ah
->intr_txqs
|= MS(s0_s
, AR_ISR_S0_QCU_TXDESC
);
108 s1_s
= REG_READ(ah
, AR_ISR_S1_S
);
109 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXERR
);
110 ah
->intr_txqs
|= MS(s1_s
, AR_ISR_S1_QCU_TXEOL
);
113 if (isr
& AR_ISR_RXORN
) {
114 ath_dbg(common
, ATH_DBG_INTERRUPT
,
115 "receive FIFO overrun interrupt\n");
121 if (AR_SREV_9100(ah
))
124 if (isr
& AR_ISR_GENTMR
) {
127 s5_s
= REG_READ(ah
, AR_ISR_S5_S
);
128 ah
->intr_gen_timer_trigger
=
129 MS(s5_s
, AR_ISR_S5_GENTIMER_TRIG
);
131 ah
->intr_gen_timer_thresh
=
132 MS(s5_s
, AR_ISR_S5_GENTIMER_THRESH
);
134 if (ah
->intr_gen_timer_trigger
)
135 *masked
|= ATH9K_INT_GENTIMER
;
137 if ((s5_s
& AR_ISR_S5_TIM_TIMER
) &&
138 !(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
139 *masked
|= ATH9K_INT_TIM_TIMER
;
145 (AR_INTR_SYNC_HOST1_FATAL
| AR_INTR_SYNC_HOST1_PERR
))
149 if (sync_cause
& AR_INTR_SYNC_HOST1_FATAL
) {
150 ath_dbg(common
, ATH_DBG_ANY
,
151 "received PCI FATAL interrupt\n");
153 if (sync_cause
& AR_INTR_SYNC_HOST1_PERR
) {
154 ath_dbg(common
, ATH_DBG_ANY
,
155 "received PCI PERR interrupt\n");
157 *masked
|= ATH9K_INT_FATAL
;
159 if (sync_cause
& AR_INTR_SYNC_RADM_CPL_TIMEOUT
) {
160 ath_dbg(common
, ATH_DBG_INTERRUPT
,
161 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
162 REG_WRITE(ah
, AR_RC
, AR_RC_HOSTIF
);
163 REG_WRITE(ah
, AR_RC
, 0);
164 *masked
|= ATH9K_INT_FATAL
;
166 if (sync_cause
& AR_INTR_SYNC_LOCAL_TIMEOUT
) {
167 ath_dbg(common
, ATH_DBG_INTERRUPT
,
168 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
171 REG_WRITE(ah
, AR_INTR_SYNC_CAUSE_CLR
, sync_cause
);
172 (void) REG_READ(ah
, AR_INTR_SYNC_CAUSE_CLR
);
178 static void ar9002_hw_fill_txdesc(struct ath_hw
*ah
, void *ds
, u32 seglen
,
179 bool is_firstseg
, bool is_lastseg
,
180 const void *ds0
, dma_addr_t buf_addr
,
183 struct ar5416_desc
*ads
= AR5416DESC(ds
);
185 ads
->ds_data
= buf_addr
;
188 ads
->ds_ctl1
|= seglen
| (is_lastseg
? 0 : AR_TxMore
);
189 } else if (is_lastseg
) {
191 ads
->ds_ctl1
= seglen
;
192 ads
->ds_ctl2
= AR5416DESC_CONST(ds0
)->ds_ctl2
;
193 ads
->ds_ctl3
= AR5416DESC_CONST(ds0
)->ds_ctl3
;
196 ads
->ds_ctl1
= seglen
| AR_TxMore
;
200 ads
->ds_txstatus0
= ads
->ds_txstatus1
= 0;
201 ads
->ds_txstatus2
= ads
->ds_txstatus3
= 0;
202 ads
->ds_txstatus4
= ads
->ds_txstatus5
= 0;
203 ads
->ds_txstatus6
= ads
->ds_txstatus7
= 0;
204 ads
->ds_txstatus8
= ads
->ds_txstatus9
= 0;
207 static int ar9002_hw_proc_txdesc(struct ath_hw
*ah
, void *ds
,
208 struct ath_tx_status
*ts
)
210 struct ar5416_desc
*ads
= AR5416DESC(ds
);
213 status
= ACCESS_ONCE(ads
->ds_txstatus9
);
214 if ((status
& AR_TxDone
) == 0)
217 ts
->ts_tstamp
= ads
->AR_SendTimestamp
;
221 if (status
& AR_TxOpExceeded
)
222 ts
->ts_status
|= ATH9K_TXERR_XTXOP
;
223 ts
->tid
= MS(status
, AR_TxTid
);
224 ts
->ts_rateindex
= MS(status
, AR_FinalTxIdx
);
225 ts
->ts_seqnum
= MS(status
, AR_SeqNum
);
227 status
= ACCESS_ONCE(ads
->ds_txstatus0
);
228 ts
->ts_rssi_ctl0
= MS(status
, AR_TxRSSIAnt00
);
229 ts
->ts_rssi_ctl1
= MS(status
, AR_TxRSSIAnt01
);
230 ts
->ts_rssi_ctl2
= MS(status
, AR_TxRSSIAnt02
);
231 if (status
& AR_TxBaStatus
) {
232 ts
->ts_flags
|= ATH9K_TX_BA
;
233 ts
->ba_low
= ads
->AR_BaBitmapLow
;
234 ts
->ba_high
= ads
->AR_BaBitmapHigh
;
237 status
= ACCESS_ONCE(ads
->ds_txstatus1
);
238 if (status
& AR_FrmXmitOK
)
239 ts
->ts_status
|= ATH9K_TX_ACKED
;
241 if (status
& AR_ExcessiveRetries
)
242 ts
->ts_status
|= ATH9K_TXERR_XRETRY
;
243 if (status
& AR_Filtered
)
244 ts
->ts_status
|= ATH9K_TXERR_FILT
;
245 if (status
& AR_FIFOUnderrun
) {
246 ts
->ts_status
|= ATH9K_TXERR_FIFO
;
247 ath9k_hw_updatetxtriglevel(ah
, true);
250 if (status
& AR_TxTimerExpired
)
251 ts
->ts_status
|= ATH9K_TXERR_TIMER_EXPIRED
;
252 if (status
& AR_DescCfgErr
)
253 ts
->ts_flags
|= ATH9K_TX_DESC_CFG_ERR
;
254 if (status
& AR_TxDataUnderrun
) {
255 ts
->ts_flags
|= ATH9K_TX_DATA_UNDERRUN
;
256 ath9k_hw_updatetxtriglevel(ah
, true);
258 if (status
& AR_TxDelimUnderrun
) {
259 ts
->ts_flags
|= ATH9K_TX_DELIM_UNDERRUN
;
260 ath9k_hw_updatetxtriglevel(ah
, true);
262 ts
->ts_shortretry
= MS(status
, AR_RTSFailCnt
);
263 ts
->ts_longretry
= MS(status
, AR_DataFailCnt
);
264 ts
->ts_virtcol
= MS(status
, AR_VirtRetryCnt
);
266 status
= ACCESS_ONCE(ads
->ds_txstatus5
);
267 ts
->ts_rssi
= MS(status
, AR_TxRSSICombined
);
268 ts
->ts_rssi_ext0
= MS(status
, AR_TxRSSIAnt10
);
269 ts
->ts_rssi_ext1
= MS(status
, AR_TxRSSIAnt11
);
270 ts
->ts_rssi_ext2
= MS(status
, AR_TxRSSIAnt12
);
272 ts
->evm0
= ads
->AR_TxEVM0
;
273 ts
->evm1
= ads
->AR_TxEVM1
;
274 ts
->evm2
= ads
->AR_TxEVM2
;
279 static void ar9002_hw_set11n_txdesc(struct ath_hw
*ah
, void *ds
,
280 u32 pktLen
, enum ath9k_pkt_type type
,
281 u32 txPower
, u32 keyIx
,
282 enum ath9k_key_type keyType
, u32 flags
)
284 struct ar5416_desc
*ads
= AR5416DESC(ds
);
289 ads
->ds_ctl0
= (pktLen
& AR_FrameLen
)
290 | (flags
& ATH9K_TXDESC_VMF
? AR_VirtMoreFrag
: 0)
291 | SM(txPower
, AR_XmitPower
)
292 | (flags
& ATH9K_TXDESC_VEOL
? AR_VEOL
: 0)
293 | (flags
& ATH9K_TXDESC_CLRDMASK
? AR_ClrDestMask
: 0)
294 | (flags
& ATH9K_TXDESC_INTREQ
? AR_TxIntrReq
: 0)
295 | (keyIx
!= ATH9K_TXKEYIX_INVALID
? AR_DestIdxValid
: 0);
298 (keyIx
!= ATH9K_TXKEYIX_INVALID
? SM(keyIx
, AR_DestIdx
) : 0)
299 | SM(type
, AR_FrameType
)
300 | (flags
& ATH9K_TXDESC_NOACK
? AR_NoAck
: 0)
301 | (flags
& ATH9K_TXDESC_EXT_ONLY
? AR_ExtOnly
: 0)
302 | (flags
& ATH9K_TXDESC_EXT_AND_CTL
? AR_ExtAndCtl
: 0);
304 ads
->ds_ctl6
= SM(keyType
, AR_EncrType
);
306 if (AR_SREV_9285(ah
) || AR_SREV_9271(ah
)) {
314 static void ar9002_hw_set11n_ratescenario(struct ath_hw
*ah
, void *ds
,
316 u32 durUpdateEn
, u32 rtsctsRate
,
318 struct ath9k_11n_rate_series series
[],
319 u32 nseries
, u32 flags
)
321 struct ar5416_desc
*ads
= AR5416DESC(ds
);
322 struct ar5416_desc
*last_ads
= AR5416DESC(lastds
);
325 if (flags
& (ATH9K_TXDESC_RTSENA
| ATH9K_TXDESC_CTSENA
)) {
326 ds_ctl0
= ads
->ds_ctl0
;
328 if (flags
& ATH9K_TXDESC_RTSENA
) {
329 ds_ctl0
&= ~AR_CTSEnable
;
330 ds_ctl0
|= AR_RTSEnable
;
332 ds_ctl0
&= ~AR_RTSEnable
;
333 ds_ctl0
|= AR_CTSEnable
;
336 ads
->ds_ctl0
= ds_ctl0
;
339 (ads
->ds_ctl0
& ~(AR_RTSEnable
| AR_CTSEnable
));
342 ads
->ds_ctl2
= set11nTries(series
, 0)
343 | set11nTries(series
, 1)
344 | set11nTries(series
, 2)
345 | set11nTries(series
, 3)
346 | (durUpdateEn
? AR_DurUpdateEna
: 0)
347 | SM(0, AR_BurstDur
);
349 ads
->ds_ctl3
= set11nRate(series
, 0)
350 | set11nRate(series
, 1)
351 | set11nRate(series
, 2)
352 | set11nRate(series
, 3);
354 ads
->ds_ctl4
= set11nPktDurRTSCTS(series
, 0)
355 | set11nPktDurRTSCTS(series
, 1);
357 ads
->ds_ctl5
= set11nPktDurRTSCTS(series
, 2)
358 | set11nPktDurRTSCTS(series
, 3);
360 ads
->ds_ctl7
= set11nRateFlags(series
, 0)
361 | set11nRateFlags(series
, 1)
362 | set11nRateFlags(series
, 2)
363 | set11nRateFlags(series
, 3)
364 | SM(rtsctsRate
, AR_RTSCTSRate
);
365 last_ads
->ds_ctl2
= ads
->ds_ctl2
;
366 last_ads
->ds_ctl3
= ads
->ds_ctl3
;
369 static void ar9002_hw_set11n_aggr_first(struct ath_hw
*ah
, void *ds
,
372 struct ar5416_desc
*ads
= AR5416DESC(ds
);
374 ads
->ds_ctl1
|= (AR_IsAggr
| AR_MoreAggr
);
375 ads
->ds_ctl6
&= ~AR_AggrLen
;
376 ads
->ds_ctl6
|= SM(aggrLen
, AR_AggrLen
);
379 static void ar9002_hw_set11n_aggr_middle(struct ath_hw
*ah
, void *ds
,
382 struct ar5416_desc
*ads
= AR5416DESC(ds
);
385 ads
->ds_ctl1
|= (AR_IsAggr
| AR_MoreAggr
);
388 ctl6
&= ~AR_PadDelim
;
389 ctl6
|= SM(numDelims
, AR_PadDelim
);
393 static void ar9002_hw_set11n_aggr_last(struct ath_hw
*ah
, void *ds
)
395 struct ar5416_desc
*ads
= AR5416DESC(ds
);
397 ads
->ds_ctl1
|= AR_IsAggr
;
398 ads
->ds_ctl1
&= ~AR_MoreAggr
;
399 ads
->ds_ctl6
&= ~AR_PadDelim
;
402 static void ar9002_hw_clr11n_aggr(struct ath_hw
*ah
, void *ds
)
404 struct ar5416_desc
*ads
= AR5416DESC(ds
);
406 ads
->ds_ctl1
&= (~AR_IsAggr
& ~AR_MoreAggr
);
409 static void ar9002_hw_set11n_burstduration(struct ath_hw
*ah
, void *ds
,
412 struct ar5416_desc
*ads
= AR5416DESC(ds
);
414 ads
->ds_ctl2
&= ~AR_BurstDur
;
415 ads
->ds_ctl2
|= SM(burstDuration
, AR_BurstDur
);
418 static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw
*ah
, void *ds
,
421 struct ar5416_desc
*ads
= AR5416DESC(ds
);
424 ads
->ds_ctl0
|= AR_VirtMoreFrag
;
426 ads
->ds_ctl0
&= ~AR_VirtMoreFrag
;
429 void ath9k_hw_setuprxdesc(struct ath_hw
*ah
, struct ath_desc
*ds
,
432 struct ar5416_desc
*ads
= AR5416DESC(ds
);
433 struct ath9k_hw_capabilities
*pCap
= &ah
->caps
;
435 ads
->ds_ctl1
= size
& AR_BufLen
;
436 if (flags
& ATH9K_RXDESC_INTREQ
)
437 ads
->ds_ctl1
|= AR_RxIntrReq
;
439 ads
->ds_rxstatus8
&= ~AR_RxDone
;
440 if (!(pCap
->hw_caps
& ATH9K_HW_CAP_AUTOSLEEP
))
441 memset(&(ads
->u
), 0, sizeof(ads
->u
));
443 EXPORT_SYMBOL(ath9k_hw_setuprxdesc
);
445 void ar9002_hw_attach_mac_ops(struct ath_hw
*ah
)
447 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
449 ops
->rx_enable
= ar9002_hw_rx_enable
;
450 ops
->set_desc_link
= ar9002_hw_set_desc_link
;
451 ops
->get_desc_link
= ar9002_hw_get_desc_link
;
452 ops
->get_isr
= ar9002_hw_get_isr
;
453 ops
->fill_txdesc
= ar9002_hw_fill_txdesc
;
454 ops
->proc_txdesc
= ar9002_hw_proc_txdesc
;
455 ops
->set11n_txdesc
= ar9002_hw_set11n_txdesc
;
456 ops
->set11n_ratescenario
= ar9002_hw_set11n_ratescenario
;
457 ops
->set11n_aggr_first
= ar9002_hw_set11n_aggr_first
;
458 ops
->set11n_aggr_middle
= ar9002_hw_set11n_aggr_middle
;
459 ops
->set11n_aggr_last
= ar9002_hw_set11n_aggr_last
;
460 ops
->clr11n_aggr
= ar9002_hw_clr11n_aggr
;
461 ops
->set11n_burstduration
= ar9002_hw_set11n_burstduration
;
462 ops
->set11n_virtualmorefrag
= ar9002_hw_set11n_virtualmorefrag
;