1 /* 2 * Copyright (c) 2016 Nordic Semiconductor ASA 3 * Copyright (c) 2016 Vinayak Kariappa Chettimada 4 * Copyright 2019 NXP 5 * 6 * SPDX-License-Identifier: Apache-2.0 7 */ 8 9 #include <stdint.h> 10 11 #include <zephyr/dt-bindings/interrupt-controller/openisa-intmux.h> 12 13 #include "hal/cntr.h" 14 #include "hal/debug.h" 15 16 #include "ll_irqs.h" 17 18 #include <fsl_device_registers.h> 19 20 #define PCS_SOURCE_RTC 2 21 cntr_init(void)22void cntr_init(void) 23 { 24 /* RTC config */ 25 /* 26 * Reset all RTC registers except for the SWR bit 27 * and the RTC_WAR and RTC_RAR 28 */ 29 RTC->CR |= RTC_CR_SWR_MASK; 30 RTC->CR &= ~RTC_CR_SWR_MASK; 31 32 /* 33 * Set TSR register to 0x1 to avoid the timer invalid (TIF) bit being 34 * set in the SR register 35 */ 36 RTC->TSR = 1; 37 38 /* Enable the RTC 32.768 kHz oscillator and clock on RTC_CLKOUT */ 39 RTC->CR |= (RTC_CR_CPS(1) | RTC_CR_OSCE(1)); 40 41 /* LPTMR config */ 42 /* Disable the timer and clear any pending IRQ. */ 43 LPTMR1->CSR = LPTMR_CSR_TEN(0); 44 45 /* 46 * TMS = 0: time counter mode, not pulse counter 47 * TFC = 1: reset counter on overflow 48 * TIE = 1: enable interrupt 49 */ 50 LPTMR1->CSR = (LPTMR_CSR_TFC(1) | LPTMR_CSR_TIE(1)); 51 52 /* 53 * PCS = 2: clock source is RTC - 32 kHz clock (SoC dependent) 54 * PBYP = 1: bypass the prescaler 55 */ 56 LPTMR1->PSR = (LPTMR_PSR_PBYP(1) | LPTMR_PSR_PCS(PCS_SOURCE_RTC)); 57 58 irq_enable(LL_RTC0_IRQn_2nd_lvl); 59 } 60 61 static uint8_t refcount; 62 static uint32_t cnt_diff; 63 cntr_start(void)64uint32_t cntr_start(void) 65 { 66 if (refcount++) { 67 return 1; 68 } 69 70 LPTMR1->CMR = 0xFFFFFFFF; 71 LPTMR1->CSR |= LPTMR_CSR_TEN(1); 72 73 return 0; 74 } 75 cntr_stop(void)76uint32_t cntr_stop(void) 77 { 78 LL_ASSERT(refcount); 79 80 if (--refcount) { 81 return 1; 82 } 83 84 cnt_diff = cntr_cnt_get(); 85 /* 86 * When TEN is clear, it resets the LPTMR internal logic, 87 * including the CNR and TCF. 88 */ 89 LPTMR1->CSR &= ~LPTMR_CSR_TEN_MASK; 90 91 return 0; 92 } 93 cntr_cnt_get(void)94uint32_t cntr_cnt_get(void) 95 { 96 /* 97 * On each read of the CNR, 98 * software must first write to the CNR with any value. 99 */ 100 LPTMR1->CNR = 0; 101 return (LPTMR1->CNR + cnt_diff); 102 } 103 cntr_cmp_set(uint8_t cmp,uint32_t value)104void cntr_cmp_set(uint8_t cmp, uint32_t value) 105 { 106 /* 107 * When the LPTMR is enabled, the first increment will take an 108 * additional one or two prescaler clock cycles due to 109 * synchronization logic. 110 */ 111 cnt_diff = cntr_cnt_get() + 1; 112 LPTMR1->CSR &= ~LPTMR_CSR_TEN_MASK; 113 114 value -= cnt_diff; 115 /* 116 * If the CMR is 0, the hardware trigger will remain asserted until 117 * the LPTMR is disabled. If the LPTMR is enabled, the CMR must be 118 * altered only when TCF is set. 119 */ 120 if (value == 0) { 121 value = 1; 122 } 123 124 LPTMR1->CMR = value; 125 LPTMR1->CSR |= LPTMR_CSR_TEN(1); 126 } 127