1/*
2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
3 *
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.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "opt_ah.h"
18
19#include "ah.h"
20#include "ah_desc.h"
21#include "ah_internal.h"
22
23#include "ar9300/ar9300.h"
24#include "ar9300/ar9300reg.h"
25#include "ar9300/ar9300desc.h"
26
27/*
28 * Get the RXDP.
29 */
30u_int32_t
31ar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype)
32{
33    if (qtype == HAL_RX_QUEUE_HP) {
34        return OS_REG_READ(ath, AR_HP_RXDP);
35    } else {
36        return OS_REG_READ(ath, AR_LP_RXDP);
37    }
38}
39
40/*
41 * Set the rx_dp.
42 */
43void
44ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)
45{
46    HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));
47
48    if (qtype == HAL_RX_QUEUE_HP) {
49        OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);
50    } else {
51        OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);
52    }
53}
54
55/*
56 * Set Receive Enable bits.
57 */
58void
59ar9300_enable_receive(struct ath_hal *ah)
60{
61    OS_REG_WRITE(ah, AR_CR, 0);
62}
63
64/*
65 * Set the RX abort bit.
66 */
67HAL_BOOL
68ar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set)
69{
70    if (set) {
71        /* Set the force_rx_abort bit */
72        OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
73
74        if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){
75            /* depending upon the BB panic status, rx state may not return to 0,
76             * so skipping the wait for BB panic reset */
77            OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
78            return AH_FALSE;
79        } else {
80            HAL_BOOL okay;
81            okay = ath_hal_wait(
82                ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0);
83            /* Wait for Rx state to return to 0 */
84            if (!okay) {
85                /* abort: chip rx failed to go idle in 10 ms */
86                OS_REG_CLR_BIT(ah, AR_DIAG_SW,
87                    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
88
89                HALDEBUG(ah, HAL_DEBUG_RX,
90                    "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
91                    __func__, OS_REG_READ(ah, AR_OBS_BUS_1));
92
93                return AH_FALSE; /* failure */
94            }
95        }
96    } else {
97        OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
98    }
99
100    return AH_TRUE; /* success */
101}
102
103/*
104 * Stop Receive at the DMA engine
105 */
106HAL_BOOL
107ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
108{
109    int wait;
110    HAL_BOOL status, okay;
111    u_int32_t org_value;
112
113#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
114#define AH_TIME_QUANTUM        100     /* usec */
115
116    OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);
117
118    if (timeout == 0) {
119        timeout = AH_RX_STOP_DMA_TIMEOUT;
120    }
121
122    org_value = OS_REG_READ(ah, AR_MACMISC);
123
124    OS_REG_WRITE(ah, AR_MACMISC,
125        ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
126         (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));
127
128        okay = ath_hal_wait(
129            ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0);
130    /* wait for Rx DMA state machine to become idle */
131        if (!okay) {
132            HALDEBUG(ah, HAL_DEBUG_RX,
133                "reg AR_DMADBG_7 is not 0, instead 0x%08x\n",
134                OS_REG_READ(ah, AR_DMADBG_7));
135        }
136
137    /* Set receive disable bit */
138    OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);
139
140    /* Wait for rx enable bit to go low */
141    for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
142        if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
143            break;
144        }
145        OS_DELAY(AH_TIME_QUANTUM);
146    }
147
148    if (wait == 0) {
149        HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n"
150                "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
151                __func__,
152                timeout / 1000,
153                OS_REG_READ(ah, AR_CR),
154                OS_REG_READ(ah, AR_DIAG_SW));
155        status = AH_FALSE;
156    } else {
157        status = AH_TRUE;
158    }
159
160    OS_REG_WRITE(ah, AR_MACMISC, org_value);
161
162    OS_MARK(ah, AH_MARK_RX_CTL,
163        status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);
164
165    return status;
166#undef AH_RX_STOP_DMA_TIMEOUT
167#undef AH_TIME_QUANTUM
168}
169
170/*
171 * Start Transmit at the PCU engine (unpause receive)
172 */
173void
174ar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning)
175{
176    ar9300_enable_mib_counters(ah);
177    ar9300_ani_reset(ah, is_scanning);
178    /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */
179    OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
180}
181
182/*
183 * Stop Transmit at the PCU engine (pause receive)
184 */
185void
186ar9300_stop_pcu_receive(struct ath_hal *ah)
187{
188    OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
189    ar9300_disable_mib_counters(ah);
190}
191
192/*
193 * Set multicast filter 0 (lower 32-bits)
194 *               filter 1 (upper 32-bits)
195 */
196void
197ar9300_set_multicast_filter(
198    struct ath_hal *ah,
199    u_int32_t filter0,
200    u_int32_t filter1)
201{
202    OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
203    OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
204}
205
206/*
207 * Get the receive filter.
208 */
209u_int32_t
210ar9300_get_rx_filter(struct ath_hal *ah)
211{
212    u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
213    u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
214    if (phybits & AR_PHY_ERR_RADAR) {
215        bits |= HAL_RX_FILTER_PHYRADAR;
216    }
217    if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) {
218        bits |= HAL_RX_FILTER_PHYERR;
219    }
220    return bits;
221}
222
223/*
224 * Set the receive filter.
225 */
226void
227ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits)
228{
229    u_int32_t phybits;
230
231    if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
232        /* Enable Rx for 4 address frames */
233        bits |= AR_RX_4ADDRESS;
234    }
235    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
236        /* HW fix for rx hang and corruption. */
237        bits |= AR_RX_CONTROL_WRAPPER;
238    }
239    OS_REG_WRITE(ah, AR_RX_FILTER,
240        bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR);
241    phybits = 0;
242    if (bits & HAL_RX_FILTER_PHYRADAR) {
243        phybits |= AR_PHY_ERR_RADAR;
244    }
245    if (bits & HAL_RX_FILTER_PHYERR) {
246        phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
247    }
248    OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
249    if (phybits) {
250        OS_REG_WRITE(ah, AR_RXCFG,
251            OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
252    } else {
253        OS_REG_WRITE(ah, AR_RXCFG,
254            OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
255    }
256}
257
258/*
259 * Select to pass PLCP headr or EVM data.
260 */
261HAL_BOOL
262ar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query)
263{
264    struct ath_hal_9300 *ahp = AH9300(ah);
265    HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0;
266
267    if (just_query) {
268        return old_value;
269    }
270    if (sel_evm) {
271        OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
272    } else {
273        OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
274    }
275
276    ahp->ah_get_plcp_hdr = !sel_evm;
277
278    return old_value;
279}
280
281void ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable)
282{
283    u_int32_t reg_val = 0;
284    reg_val =  OS_REG_READ(ah, AR_RX_FILTER);
285    if (enable){
286        reg_val |= AR_RX_PROM;
287    } else{ /*Disable promisc mode */
288        reg_val &= ~AR_RX_PROM;
289    }
290    OS_REG_WRITE(ah, AR_RX_FILTER, reg_val);
291}
292
293void
294ar9300_read_pktlog_reg(
295    struct ath_hal *ah,
296    u_int32_t *rxfilter_val,
297    u_int32_t *rxcfg_val,
298    u_int32_t *phy_err_mask_val,
299    u_int32_t *mac_pcu_phy_err_regval)
300{
301    *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER);
302    *rxcfg_val    = OS_REG_READ(ah, AR_RXCFG);
303    *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR);
304    *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338);
305    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
306        "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
307        "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
308        __func__, __LINE__,
309        *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval);
310}
311
312void
313ar9300_write_pktlog_reg(
314    struct ath_hal *ah,
315    HAL_BOOL enable,
316    u_int32_t rxfilter_val,
317    u_int32_t rxcfg_val,
318    u_int32_t phy_err_mask_val,
319    u_int32_t mac_pcu_phy_err_reg_val)
320{
321    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
322        /* HW fix for rx hang and corruption. */
323        rxfilter_val |= AR_RX_CONTROL_WRAPPER;
324    }
325    if (enable) { /* Enable pktlog phyerr setting */
326        OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val);
327        OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF);
328        OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA);
329        OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF);
330    } else { /* Disable phyerr and Restore regs */
331        OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val);
332        OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val);
333        OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val);
334        OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val);
335    }
336    HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
337        "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
338        "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
339        __func__, __LINE__,
340        enable, rxfilter_val, rxcfg_val,
341        phy_err_mask_val, mac_pcu_phy_err_reg_val);
342}
343