Lines Matching +full:overflow +full:- +full:control
3 * Copyright (c) 2020-2021 Vestas Wind Systems A/S
5 * SPDX-License-Identifier: Apache-2.0
23 #define MAX_CHANNELS ARRAY_SIZE(FTM0->CONTROLS)
68 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_set_cycles()
69 struct mcux_ftm_data *data = dev->data; in mcux_ftm_set_cycles()
78 return -ENOTSUP; in mcux_ftm_set_cycles()
83 return -EINVAL; in mcux_ftm_set_cycles()
86 if (channel >= config->channel_count) { in mcux_ftm_set_cycles()
88 return -ENOTSUP; in mcux_ftm_set_cycles()
92 irqs = FTM_GetEnabledInterrupts(config->base); in mcux_ftm_set_cycles()
95 return -EBUSY; in mcux_ftm_set_cycles()
99 data->channel[channel].dutyValue = pulse_cycles; in mcux_ftm_set_cycles()
102 data->channel[channel].level = kFTM_HighTrue; in mcux_ftm_set_cycles()
104 data->channel[channel].level = kFTM_LowTrue; in mcux_ftm_set_cycles()
110 if (period_cycles != data->period_cycles) { in mcux_ftm_set_cycles()
112 if (irqs & BIT_MASK(ARRAY_SIZE(data->channel))) { in mcux_ftm_set_cycles()
114 return -EBUSY; in mcux_ftm_set_cycles()
118 if (data->period_cycles != 0) { in mcux_ftm_set_cycles()
122 data->period_cycles, period_cycles, in mcux_ftm_set_cycles()
123 config->channel_count, dev->name); in mcux_ftm_set_cycles()
126 data->period_cycles = period_cycles; in mcux_ftm_set_cycles()
128 FTM_StopTimer(config->base); in mcux_ftm_set_cycles()
129 FTM_SetTimerPeriod(config->base, period_cycles); in mcux_ftm_set_cycles()
131 FTM_SetSoftwareTrigger(config->base, true); in mcux_ftm_set_cycles()
132 FTM_StartTimer(config->base, config->ftm_clock_source); in mcux_ftm_set_cycles()
135 status = FTM_SetupPwmMode(config->base, data->channel, in mcux_ftm_set_cycles()
136 config->channel_count, config->mode); in mcux_ftm_set_cycles()
139 return -ENOTSUP; in mcux_ftm_set_cycles()
141 FTM_SetSoftwareTrigger(config->base, true); in mcux_ftm_set_cycles()
152 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_configure_capture()
153 struct mcux_ftm_data *data = dev->data; in mcux_ftm_configure_capture()
159 return -ENOTSUP; in mcux_ftm_configure_capture()
162 if (pair >= ARRAY_SIZE(data->capture)) { in mcux_ftm_configure_capture()
164 return -EINVAL; in mcux_ftm_configure_capture()
167 if (FTM_GetEnabledInterrupts(config->base) & BIT(PAIR_2ND_CH(pair))) { in mcux_ftm_configure_capture()
169 return -EBUSY; in mcux_ftm_configure_capture()
174 return -EINVAL; in mcux_ftm_configure_capture()
179 return -ENOTSUP; in mcux_ftm_configure_capture()
182 data->capture[pair].callback = cb; in mcux_ftm_configure_capture()
183 data->capture[pair].user_data = user_data; in mcux_ftm_configure_capture()
184 param = &data->capture[pair].param; in mcux_ftm_configure_capture()
187 param->mode = kFTM_Continuous; in mcux_ftm_configure_capture()
189 param->mode = kFTM_OneShot; in mcux_ftm_configure_capture()
193 data->capture[pair].pulse_capture = false; in mcux_ftm_configure_capture()
196 param->currChanEdgeMode = kFTM_FallingEdge; in mcux_ftm_configure_capture()
197 param->nextChanEdgeMode = kFTM_FallingEdge; in mcux_ftm_configure_capture()
199 param->currChanEdgeMode = kFTM_RisingEdge; in mcux_ftm_configure_capture()
200 param->nextChanEdgeMode = kFTM_RisingEdge; in mcux_ftm_configure_capture()
203 data->capture[pair].pulse_capture = true; in mcux_ftm_configure_capture()
206 param->currChanEdgeMode = kFTM_FallingEdge; in mcux_ftm_configure_capture()
207 param->nextChanEdgeMode = kFTM_RisingEdge; in mcux_ftm_configure_capture()
209 param->currChanEdgeMode = kFTM_RisingEdge; in mcux_ftm_configure_capture()
210 param->nextChanEdgeMode = kFTM_FallingEdge; in mcux_ftm_configure_capture()
219 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_enable_capture()
220 struct mcux_ftm_data *data = dev->data; in mcux_ftm_enable_capture()
225 return -ENOTSUP; in mcux_ftm_enable_capture()
228 if (pair >= ARRAY_SIZE(data->capture)) { in mcux_ftm_enable_capture()
230 return -EINVAL; in mcux_ftm_enable_capture()
233 if (!data->capture[pair].callback) { in mcux_ftm_enable_capture()
235 return -EINVAL; in mcux_ftm_enable_capture()
238 if (FTM_GetEnabledInterrupts(config->base) & BIT(PAIR_2ND_CH(pair))) { in mcux_ftm_enable_capture()
240 return -EBUSY; in mcux_ftm_enable_capture()
243 FTM_ClearStatusFlags(config->base, BIT(PAIR_1ST_CH(pair)) | in mcux_ftm_enable_capture()
246 FTM_SetupDualEdgeCapture(config->base, pair, &data->capture[pair].param, in mcux_ftm_enable_capture()
249 FTM_EnableInterrupts(config->base, BIT(PAIR_1ST_CH(pair)) | in mcux_ftm_enable_capture()
257 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_disable_capture()
258 struct mcux_ftm_data *data = dev->data; in mcux_ftm_disable_capture()
263 return -ENOTSUP; in mcux_ftm_disable_capture()
266 if (pair >= ARRAY_SIZE(data->capture)) { in mcux_ftm_disable_capture()
268 return -EINVAL; in mcux_ftm_disable_capture()
271 FTM_DisableInterrupts(config->base, BIT(PAIR_1ST_CH(pair)) | in mcux_ftm_disable_capture()
275 config->base->COMBINE &= ~(1UL << (FTM_COMBINE_DECAP0_SHIFT + in mcux_ftm_disable_capture()
282 uint16_t cnt, bool overflow) in mcux_ftm_capture_first_edge() argument
284 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_capture_first_edge()
285 struct mcux_ftm_data *data = dev->data; in mcux_ftm_capture_first_edge()
289 __ASSERT_NO_MSG(pair < ARRAY_SIZE(data->capture)); in mcux_ftm_capture_first_edge()
290 capture = &data->capture[pair]; in mcux_ftm_capture_first_edge()
292 FTM_DisableInterrupts(config->base, BIT(PAIR_1ST_CH(pair))); in mcux_ftm_capture_first_edge()
294 capture->first_edge_cnt = cnt; in mcux_ftm_capture_first_edge()
295 capture->first_edge_overflows = data->overflows; in mcux_ftm_capture_first_edge()
296 capture->first_edge_overflow = overflow; in mcux_ftm_capture_first_edge()
298 LOG_DBG("pair = %d, 1st cnt = %u, 1st ovf = %d", pair, cnt, overflow); in mcux_ftm_capture_first_edge()
302 uint16_t cnt, bool overflow) in mcux_ftm_capture_second_edge() argument
305 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_capture_second_edge()
306 struct mcux_ftm_data *data = dev->data; in mcux_ftm_capture_second_edge()
307 uint32_t second_edge_overflows = data->overflows; in mcux_ftm_capture_second_edge()
316 __ASSERT_NO_MSG(pair < ARRAY_SIZE(data->capture)); in mcux_ftm_capture_second_edge()
317 capture = &data->capture[pair]; in mcux_ftm_capture_second_edge()
319 first_cnv = config->base->CONTROLS[PAIR_1ST_CH(pair)].CnV; in mcux_ftm_capture_second_edge()
320 second_cnv = config->base->CONTROLS[PAIR_2ND_CH(pair)].CnV; in mcux_ftm_capture_second_edge()
322 if (capture->pulse_capture) { in mcux_ftm_capture_second_edge()
323 /* Clear both edge flags for pulse capture to capture first edge overflow counter */ in mcux_ftm_capture_second_edge()
324 FTM_ClearStatusFlags(config->base, BIT(PAIR_1ST_CH(pair)) | BIT(PAIR_2ND_CH(pair))); in mcux_ftm_capture_second_edge()
327 FTM_ClearStatusFlags(config->base, BIT(PAIR_2ND_CH(pair))); in mcux_ftm_capture_second_edge()
330 if (unlikely(capture->first_edge_overflow && first_cnv > capture->first_edge_cnt)) { in mcux_ftm_capture_second_edge()
331 /* Compensate for the overflow registered in the same IRQ */ in mcux_ftm_capture_second_edge()
332 capture->first_edge_overflows--; in mcux_ftm_capture_second_edge()
335 if (unlikely(overflow && second_cnv > cnt)) { in mcux_ftm_capture_second_edge()
336 /* Compensate for the overflow registered in the same IRQ */ in mcux_ftm_capture_second_edge()
337 second_edge_overflows--; in mcux_ftm_capture_second_edge()
340 overflows = second_edge_overflows - capture->first_edge_overflows; in mcux_ftm_capture_second_edge()
344 if (u32_mul_overflow(overflows, config->base->MOD, &cycles)) { in mcux_ftm_capture_second_edge()
345 LOG_ERR("overflow while calculating cycles"); in mcux_ftm_capture_second_edge()
346 status = -ERANGE; in mcux_ftm_capture_second_edge()
348 cycles -= first_cnv; in mcux_ftm_capture_second_edge()
350 LOG_ERR("overflow while calculating cycles"); in mcux_ftm_capture_second_edge()
352 status = -ERANGE; in mcux_ftm_capture_second_edge()
356 cycles = second_cnv - first_cnv; in mcux_ftm_capture_second_edge()
361 pair, capture->first_edge_overflows, second_edge_overflows, overflows, first_cnv, in mcux_ftm_capture_second_edge()
362 second_cnv, cycles, cnt, overflow); in mcux_ftm_capture_second_edge()
364 if (capture->pulse_capture) { in mcux_ftm_capture_second_edge()
365 capture->callback(dev, pair, 0, cycles, status, in mcux_ftm_capture_second_edge()
366 capture->user_data); in mcux_ftm_capture_second_edge()
368 capture->callback(dev, pair, cycles, 0, status, in mcux_ftm_capture_second_edge()
369 capture->user_data); in mcux_ftm_capture_second_edge()
372 if (capture->param.mode == kFTM_OneShot) { in mcux_ftm_capture_second_edge()
373 /* One-shot capture done */ in mcux_ftm_capture_second_edge()
374 FTM_DisableInterrupts(config->base, BIT(PAIR_2ND_CH(pair))); in mcux_ftm_capture_second_edge()
375 } else if (capture->pulse_capture) { in mcux_ftm_capture_second_edge()
377 FTM_EnableInterrupts(config->base, BIT(PAIR_1ST_CH(pair))); in mcux_ftm_capture_second_edge()
380 capture->first_edge_cnt = cnt; in mcux_ftm_capture_second_edge()
381 capture->first_edge_overflows = second_edge_overflows; in mcux_ftm_capture_second_edge()
382 capture->first_edge_overflow = false; in mcux_ftm_capture_second_edge()
388 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_handle_overflow()
389 struct mcux_ftm_data *data = dev->data; in mcux_ftm_handle_overflow()
391 if (FTM_GetStatusFlags(config->base) & kFTM_TimeOverflowFlag) { in mcux_ftm_handle_overflow()
392 data->overflows++; in mcux_ftm_handle_overflow()
393 FTM_ClearStatusFlags(config->base, kFTM_TimeOverflowFlag); in mcux_ftm_handle_overflow()
402 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_irq_handler()
403 bool overflow; in mcux_ftm_irq_handler() local
409 flags = FTM_GetStatusFlags(config->base); in mcux_ftm_irq_handler()
410 irqs = FTM_GetEnabledInterrupts(config->base); in mcux_ftm_irq_handler()
411 cnt = config->base->CNT; in mcux_ftm_irq_handler()
413 overflow = mcux_ftm_handle_overflow(dev); in mcux_ftm_irq_handler()
418 mcux_ftm_capture_second_edge(dev, ch, cnt, overflow); in mcux_ftm_irq_handler()
420 mcux_ftm_capture_first_edge(dev, ch, cnt, overflow); in mcux_ftm_irq_handler()
430 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_get_cycles_per_sec()
431 struct mcux_ftm_data *data = dev->data; in mcux_ftm_get_cycles_per_sec()
433 *cycles = data->clock_freq >> config->prescale; in mcux_ftm_get_cycles_per_sec()
440 const struct mcux_ftm_config *config = dev->config; in mcux_ftm_init()
441 struct mcux_ftm_data *data = dev->data; in mcux_ftm_init()
442 ftm_chnl_pwm_config_param_t *channel = data->channel; in mcux_ftm_init()
447 err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); in mcux_ftm_init()
452 if (config->channel_count > ARRAY_SIZE(data->channel)) { in mcux_ftm_init()
454 return -EINVAL; in mcux_ftm_init()
457 if (!device_is_ready(config->clock_dev)) { in mcux_ftm_init()
458 LOG_ERR("clock control device not ready"); in mcux_ftm_init()
459 return -ENODEV; in mcux_ftm_init()
462 if (clock_control_get_rate(config->clock_dev, config->clock_subsys, in mcux_ftm_init()
463 &data->clock_freq)) { in mcux_ftm_init()
465 return -EINVAL; in mcux_ftm_init()
468 for (i = 0; i < config->channel_count; i++) { in mcux_ftm_init()
469 channel->chnlNumber = i; in mcux_ftm_init()
470 channel->level = kFTM_NoPwmSignal; in mcux_ftm_init()
471 channel->dutyValue = 0; in mcux_ftm_init()
472 channel->firstEdgeValue = 0; in mcux_ftm_init()
477 ftm_config.prescale = config->prescale; in mcux_ftm_init()
479 FTM_Init(config->base, &ftm_config); in mcux_ftm_init()
482 config->irq_config_func(dev); in mcux_ftm_init()
483 FTM_EnableInterrupts(config->base, in mcux_ftm_init()
486 data->period_cycles = 0xFFFFU; in mcux_ftm_init()
487 FTM_SetTimerPeriod(config->base, data->period_cycles); in mcux_ftm_init()
488 FTM_SetSoftwareTrigger(config->base, true); in mcux_ftm_init()
489 FTM_StartTimer(config->base, config->ftm_clock_source); in mcux_ftm_init()
511 const struct mcux_ftm_config *cfg = dev->config; in mcux_ftm_isr()
513 mcux_ftm_irq_handler(dev, 0, cfg->channel_count); in mcux_ftm_isr()
547 #if DT_INST_IRQ_HAS_NAME(0, overflow)