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