| #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; | |
| 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; | |
| 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; | |
| //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); |