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