charger: smb345: add hot limit temperature to stop charging

Bug: 11476629
Change-Id: I5c7039e2a371b404f9f4e86e7b28542921138608
Signed-off-by: Hank_Lee <Hank_Lee@asus.com>
diff --git a/drivers/power/bq27541_battery.c b/drivers/power/bq27541_battery.c
index cde5011..217e53a 100755
--- a/drivers/power/bq27541_battery.c
+++ b/drivers/power/bq27541_battery.c
@@ -89,6 +89,7 @@
 	enum power_supply_property psp, union power_supply_propval *val);
 extern unsigned  get_usb_cable_status(void);
 extern int smb347_charger_enable(bool enable);
+extern int smb347_config_thermal_charging(int temp);
 
 module_param(battery_current, uint, 0644);
 module_param(battery_remaining_capacity, uint, 0644);
@@ -148,6 +149,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
 void check_cabe_type(void)
@@ -344,6 +346,26 @@
 	.attrs = battery_smbus_attributes,
 };
 
+static int bq27541_battery_current(void)
+{
+	int ret;
+	int curr = 0;
+
+	ret = bq27541_read_i2c(bq27541_data[REG_CURRENT].addr, &curr, 0);
+	if (ret) {
+		BAT_ERR("error reading current ret = %x\n", ret);
+		return 0;
+	}
+
+	curr = (s16)curr;
+
+	if (curr >= bq27541_data[REG_CURRENT].min_value &&
+		curr <= bq27541_data[REG_CURRENT].max_value) {
+		return curr;
+	} else
+		return 0;
+}
+
 static void battery_status_poll(struct work_struct *work)
 {
        struct bq27541_device_info *batt_dev = container_of(work, struct bq27541_device_info, status_poll_work.work);
@@ -353,6 +375,10 @@
 
 	power_supply_changed(&bq27541_supply[Charger_Type_Battery]);
 
+	if (!bq27541_device->temp_err)
+		if (ac_on || usb_on)
+			smb347_config_thermal_charging(bq27541_device->old_temperature/10);
+
 	/* Schedule next polling */
 	queue_delayed_work(battery_work_queue, &batt_dev->status_poll_work, bat_check_interval*HZ);
 }
@@ -599,6 +625,11 @@
 		bq27541_device->old_temperature = val->intval = ret;
 		BAT_NOTICE("temperature= %u (0.1¢XC)\n", val->intval);
 	}
+	if (psp == POWER_SUPPLY_PROP_CURRENT_NOW) {
+		val->intval = bq27541_device->bat_current
+			= bq27541_battery_current();
+		BAT_NOTICE("current = %d mA\n", val->intval);
+	}
 	return 0;
 }
 
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index 03f5263..1c5d136 100755
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -108,6 +108,8 @@
 #define DELAY_FOR_CURR_LIMIT_RECONF (60)
 #define ADAPTER_PROTECT_DELAY (4*HZ)
 #define GPIO_AC_OK		TEGRA_GPIO_PV1
+#define ENABLE_PIN_CTRL_MASK 0x60
+#define BAT_Hot_Limit 45
 
 /* Functions declaration */
 static int smb347_configure_charger(struct i2c_client *client, int value);
@@ -1060,42 +1062,37 @@
 static ssize_t smb347_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = charger->client;
-	uint8_t config_reg[14], cmd_reg[1], status_reg[10];
-	int i, ret = 0;
+	uint8_t config_reg[15], cmd_reg[1], status_reg[10];
+	char tmp_buf[64];
+	int i, cfg_ret, cmd_ret, sts_ret = 0;
 
-	ret += i2c_smbus_read_i2c_block_data(client, smb347_CHARGE, 15, config_reg)
-	     + i2c_smbus_read_i2c_block_data(client, smb347_CMD_REG, 2, cmd_reg)
-	     + i2c_smbus_read_i2c_block_data(client, smb347_INTR_STS_A, 11, status_reg);
+	cfg_ret = i2c_smbus_read_i2c_block_data(client, smb347_CHARGE, 15, config_reg);
+	cmd_ret = i2c_smbus_read_i2c_block_data(client, smb347_CMD_REG, 2, cmd_reg);
+	sts_ret = i2c_smbus_read_i2c_block_data(client, smb347_INTR_STS_A, 11, status_reg);
 
-	if (ret < 0)
-		SMB_ERR("failed to read charger reg !\n");
+	sprintf(tmp_buf, "SMB34x Configuration Registers Detail\n"
+					"==================\n");
+	strcpy(buf, tmp_buf);
 
-	SMB_INFO("smb347 Registers\n");
-	SMB_INFO("------------------\n");
-	for(i=0;i<=14;i++)
-		SMB_INFO("Reg[%02xh]=0x%02x\n", i, config_reg[i]);
-	for(i=0;i<=1;i++)
-		SMB_INFO("Reg[%02xh]=0x%02x\n", 48+i, cmd_reg[i]);
-	for(i=0;i<=10;i++)
-		SMB_INFO("Reg[%02xh]=0x%02x\n", 53+i, status_reg[i]);
-
-	return sprintf(buf, "Reg[06h]=0x%02x\n"
-		"Reg[08h]=0x%02x\n"
-		"Reg[30h]=0x%02x\n"
-		"Reg[31h]=0x%02x\n"
-		"Reg[39h]=0x%02x\n"
-		"Reg[3dh]=0x%02x\n"
-		"Reg[3eh]=0x%02x\n"
-		"Reg[3fh]=0x%02x\n",
-		config_reg[6],
-		config_reg[8],
-		cmd_reg[0],
-		cmd_reg[1],
-		status_reg[4],
-		status_reg[8],
-		status_reg[9],
-		status_reg[10]);
-
+	if (cfg_ret > 0) {
+		for(i=0;i<=14;i++) {
+			sprintf(tmp_buf, "Reg%02xh:\t0x%02x\n", i, config_reg[i]);
+			strcat(buf, tmp_buf);
+		}
+	}
+	if (cmd_ret > 0) {
+		for(i=0;i<=1;i++) {
+			sprintf(tmp_buf, "Reg%02xh:\t0x%02x\n", 48+i, cmd_reg[i]);
+			strcat(buf, tmp_buf);
+		}
+	}
+	if (sts_ret > 0) {
+		for(i=0;i<=10;i++) {
+			sprintf(tmp_buf, "Reg%02xh:\t0x%02x\n", 53+i, status_reg[i]);
+			strcat(buf, tmp_buf);
+		}
+	}
+	return strlen(buf);
 }
 
 static void smb347_default_setback(void)
@@ -1161,6 +1158,53 @@
 	return -1;
 }
 
+int smb347_config_thermal_charging(int temp)
+{
+	struct i2c_client *client = charger->client;
+	int ret = 0, retval, setting = 0;
+
+	mdelay(150);
+	SMB_NOTICE("temp=%d\n", temp);
+
+	ret = smb347_volatile_writes(client, smb347_ENABLE_WRITE);
+		if (ret < 0) {
+			dev_err(&client->dev, "%s() charger enable write error..\n", __func__);
+			goto error;
+	}
+
+	/*charger enable/disable*/
+	retval = smb347_read(client, smb347_PIN_CTRL);
+	if (retval < 0) {
+		dev_err(&client->dev, "%s(): Failed in reading 0x%02x",
+				__func__, smb347_PIN_CTRL);
+		goto error;
+	}
+
+	setting = retval & ENABLE_PIN_CTRL_MASK;
+	if (temp > BAT_Hot_Limit) {
+		if (setting != 0x40) {
+			SMB_NOTICE("Charger disable\n");
+			smb347_charger_enable(false);
+		} else
+			SMB_NOTICE("Bypass charger disable\n");
+	} else {
+		if (setting != 0x60) {
+			SMB_NOTICE("Charger enable\n");
+			smb347_charger_enable(true);
+		} else
+			SMB_NOTICE("Bypass charger enable\n");
+	}
+
+	ret = smb347_volatile_writes(client, smb347_DISABLE_WRITE);
+	if (ret < 0) {
+		dev_err(&client->dev, "%s() charger enable write error..\n", __func__);
+		goto error;
+	}
+error:
+	return ret;
+}
+EXPORT_SYMBOL(smb347_config_thermal_charging);
+
 static int __devinit smb347_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {