Merge "[Feature][R305][task-view-1918] add charger code for V4"
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c b/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
index 59504bb..baf731e 100755
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
@@ -1336,6 +1336,17 @@
 	{3530,12}, {3590,10}, {3450,5}
 };
 
+struct sgm41513_charge_current_limit zx234502_charger_temp_current[] =
+{
+	//grade							above below	current voltage_limit
+	{POWER_SUPPLY_HEALTH_UNKNOWN,	1700,	-1,		0,		-1},  //ntc offline 
+	{POWER_SUPPLY_HEALTH_COLD,		1273,	1700,	0,		-1},
+	{POWER_SUPPLY_HEALTH_COOL,		1057,	1273,	900,	-1},
+	{POWER_SUPPLY_HEALTH_GOOD,		623,	1057,	1740,	-1},
+	{POWER_SUPPLY_HEALTH_WARM,		434,	623,	840,	-1},
+	{POWER_SUPPLY_HEALTH_OVERHEAT,	-1,		434,	0,		-1}
+};
+
 static struct  sgm41513_platform_data sgm41513_charger_platform = {
 	.gpio_int		=	PIN_CHARGE_INT,  //gpio55
 	.gpio_int_fun_sel = CHARGE_INT_FUNC_SEL,
@@ -1343,6 +1354,12 @@
 	.charging_size = SGM41513_BAT_VOLTAGE_LEN,
 	.discharging      =  &sgm41513_bat_volage_discharge,
 	.discharging_size = SGM41513_BAT_VOLTAGE_LEN,
+	.temp_current_map = &zx234502_charger_temp_current,
+	.temp_current_map_size = ARRAY_SIZE(zx234502_charger_temp_current),
+	.max_charge_voltage = 4400,
+	.max_input_current = 2300,
+	.pre_charge_current = 110,
+	.terminate_charge_current = 110,
 	.ts_flag = FALSE,
 	.boost_flag = TRUE,
 };
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c b/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
index 795a832..45428c6 100755
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
@@ -34,13 +34,36 @@
 #include <linux/debugfs.h>
 #include <asm/uaccess.h>
 
+#define OUT_5V_GPIO ZX29_GPIO_119
+#define DCIN_5V_GPIO ZX29_GPIO_125
+#define DCIN_5V_GPIO_FUNC_GPIO GPIO125_GPIO125
+#define DCIN_5V_GPIO_FUNC_EXT_INT GPIO125_EXT_INT14
+#define DCIN_5V_DT_INT  PCU_EX14_INT
+
+#define CHG_PLUG_IN		GPIO_LOW
+#define CHG_PLUG_OUT	GPIO_HIGH
+
 #define DBG_CHARGE 1
+
+#define CHANGE_ROLE_VOTAGE 3600
 //*
 extern int get_typec_role(void);
 extern set_typec_try_role(int type);
 //*/
 
+enum type_usb_detect_stage
+{
+	USB_STATUS_UNKOWN = 0,
+	USB_STATUS_DETECTING,
+	USB_STATUS_CONNECTED,
+	USB_STATUS_DISCONNECTING,
+	USB_STATUS_DISCONNECTED
+};
+
 static int ce_enabled = 0;
+//const int green_voltage_level = 3650;
+//const int red_voltage_level = 3510;
+
 /*
  * The FAULT register is latched by the sgm41513 (except for NTC_FAULT)
  * so the first read after a fault returns the latched value and subsequent
@@ -61,17 +84,31 @@
 	kernel_ulong_t			model;
 	unsigned int			gpio_int;
 	unsigned int			irq;
+	unsigned int			chgin_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;
+	bool			dcin_5v_pulgin_flag;
+	volatile int	current_charging_flag;
+	volatile int	last_reported_charging_flag;
+	volatile int	during_voltage_query_flag;
+	volatile bool	discharging_flag;
+	enum type_usb_detect_stage	usb_detect_flag;
+	volatile bool	power_role_switch_only;
+	volatile int	dwc_otg_chg_inform_status;
+	volatile bool	can_switch_role_flag;
+	bool			battery_online_flag;
+	unsigned int	usb_plug_in_out_check_cnt;
+	u8				reg08;
 	u8				reg09;
 	u8				cbis_curr_reg;
 	u8              pis_curr_reg;
 	u8              cfis_curr_reg;
 
 	u8				ciis_pre_reg;
+	u8				pre_reg08;
 	u8				pre_reg09;
 	u8              pis_pre_reg;
 	u8              cfis_pre_reg;
@@ -79,6 +116,7 @@
 	u8				boost_online_flag;
 	struct delayed_work		boostWorkStruct ;
 	struct delayed_work charge_monitor_work;
+	volatile bool	charge_monitor_work_running_flag;
 	struct workqueue_struct *boostQueue;
 	struct semaphore		chgirq_sem;
 	struct task_struct		*chg_irq_thread;
@@ -91,46 +129,22 @@
 //struct sgm41513_platform_data *g_platform_data = NULL;
 struct sgm41513_dev_info *g_bdi = NULL;
 
-/* REG01[2:0] (ISET_DCIN) in mAh */
-static const int sgm41513_in_ilimit_values[] = {
-   150,  450,  850,  1000,  1500,  2000, 2500, 3000
-};
-/* REG01[6:3] (VINDPM) in mVh */
-static const int sgm41513_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 sgm41513_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
-};
+static int g_last_real_voltage = 0;
+int can_cc_hardreset(void) {
+	int ret;
+	if (g_bdi == NULL)
+	    return 0;
+	if (g_bdi->charger.type == POWER_SUPPLY_PCAC__AC)
+		ret = g_last_real_voltage > red_voltage_level;
+	else
+		ret = ce_enabled == 0 ? (get_adc1_voltage() > red_voltage_level) : (g_last_real_voltage > red_voltage_level);
+	
+	printk("cy: can_cc_hardreset %d, g_last_real_voltage %d, voltage %d\n", ret, g_last_real_voltage, get_adc1_voltage());
+	return ret;
+}
+*/
 
-/* REG04[3:1] (VSETA) in mV */
-static const int sgm41513_cvc_vseta_values[] = {
-	4100, 4150, 4200, 4250, 4300, 4350, 4400, 4450,
-};
-
-/* REG02[7:5] (VSYS_MIN) in mV */
-static const int sgm41513_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
@@ -232,211 +246,12 @@
 	return sgm41513_write_mask(bdi, reg, mask, shift, idx);
 }
 
-//#ifdef CONFIG_SYSFS
-#if 0
-/*
- * There are a numerous options that are configurable on the sgm41513
- * 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 sgm41513_sysfs_field_info {
-	struct device_attribute	attr;
-	u8	reg;
-	u8	mask;
-	u8	shift;
-};
-
-
-#define SGM41513_SYSFS_FIELD(_name, r, f, m, store)			\
-{									\
-	.attr	= __ATTR(f_##_name, m, sgm41513_sysfs_show, store),	\
-	.reg	= SGM41513_REG_##r,					\
-	.mask	= SGM41513_REG_##r##_##f##_MASK,				\
-	.shift	= SGM41513_REG_##r##_##f##_SHIFT,			\
-}
-
-#define SGM41513_SYSFS_FIELD_RW(_name, r, f)				\
-		SGM41513_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO,	\
-				sgm41513_sysfs_store)
-
-#define SGM41513_SYSFS_FIELD_RO(_name, r, f)				\
-		SGM41513_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
-
-static ssize_t sgm41513_sysfs_show(struct device *dev,
-		struct device_attribute *attr, char *buf);
-static ssize_t sgm41513_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 sgm41513_sysfs_field_info sgm41513_sysfs_field_tbl[] = {
-			/*	sysfs name	reg	field in reg */
-	SGM41513_SYSFS_FIELD_RW(chg_reset,		MS,	CHGRST),
-	SGM41513_SYSFS_FIELD_RW(pmuon,		MS,	PMUON),
-	SGM41513_SYSFS_FIELD_RW(en_ship,		MS,	ENSHIP),
-	SGM41513_SYSFS_FIELD_RW(en_otg,		MS,	ENOTG),
-	SGM41513_SYSFS_FIELD_RW(chg_config,	MS,	ENCHG),
-	SGM41513_SYSFS_FIELD_RW(en_powerbank,		MS,	PWRBNK),
-	SGM41513_SYSFS_FIELD_RW(insus,		MS,	INSUS),
-	SGM41513_SYSFS_FIELD_RW(in_limit,	ISC,	ISET_DCIN),
-	SGM41513_SYSFS_FIELD_RW(vsys_min,		VSC,	VSYS_MIN),
-	SGM41513_SYSFS_FIELD_RW(ichg,	CCC,	ISETA),
-	SGM41513_SYSFS_FIELD_RW(force_ichg_50pct,		CCC,	ICHG_50PCT),
-	SGM41513_SYSFS_FIELD_RW(iprechg,		CVC,	IPRECHG),
-	SGM41513_SYSFS_FIELD_RW(vbat_full,		CVC,	VBAT),
-	SGM41513_SYSFS_FIELD_RW(vpre_to_fast, 	CVC,	VBATFC),
-	SGM41513_SYSFS_FIELD_RW(en_timer,		CTC,	EN_TIMER),
-	SGM41513_SYSFS_FIELD_RW(en_2timer,		CTC,	EN_2XTIMER),
-	SGM41513_SYSFS_FIELD_RW(stopchg_flag,		OTGC,	OTGV),
-	SGM41513_SYSFS_FIELD_RW(iotg_limit,		OTGC,	OTGI_LIM),
-	SGM41513_SYSFS_FIELD_RW(ents_otg,	OTGC,	ENTS_OTG),
-	SGM41513_SYSFS_FIELD_RO(en_therm,	THR,	EN_THERM),
-	SGM41513_SYSFS_FIELD_RW(therm_threshold,	THR,	THERM_THLD),	
-	SGM41513_SYSFS_FIELD_RW(en_2det, THR,	EN_2DET),
-	SGM41513_SYSFS_FIELD_RW(en_1det, THR,	EN_1DET),
-	SGM41513_SYSFS_FIELD_RW(en_jeita,	THR,	EN_JEITA),
-	SGM41513_SYSFS_FIELD_RW(en_ilimitdj,	THR,	EN_ILIMITDJ),
-	SGM41513_SYSFS_FIELD_RW(tscold,		TS,	COLD),
-	SGM41513_SYSFS_FIELD_RW(tscool,	TS,	COOL),
-	SGM41513_SYSFS_FIELD_RW(tswarm,	TS,	WARM),
-	SGM41513_SYSFS_FIELD_RW(tshot,	TS,	HOT),
-	SGM41513_SYSFS_FIELD_RW(ntcdet,	PTS,NTCDET),
-	SGM41513_SYSFS_FIELD_RW(int_clear, CIIS,	INT),
-	SGM41513_SYSFS_FIELD_RO(ciis_reg,	CIIS,	ALL),
-	SGM41513_SYSFS_FIELD_RW(mask_chgrun,	CIIM,	MASK_CHGRUN),
-	SGM41513_SYSFS_FIELD_RW(mask_inlimit,	CIIM,	MASK_INLIMIT),
-	SGM41513_SYSFS_FIELD_RW(mask_thr,	CIIM,	MASK_THR),
-	SGM41513_SYSFS_FIELD_RW(mask_ts,	CIIM,	MASK_TS),
-	SGM41513_SYSFS_FIELD_RW(mask_dcdet,	CIIM,	MASK_DCDET),
-	SGM41513_SYSFS_FIELD_RO(cbis_reg,	CBIS,	ALL),
-	SGM41513_SYSFS_FIELD_RW(mask_pg,	CBIM,	MASK_DCIN_PG),
-	SGM41513_SYSFS_FIELD_RW(mask_batlow,	CBIM,	MASK_BATLOW),
-	SGM41513_SYSFS_FIELD_RW(mask_nobat,	CBIM,	MASK_NOBAT),
-	SGM41513_SYSFS_FIELD_RW(mask_eoc,	CBIM,	MASK_EOC),
-	SGM41513_SYSFS_FIELD_RW(mask_timer,	CBIM,	MASK_SAFE_TIMER),
-	SGM41513_SYSFS_FIELD_RW(mask_otg_fault,		CBIM,	MASK_OTG_FAULT),
-	SGM41513_SYSFS_FIELD_RO(pis_reg,	PIS,	ALL),
-	SGM41513_SYSFS_FIELD_RW(mask_pwron_it,	PIM,	MASK_POWERON_IT),
-	SGM41513_SYSFS_FIELD_RW(mask_pwron_lp, PIM,	MASK_POWERON_LP),
-	SGM41513_SYSFS_FIELD_RO(cfis_reg,	CFIS,	ALL),			
-	SGM41513_SYSFS_FIELD_RO(version_info,	VER,	INFO),	
-};
-
-static struct attribute *
-	sgm41513_sysfs_attrs[ARRAY_SIZE(sgm41513_sysfs_field_tbl) + 1];
-
-static const struct attribute_group sgm41513_sysfs_attr_group = {
-	.attrs = sgm41513_sysfs_attrs,
-};
-
-static void sgm41513_sysfs_init_attrs(void)
-{
-	int i, limit = ARRAY_SIZE(sgm41513_sysfs_field_tbl);
-
-	for (i = 0; i < limit; i++)
-		sgm41513_sysfs_attrs[i] = &sgm41513_sysfs_field_tbl[i].attr.attr;
-
-	sgm41513_sysfs_attrs[limit] = NULL; /* Has additional entry for this */
-}
-
-static struct sgm41513_sysfs_field_info *sgm41513_sysfs_field_lookup(
-		const char *name)
-{
-	int i, limit = ARRAY_SIZE(sgm41513_sysfs_field_tbl);
-
-	for (i = 0; i < limit; i++)
-		if (!strcmp(name, sgm41513_sysfs_field_tbl[i].attr.attr.name))
-			break;
-
-	if (i >= limit)
-		return NULL;
-
-	return &sgm41513_sysfs_field_tbl[i];
-}
-
-static ssize_t sgm41513_sysfs_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct power_supply *psy = dev_get_drvdata(dev);
-	struct sgm41513_dev_info *bdi =
-			container_of(psy, struct sgm41513_dev_info, charger);
-	struct sgm41513_sysfs_field_info *info;
-	int ret;
-	u8 v;
-
-	info = sgm41513_sysfs_field_lookup(attr->attr.name);
-	if (!info)
-		return -EINVAL;
-
-	ret = sgm41513_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 sgm41513_sysfs_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct power_supply *psy = dev_get_drvdata(dev);
-	struct sgm41513_dev_info *bdi =
-			container_of(psy, struct sgm41513_dev_info, charger);
-	struct sgm41513_sysfs_field_info *info;
-	int ret;
-	u8 v;
-
-	info = sgm41513_sysfs_field_lookup(attr->attr.name);
-	if (!info)
-		return -EINVAL;
-
-	ret = kstrtou8(buf, 0, &v);
-	if (ret < 0)
-		return ret;
-
-	ret = sgm41513_write_mask(bdi, info->reg, info->mask, info->shift, v);
-	if (ret)
-		return ret;
-
-	return count;
-}
-
-static int sgm41513_sysfs_create_group(struct sgm41513_dev_info *bdi)
-{
-	sgm41513_sysfs_init_attrs();
-
-	return sysfs_create_group(&bdi->charger.dev->kobj,
-			&sgm41513_sysfs_attr_group);
-}
-
-static void sgm41513_sysfs_remove_group(struct sgm41513_dev_info *bdi)
-{
-	sysfs_remove_group(&bdi->charger.dev->kobj, &sgm41513_sysfs_attr_group);
-}
-#else
 static int sgm41513_sysfs_create_group(struct sgm41513_dev_info *bdi)
 {
 	return 0;
 }
 
 static inline void sgm41513_sysfs_remove_group(struct sgm41513_dev_info *bdi) {}
-#endif
-
-#if 0
-/*set the Vsys min*/
-static int sgm41513_set_vsys_min(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
-{
-	return sgm41513_set_field_val(bdi, SGM41513_REG_VSC,
-			SGM41513_REG_VSC_VSYS_MIN_MASK, SGM41513_REG_VSC_VSYS_MIN_SHIFT,
-			sgm41513_cvc_vseta_values,
-			ARRAY_SIZE(sgm41513_cvc_vseta_values), val->intval);	
-	//return 0
-}
-#endif
 
 //#define func_trace() do{printk("cy: functrace %s:%d\n", __func__, __LINE__);}while(0)
 #define func_trace() do{}while(0)
@@ -448,14 +263,14 @@
 
 	func_trace();
 	/* Reset the registers */
-	ret = sgm41513_write_mask(bdi, SGM41513_REG08,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,0x1);
+	ret = sgm41513_write_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,0x1);
 	if (ret < 0)
 		return ret;
 
 	/* Reset bit will be cleared by hardware so poll until it is */
 	do
     	{
-		ret = sgm41513_read_mask(bdi, SGM41513_REG08,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,&v);
+		ret = sgm41513_read_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,&v);
 		if (ret < 0)
 			return ret;
 
@@ -475,24 +290,102 @@
 
 /* Charger power supply property routines */
 
-extern void typec_pwr_role_set1(void);
 static void dump_sgm_regs(struct i2c_client *client);
 static int sgm41513_charger_get_charge_type(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
 {
 	printk("cy: sgm41513_charger_get_charge_type 1\n");
 	val->intval = bdi->charger.type;
-	//set_typec_try_role(1);
-	//typec_pwr_role_set1();
 	return 0;
 }
 
-static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+static void set_ce_gpio(int val)
 {
-	u8 v=0, vbus_stat=0, chrg_stat=0, pg_stat=0;
+	if (val > 0)
+	{
+		gpio_direction_output(120, 0);
+		ce_enabled = 1;
+	}
+	else
+	{
+		gpio_direction_output(120, 1);
+		ce_enabled = 0;
+	}
+}
+
+static int sgm41513_get_real_voltage(void)
+{
+	int ret, local_ce_flag=0;
+	u8 v=0;
+	if (ce_enabled == 1)
+	{
+		ret = sgm41513_read_mask(g_bdi, SGM41513_REG08, SGM41513_REG08_CHRG_STAT_MASK, SGM41513_REG08_CHRG_STAT_SHIFT, &v);
+		if (v == 1 || v == 2)
+		{
+			local_ce_flag = 1;
+			mutex_lock(&g_bdi->bs_reg_lock);
+			g_bdi->during_voltage_query_flag = 2;
+			mutex_unlock(&g_bdi->bs_reg_lock);
+			set_ce_gpio(0);
+			msleep(100);
+		}
+	}
+	ret = get_adc1_voltage() - (local_ce_flag == 1 ? 8 : 0);
+	if (local_ce_flag)
+	{
+		set_ce_gpio(1);
+		mutex_lock(&g_bdi->bs_reg_lock);
+		g_bdi->during_voltage_query_flag = 1;
+		mutex_unlock(&g_bdi->bs_reg_lock);
+	}
+	return ret;
+}
+
+int can_cc_hardreset(void)
+{
+	if (g_bdi->dcin_5v_pulgin_flag)
+		return true;
+	return sgm41513_get_real_voltage() > CHANGE_ROLE_VOTAGE;
+}
+
+static int convert_charger_status(u8 v)
+{
+	u8 vbus_stat=0, chrg_stat=0, pg_stat=0;
 	int status=POWER_SUPPLY_STATUS_UNKNOWN;
+	
+	vbus_stat = ((v&SGM41513_REG08_VBUS_STAT_MASK) >> SGM41513_REG08_VBUS_STAT_SHIFT);
+	chrg_stat = ((v&SGM41513_REG08_CHRG_STAT_MASK) >> SGM41513_REG08_CHRG_STAT_SHIFT);
+	pg_stat = ((v&SGM41513_REG08_PG_STAT_MASK) >> SGM41513_REG08_PG_STAT_SHIFT);
+	printk("cy: sgm41513_charger_get_status v=%d, %d %d %d\n", v, vbus_stat, chrg_stat, pg_stat);
+
+	if (vbus_stat == 0 || vbus_stat == 7 || (chrg_stat == 0 && pg_stat == 0))
+	{
+		status = POWER_SUPPLY_STATUS_DISCHARGING;
+	}
+	else if(chrg_stat == 1 || chrg_stat == 2)
+	{
+		if (ce_enabled == 1)
+			status = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+	else if(chrg_stat == 0 || ce_enabled == 0)
+	{
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+	else if(chrg_stat == 3)
+	{
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+
+	return status;
+}
+
+static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val, bool full_check)
+{
+	u8 v=0;
 	int ret=0;
 
-	printk("cy: sgm41513_charger_get_status 3\n");
+	//printk("cy: sgm41513_charger_get_status 3\n");
 	//dump_sgm_regs(bdi->client);
 	//set_typec_try_role(0);
 	//typec_pwr_role_set1();
@@ -504,96 +397,36 @@
 		printk("cy: read reg 08 error\n");
 		return -EIO;
 	}
-
-	vbus_stat = ((v&SGM41513_REG08_VBUS_STAT_MASK) >> SGM41513_REG08_VBUS_STAT_SHIFT);
-	chrg_stat = ((v&SGM41513_REG08_CHRG_STAT_MASK) >> SGM41513_REG08_CHRG_STAT_SHIFT);
-	pg_stat = ((v&SGM41513_REG08_PG_STAT_MASK) >> SGM41513_REG08_PG_STAT_SHIFT);
-
-	if (vbus_stat == 0 || vbus_stat == 7 || (chrg_stat == 0 && pg_stat == 0))
+	else
 	{
-		status = POWER_SUPPLY_STATUS_DISCHARGING;
-	}
-	else if(chrg_stat == 1 || chrg_stat == 2)
-	{
-		status = POWER_SUPPLY_STATUS_CHARGING;
-	}
-	else if(chrg_stat == 0)
-	{
-		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-	}
-	else if(chrg_stat == 3)
-	{
-		status = POWER_SUPPLY_STATUS_FULL;
+		val->intval = convert_charger_status(v);
+		if (full_check && val->intval == POWER_SUPPLY_STATUS_NOT_CHARGING && sgm41513_get_real_voltage() >= bdi->pdata->max_charge_voltage)
+		{
+			val->intval = POWER_SUPPLY_STATUS_FULL;
+		}
 	}
 
-	if (!ret)
-		val->intval = status;
-
-	printk("cy: sgm41513_charger_get_status exit\n");
+	if (full_check)
+		printk("cy: sgm41513_charger_get_status %d exit\n", val->intval);
 	return ret;
 }
 
 static int sgm41513_charger_get_health(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
 {
-	u8 ciis_reg=0, cbis_reg=0, cfis_reg=0;
-	int health=0, ret=0;
+	u8 v;
+	int ret;
 
-	func_trace();
-	//mutex_lock(&bdi->bs_reg_lock);
-
-#if 0
-	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 = sgm41513_read(bdi, SGM41513_REG_CIIS, &ciis_reg);
-		if (ret < 0)
-			return ret;
-		ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &cbis_reg);
-		if (ret < 0)
-			return ret;
-		ret = sgm41513_read(bdi, SGM41513_REG_CFIS, &cfis_reg);
-		if (ret < 0)
-			return ret;
-
-		printk(KERN_INFO "sgm41513_charger_get_health REG_0xa=0x%x,REG_0xc=0x%x,REG_0x10=0x%x.\n",ciis_reg,cbis_reg,cfis_reg);	
-
+	ret = sgm41513_read_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_PN_MASK,
+							SGM41513_REG0B_PN_SHIFT, &v);
+	if (ret < 0 || v == 0)
+	{
+		val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+	}
+	else
+	{
+		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 	}
 
-	if (cbis_reg & SGM41513_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 & SGM41513_REG_CBIS_SAFE_TIMER_MASK) {	
-		health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
-	}
-	else if(cbis_reg & SGM41513_REG_CBIS_DCIN_PG_MASK) {	
-		health = POWER_SUPPLY_HEALTH_GOOD;
-	}
-	else if(ciis_reg & (SGM41513_REG_CIIS_INLIMIT_MASK|SGM41513_REG_CIIS_THERM_MASK)) {	
-		health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
-	}
-	else if(cfis_reg & SGM41513_REG_CFIS_THSD_MASK){
-		health = POWER_SUPPLY_HEALTH_OVERHEAT;	/*the chip hot error*/
-	}
-	else{	
-		health = POWER_SUPPLY_HEALTH_UNKNOWN;
-    }
-	
-	val->intval = health;
-
-#endif
-	val->intval = POWER_SUPPLY_HEALTH_GOOD;
 	return 0;
 }
 
@@ -611,47 +444,6 @@
 	return 0;
 }EXPORT_SYMBOL (sgm41513_charger_get_online);
 
-#if 0
-static int sgm41513_charger_get_current(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
-	int curr, ret;
-
-	ret = sgm41513_get_field_val(bdi, SGM41513_REG_ISC,
-			SGM41513_REG_ISC_ISET_DCIN_MASK, SGM41513_REG_ISC_ISET_DCIN_SHIFT,
-			sgm41513_in_ilimit_values,
-			ARRAY_SIZE(sgm41513_in_ilimit_values), &curr);
-	if (ret < 0)
-		return ret;
-
-	val->intval = curr;
-	return 0;
-}
-
-static int sgm41513_charger_get_current_max(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
-	int idx = ARRAY_SIZE(sgm41513_in_ilimit_values) - 1;
-
-	val->intval = sgm41513_in_ilimit_values[idx];
-	return 0;
-}
-
-static int sgm41513_charger_get_voltage(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
-#if 0
-	int voltage, ret;
-	ret = sgm41513_get_field_val(bdi, SGM41513_REG_CVC,
-			SGM41513_REG_CVC_VBAT_MASK, SGM41513_REG_CVC_VBAT_SHIFT,
-			sgm41513_cvc_vseta_values,
-			ARRAY_SIZE(sgm41513_cvc_vseta_values), &voltage);
-	if (ret < 0)
-		return ret;
-
-	val->intval = voltage;
-#endif
-return 0;
-}
-#endif
-
 static int sgm41513_charger_get_charger_enabled(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
 {
 	u8 charger_enabled;
@@ -702,16 +494,6 @@
 
 }
 
-#if 0
-static int sgm41513_charger_set_current(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
-{
-	return sgm41513_set_field_val(bdi, SGM41513_REG_ISC,
-			SGM41513_REG_ISC_ISET_DCIN_MASK, SGM41513_REG_ISC_ISET_DCIN_MASK,
-			sgm41513_in_ilimit_values,
-			ARRAY_SIZE(sgm41513_in_ilimit_values), val->intval);
-	
-}
-#endif
 static int sgm41513_charger_set_voltage(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
 {
 	int n;
@@ -719,22 +501,127 @@
 	if (val->intval == 4350)
 		n =15;
 	else
-		n = (val->intval - 3856) / 32;
+		n = (val->intval - 3856 + 15) / 32;
 	return sgm41513_write_mask(bdi, SGM41513_REG04,
 			SGM41513_REG04_VREG_MASK, SGM41513_REG04_VREG_SHIFT, n);
 }
 
-static int set_ce_gpio(int val)
+static int convert_iindpm_from_current(short curr_val)
 {
-	if (val > 0)
-	{
-		gpio_direction_output(120, 0);
-		ce_enabled = 1;
-	}
+	if (curr_val <= 100 )
+		return 0;
+	else if (curr_val >= 3200)
+		return 0x1f;
 	else
+		return (curr_val - 100) / 100;
+}
+
+static int convert_ichg_from_current(short curr_val)
+{
+	int reg_val;
+	if (curr_val < 0)
+		reg_val = -1;
+	else if (curr_val <= 40)
+		reg_val = curr_val / 5;
+	else if (curr_val <= 110)
+		reg_val = 0x08 + (curr_val - 40) / 10;	
+	else if (curr_val <= 270)
+		reg_val = 0x0F + (curr_val - 110) / 20;	
+	else if (curr_val <= 540)
+		reg_val = 0x17 + (curr_val - 270) / 30;	
+	else if (curr_val <= 1500)
+		reg_val = 0x20 + (curr_val - 540) / 60;	
+	else if (curr_val <= 2940)
+		reg_val = 0x30 + (curr_val - 1500) / 120;
+	else 
+		reg_val = 0x3d;
+	return reg_val;
+}
+
+static int convert_iprechg_iterm_from_current(short curr_val)
+{
+	int reg_val;
+	printk("cy: convert_iprechg_iterm_from_current1\n");
+	if (curr_val < 5)
+		reg_val = 0;
+	else if (curr_val <= 20)
+		reg_val = (curr_val - 5) / 5;
+	else if (curr_val <= 60)
+		reg_val = 0x3 + (curr_val - 20) / 10;
+	else if (curr_val <= 200)
+		reg_val = 0x7 + (curr_val - 60) / 20;
+	else
+		reg_val = 0xf;
+	printk("cy: convert_iprechg_iterm_from_current %d\n",reg_val);
+	return reg_val;
+}
+
+static struct sgm41513_charge_current_limit * get_current_temp_status(struct sgm41513_dev_info *bdi)
+{
+	int voltage, i;
+	struct sgm41513_charge_current_limit *p = NULL;
+	
+	voltage = get_adc2_voltage();
+	//voltage = 678; //tmp for test
+	pr_err("%s voltage %d\n",__func__, voltage);
+	for (i=0; i<bdi->pdata->temp_current_map_size; i++) 
 	{
-		gpio_direction_output(120, 1);
-		ce_enabled = 0;
+		p = &bdi->pdata->temp_current_map[i];
+		if ((p->temp_voltage_below == -1 && voltage >= p->temp_voltage_above)
+			|| (voltage < p->temp_voltage_below && voltage >= p->temp_voltage_above)
+			|| (p->temp_voltage_above == -1 && voltage < p->temp_voltage_below))
+		{
+			return p;
+		}
+	}
+	return NULL;
+}
+
+static void set_charge_current(struct sgm41513_dev_info *bdi)
+{
+	int ret, i;
+	u8 last_curr = -1;
+	u8 need_curr = -1;
+	union power_supply_propval val;
+	struct sgm41513_charge_current_limit *p = NULL;
+	
+	ret = sgm41513_read_mask(bdi,SGM41513_REG02,
+		SGM41513_REG02_ICHG_MASK,
+		SGM41513_REG02_ICHG_SHIFT,
+		&last_curr);
+
+	p = get_current_temp_status(bdi);
+	if (p == NULL)
+	{
+		dev_info(bdi->dev, "bad temperature range assigned\n");
+		return;
+	}
+
+	need_curr = convert_ichg_from_current(p->current_limit);
+	if (p->max_voltage != -1 && need_curr > 0)
+	{
+		val.intval = p->max_voltage;
+		sgm41513_charger_set_voltage(bdi, &val);
+	}
+
+	printk("cy: last_curr %d, need_curr %d\n",last_curr, need_curr);
+	if (need_curr != (u8)-1 && last_curr != need_curr)
+	{
+		ret = sgm41513_write_mask(bdi,SGM41513_REG02,
+			SGM41513_REG02_ICHG_MASK,
+			SGM41513_REG02_ICHG_SHIFT,
+			need_curr);
+		last_curr = need_curr;
+	}
+}
+
+static void re_schedule_charge_monitor_work(struct sgm41513_dev_info *bdi, bool re_count_down)
+{
+	if (!bdi->charge_monitor_work_running_flag || re_count_down)
+	{
+		cancel_delayed_work_sync(&bdi->charge_monitor_work);
+		schedule_delayed_work(&bdi->charge_monitor_work, HZ/2);
+		bdi->charge_monitor_work_running_flag = true;
 	}
 }
 
@@ -763,18 +650,34 @@
 
 	if (enable_charge.intval == 1)
 	{
+		set_charge_current(bdi);
 		ret = sgm41513_write_mask(bdi, SGM41513_REG00,
 			SGM41513_REG00_EN_HIZ_MASK, 
 			SGM41513_REG00_EN_HIZ_SHIFT, 0);
 	}
 
-	printk("cy: sgm41513_charger_set_charger_config 2\n");
-	 ret = sgm41513_write_mask(bdi, SGM41513_REG01,
+	ret = sgm41513_write_mask(bdi, SGM41513_REG01,
 			SGM41513_REG01_CHG_CONFIG_MASK,
 			SGM41513_REG01_CHG_CONFIG_SHIFT, enable_charge.intval );  /*0:disable 1:enable*/
 
-	 set_ce_gpio(enable_charge.intval);
-	 
+
+	bdi->current_charging_flag = POWER_SUPPLY_STATUS_UNKNOWN; // notify query
+
+	if (bdi->battery_online_flag && enable_charge.intval != 0)
+	{
+		set_ce_gpio(1);
+		re_schedule_charge_monitor_work(bdi, true);
+	}
+	else if (enable_charge.intval == 0)
+		set_ce_gpio(0);
+	else
+	{
+		printk("battery is not online\n");
+		ret = -1;
+	}
+	//set_charge_current(bdi);
+	//power_supply_changed(&bdi->charger);
+
 	 return ret;
 }
 
@@ -800,7 +703,8 @@
 	
 	case POWER_SUPPLY_PROP_STATUS:
 		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_STATUS\n");
-		ret = sgm41513_charger_get_status(bdi, val);
+		ret = sgm41513_charger_get_status(bdi, val, true);
+		bdi->last_reported_charging_flag = val->intval;
 		break;
 	case POWER_SUPPLY_PROP_HEALTH:
 		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_HEALTH\n");
@@ -881,15 +785,32 @@
 	case POWER_SUPPLY_PROP_PD_ACTIVE:
 		printk("cy: POWER_SUPPLY_PROP_PD_ACTIVE %d\n", val->intval);
 		break;
-    	case POWER_SUPPLY_PROP_CHARGE_ENABLED:
-		printk("cy: POWER_SUPPLY_PROP_CHARGE_ENABLED\n");
-        	ret = sgm41513_charger_set_charger_config(bdi, val);			
-		power_supply_changed(&bdi->charger);
+    case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+		printk("cy: POWER_SUPPLY_PROP_CHARGE_ENABLED val %d, dcin %d\n", val->intval, bdi->dcin_5v_pulgin_flag);
+		if (val->intval == 0 || bdi->dcin_5v_pulgin_flag)
+        	ret = sgm41513_charger_set_charger_config(bdi, val);
         	break;
 	case POWER_SUPPLY_PROP_USB_OTG:
-		printk("cy: POWER_SUPPLY_PROP_USB_OTG\n");
-		ret = sgm41513_write_mask(bdi,SGM41513_REG01,
-			SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
+		printk("cy: POWER_SUPPLY_PROP_USB_OTG val %d, dcin %d\n", val->intval, bdi->dcin_5v_pulgin_flag);
+		if (val->intval != 0 && bdi->dcin_5v_pulgin_flag)
+		{
+			ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+				SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,0);
+			gpio_direction_output(OUT_5V_GPIO, 1);
+		}
+		else if (val->intval != 0)
+		{
+			ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+				SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,1);
+			gpio_direction_output(OUT_5V_GPIO, 0);
+
+		}
+		else  // val->intval == 0
+		{
+			ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+				SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,0);
+			gpio_direction_output(OUT_5V_GPIO, 0);
+		}
 		break;
 	default:
 		printk("cy: unkown\n");
@@ -955,69 +876,37 @@
 
 static int sgm41513_battery_get_health(struct sgm41513_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;
+	struct sgm41513_charge_current_limit *p;
+	p = get_current_temp_status(bdi);
+	if (p == NULL)
+	{
+		return -1;
 	}
-
-	if (bdi->battery_health_valid) {
-		v = bdi->reg09;
-		bdi->battery_health_valid = false;
-	} else {
-
-		ret = sgm41513_read(bdi, SGM41513_REG09, &v);
-		if (ret < 0){	
-
-			mutex_unlock(&bdi->bs_reg_lock);
-			return ret;
-		}
-	}
-
-	if (v & SGM41513_REG09_BAT_FAULT_MASK) {
-		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-	} else {
-		v &= SGM41513_REG09_NTC_FAULT_MASK;
-		v >>= SGM41513_REG09_NTC_FAULT_SHIFT;
-
-		switch (v) {
-		case 0: /* Normal */
-			health = POWER_SUPPLY_HEALTH_GOOD;
-			break;
-		case 2: /* warm*/		
-			health = POWER_SUPPLY_HEALTH_WARM;
-			break;
-		case 6: /* Hot */		
-			health = POWER_SUPPLY_HEALTH_OVERHEAT;
-			break;
-		case 3:/* Cool*/
-			health = POWER_SUPPLY_HEALTH_COOL;
-			break;			
-		case 5: /* Cold */
-			health = POWER_SUPPLY_HEALTH_COLD;
-			break;
-		default:
-			health = POWER_SUPPLY_HEALTH_UNKNOWN;
-		}
-	}
-
-	val->intval = health;
-	mutex_unlock(&bdi->bs_reg_lock);
+	val->intval = p->temp_grade;
 	return 0;
 }
 
 static int sgm41513_battery_get_online(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
 {
-	int ret;
-
-	ret = get_adc2_voltage();
-	printk("cy adc2 voltage %d\n", ret);
-	val->intval = (ret <= 1700);
+	
+	struct sgm41513_charge_current_limit *p;
+	p = get_current_temp_status(bdi);
+	if (p == NULL)
+	{
+		return -1;
+	}
+	if (p->temp_grade == POWER_SUPPLY_HEALTH_UNKNOWN &&  get_adc1_voltage() < 100 )
+	{
+		if (val != NULL)
+			val->intval = 0;
+		bdi->battery_online_flag = false;
+	}
+	else
+	{
+		if (val != NULL)
+			val->intval = 1;
+		bdi->battery_online_flag = true;
+	}
 	return 0;
 }
 
@@ -1104,8 +993,8 @@
 		break;
 
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		//#ifdef CONFIG_ZX234290_ADC						
-		val->intval = get_adc1_voltage() - 15;
+		//#ifdef CONFIG_ZX234290_ADC
+		val->intval = sgm41513_get_real_voltage();
 		ret = 0;
 		break;
 #if 1
@@ -1211,13 +1100,25 @@
 {	
 	int ret;
 	printk("cy: sgm41513_boost_set_charge_enable\n");
-	//set_typec_try_role(2);
 	ret = sgm41513_write_mask(bdi,SGM41513_REG01,
 		SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
 
 	return ret;
 }
 
+static int sgm41513_boost_get_charge_enable(struct sgm41513_dev_info *bdi, union power_supply_propval *val)
+{
+	u8 v;
+	int ret;
+	ret = sgm41513_read_mask(bdi,SGM41513_REG01,
+		SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,&v);
+	
+	if (ret == 0)
+		val->intval = v;
+
+	return ret;
+}
+
 static int sgm41513_boost_set_current_now(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
 {
 	return  0;
@@ -1241,6 +1142,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		ret = sgm41513_boost_get_current_now(bdi, val);
         break;
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+		ret = sgm41513_boost_get_charge_enable(bdi, val);
+		break;
 	#if 0
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		ret = sgm41513_boost_get_current_max(bdi, val);
@@ -1385,72 +1289,6 @@
 	func_trace();
 }
 
-/*
-		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 sgm41513_charger_config_groupB_Regs(struct sgm41513_dev_info *bdi)
-{
-	int ret;
-	return 0;//@todo cy add
-
-#if 0
-	/*set VINDPM to 4.52V*/
-	ret = sgm41513_write_mask(bdi,SGM41513_REG_ISC,
-				   SGM41513_REG_ISC_VINDPM_MASK,
-				   SGM41513_REG_ISC_VINDPM_SHIFT,
-				   0x8);
-	/*set VSETA to 4.2V*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_CVC,
-				   SGM41513_REG_CVC_VBAT_MASK,
-				   SGM41513_REG_CVC_VBAT_SHIFT,
-				   0x2);
-
-	/*disable the timer*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
-				   SGM41513_REG_CTC_EN_TIMER_MASK,
-				   SGM41513_REG_CTC_EN_TIMER_SHIFT,
-				   0x0);
-	/*disable the 2*timer*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
-				   SGM41513_REG_CTC_EN_2XTIMER_MASK,
-				   SGM41513_REG_CTC_EN_2XTIMER_SHIFT,
-				   0x0);
-	/*set CVCOMP to 20mV*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_CTC,
-				   SGM41513_REG_CTC_CVCOMP_MASK,
-				   SGM41513_REG_CTC_CVCOMP_SHIFT,
-				   0x4);
-
-
-	/*disable the JETTA*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_THR,
-					SGM41513_REG_THR_EN_JEITA_MASK,
-					SGM41513_REG_THR_EN_JEITA_SHIFT,
-					0x0);
-
-	/*set the temprator   cool */
-	/*00:0	01:5  10:10  11:15*/
-	ret += sgm41513_write_mask(bdi,SGM41513_REG_TS,
-					SGM41513_REG_TS_COOL_MASK,
-					SGM41513_REG_TS_COOL_SHIFT,
-					0x0);
-
-	if (ret < 0){
-		goto out;
-	}
-
-	return 0;
-
-	out:
-		//pm_runtime_put_sync(bdi->dev);
-		dev_err(bdi->dev, "sgm41513_charger_groupB_config ERROR: %d\n", ret);
-		return ret;
-
-#endif
-}
-
 static int sgm41513_hw_init(struct sgm41513_dev_info *bdi)
 {
 	u8 v;
@@ -1468,16 +1306,37 @@
 	//zx29_gpio_output_data(ZX29_GPIO_51, 1);
 #endif 
 	//pm_runtime_get_sync(bdi->dev);
-	
+
+	set_ce_gpio(0);
+
 	ret = sgm41513_write_mask(bdi,SGM41513_REG0B,
 		SGM41513_REG0B_REGRST_MASK,
 		SGM41513_REG0B_REGRST_SHIFT,
 		0x1);
 	if (ret < 0){
-		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		pr_err("soft rest fail! line %d ret %d\n", __LINE__, ret);
 		goto out;
 	}
-	pr_err("cy: line %d ret %d\n", __LINE__, ret);
+	for (i=0;i<1000;i++)
+	{
+		udelay(100);
+		ret = sgm41513_read_mask(bdi,SGM41513_REG0B,
+			SGM41513_REG0B_REGRST_MASK,
+			SGM41513_REG0B_REGRST_SHIFT,
+			&v);
+		if (ret == 0 && v == 0)
+			break;
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+		SGM41513_REG00_IINDPM_MASK,
+		SGM41513_REG00_IINDPM_SHIFT,
+		convert_iindpm_from_current(bdi->pdata->max_input_current));
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG06,
+		SGM41513_REG06_OVP_MASK,
+		SGM41513_REG06_OVP_SHIFT,
+		0x1);
 
 /*
 	ret = sgm41513_write_mask(bdi,SGM41513_REG06,
@@ -1499,10 +1358,17 @@
 	ret = sgm41513_write_mask(bdi,SGM41513_REG03,
 		SGM41513_REG03_ITERM_MASK,
 		SGM41513_REG03_ITERM_SHIFT,
-		0xd);
+		convert_iprechg_iterm_from_current(bdi->pdata->terminate_charge_current)); 
 	if (ret < 0){
-		pr_err("cy: line %d ret %d\n", __LINE__, ret);
-		//goto out;
+		pr_err("set iterm fail, line %d ret %d\n", __LINE__, ret);
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG03,
+		SGM41513_REG03_IPRECHG_MASK,
+		SGM41513_REG03_IPRECHG_SHIFT,
+		convert_iprechg_iterm_from_current(bdi->pdata->pre_charge_current)); 
+	if (ret < 0){
+		pr_err("set iprechg fail, line %d ret %d\n", __LINE__, ret);
 	}
 
 	dump_sgm_regs(bdi->client);
@@ -1513,10 +1379,10 @@
 			SGM41513_REG0B_PN_MASK,
 			SGM41513_REG0B_PN_SHIFT,
 			&v);
-	
+
 	if (ret < 0){
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
-	    	goto out;
+	    goto out;
 	}
 
 	printk(KERN_INFO "sgm41513_hw_init:sgm41513-charger version reg: 0x%x\n", v);
@@ -1525,13 +1391,8 @@
 	if (ret < 0){
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
 	}
-	/*
-	if (v != bdi->model) {
-		ret = -ENODEV;
-		goto out;
-	}
-	*/
-	voltage_val.intval = 4400;
+
+	voltage_val.intval = bdi->pdata->max_charge_voltage;
 	ret = sgm41513_charger_set_voltage(bdi,&voltage_val);
 	if (ret < 0){
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
@@ -1547,16 +1408,16 @@
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
 		goto out;
 	}
-	
+
 	ret = sgm41513_write_mask(bdi,SGM41513_REG02,
 		SGM41513_REG02_BOOST_LIM_MASK,
 		SGM41513_REG02_BOOST_LIM_SHIFT,
-		0x1);
+		0x0);
 	if (ret < 0){
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
 		goto out;
 	}
-	
+
 	ret = sgm41513_write_mask(bdi,SGM41513_REG02,
 		SGM41513_REG02_ICHG_MASK,
 		SGM41513_REG02_ICHG_SHIFT,
@@ -1565,13 +1426,13 @@
 		pr_err("cy: line %d ret %d\n", __LINE__, ret);
 		goto out;
 	}
-	
+
 	dump_sgm_regs(bdi->client);
-	printk("cy: get_adc1_voltage %d\n", ret);
 	voltage = get_adc1_voltage();
-	//*
-	if (voltage < 3800) {
-		set_typec_try_role(0); // try dongle
+	printk("cy: get_adc1_voltage %d\n", voltage);
+	/*
+	if (voltage < red_voltage_level) {
+		set_typec_try_role(1); // try dongle
 	} else {
 		set_typec_try_role(1);
 	}
@@ -1590,7 +1451,6 @@
 	return ret;
 }
 
-
 static irqreturn_t sgm41513_charger_irq_primary_handler(int irq, struct sgm41513_dev_info *bdi)
 {
 	func_trace();
@@ -1603,14 +1463,149 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t dcin_5v_irq_primary_thread(int irq, struct sgm41513_dev_info *bdi)
+{
+	int value, out_5v_value;
+	union power_supply_propval enable_charge;
+	zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_GPIO);
+	gpio_direction_input(DCIN_5V_GPIO);
+	value = gpio_get_value(DCIN_5V_GPIO);
+	bdi->dcin_5v_pulgin_flag = (value == CHG_PLUG_IN);
+	
+	if (bdi->dcin_5v_pulgin_flag)
+	{
+		enable_charge.intval = 1;
+	}
+	else
+	{
+		enable_charge.intval = 0;
+	}
+
+	sgm41513_charger_set_charger_config(bdi, &enable_charge);
+
+	if (bdi->dcin_5v_pulgin_flag) 
+	{
+		set_typec_try_role(2);
+	}
+	else
+	{
+		set_typec_try_role(0);
+	}
+	
+	zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_EXT_INT);
+	if(value == 1)
+	{
+	  zx29_gpio_set_inttype(DCIN_5V_GPIO,IRQ_TYPE_EDGE_FALLING);
+	  pcu_int_clear(DCIN_5V_DT_INT);
+	}
+	else
+	{
+	  zx29_gpio_set_inttype(DCIN_5V_GPIO,IRQ_TYPE_EDGE_RISING);
+	  pcu_int_clear(DCIN_5V_DT_INT);
+	}
+	printk(KERN_INFO"%s,value:%d,end\n", __func__,value);
+	return IRQ_HANDLED;
+}
+
+#define MAX_PLUG_IN_OUT_CHECK_CNT 6
+
+extern int check_typec_role(void);
+void sgm41513_notify_usb_detect(int stage)
+{
+	//printk("cy: sgm41513_notify_usb_detect stage %d, usb_detect_flag %d, dwc_otg_chg_inform_status %d\n", stage, g_bdi->usb_detect_flag, g_bdi->dwc_otg_chg_inform_status);
+	mutex_lock(&g_bdi->bs_reg_lock);
+	if ((stage == 0 || stage == 4) && g_bdi->dwc_otg_chg_inform_status == 1)
+	{
+		g_bdi->dwc_otg_chg_inform_status = 2; // todo otg chg inform
+		//dwc_otg_chg_inform(0);
+		g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+		g_bdi->usb_detect_flag = USB_STATUS_DETECTING;
+		mutex_unlock(&g_bdi->bs_reg_lock);
+		re_schedule_charge_monitor_work(g_bdi, false);
+		return;
+	}
+	else if (stage == 0)
+	{
+		if (g_bdi->usb_detect_flag == USB_STATUS_UNKOWN || g_bdi->usb_detect_flag == USB_STATUS_DISCONNECTED)
+		{
+			g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+			g_bdi->usb_detect_flag = USB_STATUS_DETECTING;
+			mutex_unlock(&g_bdi->bs_reg_lock);
+			re_schedule_charge_monitor_work(g_bdi, false);
+			return;
+		}
+	}
+	else if (stage == 1)
+	{
+		//mutex_unlock(&g_bdi->bs_reg_lock);
+		//dwc_otg_chg_inform(1); //tmp add to fix not recongnize usb plugin since force usb
+		//dwc_otg_chg_inform(0);
+		//mutex_lock(&g_bdi->bs_reg_lock);
+		g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+		g_bdi->can_switch_role_flag = true;
+		g_bdi->usb_plug_in_out_check_cnt = 0;
+		g_bdi->power_role_switch_only = false;
+	}
+	else if (stage == 2)
+	{
+		g_bdi->usb_plug_in_out_check_cnt = 1;
+		g_bdi->usb_detect_flag = USB_STATUS_DISCONNECTING;
+		g_bdi->can_switch_role_flag = false;
+		g_bdi->discharging_flag = false;
+		g_bdi->power_role_switch_only = false;
+		mutex_unlock(&g_bdi->bs_reg_lock);
+		re_schedule_charge_monitor_work(g_bdi, true);
+		return;
+	}
+	else if (stage == 3)
+	{
+		//mutex_unlock(&g_bdi->bs_reg_lock);
+		//dwc_otg_chg_inform(1); //tmp add to fix not recongnize usb plugin since force usb
+		//dwc_otg_chg_inform(0);
+		//mutex_lock(&g_bdi->bs_reg_lock);
+		g_bdi->discharging_flag = true;
+		g_bdi->can_switch_role_flag = false;
+		g_bdi->power_role_switch_only = false;
+		g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+	}
+	else if (stage == 4) //dwc_otg_chg_inform_status == 0
+	{
+		g_bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+		g_bdi->power_role_switch_only = true;
+		mutex_unlock(&g_bdi->bs_reg_lock);
+		re_schedule_charge_monitor_work(g_bdi, false);
+		return;
+	}
+	else
+	{
+		printk("cy: unkown stage %d\n", stage);
+	}
+	mutex_unlock(&g_bdi->bs_reg_lock);
+}
+
+bool sgm41513_can_power_switch(void)
+{
+	bool ret = true;
+	/*
+	mutex_lock(&g_bdi->bs_reg_lock);
+	ret = g_bdi->can_switch_role_flag;
+	mutex_unlock(&g_bdi->bs_reg_lock);
+	*/
+	if (g_bdi->charger.type == POWER_SUPPLY_PCAC__AC)
+		ret = false;
+	return ret;
+}
+
 static irqreturn_t sgm41513_irq_handler_thread(void *data)
 {
 	struct sgm41513_dev_info *bdi = data;
 	bool charger_changed_flag = false;
 	bool battery_changed_flag = false;
 	bool boost_changed_flag = false;
-	int ret;
-	u8 ms;
+	int ret, i, required_iindpm, last_charge_state;
+	u8 reg08, reg0a, reg0e, chrg_stat;
+	bool vbus_gd_flag, usb_in_flag, usb_host_flag, last_vbus_gd_flag, last_usb_in_flag, last_usb_host_flag;
+	bool no_cc_usb_plugin_check, no_cc_usb_plugout_check;
 	struct sched_param param = { .sched_priority = 2 };
 	param.sched_priority= 31;
 	func_trace();
@@ -1621,30 +1616,143 @@
 		down(&bdi->chgirq_sem);
 		//pm_runtime_get_sync(bdi->dev);
 		mutex_lock(&bdi->bs_reg_lock);
+		bdi->pre_reg08=bdi->reg08;
 		bdi->pre_reg09=bdi->reg09;
 		bdi->pis_pre_reg=bdi->pis_curr_reg;
 		bdi->cfis_pre_reg = bdi->cfis_curr_reg;
+		charger_changed_flag = false;
+		battery_changed_flag = false;
+		boost_changed_flag = false;
 		
 		//printk(KERN_INFO"sgm41513_irq_handler_thread\n");
 		
-		
-#if 0
-		ret = sgm41513_read(bdi, SGM41513_REG_MS, &ms);
+		ret = sgm41513_read(bdi, SGM41513_REG0A, &reg0a);
 		if (ret < 0) {		
-			dev_err(bdi->dev, "Can't read MS reg: %d\n", ret);
-			mutex_unlock(&bdi->bs_reg_lock);
-			goto out;
-		}
-		//printk("sgm41513 MS reg is %d",ms);
-		
-		ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &bdi->cbis_curr_reg);
-		if (ret < 0) {		
-			dev_err(bdi->dev, "Can't read CBIS reg: %d\n", ret);
+			dev_err(bdi->dev, "Can't read 0a reg: %d\n", ret);
 			mutex_unlock(&bdi->bs_reg_lock);
 			goto out;
 		}
 
-		
+		ret = sgm41513_read(bdi, SGM41513_REG08, &reg08);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read 08 reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		last_vbus_gd_flag = vbus_gd_flag = (reg0a & SGM41513_REG0A_VBUS_GD_MASK) != 0;
+		last_usb_in_flag = usb_in_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) != 0;
+		last_usb_host_flag = usb_host_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) == (0x7 << SGM41513_REG08_VBUS_STAT_SHIFT);
+
+		no_cc_usb_plugin_check = (usb_host_flag == 0 && vbus_gd_flag != 0  && !bdi->dcin_5v_pulgin_flag && bdi->usb_detect_flag == USB_STATUS_DISCONNECTED); 
+		no_cc_usb_plugout_check = (usb_host_flag == 0 && vbus_gd_flag == 0  && !bdi->dcin_5v_pulgin_flag && bdi->usb_detect_flag == USB_STATUS_CONNECTED );
+
+		//*
+		printk("cy: usb_host_flag: %d, vbus_gd_flag: %d, ce_enabled %d, no_cc_usb_plugin_check %d, no_cc_usb_plugout_check %d\n",
+		usb_host_flag, vbus_gd_flag, ce_enabled, 
+		no_cc_usb_plugin_check, no_cc_usb_plugout_check);
+		printk("cy: dcin state %d\n", bdi->dcin_5v_pulgin_flag);
+		//printk("cy: reg 08: %d, reg 0a: %d\n", reg08, reg0a);
+		//*/
+		if (no_cc_usb_plugin_check ||no_cc_usb_plugout_check ) 
+		{
+			for(i=0;i<5;i++)
+			{
+				mutex_unlock(&bdi->bs_reg_lock);
+				msleep(20);
+				mutex_lock(&bdi->bs_reg_lock);
+				if (bdi->dcin_5v_pulgin_flag)
+					break;
+				ret = sgm41513_read(bdi, SGM41513_REG08, &reg08);
+				if (ret < 0) {		
+					dev_err(bdi->dev, "Can't read 08 reg: %d\n", ret);
+					mutex_unlock(&bdi->bs_reg_lock);
+					goto out;
+				}
+				vbus_gd_flag = (reg0a & SGM41513_REG0A_VBUS_GD_MASK) != 0;
+				usb_in_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) != 0;
+				usb_host_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) == (0x7 << SGM41513_REG08_VBUS_STAT_SHIFT);
+				printk("cy: dcin state %d\n", bdi->dcin_5v_pulgin_flag);
+				if (vbus_gd_flag !=0 || usb_in_flag !=0 || usb_host_flag != 0)
+				{
+					if (bdi->usb_detect_flag == USB_STATUS_UNKOWN)
+					{
+						bdi->usb_detect_flag = USB_STATUS_DETECTING;						
+						bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+					}
+
+					if (bdi->dwc_otg_chg_inform_status == 1)
+					{
+						bdi->dwc_otg_chg_inform_status = 2;
+						re_schedule_charge_monitor_work(bdi, false);
+					}
+				}
+				if (last_vbus_gd_flag != vbus_gd_flag || last_usb_host_flag != usb_host_flag)
+				{
+					break;
+				}
+			}
+			if (!bdi->dcin_5v_pulgin_flag && i >= 5) 
+			{
+				if (no_cc_usb_plugin_check)
+				{
+					if (bdi->usb_detect_flag == USB_STATUS_DISCONNECTED)
+					{
+						bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+						//bdi->usb_plug_in_out_check_cnt = MAX_PLUG_IN_OUT_CHECK_CNT;
+					}
+				}
+				else if (no_cc_usb_plugout_check) 
+				{
+					mutex_unlock(&bdi->bs_reg_lock);
+					if (bdi->usb_detect_flag == USB_STATUS_CONNECTED)
+					{
+						bdi->usb_detect_flag = USB_STATUS_DISCONNECTING;
+						bdi->usb_plug_in_out_check_cnt = 1;
+						re_schedule_charge_monitor_work(bdi, true);
+					}
+					mutex_lock(&bdi->bs_reg_lock);
+				}
+				else
+				{
+					printk("cy: usb check again %d\n", __LINE__);
+				}
+			}
+		}
+
+		bdi->reg08 = reg08;
+
+		last_charge_state = bdi->current_charging_flag;
+		if (bdi->during_voltage_query_flag != 2)
+		{
+			bdi->current_charging_flag = convert_charger_status(reg08);
+		}
+
+		if (bdi->dcin_5v_pulgin_flag && bdi->current_charging_flag == POWER_SUPPLY_STATUS_CHARGING && bdi->current_charging_flag != last_charge_state)
+		{
+			required_iindpm = convert_iindpm_from_current(bdi->pdata->max_input_current);
+			ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+						SGM41513_REG00_IINDPM_MASK,
+						SGM41513_REG00_IINDPM_SHIFT,
+						required_iindpm);
+		}
+
+		ret = sgm41513_read(bdi, SGM41513_REG09, &bdi->reg09);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read 09 reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		ret = sgm41513_read(bdi, SGM41513_REG0E, &reg0e);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read 0E reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+
+#if 0		
 		ret = sgm41513_read(bdi, SGM41513_REG_PIS, &bdi->pis_curr_reg);
 		if (ret < 0) {
 			dev_err(bdi->dev, "Can't read PIS reg: %d\n", ret);
@@ -1763,6 +1871,8 @@
 		bdi->battery_health_valid = true;/****?***/
 		bdi->battery_status_valid = true;/****?***/
 
+		
+#endif
 		mutex_unlock(&bdi->bs_reg_lock);
 
 		/*
@@ -1790,12 +1900,11 @@
 
 	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);
+		//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);
-#endif
+		//printk(KERN_INFO"cy: sgm41513_irq_handler_thread loop again, charger_changed_flag %d\n", charger_changed_flag);
 	}
 	func_trace();
 	return 0;
@@ -1837,7 +1946,7 @@
 	}
 
 	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);
+	zx29_gpio_pd_pu_set(pdata->gpio_int, IO_CFG_PULL_UP/*IO_CFG_PULL_DISABLE*/);
 
 	bdi->gpio_int = pdata->gpio_int;
 	//pcu_int_clear(bdi->irq);
@@ -1952,76 +2061,27 @@
 
 }
 
-static T_TYPE_USB_DETECT g_chg_type = 0;
 void sgm41513_charge_typedet(T_TYPE_USB_DETECT chg_type)
 {
 	int ret;
-	union power_supply_propval val = {.intval = 0};
+	u8 vubs_flag;
 	#ifdef DBG_CHARGE
 	printk(KERN_INFO"charge type is %d in\n",chg_type);
 	#endif
 	func_trace();
-	g_chg_type  = chg_type;
+	g_bdi->usb_detect_flag = USB_STATUS_CONNECTED;
+	g_bdi->usb_plug_in_out_check_cnt = 0;
 #if 1
 	if(TYPE_ADAPTER == chg_type){
 		
 		printk(KERN_INFO"chg type is TYPE_ADAPTER\n");
-		//gpio_direction_output(120, 0);
-		//ce_enabled = 1;
-		val.intval = 1;
-		 /*set the DCIN Current = 2.4A*/
-		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
-					   SGM41513_REG00_IINDPM_MASK,
-					   SGM41513_REG00_IINDPM_SHIFT,
-					   0x17);
-		if (ret < 0){
-			printk(KERN_INFO"write REG_00 fault\n");
-		}
+		//set_typec_try_role(0);
 		g_bdi->charger.type = POWER_SUPPLY_PCAC__AC;
-		dump_sgm_regs(g_bdi->client);
-		sgm41513_charger_set_charger_config(g_bdi, &val);
 	}
-	
-	else {
-		//ret = get_typec_role();
-		//printk(KERN_INFO"chgage type is TYPE_PC %d\n", ret);
-		gpio_direction_output(120, 1);
-		ce_enabled = 0;
-		
-		 /*set the DCIN Current = 450mA*/
-		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
-					   SGM41513_REG00_IINDPM_MASK,
-					   SGM41513_REG00_IINDPM_SHIFT,
-					   0x4);
-		if (ret < 0){
-			printk(KERN_INFO"write REG_01 fault\n");
-		}
-
-		/*
-		voltage = get_adc1_voltage();
-		if (voltage > 3500) {
-			ret = sgm41513_write_mask(bdi,SGM41513_REG00, SGM41513_REG00_EN_HIZ_MASK, 
-				SGM41513_REG00_EN_HIZ_SHIFT, 0x1);
-		}
-		*/
+	else if (TYPE_COMPUTER == chg_type) {
 		g_bdi->charger.type = POWER_SUPPLY_PCAC__PC;
-		dump_sgm_regs(g_bdi->client);
+		//set_typec_try_role(0);
 	}
-		
-		//#ifdef CONFIG_CHARGER_SGM41513_EVB
-#if 0
-		 /*set the DCIN Current = 2A*/
-		ret = sgm41513_write_mask(g_bdi,SGM41513_REG_ISC,
-					   SGM41513_REG_ISC_ISET_DCIN_MASK,
-					   SGM41513_REG_ISC_ISET_DCIN_SHIFT,
-					   0x5);
-		if (ret < 0){
-			printk(KERN_INFO"write REG_01 fault\n");
-		}
-		#endif
-
-		
-
 #endif
 }
 
@@ -2207,10 +2267,11 @@
 	int ret = 0;
 	struct sgm41513_dev_info * bdi = NULL;
 	struct delayed_work *charge_monitor_work = NULL;
-	union power_supply_propval val = {.intval = 4100};
+	union power_supply_propval val = {.intval = 0};
 	//static u8 last_chg_method = 0;
-	u8 last_curr = -1;
-	u8 need_curr = -1;
+	u8 vbus_stat = -1;
+	int next_run_wait_time = 10 * HZ;
+	bool need_change_typec_role = false;
 
 	charge_monitor_work = container_of(work, struct delayed_work, work);
 	if(charge_monitor_work == NULL) {
@@ -2222,44 +2283,73 @@
 		pr_err("Cann't get sgm \n");
 		return ;
 	}
-	
-	ret = sgm41513_read_mask(bdi,SGM41513_REG02,
-		SGM41513_REG02_ICHG_MASK,
-		SGM41513_REG02_ICHG_SHIFT,
-		&last_curr);
 
-	ret = get_adc2_voltage();
-	pr_err("%s voltage %d\n",__func__, ret);
-	if (ret >1284 || ret < 422){ // bellow 0 deg or above 60 deg, curr set to 0
-		need_curr = 0x0;
-		printk("cy: need 0\n");
-	} else if (ret > 1057) { // above 0 deg and bellow 15 deg, curr set to 500mA
-		need_curr = 0x1f;
-		printk("cy: need 1f\n");
-	} else if (ret > 623 && ret <= 1057) { // above 15 deg and bellow 45 dec, curr set to 2A
-		need_curr = 0x34;
-		printk("cy: need 34\n");
-	} else if (ret >= 422 && ret <= 623) { // above 45 deg and bellow 60 dec, curr set to 1A, max vol set to 4.1V
-		need_curr = 0x27;
-		printk("cy: need 27\n");
-		sgm41513_charger_set_voltage(bdi, &val);
-	}
-	else {
-		need_curr = -1;
-		printk("cy: unkown condition\n");
-	}
-	printk("cy: last_curr %d, need_curr %d\n",last_curr, need_curr);
-	if (need_curr != -1 && last_curr != need_curr)
+	if (bdi->dwc_otg_chg_inform_status == 2)
 	{
-		ret = sgm41513_write_mask(bdi,SGM41513_REG02,
-			SGM41513_REG02_ICHG_MASK,
-			SGM41513_REG02_ICHG_SHIFT,
-			need_curr);
-		last_curr = need_curr;
+		dwc_otg_chg_inform(0);
+		bdi->dwc_otg_chg_inform_status = 0;
 	}
+
+	if (ce_enabled == 1)
+	{
+		//dump_sgm_regs(bdi->client);
+		//return;
+		set_charge_current(bdi);
+	}
+
+	/*
+	printk("cy: charger_monitor_work_func ce_enabled %d, usb_plug_in_out_check_cnt %d, usb_detect_flag %d, discharging_flag %d \n",
+			ce_enabled, bdi->usb_plug_in_out_check_cnt, bdi->usb_detect_flag, bdi->discharging_flag);
+	*/
+	mutex_lock(&bdi->bs_reg_lock);
+	if (bdi->usb_plug_in_out_check_cnt > 0)
+	{
+		bdi->usb_plug_in_out_check_cnt --;
+		if (bdi->usb_plug_in_out_check_cnt <=0 && g_bdi->power_role_switch_only)
+		{
+			need_change_typec_role = true;
+			g_bdi->power_role_switch_only = false;
+		}
+		else if (bdi->usb_plug_in_out_check_cnt <=0 &&!bdi->discharging_flag && (bdi->usb_detect_flag != USB_STATUS_DISCONNECTED && bdi->usb_detect_flag != USB_STATUS_CONNECTED))
+		{
+			printk("cy: usb disconnect\n");
+			bdi->usb_detect_flag = USB_STATUS_DISCONNECTED;
+			bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+			dwc_otg_chg_inform(1);
+			bdi->dwc_otg_chg_inform_status = 1;
+			//check_typec_role();
+			need_change_typec_role = true;
+		}
+		next_run_wait_time = HZ/2;
+	}
+	mutex_unlock(&bdi->bs_reg_lock);
+	if (need_change_typec_role)
+	{
+		//check_typec_role();
+	}
+
+	if(bdi->usb_plug_in_out_check_cnt <= 0 && (!bdi->during_voltage_query_flag && ce_enabled == 0) && 
+		bdi->current_charging_flag ==  bdi->last_reported_charging_flag)
+	{
+		bdi->charge_monitor_work_running_flag = false;
+		return;
+	}
+	else if (bdi->current_charging_flag != bdi->last_reported_charging_flag || bdi->during_voltage_query_flag == 1)
+	{
+		sgm41513_charger_get_status(bdi, &val, false);
+		bdi->current_charging_flag = val.intval;
+		bdi->during_voltage_query_flag = 0;
+		if (bdi->current_charging_flag != bdi->last_reported_charging_flag)
+		{
+			power_supply_changed(&bdi->charger);
+		}
+		next_run_wait_time = HZ/2;
+	}
+
 	dump_sgm_regs(bdi->client);
 OUT:	
-	schedule_delayed_work(&bdi->charge_monitor_work, 10*HZ);
+	bdi->charge_monitor_work_running_flag = true;
+	schedule_delayed_work(&bdi->charge_monitor_work, next_run_wait_time);
 }
 
 static int sgm41513_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -2271,15 +2361,15 @@
 	int ret;
 	int i;  /*when err try 3 times*/
 	u8 v;
-	//use for other 
-	//g_platform_data= client->dev.platform_data;
 
 	printk(KERN_INFO "charger probe.\n");
 
-	//zx29_gpio_set_direction(120,GPIO_OUT);
-	//zx29_gpio_output_data(120,1);
-	//ret = gpio_direction_output(120, 0);
-        //printk("cy: set derection %d\n", ret);
+	set_ce_gpio(0); //make sure ce status ok
+
+	gpio_direction_output(OUT_5V_GPIO, 0);
+
+	zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_GPIO);
+	gpio_direction_input(DCIN_5V_GPIO);
 
 	dump_sgm_regs(client);
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -2292,6 +2382,7 @@
 		dev_err(dev, "Can't alloc bdi struct\n");
 		return -ENOMEM;
 	}
+	bdi->dcin_5v_pulgin_flag = (gpio_get_value(DCIN_5V_GPIO) == CHG_PLUG_IN);
 	bdi->pdata = pdata;
 	bdi->client = client;
 	bdi->dev = dev;
@@ -2299,23 +2390,33 @@
 	strncpy(bdi->model_name, id->name, sizeof(bdi->model_name)-1);
 	mutex_init(&bdi->bs_reg_lock);
 	bdi->first_time = true;
+	bdi->current_charging_flag = POWER_SUPPLY_STATUS_UNKNOWN;
+	bdi->last_reported_charging_flag = -1; //force to report once
+	bdi->during_voltage_query_flag = 0;
+	bdi->discharging_flag = false;
+	bdi->charge_monitor_work_running_flag = false;
+	bdi->battery_online_flag = false;
+	bdi->usb_detect_flag = USB_STATUS_UNKOWN;
+	bdi->dwc_otg_chg_inform_status = 1;
+	bdi->can_switch_role_flag = false;
 	bdi->charger_health_valid = false;
 	bdi->battery_health_valid = false;
 	bdi->battery_status_valid = false;
+	bdi->usb_plug_in_out_check_cnt = 0;
 
 	g_bdi = bdi;
 
 	i2c_set_clientdata(client, bdi);
 
-	if (dev->of_node)
-		ret = 0;//sgm41513_setup_dt(bdi);
-	else
-		ret = sgm41513_setup_pdata(bdi, pdata);
+	ret = sgm41513_setup_pdata(bdi, pdata);
 
 	if (ret) {
 		dev_err(dev, "Can't get irq info\n");
 		return -EINVAL;
 	}
+
+	sgm41513_battery_get_online(bdi, NULL);
+
 #ifdef DBG_CHARGE
 	printk(KERN_INFO "hwinit.\n");
 #endif
@@ -2336,22 +2437,6 @@
 #ifdef DBG_CHARGE
 	printk(KERN_INFO "sgm41513_probe sgm41513_hw_init ok.\n");
 #endif
-#ifdef CONFIG_CHARGER_SGM41513_EVB
-	 /*set the DCIN Current = 2A*/
-	/*
-	ret = sgm41513_write_mask(g_bdi,SGM41513_REG_ISC,
-				   SGM41513_REG_ISC_ISET_DCIN_MASK,
-				   SGM41513_REG_ISC_ISET_DCIN_SHIFT,
-				   0x5);
-	if (ret < 0){
-		printk(KERN_INFO"write REG_01 fault\n");
-	}
-	*/
-#endif
-	ret = sgm41513_charger_config_groupB_Regs(bdi);
-	if (ret < 0) {
-		printk(KERN_INFO "groupB config faild.\n");
-	}
 
 	sgm41513_charger_init(&bdi->charger);
 
@@ -2395,7 +2480,7 @@
 		INIT_DELAYED_WORK(&bdi->boostWorkStruct,sgm41513_boost_workstruct_callback);
 		INIT_DELAYED_WORK(&bdi->charge_monitor_work, charger_monitor_work_func);
 		
-		schedule_delayed_work(&bdi->charge_monitor_work,100);
+		//schedule_delayed_work(&bdi->charge_monitor_work,100);
 		//queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,20000);
 	#ifdef DBG_CHARGE
 		printk(KERN_INFO "setup_workqueue.\n");
@@ -2413,6 +2498,28 @@
 	
 	sema_init(&bdi->chgirq_sem, 0);
 	
+	
+	bdi->chgin_irq= gpio_to_irq(DCIN_5V_GPIO);
+
+	ret = zx29_gpio_config(DCIN_5V_GPIO,DCIN_5V_GPIO_FUNC_EXT_INT);
+	if (ret < 0)
+	{
+		dev_err(dev, "init dcin_5v interrupt error.\n");	
+	}
+	else
+	{
+		zx29_gpio_set_inttype(DCIN_5V_GPIO, bdi->dcin_5v_pulgin_flag ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH);  //INT_POSEDGE
+	}
+
+	ret = request_threaded_irq(bdi->chgin_irq, NULL, dcin_5v_irq_primary_thread, IRQF_ONESHOT, "dcin-5v-chgin", bdi);
+	if (ret < 0) {
+		dev_err(dev, "Can't set up irq handler %d\n", __LINE__);
+		if (DCIN_5V_GPIO)
+			gpio_free(DCIN_5V_GPIO);
+	}
+
+	irq_set_irq_wake(bdi->chgin_irq, 1);
+
 	ret = sgm41513_init_state(bdi);
 	if(ret)
 	{
@@ -2465,17 +2572,16 @@
 
 	dwc_otg_chg_inform(!ret);
 	*/
-
-	ret = sgm41513_read_mask(bdi, SGM41513_REG08,
-			SGM41513_REG08_VBUS_STAT_MASK,
-			SGM41513_REG08_VBUS_STAT_SHIFT,
-			&v);
-
-	if (ret >= 0) {
-		printk("cy: vbus stat %d \n", v);
-		//dwc_otg_chg_inform(!v);
+	if (bdi->dcin_5v_pulgin_flag || sgm41513_get_real_voltage() > CHANGE_ROLE_VOTAGE)
+	{
+		set_typec_try_role(1);
+	}
+	else
+	{
+		set_typec_try_role(0);
 	}
 
+	sgm41513_charger_irq_primary_handler(bdi->irq, bdi);
 
 #ifdef DBG_CHARGE
 	printk(KERN_INFO "sgm41513_probe end.\n");
diff --git a/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h b/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
index 251dcaf..0ed5b5d 100644
--- a/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
+++ b/lynq/R305/V4/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
@@ -10,6 +10,7 @@
 #define _SGM41513_CHARGER_H_
 
 #include <linux/bitops.h>
+#include <linux/power_supply.h>
 #include <mach/gpio.h>
 
 typedef void                VOID;
@@ -159,6 +160,8 @@
 
 
 #define SGM41513_REG0A						0x0A
+#define SGM41513_REG0A_VBUS_GD_MASK			BIT(7)
+#define SGM41513_REG0A_VBUS_GD_SHIFT			7
 
 
 #define SGM41513_REG0B						0x0B  /*record the version info*/
@@ -168,6 +171,9 @@
 #define SGM41513_REG0B_PN_MASK				(BIT(6)|BIT(5)|BIT(4)|BIT(3))
 #define SGM41513_REG0B_PN_SHIFT					3
 
+
+#define SGM41513_REG0E						0x0E
+
 #define SGM41513_REG_VERS						0x03
 
 #define SGM41513_REG_MAX						0x10
@@ -177,6 +183,14 @@
 	short level; /*in percent(0..100%)*/
 };
 
+struct sgm41513_charge_current_limit{
+	int temp_grade;
+	short temp_voltage_above; /* in mV - specify -1 for not set */
+	short temp_voltage_below; /* in mV - specify -1 for not set */
+	short current_limit; /* in mA */
+	short max_voltage; /* in mV - specify -1 for not set*/
+};
+
 struct sgm41513_platform_data {
 	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
 	gpio_func_id 	gpio_int_fun_sel;
@@ -186,6 +200,12 @@
 	int charging_size;
 	struct sgm41513_bat_calibration  *discharging;
 	int	discharging_size;
+	struct sgm41513_charge_current_limit *temp_current_map;
+	int temp_current_map_size;
+	int max_charge_voltage; /* in mV */
+	int max_input_current; /* in mA */
+	int pre_charge_current; /* in mA */
+	int terminate_charge_current; /* in mA */
 	bool	ts_flag;
 	bool	boost_flag;
 	unsigned int	boost_cur_gpio1;
diff --git a/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux b/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
index 32c2702..9c58637 100755
--- a/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
+++ b/lynq/R305/V4/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
@@ -1360,8 +1360,7 @@
 # CONFIG_W1 is not set
 CONFIG_POWER_SUPPLY=y
 CONFIG_POWER_SUPPLY_DEBUG=y
-CONFIG_CHARGER_AW3215=y
-#CONFIG_CHARGER_SGM41513 is not set
+CONFIG_CHARGER_SGM41513=y
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 CONFIG_WATCHDOG=y
diff --git a/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c b/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
index 584cb2d..8caac69 100755
--- a/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
+++ b/lynq/R305/V4/boot/common/src/uboot/board/zte/zx297520v3/zx297520v3_ufi_mini.c
@@ -229,11 +229,10 @@
     zDrvGpio_SetDirection(GPIO120,GPIO_OUT);
     zDrvGpio_SetOutputValue(GPIO120,GPIO_LOW);
 
-	
-    zDrvGpio_PullUpDown(GPIO27, 0);
-    zDrvGpio_SetFunc(GPIO27,GPIO27_GPIO27);
-    zDrvGpio_SetDirection(GPIO27,GPIO_OUT);
-    zDrvGpio_SetOutputValue(GPIO27,GPIO_LOW);
+    // zDrvGpio_PullUpDown(GPIO27, 0);
+    // zDrvGpio_SetFunc(GPIO27,GPIO27_GPIO27);
+    // zDrvGpio_SetDirection(GPIO27,GPIO_OUT);
+    // zDrvGpio_SetOutputValue(GPIO27,GPIO_LOW);
 
     //you.chen@20250708 temp support switch card by Analog Switch IC -- begin
     //zDrvGpio_PullUpDown(GPIO49, GPIO_PULL_UP);
@@ -258,21 +257,21 @@
     zDrvGpio_SetFunc(GPIO52,GPIO52_GPIO52);
     zDrvGpio_SetDirection(GPIO52,GPIO_IN);
 
-    zDrvGpio_PullUpDown(GPIO125, GPIO_PULL_DOWN);
+    zDrvGpio_PullUpDown(GPIO125, GPIO_PULL_UP);
     zDrvGpio_SetFunc(GPIO125,GPIO125_GPIO125);
     zDrvGpio_SetDirection(GPIO125,GPIO_IN);
 
-    zDrvGpio_PullUpDown(GPIO36, 0);
-    zDrvGpio_SetFunc(GPIO36,GPIO36_GPIO36);
-    zDrvGpio_SetDirection(GPIO36, GPIO_OUT);
-    if (GPIO_HIGH == zDrvGpio_GetInputValue(GPIO125))
-    {
-	    zDrvGpio_SetOutputValue(GPIO36,GPIO_HIGH);
-    }
-    else
-    {
-	    zDrvGpio_SetOutputValue(GPIO36, GPIO_LOW);
-    }
+    // zDrvGpio_PullUpDown(GPIO36, 0);
+    // zDrvGpio_SetFunc(GPIO36,GPIO36_GPIO36);
+    // zDrvGpio_SetDirection(GPIO36, GPIO_OUT);
+    // if (GPIO_HIGH == zDrvGpio_GetInputValue(GPIO125))
+    // {
+	//     zDrvGpio_SetOutputValue(GPIO36,GPIO_HIGH);
+    // }
+    // else
+    // {
+	//     zDrvGpio_SetOutputValue(GPIO36, GPIO_LOW);
+    // }
 
     zDrvGpio_PullUpDown(GPIO121, 0);
     zDrvGpio_SetFunc(GPIO121,GPIO121_GPIO121);