From e19bdc2a7a948c36c7a675077ca4b906cf474e6a Mon Sep 17 00:00:00 2001
From: =?utf8?q?=E8=AE=B8=E7=9B=9B=E9=A3=9E?= <xsf@rock-chips.com>
Date: Thu, 11 Sep 2014 19:12:26 +0800
Subject: [PATCH] adc-battery: add adc-battery
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

Signed-off-by: 许盛飞 <xsf@rock-chips.com>
---
 drivers/power/Kconfig                      |   5 +
 drivers/power/Makefile                     |   1 +
 drivers/power/rk30_factory_adc_battery.c   | 451 +++++++++++++--------
 include/linux/power/rockchip-adc-battery.h |  78 ++++
 4 files changed, 364 insertions(+), 171 deletions(-)
 create mode 100755 include/linux/power/rockchip-adc-battery.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index b4efe9ae988f..4ad577dfa837 100755
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -392,6 +392,11 @@ config CHARGER_MAX8998
 	  Say Y to enable support for the battery charger control sysfs and
 	  platform data of MAX8998/LP3974 PMICs.
 
+config BATTERY_RK30_ADC_FAC
+        tristate "RK30 ADC Battery Factory"
+        help
+          Say Y to enable support for the battery on the RK30.
+
 config CHARGER_BQ2415X
 	tristate "TI BQ2415x battery charger driver"
 	depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index e29ceac95b8a..6918e87b5ed4 100755
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_CHARGER_BQ2415X)	+= bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)		+= avs/
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
+obj-$(CONFIG_BATTERY_RK30_ADC_FAC)  += rk30_factory_adc_battery.o
 obj-$(CONFIG_CW2015_BATTERY)  += cw2015_battery.o
 obj-$(CONFIG_BATTERY_RICOH619)	+= ricoh619-battery.o
 obj-$(CONFIG_CHARGER_DISPLAY)		+= rk29_charger_display.o
diff --git a/drivers/power/rk30_factory_adc_battery.c b/drivers/power/rk30_factory_adc_battery.c
index e15256617583..157e21e122ef 100644
--- a/drivers/power/rk30_factory_adc_battery.c
+++ b/drivers/power/rk30_factory_adc_battery.c
@@ -25,10 +25,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <linux/adc.h>
-#include <mach/iomux.h>
-#include <mach/board.h>
 #include <linux/delay.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
@@ -38,21 +35,28 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/earlysuspend.h>
 #include <linux/suspend.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/power/rockchip-adc-battery.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
+
 #ifdef CONFIG_EARLYSUSPEND
 /* kernel/power/earlysuspend.c */
 extern suspend_state_t get_suspend_state(void);
 #endif
 
-static int rk30_battery_dbg_level = 0;
+static int rk30_battery_dbg_level;
 module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
 #define DBG( args...) \
-	do { \
-		if (rk30_battery_dbg_level) { \
-			pr_info(args); \
-		} \
-	} while (0)
+do {\
+	if (rk30_battery_dbg_level) {\
+		pr_info(args);\
+	} \
+} while (0)
 
 #define	TIMER_MS_COUNTS		 1000	
 #define	SLOPE_SECOND_COUNTS	               15	
@@ -79,9 +83,13 @@ module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
 #elif defined(CONFIG_ARCH_RK2928)
 #define  BAT_DEFINE_VALUE                                         3300
 #else
-#define  BAT_DEFINE_VALUE	                                     2500
+#define  BAT_DEFINE_VALUE	                                  3300  /*2500*/
 #endif
 
+#define RK30_GPIO_LOW 0
+#define RK30_GPIO_HIGH 1
+
+
 
 #define BATT_FILENAME "/data/bat_last_capacity.dat"
 
@@ -97,9 +105,9 @@ unsigned long gSecondsCnt = 0;
 char gDischargeFlag[4] = {"on "};
 
 
-#ifdef CONFIG_BATTERY_RK30_VOL3V8
-#define BATT_MAX_VOL_VALUE                             4120               	//Full  charge volate	 
-#define BATT_ZERO_VOL_VALUE                            3600//3500              	//power down voltage
+#if 1
+#define BATT_MAX_VOL_VALUE	4250/*Full  charge volatge*/
+#define BATT_ZERO_VOL_VALUE	3500/*power down voltage*/
 #define BATT_NOMAL_VOL_VALUE                         3800            
 
 static int batt_table[2*BATT_NUM+6] =
@@ -157,7 +165,7 @@ struct rk30_adc_battery_data {
 	//struct timer_list       timer;
 	struct workqueue_struct *wq;
 	struct delayed_work 	    delay_work;
-	struct delayed_work	   check_work;
+	struct delayed_work	check_work;
 	struct work_struct 	    dcwakeup_work;
 	struct work_struct                   lowerpower_work;
 	bool                    resume;
@@ -231,6 +239,11 @@ extern int get_gadget_connect_flag(void);
 extern int dwc_otg_check_dpdm(void);
 static int  is_charge_ok(struct rk30_adc_battery_data *bat);
 static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat);
+extern void rk_send_wakeup_key(void);
+static  bool batt_gpio_is_valid(int number)
+{
+	return number > 0 && number < 256;
+}
 
 
 #ifdef  BATTERY_APK
@@ -245,7 +258,7 @@ static ssize_t bat_param_read(struct device *dev,struct device_attribute *attr,
 		printk("i=%d batt_table=%d\n",i+17,batt_table[i+17]);
 	return 0;
 }
-DEVICE_ATTR(batparam, 0664, bat_param_read,NULL);
+DEVICE_ATTR(batparam, 0444, bat_param_read, NULL);
 
 
 static ssize_t rkbatt_show_debug_attrs(struct device *dev,
@@ -338,6 +351,20 @@ static struct device_attribute rkbatt_attrs[] = {
 	__ATTR(flag,  0555, rkbatt_show_flag_attrs,  rkbatt_restore_flag_attrs),
 };
 
+static int rk_adc_battery_iio_read(struct rk30_adc_battery_platform_data *data)
+{
+	struct iio_channel *channel = data->chan;
+	int val, ret;
+
+	ret = iio_read_channel_raw(channel, &val);
+	if (ret < 0) {
+		pr_err("read channel() error: %d\n", ret);
+		return ret;
+	}
+	return val;
+}
+
+
 static int create_sysfs_interfaces(struct device *dev)
 {
 	int liTmep;
@@ -361,7 +388,6 @@ error:
 
 #endif
 
-
 static int rk30_adc_battery_load_capacity(void)
 {
 	char value[4];
@@ -418,26 +444,24 @@ EXPORT_SYMBOL_GPL(adc_battery_notifier_call_chain);
 static void rk_start_charge(struct rk30_adc_battery_data *bat)
 {
 	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
-	if (pdata->charge_set_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(pdata->charge_set_pin))
 		gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level);
-	}
 }
 
 static void rk_stop_charge(struct rk30_adc_battery_data *bat)
 {
 	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 
-	if (pdata->charge_set_pin != INVALID_GPIO){
+
+	if (batt_gpio_is_valid(pdata->charge_set_pin))
 		gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-	}
 }
 
 static int  get_ac_status(struct rk30_adc_battery_data *bat){
 	
 	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 	int status = 0;
-	if (pdata->dc_det_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(pdata->dc_det_pin)) {
 	       	if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level){
 				status = 1;
 			}else{
@@ -451,18 +475,8 @@ static int  get_ac_status(struct rk30_adc_battery_data *bat){
 
 	return status;
 }
-// state of charge  --- charge-display
-static int  get_usb_status1(struct rk30_adc_battery_data *bat){
-	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-	int status = 0;
-	if(pdata->is_usb_charging){
-		status = pdata->is_usb_charging();
-	}
-	return status;
-
-	
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 
-}
 //state of charge ----running
 static int  get_usb_status2(struct rk30_adc_battery_data *bat){
 
@@ -506,24 +520,22 @@ static int  get_usb_status2(struct rk30_adc_battery_data *bat){
 	return usb_status;
 
 }
-
+#endif
 static int rk_battery_get_status(struct rk30_adc_battery_data *bat)
 {
 	int charge_on = 0;
-	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+/*	struct rk30_adc_battery_platform_data *pdata = bat->pdata;*/
 	int ac_ac_charging = 0, usb_ac_charging = 0;
 	int i=0;
 
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
 	ac_ac_charging = get_ac_status(bat);
 	if(1 == ac_ac_charging)
 		charge_on = 1;
-#endif
 
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)	
 		if (strstr(saved_command_line,"charger")){
 			wake_lock(&charge_display_lock);  //lock
-			if( bat->pdata->usb_det_pin  != INVALID_GPIO ){
+			if (batt_gpio_is_valid(bat->pdata->usb_det_pin)) {
 				if( gpio_get_value(bat->pdata->usb_det_pin)== bat->pdata->usb_det_level){
 					if(( 1 == usb_ac_charging )||( 1 == ac_ac_charging ))
 						bat -> ac_charging = 1;
@@ -620,10 +632,11 @@ static int  is_charge_ok(struct rk30_adc_battery_data *bat)
 	if( 1 != bat->charge_level)
 		return -1;
 	
-	if((pdata->charge_ok_pin == INVALID_GPIO)&& ( pdata->charging_ok == NULL))
+	if ((!(batt_gpio_is_valid(pdata->charge_ok_pin))) && (
+		pdata->charging_ok == NULL))
 		return -1;
 	
-	if (pdata->charge_ok_pin != INVALID_GPIO){		
+	if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
 		if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
 			charge_is_ok =1;
 		}
@@ -634,7 +647,6 @@ static int  is_charge_ok(struct rk30_adc_battery_data *bat)
 	
 	return charge_is_ok;
 
-
 }
 
 
@@ -777,7 +789,7 @@ static int rk_adc_voltage(struct rk30_adc_battery_data *bat, int value)
 		ref_voltage = adc_get_curr_ref_volt();
 		voltage = (value * ref_voltage * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]); 
 #else
-		voltage =voltage = adc_to_voltage(value);
+		voltage = adc_to_voltage(value);
 #endif
 	}
 	
@@ -818,7 +830,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
 
 
 	value = bat->adc_val;
-	adc_async_read(bat->client);
+	bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 
 	*(bat->pSamples++) = rk_adc_voltage(bat,value);
 
@@ -900,11 +912,15 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 	int capacity = 0;
 
 	int  *p;
+
 	if (bat->pdata->use_board_table)
-		p = bat->pdata->board_batt_table;	
+		p = bat->pdata->board_batt_table;
+	else if (bat->pdata->dts_batt_table)
+		p = bat->pdata->dts_batt_table;
 	else 
 		p = batt_table;
 
+
 	if (1 == bat->charge_level){  //charge
 		if(0 == bat->start_voltage_status ){
 			if(BatVoltage >= (p[2*BATT_NUM +5])){
@@ -1011,12 +1027,11 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
     return capacity;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 
 static void rk_usb_charger(struct rk30_adc_battery_data *bat)
 {
-
 	int capacity = 0;
-//	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 	int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
 	int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
 
@@ -1145,6 +1160,7 @@ static void rk_usb_charger(struct rk30_adc_battery_data *bat)
 		bat->capacitytmp = capacity;
 
 }
+#endif
 static void rk_ac_charger(struct rk30_adc_battery_data *bat)
 {
 	int capacity = 0;
@@ -1360,10 +1376,12 @@ static void rk30_adc_battery_poweron_capacity_check(struct rk30_adc_battery_data
 		if(bat->bat_capacity == 0)
 			bat->bat_capacity =1;
 	}
-	printk("old_capacity = %d , new_capacity =%d, capacity = %d\n  ",old_capacity,new_capacity ,bat ->bat_capacity);
+	DBG("oldcapacity %d,newcapacity %d,capacity %d\n", old_capacity
+		, new_capacity, bat->bat_capacity);
 
 	bat ->bat_change = 1;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 #define to_battery_usb_device_info(x) container_of((x), \
 		struct rk30_adc_battery_data, usb);
 
@@ -1407,7 +1425,7 @@ static struct power_supply rk30_usb_supply =
 	.properties     = rk30_adc_battery_usb_props,
 	.num_properties = ARRAY_SIZE(rk30_adc_battery_usb_props),
 };
-
+#endif
 static irqreturn_t rk30_adc_battery_dc_wakeup(int irq, void *dev_id)
 {   
 	disable_irq_nosync(irq);
@@ -1470,9 +1488,6 @@ static void rk30_adc_battery_dcdet_delaywork(struct work_struct *work)
 	struct rk30_adc_battery_data  *bat = container_of((work), \
 		struct rk30_adc_battery_data, dcwakeup_work);
 
-	rk28_send_wakeup_key(); // wake up the system
-
-	
 	pdata    = bat->pdata;
 	irq        = gpio_to_irq(pdata->dc_det_pin);
 	free_irq(irq, NULL);
@@ -1484,6 +1499,7 @@ static void rk30_adc_battery_dcdet_delaywork(struct work_struct *work)
 	}
 
 	power_supply_changed(&bat ->ac);
+	rk_send_wakeup_key();
 
 	bat ->bat_status_cnt = 0;        //the state of battery is change
 
@@ -1600,7 +1616,8 @@ static void rk30_adc_battery_resume_check(struct rk30_adc_battery_data *bat)
 	bat ->old_charge_level = -1;
 	bat ->pSamples = bat->adc_samples;
 
-	adc_sync_read(bat->client);                             //start adc sample
+	bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
 	level = oldlevel =  rk_battery_get_status(bat);//rk30_adc_battery_status_samples(bat);//init charge status
 
 	for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) {               //0.3 s   
@@ -1625,7 +1642,7 @@ static void rk30_adc_battery_resume_check(struct rk30_adc_battery_data *bat)
 		bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;  // aviod the value of capacity increase    dicharge
 	}
 
-		if( bat ->pdata->batt_low_pin != INVALID_GPIO){
+		if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
 			if (gpio_get_value(bat ->pdata->batt_low_pin) == bat ->pdata->batt_low_level)
 				bat->bat_capacity = 0;
 
@@ -1642,7 +1659,7 @@ static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t st
 	data ->suspend_time = get_seconds();
 	cancel_delayed_work(&data ->delay_work);
 	
-	if( data ->pdata->batt_low_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
 		
 		irq = gpio_to_irq(data ->pdata->batt_low_pin);
 		enable_irq(irq);
@@ -1663,7 +1680,7 @@ static int rk30_adc_battery_resume(struct platform_device *dev)
 	data ->resume_time = get_seconds();
 	data ->resume = true;
 	queue_delayed_work(data->wq, &data ->delay_work, msecs_to_jiffies(100));
-	if( data ->pdata->batt_low_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
 		
 		irq = gpio_to_irq(data ->pdata ->batt_low_pin);
 	    	disable_irq_wake(irq);
@@ -1680,8 +1697,8 @@ static int rk30_adc_battery_resume(struct platform_device *dev)
 unsigned long AdcTestCnt = 0;
 static void rk30_adc_battery_timer_work(struct work_struct *work)
 {
-struct rk30_adc_battery_data  *bat = container_of((work), \
-		struct rk30_adc_battery_data, delay_work);
+	struct rk30_adc_battery_data  *bat = container_of((work), struct
+		rk30_adc_battery_data, delay_work.work);
 
 #ifdef CONFIG_PM
 	if (bat ->resume) {
@@ -1764,65 +1781,46 @@ struct rk30_adc_battery_data  *bat = container_of((work), \
 static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata)
 {
 	int ret = 0;
-	
-	if (pdata->io_init) {
-		pdata->io_init();
-		return 0;
-	}
-	
-	//charge control pin
-	if (pdata->charge_set_pin != INVALID_GPIO){
-	    	ret = gpio_request(pdata->charge_set_pin, NULL);
-	    	if (ret) {
-	    		printk("failed to request dc_det gpio\n");
-	    		goto error;
-		    	}
-	    	gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-	}
-	
-	//dc charge detect pin
-	if (pdata->dc_det_pin != INVALID_GPIO){
+
+	if (batt_gpio_is_valid(pdata->dc_det_pin)) {
 	    	ret = gpio_request(pdata->dc_det_pin, NULL);
 	    	if (ret) {
-	    		printk("failed to request dc_det gpio\n");
+			pr_info("failed to request dc_det gpio\n");
 	    		goto error;
 	    	}
 	
-	    	gpio_pull_updown(pdata->dc_det_pin, GPIOPullUp);//important
 	    	ret = gpio_direction_input(pdata->dc_det_pin);
 	    	if (ret) {
-	    		printk("failed to set gpio dc_det input\n");
+			pr_info("failed to set gpio dc_det input\n");
 	    		goto error;
 	    	}
 	}
 	
 	//charge ok detect
-	if (pdata->charge_ok_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
  		ret = gpio_request(pdata->charge_ok_pin, NULL);
 	    	if (ret) {
-	    		printk("failed to request charge_ok gpio\n");
+			pr_err("failed to request charge_ok gpio\n");
 	    		goto error;
 	    	}
 	
-	    	gpio_pull_updown(pdata->charge_ok_pin, GPIOPullUp);//important
 	    	ret = gpio_direction_input(pdata->charge_ok_pin);
 	    	if (ret) {
-	    		printk("failed to set gpio charge_ok input\n");
+			pr_err("failed to set gpio charge_ok input\n");
 	    		goto error;
 	    	}
 	}
 	//batt low pin
-	if( pdata->batt_low_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(pdata->batt_low_pin)) {
  		ret = gpio_request(pdata->batt_low_pin, NULL);
 	    	if (ret) {
-	    		printk("failed to request batt_low_pin gpio\n");
+			pr_err("failed to request batt_low_pin gpio\n");
 	    		goto error;
 	    	}
 	
-	    	gpio_pull_updown(pdata->batt_low_pin, GPIOPullUp); 
 	    	ret = gpio_direction_input(pdata->batt_low_pin);
 	    	if (ret) {
-	    		printk("failed to set gpio batt_low_pin input\n");
+			pr_err("failed to set gpio batt_low_pin input\n");
 	    		goto error;
 	    	}
 	}
@@ -1840,7 +1838,10 @@ int get_battery_status(void)
 static int rk_adc_battery_poweron_status(struct rk30_adc_battery_data *bat)
 {
 	int status; 
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 	int otg_status = 0;
+#endif
+
 //	struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 
 	if (get_ac_status(bat) ){		
@@ -1903,9 +1904,10 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 	//bat ->old_charge_level
 //	pSamples = bat->adc_samples;
 
-	adc_sync_read(bat->client);                             //start adc sample
 
-	DBG("first_adc_value is  %d \n",bat->adc_val );
+	bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
+	DBG("first_adc_value is  %d\n", bat->adc_val);
 	level = oldlevel =	 rk_adc_battery_poweron_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
 
 	for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){                //0.3 s
@@ -1925,7 +1927,7 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 		mdelay(10);
 		check_data[i] = bat->adc_val;
 		
-		adc_async_read(bat->client);
+		bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 		bat->adc_value += check_data[i];
 	}
 	bat->adc_value  /=  NUM_VOLTAGE_SAMPLE;
@@ -1989,13 +1991,16 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 #endif
 
 	if(0 !=bat ->pdata->low_voltage_protection ){
-		if((bat->bat_voltage <=  bat ->pdata->low_voltage_protection))
+		if (bat->bat_voltage <= bat->pdata->low_voltage_protection) {
 			system_lowerpower = 1;
 			printk("protection lower power .....\n");
+			}
 	}else{
-		if((bat->bat_voltage <= BATT_ZERO_VOL_VALUE))
+		if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE) {
 			system_lowerpower = 1;
-			printk("lower power .....\n");
+			pr_info("lower power bat->bat_voltage = %d\n"
+				, bat->bat_voltage);
+			}
 	}	
 
 #if 0
@@ -2006,21 +2011,6 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 
 }
 
-static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result)
-{
-	struct rk30_adc_battery_data  *bat = container_of((client), \
-				struct rk30_adc_battery_data, client);
-
-	if (result < 0){
-		DBG("adc_battery_callback    resule < 0 , the value ");
-		return;
-	}else{
-		gBatteryData->adc_val = result;
-		DBG("result = %d, gBatteryData->adc_val = %d\n", result, gBatteryData->adc_val );
-	}
-	return;
-}
-
 static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 {
 	int irq;
@@ -2028,13 +2018,12 @@ static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 	struct rk30_adc_battery_data  *bat = container_of((work), \
 			struct rk30_adc_battery_data, lowerpower_work);
 
-	if( bat->pdata->batt_low_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
 		irq = gpio_to_irq(bat ->pdata ->batt_low_pin);
 		disable_irq(irq);
 	}
 
 	printk("lowerpower\n");
- 	rk28_send_wakeup_key(); // wake up the system	
 	return;
 }
 
@@ -2052,7 +2041,7 @@ static void rk_lowerpower_check(struct rk30_adc_battery_data *bat)
 	
 	for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
 		mdelay(10);
-		adc_async_read(bat->client);
+		bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 		check_data[i] = bat->adc_val;	
 
 		adc_val += check_data[i];
@@ -2072,8 +2061,9 @@ static void rk_lowerpower_check(struct rk30_adc_battery_data *bat)
 }
 static void rk_adc_battery_check_work(struct work_struct *work)
 {
-	struct rk30_adc_battery_data  *bat = container_of((work), \
-			struct rk30_adc_battery_data, check_work);
+	struct rk30_adc_battery_data  *bat =
+		container_of((work), struct
+		rk30_adc_battery_data, check_work.work);
 	
 		if(1 == get_ac_status(bat)){
 			bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
@@ -2102,29 +2092,132 @@ static int battery_notifier_call(struct notifier_block *nb,
 		container_of(nb, struct rk30_adc_battery_data, battery_nb);
 
 	switch (event) {
-		case LCDC_ON:
-			DBG("LCDC on \n");
-			rk_lowerpower_check(bat);//for lower power protect
-			break;
+	case 1:
+		rk_lowerpower_check(bat);
+		break;
 
-		case BACKLIGHT_ON:
-			DBG("display \n");
-			poweron_lowerpoer_handle(bat);
-			break;
-		default:
-			return NOTIFY_OK;
-		}
+	case 2:
+		poweron_lowerpoer_handle(bat);
+		break;
+	default:
+		return NOTIFY_OK;
+	}
 	return NOTIFY_OK;
 }
+
+#ifdef CONFIG_OF
+static int rk31_adcbat_parse_dt(struct platform_device *pdev, struct
+rk30_adc_battery_platform_data *data)
+{
+	struct device_node *node = pdev->dev.of_node;
+	enum of_gpio_flags flags;
+	struct property *prop;
+	int length;
+	u32 value;
+	int ret;
+	int i;
+	size_t size;
+	 struct iio_channel *chan;
+
+	if (!node)
+		return -ENODEV;
+
+	chan = iio_channel_get(&pdev->dev, NULL);
+	if (IS_ERR(chan))
+		pr_err("iio_channel_get fail\n");
+	data->chan = chan;
+
+	/* determine the number of config info */
+	prop = of_find_property(node, "bat_table", &length);
+	if (!prop)
+		return -EINVAL;
+
+	length /= sizeof(u32);
+
+	if (length > 0) {
+		size = (sizeof(*data->dts_batt_table)) * length;
+		data->dts_batt_table =
+			devm_kzalloc(&(pdev->dev), size, GFP_KERNEL);
+		if (!data->dts_batt_table)
+			return -ENOMEM;
+
+		ret = of_property_read_u32_array(node
+			, "bat_table", data->dts_batt_table, length);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 4; i < length; i++) {
+		batt_table[i] = data->dts_batt_table[i];
+
+		pr_info("data->dts_batt_table[ %d ] %d %d\n", i
+			, data->dts_batt_table[i], batt_table[i]);
+	}
+	data->dc_det_pin = of_get_named_gpio_flags(node
+		, "dc_det_gpio", 0, &flags);
+	if (data->dc_det_pin == -EPROBE_DEFER)
+		pr_info("%s  dc_det_gpio error\n", __func__);
+
+	if (batt_gpio_is_valid(data->dc_det_pin))
+		data->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW)
+		?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+	data->batt_low_pin = of_get_named_gpio_flags(node
+		, "bat_low_gpio", 0, &flags);
+	if (data->batt_low_pin == -EPROBE_DEFER)
+		pr_info("%s  bat_low_gpio error\n", __func__);
+
+	if (batt_gpio_is_valid(data->batt_low_pin))
+		data->batt_low_level = (flags & OF_GPIO_ACTIVE_LOW)
+		?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+	data->charge_ok_pin = of_get_named_gpio_flags(node
+		, "chg_ok_gpio", 0, &flags);
+	if (data->charge_ok_pin == -EPROBE_DEFER)
+		pr_info("%s  chg_ok_gpio error\n", __func__);
+
+	if (batt_gpio_is_valid(data->charge_ok_pin))
+		data->charge_ok_level = (flags & OF_GPIO_ACTIVE_LOW)
+		? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+	ret = of_property_read_u32(node, "is_dc_charge", &value);
+	if (ret < 0) {
+		pr_info("%s:hardware unsupport dc charge\n", __func__);
+		value = 0;
+	}
+	data->is_dc_charge = value;
+
+	ret = of_property_read_u32(node, "is_usb_charge"
+		, &value);
+	if (ret < 0) {
+		pr_err("%s:hardware unsupport usb charge\n", __func__);
+		value = 0;
+	}
+	data->is_usb_charge = value;
+
+	pr_info("rk30 battery:support %s %s charger\n",
+		data->is_dc_charge ? "DC" : ""
+		, data->is_usb_charge ? "USB" : "");
+
+	return 0;
+}
+#else
+static int rk31_adcbat_parse_dt(struct platform_device
+*dev, struct rk30_adc_battery_platform_data *data)
+{
+	return -ENODEV;
+}
+#endif
+
+
 static int rk30_adc_battery_probe(struct platform_device *pdev)
 {
 
 	int    ret;
 	int    irq;
 	int    irq_flag;
-	struct adc_client                   *client;
 	struct rk30_adc_battery_data          *data;
-	struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+	struct rk30_adc_battery_platform_data *pdata;
 #ifdef CONFIG_MACH_RK_FAC
 	int i;
 	for(i=0;i<BATT_NUM;i++)
@@ -2134,14 +2227,21 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	}
 #endif 	
 	gSecondsCnt = get_seconds();
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	/*data = kzalloc(sizeof(*data), GFP_KERNEL);*/
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (data == NULL) {
 		ret = -ENOMEM;
 		goto err_data_alloc_failed;
 	}
+
+	/*pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);*/
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (pdata == NULL) {
+		ret = -ENOMEM;
+		goto err_pdata_alloc_failed;
+	}
 	memset(data, 0, sizeof(struct rk30_adc_battery_data));
 	gBatteryData = data;
-
 	platform_set_drvdata(pdev, data);
 
    	data->pdata = pdata;
@@ -2171,9 +2271,17 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	data->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
  	wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");	
  	wake_lock_init(&charge_display_lock, WAKE_LOCK_SUSPEND, "charge_display_lock");	//charge_display_lock
-	wake_lock_init(&batt_wake_lock_detect_lowpower, WAKE_LOCK_SUSPEND, "lowpower_lock");	
-	
-	ret = rk30_adc_battery_io_init(pdata);
+	wake_lock_init(&batt_wake_lock_detect_lowpower
+		, WAKE_LOCK_SUSPEND, "lowpower_lock");
+
+	ret = rk31_adcbat_parse_dt(pdev, data->pdata);
+	/*ret = rk31_adcbat_parse_dt(pdev, pdata);*/
+	if (ret < 0) {
+		pr_err("failed to find rk30 adc battery platform data\n");
+		goto err_io_init;
+	}
+
+	ret = rk30_adc_battery_io_init(data->pdata);
 	 if (ret) {
 	 	ret = -EINVAL;
 	 	goto err_io_init;
@@ -2182,19 +2290,12 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2));
 
 	 //register adc for battery sample
-	 if(0 == pdata->adc_channel)
-		client = adc_register(0, rk30_adc_battery_callback, NULL);  //pdata->adc_channel = ani0
-	else
-		client = adc_register(pdata->adc_channel, rk30_adc_battery_callback, NULL);  
-	if(!client){
-		ret = -EINVAL;
-		goto err_adc_register_failed;
-	}
+
 	data->wq = create_singlethread_workqueue("adc_battd");
 	    
 	 //variable init
-	data->client  = client;
-	data->adc_val = adc_sync_read(client);
+	/*data->client  = client;*/
+	data->adc_val = rk_adc_battery_iio_read(data->pdata);
 
 	data ->bat = rk30_battery_supply;
 	ret = power_supply_register(&pdev->dev,&data ->bat);
@@ -2220,13 +2321,13 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 		goto err_ac_failed;
 	}
 
-#if  defined (CONFIG_BATTERY_RK30_AC_CHARGE)
 	//init dc dectet irq & delay work
-	if (pdata->dc_det_pin != INVALID_GPIO){
+	if (batt_gpio_is_valid(data->pdata->dc_det_pin)) {
 		INIT_WORK(&data->dcwakeup_work, rk30_adc_battery_dcdet_delaywork);
 		
-		irq = gpio_to_irq(pdata->dc_det_pin);	        
-		irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+		irq = gpio_to_irq(data->pdata->dc_det_pin);
+		irq_flag = gpio_get_value(data->pdata->dc_det_pin)
+			? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
 	    	ret = request_irq(irq, rk30_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);
 	    	if (ret) {
 			ret = -EINVAL;
@@ -2236,7 +2337,6 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	    	enable_irq_wake(irq);  
     	
 	}
-#endif
 
 #ifdef BATTERY_APK
 	ret = device_create_file(&pdev->dev,&dev_attr_batparam);
@@ -2261,7 +2361,7 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 //	data->wq = create_singlethread_workqueue("adc_battd");
 	INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work);
 
-	if(1 == pdata->save_capacity ){
+	if (1 == data->pdata->save_capacity) {
 		queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10));
 		data ->poweron_check = 1;
 	}else{
@@ -2270,18 +2370,17 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	}
 	INIT_DELAYED_WORK(&data->check_work, rk_adc_battery_check_work);
 	queue_delayed_work(data ->wq, &data ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
-	if( pdata->batt_low_pin != INVALID_GPIO){
-		
-		if (gpio_get_value(pdata->batt_low_pin) ==0){
-		       mdelay(20);	   
-		       if (gpio_get_value(pdata->batt_low_pin) ==0){
+	if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
+		if (0 == gpio_get_value(data->pdata->batt_low_pin)) {
+		       mdelay(20);
+			if (gpio_get_value(data->pdata->batt_low_pin) == 0) {
 		       	 printk("lower power\n");
 		               kernel_power_off(); 
 		       }
 		}
 		
 		INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);		
-		irq = gpio_to_irq(pdata->batt_low_pin);		
+		irq = gpio_to_irq(data->pdata->batt_low_pin);
 	    	ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
 	    	if (ret) {
 			ret = -EINVAL;
@@ -2298,7 +2397,6 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 	
 	return 0;
 err_sysfs:	
-err_usb_failed:
 	power_supply_unregister(&data ->usb);
 err_ac_failed:
 	power_supply_unregister(&data ->ac);
@@ -2307,17 +2405,18 @@ err_battery_failed:
 	power_supply_unregister(&data ->bat);
     
 err_dcirq_failed:
-	if (pdata->dc_det_pin != INVALID_GPIO){
-		free_irq(gpio_to_irq(pdata->dc_det_pin), data);
-	}
+	if (batt_gpio_is_valid(data->pdata->dc_det_pin))
+		free_irq(gpio_to_irq(data->pdata->dc_det_pin), data);
 #if 1
  err_lowpowerirq_failed:
- 	if( pdata->batt_low_pin != INVALID_GPIO){
-		free_irq(gpio_to_irq(pdata->batt_low_pin), data);
- 	}
+	if (batt_gpio_is_valid(data->pdata->batt_low_pin))
+		free_irq(gpio_to_irq(data->pdata->batt_low_pin), data);
+
 #endif
-err_adc_register_failed:
-err_io_init:    
+err_io_init:
+
+err_pdata_alloc_failed:
+	kfree(pdata);
 err_data_alloc_failed:
 	kfree(data);
 
@@ -2329,23 +2428,21 @@ err_data_alloc_failed:
 static int rk30_adc_battery_remove(struct platform_device *pdev)
 {
 	struct rk30_adc_battery_data *data = platform_get_drvdata(pdev);
-	struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+	struct rk30_adc_battery_platform_data *pdata = data->pdata;
 
 	cancel_delayed_work_sync(&data->delay_work);	
-#if  defined (CONFIG_BATTERY_RK30_AC_CHARGE)
-    if (pdata->dc_det_pin != INVALID_GPIO)
-        cancel_delayed_work_sync(&data->dcwakeup_work);
-#endif
+	if (batt_gpio_is_valid(pdata->dc_det_pin))
+		cancel_work_sync(&data->dcwakeup_work);
         cancel_delayed_work_sync(&data->check_work);
 
-    if( pdata->batt_low_pin != INVALID_GPIO)
-        cancel_delayed_work_sync(&data->lowerpower_work);
+	if (batt_gpio_is_valid(pdata->batt_low_pin))
+		cancel_work_sync(&data->lowerpower_work);
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
 		power_supply_unregister(&data ->usb);
 #endif
 	power_supply_unregister(&data ->ac);
 	power_supply_unregister(&data ->bat);
-    if (pdata->dc_det_pin != INVALID_GPIO)
+	if (batt_gpio_is_valid(pdata->dc_det_pin))
 		free_irq(gpio_to_irq(pdata->dc_det_pin), data);
 
 	kfree(data);
@@ -2353,14 +2450,24 @@ static int rk30_adc_battery_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id rk30_adc_battery_dt_match[] = {
+	{ .compatible = "rk30-adc-battery",},
+	{},
+};
+MODULE_DEVICE_TABLE(of, rk30_adc_battery_dt_match);
+#endif
+
+
 static struct platform_driver rk30_adc_battery_driver = {
 	.probe		= rk30_adc_battery_probe,
 	.remove		= rk30_adc_battery_remove,
 	.suspend		= rk30_adc_battery_suspend,
 	.resume		= rk30_adc_battery_resume,
 	.driver = {
-		.name = "rk30-battery",
+		.name = "rk30-adc-battery",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(rk30_adc_battery_dt_match),
 	}
 };
 
@@ -2378,6 +2485,8 @@ subsys_initcall(rk30_adc_battery_init);
 //fs_initcall(rk30_adc_battery_init);
 module_exit(rk30_adc_battery_exit);
 
+
+
 MODULE_DESCRIPTION("Battery detect driver for the rk30");
 MODULE_AUTHOR("luowei lw@rock-chips.com");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/power/rockchip-adc-battery.h b/include/linux/power/rockchip-adc-battery.h
new file mode 100755
index 000000000000..d6e7f6290020
--- /dev/null
+++ b/include/linux/power/rockchip-adc-battery.h
@@ -0,0 +1,78 @@
+/*
+ * RockChip ADC Battery Driver
+ * Copyright (C) 2012, RockChip
+ *
+ * Authors: xuhuicong <xhc@rock-chips.com>
+ *
+ * Based on rk30_adc_battery.c
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef RK_ADC_BATTERY_H
+#define RK_ADC_BATTERY_H
+
+
+/* adc battery */
+struct rk30_adc_battery_platform_data {
+	int (*io_init)(void);
+	int (*io_deinit)(void);
+	int (*is_dc_charging)(void);
+	int (*charging_ok)(void);
+
+	int (*is_usb_charging)(void);
+	int spport_usb_charging;
+	int (*control_usb_charging)(int);
+	int usb_det_pin;
+	int dc_det_pin;
+	int batt_low_pin;
+	int charge_ok_pin;
+	int charge_set_pin;
+	int back_light_pin;
+
+	int ctrl_charge_led_pin;
+	int ctrl_charge_enable;
+	void (*ctrl_charge_led)(int);
+
+	int dc_det_level;
+	int batt_low_level;
+	int charge_ok_level;
+	int charge_set_level;
+	int usb_det_level;
+
+	int adc_channel;
+
+	int dc_det_pin_pull;
+	int batt_low_pin_pull;
+	int charge_ok_pin_pull;
+	int charge_set_pin_pull;
+
+	int low_voltage_protection;
+
+	int charging_sleep;
+
+	int is_reboot_charging;
+	int save_capacity;
+
+	int reference_voltage;
+	int pull_up_res;
+	int pull_down_res;
+
+	int time_down_discharge;
+	int time_up_charge;
+	int  use_board_table;
+	int  table_size;
+	int  *discharge_table;
+	int  *charge_table;
+	int  *property_tabel;
+	int *board_batt_table;
+	int *dts_batt_table;
+
+	int is_dc_charge;
+	int is_usb_charge;
+	struct iio_channel *chan;
+};
+#endif
-- 
2.34.1