• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
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 /*****************************************************************************
17 *
18 * File Name : wm_adc.c
19 *
20 * Description: adc Driver Module
21 *
22 * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
23 * All rights reserved.
24 *
25 * Author : dave
26 *
27 * Date : 2014-8-15
28 *****************************************************************************/
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include "wm_regs.h"
33 #include "wm_dma.h"
34 #include "wm_io.h"
35 #include "wm_irq.h"
36 #include "wm_mem.h"
37 #include "wm_adc.h"
38 
39 #define HR_SD_ADC_CONFIG_REG 0
40 static int adc_offset = 0;
41 static int *adc_dma_buffer = NULL;
42 volatile ST_ADC gst_adc;
43 
ADC_IRQHandler(void)44 ATTRIBUTE_ISR void ADC_IRQHandler(void)
45 {
46     u32 adcvalue;
47     int reg;
48     csi_kernel_intrpt_enter();
49 
50     reg = tls_reg_read32(HR_SD_ADC_INT_STATUS);
51     if (reg & ADC_INT_MASK) {     // ADC中断
52         tls_adc_clear_irq(ADC_INT_TYPE_ADC);
53 
54         if (gst_adc.adc_cb) {
55             adcvalue = tls_read_adc_result();
56             gst_adc.adc_cb((int *)&adcvalue, 1);
57         }
58     }
59     if (reg & CMP_INT_MASK) {
60         tls_adc_clear_irq(ADC_INT_TYPE_ADC_COMP);
61         if (gst_adc.adc_bigger_cb)
62             gst_adc.adc_bigger_cb(NULL, 0);
63     }
64     csi_kernel_intrpt_exit();
65 }
66 
adc_dma_isr_callbk(void)67 static void adc_dma_isr_callbk(void)
68 {
69     if (gst_adc.adc_dma_cb) {
70         if (adc_dma_buffer) {
71             gst_adc.adc_dma_cb((int *)(adc_dma_buffer), gst_adc.valuelen);
72         }
73     }
74 }
75 
tls_adc_init(u8 ifusedma,u8 dmachannel)76 void tls_adc_init(u8 ifusedma, u8 dmachannel)
77 {
78     tls_reg_write32(HR_SD_ADC_CTRL, ANALOG_SWITCH_TIME_VAL(0x50)|ANALOG_INIT_TIME_VAL(0x50)|ADC_IRQ_EN_VAL(0x1));
79     tls_irq_enable(ADC_IRQn);
80 
81     // 注册中断和channel有关,所以需要先请求
82     if (ifusedma) {
83         gst_adc.dmachannel = tls_dma_request(dmachannel, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_SDADC_CH0 + dmachannel) |
84                             TLS_DMA_FLAGS_HARD_MODE);    // 请求dma,不要直接指定,因为请求的dma可能会被别的任务使用
85         if (gst_adc.dmachannel != 0xFF) {
86             tls_dma_irq_register(gst_adc.dmachannel, (void(*)(void*))adc_dma_isr_callbk,
87                                  NULL, TLS_DMA_IRQ_TRANSFER_DONE);
88         }
89     }
90 }
91 
tls_adc_clear_irq(int inttype)92 void tls_adc_clear_irq(int inttype)
93 {
94     int reg;
95     reg = tls_reg_read32(HR_SD_ADC_INT_STATUS);
96     if (ADC_INT_TYPE_ADC == inttype) {
97         reg |= ADC_INT_MASK;
98         tls_reg_write32(HR_SD_ADC_INT_STATUS, reg);
99     } else if (ADC_INT_TYPE_ADC_COMP== inttype) {
100         reg |= CMP_INT_MASK;
101         tls_reg_write32(HR_SD_ADC_INT_STATUS, reg);
102     } else if (ADC_INT_TYPE_DMA == inttype) {
103         tls_dma_irq_clr(gst_adc.dmachannel, TLS_DMA_IRQ_TRANSFER_DONE);
104     }
105 }
106 
tls_adc_irq_register(int inttype,void (* callback)(int * buf,u16 len))107 void tls_adc_irq_register(int inttype, void (*callback)(int *buf, u16 len))
108 {
109     if (ADC_INT_TYPE_ADC == inttype) {
110         gst_adc.adc_cb = callback;
111     } else if (ADC_INT_TYPE_DMA == inttype) {
112         gst_adc.adc_dma_cb = callback;
113     } else if (ADC_INT_TYPE_ADC_COMP == inttype) {
114         gst_adc.adc_bigger_cb = callback;
115     }
116 }
117 
tls_read_adc_result(void)118 u32 tls_read_adc_result(void)
119 {
120     u32 value;
121     u32 ret;
122 
123     value = tls_reg_read32(HR_SD_ADC_RESULT_REG);
124     ret = ADC_RESULT_VAL(value);
125 
126     return ret;
127 }
128 
tls_adc_start_with_cpu(int Channel)129 void tls_adc_start_with_cpu(int Channel)
130 {
131     u32 value;
132 
133     /* Stop adc first */
134     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
135     value |= CONFIG_PD_ADC_VAL(1);
136     value &= ~(CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
137     value &= ~(CONFIG_ADC_CHL_SEL_MASK);
138     value |= CONFIG_ADC_CHL_SEL(Channel);
139 
140     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);
141 
142     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
143     value &= ~(CONFIG_PD_ADC_VAL(1));
144     value |= (CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
145     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);
146 }
147 
tls_adc_start_with_dma(int Channel,int Length)148 void tls_adc_start_with_dma(int Channel, int Length)
149 {
150     u32 value;
151     int len;
152     int channel = Channel;
153 
154     if (channel < 0 || channel > 11) { // 11:byte alignment
155         return;
156     }
157 
158     if (Length > ADC_DEST_BUFFER_SIZE)
159         len = ADC_DEST_BUFFER_SIZE;
160     else
161         len = Length;
162 
163     gst_adc.valuelen = len;
164 
165     if (adc_dma_buffer) {
166         tls_mem_free(adc_dma_buffer);
167         adc_dma_buffer = NULL;
168     }
169 
170     adc_dma_buffer = tls_mem_alloc(len * 4); // 4:byte alignment
171     if (adc_dma_buffer == NULL) {
172         wm_printf("adc dma buffer alloc failed\r\n");
173         return;
174     }
175 
176     channel &= 0xF;
177 
178     /* disable adc:set adc pd, rstn and ldo disable */
179     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
180     value |= CONFIG_PD_ADC_VAL(1);
181     value &= ~(CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
182     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);
183 
184     /* Stop dma if necessary */
185     while (DMA_CHNLCTRL_REG(gst_adc.dmachannel) & 1) {
186         DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 2; // 2:byte alignment
187     }
188 
189     DMA_SRCADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG;
190     DMA_DESTADDR_REG(gst_adc.dmachannel) = adc_dma_buffer;
191     DMA_SRCWRAPADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG;
192     DMA_DESTWRAPADDR_REG(gst_adc.dmachannel) = adc_dma_buffer;
193     DMA_WRAPSIZE_REG(gst_adc.dmachannel) = (len * 4) << 16;
194 
195     /* Dest_add_inc, halfword,  */
196     DMA_CTRL_REG(gst_adc.dmachannel) = (3 << 3)|(2 << 5)|((len * 4) << 8)|(1 << 0);
197     DMA_INTMASK_REG &= ~(0x01 << (gst_adc.dmachannel *2 + 1));
198     DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 1;        /* Enable dma */
199 
200     /* Enable dma */
201     value = tls_reg_read32(HR_SD_ADC_CTRL);
202     value |= (1 << 0);
203     tls_reg_write32(HR_SD_ADC_CTRL, value);
204 
205     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
206     value &= ~(CONFIG_ADC_CHL_SEL_MASK);
207     value |= CONFIG_ADC_CHL_SEL(channel);
208     value &= ~(CONFIG_PD_ADC_VAL(1));
209     value |= (CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
210     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);        /* start adc */
211 }
212 
tls_adc_stop(int ifusedma)213 void tls_adc_stop(int ifusedma)
214 {
215     u32 value;
216 
217     tls_reg_write32(HR_SD_ADC_PGA_CTRL, 0);
218 
219     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
220     value |= CONFIG_PD_ADC_VAL(1);
221     value &= ~(CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
222     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);
223 
224     /* Disable dma */
225     value = tls_reg_read32(HR_SD_ADC_CTRL);
226     value &= ~(1<<0);
227     tls_reg_write32(HR_SD_ADC_CTRL, value);
228 
229     /* Disable compare function and compare irq */
230     value = tls_reg_read32(HR_SD_ADC_CTRL);
231     value &= ~(3<<4);
232     tls_reg_write32(HR_SD_ADC_CTRL, value);
233 
234     if (ifusedma)
235         tls_dma_free(gst_adc.dmachannel);
236 
237     if (adc_dma_buffer) {
238         tls_mem_free(adc_dma_buffer);
239         adc_dma_buffer = NULL;
240     }
241 }
242 
tls_adc_config_cmp_reg(int cmp_data,int cmp_pol)243 void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol)
244 {
245     u32 value;
246 
247     tls_reg_write32(HR_SD_ADC_CMP_VALUE, CONFIG_ADC_INPUT_CMP_VAL(cmp_data));
248 
249     value = tls_reg_read32(HR_SD_ADC_CTRL);
250     if (cmp_pol) {
251         value |= CMP_POLAR_MASK;
252     } else {
253         value &= ~CMP_POLAR_MASK;
254     }
255     tls_reg_write32(HR_SD_ADC_CTRL, value);
256 }
257 
tls_adc_cmp_start(int Channel,int cmp_data,int cmp_pol)258 void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol)
259 {
260     u32 value;
261 
262     /* Stop adc first */
263     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
264     value |= CONFIG_PD_ADC_VAL(1);
265     value &= ~(CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
266     value |= CONFIG_ADC_CHL_SEL(Channel);
267     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);
268 
269     tls_adc_config_cmp_reg(cmp_data, cmp_pol);
270 
271     value = tls_reg_read32(HR_SD_ADC_ANA_CTRL);
272     value &= ~(CONFIG_PD_ADC_VAL(1));
273     value |= (CONFIG_RSTN_ADC_VAL(1)|CONFIG_EN_LDO_ADC_VAL(1));
274     tls_reg_write32(HR_SD_ADC_ANA_CTRL, value);     /* start adc */
275 
276     /* Enable compare function and compare irq */
277     value = tls_reg_read32(HR_SD_ADC_CTRL);
278     value |= (3<<4);
279     tls_reg_write32(HR_SD_ADC_CTRL, value);
280 }
281 
tls_adc_reference_sel(int ref)282 void tls_adc_reference_sel(int ref)
283 {
284     u32 value;
285 
286     value = tls_reg_read32(HR_SD_ADC_PGA_CTRL);
287     if (ADC_REFERENCE_EXTERNAL == ref) {
288         value |= BYPASS_INNER_REF_SEL;
289     } else if (ADC_REFERENCE_INTERNAL == ref) {
290         value &= ~BYPASS_INNER_REF_SEL;
291     }
292     tls_reg_write32(HR_SD_ADC_PGA_CTRL, value);
293 }
294 
tls_adc_set_clk(int div)295 void tls_adc_set_clk(int div)
296 {
297     u32 value;
298 
299     value = tls_reg_read32(HR_CLK_SEL_CTL);
300     value &= ~(0xFF<<8);
301     value |=  (div&0xFF)<<8;
302     tls_reg_write32(HR_CLK_SEL_CTL, value);
303     value = tls_reg_read32(HR_CLK_DIV_CTL);
304     value |= (1 << 31);
305     tls_reg_write32(HR_CLK_DIV_CTL, value);
306 }
307 
tls_adc_set_pga(int gain1,int gain2)308 void tls_adc_set_pga(int gain1, int gain2)
309 {
310     u32 val = 0;
311     u8 gain1times = 0;
312     u8 gain2times = 0;
313     switch (gain1) {
314         case 1:
315             gain1times = 0;
316             break;
317         case 16:
318             gain1times = 1;
319             break;
320         case 32:
321             gain1times = 2;
322             break;
323         case 64:
324             gain1times = 3;
325             break;
326         case 128:
327             gain1times = 4;
328             break;
329         case 256:
330             gain1times = 5;
331             break;
332         default:
333             gain1times = 0;
334             break;
335     }
336 
337     switch (gain2) {
338         case 1:
339             gain2times = 0;
340             break;
341         case 2:
342             gain2times = 1;
343             break;
344         case 3:
345             gain2times = 2;
346             break;
347         case 4:
348             gain2times = 3;
349             break;
350         default:
351             gain2times = 0;
352             break;
353     }
354 
355     val = GAIN_CTRL_PGA_VAL(gain2times)|CLK_CHOP_SEL_PGA_VAL(gain1times)|
356         PGA_BYPASS_VAL(0)|PGA_CHOP_ENP_VAL(1)|PGA_EN_VAL(1);
357     tls_reg_write32(HR_SD_ADC_PGA_CTRL, val);
358 }
359 
signedToUnsignedData(int * adcValue)360 void signedToUnsignedData(int *adcValue)
361 {
362     if (*adcValue &0x20000) {
363         *adcValue = *adcValue &0x1FFFF;
364     } else {
365         *adcValue = *adcValue |0x20000;
366     }
367 }
368 
waitForAdcDone(void)369 static void waitForAdcDone(void)
370 {
371     u32 counter = 0;
372     u32 timeout = 10000;
373     u32 reg = 0;
374 
375     /* wait for transfer success */
376     tls_irq_disable(ADC_IRQn);
377     while (timeout--) {
378         reg = tls_reg_read32(HR_SD_ADC_INT_STATUS);
379         if (reg & ADC_INT_MASK) {
380             counter++;
381             tls_reg_write32(HR_SD_ADC_INT_STATUS, reg|ADC_INT_MASK);
382             if (counter == 4) { // 4:byte alignment
383                 break;
384             }
385         } else if (reg & CMP_INT_MASK) {
386             counter++;
387             tls_reg_write32(HR_SD_ADC_INT_STATUS, reg|CMP_INT_MASK);
388             if (counter == 4) { // 4:byte alignment
389                 break;
390             }
391         }
392     }
393     tls_irq_enable(ADC_IRQn);
394 }
395 
adc_get_offset(void)396 u32 adc_get_offset(void)
397 {
398     adc_offset = 0;
399     tls_adc_init(0, 0);
400     tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
401     tls_adc_start_with_cpu(CONFIG_ADC_CHL_OFFSET);
402     tls_adc_set_pga(1, 1);
403     tls_adc_set_clk(0x28);
404 
405     waitForAdcDone();
406     adc_offset = tls_read_adc_result(); // 获取adc转换结果
407     signedToUnsignedData(&adc_offset);
408     tls_adc_stop(0);
409 
410     return adc_offset;
411 }
412 
adc_get_interTemp(void)413 int adc_get_interTemp(void)
414 {
415     return adc_temp();
416 }
417 
adc_get_inputVolt(u8 channel)418 int adc_get_inputVolt(u8 channel)
419 {
420     int average = 0;
421     double voltage = 0.0;
422 
423     adc_get_offset();
424 
425     tls_adc_init(0, 0);
426     tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
427     tls_adc_set_pga(1, 1);
428     tls_adc_set_clk(0x28);
429     tls_adc_start_with_cpu(channel);
430 
431     waitForAdcDone();
432     average = tls_read_adc_result();
433     signedToUnsignedData(&average);
434     tls_adc_stop(0);
435 
436     if ((channel == 8) || (channel == 9)) {
437         voltage = ((double)average - (double)adc_offset)/4.0;
438         voltage = voltage*(126363/1000)/1000000;
439     } else {
440         voltage = ((double)average - (double)adc_offset)/4.0;
441         voltage = 1.196 + voltage*(126363/1000.0)/1000000;
442     }
443 
444     average = (int)(voltage * 1000); // 1000:byte alignment
445     return average;
446 }
447 
adc_get_interVolt(void)448 u32 adc_get_interVolt(void)
449 {
450     u32 voltValue;
451     u32 value = 0;
452     adc_get_offset();
453 
454     tls_adc_init(0, 0);
455     tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
456     tls_adc_set_pga(1, 1);
457     tls_adc_set_clk(0x28);
458     tls_adc_start_with_cpu(CONFIG_ADC_CHL_VOLT);
459     voltValue = 0;
460     for (int i = 0;i < 10; i++) { // 10:loop cap
461         waitForAdcDone();
462         value = tls_read_adc_result();
463         signedToUnsignedData(&value);
464         voltValue += value;
465     }
466     voltValue = voltValue / 10; // 10:byte alignment
467     tls_adc_stop(0);
468     voltValue =
469         ((voltValue - adc_offset) * 685 / 20 + 1200000) * 2; // 685:byte alignment, 20:byte alignment, 2:byte alignment
470     value = voltValue - voltValue * 10 / 100; // 10:byte alignment, 100:byte alignment
471 
472     return value / 1000; // 1000:byte alignment
473 }
474 
475 /**
476  * @brief          This function is used to get chip's internal work temperature
477  *
478  * @return         chip temperature, unit: 1/1000 degree
479  *
480  * @note           Only use to get chip's internal work temperature.
481  */
adc_temp(void)482 int adc_temp(void)
483 {
484     u32 code1 = 0, code2 = 0;
485     u32 val = 0;
486     int temperature = 0;
487 
488     tls_adc_init(0, 0);
489     tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
490     tls_adc_set_pga(1, 4); // 4:value of gain2
491     tls_adc_start_with_cpu(CONFIG_ADC_CHL_TEMP);
492     tls_adc_set_clk(0x28);
493     val = tls_reg_read32(HR_SD_ADC_TEMP_CTRL);
494     val &= ~TEMP_GAIN_MASK;
495     val |= TEMP_GAIN_VAL(0);
496     val |= TEMP_EN_VAL(1);
497 
498     val &= (~(TEMP_CAL_OFFSET_MASK));
499     tls_reg_write32(HR_SD_ADC_TEMP_CTRL, val);
500     waitForAdcDone();
501     code1 = tls_read_adc_result();
502     signedToUnsignedData((int *)&code1);
503 
504     val |= TEMP_CAL_OFFSET_MASK;
505     tls_reg_write32(HR_SD_ADC_TEMP_CTRL, val);
506     waitForAdcDone();
507     code2 = tls_read_adc_result();
508     signedToUnsignedData((int *)&code2);
509 
510     val &= ~(TEMP_EN_VAL(1));
511     tls_reg_write32(HR_SD_ADC_TEMP_CTRL, val);
512 
513     tls_adc_stop(0);
514 
515     temperature = ((int)code1 - (int)code2);
516 
517     temperature = ((temperature * 1000 / (int)(2 * 2 * 4) - // 1000:byte alignment, 2:byte alignment, 4:byte alignment
518         4120702) * 1000 / 15548); // 4120702:byte alignment, 1000:byte alignment, 15548:byte alignment
519 
520     return temperature;
521 }