#include <linux/init.h> /* For init/exit macros */ | |
#include <linux/module.h> /* For MODULE_ marcros */ | |
#include <linux/interrupt.h> | |
#include <linux/spinlock.h> | |
#include <linux/platform_device.h> | |
#include <linux/device.h> | |
#include <linux/fs.h> | |
#include <linux/cdev.h> | |
#include <linux/delay.h> | |
#include <linux/mutex.h> | |
#include <linux/kthread.h> | |
#include <linux/rtc.h> | |
#include <linux/mfd/zx234290.h> | |
#include <mach/spinlock.h> | |
#include <linux/wakelock.h> | |
#define ZX234290_VBAT_ADC_COMPENDATE_VALUE 50 | |
typedef enum adc_channel | |
{ | |
ADC_CHANNEL_VBAT_ADC = 0, | |
ADC_CHANNEL_VADC2 = 1, /* 01 */ | |
ADC_CHANNEL_VADC1 = 2, /* 10 */ | |
MAX_ADC_CHANNEL | |
}zx234290_adc_channel; | |
/******************************************************************************* | |
* Function:zx234290_adc_correspond | |
* Description:adjust battery voltage according to compensate value | |
* Parameters: | |
* Input: | |
* channel: adc channel | |
* value:battery voltage needed be compensated | |
* Output: | |
* | |
* Returns: | |
* 0: success | |
* -1:failed | |
* | |
* Others: | |
********************************************************************************/ | |
static int zx234290_adc_correspond(zx234290_adc_channel channel, int *value) | |
{ | |
int nTemp; | |
switch (channel) | |
{ | |
case ADC_CHANNEL_VBAT_ADC: | |
{ | |
nTemp = (int)((uint64_t)(5000-0)*(*value)/4096); | |
*value = nTemp + 0;//ZX234290_VBAT_ADC_COMPENDATE_VALUE; // compensate the battery voltage value | |
break; | |
} | |
case ADC_CHANNEL_VADC1: | |
{ | |
nTemp = (int)((uint64_t)(5000-0)*(*value)/4096); | |
*value = nTemp + 0; | |
break; | |
} | |
case ADC_CHANNEL_VADC2: | |
{ | |
nTemp = (int)((uint64_t)(5000-0)*(*value)/4096); | |
*value = nTemp + 0; | |
break; | |
} | |
default: | |
{ | |
return -1; | |
} | |
} | |
return 0; | |
} | |
/******************************************************************************* | |
* Function:zx234290_adc_read_vbat | |
* Description:read vbat adc value | |
* Parameters: | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* nTempAdc:the value of vbat adc | |
* Others: | |
********************************************************************************/ | |
static int zx234290_adc_read_vbat(void) | |
{ | |
int nRet; | |
int nTempAdc = 0; | |
unsigned char msb=0, lsb=0; | |
/* read msb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC_VBATMSB, &msb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_VBATADC_MSB, &msb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
/* read lsb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC_VBATLSB, &lsb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_VBATADC_LSB, &lsb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
nTempAdc = (int)msb; | |
nTempAdc = ((nTempAdc<<4)|lsb>>4); | |
return nTempAdc; | |
} | |
/******************************************************************************* | |
* Function:zx234290_adc_read_adc1 | |
* Description:read the channel of adc1 value | |
* Parameters: | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* nTempAdc:the value of adc1 channel | |
* Others: | |
********************************************************************************/ | |
static int zx234290_adc_read_adc1(void) | |
{ | |
int nRet; | |
int nTempAdc = 0; | |
unsigned char msb=0, lsb=0; | |
/* read msb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC1MSB, &msb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC1_MSB, &msb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
/* read lsb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC1LSB, &lsb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC1_LSB, &lsb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
nTempAdc = (int)msb; | |
nTempAdc = ((nTempAdc<<4)|lsb>>4); | |
return nTempAdc; | |
} | |
/******************************************************************************* | |
* Function:zx234290_adc_read_adc2 | |
* Description:read the channel of adc2value | |
* Parameters: | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* nTempAdc:the value of adc2 channel | |
* Others: | |
********************************************************************************/ | |
static int zx234290_adc_read_adc2(void) | |
{ | |
int nRet; | |
int nTempAdc = 0; | |
unsigned char msb=0, lsb=0; | |
/* read msb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC2MSB, &msb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC2_MSB, &msb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
/* read lsb */ | |
//nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC2LSB, &lsb); | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_ADC2_LSB, &lsb); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
nTempAdc = (int)msb; | |
nTempAdc = ((nTempAdc<<4)|lsb>>4); | |
return nTempAdc; | |
} | |
/************************************************************************** | |
* Function: zx234290_adc_read | |
* Description: read ADC value according to adc channel | |
* Parameters: | |
* Input: | |
* channel:which channel want to be read | |
* | |
* Output: | |
* value:the adc value correspond to channel | |
* Returns: | |
* 0 if success, not 0 if faile | |
* Others: None | |
**************************************************************************/ | |
extern struct wake_lock adc_wake_lock; | |
static int zx234290_adc_read(zx234290_adc_channel channel, int *value) | |
{ | |
int nRet = 0; | |
int nTempAdc = 0; | |
int reg_val=0, mask=0; | |
int num=1; | |
unsigned char status_a=0; | |
unsigned char content =0; | |
if(channel >= MAX_ADC_CHANNEL) | |
{ | |
return -1; | |
} | |
soft_spin_lock(ADC_SFLOCK); | |
wake_lock(&adc_wake_lock); | |
if (channel != ADC_CHANNEL_VBAT_ADC) | |
{ | |
/* select channel */ | |
reg_val = channel << 3; /* ×óÒÆ3λ£¬Î»¿í 2λ */ | |
mask = 0x18; | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return nRet; | |
} | |
content &= ~mask; | |
content |= reg_val; | |
nRet = zx234290_i2c_write_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return nRet; | |
} | |
} | |
#if 0 | |
/* set start bit */ | |
reg_val = 1 << 5; /* ¸ÃλÖà 1 */ | |
mask = 0x20; | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
content &= ~mask; | |
content |= reg_val; | |
nRet = zx234290_i2c_write_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
return nRet; | |
} | |
msleep(30); /* ÑÓʱ30ms */ | |
#else | |
reg_val = 1 << 5; /* ¸ÃλÖà 1 */ | |
mask = 0x20; | |
for(num=1; num <= 50; num++) | |
{ | |
/* set start bit */ | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return nRet; | |
} | |
content &= ~mask; | |
content |= reg_val; | |
nRet = zx234290_i2c_write_simple(ZX234290_REG_ADDR_SYS_CTRL, &content); | |
if (nRet != 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return nRet; | |
} | |
udelay(500); | |
/*read status_A*/ | |
nRet = zx234290_i2c_read_simple(ZX234290_REG_ADDR_STSA, &status_a); | |
if (nRet != 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return nRet; | |
} | |
if(status_a & 0x04) | |
{ | |
// printk( "get adc,break num =%d ...\n", num); | |
break; | |
} | |
} | |
#endif | |
/* ÕâÀïÒªµÈÖжÏÀ´ ²ÅÄܶÁ */ | |
switch (channel) { | |
case ADC_CHANNEL_VBAT_ADC: | |
nTempAdc = zx234290_adc_read_vbat(); | |
break; | |
case ADC_CHANNEL_VADC1: | |
nTempAdc = zx234290_adc_read_adc1(); | |
break; | |
case ADC_CHANNEL_VADC2: | |
nTempAdc = zx234290_adc_read_adc2(); | |
break; | |
default: | |
break; | |
} | |
if (nTempAdc < 0) | |
{ | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
return 0; | |
} | |
/* ת»» */ | |
zx234290_adc_correspond(channel, &nTempAdc); | |
*value = (int)nTempAdc; | |
wake_unlock(&adc_wake_lock); | |
soft_spin_unlock(ADC_SFLOCK); | |
//pmic_AdcUnlock(); | |
return nRet; | |
} | |
/************************************************************************** | |
* Function: get_battery_voltage | |
* Description: get battery voltage | |
* Parameters: | |
* Input: | |
* | |
* | |
* Output: | |
* | |
* Returns: | |
* avgValue:battery voltage | |
* Others: None | |
**************************************************************************/ | |
uint get_battery_voltage(void) | |
{ | |
int counter = 3; | |
int index=0; | |
int tmpValue=0,totalValue=0; | |
uint avgValue; | |
#ifdef _USE_VEHICLE_DC | |
printk("%s adc not support in ap\n",__func__); | |
return 0; | |
#endif | |
for(index = 0; index < counter; index++) | |
{ | |
zx234290_adc_read(ADC_CHANNEL_VBAT_ADC, &tmpValue); | |
totalValue += tmpValue; | |
} | |
avgValue = (uint)(totalValue / counter); | |
return avgValue; | |
} | |
EXPORT_SYMBOL(get_battery_voltage); | |
/************************************************************************** | |
* Function: get_adc1_voltage | |
* Description: get adc1 voltage | |
* Parameters: | |
* Input: | |
* | |
* | |
* Output: | |
* | |
* Returns: | |
* avgValue:adc voltage | |
* Others: None | |
**************************************************************************/ | |
uint get_adc1_voltage(void) | |
{ | |
int counter = 3; | |
int index=0; | |
int tmpValue=0,totalValue=0; | |
uint avgValue; | |
#ifdef _USE_VEHICLE_DC | |
printk("%s adc not support in ap\n",__func__); | |
return 0; | |
#endif | |
for(index = 0; index < counter; index++) | |
{ | |
zx234290_adc_read(ADC_CHANNEL_VADC1, &tmpValue); | |
totalValue += tmpValue; | |
} | |
avgValue = (uint)(totalValue / counter); | |
return avgValue; | |
} | |
EXPORT_SYMBOL(get_adc1_voltage); | |
/************************************************************************** | |
* Function: get_adc2_voltage | |
* Description: get adc2 voltage | |
* Parameters: | |
* Input: | |
* | |
* | |
* Output: | |
* | |
* Returns: | |
* avgValue:adc2 voltage | |
* Others: None | |
**************************************************************************/ | |
//extern struct wake_lock adc_wake_lock; | |
uint get_adc2_voltage(void) | |
{ | |
int counter = 3; | |
int index=0; | |
int tmpValue=0,totalValue=0; | |
uint avgValue; | |
#ifdef _USE_VEHICLE_DC | |
printk("%s adc not support in ap\n",__func__); | |
return 0; | |
#endif | |
//wake_lock(&adc_wake_lock); | |
for(index = 0; index < counter; index++) | |
{ | |
zx234290_adc_read(ADC_CHANNEL_VADC2, &tmpValue); | |
totalValue += tmpValue; | |
} | |
//wake_unlock(&adc_wake_lock); | |
avgValue = (uint)(totalValue / counter); | |
return avgValue; | |
} | |
EXPORT_SYMBOL(get_adc2_voltage); |