• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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