1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * Description: Provides adc driver source \n
16 *
17 * History: \n
18 * 2022-09-16, Create file. \n
19 */
20
21 #include "common_def.h"
22 #include "hal_adc.h"
23 #include "adc_porting.h"
24 #include "adc.h"
25
26 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
27 bool adc_is_power_on[AFE_SCAN_MODE_MAX_NUM] = {false}; /* ADC is power on or not. */
28 #else
29 bool adc_is_power_on = false; /* ADC is power on or not. */
30 #endif /* CONFIG_ADC_SUPPORT_AFE */
31
32 bool adc_is_initialised = false; /* ADC is initialised or not. */
33
34 #if defined(CONFIG_ADC_SUPPORT_DIFFERENTIAL)
35 uint8_t adc_working_channel[2] = {0}; /* ADC differential channel be choosed. */
36 #else
37 uint8_t adc_working_channel = 0; /* ADC channel be choosed. */
38 #endif /* CONFIG_ADC_SUPPORT_DIFFERENTIAL */
39
40 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
41 afe_scan_mode_t adc_working_afe = AFE_SCAN_MODE_MAX_NUM;
42 #endif /* CONFIG_ADC_SUPPORT_AFE */
43
44
45 static hal_adc_funcs_t *g_hal_funcs = NULL;
46
uapi_adc_init(adc_clock_t clock)47 errcode_t uapi_adc_init(adc_clock_t clock)
48 {
49 if (adc_is_initialised) {
50 return ERRCODE_SUCC;
51 }
52
53 adc_port_init_clock(clock);
54 adc_port_clock_enable(true);
55 adc_port_register_hal_funcs();
56 g_hal_funcs = hal_adc_get_funcs();
57 errcode_t ret = g_hal_funcs->init();
58 if (ret != ERRCODE_SUCC) {
59 return ret;
60 }
61 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
62 adc_port_register_irq();
63 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
64 adc_is_initialised = true;
65
66 return ret;
67 }
68
uapi_adc_deinit(void)69 errcode_t uapi_adc_deinit(void)
70 {
71 if (!adc_is_initialised) {
72 return ERRCODE_SUCC;
73 }
74
75 errcode_t ret = g_hal_funcs->deinit();
76
77 adc_port_unregister_hal_funcs();
78
79 adc_port_clock_enable(false);
80 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
81 adc_port_unregister_irq();
82 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
83 adc_is_initialised = false;
84
85 return ret;
86 }
87
uapi_adc_power_en(afe_scan_mode_t afe_scan_mode,bool en)88 void uapi_adc_power_en(afe_scan_mode_t afe_scan_mode, bool en)
89 {
90 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
91 if (afe_scan_mode >= AFE_SCAN_MODE_MAX_NUM || adc_is_power_on[afe_scan_mode] == en) {
92 return;
93 }
94 #else
95 if (adc_is_power_on == en) {
96 return;
97 }
98 #endif /* CONFIG_ADC_SUPPORT_AFE */
99
100 adc_port_power_on(en);
101 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
102 #if (AFE_ENABLE_INTERRUPT)
103 if (en) {
104 adc_working_afe = afe_scan_mode;
105 adc_port_register_irq(afe_scan_mode);
106 } else {
107 adc_port_unregister_irq(afe_scan_mode);
108 }
109 #endif /* AFE_ENABLE_INTERRUPT */
110 #endif /* CONFIG_ADC_SUPPORT_AFE */
111
112 g_hal_funcs->power_en(afe_scan_mode, en);
113
114 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
115 adc_is_power_on[afe_scan_mode] = en;
116 #else
117 adc_is_power_on = en;
118 #endif /* CONFIG_ADC_SUPPORT_AFE */
119 }
120
uapi_adc_is_using(void)121 bool uapi_adc_is_using(void)
122 {
123 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
124 return adc_is_power_on[AFE_GADC_MODE] || adc_is_power_on[AFE_HADC_MODE];
125 #else
126 return adc_is_power_on;
127 #endif /* CONFIG_ADC_SUPPORT_AFE */
128 }
129
uapi_adc_open_channel(uint8_t channel)130 errcode_t uapi_adc_open_channel(uint8_t channel)
131 {
132 if (unlikely(channel >= ADC_CHANNEL_MAX_NUM)) {
133 return ERRCODE_ADC_INVALID_PARAMETER;
134 }
135
136 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
137 if (uapi_adc_auto_scan_is_enabled()) {
138 return ERRCODE_ADC_SCAN_NOT_DISABLE;
139 }
140 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
141 uint32_t irq_sts = adc_irq_lock();
142 #if defined(CONFIG_ADC_SUPPORT_AFE)
143 errcode_t ret = g_hal_funcs->ch_set(channel, true);
144 #else
145 errcode_t ret = g_hal_funcs->ch_set((adc_channel_t)channel, true);
146 #endif /* CONFIG_ADC_SUPPORT_AFE */
147 adc_irq_unlock(irq_sts);
148 if (ret == ERRCODE_SUCC) {
149 #if defined(CONFIG_ADC_SUPPORT_DIFFERENTIAL)
150 adc_working_channel[0] = channel;
151 #else
152 adc_working_channel = channel;
153 #endif
154 }
155
156 return ret;
157 }
158
uapi_adc_close_channel(uint8_t channel)159 errcode_t uapi_adc_close_channel(uint8_t channel)
160 {
161 #if defined(CONFIG_ADC_SUPPORT_DIFFERENTIAL)
162 if (unlikely(channel != adc_working_channel[0])) {
163 return ERRCODE_ADC_INVALID_PARAMETER;
164 }
165 #else
166 if (unlikely(channel != adc_working_channel)) {
167 return ERRCODE_ADC_INVALID_PARAMETER;
168 }
169 #endif
170
171 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
172 if (uapi_adc_auto_scan_is_enabled()) {
173 return ERRCODE_ADC_SCAN_NOT_DISABLE;
174 }
175 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
176
177 uint32_t irq_sts = adc_irq_lock();
178 errcode_t ret = g_hal_funcs->ch_set((adc_channel_t)channel, false);
179 adc_irq_unlock(irq_sts);
180 if (ret == ERRCODE_SUCC) {
181 #if defined(CONFIG_ADC_SUPPORT_DIFFERENTIAL)
182 adc_working_channel[0] = ADC_CHANNEL_NONE;
183 #else
184 adc_working_channel = ADC_CHANNEL_NONE;
185 #endif
186 }
187 return ret;
188 }
189
190 #if defined(CONFIG_ADC_SUPPORT_DIFFERENTIAL)
uapi_adc_open_differential_channel(uint8_t postive_ch,uint8_t negative_ch)191 errcode_t uapi_adc_open_differential_channel(uint8_t postive_ch, uint8_t negative_ch)
192 {
193 if (unlikely(postive_ch >= ADC_CHANNEL_MAX_NUM) || unlikely(negative_ch >= ADC_CHANNEL_MAX_NUM)) {
194 return ERRCODE_ADC_INVALID_PARAMETER;
195 }
196
197 uint32_t irq_sts = adc_irq_lock();
198 errcode_t ret = g_hal_funcs->diff_ch_set((adc_channel_t)postive_ch, (adc_channel_t)negative_ch, true);
199 adc_irq_unlock(irq_sts);
200 if (ret == ERRCODE_SUCC) {
201 adc_working_channel[0] = postive_ch;
202 adc_working_channel[1] = negative_ch;
203 }
204
205 return ret;
206 }
207
uapi_adc_close_differential_channel(uint8_t postive_ch,uint8_t negative_ch)208 errcode_t uapi_adc_close_differential_channel(uint8_t postive_ch, uint8_t negative_ch)
209 {
210 if (unlikely(postive_ch != adc_working_channel[0]) ||
211 unlikely(negative_ch != adc_working_channel[1])) {
212 return ERRCODE_ADC_INVALID_PARAMETER;
213 }
214
215 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
216 if (uapi_adc_auto_scan_is_enabled()) {
217 return ERRCODE_ADC_SCAN_NOT_DISABLE;
218 }
219 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
220
221 uint32_t irq_sts = adc_irq_lock();
222 errcode_t ret = g_hal_funcs->diff_ch_set((adc_channel_t)postive_ch, (adc_channel_t)negative_ch, false);
223 adc_irq_unlock(irq_sts);
224 if (ret == ERRCODE_SUCC) {
225 adc_working_channel[0] = ADC_CHANNEL_NONE;
226 adc_working_channel[1] = ADC_CHANNEL_NONE;
227 }
228 return ret;
229 }
230 #endif
231
232 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
adc_auto_scan_ch_param_check(uint8_t channel,adc_scan_config_t * config,adc_callback_t callback)233 static bool adc_auto_scan_ch_param_check(uint8_t channel, adc_scan_config_t *config, adc_callback_t callback)
234 {
235 if (unlikely(channel >= ADC_CHANNEL_MAX_NUM)) {
236 return false;
237 }
238
239 if (unlikely(callback == NULL)) {
240 return false;
241 }
242
243 if (unlikely(config->type > HAL_ADC_SCAN_TYPE_THRESHOLD)) {
244 return false;
245 }
246
247 if (unlikely(config->freq >= HAL_ADC_SCAN_FREQ_MAX)) {
248 return false;
249 }
250
251 return true;
252 }
253
uapi_adc_auto_scan_ch_enable(uint8_t channel,adc_scan_config_t config,adc_callback_t callback)254 errcode_t uapi_adc_auto_scan_ch_enable(uint8_t channel, adc_scan_config_t config, adc_callback_t callback)
255 {
256 hal_adc_scan_config_t adc_config;
257
258 if (!adc_auto_scan_ch_param_check(channel, &config, callback)) {
259 return ERRCODE_ADC_INVALID_PARAMETER;
260 }
261 if (unlikely(!adc_is_power_on)) {
262 return ERRCODE_PWM_NOT_POWER_ON;
263 }
264
265 adc_config.type = (hal_adc_scan_type_t)config.type;
266 adc_config.freq = (hal_adc_scan_freq_t)config.freq;
267 #if defined(CONFIG_ADC_SUPPORT_LONG_SAMPLE)
268 adc_config.long_sample_time = config.long_sample_time;
269 #endif
270 adc_config.threshold_l = config.threshold_l;
271 adc_config.threshold_h = config.threshold_h;
272
273 adc_port_init_clock(ADC_CLOCK_500KHZ);
274
275 errcode_t ret = g_hal_funcs->ch_config((adc_channel_t)channel, &adc_config, (hal_adc_callback_t)callback);
276 if (ret != ERRCODE_SUCC) {
277 adc_port_init_clock(ADC_CLOCK_015KHZ);
278 }
279
280 return ret;
281 }
282
uapi_adc_auto_scan_ch_disable(uint8_t channel)283 errcode_t uapi_adc_auto_scan_ch_disable(uint8_t channel)
284 {
285 if (unlikely(channel >= ADC_CHANNEL_MAX_NUM)) {
286 return ERRCODE_ADC_INVALID_PARAMETER;
287 }
288
289 return g_hal_funcs->ch_enable((adc_channel_t)channel, false);
290 }
291
uapi_adc_auto_scan_disable(void)292 void uapi_adc_auto_scan_disable(void)
293 {
294 g_hal_funcs->enable(false);
295 uapi_adc_open_channel(ADC_CHANNEL_NONE);
296 #if defined(CONFIG_ADC_SUPPORT_AFE) && defined(CONFIG_ADC_SUPPORT_HAFE)
297 uapi_adc_power_en(adc_working_afe, false);
298 #else
299 uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, false);
300 #endif /* CONFIG_ADC_SUPPORT_AFE */
301 }
302
uapi_adc_auto_scan_is_enabled(void)303 bool uapi_adc_auto_scan_is_enabled(void)
304 {
305 return g_hal_funcs->isenable();
306 }
307 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
308
uapi_adc_manual_sample(uint8_t channel)309 int32_t uapi_adc_manual_sample(uint8_t channel)
310 {
311 if (channel >= ADC_CHANNEL_MAX_NUM) { return 0; }
312
313 return g_hal_funcs->manual((adc_channel_t)channel);
314 }
315
316 #if defined(CONFIG_ADC_SUPPORT_AFE)
uapi_adc_auto_sample(uint8_t channel)317 int32_t uapi_adc_auto_sample(uint8_t channel)
318 {
319 if (channel >= ADC_CHANNEL_MAX_NUM) { return 0; }
320
321 return g_hal_funcs->auto_sample((adc_channel_t)channel);
322 }
323 #endif /* CONFIG_ADC_SUPPORT_AFE */
324