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 }