zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/power/zx234502_charger.c b/ap/os/linux/linux-3.4.x/drivers/power/zx234502_charger.c
new file mode 100644
index 0000000..9e72408
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/power/zx234502_charger.c
@@ -0,0 +1,2391 @@
+/*
+ * Driver for the TI zx234502 battery charger.
+ *
+ * Author: Mark A. Greer <mgreer@animalcreek.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+//#include <linux/mutex.h>
+#include <linux/semaphore.h>
+
+#include <linux/power/zx234502_charger.h>
+#include <linux/mfd/zx234290.h>
+
+#include <mach/gpio.h>
+#include <mach/pcu.h>
+#include <mach/zx29_usb.h>
+#include <linux/workqueue.h>
+
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+
+/*
+ * The FAULT register is latched by the zx234502 (except for NTC_FAULT)
+ * so the first read after a fault returns the latched value and subsequent
+ * reads return the current value.  In order to return the fault status
+ * to the user, have the interrupt handler save the reg's value and retrieve
+ * it in the appropriate health/status routine.  Each routine has its own
+ * flag indicating whether it should use the value stored by the last run
+ * of the interrupt handler or do an actual reg read.  That way each routine
+ * can report back whatever fault may have occured.
+ */
+struct zx234502_dev_info {
+	struct i2c_client		*client;
+	struct device			*dev;
+	struct power_supply		charger;
+	struct power_supply		battery;
+	struct power_supply     boost;
+	char					model_name[I2C_NAME_SIZE];
+	kernel_ulong_t			model;
+	unsigned int			gpio_int;
+	unsigned int			irq;
+	struct mutex			bs_reg_lock;
+	bool			first_time; /*let the first reset do not ask mmi*/
+	bool			charger_health_valid;
+	bool			battery_health_valid;
+	bool			battery_status_valid;
+	u8				ciis_curr_reg;
+	u8				cbis_curr_reg;
+	u8              pis_curr_reg;
+	u8              cfis_curr_reg;
+
+	u8				ciis_pre_reg;
+	u8				cbis_pre_reg;
+	u8              pis_pre_reg;
+	u8              cfis_pre_reg;
+	u8				watchdog;
+	u8				boost_online_flag;
+	struct delayed_work		boostWorkStruct ;
+	struct workqueue_struct *boostQueue;
+	struct semaphore		chgirq_sem;
+	struct task_struct		*chg_irq_thread;
+	u16 boostcount;
+	
+	struct zx234502_platform_data *pdata;
+    //unsigned int    chg_type;
+};
+
+//struct zx234502_platform_data *g_platform_data = NULL;
+struct zx234502_dev_info *g_bdi = NULL;
+
+/* REG01[2:0] (ISET_DCIN) in mAh */
+static const int zx234502_in_ilimit_values[] = {
+   150,  450,  850,  1000,  1500,  2000, 2500, 3000
+};
+/* REG01[6:3] (VINDPM) in mVh */
+static const int zx234502_vindpm_values[] = {
+   3880,  3960,  4040,  4120,  
+   4200,4280, 4360, 4440,
+   4520,4600, 4680, 4760,
+   4840,4920, 5000, 5080,
+};
+
+/*
+ * The tables below provide a 2-way mapping for the value that goes in
+ * the register field and the real-world value that it represents.
+ * The index of the array is the value that goes in the register; the
+ * number at that index in the array is the real-world value that it
+ * represents.
+ */
+/* REG02[7:2] (ISETA) in mAh */
+static const int zx234502_isc_ichg_values[] = {
+	 512,  576,  640,  704,  768,  832,  896,  960,
+	1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472,
+	1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984,
+	2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496,
+	2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008,
+	3072, 3136, 3200, 3264, 3328, 3392, 3456, 3520,
+	3584, 3648, 3712, 3776, 3840, 3904, 3968, 4032,
+	4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544
+};
+
+/* REG04[3:1] (VSETA) in mV */
+static const int zx234502_cvc_vseta_values[] = {
+	4100, 4150, 4200, 4250, 4300, 4350, 4400, 4450,
+};
+
+/* REG02[7:5] (VSYS_MIN) in mV */
+static const int zx234502_vsc_sysmin_values[] = {
+	3100, 3200, 3300, 3400, 3500, 3600, 3700,3800
+};
+static int stopchg_flag = 0;
+/*
+ * Return the index in 'tbl' of greatest value that is less than or equal to
+ * 'val'.  The index range returned is 0 to 'tbl_size' - 1.  Assumes that
+ * the values in 'tbl' are sorted from smallest to largest and 'tbl_size'
+ * is less than 2^8.
+ */
+static u8 zx234502_find_idx(const int tbl[], int tbl_size, int v)
+{
+	int i;
+
+	for (i = 1; i < tbl_size; i++)
+		if (v < tbl[i])
+			break;
+
+	return i - 1;
+}
+
+/* Basic driver I/O routines */
+
+static int zx234502_read(struct zx234502_dev_info *bdi, u8 reg, u8 *data)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(bdi->client, reg);
+	if (ret < 0)
+		return ret;
+
+	*data = ret;
+	return 0;
+}
+
+static int zx234502_write(struct zx234502_dev_info *bdi, u8 reg, u8 data)
+{
+	return i2c_smbus_write_byte_data(bdi->client, reg, data);
+}
+
+static int zx234502_read_mask(struct zx234502_dev_info *bdi, u8 reg,
+		u8 mask, u8 shift, u8 *data)
+{
+	u8 v;
+	int ret;
+
+	ret = zx234502_read(bdi, reg, &v);
+	if (ret < 0)
+		return ret;
+
+	v &= mask;
+	v >>= shift;
+	*data = v;
+
+	return 0;
+}
+
+static int zx234502_write_mask(struct zx234502_dev_info *bdi, u8 reg,
+		u8 mask, u8 shift, u8 data)
+{
+	u8 v;
+	int ret;
+
+	ret = zx234502_read(bdi, reg, &v);
+	if (ret < 0)
+		return ret;
+
+	v &= ~mask;
+	v |= ((data << shift) & mask);
+
+	return zx234502_write(bdi, reg, v);
+}
+
+static int zx234502_get_field_val(struct zx234502_dev_info *bdi,
+		u8 reg, u8 mask, u8 shift,
+		const int tbl[], int tbl_size,
+		int *val)
+{
+	u8 v;
+	int ret;
+
+	ret = zx234502_read_mask(bdi, reg, mask, shift, &v);
+	if (ret < 0)
+		return ret;
+
+	v = (v >= tbl_size) ? (tbl_size - 1) : v;
+	*val = tbl[v];
+
+	return 0;
+}
+
+static int zx234502_set_field_val(struct zx234502_dev_info *bdi,
+		u8 reg, u8 mask, u8 shift,
+		const int tbl[], int tbl_size,
+		int val)
+{
+	u8 idx;
+
+	idx = zx234502_find_idx(tbl, tbl_size, val);
+
+	return zx234502_write_mask(bdi, reg, mask, shift, idx);
+}
+
+//#ifdef CONFIG_SYSFS
+#if 0
+/*
+ * There are a numerous options that are configurable on the zx234502
+ * that go well beyond what the power_supply properties provide access to.
+ * Provide sysfs access to them so they can be examined and possibly modified
+ * on the fly.  They will be provided for the charger power_supply object only
+ * and will be prefixed by 'f_' to make them easier to recognize.
+ */
+
+struct zx234502_sysfs_field_info {
+	struct device_attribute	attr;
+	u8	reg;
+	u8	mask;
+	u8	shift;
+};
+
+
+#define ZX234502_SYSFS_FIELD(_name, r, f, m, store)			\
+{									\
+	.attr	= __ATTR(f_##_name, m, zx234502_sysfs_show, store),	\
+	.reg	= ZX234502_REG_##r,					\
+	.mask	= ZX234502_REG_##r##_##f##_MASK,				\
+	.shift	= ZX234502_REG_##r##_##f##_SHIFT,			\
+}
+
+#define ZX234502_SYSFS_FIELD_RW(_name, r, f)				\
+		ZX234502_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO,	\
+				zx234502_sysfs_store)
+
+#define ZX234502_SYSFS_FIELD_RO(_name, r, f)				\
+		ZX234502_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
+
+static ssize_t zx234502_sysfs_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+static ssize_t zx234502_sysfs_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+
+/* On i386 ptrace-abi.h defines SS that breaks the macro calls below. */
+//#undef SS
+
+static struct zx234502_sysfs_field_info zx234502_sysfs_field_tbl[] = {
+			/*	sysfs name	reg	field in reg */
+	ZX234502_SYSFS_FIELD_RW(chg_reset,		MS,	CHGRST),
+	ZX234502_SYSFS_FIELD_RW(pmuon,		MS,	PMUON),
+	ZX234502_SYSFS_FIELD_RW(en_ship,		MS,	ENSHIP),
+	ZX234502_SYSFS_FIELD_RW(en_otg,		MS,	ENOTG),
+	ZX234502_SYSFS_FIELD_RW(chg_config,	MS,	ENCHG),
+	ZX234502_SYSFS_FIELD_RW(en_powerbank,		MS,	PWRBNK),
+	ZX234502_SYSFS_FIELD_RW(insus,		MS,	INSUS),
+	ZX234502_SYSFS_FIELD_RW(in_limit,	ISC,	ISET_DCIN),
+	ZX234502_SYSFS_FIELD_RW(vsys_min,		VSC,	VSYS_MIN),
+	ZX234502_SYSFS_FIELD_RW(ichg,	CCC,	ISETA),
+	ZX234502_SYSFS_FIELD_RW(force_ichg_50pct,		CCC,	ICHG_50PCT),
+	ZX234502_SYSFS_FIELD_RW(iprechg,		CVC,	IPRECHG),
+	ZX234502_SYSFS_FIELD_RW(vbat_full,		CVC,	VBAT),
+	ZX234502_SYSFS_FIELD_RW(vpre_to_fast, 	CVC,	VBATFC),
+	ZX234502_SYSFS_FIELD_RW(en_timer,		CTC,	EN_TIMER),
+	ZX234502_SYSFS_FIELD_RW(en_2timer,		CTC,	EN_2XTIMER),
+	ZX234502_SYSFS_FIELD_RW(stopchg_flag,		OTGC,	OTGV),
+	ZX234502_SYSFS_FIELD_RW(iotg_limit,		OTGC,	OTGI_LIM),
+	ZX234502_SYSFS_FIELD_RW(ents_otg,	OTGC,	ENTS_OTG),
+	ZX234502_SYSFS_FIELD_RO(en_therm,	THR,	EN_THERM),
+	ZX234502_SYSFS_FIELD_RW(therm_threshold,	THR,	THERM_THLD),	
+	ZX234502_SYSFS_FIELD_RW(en_2det, THR,	EN_2DET),
+	ZX234502_SYSFS_FIELD_RW(en_1det, THR,	EN_1DET),
+	ZX234502_SYSFS_FIELD_RW(en_jeita,	THR,	EN_JEITA),
+	ZX234502_SYSFS_FIELD_RW(en_ilimitdj,	THR,	EN_ILIMITDJ),
+	ZX234502_SYSFS_FIELD_RW(tscold,		TS,	COLD),
+	ZX234502_SYSFS_FIELD_RW(tscool,	TS,	COOL),
+	ZX234502_SYSFS_FIELD_RW(tswarm,	TS,	WARM),
+	ZX234502_SYSFS_FIELD_RW(tshot,	TS,	HOT),
+	ZX234502_SYSFS_FIELD_RW(ntcdet,	PTS,NTCDET),
+	ZX234502_SYSFS_FIELD_RW(int_clear, CIIS,	INT),
+	ZX234502_SYSFS_FIELD_RO(ciis_reg,	CIIS,	ALL),
+	ZX234502_SYSFS_FIELD_RW(mask_chgrun,	CIIM,	MASK_CHGRUN),
+	ZX234502_SYSFS_FIELD_RW(mask_inlimit,	CIIM,	MASK_INLIMIT),
+	ZX234502_SYSFS_FIELD_RW(mask_thr,	CIIM,	MASK_THR),
+	ZX234502_SYSFS_FIELD_RW(mask_ts,	CIIM,	MASK_TS),
+	ZX234502_SYSFS_FIELD_RW(mask_dcdet,	CIIM,	MASK_DCDET),
+	ZX234502_SYSFS_FIELD_RO(cbis_reg,	CBIS,	ALL),
+	ZX234502_SYSFS_FIELD_RW(mask_pg,	CBIM,	MASK_DCIN_PG),
+	ZX234502_SYSFS_FIELD_RW(mask_batlow,	CBIM,	MASK_BATLOW),
+	ZX234502_SYSFS_FIELD_RW(mask_nobat,	CBIM,	MASK_NOBAT),
+	ZX234502_SYSFS_FIELD_RW(mask_eoc,	CBIM,	MASK_EOC),
+	ZX234502_SYSFS_FIELD_RW(mask_timer,	CBIM,	MASK_SAFE_TIMER),
+	ZX234502_SYSFS_FIELD_RW(mask_otg_fault,		CBIM,	MASK_OTG_FAULT),
+	ZX234502_SYSFS_FIELD_RO(pis_reg,	PIS,	ALL),
+	ZX234502_SYSFS_FIELD_RW(mask_pwron_it,	PIM,	MASK_POWERON_IT),
+	ZX234502_SYSFS_FIELD_RW(mask_pwron_lp, PIM,	MASK_POWERON_LP),
+	ZX234502_SYSFS_FIELD_RO(cfis_reg,	CFIS,	ALL),			
+	ZX234502_SYSFS_FIELD_RO(version_info,	VER,	INFO),	
+};
+
+static struct attribute *
+	zx234502_sysfs_attrs[ARRAY_SIZE(zx234502_sysfs_field_tbl) + 1];
+
+static const struct attribute_group zx234502_sysfs_attr_group = {
+	.attrs = zx234502_sysfs_attrs,
+};
+
+static void zx234502_sysfs_init_attrs(void)
+{
+	int i, limit = ARRAY_SIZE(zx234502_sysfs_field_tbl);
+
+	for (i = 0; i < limit; i++)
+		zx234502_sysfs_attrs[i] = &zx234502_sysfs_field_tbl[i].attr.attr;
+
+	zx234502_sysfs_attrs[limit] = NULL; /* Has additional entry for this */
+}
+
+static struct zx234502_sysfs_field_info *zx234502_sysfs_field_lookup(
+		const char *name)
+{
+	int i, limit = ARRAY_SIZE(zx234502_sysfs_field_tbl);
+
+	for (i = 0; i < limit; i++)
+		if (!strcmp(name, zx234502_sysfs_field_tbl[i].attr.attr.name))
+			break;
+
+	if (i >= limit)
+		return NULL;
+
+	return &zx234502_sysfs_field_tbl[i];
+}
+
+static ssize_t zx234502_sysfs_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, charger);
+	struct zx234502_sysfs_field_info *info;
+	int ret;
+	u8 v;
+
+	info = zx234502_sysfs_field_lookup(attr->attr.name);
+	if (!info)
+		return -EINVAL;
+
+	ret = zx234502_read_mask(bdi, info->reg, info->mask, info->shift, &v);
+	if (ret)
+		return ret;
+
+	return scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
+}
+
+static ssize_t zx234502_sysfs_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, charger);
+	struct zx234502_sysfs_field_info *info;
+	int ret;
+	u8 v;
+
+	info = zx234502_sysfs_field_lookup(attr->attr.name);
+	if (!info)
+		return -EINVAL;
+
+	ret = kstrtou8(buf, 0, &v);
+	if (ret < 0)
+		return ret;
+
+	ret = zx234502_write_mask(bdi, info->reg, info->mask, info->shift, v);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static int zx234502_sysfs_create_group(struct zx234502_dev_info *bdi)
+{
+	zx234502_sysfs_init_attrs();
+
+	return sysfs_create_group(&bdi->charger.dev->kobj,
+			&zx234502_sysfs_attr_group);
+}
+
+static void zx234502_sysfs_remove_group(struct zx234502_dev_info *bdi)
+{
+	sysfs_remove_group(&bdi->charger.dev->kobj, &zx234502_sysfs_attr_group);
+}
+#else
+static int zx234502_sysfs_create_group(struct zx234502_dev_info *bdi)
+{
+	return 0;
+}
+
+static inline void zx234502_sysfs_remove_group(struct zx234502_dev_info *bdi) {}
+#endif
+
+#if 0
+/*set the Vsys min*/
+static int zx234502_set_vsys_min(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{
+	return zx234502_set_field_val(bdi, ZX234502_REG_VSC,
+			ZX234502_REG_VSC_VSYS_MIN_MASK, ZX234502_REG_VSC_VSYS_MIN_SHIFT,
+			zx234502_cvc_vseta_values,
+			ARRAY_SIZE(zx234502_cvc_vseta_values), val->intval);	
+	//return 0
+}
+#endif
+static int zx234502_register_reset(struct zx234502_dev_info *bdi)
+{
+	int ret, limit = 100;
+	u8 v;
+
+	/* Reset the registers */
+	ret = zx234502_write_mask(bdi, ZX234502_REG_MS,ZX234502_REG_MS_CHGRST_MASK,ZX234502_REG_MS_CHGRST_SHIFT,0x1);
+	if (ret < 0)
+		return ret;
+
+	/* Reset bit will be cleared by hardware so poll until it is */
+	do
+    {
+		ret = zx234502_read_mask(bdi, ZX234502_REG_MS,ZX234502_REG_MS_CHGRST_MASK,ZX234502_REG_MS_CHGRST_SHIFT,&v);
+		if (ret < 0)
+			return ret;
+
+		if (!v)
+			break;
+
+		udelay(10);
+	} while (--limit);
+
+	if (!limit)
+		return -EIO;
+
+	return 0;
+}
+
+
+/* Charger power supply property routines */
+
+static int zx234502_charger_get_charge_type(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	val->intval = bdi->charger.type;
+	return 0;
+}
+
+static int zx234502_charger_get_status(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 cbis_reg=0,ms_reg=0;
+	int status=POWER_SUPPLY_STATUS_UNKNOWN;
+	int ret=0;
+
+	mutex_lock(&bdi->bs_reg_lock);
+
+	if (bdi->battery_status_valid) {
+		cbis_reg = bdi->cbis_curr_reg;
+		bdi->battery_status_valid = false;
+		mutex_unlock(&bdi->bs_reg_lock);
+	} else {
+		mutex_unlock(&bdi->bs_reg_lock);
+
+		ret = zx234502_read(bdi, ZX234502_REG_CBIS, &cbis_reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = zx234502_read(bdi, ZX234502_REG_MS, &ms_reg);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The battery must be discharging when any of these are true:
+	 * - there is no good power source;
+	 * - there is a charge fault.
+	 * Could also be discharging when in "supplement mode" but
+	 * there is no way to tell when its in that mode.
+	 */
+	if (!(cbis_reg & ZX234502_REG_CBIS_DCIN_PG_MASK )||(cbis_reg & ZX234502_REG_CBIS_NOBAT_MASK )) {
+		status = POWER_SUPPLY_STATUS_DISCHARGING;
+	} 
+	else if (ms_reg & ZX234502_REG_MS_ENCHG_MASK){
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+	// disable or full
+	else if(ms_reg & ZX234502_REG_MS_INSUS_MASK)
+	{
+		if (((cbis_reg & ZX234502_REG_CBIS_CHGSTAT_MASK) >> ZX234502_REG_CBIS_CHGSTAT_SHIFT)== 3)
+		{
+			status = POWER_SUPPLY_STATUS_FULL;
+		}
+		else
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;		
+	}
+	else {
+		cbis_reg &= ZX234502_REG_CBIS_CHGSTAT_MASK;
+		cbis_reg >>= ZX234502_REG_CBIS_CHGSTAT_SHIFT;
+
+		switch (cbis_reg) {
+		case 0x0: /* Charging */	
+		case 0x2: /* ReCharging frome THERM */
+			status = POWER_SUPPLY_STATUS_CHARGING;
+			break;
+		case 0x3: /* Charge Termination Done */
+			status = POWER_SUPPLY_STATUS_FULL;
+			break;
+		default:
+			ret = -EIO;
+		}
+	}
+
+	if (!ret)
+		val->intval = status;
+
+	return ret;
+}
+
+static int zx234502_charger_get_health(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 ciis_reg=0, cbis_reg=0, cfis_reg=0;
+	int health=0, ret=0;
+
+	mutex_lock(&bdi->bs_reg_lock);
+
+	if (bdi->charger_health_valid) {
+		bdi->charger_health_valid = false;
+		cbis_reg = bdi->cbis_curr_reg;
+		ciis_reg = bdi->ciis_curr_reg;
+		cfis_reg = bdi->cfis_curr_reg;
+		mutex_unlock(&bdi->bs_reg_lock);
+	} else {
+		mutex_unlock(&bdi->bs_reg_lock);
+
+		ret = zx234502_read(bdi, ZX234502_REG_CIIS, &ciis_reg);
+		if (ret < 0)
+			return ret;
+		ret = zx234502_read(bdi, ZX234502_REG_CBIS, &cbis_reg);
+		if (ret < 0)
+			return ret;
+		ret = zx234502_read(bdi, ZX234502_REG_CFIS, &cfis_reg);
+		if (ret < 0)
+			return ret;
+
+		printk(KERN_INFO "zx234502_charger_get_health REG_0xa=0x%x,REG_0xc=0x%x,REG_0x10=0x%x.\n",ciis_reg,cbis_reg,cfis_reg);	
+
+	}
+
+	if (cbis_reg & ZX234502_REG_CBIS_OTG_FAULT_MASK) {
+		/*
+		 * This could be over-current or over-voltage but there's
+		 * no way to tell which.  Return 'OVERVOLTAGE' since there
+		 * isn't an 'OVERCURRENT' value defined that we can return
+		 * even if it was over-current.
+		 */
+		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+	} 
+	else if(cbis_reg & ZX234502_REG_CBIS_SAFE_TIMER_MASK) {	
+		health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
+	}
+	else if(cbis_reg & ZX234502_REG_CBIS_DCIN_PG_MASK) {	
+		health = POWER_SUPPLY_HEALTH_GOOD;
+	}
+	else if(ciis_reg & (ZX234502_REG_CIIS_INLIMIT_MASK|ZX234502_REG_CIIS_THERM_MASK)) {	
+		health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+	}
+	else if(cfis_reg & ZX234502_REG_CFIS_THSD_MASK){
+		health = POWER_SUPPLY_HEALTH_OVERHEAT;	/*the chip hot error*/
+	}
+	else{	
+		health = POWER_SUPPLY_HEALTH_UNKNOWN;
+    }
+	
+	val->intval = health;
+
+	return 0;
+}
+
+int zx234502_charger_get_online(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 v;
+	int ret;
+
+	ret = zx234502_read_mask(bdi, ZX234502_REG_CBIS,ZX234502_REG_CBIS_DCIN_PG_MASK,
+							ZX234502_REG_CBIS_DCIN_PG_SHIFT, &v);
+	if (ret < 0)
+		return ret;
+
+	val->intval = v;
+	return 0;
+}EXPORT_SYMBOL (zx234502_charger_get_online);
+#if 0
+static int zx234502_charger_get_current(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	int curr, ret;
+
+	ret = zx234502_get_field_val(bdi, ZX234502_REG_ISC,
+			ZX234502_REG_ISC_ISET_DCIN_MASK, ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+			zx234502_in_ilimit_values,
+			ARRAY_SIZE(zx234502_in_ilimit_values), &curr);
+	if (ret < 0)
+		return ret;
+
+	val->intval = curr;
+	return 0;
+}
+
+static int zx234502_charger_get_current_max(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	int idx = ARRAY_SIZE(zx234502_in_ilimit_values) - 1;
+
+	val->intval = zx234502_in_ilimit_values[idx];
+	return 0;
+}
+
+static int zx234502_charger_get_voltage(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+#if 0
+	int voltage, ret;
+	ret = zx234502_get_field_val(bdi, ZX234502_REG_CVC,
+			ZX234502_REG_CVC_VBAT_MASK, ZX234502_REG_CVC_VBAT_SHIFT,
+			zx234502_cvc_vseta_values,
+			ARRAY_SIZE(zx234502_cvc_vseta_values), &voltage);
+	if (ret < 0)
+		return ret;
+
+	val->intval = voltage;
+#endif
+return 0;
+}
+#endif
+
+static int zx234502_charger_get_charger_enabled(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 charger_enabled;
+	int ret;
+
+	ret = zx234502_read_mask(bdi, ZX234502_REG_MS,
+			ZX234502_REG_MS_INSUS_MASK,
+			ZX234502_REG_MS_INSUS_SHIFT, &charger_enabled);
+	if (ret < 0)
+		return ret;
+
+	val->intval = !charger_enabled;
+	return 0;
+}
+static int zx234502_charger_get_voltage_max(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	int voltage, ret;
+
+	ret = zx234502_get_field_val(bdi, ZX234502_REG_CVC,
+			ZX234502_REG_CVC_VBAT_MASK, ZX234502_REG_CVC_VBAT_SHIFT,
+			zx234502_cvc_vseta_values,
+			ARRAY_SIZE(zx234502_cvc_vseta_values), &voltage);
+	if (ret < 0)
+		return ret;
+
+	val->intval = voltage;
+	return 0;
+
+}
+#if 0
+static int zx234502_charger_set_current(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	return zx234502_set_field_val(bdi, ZX234502_REG_ISC,
+			ZX234502_REG_ISC_ISET_DCIN_MASK, ZX234502_REG_ISC_ISET_DCIN_MASK,
+			zx234502_in_ilimit_values,
+			ARRAY_SIZE(zx234502_in_ilimit_values), val->intval);
+	
+}
+#endif
+static int zx234502_charger_set_voltage(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{
+	return zx234502_set_field_val(bdi, ZX234502_REG_CVC,
+			ZX234502_REG_CVC_VBAT_MASK, ZX234502_REG_CVC_VBAT_SHIFT,
+			zx234502_cvc_vseta_values,
+			ARRAY_SIZE(zx234502_cvc_vseta_values), val->intval);
+}
+
+static int zx234502_charger_set_charger_config(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{
+	int ret;
+	union power_supply_propval   enable_charge;
+	
+	if (val->intval){
+		enable_charge.intval = 0 ;
+		stopchg_flag = 1;
+		ret = zx234502_write_mask(bdi, ZX234502_REG_OTGC,
+			ZX234502_REG_OTGC_OTGV_MASK,
+			ZX234502_REG_OTGC_OTGV_SHIFT,1);  
+		printk("mmi start chg\n");
+	}
+	else{
+		stopchg_flag = 2;
+		enable_charge.intval = 1 ;	
+		ret = zx234502_write_mask(bdi, ZX234502_REG_OTGC,
+			ZX234502_REG_OTGC_OTGV_MASK,
+			ZX234502_REG_OTGC_OTGV_SHIFT,2);  
+		printk("mmi stop chg\n");
+	}
+
+	 ret = zx234502_write_mask(bdi, ZX234502_REG_MS,
+			ZX234502_REG_MS_INSUS_MASK,
+			ZX234502_REG_MS_INSUS_SHIFT, enable_charge.intval );  /*0:disable 1:enable*/
+	 
+	 return ret;
+}
+
+
+static int zx234502_charger_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi = container_of(psy, struct zx234502_dev_info, charger);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PC1_AC2:
+		ret = zx234502_charger_get_charge_type(bdi, val);
+		break;
+	
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = zx234502_charger_get_status(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = zx234502_charger_get_health(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = zx234502_charger_get_online(bdi, val);
+		break;
+
+	/*
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = zx234502_charger_get_current(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		ret = zx234502_charger_get_current_max(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = zx234502_charger_get_voltage(bdi, val);
+		break;
+*/
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		ret = zx234502_charger_get_voltage_max(bdi, val);
+		break;
+		
+	case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+		ret = zx234502_charger_get_charger_enabled(bdi, val);
+		break;
+	default:
+		ret = -ENODATA;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_charger_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, charger);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+#if 0
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = zx234502_charger_set_current(bdi, val);
+		break;
+#endif
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		ret = zx234502_charger_set_voltage(bdi, val);
+		break;
+
+    case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+        ret = zx234502_charger_set_charger_config(bdi, val);			
+		power_supply_changed(&bdi->charger);
+        break;
+	default:
+		ret = -EINVAL;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_charger_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	switch (psp)
+    {
+    	//case POWER_SUPPLY_PROP_CURRENT_NOW:
+    	case POWER_SUPPLY_PROP_VOLTAGE_MAX:		
+		case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+    		ret = 1;
+    		break;
+	    default:
+		    ret = 0;
+			break;
+	}
+
+	return ret;
+}
+
+static enum power_supply_property zx234502_charger_properties[] = {
+	POWER_SUPPLY_PROP_PC1_AC2,
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_ONLINE,
+	//POWER_SUPPLY_PROP_CURRENT_NOW,
+	//POWER_SUPPLY_PROP_CURRENT_MAX,
+	//POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_CHARGE_ENABLED,
+};
+
+static char *zx234502_charger_supplied_to[] = {
+	"main-battery",
+};
+
+static void zx234502_charger_init(struct power_supply *charger)
+{
+	charger->name = "charger";
+	charger->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	charger->properties = zx234502_charger_properties;
+	charger->num_properties = ARRAY_SIZE(zx234502_charger_properties);
+	charger->supplied_to = zx234502_charger_supplied_to;
+	//charger->num_supplies = ARRAY_SIZE(zx234502_charger_supplied_to);
+	charger->get_property = zx234502_charger_get_property;
+	charger->set_property = zx234502_charger_set_property;
+	charger->property_is_writeable = zx234502_charger_property_is_writeable;
+}
+
+/* Battery power supply property routines */
+
+static int zx234502_battery_get_health(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 v;
+	int health, ret;
+
+	mutex_lock(&bdi->bs_reg_lock);
+	
+	if(true!=bdi->pdata->ts_flag){
+		val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+		mutex_unlock(&bdi->bs_reg_lock);
+		return 0;
+	}
+
+	if (bdi->battery_health_valid) {
+		v = bdi->ciis_curr_reg;
+		bdi->battery_health_valid = false;
+	} else {
+
+		ret = zx234502_read(bdi, ZX234502_REG_CIIS, &v);
+		if (ret < 0){	
+
+			mutex_unlock(&bdi->bs_reg_lock);
+			return ret;
+		}
+	}
+
+	if (v & ZX234502_REG_CIIS_THERM_MASK) {
+		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+	} else {
+		v &= ZX234502_REG_CIIS_TS_METER_MASK;
+		v >>= ZX234502_REG_CIIS_TS_METER_SHIFT;
+
+		switch (v) {
+		case ZX234502_REG_CISS_TS_NORMAL: /* Normal */
+			health = POWER_SUPPLY_HEALTH_GOOD;
+			break;
+		case ZX234502_REG_CISS_TS_WARM: /*warm*/		
+			health = POWER_SUPPLY_HEALTH_WARM;
+			break;
+		case ZX234502_REG_CISS_TS_HOT: /* TS1 Hot */		
+			health = POWER_SUPPLY_HEALTH_OVERHEAT;
+			break;
+		case ZX234502_REG_CISS_TS_COOL:/*Cool*/
+			health = POWER_SUPPLY_HEALTH_COOL;
+			break;			
+		case ZX234502_REG_CISS_TS_COLD: /* TS1 Cold */
+			health = POWER_SUPPLY_HEALTH_COLD;
+			break;
+		default:
+			health = POWER_SUPPLY_HEALTH_UNKNOWN;
+		}
+	}
+
+	val->intval = health;
+	mutex_unlock(&bdi->bs_reg_lock);
+	return 0;
+}
+
+static int zx234502_battery_get_online(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 batfet_disable;
+	int ret;
+
+	ret = zx234502_read_mask(bdi, ZX234502_REG_CBIS,
+			ZX234502_REG_CBIS_NOBAT_MASK,
+			ZX234502_REG_CBIS_NOBAT_SHIFT, &batfet_disable);
+	if (ret < 0)
+		return ret;
+
+	val->intval = !batfet_disable;
+	return 0;
+}
+#if 0
+static int zx234502_battery_get_capacity(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	int ret;
+    uint volt;
+	int bat_levl = 0;
+	int i =0;
+	//union power_supply_propval * online;
+	struct zx234502_bat_calibration *calibration;
+
+	//zx234502_charger_get_online(bdi,online);
+
+	u8 v;
+	ret = zx234502_read_mask(bdi, ZX234502_REG_CBIS,ZX234502_REG_CBIS_DCIN_PG_MASK,
+							ZX234502_REG_CBIS_DCIN_PG_SHIFT, &v);
+	if(v)
+		calibration = bdi->pdata->charging;
+	else
+		calibration = bdi->pdata->discharging;		
+//#ifdef CONFIG_ZX234290_ADC						
+	volt = get_battery_voltage();
+//#endif
+	if (volt > calibration[0].voltage) {
+		bat_levl = calibration[0].level;
+	} else {
+		for (i = 0; calibration[i+1].voltage >= 0; i++) {
+			if (volt <= calibration[i].voltage &&
+					volt >= calibration[i+1].voltage) {
+				/* interval found - interpolate within range */
+				bat_levl = calibration[i].level -
+					((calibration[i].voltage - volt) *
+					(calibration[i].level -
+					calibration[i+1].level)) /
+					(calibration[i].voltage -
+					calibration[i+1].voltage);
+				break;
+			}
+		}
+	}
+	
+	val->intval = bat_levl;
+	//return 0;
+	
+	return ret;
+}
+#endif
+
+static int zx234502_battery_set_online(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{
+	return zx234502_write_mask(bdi, ZX234502_REG_MS,
+			ZX234502_REG_MS_ENSHIP_MASK,
+			ZX234502_REG_MS_ENSHIP_SHIFT, !val->intval); /*1:enable 0:disable*/
+}
+
+
+static int zx234502_battery_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, battery);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+		
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = zx234502_battery_get_health(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = zx234502_battery_get_online(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_TEMP:					
+		val->intval = get_adc2_voltage();
+		ret = 0;			
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		//#ifdef CONFIG_ZX234290_ADC						
+		val->intval = get_adc1_voltage() - 15;
+		ret = 0;
+		break;
+#if 0
+	case POWER_SUPPLY_PROP_CAPACITY:
+		ret = zx234502_battery_get_capacity(bdi, val);
+		break;
+#endif
+	default:
+		ret = -ENODATA;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_battery_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, battery);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_put_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = zx234502_battery_set_online(bdi, val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_battery_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static enum power_supply_property zx234502_battery_properties[] = {
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	//POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static void zx234502_battery_init(struct power_supply *battery)
+{
+	battery->name = "battery";
+	battery->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	battery->properties = zx234502_battery_properties;
+	battery->num_properties = ARRAY_SIZE(zx234502_battery_properties);
+	battery->get_property = zx234502_battery_get_property;
+	battery->set_property = zx234502_battery_set_property;
+	battery->property_is_writeable = zx234502_battery_property_is_writeable;
+}
+
+
+static int zx234502_boost_get_online(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{	
+
+	val->intval  = bdi->boost_online_flag;
+	return 0;
+}
+
+
+static int zx234502_boost_get_current_now(struct zx234502_dev_info *bdi,union power_supply_propval *val)
+{
+	//gpio_set1 is GPIO39
+	//gpio_set2 is GPIO40
+	//gpio_set3 is GPIO41
+	int gpio_set1,gpio_set2,gpio_set3;
+
+	gpio_set1 = gpio_get_value(bdi->pdata->boost_cur_gpio1);	
+	gpio_set2 = gpio_get_value(bdi->pdata->boost_cur_gpio2);
+	gpio_set3 = gpio_get_value(bdi->pdata->boost_cur_gpio3);	
+
+	if((GPIO_LOW==gpio_set1)&(GPIO_LOW==gpio_set2)&(GPIO_HIGH==gpio_set3)){
+		val->intval = 600;
+	}
+	else if((GPIO_LOW==gpio_set1)&(GPIO_HIGH==gpio_set2)&(GPIO_LOW==gpio_set3)){
+		val->intval = 1000;		
+	}
+	else if((GPIO_LOW==gpio_set1)&(GPIO_HIGH==gpio_set2)&(GPIO_HIGH==gpio_set3)){
+		val->intval = 1750;				
+	}
+	else if((GPIO_HIGH==gpio_set1)&(GPIO_LOW==gpio_set2)&(GPIO_LOW==gpio_set3)){
+		val->intval = 2000;
+	}
+	else if((GPIO_HIGH==gpio_set1)&(GPIO_LOW==gpio_set2)&(GPIO_HIGH==gpio_set3)){
+		val->intval = 2850;		
+	}
+	else{
+		
+		dev_dbg(bdi->dev, "The boost current set with err\n");
+		return -1;
+	}
+	
+	return 0;
+}
+
+#if 0
+static int zx234502_boost_get_current_max(struct zx234502_dev_info *bdi, union power_supply_propval *val)
+{
+	val->intval = 2850;		
+    return 0;
+}
+#endif
+static int zx234502_boost_set_charge_enable(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{	
+	zx234502_write_mask(bdi,ZX234502_REG_MS,
+	ZX234502_REG_MS_PWRBNK_MASK,ZX234502_REG_MS_PWRBNK_SHIFT,val->intval);
+
+	/*set the gpio34 open = HIGH*/   
+	gpio_set_value(bdi->pdata->boost_loadswitch_gpio,val->intval); 
+	//zx29_gpio_output_data(bdi->pdata->boost_loadswitch_gpio,GPIO_HIGH);
+  	
+   return 0;
+}
+
+static int zx234502_boost_set_current_now(struct zx234502_dev_info *bdi,const union power_supply_propval *val)
+{
+    //gpio from 35/36/37   changed to 39/40/41
+	//gpio_set1 is GPIO39
+	//gpio_set2 is GPIO40
+	//gpio_set3 is GPIO41
+	int gpio_set1,gpio_set2,gpio_set3;
+	
+	if(val->intval < 601){		
+		/*0.6A GPIO35:LOW  GPIO36:LOW  GPIO37:HIGH 40k */
+		gpio_set1 = GPIO_LOW;	
+		gpio_set2 = GPIO_LOW;	
+		gpio_set3 = GPIO_HIGH;
+	}
+	else if( (600 < val->intval)&&(val->intval< 1001)){	
+		/*1A  GPIO35:LOW  GPIO36:HIGH  GPIO37:LOW 20k */
+		gpio_set1 = GPIO_LOW;	
+		gpio_set2 = GPIO_HIGH;	
+		gpio_set3 = GPIO_LOW;			
+	}
+	else if( (1000 < val->intval)&&(val->intval < 1751)){
+		/*1.75A GPIO35:LOW  GPIO36:HIGH  GPIO37:HIGH  13.3k*/
+		gpio_set1 = GPIO_LOW;	
+		gpio_set2 = GPIO_HIGH;	
+		gpio_set3 = GPIO_HIGH;	
+	}
+	else if(( 1750 < val->intval) &&( val->intval < 2001)){
+		/*2A  GPIO35:HIGH  GPIO36:LOW  GPIO37:LOW 10k */
+		gpio_set1 = GPIO_HIGH;	
+		gpio_set2 = GPIO_LOW;	
+		gpio_set3 = GPIO_LOW;	
+	}
+	else{
+		/*2.85A GPIO35:HIGH  GPIO36:LOW  GPIO37:HIGH 8k*/
+		gpio_set1 = GPIO_HIGH;	
+		gpio_set2 = GPIO_LOW;	
+		gpio_set3 = GPIO_HIGH;
+	}
+	
+	gpio_set_value(bdi->pdata->boost_cur_gpio1, gpio_set1);	
+	gpio_set_value(bdi->pdata->boost_cur_gpio2, gpio_set2);
+	gpio_set_value(bdi->pdata->boost_cur_gpio3, gpio_set3);	
+	return  0;
+}
+
+static int zx234502_boost_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, boost);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = zx234502_boost_get_online(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = zx234502_boost_get_current_now(bdi, val);
+        break;
+	#if 0
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		ret = zx234502_boost_get_current_max(bdi, val);
+        break;
+	#endif
+	default:
+		ret = -ENODATA;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_boost_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const  union power_supply_propval *val)
+{
+	struct zx234502_dev_info *bdi =
+			container_of(psy, struct zx234502_dev_info, boost);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_put_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+		ret = zx234502_boost_set_charge_enable(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = zx234502_boost_set_current_now(bdi, val);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int zx234502_boost_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static enum power_supply_property zx234502_boost_properties[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	//WER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_BOOST_ENABLE,
+};
+
+static void zx234502_boost_init(struct power_supply *boost)
+{
+	#ifdef  DBG_CHARGE
+	//printk(KERN_INFO "zx234502_boost_init =%x.\n",boost);
+	#endif
+	boost->name = "boost";
+	boost->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	boost->properties = zx234502_boost_properties;
+	boost->num_properties = ARRAY_SIZE(zx234502_boost_properties);
+	boost->get_property = zx234502_boost_get_property;
+	boost->set_property = zx234502_boost_set_property;
+	boost->property_is_writeable = zx234502_boost_property_is_writeable;
+}
+
+
+static int zx234502_charger_gpio_config(struct device *dev,int pin,gpio_func_id func_sel,char *name)
+{
+	int ret = -1;
+	
+	if (gpio_is_valid(pin)){
+		ret = gpio_request(pin, name);
+		if (ret){
+			dev_err(dev, "cannot get [%s] gpio\n",name);
+			return -1;
+		}
+		ret = zx29_gpio_config(pin,func_sel);	
+		if(ret){
+			dev_err(dev, "cannot config [%s] gpio\n",name);
+			gpio_free(pin);
+			return -1;
+		}
+	}
+	
+	return 0;
+}
+
+#if 0
+//zx234500_charger_gpio_config_input
+static void zx234502_charger_gpio_config_input(struct device *dev,int gpio,gpio_func_id func_sel,char *str)	
+{
+	if(zx234502_charger_gpio_config(dev,gpio,func_sel,str)!=0)
+		return;	
+	zx29_gpio_set_direction(gpio,GPIO_IN);
+	zx29_gpio_input_data(gpio);
+}
+#endif
+
+//zx234500_charger_gpio_config_output
+static int  zx234502_charger_gpio_config_output(struct device *dev,int gpio,gpio_func_id func_sel,char *str,int value2)	
+{
+	if(zx234502_charger_gpio_config(dev,gpio,func_sel,str)!=0)
+		return -1;
+	zx29_gpio_set_direction(gpio,GPIO_OUT);
+	zx29_gpio_output_data(gpio,value2);
+
+	return 0;
+}
+
+static int zx234502_boost_gpio_init(struct device *dev, struct zx234502_platform_data *pdata)
+{
+	int ret = -1;
+
+	ret = zx234502_charger_gpio_config_output(dev,pdata->boost_loadswitch_gpio,pdata->boost_loadswitch_fun_sel,"LoadSwitch",GPIO_LOW);
+	/*set the out put current 1A*/
+	ret += zx234502_charger_gpio_config_output(dev,pdata->boost_cur_gpio1,pdata->boost_gpio1_fun_sel,"Iset1",GPIO_LOW);
+	ret += zx234502_charger_gpio_config_output(dev,pdata->boost_cur_gpio2,pdata->boost_gpio2_fun_sel,"Iset2",GPIO_HIGH);
+	ret += zx234502_charger_gpio_config_output(dev,pdata->boost_cur_gpio3,pdata->boost_gpio3_fun_sel,"Iset3",GPIO_LOW);
+
+	return ret;	
+}
+
+static void zx234502_boost_gpio_uninit(struct zx234502_platform_data *pdata)
+{    
+	gpio_free(pdata->boost_loadswitch_gpio);
+	gpio_free(pdata->boost_cur_gpio1);
+	gpio_free(pdata->boost_cur_gpio2);
+	gpio_free(pdata->boost_cur_gpio3);
+}
+
+/*
+		when BAT goes under BAEdet(3.4V) or CHGRST set 1
+		Group B(A1,A2,A3,A4,A5,A7) registers will reset
+		call this function in init or dcin
+*/
+static int zx234502_charger_config_groupB_Regs(struct zx234502_dev_info *bdi)
+{
+	int ret;
+
+	/*set VINDPM to 4.52V*/
+	ret = zx234502_write_mask(bdi,ZX234502_REG_ISC,
+				   ZX234502_REG_ISC_VINDPM_MASK,
+				   ZX234502_REG_ISC_VINDPM_SHIFT,
+				   0x8);
+	/*set VSETA to 4.2V*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CVC,
+				   ZX234502_REG_CVC_VBAT_MASK,
+				   ZX234502_REG_CVC_VBAT_SHIFT,
+				   0x2);
+
+	/*disable the timer*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CTC,
+				   ZX234502_REG_CTC_EN_TIMER_MASK,
+				   ZX234502_REG_CTC_EN_TIMER_SHIFT,
+				   0x0);
+	/*disable the 2*timer*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CTC,
+				   ZX234502_REG_CTC_EN_2XTIMER_MASK,
+				   ZX234502_REG_CTC_EN_2XTIMER_SHIFT,
+				   0x0);
+	/*set CVCOMP to 20mV*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CTC,
+				   ZX234502_REG_CTC_CVCOMP_MASK,
+				   ZX234502_REG_CTC_CVCOMP_SHIFT,
+				   0x4);
+
+
+	/*disable the JETTA*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_THR,
+					ZX234502_REG_THR_EN_JEITA_MASK,
+					ZX234502_REG_THR_EN_JEITA_SHIFT,
+					0x0);
+
+	/*set the temprator   cool */
+	/*00:0	01:5  10:10  11:15*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_TS,
+					ZX234502_REG_TS_COOL_MASK,
+					ZX234502_REG_TS_COOL_SHIFT,
+					0x0);
+
+	if (ret < 0){
+		goto out;
+	}
+
+	return 0;
+
+	out:
+		//pm_runtime_put_sync(bdi->dev);
+		dev_err(bdi->dev, "zx234502_charger_groupB_config ERROR: %d\n", ret);
+		return ret;
+
+}
+
+static int zx234502_hw_init(struct zx234502_dev_info *bdi)
+{
+	u8 v;
+	int ret;
+
+	union power_supply_propval voltage_val = {0};
+
+#ifdef DBG_CHARGE
+	//set pshold1 1,just for test
+	//gpio_request(ZX29_GPIO_51, "pshold1");
+	//zx29_gpio_config(ZX29_GPIO_51, GPIO51_GPIO51);
+	//zx29_gpio_set_direction(ZX29_GPIO_51, GPIO_OUT);
+	//zx29_gpio_output_data(ZX29_GPIO_51, 1);
+#endif 
+	//pm_runtime_get_sync(bdi->dev);
+
+	/* First check that the device really is what its supposed to be */
+	ret = zx234502_read_mask(bdi, ZX234502_REG_VER,
+			ZX234502_REG_VER_INFO_MASK,
+			ZX234502_REG_VER_INFO_SHIFT,
+			&v);
+	
+	if (ret < 0){
+	    	goto out;
+	}
+	//printk(KERN_INFO "zx234502_hw_init:zx234502-charger version reg: 0x%x\n", v);
+	/*
+	if (v != bdi->model) {
+		ret = -ENODEV;
+		goto out;
+	}
+	*/
+	voltage_val.intval = 4350;
+	ret = zx234502_charger_set_voltage(bdi,&voltage_val);
+	if (ret < 0){
+		goto out;
+	}
+
+	/*disable the timer*/
+	ret = zx234502_write_mask(bdi,ZX234502_REG_CTC,
+		ZX234502_REG_CTC_EN_TIMER_MASK,
+		ZX234502_REG_CTC_EN_TIMER_SHIFT,
+		0x0);
+	if (ret < 0){
+		goto out;
+	}
+	/*disable the 2*timer*/
+	ret = zx234502_write_mask(bdi,ZX234502_REG_CTC,
+		ZX234502_REG_CTC_EN_2XTIMER_MASK,
+		ZX234502_REG_CTC_EN_2XTIMER_SHIFT,
+		0x0);
+
+	if (ret < 0){
+		goto out;
+	}
+
+	 //enable PMUON
+	 //ret = zx234502_write_mask(bdi,ZX234502_REG_MS,
+	//				 ZX234502_REG_MS_PMUON_MASK,
+	//				 ZX234502_REG_MS_PMUON_SHIFT,
+	//				 0x1);
+	 //config NTCDET 
+	 // 				 0:enable auto ntc detection
+	 // 				 1:disable auto ntc detection
+	 ret += zx234502_write_mask(bdi,ZX234502_REG_PTS,
+					 ZX234502_REG_PTS_NTCDET_MASK,
+					 ZX234502_REG_PTS_NTCDET_SHIFT,
+					 0x1);
+	 //when NTCDET is 1 ,TSSEL is to select R
+	 // 				 0:10k
+	 // 				 1:100k
+	 //ret += zx234502_write_mask(bdi,ZX234502_REG_PTS,
+	//				 ZX234502_REG_PTS_TSSEL_MASK,
+	//				 ZX234502_REG_PTS_TSSEL_SHIFT,
+	//				 0x0);
+
+	/*disable the charger detect*/
+	ret += zx234502_write_mask(bdi,ZX234502_REG_THR,
+					ZX234502_REG_THR_EN_2DET_MASK,
+					ZX234502_REG_THR_EN_2DET_SHIFT,
+					0x0);
+	ret += zx234502_write_mask(bdi,ZX234502_REG_THR,
+					ZX234502_REG_THR_EN_1DET_MASK,
+					ZX234502_REG_THR_EN_1DET_SHIFT,
+					0x0);
+	//enable charger
+	ret += zx234502_write_mask(bdi,ZX234502_REG_MS,
+					ZX234502_REG_MS_ENCHG_MASK,
+					ZX234502_REG_MS_ENCHG_SHIFT,
+					0x0);
+	ret += zx234502_write_mask(bdi,ZX234502_REG_MS,
+					ZX234502_REG_MS_INSUS_MASK,
+					ZX234502_REG_MS_INSUS_SHIFT,
+					0x0);				
+	//mask /SAFE it
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CBIM,ZX234502_REG_CBIM_MASK_SAFE_TIMER_MASK,
+							   ZX234502_REG_CBIM_MASK_SAFE_TIMER_SHIFT,0x1);
+	 //mask CHGRUN it
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CIIM,ZX234502_REG_CIIM_MASK_CHGRUN_MASK,
+							  ZX234502_REG_CIIM_MASK_CHGRUN_SHIFT,0x1);
+	 //mask INLIMIT it
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CIIM,ZX234502_REG_CIIM_MASK_INLIMIT_MASK,
+							  ZX234502_REG_CIIM_MASK_INLIMIT_SHIFT,0x1);
+	 //mask DCDET it
+	ret += zx234502_write_mask(bdi,ZX234502_REG_CIIM,ZX234502_REG_CIIM_MASK_DCDET_MASK,
+							   ZX234502_REG_CIIM_MASK_DCDET_SHIFT,0x1);
+	if (ret < 0){
+		goto out;
+	}
+
+    //set ts_meter interrupt mask
+	if(true !=bdi->pdata->ts_flag){
+		zx234502_write_mask(bdi,ZX234502_REG_CIIM,ZX234502_REG_CIIM_MASK_TS_MASK,
+	 	                     ZX234502_REG_CIIM_MASK_TS_SHIFT,0x1);
+	}
+
+    return 0;
+
+out:
+	//pm_runtime_put_sync(bdi->dev);
+	dev_err(bdi->dev, "zx234502_hw_init err: %d\n", ret);
+	return ret;
+}
+
+
+static irqreturn_t zx234502_charger_irq_primary_handler(int irq, struct zx234502_dev_info *bdi)
+{
+	disable_irq_nosync(irq);
+	//pcu_int_clear(irq);
+	pcu_clr_irq_pending(irq);
+	
+	up(&bdi->chgirq_sem);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t zx234502_irq_handler_thread(void *data)
+{
+	struct zx234502_dev_info *bdi = data;
+	bool charger_changed_flag = false;
+	bool battery_changed_flag = false;
+	bool boost_changed_flag = false;
+	int ret;
+	u8 ms;
+	struct sched_param param = { .sched_priority = 2 };
+	param.sched_priority= 31;
+	sched_setscheduler(current, SCHED_FIFO, &param);
+
+	while(1)
+	{
+		down(&bdi->chgirq_sem);
+		//pm_runtime_get_sync(bdi->dev);
+		mutex_lock(&bdi->bs_reg_lock);
+		bdi->cbis_pre_reg=bdi->cbis_curr_reg;
+		bdi->pis_pre_reg=bdi->pis_curr_reg;
+		bdi->ciis_pre_reg=bdi->ciis_curr_reg;
+		bdi->cfis_pre_reg = bdi->cfis_curr_reg;
+		
+		//printk(KERN_INFO"zx234502_irq_handler_thread\n");
+		
+		
+		ret = zx234502_read(bdi, ZX234502_REG_MS, &ms);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read MS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+		//printk("zx234502 MS reg is %d",ms);
+		
+		ret = zx234502_read(bdi, ZX234502_REG_CBIS, &bdi->cbis_curr_reg);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read CBIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		
+		ret = zx234502_read(bdi, ZX234502_REG_PIS, &bdi->pis_curr_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read PIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		ret = zx234502_read(bdi, ZX234502_REG_CIIS, &bdi->ciis_curr_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read CIIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+		printk("cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n", 
+		                  bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
+		/*clear the A10 int*/
+		ret = zx234502_write_mask(bdi, ZX234502_REG_CIIS,ZX234502_REG_CIIS_INT_MASK,ZX234502_REG_CIIS_INT_SHIFT,0);
+		
+		if (ret < 0) {
+			printk(KERN_INFO"chg clear int failed 1\n");
+			ret = zx234502_write_mask(bdi, ZX234502_REG_CIIS,ZX234502_REG_CIIS_INT_MASK,ZX234502_REG_CIIS_INT_SHIFT,0);
+			if (ret < 0) {
+				printk(KERN_INFO"chg clear int failed 2\n");
+				ret = zx234502_write_mask(bdi, ZX234502_REG_CIIS,ZX234502_REG_CIIS_INT_MASK,ZX234502_REG_CIIS_INT_SHIFT,0);
+				if (ret < 0) {	
+					printk(KERN_INFO"chg clear int failed 3\n");
+				}
+				else{
+					printk(KERN_INFO"chg clear int failed ok 3\n");
+					//panic(0);
+				}		
+			}
+			else{
+				printk(KERN_INFO"chg clear int failed ok 2\n");
+			}
+		}
+			
+		if(bdi->cbis_curr_reg != bdi->cbis_pre_reg){
+			if ((bdi->cbis_curr_reg & ZX234502_REG_CBIS_DCIN_PG_MASK) != (bdi->cbis_pre_reg & ZX234502_REG_CBIS_DCIN_PG_MASK)) {
+				if(bdi->cbis_curr_reg & ZX234502_REG_CBIS_DCIN_PG_MASK){			
+					//zx234502_hw_init(bdi);
+					printk(KERN_INFO"chg usb in\n");
+					dwc_otg_chg_inform(0);/*usb in*/
+
+					ret = zx234502_charger_config_groupB_Regs(bdi);
+					if(ret)
+					{
+						printk(KERN_INFO"chg config groupB Regs failed\n");
+					}
+					// ret = zx234502_write_mask(bdi,ZX234502_REG_MS,ZX234502_REG_MS_PMUON_MASK,ZX234502_REG_MS_PMUON_SHIFT,0x1);
+				}
+				else{
+					printk(KERN_INFO"chg usb out\n");
+					dwc_otg_chg_inform(1);/*usb out*/
+					bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+					// ret = zx234502_write_mask(bdi,ZX234502_REG_MS,ZX234502_REG_MS_PMUON_MASK,ZX234502_REG_MS_PMUON_SHIFT,0x0);
+				}
+			}
+			charger_changed_flag = true;
+		}
+
+		if(true == bdi->pdata->boost_flag){
+			if (bdi->pis_curr_reg != bdi->pis_pre_reg) {	
+				if(bdi->pis_curr_reg & ZX234502_REG_PIS_POWERON_IT_MASK){			
+					queue_delayed_work(g_bdi->boostQueue,&bdi->boostWorkStruct,2000);	
+				}		
+				boost_changed_flag = true;
+				bdi->boost_online_flag = 1;
+			}
+		}
+		
+		if (bdi->ciis_curr_reg != bdi->ciis_pre_reg) {	
+			if(true == bdi->pdata->ts_flag){		
+				if((bdi->ciis_curr_reg & ZX234502_REG_CIIS_TS_METER_MASK) != (bdi->ciis_pre_reg & ZX234502_REG_CIIS_TS_METER_MASK)){
+#ifdef DBG_CHARGE
+					switch((bdi->ciis_curr_reg&ZX234502_REG_CIIS_TS_METER_MASK )>>ZX234502_REG_CIIS_TS_METER_SHIFT){		
+					case 0:
+#ifdef DBG_CHARGE
+						printk(KERN_INFO"chg bat temp nomrmal\n");
+#endif
+						break;
+					case ZX234502_REG_CISS_TS_WARM:/*warm*/	
+					/*in warm state,stop boost*/
+#ifdef DBG_CHARGE
+					printk(KERN_INFO"chg bat temp warm \n");
+#endif
+					break;
+					case ZX234502_REG_CISS_TS_COOL:/*cool*/
+						/*in cool state,stop boost*/
+#ifdef DBG_CHARGE
+						printk(KERN_INFO"chg bat  temp cool\n");
+#endif
+						//chg_disable.intval = 1;
+						//pwrbnk_enable.intval = 0;
+						//zx234502_charger_set_charger_config(bdi,&chg_disable);
+						//zx234502_boost_set_charge_enable(bdi, &pwrbnk_enable);
+						break;
+					case 3:/*hot*/ 
+						/*in hot state,charger chip auto off*/
+						printk(KERN_INFO"chg bat temp hot \n");
+						break;
+					case 6:/*cold*/	
+						/*in cold state,charger chip auto off*/
+						printk(KERN_INFO"chg bat temp cold\n");
+						break;
+					default:
+						printk(KERN_INFO"chg bat temp unkonw\n");
+						break;	
+					}	
+#endif
+				}
+			}
+			battery_changed_flag = true;	
+		}
+		bdi->charger_health_valid = true;/****?***/
+		bdi->battery_health_valid = true;/****?***/
+		bdi->battery_status_valid = true;/****?***/
+
+		mutex_unlock(&bdi->bs_reg_lock);
+
+		/*
+		 * Sometimes zx234502 gives a steady trickle of interrupts even
+		 * though the watchdog timer is turned off and neither the STATUS
+		 * nor FAULT registers have changed.  Weed out these sprurious
+		 * interrupts so userspace isn't alerted for no reason.
+		 * In addition, the chip always generates an interrupt after
+		 * register reset so we should ignore that one (the very first
+		 * interrupt received).
+		 */
+		//if (charger_changed_flag && !bdi->first_time) 
+		if (charger_changed_flag ) 
+			power_supply_changed(&bdi->charger);
+		//if (battery_changed_flag && !bdi->first_time) 
+		if (battery_changed_flag) 
+			power_supply_changed(&bdi->battery);
+		if (true == bdi->pdata->boost_flag){		
+			//if (boost_changed_flag && !bdi->first_time) 
+			if (boost_changed_flag ) 
+			power_supply_changed(&bdi->boost);
+		}
+		
+		bdi->first_time = false;
+
+	out:
+		//pm_runtime_put_sync(bdi->dev);
+		
+		dev_dbg(bdi->dev, "read reg:cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n", 
+		                  bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
+		
+		enable_irq(bdi->irq);
+	}
+	return 0;
+}
+
+
+static int zx234502_setup_pdata(struct zx234502_dev_info *bdi,
+		struct zx234502_platform_data *pdata)
+{
+	int ret;
+
+#if 0
+	if (!gpio_is_valid(pdata->gpio_int))
+		return -1;
+
+	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
+	if (ret < 0)
+		return -1;
+
+	ret = gpio_direction_input(pdata->gpio_int);
+	if (ret < 0)
+		goto out;
+
+	bdi->irq = gpio_to_irq(pdata->gpio_int);
+	if (!bdi->irq)
+		goto out;
+#endif
+	
+	bdi->irq = gpio_to_irq(pdata->gpio_int);
+	#ifdef  DBG_CHARGE
+	printk(KERN_INFO"zx234502_setup_pdata irq= %d\n",bdi->irq);
+	#endif
+	/*Ñ¡Ôñ´Ë¸´Óù¦ÄÜΪÖжϹ¦ÄÜ*/
+	ret = zx29_gpio_config(pdata->gpio_int,pdata->gpio_int_fun_sel);/********GPIO11:0 /EXT_INT:5*******/
+	if (ret < 0){
+		printk(KERN_INFO"zx234502 zx29_gpio_config error int= %d,fun= %d\n",pdata->gpio_int,pdata->gpio_int_fun_sel);		
+		return -1;
+	}
+
+	zx29_gpio_set_inttype(pdata->gpio_int,IRQ_TYPE_EDGE_FALLING/*IRQ_TYPE_EDGE_RISING*/);  //INT_POSEDGE
+	zx29_gpio_pd_pu_set(pdata->gpio_int, IO_CFG_PULL_DISABLE);
+
+	bdi->gpio_int = pdata->gpio_int;
+	//pcu_int_clear(bdi->irq);
+	pcu_clr_irq_pending(bdi->irq);
+	return 0;
+#if 0
+out:
+	gpio_free(pdata->gpio_int);
+	return -1;
+#endif
+
+}
+
+
+static int zx234502_init_state(struct zx234502_dev_info *bdi)
+{
+	u8 cfis_reg,pis_reg,cbis_reg,ciis_reg;
+	int ret;
+
+	printk(KERN_INFO "zx234502_init_state start.\n");
+
+	ret = zx234502_read(bdi, ZX234502_REG_CBIS, &cbis_reg);
+	if (ret < 0){
+		printk(KERN_INFO "charger:init state:Can't read CBIS reg: 0x%x\n", cbis_reg);
+		return ret;
+	}
+
+	ret = zx234502_read(bdi, ZX234502_REG_PIS, &pis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read PIS reg: %d\n", ret);
+		return ret;
+	}
+	
+	ret = zx234502_read(bdi, ZX234502_REG_CFIS, &cfis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read CFIS reg: %d\n", ret);
+		return ret;
+	}
+
+	ret = zx234502_read(bdi, ZX234502_REG_CIIS, &ciis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read CISS reg: %d\n", ret);
+		return ret;
+	}
+
+	mutex_lock(&bdi->bs_reg_lock);
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO "zx234502_init_state get lock  ok.\n");
+	#endif
+	bdi->cbis_curr_reg= cbis_reg;
+	bdi->pis_curr_reg= pis_reg;
+	bdi->cfis_curr_reg= cfis_reg;
+	bdi->ciis_curr_reg = ciis_reg;
+	bdi->charger.type = POWER_SUPPLY_TYPE_UNKNOWN;
+	
+	if(bdi->cbis_curr_reg & ZX234502_REG_CBIS_DCIN_PG_MASK){			
+		printk(KERN_INFO"send ap usb in message\n");
+		dwc_otg_chg_inform(0);/*usb in*/
+	}
+	else{
+		printk(KERN_INFO"send ap usb out message\n");
+		dwc_otg_chg_inform(1);/*usb out*/	
+	}
+	#ifdef DBG_CHARGE
+	if(bdi->cbis_curr_reg & BIT(5))
+		printk(KERN_INFO "no batterty.\n");
+	else
+		printk(KERN_INFO " baterry installed.\n");
+	#endif
+	mutex_unlock(&bdi->bs_reg_lock);
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "zx234502_init_state:cfis_reg10=0x%x,pis_reg0E=0x%x,cbis_reg0C=0x%x,ciis_reg0A=0x%x.\n",cfis_reg,pis_reg,cbis_reg,ciis_reg);
+#endif
+
+	return 0;
+}
+
+
+static void zx234502_boost_workstruct_callback(struct work_struct *work )
+{	
+	uint vol_curr = 0;
+	#ifdef DBG_CHARGE
+	u8 mainset;
+	#endif
+	struct zx234502_dev_info *bdi =
+			container_of(work, struct zx234502_dev_info, boostWorkStruct);	
+	vol_curr = get_adc2_voltage();/*get boost current*/
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO"boost current is %d in\n",vol_curr);
+	zx234502_read(bdi, 0, &mainset);
+	printk(KERN_INFO"powerbank is %d in\n",mainset);
+	printk(KERN_INFO"workqueue test\n");
+	#endif
+	if (vol_curr < ZX234502_BOOST_V_LIMIT)/*50mV*/{
+		bdi->boostcount++;
+	}
+	if(bdi->boostcount > 3){
+		bdi->boostcount = 0;	
+		bdi->boost_online_flag = 0;
+		power_supply_changed(&bdi->boost);
+		cancel_delayed_work_sync(&bdi->boostWorkStruct);
+	}
+	else{
+		bdi->boost_online_flag = 1;
+		queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,2000);		
+	}
+
+}
+static void zx234502_charge_typedet(T_TYPE_USB_DETECT chg_type)
+{
+	int ret;
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO"charge type is %d in\n",chg_type);
+	#endif
+	if(TYPE_ADAPTER == chg_type){
+		
+		printk(KERN_INFO"chg type is TYPE_ADAPTER\n");
+		 /*set the DCIN Current = 1A*/
+		ret = zx234502_write_mask(g_bdi,ZX234502_REG_ISC,
+					   ZX234502_REG_ISC_ISET_DCIN_MASK,
+					   ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+					   0x3);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_01 fault\n");
+		}
+		g_bdi->charger.type = POWER_SUPPLY_PCAC__AC;
+	}
+	
+	else{
+		printk(KERN_INFO"chgage type is TYPE_PC\n");
+		
+		 /*set the DCIN Current = 450mA*/
+		ret = zx234502_write_mask(g_bdi,ZX234502_REG_ISC,
+					   ZX234502_REG_ISC_ISET_DCIN_MASK,
+					   ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+					   0x1);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_01 fault\n");
+		}
+		
+		g_bdi->charger.type = POWER_SUPPLY_PCAC__PC;
+	}
+		
+		
+		#ifdef CONFIG_CHARGER_ZX234502_EVB
+		 /*set the DCIN Current = 2A*/
+		ret = zx234502_write_mask(g_bdi,ZX234502_REG_ISC,
+					   ZX234502_REG_ISC_ISET_DCIN_MASK,
+					   ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+					   0x5);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_01 fault\n");
+		}
+		#endif
+
+}
+
+
+#if defined(CONFIG_DEBUG_FS)
+static ssize_t debugfs_regs_write(struct file *file, const char __user *buf,size_t nbytes, loff_t *ppos)
+{
+	unsigned int val1, val2;
+	u8 reg, value;
+	int ret;
+	char *kern_buf;
+	struct seq_file	*s = file->private_data;
+	struct zx234502_dev_info *zx234502 = s->private;
+
+	kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+	if (!kern_buf) {
+		printk(KERN_INFO "zx234502_charger: Failed to allocate buffer\n");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
+		kfree(kern_buf);
+		return -ENOMEM;
+	}
+	printk(KERN_INFO "%s input str=%s,nbytes=%d \n", __func__, kern_buf,nbytes);	
+	
+	ret = sscanf(kern_buf, "%x:%x", &val1, &val2);
+	if (ret < 2 || val1 > ZX234502_REG_MAX ) {
+		printk(KERN_INFO "zx234502_charger: failed to read user buf, ret=%d, input 0x%x:0x%x\n",
+				ret, val1, val2);
+		kfree(kern_buf);
+		return -EINVAL;
+	}
+	kfree(kern_buf);
+
+	reg = val1 & 0xff;
+	value = val2 & 0xff;
+	printk(KERN_INFO "%s input %x,%x; reg=%x,value=%x\n", __func__, val1, val2, reg, value);	
+	ret = zx234502_write(zx234502,reg, value);
+
+	return ret ? ret : nbytes;
+}
+
+static int debugfs_regs_show(struct seq_file *s, void *v)
+{
+	int i;
+	u8 value[ZX234502_REG_MAX];
+	int ret=0;
+	int curr = 0;
+	struct zx234502_dev_info *zx234502 = s->private;
+
+	for (i = 0; i < ZX234502_REG_MAX; i++){
+		ret = zx234502_read(zx234502, i, &(value[i]));
+		
+		if(ret){			
+			printk(KERN_INFO "%s err=%d, break\n", __func__, ret);	
+			seq_printf(s, "%s err=%d, break", __func__, ret);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < ZX234502_REG_MAX; i++) {	
+		if((i+1)%9 == 0)
+			seq_printf(s, "\n");	
+		
+		seq_printf(s, "[0x%x]%02x ", i, value[i]);				
+	}
+	/*charger type*/
+	if(zx234502->charger.type ==POWER_SUPPLY_PCAC__PC){
+		seq_printf(s, "charger type is  PC\n");
+	}
+	else if(zx234502->charger.type ==POWER_SUPPLY_PCAC__AC){
+		seq_printf(s, "charger type is  AC\n");
+	}
+	else
+	seq_printf(s, "charger type is  unknow = %d\n",zx234502->charger.type);
+
+	/*stopchg_flag*/
+	if(1==stopchg_flag){
+		seq_printf(s, "mmi set charger enable,the charger state = %d\n",!(value[ZX234502_REG_MS]&ZX234502_REG_MS_INSUS_MASK));
+	}
+	else if(2==stopchg_flag){
+		seq_printf(s, "mmi set charger disable,the charger state = %d\n",!(value[ZX234502_REG_MS]&ZX234502_REG_MS_INSUS_MASK));
+	}
+	else
+		seq_printf(s, "mmi never set the charger ,the charger state = %d\n",!(value[ZX234502_REG_MS]&ZX234502_REG_MS_INSUS_MASK));
+
+	/*charge current*/
+	ret = zx234502_get_field_val(zx234502, ZX234502_REG_ISC,
+		ZX234502_REG_ISC_ISET_DCIN_MASK, ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+		zx234502_in_ilimit_values,
+		ARRAY_SIZE(zx234502_in_ilimit_values), &curr);
+	
+	if (ret < 0)
+		return ret;
+	seq_printf(s, "the charger current now  = %dmA\n",curr);
+
+
+	return ret;
+}
+
+#define DEBUGFS_FILE_ENTRY(name) \  
+static int debugfs_##name##_open(struct inode *inode, struct file *file) \  
+{\  
+return single_open(file, debugfs_##name##_show, inode->i_private); \  
+}\  
+\  
+static const struct file_operations debugfs_##name##_fops = { \  
+.owner= THIS_MODULE, \  
+.open= debugfs_##name##_open, \  
+.write=debugfs_##name##_write, \
+.read= seq_read, \  
+.llseek= seq_lseek, \  
+.release= single_release, \  
+}  
+
+DEBUGFS_FILE_ENTRY(regs);
+
+static struct dentry *g_charger_root;
+
+static void debugfs_charger_init(struct zx234502_dev_info  *zx234502)
+{
+	struct dentry *root;
+	struct dentry *node;		
+	int i;
+	
+	if(!zx234502)
+		return;
+
+	//create root
+	root = debugfs_create_dir("charger_zx29", NULL);
+	if (!root)	{	
+		dev_err(&zx234502->dev, "debugfs_create_dir err=%d\n", IS_ERR(root));
+		goto err;
+	}
+
+	//print regs;
+	node = debugfs_create_file("regs", S_IRUGO | S_IWUGO, root, zx234502,  &debugfs_regs_fops);
+	if (!node){
+		dev_err(&zx234502->dev, "debugfs_create_dir err=%d\n", IS_ERR(node));
+		goto err;
+	}
+	
+	g_charger_root = (void *)root;
+	return;
+err:
+	dev_err(&zx234502->dev, "debugfs_charger_init err\n");
+}
+
+#endif
+
+
+static int zx234502_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct device *dev = &client->dev;
+	struct zx234502_platform_data *pdata = client->dev.platform_data;
+	struct zx234502_dev_info *bdi;
+	int ret;
+	int i;  /*when err try 3 times*/
+	//use for other 
+	//g_platform_data= client->dev.platform_data;
+
+	printk(KERN_INFO "charger probe.\n");
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
+		return -ENODEV;
+	}
+
+	bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);
+	if (!bdi) {
+		dev_err(dev, "Can't alloc bdi struct\n");
+		return -ENOMEM;
+	}
+	bdi->pdata = pdata;
+	bdi->client = client;
+	bdi->dev = dev;
+	bdi->model = id->driver_data;
+	strncpy(bdi->model_name, id->name, sizeof(bdi->model_name)-1);
+	mutex_init(&bdi->bs_reg_lock);
+	bdi->first_time = true;
+	bdi->charger_health_valid = false;
+	bdi->battery_health_valid = false;
+	bdi->battery_status_valid = false;
+
+	g_bdi = bdi;
+
+	i2c_set_clientdata(client, bdi);
+
+	if (dev->of_node)
+		ret = 0;//zx234502_setup_dt(bdi);
+	else
+		ret = zx234502_setup_pdata(bdi, pdata);
+
+	if (ret) {
+		dev_err(dev, "Can't get irq info\n");
+		return -EINVAL;
+	}
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "hwinit.\n");
+#endif
+	//pm_runtime_enable(dev);
+	//pm_runtime_resume(dev);
+	i = 0;
+	do{	
+		ret = zx234502_hw_init(bdi);
+		if (ret < 0) {
+			printk(KERN_INFO "zx234502_probe Hardware init failed times = %d\n",(i+1));
+			i++;
+		}
+		else
+			break;
+		
+	}while(i<3);	
+
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "zx234502_probe zx234502_hw_init ok.\n");
+#endif
+#ifdef CONFIG_CHARGER_ZX234502_EVB
+	 /*set the DCIN Current = 2A*/
+	ret = zx234502_write_mask(g_bdi,ZX234502_REG_ISC,
+				   ZX234502_REG_ISC_ISET_DCIN_MASK,
+				   ZX234502_REG_ISC_ISET_DCIN_SHIFT,
+				   0x5);
+	if (ret < 0){
+		printk(KERN_INFO"write REG_01 fault\n");
+	}
+#endif
+	ret = zx234502_charger_config_groupB_Regs(bdi);
+	if (ret < 0) {
+		printk(KERN_INFO "groupB config faild.\n");
+	}
+
+	zx234502_charger_init(&bdi->charger);
+
+	ret = power_supply_register(dev, &bdi->charger);
+	if (ret) {
+		dev_err(dev, "Can't register charger\n");
+		goto out2;
+	}
+	printk(KERN_INFO "zx234502_probe power_supply_register charger ok.\n");
+
+	zx234502_battery_init(&bdi->battery);
+
+	ret = power_supply_register(dev, &bdi->battery);
+	if (ret) {
+		dev_err(dev, "Can't register battery\n");
+		goto out3;
+	}
+	printk(KERN_INFO "zx234502_probe power_supply_register battery ok.\n");
+	
+	if(true == pdata->boost_flag){
+		zx234502_boost_init(&bdi->boost);
+		ret = power_supply_register(dev, &bdi->boost);
+		if (ret) {
+			dev_err(dev, "Can't register boost\n");
+			goto out4;
+		}
+		
+		ret = zx234502_boost_gpio_init(dev,pdata);	
+		if (ret) {
+			dev_err(dev, "Can't register boost\n");
+			goto out4;
+		}
+	#ifdef DBG_CHARGE
+		printk(KERN_INFO "zx234502_boost_gpio_init.\n");
+	#endif
+	    
+		bdi->boostQueue = create_workqueue("zx234502boost");
+		if (!bdi->boostQueue){
+			if(bdi->pdata->boost_cur_gpio1)
+				gpio_free(bdi->pdata->boost_cur_gpio1);
+			if(bdi->pdata->boost_cur_gpio2)
+				gpio_free(bdi->pdata->boost_cur_gpio2);
+			if(bdi->pdata->boost_cur_gpio3)
+				gpio_free(bdi->pdata->boost_cur_gpio3);
+			if(bdi->pdata->boost_loadswitch_gpio)
+				gpio_free(bdi->pdata->boost_loadswitch_gpio);
+			
+			ret = -1;
+			goto out4;
+		}
+		
+		INIT_DELAYED_WORK(&bdi->boostWorkStruct,zx234502_boost_workstruct_callback);
+		
+		//queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,20000);
+	#ifdef DBG_CHARGE
+		printk(KERN_INFO "setup_workqueue.\n");
+	#endif
+	}
+#if 0
+//#ifdef CONFIG_SYSFS
+	ret = zx234502_sysfs_create_group(bdi);
+	if (ret) {
+		dev_err(dev, "Can't create sysfs entries\n");
+		goto out5;
+	}
+#endif
+	dwc_chg_Regcallback(zx234502_charge_typedet);/*register for usb*/
+	
+	sema_init(&bdi->chgirq_sem, 0);
+	
+	ret = zx234502_init_state(bdi);
+	if(ret)
+	{
+		dev_err(dev, "zx234502 init state error.\n");	
+		goto out1;
+	}
+	
+	bdi->chg_irq_thread = kthread_run(zx234502_irq_handler_thread, bdi, "zx234502-chgirq");
+	BUG_ON(IS_ERR(bdi->chg_irq_thread));
+	
+	ret = request_irq(bdi->irq, zx234502_charger_irq_primary_handler,IRQF_NO_THREAD, "zx234502-charger", bdi);
+	if (ret < 0) {
+		dev_err(dev, "Can't set up irq handler\n");	
+		goto out1;
+	}
+	irq_set_irq_wake(bdi->irq, 1);
+	
+	/*clear all int*/
+	ret = zx234502_write_mask(bdi,ZX234502_REG_CIIS,ZX234502_REG_CIIS_INT_MASK,ZX234502_REG_CIIS_INT_SHIFT,0x0);
+	if (ret == 0) {
+		printk(KERN_INFO "clear int ok \n");
+	}
+
+
+#if defined(CONFIG_DEBUG_FS)
+	debugfs_charger_init(bdi);
+#endif
+
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "zx234502_probe end.\n");
+#endif
+
+	return 0;
+#if 0
+out5:
+	zx234502_sysfs_remove_group(bdi);
+#endif
+out4:
+	power_supply_unregister(&bdi->boost);
+out3:
+	power_supply_unregister(&bdi->battery);
+out2:
+	//pm_runtime_disable(dev);
+	power_supply_unregister(&bdi->charger);
+out1:
+	if (bdi->gpio_int)
+		gpio_free(bdi->gpio_int);
+	dwc_chg_Regcallback(NULL);/*unregister for usb*/
+
+	return ret;
+}
+
+static int zx234502_remove(struct i2c_client *client)
+{
+	struct zx234502_dev_info *bdi = i2c_get_clientdata(client);
+	struct zx234502_platform_data *pdata = client->dev.platform_data;
+
+	if(!bdi)	
+		return -EINVAL;
+
+	//pm_runtime_get_sync(bdi->dev);
+	zx234502_register_reset(bdi);
+	//pm_runtime_put_sync(bdi->dev);
+
+	zx234502_sysfs_remove_group(bdi);
+	power_supply_unregister(&bdi->battery);
+	power_supply_unregister(&bdi->charger);
+	if(true == pdata->boost_flag)
+		power_supply_unregister(&bdi->boost);
+	pm_runtime_disable(bdi->dev);
+
+	if (bdi->gpio_int)
+		gpio_free(bdi->gpio_int);
+	zx234502_boost_gpio_uninit(pdata);
+
+	if(bdi->boostQueue)
+		destroy_workqueue(bdi->boostQueue);
+	
+#if defined(CONFIG_DEBUG_FS)
+	if(g_charger_root){
+		printk(KERN_INFO "zx234502_device_exit:debugfs_remove_recursive \n");
+		debugfs_remove_recursive(g_charger_root);
+	}
+#endif
+
+	return 0;
+}
+
+static int zx234502_suspend(struct i2c_client *not_use, pm_message_t mesg)
+{
+	
+	disable_irq_nosync(g_bdi->irq);
+	return 0;
+	
+}
+
+static int zx234502_resume(struct i2c_client *not_use)
+{
+	
+	enable_irq(g_bdi->irq);
+	return 0;
+	
+}
+/*
+ * Only support the zx234502 right now.  The bq24192, bq24192i, and bq24193
+ * are similar but not identical so the driver needs to be extended to
+ * support them.
+ */
+static const struct i2c_device_id zx234502_i2c_ids[] = {
+	{ "zx234502-charger", ZX234502_REG_VERS },
+	{ },
+};
+
+static struct i2c_driver zx234502_driver = {
+	.probe		= zx234502_probe,
+	.remove		= zx234502_remove,
+	.id_table	= zx234502_i2c_ids,
+	.driver = {
+		.name		= "zx234502-charger",
+		.owner		= THIS_MODULE,
+	},
+		.suspend	= zx234502_suspend,
+	.resume		= zx234502_resume,
+};
+static int __init zx234502_i2c_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&zx234502_driver);
+	if (ret != 0)
+		pr_err("Failed to register visionox_i2c_driver : %d\n", ret);
+
+	return ret;
+}
+/* init early so consumer devices can complete system boot */
+module_init(zx234502_i2c_init);
+
+static void __exit zx234502_i2c_exit(void)
+{
+	i2c_del_driver(&zx234502_driver);
+}
+module_exit(zx234502_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
+MODULE_ALIAS("i2c:zx234502-charger");
+MODULE_DESCRIPTION("TI ZX234502 Charger Driver");