ar9300_timer.c revision 256281
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * Copyright (c) 2013 Qualcomm Atheros, Inc.
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * Permission to use, copy, modify, and/or distribute this software for any
50Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
60Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
90Sstevel@tonic-gate * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
100Sstevel@tonic-gate * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
110Sstevel@tonic-gate * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
120Sstevel@tonic-gate * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
130Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
140Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE.
150Sstevel@tonic-gate */
160Sstevel@tonic-gate
170Sstevel@tonic-gate#include "opt_ah.h"
180Sstevel@tonic-gate
190Sstevel@tonic-gate#include "ah.h"
200Sstevel@tonic-gate#include "ah_internal.h"
210Sstevel@tonic-gate
220Sstevel@tonic-gate#include "ar9300/ar9300.h"
230Sstevel@tonic-gate#include "ar9300/ar9300reg.h"
240Sstevel@tonic-gate#include "ar9300/ar9300desc.h"
250Sstevel@tonic-gate
260Sstevel@tonic-gatetypedef struct gen_timer_configuation {
270Sstevel@tonic-gate    u_int32_t   next_addr;
280Sstevel@tonic-gate    u_int32_t   period_addr;
290Sstevel@tonic-gate    u_int32_t   mode_addr;
300Sstevel@tonic-gate    u_int32_t   mode_mask;
310Sstevel@tonic-gate}  GEN_TIMER_CONFIGURATION;
320Sstevel@tonic-gate
330Sstevel@tonic-gate#define AR_GEN_TIMERS2_CFG(num) \
340Sstevel@tonic-gate    AR_GEN_TIMERS2_ ## num ## _NEXT, \
350Sstevel@tonic-gate    AR_GEN_TIMERS2_ ## num ## _PERIOD, \
360Sstevel@tonic-gate    AR_GEN_TIMERS2_MODE, \
370Sstevel@tonic-gate    (1 << num)
380Sstevel@tonic-gatestatic const GEN_TIMER_CONFIGURATION gen_timer_configuration[] =
390Sstevel@tonic-gate{
400Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
410Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
420Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
430Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
440Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
450Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
460Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
470Sstevel@tonic-gate    {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
480Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(0)},
490Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(1)},
500Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(2)},
510Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(3)},
520Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(4)},
530Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(5)},
540Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(6)},
550Sstevel@tonic-gate    {AR_GEN_TIMERS2_CFG(7)}
560Sstevel@tonic-gate};
570Sstevel@tonic-gate
580Sstevel@tonic-gate#define AR_GENTMR_BIT(_index)   (1 << (_index))
590Sstevel@tonic-gate
600Sstevel@tonic-gateint
610Sstevel@tonic-gatear9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf)
620Sstevel@tonic-gate{
630Sstevel@tonic-gate    struct ath_hal_9300 *ahp = AH9300(ah);
640Sstevel@tonic-gate    u_int32_t           i, mask;
650Sstevel@tonic-gate    u_int32_t           avail_timer_start, avail_timer_end;
660Sstevel@tonic-gate
670Sstevel@tonic-gate    if (tsf == HAL_GEN_TIMER_TSF) {
680Sstevel@tonic-gate        avail_timer_start = AR_FIRST_NDP_TIMER;
690Sstevel@tonic-gate        avail_timer_end = AR_GEN_TIMER_BANK_1_LEN;
700Sstevel@tonic-gate    } else {
710Sstevel@tonic-gate        avail_timer_start = AR_GEN_TIMER_BANK_1_LEN;
720Sstevel@tonic-gate        avail_timer_end = AR_NUM_GEN_TIMERS;
730Sstevel@tonic-gate    }
740Sstevel@tonic-gate
750Sstevel@tonic-gate    /* Find the first availabe timer index */
760Sstevel@tonic-gate    i = avail_timer_start;
770Sstevel@tonic-gate    mask = ahp->ah_avail_gen_timers >> i;
780Sstevel@tonic-gate    for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) {
790Sstevel@tonic-gate        if (mask & 0x1) {
800Sstevel@tonic-gate            ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i));
810Sstevel@tonic-gate
820Sstevel@tonic-gate            if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) {
830Sstevel@tonic-gate                ahp->ah_enable_tsf2 = AH_TRUE;
840Sstevel@tonic-gate                ar9300_start_tsf2(ah);
850Sstevel@tonic-gate            }
860Sstevel@tonic-gate            return i;
87        }
88    }
89    return -1;
90}
91
92void ar9300_start_tsf2(struct ath_hal *ah)
93{
94    struct ath_hal_9300 *ahp = AH9300(ah);
95
96    if (ahp->ah_enable_tsf2) {
97        /* Delay might be needed after TSF2 reset */
98        OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
99        OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
100    }
101}
102
103void
104ar9300_free_generic_timer(struct ath_hal *ah, int index)
105{
106    struct ath_hal_9300 *ahp = AH9300(ah);
107
108    ar9300_stop_generic_timer(ah, index);
109    ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index);
110}
111
112void
113ar9300_start_generic_timer(
114    struct ath_hal *ah,
115    int index,
116    u_int32_t timer_next,
117    u_int32_t timer_period)
118{
119    if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
120        return;
121    }
122
123    /*
124     * Program generic timer registers
125     */
126    OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next);
127    OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period);
128    OS_REG_SET_BIT(ah,
129        gen_timer_configuration[index].mode_addr,
130        gen_timer_configuration[index].mode_mask);
131
132    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
133        /*
134         * Starting from Jupiter, each generic timer can select which tsf to
135         * use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15
136         * use tsf2.
137         */
138        if ((index < AR_GEN_TIMER_BANK_1_LEN)) {
139            OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
140        }
141        else {
142            OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
143        }
144    }
145
146    /* Enable both trigger and thresh interrupt masks */
147    OS_REG_SET_BIT(ah, AR_IMR_S5,
148                   (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
149                    SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
150}
151
152void
153ar9300_stop_generic_timer(struct ath_hal *ah, int index)
154{
155    if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
156        return;
157    }
158
159    /*
160     * Clear generic timer enable bits.
161     */
162    OS_REG_CLR_BIT(ah,
163        gen_timer_configuration[index].mode_addr,
164        gen_timer_configuration[index].mode_mask);
165
166    /* Disable both trigger and thresh interrupt masks */
167    OS_REG_CLR_BIT(ah, AR_IMR_S5,
168                   (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
169                    SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
170}
171
172void
173ar9300_get_gen_timer_interrupts(
174    struct ath_hal *ah,
175    u_int32_t *trigger,
176    u_int32_t *thresh)
177{
178    struct ath_hal_9300 *ahp = AH9300(ah);
179    *trigger = ahp->ah_intr_gen_timer_trigger;
180    *thresh = ahp->ah_intr_gen_timer_thresh;
181}
182