xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c (revision d1d015864103b253b3fcb2f72a0da5b0cfeb31b6)
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 #include "ah.h"
20 #include "ah_internal.h"
21 
22 #include "ar9300/ar9300.h"
23 #include "ar9300/ar9300reg.h"
24 #include "ar9300/ar9300desc.h"
25 
26 typedef struct gen_timer_configuation {
27     u_int32_t   next_addr;
28     u_int32_t   period_addr;
29     u_int32_t   mode_addr;
30     u_int32_t   mode_mask;
31 }  GEN_TIMER_CONFIGURATION;
32 
33 #define AR_GEN_TIMERS2_CFG(num) \
34     AR_GEN_TIMERS2_ ## num ## _NEXT, \
35     AR_GEN_TIMERS2_ ## num ## _PERIOD, \
36     AR_GEN_TIMERS2_MODE, \
37     (1 << num)
38 static const GEN_TIMER_CONFIGURATION gen_timer_configuration[] =
39 {
40     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
41     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
42     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
43     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
44     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
45     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
46     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
47     {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
48     {AR_GEN_TIMERS2_CFG(0)},
49     {AR_GEN_TIMERS2_CFG(1)},
50     {AR_GEN_TIMERS2_CFG(2)},
51     {AR_GEN_TIMERS2_CFG(3)},
52     {AR_GEN_TIMERS2_CFG(4)},
53     {AR_GEN_TIMERS2_CFG(5)},
54     {AR_GEN_TIMERS2_CFG(6)},
55     {AR_GEN_TIMERS2_CFG(7)}
56 };
57 
58 #define AR_GENTMR_BIT(_index)   (1 << (_index))
59 
60 int
ar9300_alloc_generic_timer(struct ath_hal * ah,HAL_GEN_TIMER_DOMAIN tsf)61 ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf)
62 {
63     struct ath_hal_9300 *ahp = AH9300(ah);
64     u_int32_t           i, mask;
65     u_int32_t           avail_timer_start, avail_timer_end;
66 
67     if (tsf == HAL_GEN_TIMER_TSF) {
68         avail_timer_start = AR_FIRST_NDP_TIMER;
69         avail_timer_end = AR_GEN_TIMER_BANK_1_LEN;
70     } else {
71         avail_timer_start = AR_GEN_TIMER_BANK_1_LEN;
72         avail_timer_end = AR_NUM_GEN_TIMERS;
73     }
74 
75     /* Find the first availabe timer index */
76     i = avail_timer_start;
77     mask = ahp->ah_avail_gen_timers >> i;
78     for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) {
79         if (mask & 0x1) {
80             ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i));
81 
82             if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) {
83                 ahp->ah_enable_tsf2 = AH_TRUE;
84                 ar9300_start_tsf2(ah);
85             }
86             return i;
87         }
88     }
89     return -1;
90 }
91 
ar9300_start_tsf2(struct ath_hal * ah)92 void 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 
103 void
ar9300_free_generic_timer(struct ath_hal * ah,int index)104 ar9300_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 
112 void
ar9300_start_generic_timer(struct ath_hal * ah,int index,u_int32_t timer_next,u_int32_t timer_period)113 ar9300_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 
152 void
ar9300_stop_generic_timer(struct ath_hal * ah,int index)153 ar9300_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 
172 void
ar9300_get_gen_timer_interrupts(struct ath_hal * ah,u_int32_t * trigger,u_int32_t * thresh)173 ar9300_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