1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_pit.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.pit"
14 #endif
15 
16 /*******************************************************************************
17  * Prototypes
18  ******************************************************************************/
19 /*!
20  * @brief Gets the instance from the base address to be used to gate or ungate the module clock
21  *
22  * @param base PIT peripheral base address
23  *
24  * @return The PIT instance
25  */
26 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
27 static uint32_t PIT_GetInstance(PIT_Type *base);
28 #endif
29 
30 /*******************************************************************************
31  * Variables
32  ******************************************************************************/
33 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
34 /*! @brief Pointers to PIT bases for each instance. */
35 static PIT_Type *const s_pitBases[] = PIT_BASE_PTRS;
36 /*! @brief Pointers to PIT clocks for each instance. */
37 static const clock_ip_name_t s_pitClocks[] = PIT_CLOCKS;
38 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
39 
40 /*******************************************************************************
41  * Code
42  ******************************************************************************/
43 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
PIT_GetInstance(PIT_Type * base)44 static uint32_t PIT_GetInstance(PIT_Type *base)
45 {
46     uint32_t instance;
47 
48     /* Find the instance index from base address mappings. */
49     for (instance = 0; instance < ARRAY_SIZE(s_pitBases); instance++)
50     {
51         if (s_pitBases[instance] == base)
52         {
53             break;
54         }
55     }
56 
57     assert(instance < ARRAY_SIZE(s_pitBases));
58 
59     return instance;
60 }
61 #endif
62 
63 /*!
64  * brief Ungates the PIT clock, enables the PIT module, and configures the peripheral for basic operations.
65  *
66  * note This API should be called at the beginning of the application using the PIT driver.
67  *
68  * param base   PIT peripheral base address
69  * param config Pointer to the user's PIT config structure
70  */
PIT_Init(PIT_Type * base,const pit_config_t * config)71 void PIT_Init(PIT_Type *base, const pit_config_t *config)
72 {
73     assert(NULL != config);
74 
75 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
76     /* Ungate the PIT clock*/
77     CLOCK_EnableClock(s_pitClocks[PIT_GetInstance(base)]);
78 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
79 
80 #if defined(FSL_FEATURE_PIT_HAS_MDIS) && FSL_FEATURE_PIT_HAS_MDIS
81     /* Enable PIT timers */
82     base->MCR &= ~PIT_MCR_MDIS_MASK;
83 #endif
84 
85 #if defined(FSL_FEATURE_PIT_TIMER_COUNT) && (FSL_FEATURE_PIT_TIMER_COUNT)
86     /* Clear all status bits for all channels to make sure the status of all TCTRL registers is clean. */
87     for (uint8_t i = 0U; i < (uint32_t)FSL_FEATURE_PIT_TIMER_COUNT; i++)
88     {
89         base->CHANNEL[i].TCTRL &= ~(PIT_TCTRL_TEN_MASK | PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK);
90     }
91 #endif /* FSL_FEATURE_PIT_TIMER_COUNT */
92 
93     /* Config timer operation when in debug mode */
94     if (true == config->enableRunInDebug)
95     {
96         base->MCR &= ~PIT_MCR_FRZ_MASK;
97     }
98     else
99     {
100         base->MCR |= PIT_MCR_FRZ_MASK;
101     }
102 }
103 
104 /*!
105  * brief Gates the PIT clock and disables the PIT module.
106  *
107  * param base PIT peripheral base address
108  */
PIT_Deinit(PIT_Type * base)109 void PIT_Deinit(PIT_Type *base)
110 {
111 #if defined(FSL_FEATURE_PIT_HAS_MDIS) && FSL_FEATURE_PIT_HAS_MDIS
112     /* Disable PIT timers */
113     base->MCR |= PIT_MCR_MDIS_MASK;
114 #endif
115 
116 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
117     /* Gate the PIT clock*/
118     CLOCK_DisableClock(s_pitClocks[PIT_GetInstance(base)]);
119 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
120 }
121 
122 #if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
123 
124 /*!
125  * brief Reads the current lifetime counter value.
126  *
127  * The lifetime timer is a 64-bit timer which chains timer 0 and timer 1 together.
128  * Timer 0 and 1 are chained by calling the PIT_SetTimerChainMode before using this timer.
129  * The period of lifetime timer is equal to the "period of timer 0 * period of timer 1".
130  * For the 64-bit value, the higher 32-bit has the value of timer 1, and the lower 32-bit
131  * has the value of timer 0.
132  *
133  * param base PIT peripheral base address
134  *
135  * return Current lifetime timer value
136  */
PIT_GetLifetimeTimerCount(PIT_Type * base)137 uint64_t PIT_GetLifetimeTimerCount(PIT_Type *base)
138 {
139     uint32_t valueH = 0U;
140     uint32_t valueL = 0U;
141 
142     /* LTMR64H should be read before LTMR64L */
143     valueH = base->LTMR64H;
144     valueL = base->LTMR64L;
145 
146     return (((uint64_t)valueH << 32U) + (uint64_t)(valueL));
147 }
148 
149 #endif /* FSL_FEATURE_PIT_HAS_LIFETIME_TIMER */
150