Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c
48526 views
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
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
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
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
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
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
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
183