ar9300_beacon.c revision 250003
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#ifdef AH_SUPPORT_AR9300
20
21#include "ah.h"
22#include "ah_internal.h"
23
24#include "ar9300/ar9300.h"
25#include "ar9300/ar9300reg.h"
26
27#define TU_TO_USEC(_tu) ((_tu) << 10)
28
29extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q);
30
31/*
32 * Initializes all of the hardware registers used to
33 * send beacons.  Note that for station operation the
34 * driver calls ar9300_set_sta_beacon_timers instead.
35 */
36void
37ar9300_beacon_init(struct ath_hal *ah,
38    u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode)
39{
40    struct ath_hal_private  *ap  = AH_PRIVATE(ah);
41    u_int32_t               beacon_period_usec;
42
43    HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP);
44    if (opmode == HAL_M_IBSS) {
45        OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
46    }
47    OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, ONE_EIGHTH_TU_TO_USEC(next_beacon));
48    OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
49        (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
50        ap->ah_config.ath_hal_dma_beacon_response_time));
51    OS_REG_WRITE(ah, AR_NEXT_SWBA,
52        (ONE_EIGHTH_TU_TO_USEC(next_beacon) -
53        ap->ah_config.ath_hal_sw_beacon_response_time));
54
55    beacon_period_usec =
56        ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8);
57    OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec);
58    OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec);
59    OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec);
60
61    /* reset TSF if required */
62    if (beacon_period & HAL_BEACON_RESET_TSF) {
63        ar9300_reset_tsf(ah);
64    }
65
66    /* enable timers */
67    OS_REG_SET_BIT(ah, AR_TIMER_MODE,
68        AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN);
69}
70
71/*
72 * Set all the beacon related bits on the h/w for stations
73 * i.e. initializes the corresponding h/w timers;
74 */
75void
76ar9300_set_sta_beacon_timers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
77{
78    u_int32_t next_tbtt, beaconintval, dtimperiod, beacontimeout;
79    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
80
81    HALASSERT(bs->bs_intval != 0);
82
83    /* no cfp setting since h/w automatically takes care */
84    OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
85
86    /*
87     * Start the beacon timers by setting the BEACON register
88     * to the beacon interval; no need to write tim offset since
89     * h/w parses IEs.
90     */
91    OS_REG_WRITE(ah, AR_BEACON_PERIOD,
92                 TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
93    OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
94                 TU_TO_USEC(bs->bs_intval & HAL_BEACON_PERIOD));
95    /*
96     * Configure the BMISS interrupt.  Note that we
97     * assume the caller blocks interrupts while enabling
98     * the threshold.
99     */
100    HALASSERT(bs->bs_bmissthreshold <=
101        (AR_RSSI_THR_BM_THR >> AR_RSSI_THR_BM_THR_S));
102    OS_REG_RMW_FIELD(ah, AR_RSSI_THR,
103        AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
104
105    /*
106     * Program the sleep registers to correlate with the beacon setup.
107     */
108
109    /*
110     * Current implementation assumes sw processing of beacons -
111     * assuming an interrupt is generated every beacon which
112     * causes the hardware to become awake until the sw tells
113     * it to go to sleep again; beacon timeout is to allow for
114     * beacon jitter; cab timeout is max time to wait for cab
115     * after seeing the last DTIM or MORE CAB bit
116     */
117#define CAB_TIMEOUT_VAL         10 /* in TU */
118#define BEACON_TIMEOUT_VAL      10 /* in TU */
119#define MIN_BEACON_TIMEOUT_VAL   1 /* in 1/8 TU */
120#define SLEEP_SLOP               3 /* in TU */
121
122    /*
123     * For max powersave mode we may want to sleep for longer than a
124     * beacon period and not want to receive all beacons; modify the
125     * timers accordingly; make sure to align the next TIM to the
126     * next DTIM if we decide to wake for DTIMs only
127     */
128    beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
129    HALASSERT(beaconintval != 0);
130    if (bs->bs_sleepduration > beaconintval) {
131        HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
132                bs->bs_sleepduration);
133        beaconintval = bs->bs_sleepduration;
134    }
135    dtimperiod = bs->bs_dtimperiod;
136    if (bs->bs_sleepduration > dtimperiod) {
137        HALASSERT(dtimperiod == 0 ||
138            roundup(bs->bs_sleepduration, dtimperiod) ==
139                bs->bs_sleepduration);
140        dtimperiod = bs->bs_sleepduration;
141    }
142    HALASSERT(beaconintval <= dtimperiod);
143    if (beaconintval == dtimperiod) {
144        next_tbtt = bs->bs_nextdtim;
145    } else {
146        next_tbtt = bs->bs_nexttbtt;
147    }
148
149    HALDEBUG(ah, HAL_DEBUG_BEACON,
150        "%s: next DTIM %d\n", __func__, bs->bs_nextdtim);
151    HALDEBUG(ah, HAL_DEBUG_BEACON,
152        "%s: next beacon %d\n", __func__, next_tbtt);
153    HALDEBUG(ah, HAL_DEBUG_BEACON,
154        "%s: beacon period %d\n", __func__, beaconintval);
155    HALDEBUG(ah, HAL_DEBUG_BEACON,
156        "%s: DTIM period %d\n", __func__, dtimperiod);
157
158    OS_REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
159    OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(next_tbtt - SLEEP_SLOP));
160
161    /* cab timeout is now in 1/8 TU */
162    OS_REG_WRITE(ah, AR_SLEEP1,
163        SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
164        | AR_SLEEP1_ASSUME_DTIM);
165
166    /* beacon timeout is now in 1/8 TU */
167    if (p_cap->hal_auto_sleep_support) {
168        beacontimeout = (BEACON_TIMEOUT_VAL << 3);
169    } else {
170        /*
171         * Use a very small value to make sure the timeout occurs before
172         * the TBTT.  In this case the chip will not go back to sleep
173         * automatically, instead it will wait for the SW to explicitly
174         * set it to that mode.
175         */
176        beacontimeout = MIN_BEACON_TIMEOUT_VAL;
177    }
178
179    OS_REG_WRITE(ah, AR_SLEEP2,
180        SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
181
182    OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
183    OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
184
185    /* clear HOST AP related timers first */
186    OS_REG_CLR_BIT(ah, AR_TIMER_MODE, (AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN));
187
188    OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN
189                    | AR_DTIM_TIMER_EN);
190
191    /* TSF out of range threshold */
192    OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
193
194#undef CAB_TIMEOUT_VAL
195#undef BEACON_TIMEOUT_VAL
196#undef SLEEP_SLOP
197}
198#endif /* AH_SUPPORT_AR9300 */
199