1 /*
2  * Copyright 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_hscmp.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.hscmp"
16 #endif
17 
18 #if defined(HSCMP_RSTS)
19 #define HSCMP_RESETS_ARRAY HSCMP_RSTS
20 #endif
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 #if defined(HSCMP_CLOCKS)
26 /*!
27  * @brief Get instance number for HSCMP module.
28  *
29  * @param base HSCMP peripheral base address
30  */
31 static uint32_t HSCMP_GetInstance(HSCMP_Type *base);
32 #endif /* HSCMP_CLOCKS */
33 
34 /*******************************************************************************
35  * Variables
36  ******************************************************************************/
37 #if defined(HSCMP_CLOCKS)
38 /*! @brief Pointers to HSCMP bases for each instance. */
39 static HSCMP_Type *const s_hscmpBases[] = HSCMP_BASE_PTRS;
40 
41 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
42 /*! @brief Pointers to HSCMP clocks for each instance. */
43 static const clock_ip_name_t s_hscmpClocks[] = HSCMP_CLOCKS;
44 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
45 #endif /* HSCMP_CLOCKS */
46 
47 #if defined(HSCMP_RESETS_ARRAY)
48 /* Reset array */
49 static const reset_ip_name_t s_hscmpResets[] = HSCMP_RESETS_ARRAY;
50 #endif
51 
52 /*******************************************************************************
53  * Codes
54  ******************************************************************************/
55 #if defined(HSCMP_CLOCKS) || defined(HSCMP_RESETS_ARRAY)
HSCMP_GetInstance(HSCMP_Type * base)56 static uint32_t HSCMP_GetInstance(HSCMP_Type *base)
57 {
58     uint32_t instance;
59 
60     /* Find the instance index from base address mappings. */
61     for (instance = 0; instance < ARRAY_SIZE(s_hscmpBases); instance++)
62     {
63         if (s_hscmpBases[instance] == base)
64         {
65             break;
66         }
67     }
68 
69     assert(instance < ARRAY_SIZE(s_hscmpBases));
70 
71     return instance;
72 }
73 #endif /* HSCMP_CLOCKS */
74 
75 /*!
76  * brief Initialize the HSCMP
77  *
78  * This function initializes the HSCMP module. The operations included are:
79  * - Enabling the clock for HSCMP module.
80  * - Configuring the comparator.
81  * - Enabling the HSCMP module.
82  * Note: For some devices, multiple HSCMP instance share the same clock gate. In this case, to enable the clock for
83  * any instance enables all the HSCMPs. Check the chip reference manual for the clock assignment of the HSCMP.
84  *
85  * param base HSCMP peripheral base address.
86  * param config Pointer to "hscmp_config_t" structure.
87  */
HSCMP_Init(HSCMP_Type * base,const hscmp_config_t * config)88 void HSCMP_Init(HSCMP_Type *base, const hscmp_config_t *config)
89 {
90     assert(config != NULL);
91 
92     uint32_t tmp32;
93 
94 #if defined(HSCMP_CLOCKS)
95 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
96     /* Enable the clock. */
97     CLOCK_EnableClock(s_hscmpClocks[HSCMP_GetInstance(base)]);
98 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
99 #endif /* HSCMP_CLOCKS */
100 
101 #if defined(HSCMP_RESETS_ARRAY)
102     RESET_ReleasePeripheralReset(s_hscmpResets[HSCMP_GetInstance(base)]);
103 #endif
104 
105     /* Configure. */
106     HSCMP_Enable(base, false);
107     /* CCR0 register. */
108     if (config->enableStopMode)
109     {
110         base->CCR0 |= HSCMP_CCR0_CMP_STOP_EN_MASK;
111     }
112     else
113     {
114         base->CCR0 &= ~HSCMP_CCR0_CMP_STOP_EN_MASK;
115     }
116     /* CCR1 register. */
117     tmp32 = base->CCR1 & ~(HSCMP_CCR1_COUT_PEN_MASK | HSCMP_CCR1_COUT_SEL_MASK | HSCMP_CCR1_COUT_INV_MASK);
118     if (config->enableOutputPin)
119     {
120         tmp32 |= HSCMP_CCR1_COUT_PEN_MASK;
121     }
122     if (config->useUnfilteredOutput)
123     {
124         tmp32 |= HSCMP_CCR1_COUT_SEL_MASK;
125     }
126     if (config->enableInvertOutput)
127     {
128         tmp32 |= HSCMP_CCR1_COUT_INV_MASK;
129     }
130     base->CCR1 = tmp32;
131     /* CCR2 register. */
132     tmp32 = base->CCR2 & ~(HSCMP_CCR2_HYSTCTR_MASK | HSCMP_CCR2_CMP_NPMD_MASK | HSCMP_CCR2_CMP_HPMD_MASK);
133     tmp32 |= HSCMP_CCR2_HYSTCTR(config->hysteresisMode);
134     tmp32 |= ((uint32_t)(config->powerMode) << HSCMP_CCR2_CMP_HPMD_SHIFT);
135     base->CCR2 = tmp32;
136 
137     HSCMP_Enable(base, true); /* Enable the HSCMP module. */
138 }
139 
140 /*!
141  * brief De-initializes the HSCMP module.
142  *
143  * This function de-initializes the HSCMP module. The operations included are:
144  * - Disabling the HSCMP module.
145  * - Disabling the clock for HSCMP module.
146  *
147  * This function disables the clock for the HSCMP.
148  * Note: For some devices, multiple HSCMP instance shares the same clock gate. In this case, before disabling the
149  * clock for the HSCMP, ensure that all the HSCMP instances are not used.
150  *
151  * param base HSCMP peripheral base address.
152  */
HSCMP_Deinit(HSCMP_Type * base)153 void HSCMP_Deinit(HSCMP_Type *base)
154 {
155     /* Disable the HSCMP module. */
156     HSCMP_Enable(base, false);
157 #if defined(HSCMP_CLOCKS)
158 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
159     /* Disable the clock. */
160     CLOCK_DisableClock(s_hscmpClocks[HSCMP_GetInstance(base)]);
161 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
162 #endif /* HSCMP_CLOCKS */
163 }
164 
165 /*!
166  * brief Gets an available pre-defined settings for the comparator's configuration.
167  *
168  * This function initializes the comparator configuration structure to these default values:
169  * code
170  *   config->enableStopMode      = false;
171  *   config->enableOutputPin     = false;
172  *   config->useUnfilteredOutput = false;
173  *   config->enableInvertOutput  = false;
174  *   config->hysteresisMode      = kHSCMP_HysteresisLevel0;
175  *   config->powerMode           = kHSCMP_LowSpeedPowerMode;
176  * endcode
177  * param config Pointer to "hscmp_config_t" structure.
178  */
HSCMP_GetDefaultConfig(hscmp_config_t * config)179 void HSCMP_GetDefaultConfig(hscmp_config_t *config)
180 {
181     /* Initializes the configure structure to zero. */
182     (void)memset(config, 0, sizeof(*config));
183 
184     config->enableStopMode      = false;
185     config->enableOutputPin     = false;
186     config->useUnfilteredOutput = false;
187     config->enableInvertOutput  = false;
188     config->hysteresisMode      = kHSCMP_HysteresisLevel0;
189     config->powerMode           = kHSCMP_LowSpeedPowerMode;
190 }
191 
192 /*!
193  * brief Select the input channels for HSCMP. This function determines which input
194  *        is selected for the negative and positive mux.
195  *
196  * param base HSCMP peripheral base address.
197  * param positiveChannel Positive side input channel number. Available range is 0-7.
198  * param negativeChannel Negative side input channel number. Available range is 0-7.
199  */
HSCMP_SetInputChannels(HSCMP_Type * base,uint32_t positiveChannel,uint32_t negativeChannel)200 void HSCMP_SetInputChannels(HSCMP_Type *base, uint32_t positiveChannel, uint32_t negativeChannel)
201 {
202     uint32_t tmp32;
203 
204     tmp32 = base->CCR2 & ~(HSCMP_CCR2_PSEL_MASK | HSCMP_CCR2_MSEL_MASK);
205     tmp32 |= HSCMP_CCR2_PSEL(positiveChannel) | HSCMP_CCR2_MSEL(negativeChannel);
206     base->CCR2 = tmp32;
207 }
208 
209 /*!
210  * brief Configures the filter.
211  *
212  * param base HSCMP peripheral base address.
213  * param config Pointer to "hscmp_filter_config_t" structure.
214  */
HSCMP_SetFilterConfig(HSCMP_Type * base,const hscmp_filter_config_t * config)215 void HSCMP_SetFilterConfig(HSCMP_Type *base, const hscmp_filter_config_t *config)
216 {
217     assert(config != NULL);
218 
219     uint32_t tmp32;
220 
221     tmp32 = base->CCR1 & ~(HSCMP_CCR1_FILT_PER_MASK | HSCMP_CCR1_FILT_CNT_MASK | HSCMP_CCR1_SAMPLE_EN_MASK);
222     if (config->enableSample)
223     {
224         tmp32 |= HSCMP_CCR1_SAMPLE_EN_MASK;
225     }
226     tmp32 |= HSCMP_CCR1_FILT_PER(config->filterSamplePeriod) | HSCMP_CCR1_FILT_CNT(config->filterSampleCount);
227     base->CCR1 = tmp32;
228 }
229 
230 /*!
231  * brief Configure the internal DAC module.
232  *
233  * param base HSCMP peripheral base address.
234  * param config Pointer to "hscmp_dac_config_t" structure. If config is "NULL", disable internal DAC.
235  */
HSCMP_SetDACConfig(HSCMP_Type * base,const hscmp_dac_config_t * config)236 void HSCMP_SetDACConfig(HSCMP_Type *base, const hscmp_dac_config_t *config)
237 {
238     uint32_t tmp32;
239     if (config == NULL)
240     {
241         tmp32 = 0U; /* Disable internal DAC. */
242     }
243     else
244     {
245         tmp32 = HSCMP_DCR_VRSEL(config->referenceVoltageSource) | HSCMP_DCR_DAC_DATA(config->DACValue);
246         if (config->enableLowPowerMode)
247         {
248             tmp32 |= HSCMP_DCR_DAC_HPMD_MASK;
249         }
250         tmp32 |= HSCMP_DCR_DAC_EN_MASK;
251     }
252     base->DCR = tmp32;
253 }
254