18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "hw.h" 188c2ecf20Sopenharmony_ci#include <linux/export.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define AR_BufLen 0x00000fff 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic void ar9002_hw_rx_enable(struct ath_hw *ah) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_CR, AR_CR_RXE); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void ar9002_hw_set_desc_link(void *ds, u32 ds_link) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci ((struct ath_desc*) ds)->ds_link = ds_link; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, 338c2ecf20Sopenharmony_ci u32 *sync_cause_p) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci u32 isr = 0; 368c2ecf20Sopenharmony_ci u32 mask2 = 0; 378c2ecf20Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 388c2ecf20Sopenharmony_ci u32 sync_cause = 0; 398c2ecf20Sopenharmony_ci bool fatal_int = false; 408c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (!AR_SREV_9100(ah)) { 438c2ecf20Sopenharmony_ci if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { 448c2ecf20Sopenharmony_ci if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) 458c2ecf20Sopenharmony_ci == AR_RTC_STATUS_ON) { 468c2ecf20Sopenharmony_ci isr = REG_READ(ah, AR_ISR); 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & 518c2ecf20Sopenharmony_ci AR_INTR_SYNC_DEFAULT; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci *masked = 0; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (!isr && !sync_cause) 568c2ecf20Sopenharmony_ci return false; 578c2ecf20Sopenharmony_ci } else { 588c2ecf20Sopenharmony_ci *masked = 0; 598c2ecf20Sopenharmony_ci isr = REG_READ(ah, AR_ISR); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (isr) { 638c2ecf20Sopenharmony_ci if (isr & AR_ISR_BCNMISC) { 648c2ecf20Sopenharmony_ci u32 isr2; 658c2ecf20Sopenharmony_ci isr2 = REG_READ(ah, AR_ISR_S2); 668c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_TIM) 678c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_TIM; 688c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_DTIM) 698c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_DTIM; 708c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_DTIMSYNC) 718c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_DTIMSYNC; 728c2ecf20Sopenharmony_ci if (isr2 & (AR_ISR_S2_CABEND)) 738c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_CABEND; 748c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_GTT) 758c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_GTT; 768c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_CST) 778c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_CST; 788c2ecf20Sopenharmony_ci if (isr2 & AR_ISR_S2_TSFOOR) 798c2ecf20Sopenharmony_ci mask2 |= ATH9K_INT_TSFOOR; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 828c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S2, isr2); 838c2ecf20Sopenharmony_ci isr &= ~AR_ISR_BCNMISC; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) 888c2ecf20Sopenharmony_ci isr = REG_READ(ah, AR_ISR_RAC); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (isr == 0xffffffff) { 918c2ecf20Sopenharmony_ci *masked = 0; 928c2ecf20Sopenharmony_ci return false; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci *masked = isr & ATH9K_INT_COMMON; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM | 988c2ecf20Sopenharmony_ci AR_ISR_RXOK | AR_ISR_RXERR)) 998c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_RX; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (isr & 1028c2ecf20Sopenharmony_ci (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | 1038c2ecf20Sopenharmony_ci AR_ISR_TXEOL)) { 1048c2ecf20Sopenharmony_ci u32 s0_s, s1_s; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_TX; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { 1098c2ecf20Sopenharmony_ci s0_s = REG_READ(ah, AR_ISR_S0_S); 1108c2ecf20Sopenharmony_ci s1_s = REG_READ(ah, AR_ISR_S1_S); 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci s0_s = REG_READ(ah, AR_ISR_S0); 1138c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S0, s0_s); 1148c2ecf20Sopenharmony_ci s1_s = REG_READ(ah, AR_ISR_S1); 1158c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S1, s1_s); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci isr &= ~(AR_ISR_TXOK | 1188c2ecf20Sopenharmony_ci AR_ISR_TXDESC | 1198c2ecf20Sopenharmony_ci AR_ISR_TXERR | 1208c2ecf20Sopenharmony_ci AR_ISR_TXEOL); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); 1248c2ecf20Sopenharmony_ci ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); 1258c2ecf20Sopenharmony_ci ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); 1268c2ecf20Sopenharmony_ci ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (isr & AR_ISR_RXORN) { 1308c2ecf20Sopenharmony_ci ath_dbg(common, INTERRUPT, 1318c2ecf20Sopenharmony_ci "receive FIFO overrun interrupt\n"); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci *masked |= mask2; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) { 1388c2ecf20Sopenharmony_ci u32 s5_s; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { 1418c2ecf20Sopenharmony_ci s5_s = REG_READ(ah, AR_ISR_S5_S); 1428c2ecf20Sopenharmony_ci } else { 1438c2ecf20Sopenharmony_ci s5_s = REG_READ(ah, AR_ISR_S5); 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci ah->intr_gen_timer_trigger = 1478c2ecf20Sopenharmony_ci MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci ah->intr_gen_timer_thresh = 1508c2ecf20Sopenharmony_ci MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (ah->intr_gen_timer_trigger) 1538c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_GENTIMER; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if ((s5_s & AR_ISR_S5_TIM_TIMER) && 1568c2ecf20Sopenharmony_ci !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) 1578c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_TIM_TIMER; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 1608c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S5, s5_s); 1618c2ecf20Sopenharmony_ci isr &= ~AR_ISR_GENTMR; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 1668c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR, isr); 1678c2ecf20Sopenharmony_ci REG_READ(ah, AR_ISR); 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (AR_SREV_9100(ah)) 1718c2ecf20Sopenharmony_ci return true; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (sync_cause) { 1748c2ecf20Sopenharmony_ci if (sync_cause_p) 1758c2ecf20Sopenharmony_ci *sync_cause_p = sync_cause; 1768c2ecf20Sopenharmony_ci fatal_int = 1778c2ecf20Sopenharmony_ci (sync_cause & 1788c2ecf20Sopenharmony_ci (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) 1798c2ecf20Sopenharmony_ci ? true : false; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (fatal_int) { 1828c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { 1838c2ecf20Sopenharmony_ci ath_dbg(common, ANY, 1848c2ecf20Sopenharmony_ci "received PCI FATAL interrupt\n"); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { 1878c2ecf20Sopenharmony_ci ath_dbg(common, ANY, 1888c2ecf20Sopenharmony_ci "received PCI PERR interrupt\n"); 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { 1938c2ecf20Sopenharmony_ci ath_dbg(common, INTERRUPT, 1948c2ecf20Sopenharmony_ci "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); 1958c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); 1968c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_RC, 0); 1978c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { 2008c2ecf20Sopenharmony_ci ath_dbg(common, INTERRUPT, 2018c2ecf20Sopenharmony_ci "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); 2058c2ecf20Sopenharmony_ci (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return true; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void 2128c2ecf20Sopenharmony_ciar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci struct ar5416_desc *ads = AR5416DESC(ds); 2158c2ecf20Sopenharmony_ci u32 ctl1, ctl6; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci ads->ds_txstatus0 = ads->ds_txstatus1 = 0; 2188c2ecf20Sopenharmony_ci ads->ds_txstatus2 = ads->ds_txstatus3 = 0; 2198c2ecf20Sopenharmony_ci ads->ds_txstatus4 = ads->ds_txstatus5 = 0; 2208c2ecf20Sopenharmony_ci ads->ds_txstatus6 = ads->ds_txstatus7 = 0; 2218c2ecf20Sopenharmony_ci ads->ds_txstatus8 = ads->ds_txstatus9 = 0; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_link, i->link); 2248c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_data, i->buf_addr[0]); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore); 2278c2ecf20Sopenharmony_ci ctl6 = SM(i->keytype, AR_EncrType); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (AR_SREV_9285(ah)) { 2308c2ecf20Sopenharmony_ci ads->ds_ctl8 = 0; 2318c2ecf20Sopenharmony_ci ads->ds_ctl9 = 0; 2328c2ecf20Sopenharmony_ci ads->ds_ctl10 = 0; 2338c2ecf20Sopenharmony_ci ads->ds_ctl11 = 0; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if ((i->is_first || i->is_last) && 2378c2ecf20Sopenharmony_ci i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) { 2388c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl2, set11nTries(i->rates, 0) 2398c2ecf20Sopenharmony_ci | set11nTries(i->rates, 1) 2408c2ecf20Sopenharmony_ci | set11nTries(i->rates, 2) 2418c2ecf20Sopenharmony_ci | set11nTries(i->rates, 3) 2428c2ecf20Sopenharmony_ci | (i->dur_update ? AR_DurUpdateEna : 0) 2438c2ecf20Sopenharmony_ci | SM(0, AR_BurstDur)); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl3, set11nRate(i->rates, 0) 2468c2ecf20Sopenharmony_ci | set11nRate(i->rates, 1) 2478c2ecf20Sopenharmony_ci | set11nRate(i->rates, 2) 2488c2ecf20Sopenharmony_ci | set11nRate(i->rates, 3)); 2498c2ecf20Sopenharmony_ci } else { 2508c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl2, 0); 2518c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl3, 0); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (!i->is_first) { 2558c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl0, 0); 2568c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl1, ctl1); 2578c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl6, ctl6); 2588c2ecf20Sopenharmony_ci return; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0) 2628c2ecf20Sopenharmony_ci | SM(i->type, AR_FrameType) 2638c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) 2648c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) 2658c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci switch (i->aggr) { 2688c2ecf20Sopenharmony_ci case AGGR_BUF_FIRST: 2698c2ecf20Sopenharmony_ci ctl6 |= SM(i->aggr_len, AR_AggrLen); 2708c2ecf20Sopenharmony_ci fallthrough; 2718c2ecf20Sopenharmony_ci case AGGR_BUF_MIDDLE: 2728c2ecf20Sopenharmony_ci ctl1 |= AR_IsAggr | AR_MoreAggr; 2738c2ecf20Sopenharmony_ci ctl6 |= SM(i->ndelim, AR_PadDelim); 2748c2ecf20Sopenharmony_ci break; 2758c2ecf20Sopenharmony_ci case AGGR_BUF_LAST: 2768c2ecf20Sopenharmony_ci ctl1 |= AR_IsAggr; 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci case AGGR_BUF_NONE: 2798c2ecf20Sopenharmony_ci break; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl0, (i->pkt_len & AR_FrameLen) 2838c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 2848c2ecf20Sopenharmony_ci | SM(i->txpower[0], AR_XmitPower0) 2858c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 2868c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) 2878c2ecf20Sopenharmony_ci | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 2888c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) 2898c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : 2908c2ecf20Sopenharmony_ci (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl1, ctl1); 2938c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl6, ctl6); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST) 2968c2ecf20Sopenharmony_ci return; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl4, set11nPktDurRTSCTS(i->rates, 0) 2998c2ecf20Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 1)); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl5, set11nPktDurRTSCTS(i->rates, 2) 3028c2ecf20Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 3)); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl7, set11nRateFlags(i->rates, 0) 3058c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 1) 3068c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 2) 3078c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 3) 3088c2ecf20Sopenharmony_ci | SM(i->rtscts_rate, AR_RTSCTSRate)); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl9, SM(i->txpower[1], AR_XmitPower1)); 3118c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl10, SM(i->txpower[2], AR_XmitPower2)); 3128c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ds_ctl11, SM(i->txpower[3], AR_XmitPower3)); 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistatic int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, 3168c2ecf20Sopenharmony_ci struct ath_tx_status *ts) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci struct ar5416_desc *ads = AR5416DESC(ds); 3198c2ecf20Sopenharmony_ci u32 status; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci status = READ_ONCE(ads->ds_txstatus9); 3228c2ecf20Sopenharmony_ci if ((status & AR_TxDone) == 0) 3238c2ecf20Sopenharmony_ci return -EINPROGRESS; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci ts->ts_tstamp = ads->AR_SendTimestamp; 3268c2ecf20Sopenharmony_ci ts->ts_status = 0; 3278c2ecf20Sopenharmony_ci ts->ts_flags = 0; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (status & AR_TxOpExceeded) 3308c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XTXOP; 3318c2ecf20Sopenharmony_ci ts->tid = MS(status, AR_TxTid); 3328c2ecf20Sopenharmony_ci ts->ts_rateindex = MS(status, AR_FinalTxIdx); 3338c2ecf20Sopenharmony_ci ts->ts_seqnum = MS(status, AR_SeqNum); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci status = READ_ONCE(ads->ds_txstatus0); 3368c2ecf20Sopenharmony_ci ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); 3378c2ecf20Sopenharmony_ci ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); 3388c2ecf20Sopenharmony_ci ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); 3398c2ecf20Sopenharmony_ci if (status & AR_TxBaStatus) { 3408c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_BA; 3418c2ecf20Sopenharmony_ci ts->ba_low = ads->AR_BaBitmapLow; 3428c2ecf20Sopenharmony_ci ts->ba_high = ads->AR_BaBitmapHigh; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci status = READ_ONCE(ads->ds_txstatus1); 3468c2ecf20Sopenharmony_ci if (status & AR_FrmXmitOK) 3478c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TX_ACKED; 3488c2ecf20Sopenharmony_ci else { 3498c2ecf20Sopenharmony_ci if (status & AR_ExcessiveRetries) 3508c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XRETRY; 3518c2ecf20Sopenharmony_ci if (status & AR_Filtered) 3528c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FILT; 3538c2ecf20Sopenharmony_ci if (status & AR_FIFOUnderrun) { 3548c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FIFO; 3558c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci if (status & AR_TxTimerExpired) 3598c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 3608c2ecf20Sopenharmony_ci if (status & AR_DescCfgErr) 3618c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 3628c2ecf20Sopenharmony_ci if (status & AR_TxDataUnderrun) { 3638c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 3648c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci if (status & AR_TxDelimUnderrun) { 3678c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 3688c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci ts->ts_shortretry = MS(status, AR_RTSFailCnt); 3718c2ecf20Sopenharmony_ci ts->ts_longretry = MS(status, AR_DataFailCnt); 3728c2ecf20Sopenharmony_ci ts->ts_virtcol = MS(status, AR_VirtRetryCnt); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci status = READ_ONCE(ads->ds_txstatus5); 3758c2ecf20Sopenharmony_ci ts->ts_rssi = MS(status, AR_TxRSSICombined); 3768c2ecf20Sopenharmony_ci ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); 3778c2ecf20Sopenharmony_ci ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); 3788c2ecf20Sopenharmony_ci ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ts->evm0 = ads->AR_TxEVM0; 3818c2ecf20Sopenharmony_ci ts->evm1 = ads->AR_TxEVM1; 3828c2ecf20Sopenharmony_ci ts->evm2 = ads->AR_TxEVM2; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci return 0; 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct ar5416_desc *ads = AR5416DESC(ds); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci switch (index) { 3928c2ecf20Sopenharmony_ci case 0: 3938c2ecf20Sopenharmony_ci return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur0); 3948c2ecf20Sopenharmony_ci case 1: 3958c2ecf20Sopenharmony_ci return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur1); 3968c2ecf20Sopenharmony_ci case 2: 3978c2ecf20Sopenharmony_ci return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur2); 3988c2ecf20Sopenharmony_ci case 3: 3998c2ecf20Sopenharmony_ci return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur3); 4008c2ecf20Sopenharmony_ci default: 4018c2ecf20Sopenharmony_ci return -1; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_civoid ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, 4068c2ecf20Sopenharmony_ci u32 size, u32 flags) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci struct ar5416_desc *ads = AR5416DESC(ds); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci ads->ds_ctl1 = size & AR_BufLen; 4118c2ecf20Sopenharmony_ci if (flags & ATH9K_RXDESC_INTREQ) 4128c2ecf20Sopenharmony_ci ads->ds_ctl1 |= AR_RxIntrReq; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci memset(&ads->u.rx, 0, sizeof(ads->u.rx)); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setuprxdesc); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_civoid ar9002_hw_attach_mac_ops(struct ath_hw *ah) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci struct ath_hw_ops *ops = ath9k_hw_ops(ah); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci ops->rx_enable = ar9002_hw_rx_enable; 4238c2ecf20Sopenharmony_ci ops->set_desc_link = ar9002_hw_set_desc_link; 4248c2ecf20Sopenharmony_ci ops->get_isr = ar9002_hw_get_isr; 4258c2ecf20Sopenharmony_ci ops->set_txdesc = ar9002_set_txdesc; 4268c2ecf20Sopenharmony_ci ops->proc_txdesc = ar9002_hw_proc_txdesc; 4278c2ecf20Sopenharmony_ci ops->get_duration = ar9002_hw_get_duration; 4288c2ecf20Sopenharmony_ci} 429