1 /*
2  * Copyright 2021-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_opamp.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.opamp"
16 #endif
17 
18 #if defined(OPAMP_RSTS)
19 #define OPAMP_RESETS_ARRAY OPAMP_RSTS
20 #endif
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 static uint32_t OPAMP_GetInstance(OPAMP_Type *base);
26 
27 /*******************************************************************************
28  * Variables
29  ******************************************************************************/
30 static OPAMP_Type *const s_opampBases[] = OPAMP_BASE_PTRS;
31 
32 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
33 /*! @brief Pointers to OPAMP clocks for each instance. */
34 static const clock_ip_name_t s_opampClocks[] = OPAMP_CLOCKS;
35 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
36 
37 #if defined(OPAMP_RESETS_ARRAY)
38 /* Reset array */
39 static const reset_ip_name_t s_opampResets[] = OPAMP_RESETS_ARRAY;
40 #endif
41 
42 /*******************************************************************************
43  * Code
44  ******************************************************************************/
45 
OPAMP_GetInstance(OPAMP_Type * base)46 static uint32_t OPAMP_GetInstance(OPAMP_Type *base)
47 {
48     uint32_t instance;
49 
50     /* Find the instance index from base address mappings. */
51     for (instance = 0UL; instance < ARRAY_SIZE(s_opampBases); instance++)
52     {
53         if (s_opampBases[instance] == base)
54         {
55             break;
56         }
57     }
58 
59     assert(instance < ARRAY_SIZE(s_opampBases));
60 
61     return instance;
62 }
63 
64 /*!
65  * brief Initialize OPAMP instance.
66  *
67  * param base OPAMP peripheral base address.
68  * param config The pointer to opamp_config_t.
69  */
OPAMP_Init(OPAMP_Type * base,const opamp_config_t * config)70 void OPAMP_Init(OPAMP_Type *base, const opamp_config_t *config)
71 {
72     assert(config != NULL);
73 
74     uint32_t tmp32 = 0U;
75 
76 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
77     /* Enable the clock. */
78     CLOCK_EnableClock(s_opampClocks[OPAMP_GetInstance(base)]);
79 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
80 
81 #if defined(OPAMP_RESETS_ARRAY)
82     RESET_ReleasePeripheralReset(s_opampResets[OPAMP_GetInstance(base)]);
83 #endif
84 
85     tmp32 = OPAMP_OPAMP_CTR_EN(config->enable) | OPAMP_OPAMP_CTR_MODE(config->mode) |
86             OPAMP_OPAMP_CTR_BIASC(config->trimOption) | OPAMP_OPAMP_CTR_INTREF(config->intRefVoltage) |
87             OPAMP_OPAMP_CTR_PREF(config->posRefVoltage) |
88 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW
89             OPAMP_OPAMP_CTR_OUTSW(config->enableOutputSwitch) |
90 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW */
91 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1
92             OPAMP_OPAMP_CTR_ADCSW1(config->enablePosADCSw1) |
93 #else
94             OPAMP_OPAMP_CTR_ADCSW(config->enablePosADCSw) |
95 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 */
96 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2
97             OPAMP_OPAMP_CTR_ADCSW2(config->enablePosADCSw2) |
98 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 */
99 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
100             OPAMP_OPAMP_CTR_INPSEL(config->PosInputChannelSelection) |
101 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL */
102 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
103             OPAMP_OPAMP_CTR_TRIGMD(config->enableTriggerMode) |
104 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
105             OPAMP_OPAMP_CTR_NGAIN(config->negGain);
106     base->OPAMP_CTR = tmp32;
107 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
108     if (config->enableRefBuffer)
109     {
110         assert((uint32_t)(config->posGain) <= 7UL);
111         base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain) | OPAMP_OPAMP_CTR_BUFEN_MASK;
112     }
113     else
114     {
115         if ((uint32_t)(config->posGain) > 7UL)
116         {
117             base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN((uint32_t)(config->posGain) - 7UL);
118         }
119         else
120         {
121             assert((uint32_t)(config->posGain) == 0UL);
122             base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain);
123         }
124     }
125 #else
126     base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain);
127 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
128 }
129 
130 /*!
131  * brief De-initialize OPAMP instance.
132  *
133  * param base OPAMP peripheral base address.
134  */
OPAMP_Deinit(OPAMP_Type * base)135 void OPAMP_Deinit(OPAMP_Type *base)
136 {
137     /* Disable OPAMP instance. */
138     base->OPAMP_CTR &= ~OPAMP_OPAMP_CTR_EN_MASK;
139 
140 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
141     /* Disable the clock. */
142     CLOCK_DisableClock(s_opampClocks[OPAMP_GetInstance(base)]);
143 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
144 }
145 
146 /*!
147  * brief Get default configuration of OPAMP.
148  *
149  * code
150  *     config->enable        = false;
151  *     config->mode          = kOPAMP_LowNoiseMode;
152  *     config->trimOption    = kOPAMP_TrimOptionDefault;
153  *     config->intRefVoltage = kOPAMP_IntRefVoltVddaDiv2;
154  *     config->enablePosADCSw = false;
155  *     config->posRefVoltage = kOPAMP_PosRefVoltVrefh3;
156  *     config->posGain       = kOPAMP_PosGainReserved;
157  *     config->negGain       = kOPAMP_NegGainBufferMode;
158  * endcode
159  *
160  * param config The pointer to opamp_config_t.
161  */
OPAMP_GetDefaultConfig(opamp_config_t * config)162 void OPAMP_GetDefaultConfig(opamp_config_t *config)
163 {
164     assert(config != NULL);
165 
166     config->enable        = false;
167     config->mode          = kOPAMP_LowNoiseMode;
168     config->trimOption    = kOPAMP_TrimOptionDefault;
169     config->intRefVoltage = kOPAMP_IntRefVoltVddaDiv2;
170     config->posRefVoltage = kOPAMP_PosRefVoltVrefh3;
171     config->posGain       = kOPAMP_PosGainReserved;
172     config->negGain       = kOPAMP_NegGainBufferMode;
173 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW
174     config->enableOutputSwitch = true;
175 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW */
176 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1
177     config->enablePosADCSw1 = false;
178 #else
179     config->enablePosADCSw = false;
180 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 */
181 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2
182     config->enablePosADCSw2 = false;
183 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 */
184 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
185     config->enableRefBuffer = false;
186 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN */
187 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
188     config->PosInputChannelSelection = kOPAMP_PosInputChannel0;
189 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL */
190 #if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
191     config->enableTriggerMode = false;
192 #endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
193 }
194