power: bq28400: Stop charging when battery is too hot/cold

Allow to provide the battery hot/cold temperature limits and
stop charging outside the cold to hot temperature range.

Change-Id: I9cf0083ed08c21268b365c04f5c48b130e08679a
Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
Signed-off-by: Eugene Yasman <eyasman@codeaurora.org>
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 1852687..beab4e2 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -136,6 +136,8 @@
 	struct power_supply	batt_psy;
 	struct power_supply	*dc_psy;
 	bool			is_charging_enabled;
+	u32			temp_cold;	/* in degree celsius */
+	u32			temp_hot;	/* in degree celsius */
 };
 
 static struct bq28400_device *bq28400_dev;
@@ -486,10 +488,14 @@
 	int rsoc;
 	s16 current_ma = 0;
 	u16 battery_status;
+	int temperature;
+	struct bq28400_device *dev = i2c_get_clientdata(client);
 
 	battery_status = bq28400_read_reg(client, SBS_BATTERY_STATUS);
 	rsoc = bq28400_read_rsoc(client);
 	current_ma = bq28400_read_current(client);
+	temperature = bq28400_read_temperature(client);
+	temperature = temperature / 10; /* in degree celsius */
 
 	if (battery_status & BAT_STATUS_EMPTY)
 		pr_debug("Battery report Empty.\n");
@@ -513,8 +519,11 @@
 		return POWER_SUPPLY_STATUS_FULL;
 	}
 
-	/* Enable charging when battery is not full */
-	bq28400_enable_charging(bq28400_dev, true);
+	/* Enable charging when battery is not full and temperature is ok */
+	if ((temperature > dev->temp_cold) && (temperature < dev->temp_hot))
+		bq28400_enable_charging(bq28400_dev, true);
+	else
+		bq28400_enable_charging(bq28400_dev, false);
 
 	/*
 	* Positive current indicates charging
@@ -825,6 +834,12 @@
 				   const struct i2c_device_id *id)
 {
 	int ret = 0;
+	struct device_node *dev_node = client->dev.of_node;
+
+	if (dev_node == NULL) {
+		pr_err("Device Tree node doesn't exist.\n");
+		return -ENODEV;
+	}
 
 	if (!i2c_check_functionality(client->adapter,
 				I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -843,6 +858,23 @@
 		return -ENOMEM;
 	}
 
+	/* Note: Lithium-ion battery normal temperature range 0..40 C */
+	ret = of_property_read_u32(dev_node, "ti,temp-cold",
+				   &(bq28400_dev->temp_cold));
+	if (ret) {
+		pr_err("Unable to read cold temperature. ret=%d.\n", ret);
+		goto err_dev_node;
+	}
+	pr_debug("cold temperature limit = %d C.\n", bq28400_dev->temp_cold);
+
+	ret = of_property_read_u32(dev_node, "ti,temp-hot",
+				   &(bq28400_dev->temp_hot));
+	if (ret) {
+		pr_err("Unable to read hot temperature. ret=%d.\n", ret);
+		goto err_dev_node;
+	}
+	pr_debug("hot temperature limit = %d C.\n", bq28400_dev->temp_hot);
+
 	bq28400_dev->client = client;
 	i2c_set_clientdata(client, bq28400_dev);
 
@@ -864,7 +896,7 @@
 	schedule_delayed_work(&bq28400_dev->periodic_user_space_update_work,
 			      msecs_to_jiffies(1000));
 
-	pr_info("Device is ready.\n");
+	pr_debug("Device is ready.\n");
 
 	return 0;
 
@@ -873,6 +905,7 @@
 		debugfs_remove_recursive(bq28400_dev->dent);
 	power_supply_unregister(&bq28400_dev->batt_psy);
 err_register_psy:
+err_dev_node:
 	kfree(bq28400_dev);
 	bq28400_dev = NULL;