1.adc lib更改

This commit is contained in:
payton 2023-11-06 14:25:52 +08:00 committed by payton
parent 44147ee664
commit 6e3727cab8
4 changed files with 581 additions and 19 deletions

View File

@ -20,12 +20,17 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <plat/adc_reg.h> #include <plat/adc_reg.h>
#include <plat/efuse_protected.h> #include <plat/efuse_protected.h>
#include <plat/top.h> #include <plat/top.h>
#define DRV_VERSION "1.03.000" #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#define DRV_VERSION "1.06.003"
#ifdef CONFIG_NVT_FPGA_EMULATION #ifdef CONFIG_NVT_FPGA_EMULATION
#define CALI_VDDADC 3300 #define CALI_VDDADC 3300
@ -43,7 +48,7 @@
.indexed = 1, \ .indexed = 1, \
.channel = num, \ .channel = num, \
.address = 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),\ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
.scan_index = num, \ .scan_index = num, \
.scan_type = { \ .scan_type = { \
@ -55,11 +60,13 @@
.datasheet_name = id, \ .datasheet_name = id, \
} }
static UINT8 debug_adc = 0;
static uint nvt_adc_poll_mode = 1; static uint nvt_adc_poll_mode = 1;
module_param(nvt_adc_poll_mode, int, S_IRUGO | S_IWUSR); module_param(nvt_adc_poll_mode, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(nvt_adc_poll_mode, "1:poll mode, 0:irq mode"); 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_param(nvt_adc_pow2div, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(nvt_adc_pow2div, "adc sample clock pow2 div"); MODULE_PARM_DESC(nvt_adc_pow2div, "adc sample clock pow2 div");
@ -75,8 +82,54 @@ struct nvt_adc_state {
struct clk *clk; struct clk *clk;
unsigned long trim_value; unsigned long trim_value;
u32 cali_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) static u32 adc_getreg(struct nvt_adc_state *adc, u32 offset)
{ {
return nvt_readl(adc->base + 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.clkdiv = nvt_adc_pow2div;
ctrl_reg.bit.sampavg = 0; ctrl_reg.bit.sampavg = 0;
ctrl_reg.bit.extsamp_cnt = nvt_adc_plusdiv; 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); 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) static u32 nvt_adc_get_value(struct nvt_adc_state *adc, u8 channel)
{ {
u16 adc_data; 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); *value = nvt_adc_get_value(adc, channel->address);
return IIO_VAL_INT; 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: case IIO_CHAN_INFO_SCALE:
printk("IIO_CHAN_INFO_SCALE\n"); printk("IIO_CHAN_INFO_SCALE\n");
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
@ -408,6 +875,8 @@ static void nvt_adc_get_trimdata(struct nvt_adc_state *adc)
} }
} }
#endif #endif
adc_trim = adc->cali_value;
//printk("adc_trim = %d \r\n",adc_trim);
} }
#endif #endif
@ -415,9 +884,15 @@ static int nvt_adc_probe(struct platform_device *pdev)
{ {
struct iio_dev *iio; struct iio_dev *iio;
struct nvt_adc_state *adc; struct nvt_adc_state *adc;
int err = 0, irq; int err = 0, irq , i=0;
struct resource *res; struct resource *res;
struct thermal_zone_device *thermal_zone = NULL; 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 #ifdef CONFIG_OF
const struct of_device_id *of_id; 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"); dev_err(&pdev->dev, "[NVT ADC] OF not found\n");
return -EINVAL; return -EINVAL;
} }
//pr_info("%s %d: of_id->compatible = %s\n", __func__, __LINE__, of_id->compatible); //pr_info("%s %d: of_id->compatible = %s\n", __func__, __LINE__, of_id->compatible);
#endif #endif
printk("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
adc = kzalloc(sizeof(struct nvt_adc_state), GFP_KERNEL); iio = iio_device_alloc(sizeof(struct nvt_adc_state) );
if (!adc) if (!iio){
return -ENOMEM;
iio = iio_device_alloc(sizeof(*adc));
if (!iio)
return -ENOMEM; return -ENOMEM;
}
adc = iio_priv(iio); adc = iio_priv(iio);
if (!adc ){
err = -ENOMEM;
goto iio_free;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
@ -450,6 +925,8 @@ static int nvt_adc_probe(struct platform_device *pdev)
if (!adc->base) if (!adc->base)
goto iio_free; goto iio_free;
adc_base = (u32)adc->base;
adc->clk = clk_get(&pdev->dev, dev_name(&pdev->dev)); adc->clk = clk_get(&pdev->dev, dev_name(&pdev->dev));
if (!IS_ERR(adc->clk)) { if (!IS_ERR(adc->clk)) {
clk_prepare(adc->clk); clk_prepare(adc->clk);
@ -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); 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, thermal_zone = thermal_zone_device_register("nvt_thermal", 0, 0,
adc, &ops, NULL, 0, 0); adc, &ops, NULL, 0, 0);
if (IS_ERR(thermal_zone)) { if (IS_ERR(thermal_zone)) {
dev_err(&pdev->dev, "thermal zone device is NULL\n"); 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); thermal_get_trimdata(adc);
@ -519,6 +1067,13 @@ static int nvt_adc_probe(struct platform_device *pdev)
return 0; 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_free:
iio_device_free(iio); iio_device_free(iio);
@ -527,10 +1082,16 @@ iio_free:
static int nvt_adc_remove(struct platform_device *pdev) 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_unregister(iio);
iio_device_free(iio); iio_device_free(iio);
remove_proc_entry("adc", NULL);
kfree(t_data);
return 0; return 0;
} }

View File

@ -379,6 +379,7 @@ extern UINT32 adc_readData(ADC_CHANNEL Channel);
extern BOOL adc_isDataReady(ADC_CHANNEL Channel); extern BOOL adc_isDataReady(ADC_CHANNEL Channel);
extern void adc_clearDataReady(ADC_CHANNEL Channel); extern void adc_clearDataReady(ADC_CHANNEL Channel);
extern UINT32 adc_readVoltage(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_data(void);
extern UINT32 adc_thermal_read_voltage(void); extern UINT32 adc_thermal_read_voltage(void);

BIN
code/lib/source/io/libio.a Normal file → Executable file

Binary file not shown.

Binary file not shown.