176bd547bSAdrian Chadd /*
276bd547bSAdrian Chadd  * Copyright (c) 2013 Qualcomm Atheros, Inc.
376bd547bSAdrian Chadd  *
476bd547bSAdrian Chadd  * Permission to use, copy, modify, and/or distribute this software for any
576bd547bSAdrian Chadd  * purpose with or without fee is hereby granted, provided that the above
676bd547bSAdrian Chadd  * copyright notice and this permission notice appear in all copies.
776bd547bSAdrian Chadd  *
876bd547bSAdrian Chadd  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
976bd547bSAdrian Chadd  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1076bd547bSAdrian Chadd  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1176bd547bSAdrian Chadd  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1276bd547bSAdrian Chadd  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1376bd547bSAdrian Chadd  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1476bd547bSAdrian Chadd  * PERFORMANCE OF THIS SOFTWARE.
1576bd547bSAdrian Chadd  */
1676bd547bSAdrian Chadd 
1776bd547bSAdrian Chadd #include "opt_ah.h"
1876bd547bSAdrian Chadd 
1976bd547bSAdrian Chadd #include "ah.h"
2076bd547bSAdrian Chadd #include "ah_internal.h"
2176bd547bSAdrian Chadd 
2276bd547bSAdrian Chadd #include "ar9300/ar9300.h"
2376bd547bSAdrian Chadd #include "ar9300/ar9300reg.h"
2476bd547bSAdrian Chadd #include "ar9300/ar9300desc.h"
2576bd547bSAdrian Chadd 
2676bd547bSAdrian Chadd typedef struct gen_timer_configuation {
2776bd547bSAdrian Chadd     u_int32_t   next_addr;
2876bd547bSAdrian Chadd     u_int32_t   period_addr;
2976bd547bSAdrian Chadd     u_int32_t   mode_addr;
3076bd547bSAdrian Chadd     u_int32_t   mode_mask;
3176bd547bSAdrian Chadd }  GEN_TIMER_CONFIGURATION;
3276bd547bSAdrian Chadd 
3376bd547bSAdrian Chadd #define AR_GEN_TIMERS2_CFG(num) \
3476bd547bSAdrian Chadd     AR_GEN_TIMERS2_ ## num ## _NEXT, \
3576bd547bSAdrian Chadd     AR_GEN_TIMERS2_ ## num ## _PERIOD, \
3676bd547bSAdrian Chadd     AR_GEN_TIMERS2_MODE, \
3776bd547bSAdrian Chadd     (1 << num)
3876bd547bSAdrian Chadd static const GEN_TIMER_CONFIGURATION gen_timer_configuration[] =
3976bd547bSAdrian Chadd {
4076bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4176bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4276bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4376bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4476bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4576bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4676bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4776bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
4876bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(0)},
4976bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(1)},
5076bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(2)},
5176bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(3)},
5276bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(4)},
5376bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(5)},
5476bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(6)},
5576bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(7)}
5676bd547bSAdrian Chadd };
5776bd547bSAdrian Chadd 
5876bd547bSAdrian Chadd #define AR_GENTMR_BIT(_index)   (1 << (_index))
5976bd547bSAdrian Chadd 
6076bd547bSAdrian Chadd int
ar9300_alloc_generic_timer(struct ath_hal * ah,HAL_GEN_TIMER_DOMAIN tsf)6176bd547bSAdrian Chadd ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf)
6276bd547bSAdrian Chadd {
6376bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
6476bd547bSAdrian Chadd     u_int32_t           i, mask;
6576bd547bSAdrian Chadd     u_int32_t           avail_timer_start, avail_timer_end;
6676bd547bSAdrian Chadd 
6776bd547bSAdrian Chadd     if (tsf == HAL_GEN_TIMER_TSF) {
6876bd547bSAdrian Chadd         avail_timer_start = AR_FIRST_NDP_TIMER;
6976bd547bSAdrian Chadd         avail_timer_end = AR_GEN_TIMER_BANK_1_LEN;
7076bd547bSAdrian Chadd     } else {
7176bd547bSAdrian Chadd         avail_timer_start = AR_GEN_TIMER_BANK_1_LEN;
7276bd547bSAdrian Chadd         avail_timer_end = AR_NUM_GEN_TIMERS;
7376bd547bSAdrian Chadd     }
7476bd547bSAdrian Chadd 
7576bd547bSAdrian Chadd     /* Find the first availabe timer index */
7676bd547bSAdrian Chadd     i = avail_timer_start;
7776bd547bSAdrian Chadd     mask = ahp->ah_avail_gen_timers >> i;
7876bd547bSAdrian Chadd     for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) {
7976bd547bSAdrian Chadd         if (mask & 0x1) {
8076bd547bSAdrian Chadd             ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i));
8176bd547bSAdrian Chadd 
8276bd547bSAdrian Chadd             if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) {
8376bd547bSAdrian Chadd                 ahp->ah_enable_tsf2 = AH_TRUE;
8476bd547bSAdrian Chadd                 ar9300_start_tsf2(ah);
8576bd547bSAdrian Chadd             }
8676bd547bSAdrian Chadd             return i;
8776bd547bSAdrian Chadd         }
8876bd547bSAdrian Chadd     }
8976bd547bSAdrian Chadd     return -1;
9076bd547bSAdrian Chadd }
9176bd547bSAdrian Chadd 
ar9300_start_tsf2(struct ath_hal * ah)9276bd547bSAdrian Chadd void ar9300_start_tsf2(struct ath_hal *ah)
9376bd547bSAdrian Chadd {
9476bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
9576bd547bSAdrian Chadd 
9676bd547bSAdrian Chadd     if (ahp->ah_enable_tsf2) {
9776bd547bSAdrian Chadd         /* Delay might be needed after TSF2 reset */
9876bd547bSAdrian Chadd         OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
9976bd547bSAdrian Chadd         OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
10076bd547bSAdrian Chadd     }
10176bd547bSAdrian Chadd }
10276bd547bSAdrian Chadd 
10376bd547bSAdrian Chadd void
ar9300_free_generic_timer(struct ath_hal * ah,int index)10476bd547bSAdrian Chadd ar9300_free_generic_timer(struct ath_hal *ah, int index)
10576bd547bSAdrian Chadd {
10676bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
10776bd547bSAdrian Chadd 
10876bd547bSAdrian Chadd     ar9300_stop_generic_timer(ah, index);
10976bd547bSAdrian Chadd     ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index);
11076bd547bSAdrian Chadd }
11176bd547bSAdrian Chadd 
11276bd547bSAdrian Chadd void
ar9300_start_generic_timer(struct ath_hal * ah,int index,u_int32_t timer_next,u_int32_t timer_period)11376bd547bSAdrian Chadd ar9300_start_generic_timer(
11476bd547bSAdrian Chadd     struct ath_hal *ah,
11576bd547bSAdrian Chadd     int index,
11676bd547bSAdrian Chadd     u_int32_t timer_next,
11776bd547bSAdrian Chadd     u_int32_t timer_period)
11876bd547bSAdrian Chadd {
11976bd547bSAdrian Chadd     if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
12076bd547bSAdrian Chadd         return;
12176bd547bSAdrian Chadd     }
12276bd547bSAdrian Chadd 
12376bd547bSAdrian Chadd     /*
12476bd547bSAdrian Chadd      * Program generic timer registers
12576bd547bSAdrian Chadd      */
12676bd547bSAdrian Chadd     OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next);
12776bd547bSAdrian Chadd     OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period);
12876bd547bSAdrian Chadd     OS_REG_SET_BIT(ah,
12976bd547bSAdrian Chadd         gen_timer_configuration[index].mode_addr,
13076bd547bSAdrian Chadd         gen_timer_configuration[index].mode_mask);
13176bd547bSAdrian Chadd 
13276bd547bSAdrian Chadd     if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
13376bd547bSAdrian Chadd         /*
13476bd547bSAdrian Chadd          * Starting from Jupiter, each generic timer can select which tsf to
13576bd547bSAdrian Chadd          * use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15
13676bd547bSAdrian Chadd          * use tsf2.
13776bd547bSAdrian Chadd          */
13876bd547bSAdrian Chadd         if ((index < AR_GEN_TIMER_BANK_1_LEN)) {
13976bd547bSAdrian Chadd             OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
14076bd547bSAdrian Chadd         }
14176bd547bSAdrian Chadd         else {
14276bd547bSAdrian Chadd             OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
14376bd547bSAdrian Chadd         }
14476bd547bSAdrian Chadd     }
14576bd547bSAdrian Chadd 
14676bd547bSAdrian Chadd     /* Enable both trigger and thresh interrupt masks */
14776bd547bSAdrian Chadd     OS_REG_SET_BIT(ah, AR_IMR_S5,
14876bd547bSAdrian Chadd                    (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
14976bd547bSAdrian Chadd                     SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
15076bd547bSAdrian Chadd }
15176bd547bSAdrian Chadd 
15276bd547bSAdrian Chadd void
ar9300_stop_generic_timer(struct ath_hal * ah,int index)15376bd547bSAdrian Chadd ar9300_stop_generic_timer(struct ath_hal *ah, int index)
15476bd547bSAdrian Chadd {
15576bd547bSAdrian Chadd     if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
15676bd547bSAdrian Chadd         return;
15776bd547bSAdrian Chadd     }
15876bd547bSAdrian Chadd 
15976bd547bSAdrian Chadd     /*
16076bd547bSAdrian Chadd      * Clear generic timer enable bits.
16176bd547bSAdrian Chadd      */
16276bd547bSAdrian Chadd     OS_REG_CLR_BIT(ah,
16376bd547bSAdrian Chadd         gen_timer_configuration[index].mode_addr,
16476bd547bSAdrian Chadd         gen_timer_configuration[index].mode_mask);
16576bd547bSAdrian Chadd 
16676bd547bSAdrian Chadd     /* Disable both trigger and thresh interrupt masks */
16776bd547bSAdrian Chadd     OS_REG_CLR_BIT(ah, AR_IMR_S5,
16876bd547bSAdrian Chadd                    (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
16976bd547bSAdrian Chadd                     SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
17076bd547bSAdrian Chadd }
17176bd547bSAdrian Chadd 
17276bd547bSAdrian Chadd void
ar9300_get_gen_timer_interrupts(struct ath_hal * ah,u_int32_t * trigger,u_int32_t * thresh)17376bd547bSAdrian Chadd ar9300_get_gen_timer_interrupts(
17476bd547bSAdrian Chadd     struct ath_hal *ah,
17576bd547bSAdrian Chadd     u_int32_t *trigger,
17676bd547bSAdrian Chadd     u_int32_t *thresh)
17776bd547bSAdrian Chadd {
17876bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
17976bd547bSAdrian Chadd     *trigger = ahp->ah_intr_gen_timer_trigger;
18076bd547bSAdrian Chadd     *thresh = ahp->ah_intr_gen_timer_thresh;
18176bd547bSAdrian Chadd }
182