1 /*
2  * Copyright (c) 2021-2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <rtthread.h>
7 
8 #ifdef BSP_USING_ADC
9 #include <rtdevice.h>
10 #include "board.h"
11 #include "drv_adc.h"
12 #ifdef BSP_USING_ADC12
13 #include "hpm_adc12_drv.h"
14 #endif
15 #ifdef BSP_USING_ADC16
16 #include "hpm_adc16_drv.h"
17 #endif
18 #include "hpm_sysctl_drv.h"
19 
20 
21 typedef struct
22 {
23     bool enabled;
24 } adc_channel_state_t;
25 
26 typedef struct
27 {
28     char *adc_name;
29     struct rt_adc_device hpm_adc_device;
30     bool is_adc12;
31     bool adc_enabled;
32     uint32_t adc_base;
33     adc_channel_state_t chn_state[16];
34 }hpm_rtt_adc;
35 
36 
37 
38 static uint32_t hpm_adc_init_clock(struct rt_adc_device *device);
39 static void hpm_adc_init_pins(struct rt_adc_device *device);
40 
41 static rt_err_t hpm_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled);
42 static rt_err_t hpm_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value);
43 static rt_uint8_t hpm_get_resolution(struct rt_adc_device *device);
44 static rt_int16_t hpm_get_vref(struct rt_adc_device *device);
45 
46 
47 static const struct rt_adc_ops hpm_adc_ops =
48 {
49     .enabled = hpm_adc_enabled,
50     .convert = hpm_get_adc_value,
51     .get_resolution = hpm_get_resolution,
52     .get_vref = hpm_get_vref,
53 };
54 
55 
56 static hpm_rtt_adc hpm_adc_config_tbl[] =
57 {
58 #ifdef BSP_USING_ADC0
59     {
60         .adc_name = "adc0",
61 #ifdef BSP_USING_ADC12
62         .is_adc12 = true,
63 #else
64         .is_adc12 = false,
65 #endif
66         .adc_base = (uint32_t)HPM_ADC0,
67     },
68 #endif
69 
70 #ifdef BSP_USING_ADC1
71     {
72         .adc_name = "adc1",
73 #ifdef BSP_USING_ADC12
74         .is_adc12 = true,
75 #else
76         .is_adc12 = false,
77 #endif
78         .adc_base = (uint32_t)HPM_ADC1,
79     },
80 #endif
81 
82 #ifdef BSP_USING_ADC2
83     {
84         .adc_name = "adc2",
85 #ifdef BSP_USING_ADC12
86         .is_adc12 = true,
87 #else
88         .is_adc12 = false,
89 #endif
90         .adc_base = (uint32_t)HPM_ADC2,
91     },
92 #endif
93 
94 #ifdef BSP_USING_ADC3
95     {
96         .adc_name = "adc3",
97         .is_adc12 = false,
98         .adc_base = (uint32_t)HPM_ADC3,
99     },
100 #endif
101 };
102 
103 static uint8_t adc_nums = sizeof(hpm_adc_config_tbl) / sizeof(hpm_rtt_adc);
104 
105 
hpm_adc_init_clock(struct rt_adc_device * device)106 static uint32_t hpm_adc_init_clock(struct rt_adc_device *device)
107 {
108     hpm_rtt_adc *hpm_adc;
109     uint32_t clock_freq = 0;
110     RT_ASSERT(device != RT_NULL);
111     hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
112 
113 #if defined(ADC12_SOC_MAX_CH_NUM)
114     if (hpm_adc->is_adc12)
115     {
116         clock_freq = board_init_adc12_clock((ADC12_Type*)hpm_adc->adc_base,true);
117     } else
118 #endif
119     {
120         clock_freq = board_init_adc16_clock((ADC16_Type*)hpm_adc->adc_base,true);
121     }
122     return clock_freq;
123 }
124 
hpm_adc_init_pins(struct rt_adc_device * device)125 static void hpm_adc_init_pins(struct rt_adc_device *device)
126 {
127     hpm_rtt_adc *hpm_adc;
128     RT_ASSERT(device != RT_NULL);
129     hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
130 
131 #if defined(ADC12_SOC_MAX_CH_NUM)
132     if (hpm_adc->is_adc12)
133     {
134         board_init_adc12_pins();
135     } else
136 #endif
137     {
138         board_init_adc16_pins();
139     }
140 }
init_adc_config(hpm_rtt_adc * adc)141 static rt_err_t init_adc_config(hpm_rtt_adc *adc)
142 {
143     hpm_stat_t ret;
144 
145     if (adc->is_adc12) {
146 #ifdef BSP_USING_ADC12
147         adc12_config_t cfg;
148         adc12_get_default_config(&cfg);
149         cfg.res            = adc12_res_12_bits;
150         cfg.conv_mode      = adc12_conv_mode_oneshot;
151         cfg.adc_ahb_en     = true;
152         cfg.adc_clk_div    = 3;
153         ret = adc12_init((ADC12_Type *)adc->adc_base, &cfg);
154         if (ret != status_success) {
155             return -RT_ERROR;
156         }
157 #endif
158     } else {
159 #ifdef BSP_USING_ADC16
160         adc16_config_t cfg;
161 
162         adc16_get_default_config(&cfg);
163         cfg.conv_mode      = adc16_conv_mode_oneshot;
164         cfg.res            = adc16_res_16_bits;
165         cfg.adc_clk_div    = 4;
166         cfg.sel_sync_ahb   = true;
167         cfg.adc_ahb_en     = true;
168         cfg.wait_dis = 0;
169         ret = adc16_init((ADC16_Type *)adc->adc_base, &cfg);
170         if (ret != status_success) {
171         return -RT_ERROR;
172         }
173 #endif
174 #if defined(ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT) && ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT
175     /* enable oneshot mode */
176     adc16_enable_oneshot_mode((ADC16_Type *)adc->adc_base);
177 #endif
178     }
179     return RT_EOK;
180 }
181 
init_channel_config(hpm_rtt_adc * adc,uint16_t channel)182 static rt_err_t init_channel_config(hpm_rtt_adc *adc, uint16_t channel)
183 {
184     hpm_stat_t ret;
185 
186     if (adc->is_adc12) {
187 #ifdef BSP_USING_ADC12
188         adc12_channel_config_t ch_cfg;
189 
190         adc12_get_channel_default_config(&ch_cfg);
191         ch_cfg.ch           = channel;
192         ch_cfg.diff_sel     = adc12_sample_signal_single_ended;
193         ch_cfg.sample_cycle = 20;
194 
195         ret = adc12_init_channel((ADC12_Type *)adc->adc_base, &ch_cfg);
196         if (ret != status_success) {
197             return -RT_ERROR;
198         }
199 #endif
200     } else {
201 #ifdef BSP_USING_ADC16
202         adc16_channel_config_t ch_cfg;
203 
204         adc16_get_channel_default_config(&ch_cfg);
205         ch_cfg.ch           = channel;
206         ch_cfg.sample_cycle = 20;
207         ret = adc16_init_channel((ADC16_Type *)adc->adc_base, &ch_cfg);
208         if (ret != status_success) {
209             return -RT_ERROR;
210         }
211 #endif
212     }
213     return RT_EOK;
214 }
215 
hpm_adc_enabled(struct rt_adc_device * device,rt_int8_t channel,rt_bool_t enabled)216 static rt_err_t hpm_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
217 {
218     hpm_rtt_adc *hpm_adc;
219     rt_err_t ret;
220 
221     RT_ASSERT(device != RT_NULL);
222     hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
223     if (enabled == RT_TRUE) {
224         if (!hpm_adc->chn_state[channel].enabled)
225         {
226             if (!hpm_adc->adc_enabled)
227             {
228                 hpm_adc_init_pins(device);
229                 (void)hpm_adc_init_clock(device);
230                 ret = init_adc_config(hpm_adc);
231                 if (ret != RT_EOK) {
232                     return -RT_ERROR;
233                 }
234                 hpm_adc->adc_enabled = true;
235             }
236             hpm_adc->chn_state[channel].enabled = true;
237 
238             ret = init_channel_config(hpm_adc, channel);
239             if (ret != RT_EOK) {
240                 return -RT_ERROR;
241             }
242         }
243     }
244     else
245     {
246         /* Since the ADC channel cannot be truly disabled, do nothing here */
247     }
248 
249     return RT_EOK;
250 }
251 
hpm_get_adc_value(struct rt_adc_device * device,rt_int8_t channel,rt_uint32_t * value)252 static rt_err_t hpm_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
253 {
254     hpm_rtt_adc *hpm_adc;
255     rt_err_t ret;
256     rt_uint16_t val;
257 
258     RT_ASSERT(device != RT_NULL);
259     RT_ASSERT(value != RT_NULL);
260 
261     hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
262     uint32_t adc_chn = (uint16_t)channel;
263     if (hpm_adc->is_adc12) {
264 #ifdef BSP_USING_ADC12
265         adc12_get_oneshot_result((ADC12_Type *)hpm_adc->adc_base, adc_chn, &val);
266         *value = val;
267 #endif
268     } else {
269 #ifdef BSP_USING_ADC16
270         hpm_stat_t status = adc16_get_oneshot_result((ADC16_Type *)hpm_adc->adc_base, adc_chn, &val);
271         *value = val;
272 #endif
273     }
274 
275     return RT_EOK;
276 }
277 
hpm_get_resolution(struct rt_adc_device * device)278 static rt_uint8_t hpm_get_resolution(struct rt_adc_device *device)
279 {
280     hpm_rtt_adc *hpm_adc;
281 
282     RT_ASSERT(device != RT_NULL);
283     hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
284     if (hpm_adc->is_adc12) {
285         return 12;
286     } else {
287         return 16;
288     }
289 }
290 
hpm_get_vref(struct rt_adc_device * device)291 static rt_int16_t hpm_get_vref(struct rt_adc_device *device)
292 {
293     return -RT_EIO;
294 }
295 
rt_hw_adc_init(void)296 int rt_hw_adc_init(void)
297 {
298     rt_err_t ret = RT_EOK;
299 
300     for (uint32_t i = 0; i < adc_nums; i++) {
301        ret = rt_hw_adc_register(&hpm_adc_config_tbl[i].hpm_adc_device,
302                                 hpm_adc_config_tbl[i].adc_name,
303                                 &hpm_adc_ops,
304                                 &hpm_adc_config_tbl[i]);
305        if (ret != RT_EOK) {
306            ret = RT_ERROR;
307            break;
308        }
309     }
310     return ret;
311 }
312 INIT_BOARD_EXPORT(rt_hw_adc_init);
313 
314 #endif /* BSP_USING_ADC */
315