1 /*
2  * Copyright (c) 2017 The Fuchsia Authors.
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <platform/timer_capture.h>
10 
11 #include <arch/arm/cm.h>
12 #include <assert.h>
13 #include <platform/rcc.h>
14 
15 typedef enum {
16     STM32_TIM_NOT_FOUND = -1,
17     STM32_TIM1_INDEX = 0,
18     STM32_TIM2_INDEX,
19     STM32_TIM3_INDEX,
20     STM32_TIM6_INDEX,
21     STM32_TIM7_INDEX,
22     STM32_TIM14_INDEX,
23     STM32_TIM15_INDEX,
24     STM32_TIM16_INDEX,
25     STM32_TIM17_INDEX,
26     STM32_NUM_TIMERS,
27 } stm32_timer_index_t;
28 
29 typedef TIM_TypeDef stm32_timer_regs_t;
30 
31 #define STM32_TIMER_FLAGS_32_BIT (1 << 0)
32 typedef struct stm32_timer_config_ {
33     stm32_timer_regs_t *regs;
34     uint32_t flags;
35     stm32_rcc_clk_t clock;
36     int irq;
37 } stm32_timer_config_t;
38 
39 static const stm32_timer_config_t stm32_timer_config[] = {
40 #ifdef TIM1
41     [STM32_TIM1_INDEX] = {
42         .regs = TIM1,
43         .flags = 0,
44         .clock = STM32_RCC_CLK_TIM1,
45         // TIM1 has two interrupts.  This one and TIM1_BRK_UP_TRG_COM_IRQn.
46         // This will need to be supported when more than just capture is
47         // supported.
48         .irq = TIM1_CC_IRQn,
49     },
50 #endif
51 #ifdef TIM2
52     [STM32_TIM2_INDEX] = {
53         .regs = TIM2,
54         .flags = STM32_TIMER_FLAGS_32_BIT,
55         .clock = STM32_RCC_CLK_TIM2,
56         .irq = TIM2_IRQn,
57     },
58 #endif
59 #ifdef TIM3
60     [STM32_TIM3_INDEX] = {
61         .regs = TIM3,
62         .flags = 0,
63         .clock = STM32_RCC_CLK_TIM3,
64         .irq = TIM3_IRQn,
65     },
66 #endif
67 #ifdef TIM6
68     [STM32_TIM6_INDEX] = {
69         .regs = TIM6,
70         .flags = 0,
71         .clock = STM32_RCC_CLK_TIM6,
72         .irq = TIM6_IRQn,
73     },
74 #endif
75 #ifdef TIM7
76     [STM32_TIM7_INDEX] = {
77         .regs = TIM7,
78         .flags = 0,
79         .clock = STM32_RCC_CLK_TIM7,
80         .irq = TIM7_IRQn,
81     },
82 #endif
83 #ifdef TIM14
84     [STM32_TIM14_INDEX] = {
85         .regs = TIM14,
86         .flags = 0,
87         .clock = STM32_RCC_CLK_TIM14,
88         .irq = TIM14_IRQn,
89     },
90 #endif
91 #ifdef TIM15
92     [STM32_TIM15_INDEX] = {
93         .regs = TIM15,
94         .flags = 0,
95         .clock = STM32_RCC_CLK_TIM15,
96         .irq = TIM15_IRQn,
97     },
98 #endif
99 #ifdef TIM16
100     [STM32_TIM16_INDEX] = {
101         .regs = TIM16,
102         .flags = 0,
103         .clock = STM32_RCC_CLK_TIM16,
104         .irq = TIM16_IRQn,
105     },
106 #endif
107 #ifdef TIM17
108     [STM32_TIM17_INDEX] = {
109         .regs = TIM17,
110         .flags = 0,
111         .clock = STM32_RCC_CLK_TIM17,
112         .irq = TIM17_IRQn,
113     },
114 #endif
115 };
116 
117 static stm32_timer_capture_t *stm32_timer_capture_data[STM32_NUM_TIMERS];
118 
stm32_timer_enable(const stm32_timer_config_t * config)119 static void stm32_timer_enable(const stm32_timer_config_t *config) {
120     stm32_rcc_set_enable(config->clock, true);
121 }
122 
stm32_timer_get_index(int timer)123 static stm32_timer_index_t stm32_timer_get_index(int timer) {
124     switch (timer) {
125         case 1:
126             return STM32_TIM1_INDEX;
127         case 2:
128             return STM32_TIM2_INDEX;
129         case 3:
130             return STM32_TIM3_INDEX;
131         case 6:
132             return STM32_TIM6_INDEX;
133         case 7:
134             return STM32_TIM7_INDEX;
135         case 14:
136             return STM32_TIM14_INDEX;
137         case 15:
138             return STM32_TIM15_INDEX;
139         case 16:
140             return STM32_TIM16_INDEX;
141         case 17:
142             return STM32_TIM17_INDEX;
143         default:
144             return STM32_TIM_NOT_FOUND;
145     }
146 }
147 
stm32_timer_get_config(int timer)148 static const stm32_timer_config_t *stm32_timer_get_config(int timer) {
149     stm32_timer_index_t index = stm32_timer_get_index(timer);
150     if (index == STM32_TIM_NOT_FOUND) {
151         return NULL;
152     }
153     return &stm32_timer_config[index];
154 }
155 
stm32_timer_is_32_bit(int timer)156 static bool stm32_timer_is_32_bit(int timer) {
157     switch (timer) {
158         case 2:
159             return true;
160         default:
161             return false;
162     }
163 }
164 
stm32_timer_capture_setup_chan(stm32_timer_capture_t * tc,int chan)165 static void stm32_timer_capture_setup_chan(stm32_timer_capture_t *tc, int chan) {
166     stm32_timer_regs_t *regs = tc->config->regs;
167     volatile uint32_t *ccmr = chan & 0x2 ? &regs->CCMR2 : &regs->CCMR1;
168     int shift = 8 * (chan & 1);
169 
170     uint32_t val = *ccmr;
171     val &= 0xff << shift;
172     val |= TIM_CCMR1_CC1S_0 << shift;
173     *ccmr = val;
174 
175     uint32_t config = TIM_CCER_CC1E;
176     uint32_t flags = tc->chan[chan].flags;
177     if (flags & STM32_TIMER_CAPTURE_CHAN_FLAG_FALLING) {
178         config |= TIM_CCER_CC1P;
179         if (flags & STM32_TIMER_CAPTURE_CHAN_FLAG_RISING) {
180             config |= TIM_CCER_CC1NP;
181         }
182     }
183 
184     shift = 4 * (chan & 3);
185     val = regs->CCER;
186     val &= 0xf << shift;
187     val |= config << shift;
188     regs->CCER = val;
189 }
190 
stm32_timer_get_ccr(stm32_timer_capture_t * tc,int chan)191 static uint32_t stm32_timer_get_ccr(stm32_timer_capture_t *tc, int chan) {
192     assert(0 <= chan && chan <= 3);
193     switch (chan) {
194         case 0:
195             return tc->config->regs->CCR1;
196         case 1:
197             return tc->config->regs->CCR2;
198         case 2:
199             return tc->config->regs->CCR3;
200         default:  // 3
201             return tc->config->regs->CCR4;
202     }
203 }
204 
stm32_timer_inc_overflow(stm32_timer_capture_t * tc,uint64_t overflow)205 static uint64_t stm32_timer_inc_overflow(stm32_timer_capture_t *tc, uint64_t overflow) {
206     uint64_t inc;
207     if (tc->config->flags & STM32_TIMER_FLAGS_32_BIT) {
208         inc = 0x100000000ULL;
209     } else {
210         inc = 0x10000ULL;
211     }
212     return overflow + inc;
213 }
214 
stm32_timer_median_val(stm32_timer_capture_t * tc)215 static uint32_t stm32_timer_median_val(stm32_timer_capture_t *tc) {
216     if (tc->config->flags & STM32_TIMER_FLAGS_32_BIT) {
217         return 0x7fffffff;
218     } else {
219         return 0x7fff;
220     }
221 }
222 
223 // Assumes interrupts are disabled.
stm32_timer_calc_value(stm32_timer_capture_t * tc,uint32_t sr,uint32_t val)224 static uint64_t stm32_timer_calc_value(stm32_timer_capture_t *tc, uint32_t sr, uint32_t val) {
225     uint64_t overflow = tc->overflow;
226     // Since we could be processing an overflow and capture interrupts at the
227     // same time, we don't know the ordering of the two.  Here we assume
228     // that if the capture event occurred in the lower half of the counter
229     // range, the overflow happened before the capture.
230     if (sr & TIM_SR_UIF && val < stm32_timer_median_val(tc)) {
231         overflow = stm32_timer_inc_overflow(tc, overflow);
232     }
233     return overflow | val;
234 }
235 
stm32_timer_capture_chan_irq(stm32_timer_capture_t * tc,uint32_t sr,int chan)236 static bool stm32_timer_capture_chan_irq(stm32_timer_capture_t *tc, uint32_t sr, int chan) {
237     if (tc->chan[chan].cb == NULL) {
238         return false;
239     }
240     if (sr & (TIM_SR_CC1IF << chan)) {
241         uint32_t val = stm32_timer_get_ccr(tc, chan);
242         return tc->chan[chan].cb(stm32_timer_calc_value(tc, sr, val));
243     }
244     return false;
245 }
246 
stm32_timer_capture_irq(stm32_timer_index_t index)247 static void stm32_timer_capture_irq(stm32_timer_index_t index) {
248     arm_cm_irq_entry();
249     bool resched = false;
250 
251     stm32_timer_capture_t *tc = stm32_timer_capture_data[index];
252     if (tc == NULL) {
253         goto out;
254     }
255 
256     uint32_t sr = tc->config->regs->SR;
257     uint32_t irq_ack = ~0U;
258 
259     // Since these read their corresponding CCR registers, the status flags
260     // do not need to be explicitly cleared.
261     resched |= stm32_timer_capture_chan_irq(tc, sr, 0);
262     resched |= stm32_timer_capture_chan_irq(tc, sr, 1);
263     resched |= stm32_timer_capture_chan_irq(tc, sr, 2);
264     resched |= stm32_timer_capture_chan_irq(tc, sr, 3);
265 
266 
267     // We process overflow after compares in order to handle overflow race
268     // detection there.
269     spin_lock_saved_state_t state;
270     spin_lock_irqsave(&tc->overflow_lock, state);
271     if (sr & TIM_SR_UIF) {
272         tc->overflow = stm32_timer_inc_overflow(tc, tc->overflow);
273         irq_ack &= ~TIM_SR_UIF;
274     }
275     tc->config->regs->SR = irq_ack;
276     spin_unlock_irqrestore(&tc->overflow_lock, state);
277 
278 out:
279     arm_cm_irq_exit(resched);
280 }
281 
stm32_TIM1_IRQ(void)282 void stm32_TIM1_IRQ(void) {
283     stm32_timer_capture_irq(STM32_TIM1_INDEX);
284 }
285 
stm32_TIM2_IRQ(void)286 void stm32_TIM2_IRQ(void) {
287     stm32_timer_capture_irq(STM32_TIM2_INDEX);
288 }
289 
stm32_TIM3_IRQ(void)290 void stm32_TIM3_IRQ(void) {
291     stm32_timer_capture_irq(STM32_TIM3_INDEX);
292 }
293 
stm32_TIM6_IRQ(void)294 void stm32_TIM6_IRQ(void) {
295     stm32_timer_capture_irq(STM32_TIM6_INDEX);
296 }
297 
stm32_TIM7_IRQ(void)298 void stm32_TIM7_IRQ(void) {
299     stm32_timer_capture_irq(STM32_TIM7_INDEX);
300 }
301 
stm32_TIM14_IRQ(void)302 void stm32_TIM14_IRQ(void) {
303     stm32_timer_capture_irq(STM32_TIM14_INDEX);
304 }
305 
stm32_TIM15_IRQ(void)306 void stm32_TIM15_IRQ(void) {
307     stm32_timer_capture_irq(STM32_TIM15_INDEX);
308 }
309 
stm32_TIM16_IRQ(void)310 void stm32_TIM16_IRQ(void) {
311     stm32_timer_capture_irq(STM32_TIM16_INDEX);
312 }
313 
stm32_TIM17_IRQ(void)314 void stm32_TIM17_IRQ(void) {
315     stm32_timer_capture_irq(STM32_TIM17_INDEX);
316 }
317 
stm32_timer_capture_setup(stm32_timer_capture_t * tc,int timer,uint16_t prescaler)318 status_t stm32_timer_capture_setup(stm32_timer_capture_t *tc, int timer, uint16_t prescaler) {
319     assert(prescaler > 0);
320 
321     tc->config = stm32_timer_get_config(timer);
322     if (tc->config == NULL) {
323         return ERR_NOT_FOUND;
324     }
325 
326     stm32_timer_enable(tc->config);
327 
328     stm32_timer_capture_data[stm32_timer_get_index(timer)] = tc;
329 
330     tc->overflow = 0;
331     spin_lock_init(&tc->overflow_lock);
332 
333     tc->config->regs->CR1 = 0;
334 
335     // The prescaler value applied by hardware is PSC + 1.
336     tc->config->regs->PSC = prescaler > 0 ? prescaler - 1 : 0;
337 
338     uint32_t dier =  TIM_DIER_UIE;
339 
340     int i;
341     for (i = 0; i < 4; i++) {
342         if (tc->chan[i].flags & STM32_TIMER_CAPTURE_CHAN_FLAG_ENABLE) {
343             dier |= TIM_DIER_CC1IE << i;
344             stm32_timer_capture_setup_chan(tc, i);
345         }
346     }
347 
348     tc->config->regs->DIER = dier;
349     tc->config->regs->CR1 |= TIM_CR1_CEN;
350 
351     NVIC_EnableIRQ(tc->config->irq);
352 
353     return NO_ERROR;
354 }
355 
stm32_timer_capture_get_counter(stm32_timer_capture_t * tc)356 uint64_t stm32_timer_capture_get_counter(stm32_timer_capture_t *tc) {
357     // Protect against tc->overflow being updated while we calculate the value.
358     spin_lock_saved_state_t state;
359     spin_lock_irqsave(&tc->overflow_lock, state);
360 
361     uint32_t cnt = tc->config->regs->CNT;
362     uint32_t sr = tc->config->regs->SR;
363     uint64_t value = stm32_timer_calc_value(tc, sr, cnt);
364 
365     spin_unlock_irqrestore(&tc->overflow_lock, state);
366     return value;
367 }
368 
stm32_timer_init(void)369 void stm32_timer_init(void) {
370 }
371 
stm32_timer_early_init(void)372 void stm32_timer_early_init(void) {
373 }
374