[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-adc.c b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-adc.c
new file mode 100644
index 0000000..453cbb8
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-adc.c
@@ -0,0 +1,426 @@
+#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);