xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c (revision d1d015864103b253b3fcb2f72a0da5b0cfeb31b6)
1*76bd547bSAdrian Chadd /*
2*76bd547bSAdrian Chadd  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3*76bd547bSAdrian Chadd  *
4*76bd547bSAdrian Chadd  * Permission to use, copy, modify, and/or distribute this software for any
5*76bd547bSAdrian Chadd  * purpose with or without fee is hereby granted, provided that the above
6*76bd547bSAdrian Chadd  * copyright notice and this permission notice appear in all copies.
7*76bd547bSAdrian Chadd  *
8*76bd547bSAdrian Chadd  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9*76bd547bSAdrian Chadd  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10*76bd547bSAdrian Chadd  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11*76bd547bSAdrian Chadd  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12*76bd547bSAdrian Chadd  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13*76bd547bSAdrian Chadd  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14*76bd547bSAdrian Chadd  * PERFORMANCE OF THIS SOFTWARE.
15*76bd547bSAdrian Chadd  */
16*76bd547bSAdrian Chadd 
17*76bd547bSAdrian Chadd #include "opt_ah.h"
18*76bd547bSAdrian Chadd 
19*76bd547bSAdrian Chadd #include "ah.h"
20*76bd547bSAdrian Chadd #include "ah_internal.h"
21*76bd547bSAdrian Chadd 
22*76bd547bSAdrian Chadd #include "ar9300/ar9300.h"
23*76bd547bSAdrian Chadd #include "ar9300/ar9300reg.h"
24*76bd547bSAdrian Chadd #include "ar9300/ar9300desc.h"
25*76bd547bSAdrian Chadd 
26*76bd547bSAdrian Chadd typedef struct gen_timer_configuation {
27*76bd547bSAdrian Chadd     u_int32_t   next_addr;
28*76bd547bSAdrian Chadd     u_int32_t   period_addr;
29*76bd547bSAdrian Chadd     u_int32_t   mode_addr;
30*76bd547bSAdrian Chadd     u_int32_t   mode_mask;
31*76bd547bSAdrian Chadd }  GEN_TIMER_CONFIGURATION;
32*76bd547bSAdrian Chadd 
33*76bd547bSAdrian Chadd #define AR_GEN_TIMERS2_CFG(num) \
34*76bd547bSAdrian Chadd     AR_GEN_TIMERS2_ ## num ## _NEXT, \
35*76bd547bSAdrian Chadd     AR_GEN_TIMERS2_ ## num ## _PERIOD, \
36*76bd547bSAdrian Chadd     AR_GEN_TIMERS2_MODE, \
37*76bd547bSAdrian Chadd     (1 << num)
38*76bd547bSAdrian Chadd static const GEN_TIMER_CONFIGURATION gen_timer_configuration[] =
39*76bd547bSAdrian Chadd {
40*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
41*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
42*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
43*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
44*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
45*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
46*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
47*76bd547bSAdrian Chadd     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
48*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(0)},
49*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(1)},
50*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(2)},
51*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(3)},
52*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(4)},
53*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(5)},
54*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(6)},
55*76bd547bSAdrian Chadd     {AR_GEN_TIMERS2_CFG(7)}
56*76bd547bSAdrian Chadd };
57*76bd547bSAdrian Chadd 
58*76bd547bSAdrian Chadd #define AR_GENTMR_BIT(_index)   (1 << (_index))
59*76bd547bSAdrian Chadd 
60*76bd547bSAdrian Chadd int
ar9300_alloc_generic_timer(struct ath_hal * ah,HAL_GEN_TIMER_DOMAIN tsf)61*76bd547bSAdrian Chadd ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf)
62*76bd547bSAdrian Chadd {
63*76bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
64*76bd547bSAdrian Chadd     u_int32_t           i, mask;
65*76bd547bSAdrian Chadd     u_int32_t           avail_timer_start, avail_timer_end;
66*76bd547bSAdrian Chadd 
67*76bd547bSAdrian Chadd     if (tsf == HAL_GEN_TIMER_TSF) {
68*76bd547bSAdrian Chadd         avail_timer_start = AR_FIRST_NDP_TIMER;
69*76bd547bSAdrian Chadd         avail_timer_end = AR_GEN_TIMER_BANK_1_LEN;
70*76bd547bSAdrian Chadd     } else {
71*76bd547bSAdrian Chadd         avail_timer_start = AR_GEN_TIMER_BANK_1_LEN;
72*76bd547bSAdrian Chadd         avail_timer_end = AR_NUM_GEN_TIMERS;
73*76bd547bSAdrian Chadd     }
74*76bd547bSAdrian Chadd 
75*76bd547bSAdrian Chadd     /* Find the first availabe timer index */
76*76bd547bSAdrian Chadd     i = avail_timer_start;
77*76bd547bSAdrian Chadd     mask = ahp->ah_avail_gen_timers >> i;
78*76bd547bSAdrian Chadd     for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) {
79*76bd547bSAdrian Chadd         if (mask & 0x1) {
80*76bd547bSAdrian Chadd             ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i));
81*76bd547bSAdrian Chadd 
82*76bd547bSAdrian Chadd             if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) {
83*76bd547bSAdrian Chadd                 ahp->ah_enable_tsf2 = AH_TRUE;
84*76bd547bSAdrian Chadd                 ar9300_start_tsf2(ah);
85*76bd547bSAdrian Chadd             }
86*76bd547bSAdrian Chadd             return i;
87*76bd547bSAdrian Chadd         }
88*76bd547bSAdrian Chadd     }
89*76bd547bSAdrian Chadd     return -1;
90*76bd547bSAdrian Chadd }
91*76bd547bSAdrian Chadd 
ar9300_start_tsf2(struct ath_hal * ah)92*76bd547bSAdrian Chadd void ar9300_start_tsf2(struct ath_hal *ah)
93*76bd547bSAdrian Chadd {
94*76bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
95*76bd547bSAdrian Chadd 
96*76bd547bSAdrian Chadd     if (ahp->ah_enable_tsf2) {
97*76bd547bSAdrian Chadd         /* Delay might be needed after TSF2 reset */
98*76bd547bSAdrian Chadd         OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
99*76bd547bSAdrian Chadd         OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
100*76bd547bSAdrian Chadd     }
101*76bd547bSAdrian Chadd }
102*76bd547bSAdrian Chadd 
103*76bd547bSAdrian Chadd void
ar9300_free_generic_timer(struct ath_hal * ah,int index)104*76bd547bSAdrian Chadd ar9300_free_generic_timer(struct ath_hal *ah, int index)
105*76bd547bSAdrian Chadd {
106*76bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
107*76bd547bSAdrian Chadd 
108*76bd547bSAdrian Chadd     ar9300_stop_generic_timer(ah, index);
109*76bd547bSAdrian Chadd     ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index);
110*76bd547bSAdrian Chadd }
111*76bd547bSAdrian Chadd 
112*76bd547bSAdrian Chadd void
ar9300_start_generic_timer(struct ath_hal * ah,int index,u_int32_t timer_next,u_int32_t timer_period)113*76bd547bSAdrian Chadd ar9300_start_generic_timer(
114*76bd547bSAdrian Chadd     struct ath_hal *ah,
115*76bd547bSAdrian Chadd     int index,
116*76bd547bSAdrian Chadd     u_int32_t timer_next,
117*76bd547bSAdrian Chadd     u_int32_t timer_period)
118*76bd547bSAdrian Chadd {
119*76bd547bSAdrian Chadd     if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
120*76bd547bSAdrian Chadd         return;
121*76bd547bSAdrian Chadd     }
122*76bd547bSAdrian Chadd 
123*76bd547bSAdrian Chadd     /*
124*76bd547bSAdrian Chadd      * Program generic timer registers
125*76bd547bSAdrian Chadd      */
126*76bd547bSAdrian Chadd     OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next);
127*76bd547bSAdrian Chadd     OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period);
128*76bd547bSAdrian Chadd     OS_REG_SET_BIT(ah,
129*76bd547bSAdrian Chadd         gen_timer_configuration[index].mode_addr,
130*76bd547bSAdrian Chadd         gen_timer_configuration[index].mode_mask);
131*76bd547bSAdrian Chadd 
132*76bd547bSAdrian Chadd     if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
133*76bd547bSAdrian Chadd         /*
134*76bd547bSAdrian Chadd          * Starting from Jupiter, each generic timer can select which tsf to
135*76bd547bSAdrian Chadd          * use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15
136*76bd547bSAdrian Chadd          * use tsf2.
137*76bd547bSAdrian Chadd          */
138*76bd547bSAdrian Chadd         if ((index < AR_GEN_TIMER_BANK_1_LEN)) {
139*76bd547bSAdrian Chadd             OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
140*76bd547bSAdrian Chadd         }
141*76bd547bSAdrian Chadd         else {
142*76bd547bSAdrian Chadd             OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));
143*76bd547bSAdrian Chadd         }
144*76bd547bSAdrian Chadd     }
145*76bd547bSAdrian Chadd 
146*76bd547bSAdrian Chadd     /* Enable both trigger and thresh interrupt masks */
147*76bd547bSAdrian Chadd     OS_REG_SET_BIT(ah, AR_IMR_S5,
148*76bd547bSAdrian Chadd                    (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
149*76bd547bSAdrian Chadd                     SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
150*76bd547bSAdrian Chadd }
151*76bd547bSAdrian Chadd 
152*76bd547bSAdrian Chadd void
ar9300_stop_generic_timer(struct ath_hal * ah,int index)153*76bd547bSAdrian Chadd ar9300_stop_generic_timer(struct ath_hal *ah, int index)
154*76bd547bSAdrian Chadd {
155*76bd547bSAdrian Chadd     if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {
156*76bd547bSAdrian Chadd         return;
157*76bd547bSAdrian Chadd     }
158*76bd547bSAdrian Chadd 
159*76bd547bSAdrian Chadd     /*
160*76bd547bSAdrian Chadd      * Clear generic timer enable bits.
161*76bd547bSAdrian Chadd      */
162*76bd547bSAdrian Chadd     OS_REG_CLR_BIT(ah,
163*76bd547bSAdrian Chadd         gen_timer_configuration[index].mode_addr,
164*76bd547bSAdrian Chadd         gen_timer_configuration[index].mode_mask);
165*76bd547bSAdrian Chadd 
166*76bd547bSAdrian Chadd     /* Disable both trigger and thresh interrupt masks */
167*76bd547bSAdrian Chadd     OS_REG_CLR_BIT(ah, AR_IMR_S5,
168*76bd547bSAdrian Chadd                    (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |
169*76bd547bSAdrian Chadd                     SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));
170*76bd547bSAdrian Chadd }
171*76bd547bSAdrian Chadd 
172*76bd547bSAdrian Chadd void
ar9300_get_gen_timer_interrupts(struct ath_hal * ah,u_int32_t * trigger,u_int32_t * thresh)173*76bd547bSAdrian Chadd ar9300_get_gen_timer_interrupts(
174*76bd547bSAdrian Chadd     struct ath_hal *ah,
175*76bd547bSAdrian Chadd     u_int32_t *trigger,
176*76bd547bSAdrian Chadd     u_int32_t *thresh)
177*76bd547bSAdrian Chadd {
178*76bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
179*76bd547bSAdrian Chadd     *trigger = ahp->ah_intr_gen_timer_trigger;
180*76bd547bSAdrian Chadd     *thresh = ahp->ah_intr_gen_timer_thresh;
181*76bd547bSAdrian Chadd }
182