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
16 #include <hi_isr.h>
17 #include <hi_time.h>
18 #include <hi_clock.h>
19
20 #include "adc_drv.h"
21
22 #define CHECK_EMPTY_MAX_TIME_US 3000 /* 344ns * (0xfff + 18) * 2 = 2.8ms ,reserved 3ms */
23
check_adc_fifo_empty(hi_void)24 HI_ALWAYS_STAIC_INLINE hi_bool check_adc_fifo_empty(hi_void)
25 {
26 hi_u32 reg_val = hi_reg_read_val32(REG_ADC_SR);
27 if (reg_val & ADC_SR_RNE) {
28 return HI_FALSE;
29 }
30 return HI_TRUE;
31 }
32
wait_adc_fifo_empty(hi_void)33 HI_ALWAYS_STAIC_INLINE hi_void wait_adc_fifo_empty(hi_void)
34 {
35 hi_u32 timeout = CHECK_EMPTY_MAX_TIME_US;
36 while ((check_adc_fifo_empty() == HI_FALSE) && (timeout > 0)) {
37 (hi_void)hi_reg_read_val32(REG_ADC_DR);
38 hi_udelay(1);
39 timeout--;
40 }
41 }
42
adc_check_parameter(hi_adc_channel_index channel,hi_u16 * data,hi_adc_equ_model_sel equ_model,hi_adc_cur_bais cur_bais,hi_u16 delay_cnt)43 HI_ALWAYS_STAIC_INLINE hi_u32 adc_check_parameter(hi_adc_channel_index channel, hi_u16 *data,
44 hi_adc_equ_model_sel equ_model, hi_adc_cur_bais cur_bais, hi_u16 delay_cnt)
45 {
46 if ((channel > HI_ADC_CHANNEL_7) || (data == HI_NULL) || (equ_model > HI_ADC_EQU_MODEL_8) ||
47 (cur_bais > HI_ADC_CUR_BAIS_3P3V) || (delay_cnt > 0xFF0)) {
48 return HI_ERR_ADC_PARAMETER_WRONG;
49 }
50 return HI_ERR_SUCCESS;
51 }
52
hi_adc_read(hi_adc_channel_index channel,hi_u16 * data,hi_adc_equ_model_sel equ_model,hi_adc_cur_bais cur_bais,hi_u16 delay_cnt)53 hi_u32 hi_adc_read(hi_adc_channel_index channel, hi_u16 *data, hi_adc_equ_model_sel equ_model,
54 hi_adc_cur_bais cur_bais, hi_u16 delay_cnt)
55 {
56 hi_u16 reg_val, int_value;
57 hi_u32 timeout_cnt = 0;
58 adc_cfg_reg_s adc_ctl = {0};
59 if (adc_check_parameter(channel, data, equ_model, cur_bais, delay_cnt) != HI_ERR_SUCCESS) {
60 return HI_ERR_ADC_PARAMETER_WRONG;
61 }
62
63 hi_xtal_clock clock = hi_get_xtal_clock();
64 hi_reg_read16(LS_ADC_CLK_DIV1_REG, reg_val);
65 reg_val &= ~(0xF << LS_ADC_CLK_DIV1_OFFSET);
66 if (clock == HI_XTAL_CLOCK_24M) {
67 reg_val |= (0x7 << LS_ADC_CLK_DIV1_OFFSET);
68 } else if (clock == HI_XTAL_CLOCK_40M) {
69 reg_val |= (0xC << LS_ADC_CLK_DIV1_OFFSET);
70 }
71 hi_reg_write16(LS_ADC_CLK_DIV1_REG, reg_val);
72 int_value = hi_int_lock();
73 hi_reg_write32(REG_ADC_EN, ADC_POWER_ON);
74
75 adc_ctl.ch_vld = (hi_u32)(1 << (hi_u32)channel);
76 adc_ctl.equ_model = equ_model;
77 adc_ctl.cur_bais = cur_bais;
78 adc_ctl.delay_cnt = delay_cnt + 0xF;
79 hi_reg_write32(REG_ADC_CFG, *(volatile hi_u32 *)&adc_ctl);
80
81 hi_reg_write32(REG_ADC_START, ADC_SCAN_START);
82
83 while (timeout_cnt < ADC_PER_DATA_TIMEOUT_CNT) {
84 if (!check_adc_fifo_empty()) {
85 *data = (hi_u16)hi_reg_read_val32(REG_ADC_DR);
86 if ((*data >> ADC_DATA_BIT_WIDTH) == channel) {
87 *data = *data & 0xFFF;
88 break;
89 }
90 }
91 hi_udelay(ADC_LOOP_DELAY_US);
92 timeout_cnt++;
93 }
94 if (timeout_cnt >= ADC_PER_DATA_TIMEOUT_CNT) {
95 hi_int_restore(int_value);
96 return HI_ERR_ADC_TIMEOUT;
97 }
98 hi_reg_write32(REG_ADC_STOP, ADC_SCAN_STOP);
99 hi_reg_write32(REG_ADC_IMSC, ADC_ISR_DISABLE);
100 wait_adc_fifo_empty();
101 hi_reg_write32(REG_ADC_EN, ADC_POWER_OFF);
102 hi_int_restore(int_value);
103 return HI_ERR_SUCCESS;
104 }
105
hi_adc_convert_to_voltage(hi_u16 data)106 hi_float hi_adc_convert_to_voltage(hi_u16 data)
107 {
108 float voltage = (float)data * 1.8 * 4 / 4096; /* adc code equals: voltage/4/1.8*4096 */
109 return voltage;
110 }
111
112