1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian#include "opt_ah.h"
18250003Sadrian
19250003Sadrian#include "ah.h"
20250003Sadrian#include "ah_desc.h"
21250003Sadrian#include "ah_internal.h"
22250003Sadrian
23250003Sadrian#include "ar9300/ar9300.h"
24250003Sadrian#include "ar9300/ar9300reg.h"
25250003Sadrian#include "ar9300/ar9300desc.h"
26250003Sadrian
27250003Sadrian/*
28250003Sadrian * Get the RXDP.
29250003Sadrian */
30250003Sadrianu_int32_t
31250003Sadrianar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype)
32250003Sadrian{
33250003Sadrian    if (qtype == HAL_RX_QUEUE_HP) {
34250003Sadrian        return OS_REG_READ(ath, AR_HP_RXDP);
35250003Sadrian    } else {
36250003Sadrian        return OS_REG_READ(ath, AR_LP_RXDP);
37250003Sadrian    }
38250003Sadrian}
39250003Sadrian
40250003Sadrian/*
41250003Sadrian * Set the rx_dp.
42250003Sadrian */
43250003Sadrianvoid
44250003Sadrianar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)
45250003Sadrian{
46250003Sadrian    HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));
47250003Sadrian
48250003Sadrian    if (qtype == HAL_RX_QUEUE_HP) {
49250003Sadrian        OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);
50250003Sadrian    } else {
51250003Sadrian        OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);
52250003Sadrian    }
53250003Sadrian}
54250003Sadrian
55250003Sadrian/*
56250003Sadrian * Set Receive Enable bits.
57250003Sadrian */
58250003Sadrianvoid
59250003Sadrianar9300_enable_receive(struct ath_hal *ah)
60250003Sadrian{
61250003Sadrian    OS_REG_WRITE(ah, AR_CR, 0);
62250003Sadrian}
63250003Sadrian
64250003Sadrian/*
65250003Sadrian * Set the RX abort bit.
66250003Sadrian */
67250003SadrianHAL_BOOL
68250003Sadrianar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set)
69250003Sadrian{
70250003Sadrian    if (set) {
71250003Sadrian        /* Set the force_rx_abort bit */
72250003Sadrian        OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
73250003Sadrian
74250008Sadrian        if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){
75250003Sadrian            /* depending upon the BB panic status, rx state may not return to 0,
76250003Sadrian             * so skipping the wait for BB panic reset */
77250003Sadrian            OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
78250008Sadrian            return AH_FALSE;
79250003Sadrian        } else {
80250003Sadrian            HAL_BOOL okay;
81250003Sadrian            okay = ath_hal_wait(
82250008Sadrian                ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0);
83250003Sadrian            /* Wait for Rx state to return to 0 */
84250003Sadrian            if (!okay) {
85250003Sadrian                /* abort: chip rx failed to go idle in 10 ms */
86250003Sadrian                OS_REG_CLR_BIT(ah, AR_DIAG_SW,
87250003Sadrian                    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
88250003Sadrian
89250003Sadrian                HALDEBUG(ah, HAL_DEBUG_RX,
90250003Sadrian                    "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
91250003Sadrian                    __func__, OS_REG_READ(ah, AR_OBS_BUS_1));
92250003Sadrian
93250003Sadrian                return AH_FALSE; /* failure */
94250003Sadrian            }
95250003Sadrian        }
96250003Sadrian    } else {
97250003Sadrian        OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
98250003Sadrian    }
99250003Sadrian
100250003Sadrian    return AH_TRUE; /* success */
101250003Sadrian}
102250003Sadrian
103250003Sadrian/*
104250003Sadrian * Stop Receive at the DMA engine
105250003Sadrian */
106250003SadrianHAL_BOOL
107250003Sadrianar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
108250003Sadrian{
109250003Sadrian    int wait;
110250003Sadrian    HAL_BOOL status, okay;
111250003Sadrian    u_int32_t org_value;
112250003Sadrian
113250003Sadrian#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
114250003Sadrian#define AH_TIME_QUANTUM        100     /* usec */
115250003Sadrian
116269793Sadrian    OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);
117269793Sadrian
118250003Sadrian    if (timeout == 0) {
119250003Sadrian        timeout = AH_RX_STOP_DMA_TIMEOUT;
120250003Sadrian    }
121250003Sadrian
122250003Sadrian    org_value = OS_REG_READ(ah, AR_MACMISC);
123250003Sadrian
124250003Sadrian    OS_REG_WRITE(ah, AR_MACMISC,
125250003Sadrian        ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
126250003Sadrian         (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));
127250003Sadrian
128250003Sadrian        okay = ath_hal_wait(
129250008Sadrian            ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0);
130250003Sadrian    /* wait for Rx DMA state machine to become idle */
131250003Sadrian        if (!okay) {
132250003Sadrian            HALDEBUG(ah, HAL_DEBUG_RX,
133250003Sadrian                "reg AR_DMADBG_7 is not 0, instead 0x%08x\n",
134250003Sadrian                OS_REG_READ(ah, AR_DMADBG_7));
135250003Sadrian        }
136250003Sadrian
137250003Sadrian    /* Set receive disable bit */
138250003Sadrian    OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);
139250003Sadrian
140250003Sadrian    /* Wait for rx enable bit to go low */
141250003Sadrian    for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
142250003Sadrian        if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
143250003Sadrian            break;
144250003Sadrian        }
145250003Sadrian        OS_DELAY(AH_TIME_QUANTUM);
146250003Sadrian    }
147250003Sadrian
148250003Sadrian    if (wait == 0) {
149250003Sadrian        HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n"
150250003Sadrian                "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
151250003Sadrian                __func__,
152250003Sadrian                timeout / 1000,
153250003Sadrian                OS_REG_READ(ah, AR_CR),
154250003Sadrian                OS_REG_READ(ah, AR_DIAG_SW));
155250003Sadrian        status = AH_FALSE;
156250003Sadrian    } else {
157250003Sadrian        status = AH_TRUE;
158250003Sadrian    }
159250003Sadrian
160250003Sadrian    OS_REG_WRITE(ah, AR_MACMISC, org_value);
161250003Sadrian
162269793Sadrian    OS_MARK(ah, AH_MARK_RX_CTL,
163269793Sadrian        status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);
164269793Sadrian
165250003Sadrian    return status;
166250003Sadrian#undef AH_RX_STOP_DMA_TIMEOUT
167250003Sadrian#undef AH_TIME_QUANTUM
168250003Sadrian}
169250003Sadrian
170250003Sadrian/*
171250003Sadrian * Start Transmit at the PCU engine (unpause receive)
172250003Sadrian */
173250003Sadrianvoid
174250003Sadrianar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning)
175250003Sadrian{
176250003Sadrian    ar9300_enable_mib_counters(ah);
177250003Sadrian    ar9300_ani_reset(ah, is_scanning);
178250003Sadrian    /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */
179250003Sadrian    OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
180250003Sadrian}
181250003Sadrian
182250003Sadrian/*
183250003Sadrian * Stop Transmit at the PCU engine (pause receive)
184250003Sadrian */
185250003Sadrianvoid
186250003Sadrianar9300_stop_pcu_receive(struct ath_hal *ah)
187250003Sadrian{
188250003Sadrian    OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
189250003Sadrian    ar9300_disable_mib_counters(ah);
190250003Sadrian}
191250003Sadrian
192250003Sadrian/*
193250003Sadrian * Set multicast filter 0 (lower 32-bits)
194250003Sadrian *               filter 1 (upper 32-bits)
195250003Sadrian */
196250003Sadrianvoid
197250003Sadrianar9300_set_multicast_filter(
198250003Sadrian    struct ath_hal *ah,
199250003Sadrian    u_int32_t filter0,
200250003Sadrian    u_int32_t filter1)
201250003Sadrian{
202250003Sadrian    OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
203250003Sadrian    OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
204250003Sadrian}
205250003Sadrian
206250003Sadrian/*
207250003Sadrian * Get the receive filter.
208250003Sadrian */
209250003Sadrianu_int32_t
210250003Sadrianar9300_get_rx_filter(struct ath_hal *ah)
211250003Sadrian{
212250003Sadrian    u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
213250003Sadrian    u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
214250003Sadrian    if (phybits & AR_PHY_ERR_RADAR) {
215250003Sadrian        bits |= HAL_RX_FILTER_PHYRADAR;
216250003Sadrian    }
217250003Sadrian    if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) {
218250003Sadrian        bits |= HAL_RX_FILTER_PHYERR;
219250003Sadrian    }
220250003Sadrian    return bits;
221250003Sadrian}
222250003Sadrian
223250003Sadrian/*
224250003Sadrian * Set the receive filter.
225250003Sadrian */
226250003Sadrianvoid
227250003Sadrianar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits)
228250003Sadrian{
229250003Sadrian    u_int32_t phybits;
230250003Sadrian
231291437Sadrian    if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
232250003Sadrian        /* Enable Rx for 4 address frames */
233250003Sadrian        bits |= AR_RX_4ADDRESS;
234250003Sadrian    }
235250003Sadrian    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
236250003Sadrian        /* HW fix for rx hang and corruption. */
237250003Sadrian        bits |= AR_RX_CONTROL_WRAPPER;
238250003Sadrian    }
239250003Sadrian    OS_REG_WRITE(ah, AR_RX_FILTER,
240250003Sadrian        bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR);
241250003Sadrian    phybits = 0;
242250003Sadrian    if (bits & HAL_RX_FILTER_PHYRADAR) {
243250003Sadrian        phybits |= AR_PHY_ERR_RADAR;
244250003Sadrian    }
245250003Sadrian    if (bits & HAL_RX_FILTER_PHYERR) {
246250003Sadrian        phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
247250003Sadrian    }
248250003Sadrian    OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
249250003Sadrian    if (phybits) {
250250003Sadrian        OS_REG_WRITE(ah, AR_RXCFG,
251250003Sadrian            OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
252250003Sadrian    } else {
253250003Sadrian        OS_REG_WRITE(ah, AR_RXCFG,
254250003Sadrian            OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
255250003Sadrian    }
256250003Sadrian}
257250003Sadrian
258250003Sadrian/*
259250003Sadrian * Select to pass PLCP headr or EVM data.
260250003Sadrian */
261250003SadrianHAL_BOOL
262250003Sadrianar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query)
263250003Sadrian{
264250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
265250003Sadrian    HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0;
266250003Sadrian
267250003Sadrian    if (just_query) {
268250003Sadrian        return old_value;
269250003Sadrian    }
270250003Sadrian    if (sel_evm) {
271250003Sadrian        OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
272250003Sadrian    } else {
273250003Sadrian        OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
274250003Sadrian    }
275250003Sadrian
276250003Sadrian    ahp->ah_get_plcp_hdr = !sel_evm;
277250003Sadrian
278250003Sadrian    return old_value;
279250003Sadrian}
280250003Sadrian
281250003Sadrianvoid ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable)
282250003Sadrian{
283250003Sadrian    u_int32_t reg_val = 0;
284250003Sadrian    reg_val =  OS_REG_READ(ah, AR_RX_FILTER);
285250003Sadrian    if (enable){
286250003Sadrian        reg_val |= AR_RX_PROM;
287250003Sadrian    } else{ /*Disable promisc mode */
288250003Sadrian        reg_val &= ~AR_RX_PROM;
289250003Sadrian    }
290250003Sadrian    OS_REG_WRITE(ah, AR_RX_FILTER, reg_val);
291250003Sadrian}
292250003Sadrian
293250003Sadrianvoid
294250003Sadrianar9300_read_pktlog_reg(
295250003Sadrian    struct ath_hal *ah,
296250003Sadrian    u_int32_t *rxfilter_val,
297250003Sadrian    u_int32_t *rxcfg_val,
298250003Sadrian    u_int32_t *phy_err_mask_val,
299250003Sadrian    u_int32_t *mac_pcu_phy_err_regval)
300250003Sadrian{
301250003Sadrian    *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER);
302250003Sadrian    *rxcfg_val    = OS_REG_READ(ah, AR_RXCFG);
303250003Sadrian    *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR);
304250003Sadrian    *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338);
305250003Sadrian    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
306250003Sadrian        "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
307250003Sadrian        "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
308250003Sadrian        __func__, __LINE__,
309250003Sadrian        *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval);
310250003Sadrian}
311250003Sadrian
312250003Sadrianvoid
313250003Sadrianar9300_write_pktlog_reg(
314250003Sadrian    struct ath_hal *ah,
315250003Sadrian    HAL_BOOL enable,
316250003Sadrian    u_int32_t rxfilter_val,
317250003Sadrian    u_int32_t rxcfg_val,
318250003Sadrian    u_int32_t phy_err_mask_val,
319250003Sadrian    u_int32_t mac_pcu_phy_err_reg_val)
320250003Sadrian{
321250003Sadrian    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
322250003Sadrian        /* HW fix for rx hang and corruption. */
323250003Sadrian        rxfilter_val |= AR_RX_CONTROL_WRAPPER;
324250003Sadrian    }
325250003Sadrian    if (enable) { /* Enable pktlog phyerr setting */
326250003Sadrian        OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val);
327250003Sadrian        OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF);
328250003Sadrian        OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA);
329250003Sadrian        OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF);
330250003Sadrian    } else { /* Disable phyerr and Restore regs */
331250003Sadrian        OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val);
332250003Sadrian        OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val);
333250003Sadrian        OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val);
334250003Sadrian        OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val);
335250003Sadrian    }
336250003Sadrian    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
337250003Sadrian        "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
338250003Sadrian        "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
339250003Sadrian        __func__, __LINE__,
340250003Sadrian        enable, rxfilter_val, rxcfg_val,
341250003Sadrian        phy_err_mask_val, mac_pcu_phy_err_reg_val);
342250003Sadrian}
343