blob: af82c3d18ffb9509168e9dd75833a0754b64c973 [file] [log] [blame]
#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);