[Feature][R307][task-view-492][CHARGER] to detect usb base on charger register

Change-Id: I26aa0aae262d54812c0d10ebf4bfe0c8035c4ab7
diff --git a/lynq/R307/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c b/lynq/R307/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
index 46c9b72..f784c87 100755
--- a/lynq/R307/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
+++ b/lynq/R307/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
@@ -1322,12 +1322,13 @@
 
 struct sgm41513_charge_current_limit zx234502_charger_temp_current[] =
 {
-	//above below	current voltage_limit
-	{1273,	-1,		0,		-1},
-	{1057,	1273,	500,	-1},
-	{623,	1057,	1260,	-1},
-	{434,	623,	500,	-1},
-	{-1,	434,	0,		-1}
+	//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,	540,	-1},
+	{POWER_SUPPLY_HEALTH_GOOD,		623,	1057,	1260,	-1},
+	{POWER_SUPPLY_HEALTH_WARM,		434,	623,	500,	-1},
+	{POWER_SUPPLY_HEALTH_OVERHEAT,	-1,		434,	0,		-1}
 };
 
 static struct  sgm41513_platform_data sgm41513_charger_platform = {
@@ -1339,7 +1340,7 @@
 	.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 = 4208,
+	.max_charge_voltage = 4200,
 	.max_input_current = 1800,
 	.pre_charge_current = 120,
 	.terminate_charge_current = 120,
diff --git a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
index e87b0ff..b49f488 100755
--- a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
+++ b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
@@ -70,12 +70,19 @@
 	bool			charger_health_valid;
 	bool			battery_health_valid;
 	bool			battery_status_valid;
+	volatile bool	charging_flag;
+	volatile bool	usb_detecting_flag;
+	volatile bool	usb_force_detect_flag;
+	bool			battery_online_flag;
+	unsigned int	plugout_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;
@@ -115,13 +122,6 @@
 }
 */
 
-void clear_ac_pc_flag(void)
-{
-	if (g_bdi == NULL)
-	    return;
-	g_bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
-}
-
 static int stopchg_flag = 0;
 /*
  * Return the index in 'tbl' of greatest value that is less than or equal to
@@ -292,19 +292,24 @@
 static int sgm41513_get_real_voltage(void)
 {
 	int ret, local_ce_flag=0;
+	u8 v=0;
 	if (ce_enabled == 1)
 	{
-		local_ce_flag = 1;
-		set_ce_gpio(0);
-		msleep(100);
+		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;
+			set_ce_gpio(0);
+			msleep(100);
+		}
 	}
-	ret = get_adc1_voltage() - 15;
+	ret = get_adc1_voltage() - (local_ce_flag == 1 ? 8 : 0);
 	if (local_ce_flag)
 		set_ce_gpio(1);
 	return ret;
 }
 
-static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val, bool full_check)
 {
 	u8 v=0, vbus_stat=0, chrg_stat=0, pg_stat=0;
 	int status=POWER_SUPPLY_STATUS_UNKNOWN;
@@ -345,27 +350,35 @@
 	}
 	else if(chrg_stat == 3)
 	{
-		if (sgm41513_get_real_voltage() >= bdi->pdata->max_charge_voltage)
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		if (full_check && sgm41513_get_real_voltage() >= bdi->pdata->max_charge_voltage)
 			status = POWER_SUPPLY_STATUS_FULL;
-		else
-			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
 	}
 
 	if (!ret)
 		val->intval = status;
 
-	printk("cy: sgm41513_charger_get_status %d exit\n", val->intval);
+	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);
-	val->intval = POWER_SUPPLY_HEALTH_GOOD;
+	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;
+	}
+
 	return 0;
 }
 
@@ -440,7 +453,7 @@
 	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);
 }
@@ -495,9 +508,29 @@
 	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();
+	pr_err("%s voltage %d\n",__func__, voltage);
+	for (i=0; i<bdi->pdata->temp_current_map_size; i++) 
+	{
+		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, voltage;
+	int ret, i;
 	u8 last_curr = -1;
 	u8 need_curr = -1;
 	union power_supply_propval val;
@@ -508,22 +541,18 @@
 		SGM41513_REG02_ICHG_SHIFT,
 		&last_curr);
 
-	voltage = get_adc2_voltage();
-	pr_err("%s voltage %d\n",__func__, voltage);
-	for (i=0; i<bdi->pdata->temp_current_map_size; i++) 
+	p = get_current_temp_status(bdi);
+	if (p == NULL)
 	{
-		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))
-		{
-			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);
-			}
-		}
+		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);
@@ -572,16 +601,25 @@
 			SGM41513_REG01_CHG_CONFIG_MASK,
 			SGM41513_REG01_CHG_CONFIG_SHIFT, enable_charge.intval );  /*0:disable 1:enable*/
 
-	 set_ce_gpio(enable_charge.intval);
-	 
-	if (enable_charge.intval == 0)
+
+	bdi->charging_flag = false;
+	if (bdi->battery_online_flag && enable_charge.intval != 0)
 	{
-		power_supply_changed(&bdi->charger);
+		set_ce_gpio(1);
+		cancel_delayed_work_sync(&bdi->charge_monitor_work);
+		schedule_delayed_work(&bdi->charge_monitor_work, HZ*2);
+		bdi->charging_flag = true;
 	}
-	else{	
-		cancel_delayed_work_sync(&g_bdi->charge_monitor_work);
-		schedule_delayed_work(&g_bdi->charge_monitor_work, HZ*2);
+	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;
 }
 
@@ -607,7 +645,7 @@
 	
 	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);
 		break;
 	case POWER_SUPPLY_PROP_HEALTH:
 		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_HEALTH\n");
@@ -678,12 +716,14 @@
 		break;
 	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
 		printk("cy: POWER_SUPPLY_PROP_PD_CURRENT_MAX %d\n", val->intval);
+		/*
 		if (val->intval > 100 && val->intval < bdi->pdata->max_input_current)
 		{
 			required_iindpm = convert_iindpm_from_current(val->intval);
 			cancel_delayed_work_sync(&bdi->charge_monitor_work);
 			schedule_delayed_work(&bdi->charge_monitor_work, HZ/2);
 		}
+		*/
 		break;
 	case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
 		printk("cy: POWER_SUPPLY_PROP_PD_VOLTAGE_MIN %d\n", val->intval);
@@ -773,69 +813,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;
 }
 
@@ -1262,6 +1270,11 @@
 		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,
 		SGM41513_REG06_OVP_MASK,
@@ -1387,14 +1400,29 @@
 	return IRQ_HANDLED;
 }
 
+void force_detect_usb(void)
+{
+	printk("cy: do force_detect_usb\n");
+	if (g_bdi->charger.type == POWER_SUPPLY_PCAC_UNKNOWN)
+	{
+		g_bdi->usb_force_detect_flag = true;
+		g_bdi->plugout_check_cnt = 2;
+		dwc_otg_chg_inform(0);
+		cancel_delayed_work_sync(&g_bdi->charge_monitor_work);
+		schedule_delayed_work(&g_bdi->charge_monitor_work, HZ*2);
+	}
+}
+
 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;
+	u8 reg08, reg0a, reg0e;
+	bool vbus_gd_flag, usb_in_flag, usb_host_flag, last_usb_in_flag, last_usb_host_flag;
+	union power_supply_propval enable_charge;
 	struct sched_param param = { .sched_priority = 2 };
 	param.sched_priority= 31;
 	func_trace();
@@ -1405,30 +1433,121 @@
 		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;
 		
 		//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;
+		}
+
+		//printk("cy: reg 08: %d, reg 0a: %d\n", reg08, reg0a);
+		vbus_gd_flag = (reg0a & SGM41513_REG0A_VBUS_GD_MASK) != 0;
+		last_usb_in_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) != 0;
+		last_usb_host_flag = (reg08 & SGM41513_REG08_VBUS_STAT_MASK) == (0x7 << SGM41513_REG08_VBUS_STAT_SHIFT);
+
+		if (bdi->charger.type == POWER_SUPPLY_PCAC_UNKNOWN && (vbus_gd_flag || last_usb_in_flag))
+		{
+			printk("cy: toggle usb detecting flag\n");
+			bdi->usb_detecting_flag = true;			
+			bdi->plugout_check_cnt = 2;
+			cancel_delayed_work_sync(&bdi->charge_monitor_work);
+			schedule_delayed_work(&bdi->charge_monitor_work, HZ*2);
+		}
+
+		if (bdi->usb_detecting_flag || !vbus_gd_flag || !last_usb_in_flag || bdi->usb_force_detect_flag)
+		{
+			for(i=0;i<5;i++)
+			{
+				mutex_unlock(&bdi->bs_reg_lock);
+				msleep(20);
+				mutex_lock(&bdi->bs_reg_lock);
+				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;
+				}
+				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);
+				if (last_usb_in_flag != usb_in_flag || last_usb_host_flag != usb_host_flag)
+					break;
+			}
+			if (i >= 5) 
+			{
+				printk("cy: irq thread inform begin, %d, %d\n", usb_in_flag, usb_host_flag);
+				if (bdi->plugout_check_cnt > 0 && !last_usb_in_flag)
+					bdi->plugout_check_cnt--;
+				if (bdi->charger.type != POWER_SUPPLY_PCAC_UNKNOWN && !last_usb_in_flag && bdi->plugout_check_cnt <= 0) // usb plugout
+				{
+					set_ce_gpio(0);
+					bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+					bdi->usb_force_detect_flag = false;
+					bdi->usb_detecting_flag = false;
+					dwc_otg_chg_inform(1);					
+					set_typec_try_role(1);
+					printk("cy: usb plugout inform finish\n");
+				}
+				else if ((bdi->usb_detecting_flag || bdi->usb_force_detect_flag ) && last_usb_in_flag) //usb plugin
+				{
+					printk("cy: usb plugin inform finish\n");
+					if (!bdi->usb_force_detect_flag)
+						dwc_otg_chg_inform(0);
+					else
+						bdi->usb_force_detect_flag = false;
+
+					if (!last_usb_host_flag) //charger plugin
+					{						
+						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);
+						enable_charge.intval = 1;
+						bdi->plugout_check_cnt = 0;
+						sgm41513_charger_set_charger_config(bdi, &enable_charge);
+					}
+				}
+			}
+			else{
+				printk("cy: unstable plug\n");
+			}
+		}
+		else{
+			//printk("cy: bdi->usb_detecting_flag %d, %d, %d, %d", bdi->usb_detecting_flag, vbus_gd_flag, last_usb_host_flag, bdi->usb_force_detect_flag);
+		}
+
+		bdi->reg08 = reg08;
 		
+		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);
@@ -1547,6 +1666,8 @@
 		bdi->battery_health_valid = true;/****?***/
 		bdi->battery_status_valid = true;/****?***/
 
+		
+#endif
 		mutex_unlock(&bdi->bs_reg_lock);
 
 		/*
@@ -1574,12 +1695,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;
@@ -1621,7 +1741,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);
@@ -1740,36 +1860,20 @@
 {
 	int ret;
 	u8 otg_flag;
-	union power_supply_propval val = {.intval = 0};
 	#ifdef DBG_CHARGE
 	printk(KERN_INFO"charge type is %d in\n",chg_type);
 	#endif
 	func_trace();
+	g_bdi->usb_detecting_flag = false;
 #if 1
 	if(TYPE_ADAPTER == chg_type){
 		
 		printk(KERN_INFO"chg type is TYPE_ADAPTER\n");
 		set_typec_try_role(0);
-		val.intval = 1;
-		 /*set the DCIN Current = 2.4A*/
-		
-		//g_last_real_voltage = get_adc1_voltage();
-		required_iindpm = convert_iindpm_from_current(g_bdi->pdata->max_input_current);
-		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
-					   SGM41513_REG00_IINDPM_MASK,
-					   SGM41513_REG00_IINDPM_SHIFT,
-					   required_iindpm);
-		if (ret < 0){
-			printk(KERN_INFO"write REG_00 fault\n");
-		}
 		g_bdi->charger.type = POWER_SUPPLY_PCAC__AC;
-		dump_sgm_regs(g_bdi->client);
-		sgm41513_charger_set_charger_config(g_bdi, &val);
 	}
-	
 	else if (TYPE_COMPUTER == chg_type) {
 		g_bdi->charger.type = POWER_SUPPLY_PCAC__PC;
-		
 		ret = sgm41513_read_mask(g_bdi, SGM41513_REG01,
 				SGM41513_REG01_OTG_CONFIG_MASK,
 				SGM41513_REG01_OTG_CONFIG_SHIFT, &otg_flag);
@@ -1778,36 +1882,8 @@
 		{
 			return;
 		}
-
-		required_iindpm = convert_iindpm_from_current(g_bdi->pdata->max_input_current);
-		 /*set the DCIN Current = 450mA*/
-		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
-					   SGM41513_REG00_IINDPM_MASK,
-					   SGM41513_REG00_IINDPM_SHIFT,
-					   required_iindpm);
-		if (ret < 0){
-			printk(KERN_INFO"write REG_01 fault\n");
-		}
-
-		dump_sgm_regs(g_bdi->client);
-		val.intval = 1;
-		sgm41513_charger_set_charger_config(g_bdi, &val);
+		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
 }
 
@@ -1993,7 +2069,7 @@
 	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 vbus_stat = -1;
 	u8 otg_flag = -1;
@@ -2008,40 +2084,36 @@
 		pr_err("Cann't get sgm \n");
 		return ;
 	}
-
-	ret = sgm41513_read_mask(bdi, SGM41513_REG01,
-			SGM41513_REG01_OTG_CONFIG_MASK,
-			SGM41513_REG01_OTG_CONFIG_SHIFT, &otg_flag);
 	
-	if (ret == 0 && otg_flag != 0)
+	if (ce_enabled == 1)
+	{
+		//dump_sgm_regs(bdi->client);
+		//return;
+		set_charge_current(bdi);
+	}
+
+	if (bdi->plugout_check_cnt > 0)
+	{
+		sgm41513_charger_irq_primary_handler(bdi->irq, bdi);
+	}
+	else if(ce_enabled == 0)
 	{
 		return;
 	}
+	else
+	{		
+		sgm41513_charger_get_status(bdi, &val, false);
 
-	if (required_iindpm != 0) 
-	{
-		ret = sgm41513_read_mask(bdi,SGM41513_REG08,
-			SGM41513_REG08_VBUS_STAT_MASK,
-			SGM41513_REG08_VBUS_STAT_SHIFT,
-			&vbus_stat);
-		if (ret == 0 && vbus_stat != 0)
+		if ((val.intval == POWER_SUPPLY_STATUS_CHARGING && !bdi->charging_flag) || (val.intval != POWER_SUPPLY_STATUS_CHARGING && bdi->charging_flag))
 		{
-			ret = sgm41513_write_mask(bdi,SGM41513_REG00,
-				SGM41513_REG00_IINDPM_MASK,
-				SGM41513_REG00_IINDPM_SHIFT,
-				required_iindpm);
-			if (ret == 0 ) {
-				required_iindpm = 0;
-				power_supply_changed(&bdi->charger);
-			}
+			bdi->charging_flag = (val.intval == POWER_SUPPLY_STATUS_CHARGING);
+			power_supply_changed(&bdi->charger);
 		}
 	}
 
-	set_charge_current(bdi);
-
 	dump_sgm_regs(bdi->client);
 OUT:	
-	schedule_delayed_work(&bdi->charge_monitor_work, required_iindpm == 0 ? (10 * HZ) : HZ/2);
+	schedule_delayed_work(&bdi->charge_monitor_work, bdi->plugout_check_cnt <= 0 ? (10 * HZ) : HZ/2);
 }
 
 static int sgm41513_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -2056,6 +2128,7 @@
 
 	printk(KERN_INFO "charger probe.\n");
 
+	set_ce_gpio(0); //make sure ce status ok
 
 	dump_sgm_regs(client);
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -2075,23 +2148,27 @@
 	strncpy(bdi->model_name, id->name, sizeof(bdi->model_name)-1);
 	mutex_init(&bdi->bs_reg_lock);
 	bdi->first_time = true;
+	bdi->charging_flag = false;
+	bdi->battery_online_flag = false;
+	bdi->usb_detecting_flag = false;
 	bdi->charger_health_valid = false;
 	bdi->battery_health_valid = false;
 	bdi->battery_status_valid = false;
+	bdi->plugout_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
@@ -2236,6 +2313,7 @@
 		//dwc_otg_chg_inform(!v);
 	}
 
+	sgm41513_charger_irq_primary_handler(bdi->irq, bdi);
 
 #ifdef DBG_CHARGE
 	printk(KERN_INFO "sgm41513_probe end.\n");
diff --git a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c
index 5158daa..7ea5897 100755
--- a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c
+++ b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c
@@ -393,6 +393,7 @@
 	smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
 }
 
+extern void force_detect_usb(void);
 static int pd_tcp_notifier_call(struct notifier_block *nb,
 				unsigned long event, void *data)
 {
@@ -460,6 +461,7 @@
 			 * start charger type detection,
 			 * and enable device connection
 			 */
+			force_detect_usb();
 			cancel_delayed_work_sync(&rpmd->usb_dwork);
 			rpmd->usb_dr = DR_DEVICE;
 			rpmd->usb_type_polling_cnt = 0;
diff --git a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c
index 99e2e08..6028a99 100755
--- a/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c
+++ b/lynq/R307/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c
@@ -215,7 +215,6 @@
 	return 0;
 }
 
-extern void clear_ac_pc_flag(void);
 static ssize_t tcpc_store_property(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
@@ -237,8 +236,6 @@
 			return -EINVAL;
 		}
 
-		if (val == 4)
-			clear_ac_pc_flag();
 		tcpm_typec_change_role(tcpc, val);
 		break;
 	case TCPC_DESC_TIMER:
diff --git a/lynq/R307/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h b/lynq/R307/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
index 1b75012..0ed5b5d 100755
--- a/lynq/R307/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
+++ b/lynq/R307/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
@@ -178,6 +184,7 @@
 };
 
 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 */
diff --git a/lynq/R307/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux b/lynq/R307/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
index d483a00..7b26567 100755
--- a/lynq/R307/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
+++ b/lynq/R307/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
@@ -1459,7 +1459,7 @@
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 CONFIG_DWC_OTG_USB=y
 CONFIG_DWC_DEVICE_ONLY=y
-CONFIG_DWC_DEVICE_GPIO_CHARGER=y
+# CONFIG_DWC_DEVICE_GPIO_CHARGER is not set
 
 #
 # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may