1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_freqme.h"
8 
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.lpc_freqme"
16 #endif
17 
18 #if defined(FREQME_RSTS_N)
19 #define FREQME_RESETS_ARRAY FREQME_RSTS_N
20 #endif
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 static uint32_t FREQME_GetInstance(FREQME_Type *base);
26 
27 /*******************************************************************************
28  * Variables
29  ******************************************************************************/
30 /*! @brief Array to map freqme instance number to base address. */
31 static FREQME_Type *const s_freqmeBases[] = FREQME_BASE_PTRS;
32 
33 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
34 /*! @brief Pointers to FREQME clocks for each instance. */
35 static const clock_ip_name_t s_freqmeClocks[] = FREQME_CLOCKS;
36 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
37 
38 #if defined(FREQME_RESETS_ARRAY)
39 /* Reset array */
40 static const reset_ip_name_t s_freqmeResets[] = FREQME_RESETS_ARRAY;
41 #endif
42 /*******************************************************************************
43  * Code
44  ******************************************************************************/
FREQME_GetInstance(FREQME_Type * base)45 static uint32_t FREQME_GetInstance(FREQME_Type *base)
46 {
47     uint32_t instance;
48 
49     /* Find the instance index from base address mappings. */
50     for (instance = 0U; instance < ARRAY_SIZE(s_freqmeBases); instance++)
51     {
52         if (MSDK_REG_SECURE_ADDR(s_freqmeBases[instance]) == MSDK_REG_SECURE_ADDR(base))
53         {
54             break;
55         }
56     }
57 
58     assert(instance < ARRAY_SIZE(s_freqmeBases));
59 
60     return instance;
61 }
62 
63 /*!
64  * brief Initialize freqme module, set operate mode, operate mode attribute and initialize measurement cycle.
65  *
66  * param base FREQME peripheral base address.
67  * param config The pointer to module basic configuration, please refer to freq_measure_config_t.
68  */
FREQME_Init(FREQME_Type * base,const freq_measure_config_t * config)69 void FREQME_Init(FREQME_Type *base, const freq_measure_config_t *config)
70 {
71     assert(config);
72 
73     uint32_t tmp32 = 0UL;
74 
75 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
76     /* Enable FREQME clock. */
77     CLOCK_EnableClock(s_freqmeClocks[FREQME_GetInstance(base)]);
78 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
79 
80 #if defined(FREQME_RESETS_ARRAY)
81     RESET_ReleasePeripheralReset(s_freqmeResets[FREQME_GetInstance(base)]);
82 #endif
83 
84     if (config->startMeasurement)
85     {
86         tmp32 |= FREQME_CTRL_W_MEASURE_IN_PROGRESS_MASK;
87     }
88     tmp32 |= FREQME_CTRL_W_CONTINUOUS_MODE_EN(config->enableContinuousMode) |
89              FREQME_CTRL_W_PULSE_MODE(config->operateMode);
90     if (config->operateMode == kFREQME_FreqMeasurementMode)
91     {
92         tmp32 |= FREQME_CTRL_W_REF_SCALE(config->operateModeAttribute.refClkScaleFactor);
93     }
94     else
95     {
96         tmp32 |= FREQME_CTRL_W_PULSE_POL(config->operateModeAttribute.pulsePolarity);
97     }
98 
99     base->CTRL_W = tmp32;
100 }
101 
102 /*!
103  * brief Get default configuration.
104  *
105  * code
106  *      config->operateMode = kFREQME_FreqMeasurementMode;
107  *      config->operateModeAttribute.refClkScaleFactor = 0U;
108  *      config->enableContinuousMode                   = false;
109  *      config->startMeasurement                       = false;
110  * endcode
111  *
112  * param config The pointer to module basic configuration, please refer to freq_measure_config_t.
113  */
FREQME_GetDefaultConfig(freq_measure_config_t * config)114 void FREQME_GetDefaultConfig(freq_measure_config_t *config)
115 {
116     assert(config);
117 
118     (void)memset(config, 0, sizeof(*config));
119 
120     config->operateMode                            = kFREQME_FreqMeasurementMode;
121     config->operateModeAttribute.refClkScaleFactor = 0U;
122     config->enableContinuousMode                   = false;
123     config->startMeasurement                       = false;
124 }
125 
126 /*!
127  * brief Calculate the frequency of selected target clock.
128  *
129  * note The formula: Ftarget = (RESULT - 2) * Freference / 2 ^ REF_SCALE.
130  *
131  * note This function only useful when the operate mode is selected as frequency measurement mode.
132  *
133  * param base FREQME peripheral base address.
134  * param refClkFrequency The frequency of reference clock.
135  * return The frequency of target clock, if the output result is 0, please check the module's operate mode.
136  */
FREQME_CalculateTargetClkFreq(FREQME_Type * base,uint32_t refClkFrequency)137 uint32_t FREQME_CalculateTargetClkFreq(FREQME_Type *base, uint32_t refClkFrequency)
138 {
139     uint32_t measureResult = 0UL;
140     uint32_t targetFreq    = 0UL;
141     uint64_t tmp64         = 0ULL;
142 
143     while ((base->CTRL_R & FREQME_CTRL_R_MEASURE_IN_PROGRESS_MASK) != 0UL)
144     {
145     }
146 
147     if (!FREQME_CheckOperateMode(base))
148     {
149         measureResult = base->CTRL_R & FREQME_CTRL_R_RESULT_MASK;
150         tmp64         = ((uint64_t)measureResult - 2ULL) * (uint64_t)refClkFrequency;
151         targetFreq    = (uint32_t)(tmp64 / (1ULL << (uint64_t)FREQME_GetReferenceClkScaleValue(base)));
152     }
153 
154     return targetFreq;
155 }
156