1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stddef.h>
7 #include <stdint.h>
8
9 #include <device_mec5.h>
10 #include "mec_defs.h"
11 #include "mec_adc_api.h"
12 #include "mec_ecia_api.h"
13 #include "mec_pcr_api.h"
14 #include "mec_retval.h"
15
16 #define MEC_ADC_GIRQ 17
17 #define MEC_ADC_SM_GIRQ_POS 8
18 #define MEC_ADC_RM_GIRQ_POS 9
19 #define MEC_ADC_SM_ECIA_INFO MEC5_ECIA_INFO(MEC_ADC_GIRQ, MEC_ADC_SM_GIRQ_POS, 9, 78)
20 #define MEC_ADC_RM_ECIA_INFO MEC5_ECIA_INFO(MEC_ADC_GIRQ, MEC_ADC_RM_GIRQ_POS, 9, 79)
21
adc_intr_flag_to_bitmap(uint32_t flags)22 static inline uint32_t adc_intr_flag_to_bitmap(uint32_t flags)
23 {
24 uint32_t bm = 0;
25
26 if (flags & MEC_BIT(MEC_ADC_SINGLE_INTR_POS)) {
27 bm |= MEC_BIT(MEC_ADC_SM_GIRQ_POS);
28 }
29 if (flags & MEC_BIT(MEC_ADC_REPEAT_INTR_POS)) {
30 bm |= MEC_BIT(MEC_ADC_RM_GIRQ_POS);
31 }
32
33 return bm;
34 }
35
36 /* ---- Public API ---- */
37
38 /* Initialize ADC */
mec_hal_adc_init(struct mec_adc_regs * regs,struct mec_adc_config * cfg)39 int mec_hal_adc_init(struct mec_adc_regs *regs, struct mec_adc_config *cfg)
40 {
41 uint32_t girq_bm = MEC_BIT(MEC_ADC_SM_GIRQ_POS) | MEC_BIT(MEC_ADC_RM_GIRQ_POS);
42 uint32_t temp = 4u;
43 uint8_t flags = 0;
44
45 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
46 return MEC_RET_ERR_INVAL;
47 }
48
49 mec_hal_pcr_clr_blk_slp_en(MEC_PCR_ADC0); /* clear sleep enable */
50 mec_hal_girq_bm_en(MEC_ADC_GIRQ, girq_bm, 0);
51 mec_hal_girq_bm_clr_src(MEC_ADC_GIRQ, girq_bm);
52
53 regs->CTRL = 0;
54
55 if (cfg) {
56 flags = cfg->flags;
57
58 if (flags & MEC_BIT(MEC_ADC_CFG_SOFT_RESET_POS)) {
59 regs->CTRL = MEC_BIT(MEC_ADC_CTRL_SRST_Pos);
60 while (temp--) {
61 if (!(regs->CTRL & MEC_BIT(MEC_ADC_CTRL_SRST_Pos))) {
62 break;
63 }
64 }
65 regs->CTRL = 0;
66 }
67
68 if (flags & MEC_BIT(MEC_ADC_CFG_PWR_SAVE_DIS_POS)) {
69 regs->CTRL |= MEC_BIT(MEC_ADC_CTRL_PWR_SAVE_Pos);
70 } else { /* enable by clearing the bit */
71 regs->CTRL &= (uint32_t)~MEC_BIT(MEC_ADC_CTRL_PWR_SAVE_Pos);
72 }
73
74 if (flags & MEC_BIT(MEC_ADC_CFG_SAMPLE_TIME_POS)) {
75 temp = (((uint32_t)cfg->sample_clk_hi_time << MEC_ADC_CONFIG_CHTM_Pos)
76 & MEC_ADC_CONFIG_CHTM_Msk);
77 temp |= (((uint32_t)cfg->sample_clk_lo_time << MEC_ADC_CONFIG_CLTM_Pos)
78 & MEC_ADC_CONFIG_CLTM_Msk);
79 regs->CONFIG = (regs->CONFIG & (uint32_t)~(MEC_ADC_CONFIG_CLTM_Msk
80 | MEC_ADC_CONFIG_CHTM_Msk)) | temp;
81
82 }
83
84 if (flags & MEC_BIT(MEC_ADC_CFG_WARM_UP_POS)) {
85 regs->SAR_CTRL = (regs->SAR_CTRL & (uint32_t)~(MEC_ADC_SAR_CTRL_WARMUPDLY_Msk))
86 | (((uint32_t)cfg->warm_up_delay << MEC_ADC_SAR_CTRL_WARMUPDLY_Pos)
87 & MEC_ADC_SAR_CTRL_WARMUPDLY_Msk);
88 }
89
90 if (flags & MEC_BIT(MEC_ADC_CFG_RPT_DELAY_POS)) {
91 temp = regs->DELAY &
92 (uint32_t)~(MEC_ADC_DELAY_RSTART_DLY_Msk | MEC_ADC_DELAY_RPT_DLY_Msk);
93 temp |= (((uint32_t)cfg->rpt_start_delay << MEC_ADC_DELAY_RSTART_DLY_Pos)
94 & MEC_ADC_DELAY_RSTART_DLY_Msk);
95 temp |= (((uint32_t)cfg->rpt_cycle_delay << MEC_ADC_DELAY_RPT_DLY_Pos)
96 & MEC_ADC_DELAY_RPT_DLY_Msk);
97 regs->DELAY = (regs->DELAY & (uint32_t)~(MEC_ADC_DELAY_RSTART_DLY_Msk));
98 }
99
100 if (flags & MEC_BIT(MEC_ADC_CFG_SAR_CFG_OVR_POS)) {
101 regs->SAR_CFG = cfg->sar_config;
102 }
103 }
104
105 regs->CTRL |= MEC_BIT(MEC_ADC_CTRL_ACTV_Pos);
106
107 return MEC_RET_OK;
108 }
109
mec_hal_adc_activate(struct mec_adc_regs * regs,uint8_t enable)110 int mec_hal_adc_activate(struct mec_adc_regs *regs, uint8_t enable)
111 {
112 uint32_t msk = MEC_BIT(MEC_ADC_CTRL_RDONE_Pos) | MEC_BIT(MEC_ADC_CTRL_SDONE_Pos);
113 uint32_t ctrl = 0;
114
115 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
116 return MEC_RET_ERR_INVAL;
117 }
118
119 ctrl = regs->CTRL & ~msk;
120 if (enable) {
121 ctrl |= MEC_BIT(MEC_ADC_CTRL_ACTV_Pos);
122 } else {
123 ctrl &= (uint32_t)~MEC_BIT(MEC_ADC_CTRL_ACTV_Pos);
124 }
125
126 regs->CTRL = ctrl;
127
128 return MEC_RET_OK;
129 }
130
131 /* repeat mode delays
132 * Both delays are in units of 40 us.
133 * Start delay applies once when repeat conversions are first started.
134 * Repeat delay is applied after the first conversions of the selected
135 * channels and subsequently between each set of conversions.
136 */
mec_hal_adc_repeat_delay_set(struct mec_adc_regs * regs,uint16_t start_delay,uint16_t repeat_delay)137 int mec_hal_adc_repeat_delay_set(struct mec_adc_regs *regs, uint16_t start_delay,
138 uint16_t repeat_delay)
139 {
140 uint32_t delay = (uint32_t)start_delay | ((uint32_t)repeat_delay << 16);
141
142 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
143 return MEC_RET_ERR_INVAL;
144 }
145
146 regs->DELAY = delay;
147
148 return MEC_RET_OK;
149 }
150
151 /* Set the channels for conversion in repeat mode */
mec_hal_adc_repeat_mode_chan_set(struct mec_adc_regs * regs,uint32_t rpt_chan_bm)152 int mec_hal_adc_repeat_mode_chan_set(struct mec_adc_regs *regs, uint32_t rpt_chan_bm)
153 {
154 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
155 return MEC_RET_ERR_INVAL;
156 }
157
158 regs->RCHEN = rpt_chan_bm;
159
160 return MEC_RET_OK;
161 }
162
mec_hal_adc_chan_vref_select(struct mec_adc_regs * regs,uint8_t chan_id,enum mec_adc_chan_vref vref)163 int mec_hal_adc_chan_vref_select(struct mec_adc_regs *regs, uint8_t chan_id,
164 enum mec_adc_chan_vref vref)
165 {
166 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
167 return MEC_RET_ERR_INVAL;
168 }
169
170 if ((chan_id >= MEC5_ADC_CHANNELS) || (vref > MEC_ADC_CHAN_VREF_GPIO)) {
171 return MEC_RET_ERR_INVAL;
172 }
173
174 uint32_t temp = regs->VREF_CHAN;
175
176 temp &= ~(0x3u << (chan_id * 2u));
177 temp |= (((uint32_t)vref & 0x3u) << (chan_id * 2u));
178 regs->VREF_CHAN = temp;
179
180 return MEC_RET_OK;
181 }
182
mec_hal_adc_differential_input_enable(struct mec_adc_regs * regs,uint8_t enable)183 int mec_hal_adc_differential_input_enable(struct mec_adc_regs *regs, uint8_t enable)
184 {
185 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
186 return MEC_RET_ERR_INVAL;
187 }
188
189 if (enable) {
190 regs->SAR_CTRL |= MEC_BIT(MEC_ADC_SAR_CTRL_SELDIFF_Pos);
191 } else {
192 regs->SAR_CTRL &= (uint32_t)~MEC_BIT(MEC_ADC_SAR_CTRL_SELDIFF_Pos);
193 }
194
195 return MEC_RET_OK;
196 }
197
mec_hal_adc_resolution_set(struct mec_adc_regs * regs,uint8_t resolution_bits)198 int mec_hal_adc_resolution_set(struct mec_adc_regs *regs, uint8_t resolution_bits)
199 {
200 uint32_t res = 0;
201
202 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
203 return MEC_RET_ERR_INVAL;
204 }
205
206 switch (resolution_bits) {
207 case 10:
208 res = MEC_ADC_SAR_CTRL_SELRES_10BIT;
209 break;
210 case 12:
211 res = MEC_ADC_SAR_CTRL_SELRES_12BIT;
212 break;
213 default:
214 return MEC_RET_ERR_INVAL;
215 }
216
217 regs->SAR_CTRL = (regs->SAR_CTRL & (uint32_t)~(MEC_ADC_SAR_CTRL_SELRES_Msk))
218 | (res << MEC_ADC_SAR_CTRL_SELRES_Pos);
219
220 return MEC_RET_OK;
221 }
222
mec_hal_adc_girq_ctrl(struct mec_adc_regs * regs,uint32_t flags,uint8_t enable)223 int mec_hal_adc_girq_ctrl(struct mec_adc_regs *regs, uint32_t flags, uint8_t enable)
224 {
225 uint32_t bm = 0;
226
227 if (!regs) {
228 return MEC_RET_ERR_INVAL;
229 }
230
231 bm = adc_intr_flag_to_bitmap(flags);
232 mec_hal_girq_bm_en(MEC_ADC_GIRQ, bm, enable);
233
234 return MEC_RET_OK;
235 }
236
mec_hal_adc_girq_status_clr(struct mec_adc_regs * regs,uint32_t flags)237 int mec_hal_adc_girq_status_clr(struct mec_adc_regs *regs, uint32_t flags)
238 {
239 uint32_t bm = 0;
240
241 if (!regs) {
242 return MEC_RET_ERR_INVAL;
243 }
244
245 bm = adc_intr_flag_to_bitmap(flags);
246 mec_hal_girq_bm_clr_src(MEC_ADC_GIRQ, bm);
247
248 return MEC_RET_OK;
249 }
250
mec_hal_adc_channels_done(struct mec_adc_regs * regs)251 uint32_t mec_hal_adc_channels_done(struct mec_adc_regs *regs)
252 {
253 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
254 return 0;
255 }
256
257 return regs->STATUS;
258 }
259
mec_hal_adc_channel_reading(struct mec_adc_regs * regs,uint8_t channel)260 uint32_t mec_hal_adc_channel_reading(struct mec_adc_regs *regs, uint8_t channel)
261 {
262 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
263 return 0;
264 }
265
266 if (channel >= MEC5_ADC_CHANNELS) {
267 return 0;
268 }
269
270 return regs->RD[channel];
271 }
272
273
274 /* Clear HW status in order:
275 * 1. Channels done bitmap in STATUS register
276 * 2. Single and/or Repeat sequence done in CTRL register
277 * 3. Single and/or Repeate sequence done in GIRQ.Source register
278 */
mec_hal_adc_status_clear(struct mec_adc_regs * regs,uint32_t flags)279 int mec_hal_adc_status_clear(struct mec_adc_regs *regs, uint32_t flags)
280 {
281 uint32_t ctrl_val = 0, girq_clr_bm = 0;
282
283 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
284 return MEC_RET_ERR_INVAL;
285 }
286
287 if (flags & MEC_BIT(MEC_ADC_SINGLE_INTR_POS)) {
288 regs->STATUS |= regs->SCHEN;
289 ctrl_val |= MEC_BIT(MEC_ADC_CTRL_SDONE_Pos);
290 girq_clr_bm |= MEC_BIT(MEC_ADC_SM_GIRQ_POS);
291 }
292
293 if (flags & MEC_BIT(MEC_ADC_REPEAT_INTR_POS)) {
294 regs->STATUS |= regs->RCHEN;
295 ctrl_val |= MEC_BIT(MEC_ADC_CTRL_RDONE_Pos);
296 girq_clr_bm |= MEC_BIT(MEC_ADC_RM_GIRQ_POS);
297 }
298
299 regs->CTRL |= ctrl_val;
300
301 mec_hal_girq_bm_clr_src(MEC_ADC_GIRQ, girq_clr_bm);
302
303 return MEC_RET_OK;
304 }
305
mec_hal_adc_start(struct mec_adc_regs * regs,uint16_t single_chan_bm,uint16_t rpt_chan_bm)306 int mec_hal_adc_start(struct mec_adc_regs *regs, uint16_t single_chan_bm, uint16_t rpt_chan_bm)
307 {
308 uint32_t start_val = 0, ctrl_sts = 0, girq_clr_bm = 0;
309
310 if ((uintptr_t)regs != (uintptr_t)MEC_ADC0_BASE) {
311 return MEC_RET_ERR_INVAL;
312 }
313
314 if (single_chan_bm) {
315 start_val |= MEC_BIT(MEC_ADC_CTRL_SSTART_Pos);
316 ctrl_sts |= MEC_BIT(MEC_ADC_CTRL_SDONE_Pos);
317 girq_clr_bm |= MEC_BIT(MEC_ADC_SM_GIRQ_POS);
318 regs->SCHEN = single_chan_bm;
319 }
320
321 if (rpt_chan_bm) {
322 start_val |= MEC_BIT(MEC_ADC_CTRL_RSTART_Pos);
323 ctrl_sts |= MEC_BIT(MEC_ADC_CTRL_RDONE_Pos);
324 girq_clr_bm |= MEC_BIT(MEC_ADC_RM_GIRQ_POS);
325 regs->RCHEN = rpt_chan_bm;
326 }
327
328 if (start_val) {
329 regs->STATUS = single_chan_bm | rpt_chan_bm;
330 regs->CTRL |= ctrl_sts;
331 mec_hal_girq_bm_clr_src(MEC_ADC_GIRQ, girq_clr_bm);
332 regs->CTRL |= start_val;
333 }
334
335 return MEC_RET_OK;
336 }
337
338 /* ---- Power Management ----
339 * The ADC will de-assert is CLK_REQ between each conversion in a sequence instead
340 * of at the end of a sequence.
341 * For maximum power reduction it is better to save/disable the controller.
342 * We expect the application to call save/disable when the ADC is not in the
343 * middle of a conversion sequence.
344 */
345
346 #define MEC_ADC_PM_SAVE_ITEMS_CNT 1
347 static uint8_t adc_pm_save_buf[MEC_ADC_PM_SAVE_ITEMS_CNT];
348
mec_hal_adc_pm_save_disable(void)349 void mec_hal_adc_pm_save_disable(void)
350 {
351 uint32_t ctrl = MEC_ADC0->CTRL;
352 uint8_t adc_en = 0;
353
354 if (ctrl & MEC_BIT(MEC_ADC_CTRL_ACTV_Pos)) {
355 adc_en = 1u;
356 }
357
358 adc_pm_save_buf[0] = adc_en;
359
360 /* preserve start_repeat and power_saver_dis */
361 ctrl &= MEC_BIT( MEC_ADC_CTRL_RSTART_Pos) | MEC_BIT(MEC_ADC_CTRL_PWR_SAVE_Pos);
362 MEC_ADC0->CTRL = ctrl;
363 }
364
mec_hal_adc_pm_restore(void)365 void mec_hal_adc_pm_restore(void)
366 {
367 uint32_t ctrl = MEC_ADC0->CTRL & (MEC_BIT( MEC_ADC_CTRL_RSTART_Pos)
368 | MEC_BIT(MEC_ADC_CTRL_PWR_SAVE_Pos));
369
370 if (adc_pm_save_buf[0]) {
371 ctrl |= MEC_BIT(MEC_ADC_CTRL_ACTV_Pos);
372 }
373
374 MEC_ADC0->CTRL = ctrl;
375 }
376 /* end mec_adc.c */
377