• 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 
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