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 V154 HAL adc \n
16 *
17 * History: \n
18 * 2024-02-01, Create file. \n
19 */
20 #include "common_def.h"
21 #include "tcxo.h"
22 #include "hal_adc.h"
23 #include "debug_print.h"
24 #include "osal_debug.h"
25 #include "pinctrl_porting.h"
26 #include "pinctrl.h"
27 #include "gpio.h"
28 #include "adc_porting.h"
29 #include "hal_adc_v154.h"
30
31 #define DELAY_500US 500
32 #define DELAY_300US 300
33 #define FIFO_DATA_LENS 128
34 #define MANUAL_CALI_LOW_LIMIT1 0
35 #define MANUAL_CALI_UPPER_LIMIT1 2
36 #define MANUAL_CALI_LOW_LIMIT2 3
37 #define MANUAL_CALI_UPPER_LIMIT2 31
38 #define MANUAL_CALI_LOW_LIMIT3 32
39 #define MANUAL_CALI_UPPER_LIMIT3 60
40 #define MANUAL_CALI_LOW_LIMIT4 61
41 #define MANUAL_CALI_UPPER_LIMIT4 63
42 #define MANUAL_CALI_GAIN 3
43 #define MANUAL_CALI_THRESHOLD 63
44 #define COUNT_THRESHOLD 1000
45 #define VOLTAGE_UPPER_LIMIT 3600
46 #define CH_NUM 6
47
48 static hal_adc_callback_t g_adc_receive_data_callback = NULL;
49
50 uint32_t g_fifo_data[FIFO_DATA_LENS];
51 uint32_t g_ch_output_data[CH_NUM][FIFO_DATA_LENS];
52 uint32_t g_ch_data_cnt[CH_NUM];
53
54 static bool g_adc_auto_scan_status = false;
55
hal_adc_v154_init(void)56 static errcode_t hal_adc_v154_init(void)
57 {
58 if (hal_adc_v154_regs_init() != ERRCODE_SUCC) {
59 return ERRCODE_ADC_REG_ADDR_INVALID;
60 }
61 return ERRCODE_SUCC;
62 }
63
hal_adc_v154_deinit(void)64 static errcode_t hal_adc_v154_deinit(void)
65 {
66 return ERRCODE_SUCC;
67 }
68
hal_adc_simulation_cfg(void)69 static void hal_adc_simulation_cfg(void)
70 {
71 hal_adc_simu_cfg1();
72 hal_adc_simu_cfg2();
73 hal_adc_simu_cfg3();
74 hal_adc_simu_ldo_start();
75 uapi_tcxo_delay_us(DELAY_500US);
76 hal_adc_simu_cfg4();
77 uapi_tcxo_delay_us(DELAY_300US);
78 hal_adc_simu_cfg5();
79 hal_adc_simu_cfg6();
80 uapi_tcxo_delay_us(DELAY_300US);
81 hal_adc_simu_rst_clr();
82 }
83
hal_adc_offset_auto_cali(void)84 static void hal_adc_offset_auto_cali(void)
85 {
86 hal_adc_offset_cali_state_clr();
87 hal_adc_offset_cali_data_spi_refresh();
88 hal_adc_offset_cali_set();
89 hal_adc_offset_cali_enable(1);
90 uint32_t cnt = 0;
91 while (hal_adc_offset_cali_sts() != 1) {
92 if (cnt > COUNT_THRESHOLD) {
93 break;
94 }
95 cnt++;
96 }
97 hal_adc_offset_cali_enable(0);
98 }
99
hal_adc_offset_manual_cali(void)100 static void hal_adc_offset_manual_cali(void)
101 {
102 uint32_t auto_cali_data;
103 uint32_t temp;
104 auto_cali_data = hal_adc_auto_offset_cali_data_get();
105 if (auto_cali_data >= MANUAL_CALI_LOW_LIMIT1 && auto_cali_data <= MANUAL_CALI_UPPER_LIMIT1) {
106 temp = 0;
107 } else if (auto_cali_data >= MANUAL_CALI_LOW_LIMIT2 && auto_cali_data <= MANUAL_CALI_UPPER_LIMIT2) {
108 temp = auto_cali_data - MANUAL_CALI_GAIN;
109 } else if (auto_cali_data >= MANUAL_CALI_LOW_LIMIT3 && auto_cali_data <= MANUAL_CALI_UPPER_LIMIT3) {
110 temp = auto_cali_data + MANUAL_CALI_GAIN;
111 } else if (auto_cali_data >= MANUAL_CALI_LOW_LIMIT4 && auto_cali_data <= MANUAL_CALI_UPPER_LIMIT4) {
112 temp = MANUAL_CALI_THRESHOLD;
113 }
114 hal_adc_manual_offset_cali_set(temp);
115 hal_adc_offset_cali_enable(1);
116 hal_adc_cfg_offset_cali_data_enable();
117 hal_adc_offset_cali_data_spi_refresh();
118 uint32_t cnt = 0;
119 while (hal_adc_offset_cali_sts() != 1) {
120 if (cnt > COUNT_THRESHOLD) {
121 break;
122 }
123 cnt++;
124 }
125 hal_adc_offset_cali_enable(0);
126 }
127
hal_adc_cap_auto_cali(void)128 static void hal_adc_cap_auto_cali(void)
129 {
130 hal_adc_cfg_cap_cali_finish_clr();
131 hal_adc_cfg_intr_gain_state_clr();
132 hal_adc_date_spi_refresh_clr();
133 hal_adc_cfg_cap_cali_set();
134 hal_adc_cfg_cap_cali_enable(1);
135 uint32_t cnt = 0;
136 while (hal_adc_rpt_cap_cali_sts() != 1) {
137 if (cnt > COUNT_THRESHOLD) {
138 break;
139 }
140 cnt++;
141 }
142 hal_adc_cfg_cap_cali_enable(0);
143 }
144
hal_adc_offset_manual_cali_inc(void)145 static void hal_adc_offset_manual_cali_inc(void)
146 {
147 uint32_t temp;
148 temp = 0;
149 hal_adc_manual_offset_cali_set(temp);
150 hal_adc_offset_cali_enable(1);
151 hal_adc_cfg_offset_cali_data_enable();
152 hal_adc_offset_cali_data_spi_refresh();
153 uint32_t cnt = 0;
154 while (hal_adc_offset_cali_sts() != 1) {
155 if (cnt > COUNT_THRESHOLD) {
156 break;
157 }
158 cnt++;
159 }
160 hal_adc_offset_cali_enable(0);
161 }
162
adc_port_calibration(void)163 void adc_port_calibration(void)
164 {
165 hal_adc_offset_auto_cali();
166 hal_adc_offset_manual_cali();
167 hal_adc_cap_auto_cali();
168 hal_adc_offset_manual_cali_inc();
169 }
170
adc_process_before_use_adc(void)171 static void adc_process_before_use_adc(void)
172 {
173 hal_adc_cfg_gain_cali_enable();
174 uint32_t cnt = 0;
175 while (hal_adc_gain_unit_get() != 0) {
176 if (cnt > COUNT_THRESHOLD) {
177 break;
178 }
179 cnt++;
180 }
181 cnt = 0;
182 while (hal_adc_reg_fifo_isnt_empty_get() == 1) {
183 (void)hal_adc_reg_fifo_data_get();
184 if (cnt > COUNT_THRESHOLD) {
185 break;
186 }
187 cnt++;
188 }
189 }
190
hal_adc_v154_power_en(afe_scan_mode_t afe_scan_mode,bool on)191 static void hal_adc_v154_power_en(afe_scan_mode_t afe_scan_mode, bool on)
192 {
193 unused(afe_scan_mode);
194 if (on) {
195 hal_adc_soft_rst(0);
196 hal_adc_soft_rst(1);
197 hal_adc_simulation_cfg();
198 adc_port_calibration();
199 adc_process_before_use_adc();
200 hal_adc_fifo_waterline_set();
201 hal_adc_reg_irg_fifo_interrupt_mask();
202 }
203 }
204
hal_adc_channel_trans_to_gpio_get(adc_channel_t ch)205 static pin_t hal_adc_channel_trans_to_gpio_get(adc_channel_t ch)
206 {
207 switch (ch) {
208 case ADC_CHANNEL_0:
209 return GPIO_07;
210 case ADC_CHANNEL_1:
211 return GPIO_08;
212 case ADC_CHANNEL_2:
213 return GPIO_09;
214 case ADC_CHANNEL_3:
215 return GPIO_10;
216 case ADC_CHANNEL_4:
217 return GPIO_11;
218 case ADC_CHANNEL_5:
219 return GPIO_12;
220 default:
221 return PIN_NONE;
222 }
223 }
224
hal_adc_v154_channel_set(adc_channel_t ch,bool on)225 errcode_t hal_adc_v154_channel_set(adc_channel_t ch, bool on)
226 {
227 if (ch >= ADC_CHANNEL_MAX_NUM) {
228 return ERRCODE_ADC_INVALID_CH_TYPE;
229 }
230 pin_t pin_number;
231 pin_number = hal_adc_channel_trans_to_gpio_get(ch);
232 if (on) {
233 errcode_t ret;
234 ret = uapi_pin_set_pull(pin_number, PIN_PULL_TYPE_DISABLE);
235 if (ret != ERRCODE_SUCC) {
236 return ERRCODE_FAIL;
237 }
238 ret = uapi_pin_set_mode(pin_number, PIN_MODE_0);
239 if (ret != ERRCODE_SUCC) {
240 return ERRCODE_FAIL;
241 }
242 ret = uapi_gpio_set_dir(pin_number, GPIO_DIRECTION_INPUT);
243 if (ret != ERRCODE_SUCC) {
244 return ERRCODE_FAIL;
245 }
246 }
247
248 return ERRCODE_SUCC;
249 }
250
hal_adc_fifo_data_print(void)251 static void hal_adc_fifo_data_print(void)
252 {
253 adc_fifo_data_str_t ret;
254 uint32_t code, ch, index, voltage;
255 uint32_t param2 = 0x1 << 14;
256 uint32_t param3 = 0x1 << 15;
257
258 uint32_t data_s = 1, data_b = 1, data_k = 1;
259
260 bool next = false;
261
262 errcode_t res = adc_port_get_cali_param((uint8_t *)&data_s, (uint8_t *)&data_b, (uint8_t *)&data_k);
263 if (res != ERRCODE_SUCC) {
264 print_str("efuse read failed!\r\n");
265 }
266
267 memset_s(g_ch_data_cnt, sizeof(uint32_t) * CH_NUM, 0, sizeof(uint32_t) * CH_NUM);
268
269 for (uint32_t i = 0; i < FIFO_DATA_LENS; i++) {
270 ret.d32 = g_fifo_data[i];
271 code = ret.b.data;
272 ch = ret.b.channel;
273 g_ch_data_cnt[ch]++;
274 index = g_ch_data_cnt[ch];
275 if (ret.b.data == 0) {
276 break;
277 }
278
279 if (data_k == 0) {
280 voltage = code * VOLTAGE_UPPER_LIMIT / param2;
281 } else {
282 if (data_s == 0) {
283 voltage = code * VOLTAGE_UPPER_LIMIT / data_k - data_b * VOLTAGE_UPPER_LIMIT / param3;
284 } else {
285 voltage = code * VOLTAGE_UPPER_LIMIT / data_k + data_b * VOLTAGE_UPPER_LIMIT / param3;
286 }
287 }
288 g_ch_output_data[ch][index] = voltage;
289 }
290 for (uint32_t idx = 0; idx < CH_NUM; idx++) {
291 if (g_ch_data_cnt[idx] > 0 && g_adc_receive_data_callback != NULL) {
292 g_adc_receive_data_callback(idx, g_ch_output_data[idx], g_ch_data_cnt[idx], &next);
293 }
294 }
295 }
296
hal_adc_v154_auto_scan_enable(bool en)297 static void hal_adc_v154_auto_scan_enable(bool en)
298 {
299 if (en) {
300 hal_adc_start_sample();
301 g_adc_auto_scan_status = true;
302 } else {
303 hal_adc_stop_sample();
304 g_adc_auto_scan_status = false;
305 }
306 }
307
hal_adc_v154_auto_scan_ch_enable(adc_channel_t ch,bool en)308 static errcode_t hal_adc_v154_auto_scan_ch_enable(adc_channel_t ch, bool en)
309 {
310 hal_adc_auto_scan_mode_set(ch, en);
311 if (!en) {
312 hal_adc_fifo_data_print();
313 hal_adc_v154_auto_scan_enable(false);
314 }
315 return ERRCODE_SUCC;
316 }
317
hal_adc_v154_auto_scan_ch_config(adc_channel_t ch,hal_adc_scan_config_t * config,hal_adc_callback_t callback)318 static errcode_t hal_adc_v154_auto_scan_ch_config(adc_channel_t ch, hal_adc_scan_config_t *config,
319 hal_adc_callback_t callback)
320 {
321 unused(config);
322 g_adc_receive_data_callback = callback;
323 hal_adc_v154_channel_set(ch, true);
324 hal_adc_v154_auto_scan_ch_enable(ch, true);
325 hal_adc_v154_auto_scan_enable(true);
326
327 return ERRCODE_SUCC;
328 }
329
hal_adc_v154_auto_scan_is_enabled(void)330 static bool hal_adc_v154_auto_scan_is_enabled(void)
331 {
332 return g_adc_auto_scan_status;
333 }
334
hal_adc_irq_handler(void)335 void hal_adc_irq_handler(void)
336 {
337 uint32_t index = 0;
338 uint32_t cnt = 0;
339 while (hal_adc_reg_fifo_isnt_empty_get()) {
340 if (index < FIFO_DATA_LENS) {
341 g_fifo_data[index++] = hal_adc_reg_fifo_data_get();
342 } else {
343 hal_adc_reg_fifo_data_get();
344 if (cnt > COUNT_THRESHOLD) {
345 break;
346 }
347 cnt++;
348 }
349 }
350 }
351
hal_adc_v154_manual_sample(adc_channel_t channel)352 static int32_t hal_adc_v154_manual_sample(adc_channel_t channel)
353 {
354 unused(channel);
355 return 0;
356 }
357
358 static hal_adc_funcs_t g_hal_adc_v154_funcs = {
359 .init = hal_adc_v154_init,
360 .deinit = hal_adc_v154_deinit,
361 .power_en = hal_adc_v154_power_en,
362 .ch_set = hal_adc_v154_channel_set,
363 #if defined(CONFIG_ADC_SUPPORT_AUTO_SCAN)
364 .ch_config = hal_adc_v154_auto_scan_ch_config,
365 .ch_enable = hal_adc_v154_auto_scan_ch_enable,
366 .enable = hal_adc_v154_auto_scan_enable,
367 .isenable = hal_adc_v154_auto_scan_is_enabled,
368 #endif /* CONFIG_ADC_SUPPORT_AUTO_SCAN */
369 .manual = hal_adc_v154_manual_sample
370 };
371
hal_adc_v154_funcs_get(void)372 hal_adc_funcs_t *hal_adc_v154_funcs_get(void)
373 {
374 return &g_hal_adc_v154_funcs;
375 }
376