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