From 6e3727cab88d396286ed679152537f86f4f3d339 Mon Sep 17 00:00:00 2001 From: payton Date: Mon, 6 Nov 2023 14:25:52 +0800 Subject: [PATCH] =?UTF-8?q?1.adc=20lib=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BSP/linux-kernel/drivers/iio/adc/nvt_adc.c | 599 ++++++++++++++++++++- code/lib/include/io/adc.h | 1 + code/lib/source/io/libio.a | Bin 22102 -> 23322 bytes code/lib/source/io/libio.so | Bin 21676 -> 21880 bytes 4 files changed, 581 insertions(+), 19 deletions(-) mode change 100644 => 100755 code/lib/source/io/libio.a diff --git a/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c b/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c index 3c8dec601..3e21d97bb 100755 --- a/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c +++ b/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c @@ -20,12 +20,17 @@ #include #include #include - +#include +#include #include #include #include -#define DRV_VERSION "1.03.000" +#include +#include +#include + +#define DRV_VERSION "1.06.003" #ifdef CONFIG_NVT_FPGA_EMULATION #define CALI_VDDADC 3300 @@ -43,7 +48,7 @@ .indexed = 1, \ .channel = num, \ .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ .scan_index = num, \ .scan_type = { \ @@ -55,11 +60,13 @@ .datasheet_name = id, \ } +static UINT8 debug_adc = 0; + static uint nvt_adc_poll_mode = 1; module_param(nvt_adc_poll_mode, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nvt_adc_poll_mode, "1:poll mode, 0:irq mode"); -static uint nvt_adc_pow2div = 1; +static uint nvt_adc_pow2div = 7; module_param(nvt_adc_pow2div, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nvt_adc_pow2div, "adc sample clock pow2 div"); @@ -75,8 +82,54 @@ struct nvt_adc_state { struct clk *clk; unsigned long trim_value; u32 cali_value; + struct delayed_work adc_avg_work;// cal adc mid work + struct proc_dir_entry *pproc_adc; + }; +// ADC Average func // +// data 0 +static UINT32 *t_data = NULL; +static UINT32 t_data_now = 0; // store t_data amount +static UINT32 adc_mid_val = 0; // store average value +static UINT32 adc_mid_vol = 0; // store average voltage +static UINT32 adc_mid = 0; +static UINT32 adc_mid_first = 0; // first read ready + +// data_1 +static UINT32 *t_data1 = NULL; +static UINT32 t_data_now1 = 0; // store t_data amount +static UINT32 adc_mid1_val = 0; // store average value +static UINT32 adc_mid1_vol = 0; // store average voltage +static UINT32 adc_mid1 = 0; +static UINT32 adc_mid1_first = 0; // mid2 first read ready + +// data_2 +static UINT32 *t_data2 = NULL; +static UINT32 t_data_now2 = 0; // store t_data amount +static UINT32 adc_mid2_val = 0; // store average value +static UINT32 adc_mid2_vol = 0; // store average voltage +static UINT32 adc_mid2 = 0; +static UINT32 adc_mid2_first = 0; // mid2 first read ready + +// data_3 +static UINT32 *t_data3 = NULL; +static UINT32 t_data_now3 = 0; // store t_data amount +static UINT32 adc_mid3_val = 0; // store average value +static UINT32 adc_mid3_vol = 0; // store average voltage +static UINT32 adc_mid3 = 0; +static UINT32 adc_mid3_first = 0; // mid2 first read ready +// + +static u32 adc_base = 0; +static UINT32 adc_trim = 0; + +static UINT32 adc_avg_times = 50; +static UINT32 filter = 3 ; +static UINT32 avg_sel = 3; +static UINT32 avg_sel_sts = 0; + + static u32 adc_getreg(struct nvt_adc_state *adc, u32 offset) { return nvt_readl(adc->base + offset); @@ -121,10 +174,414 @@ static void adc_set_default_hw(struct nvt_adc_state *adc) ctrl_reg.bit.clkdiv = nvt_adc_pow2div; ctrl_reg.bit.sampavg = 0; ctrl_reg.bit.extsamp_cnt = nvt_adc_plusdiv; - ctrl_reg.bit.adc_en = 0; + ctrl_reg.bit.adc_en = 1; adc_setreg(adc, ADC_CTRL_REG_OFS, ctrl_reg.reg); } +#if 1 +static int nvt_adc_read_avg_int(void) +{ + t_data = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data ,0, adc_avg_times*sizeof(int)); + + t_data1 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data1 ,0, adc_avg_times*sizeof(int)); + + t_data2 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data2 ,0, adc_avg_times*sizeof(int)); + + t_data3 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data3 ,0, adc_avg_times*sizeof(int)); + + return 1; +} + +static void nvt_adc_read_avg(struct work_struct *work) //(struct nvt_adc_state *adc, u8 channel) +{ + UINT32 adc_data = 0; + UINT32 i = 0, temp = 0; + UINT32 channel = 0; + + struct nvt_adc_state *adc = container_of(work, struct nvt_adc_state, + adc_avg_work.work); + + //adc_mid_val = adc_mid; + //adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + //printk("\n adc_mid = %d , adc_mid_val = %d , adc_mid_vol = %d \r\n\n", adc_mid, adc_mid_val, adc_mid_vol); + if (adc_mid3_first == 0) { + //schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(10)); + goto adc_avg_work ; + } + + // data 0 + if( avg_sel == 0 ){ + + if (adc_mid_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + }else{ + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid + CALI_OFFSET)*adc_trim/511; + adc_mid_first++ ; + } + + }else { + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + }else { + + if( (temp <= (adc_mid + filter)) && (temp >= (adc_mid - filter) ) ){ + t_data[t_data_now] = temp; + t_data_now++; + } + if (t_data_now != 0 && debug_adc){ + printk("0.temp = %d, t_data[t_data_now = %d] = %d , adc_mid = %u, filter = %u\r\n",temp, t_data_now-1, t_data[t_data_now-1], adc_mid, filter); + } + + // calculate average + if (t_data_now >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid_val = adc_data; + adc_mid = adc_data; + t_data_now = 0 ; + + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + + printk("reset0 adc_mid_val = %d, adc_mid_vol = %d \r\n",adc_mid_val, adc_mid_vol); + } + } + } + + + // data 1 + } else if( avg_sel == 1 ) { + + if (adc_mid1_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid1 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 + CALI_OFFSET)*adc_trim/511; + adc_mid1_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid1 + filter)) && (temp >= (adc_mid1 - filter) ) ){ + t_data1[t_data_now1] = temp; + t_data_now1++; + } + + if (t_data_now1 != 0 && debug_adc){ + printk("1.temp = %d, t_data1[t_data_now1 = %d] = %d \r\n",temp ,t_data_now1-1, t_data1[t_data_now1-1]); + } + + // calculate average + if (t_data_now1 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data1[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid1_val = adc_data; + adc_mid1 = adc_data; + t_data_now1 = 0 ; + + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 +CALI_OFFSET)*adc_trim/511; + + printk("reset1 adc_mid1 = %d, adc_mid1_vol = %d \r\n",adc_mid1, adc_mid1_val); + } + } + } + + // data 2 + } else if( avg_sel == 2 ) { + + if (adc_mid2_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid2 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 + CALI_OFFSET)*adc_trim/511; + adc_mid2_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid2 + filter)) && (temp >= (adc_mid2 - filter) ) ){ + t_data2[t_data_now2] = temp; + t_data_now2++; + } + + if (t_data_now2 != 0 && debug_adc){ + printk("2.temp = %d, t_data2[t_data_now2 = %d] = %d \r\n",temp ,t_data_now2-1, t_data2[t_data_now2-1]); + } + + // calculate average + if (t_data_now2 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data2[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid2_val = adc_data; + adc_mid2 = adc_data; + t_data_now2 = 0 ; + + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 +CALI_OFFSET)*adc_trim/511; + + printk("reset2 adc_mid2 = %d, adc_mid2_vol = %d \r\n",adc_mid2, adc_mid2_val); + } + } + } + + // data 3 + } else if( avg_sel == 3 ) { + + if (adc_mid3_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid3 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 + CALI_OFFSET)*adc_trim/511; + adc_mid3_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid3 + filter)) && (temp >= (adc_mid3 - filter) ) ){ + t_data3[t_data_now3] = temp; + t_data_now3++; + } + + if (t_data_now3 != 0 && debug_adc){ + printk("3.temp = %d, t_data3[t_data_now3 = %d] = %d \r\n",temp ,t_data_now3-1, t_data3[t_data_now3-1]); + } + + // calculate average + if (t_data_now3 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data3[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid3_val = adc_data; + adc_mid3 = adc_data; + t_data_now3 = 0 ; + + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 +CALI_OFFSET)*adc_trim/511; + + printk("reset3 adc_mid3 = %d, adc_mid3_vol = %d adc_mid3_vol=%u\r\n",adc_mid3, adc_mid3_val, adc_mid3_vol); + } + } + } + } + + adc_avg_work : + schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(5)); +} +#endif +#if 1 + +#define MAX_CMD_LENGTH 10 +static ssize_t data_proc_cmd_write(struct file *file, const char __user *buf, + size_t size, loff_t *off) +{ + int val; + int len = size; + char cmd_line[MAX_CMD_LENGTH]; + char *cmdstr = cmd_line; + const char delimiters[] = {' ', 0x0A, 0x0D, '\0'}; + char *p_arg; + union ADC_CTRL_REG ctrl_reg; + UINT32 temp; + + // check command length + if (len > (MAX_CMD_LENGTH - 1)) { + printk("%s: Command length %d is too long\n", __func__, len); + return -EINVAL; + } + + // copy command string from user space + if (copy_from_user(cmd_line, buf, len)) { + return -EINVAL; + } + + if (len == 0) + cmd_line[0] = '\0'; + else + cmd_line[len - 1] = '\0'; + + p_arg = strsep(&cmdstr, delimiters); + sscanf(p_arg, "%x", &val); + + // set avg_sel = 0 or 1 for 1 CH connect two device + avg_sel = val; + avg_sel_sts = 1; + + printk("avg_sel = %d \n", avg_sel); + + if ( avg_sel == 5 ){ + + // Check ADC is Enable + ctrl_reg.reg = nvt_readl(adc_base + ADC_CTRL_REG_OFS); + if(!ctrl_reg.bit.adc_en){ + ctrl_reg.reg = nvt_readl(adc_base + ADC_CTRL_REG_OFS); + ctrl_reg.bit.adc_en = 1; + nvt_writel(ctrl_reg.reg, adc_base + ADC_CTRL_REG_OFS); + } + + // second value + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + 0*4); + printk("ch0 second val = %d \n", temp); + + // cal second trim2 + if(temp) + adc_trim = adc_mid3_vol * 511 / temp ; + else{ + adc_trim = 511; + printk("!!!!!!!!! temp is zero\n"); + } + + printk("adc_trim = %d \n", adc_trim); + + t_data3[t_data_now3] = temp; + t_data_now3++; + adc_mid3 = temp; + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 + CALI_OFFSET)*adc_trim/511; + + adc_mid3_first = 1 ; + + } + + return size; +} + + +static int adc_proc_show(struct seq_file *seq, void *v) +{ + UINT32 volt = 0 ; + //printk("adc_avg_value = %d, adc_avg_voltage = %d \n", adc_mid_val, adc_mid_vol); + //printk("adc_avg2 value = %d, adc2_avg_voltage = %d \n", adc_mid1_val, adc_mid1_vol); + if ( avg_sel == 0 ){ + //printk("%d\n", adc_mid_vol); + volt = adc_mid_vol; + }else if ( avg_sel == 1 ){ + //printk("%d\n", adc_mid1_vol); + volt = adc_mid1_vol; + }else if ( avg_sel == 2 ){ + //printk("%d\n", adc_mid2_vol); + volt = adc_mid2_vol; + }else if ( avg_sel == 3 ){ + printk("adc_mid3_vol = %d\n", adc_mid3_vol); + volt = adc_mid3_vol; + } + seq_printf(seq,"%d\n",volt); + + return 0; +} + +static int adc_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, adc_proc_show, NULL); +} + +static struct file_operations proc_adc_fops = { + .owner = THIS_MODULE, + .open = adc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = data_proc_cmd_write, +}; + + + + +#endif + static u32 nvt_adc_get_value(struct nvt_adc_state *adc, u8 channel) { u16 adc_data; @@ -150,6 +607,16 @@ static int nvt_adc_read_raw(struct iio_dev *iio, *value = nvt_adc_get_value(adc, channel->address); return IIO_VAL_INT; + // Read Average + case IIO_CHAN_INFO_AVERAGE_RAW: + if ( avg_sel == 0 ){ + *value = adc_mid_vol; + }else{ + *value = adc_mid1_vol; + } + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: printk("IIO_CHAN_INFO_SCALE\n"); return IIO_VAL_FRACTIONAL_LOG2; @@ -188,7 +655,7 @@ static ssize_t nvt_adc_enable(struct device *dev, ret = kstrtoul(buf, 10, &input); if (ret < 0) return ret; - + adc_set_enable(adc, input); return len; @@ -408,6 +875,8 @@ static void nvt_adc_get_trimdata(struct nvt_adc_state *adc) } } #endif + adc_trim = adc->cali_value; + //printk("adc_trim = %d \r\n",adc_trim); } #endif @@ -415,9 +884,15 @@ static int nvt_adc_probe(struct platform_device *pdev) { struct iio_dev *iio; struct nvt_adc_state *adc; - int err = 0, irq; + int err = 0, irq , i=0; struct resource *res; struct thermal_zone_device *thermal_zone = NULL; + int ret_avg = 0; + struct proc_dir_entry *pentry = NULL; + + union ADC_AIN0_DATA_REG data_reg; + union ADC_STATUS_REG sts_reg; + #ifdef CONFIG_OF const struct of_device_id *of_id; @@ -426,19 +901,19 @@ static int nvt_adc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "[NVT ADC] OF not found\n"); return -EINVAL; } - //pr_info("%s %d: of_id->compatible = %s\n", __func__, __LINE__, of_id->compatible); #endif - - adc = kzalloc(sizeof(struct nvt_adc_state), GFP_KERNEL); - if (!adc) - return -ENOMEM; - - iio = iio_device_alloc(sizeof(*adc)); - if (!iio) +printk("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + iio = iio_device_alloc(sizeof(struct nvt_adc_state) ); + if (!iio){ return -ENOMEM; + } adc = iio_priv(iio); + if (!adc ){ + err = -ENOMEM; + goto iio_free; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -450,6 +925,8 @@ static int nvt_adc_probe(struct platform_device *pdev) if (!adc->base) goto iio_free; + adc_base = (u32)adc->base; + adc->clk = clk_get(&pdev->dev, dev_name(&pdev->dev)); if (!IS_ERR(adc->clk)) { clk_prepare(adc->clk); @@ -485,7 +962,7 @@ static int nvt_adc_probe(struct platform_device *pdev) adc->sample_rate = (clk_get_rate(adc->clk) / (2 * (nvt_adc_pow2div + 1))) / (4 * (26 + nvt_adc_plusdiv)); adc_set_default_hw(adc); - + iio->name = "nvt_adc"; iio->modes = INDIO_DIRECT_MODE; iio->info = &nvt_adc_info; @@ -503,12 +980,83 @@ static int nvt_adc_probe(struct platform_device *pdev) pr_info("%s: %s done voltage %d ver %s\n", __func__, dev_name(&pdev->dev), adc->cali_value, DRV_VERSION); + udelay(30); + + // if data ready + for( i = 0 ; i< 5 ; i++ ){ + sts_reg.reg = adc_getreg(adc, ADC_STATUS_REG_OFS); + if(sts_reg.bit.ain0_datardy ==1 ){ + break; + } + udelay(50); + } + + if (i==5){ + printk("\n adc ready timout !!\r\n"); + } + data_reg.reg = adc_getreg(adc, ADC_AIN0_DATA_REG_OFS); + + // read first value + adc_mid3_first = 0; + if ( avg_sel == 0 ){ + adc_mid = data_reg.reg; + adc_mid_first = 1 ; // already get firstly value + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid first value = %u\n", adc_mid_val); + + }else if(avg_sel == 1 ) { + adc_mid1 = data_reg.reg; + adc_mid1_first = 1 ; // already get firstly value + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid1 first value = %u\n", adc_mid1_val); + + }else if(avg_sel == 2 ) { + adc_mid2 = data_reg.reg; + adc_mid2_first = 1 ; // already get firstly value + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid2 first value = %u\n", adc_mid2_val); + + }else if(avg_sel == 3 ) { + adc_mid3 = data_reg.reg; +// adc_mid3_first = 1 ; // already get firstly value + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid3 first value = %u\n", adc_mid3_val); + } + + +#if 1 + // ADC Average data + /* tempeture compensation */ + ret_avg = nvt_adc_read_avg_int(); + + if(ret_avg){ + INIT_DELAYED_WORK(&adc->adc_avg_work, nvt_adc_read_avg); + schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(1)); + } + + pentry = proc_create("adc", 0, NULL, &proc_adc_fops); + if (pentry == NULL) { + dev_err(&pdev->dev, "failed to create adc proc!\n"); + err = -EINVAL; + goto t_data_free; + } + adc->pproc_adc = pentry; +#endif thermal_zone = thermal_zone_device_register("nvt_thermal", 0, 0, adc, &ops, NULL, 0, 0); if (IS_ERR(thermal_zone)) { dev_err(&pdev->dev, "thermal zone device is NULL\n"); - return PTR_ERR(thermal_zone); + err = PTR_ERR(thermal_zone); + goto t_data_free; } thermal_get_trimdata(adc); @@ -518,7 +1066,14 @@ static int nvt_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, thermal_zone); return 0; - + +t_data_free: + cancel_delayed_work(&adc->adc_avg_work); + kfree(t_data); + kfree(t_data1); + kfree(t_data2); + kfree(t_data3); + iio_free: iio_device_free(iio); @@ -527,10 +1082,16 @@ iio_free: static int nvt_adc_remove(struct platform_device *pdev) { - struct iio_dev *iio = platform_get_drvdata(pdev);; + struct iio_dev *iio = platform_get_drvdata(pdev); + struct nvt_adc_state *adc ; + adc = iio_priv(iio); + + cancel_delayed_work(&adc->adc_avg_work); iio_device_unregister(iio); iio_device_free(iio); + remove_proc_entry("adc", NULL); + kfree(t_data); return 0; } diff --git a/code/lib/include/io/adc.h b/code/lib/include/io/adc.h index ab00c8513..a12312e36 100755 --- a/code/lib/include/io/adc.h +++ b/code/lib/include/io/adc.h @@ -379,6 +379,7 @@ extern UINT32 adc_readData(ADC_CHANNEL Channel); extern BOOL adc_isDataReady(ADC_CHANNEL Channel); extern void adc_clearDataReady(ADC_CHANNEL Channel); extern UINT32 adc_readVoltage(ADC_CHANNEL Channel); +extern UINT32 adc_readVoltage_channel0_avg(UINT32 device_id, UINT32 delay_time_ms); extern UINT32 adc_thermal_read_data(void); extern UINT32 adc_thermal_read_voltage(void); diff --git a/code/lib/source/io/libio.a b/code/lib/source/io/libio.a old mode 100644 new mode 100755 index 8ef69015ff6fcaddb5794671dbaf4ac7719836d6..2a596557a97528bac79cc56d1b6c3a5b35cc7a2d GIT binary patch delta 3871 zcmcguYitx%6h714ZM(JGE*r|)e=vw)E*5F3?3g0fw@OH0yrn?6W+ zxz(b8P-(a-K0x*d)&`A`REa;7^an9bG)jCBjF{4vMih)C5~4AJ=gi#QogKhm#+$u! z?)RPZow@hS+`DuBec{d1!mvG9S6$(ft14wl!XGy6Rg%hOxk90(<|F{905F#Qr#%>x zu=oVP|I@v`7Ehqd-^p%@gY2-dEVJA1^)&_Bd%dlGPfMG(v(w)$d%Rm)+0FT{j$vv>hPn06L6PG?@ThGs(z@ zlN#aZ?25^u>A8VVulO+52ghb934of|h)Ki#)#wZJQGL`eqdy)O2H=d&JS;woB|47% zb?m#bKh1js+LEz@33-D3Ue5)9jV2zd3-t9$fz8sEPM^QOWMO;XqNMB%atDCFr7a-I z{m4iUNzShBK#LQfA5J1X94j_k49jXj#9O(stE~nyaL^WpPy;zQeprL^aoirotS|Y6 zN~;hiGNA~EC1D6va6gXS8Z4`0=Cr3Xhow-cX1`VCvZpMM2oihC;uO-@=Xfn-e_2+g zCq#5KC<5Ao5?hs$#dfENY$Qcu=Tjt0J&!V?71-}71?H7uhUKLev!+zZ{3K^`SunNO z?B&SDP9h3$l*J|y?c&JFQmw_7{T$6lE3isy!MZm%lST|32%2VqN@b2wsuJGifa)xu zU)u~=A6gSOs)xw{)sTes$Pl{-p#UP}>ZB8UA0jXf&k6H-;E97#l`scwCjz3i5MR0RWY3L@8 z>hR+_+@!(jBv`H?2tUIn>oS6W;7Eit=+}8)=9s284;I7QF?bPt!11`Ex4{{XWwat> z!VesyTbb^(4*#O!Ao-Pm>$(6#oZ?cpfCzTTiorQh5rY@Na*k=6i6FsRj%5Wqpfx7G z5OydSPgvSxBJPPH9-ywcgsl}ztu;`#dPOZ=s_Eil1LDG_S{HacoBKLjJf5;z*;NsP zYP6_MjzLu#R4!M>AlKNhVv69t=ONYM@96ROLQhxsmd@VI(6g$GGN*-J` z38~st392r=BUJ5}8+fCMVt8MeXLBoDW8d1+1omadeU_NdoU!jSmI)cSN6NYbK5wtL zOuJWDc~*MRg}drbAMTaAu~m0rY46+_TP{cMNgrkR+Dh?dJ-yxKWo%#85msbBWp?9V zQX*ENo=w_Unj0d>nZ4577(qcq>m%qZM9mSDm-Cak4N>XZf;@;Cu!ySf zWNrbATb0H-*H}wOkquD{c6vNU>@<&7d=>DA|2b;wH?niNw)z(2%*ePo-H@)zNN&d- zmhaKYL#ljGCvVosb2Rc3I{AbuAJNJCHSz@-`B|NO&dA0W*y_i1@?ni!(#WTD@?_JY zY+L=0I`ybVje91t^uKlLr6#3vf9mAp8hN2co*frkc%LfIKw4Y)3mSQmMqY_=^!yCi zsU0w}MyV(cjXTFCuDjD4lI$ru0Yz@-)6nEWdebnc(I{=$ggcy%$g33 zrCh^tpXlNyOl(fFiC^pJ%SdP2#49@b2CgdKR)0%JC*n&>Cq}r1Z?G(2|7Z-|WmvELxIZdAe)Eo%_csNHI zNvV(UxUi!!fi>H0;%TJu*QKG?JBloOF^hyR#skQAvHgy0(`2NwWwqyPW_ delta 3015 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