power: pm8921-charger: config cold/hot threshold

Pmic 8921, has configurable hot and cold battery thresholds as
percent of VREF_THERM. Provide means to configure these via
platform data.

One has to set the config values in the charger platform data defined
in the board file.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 257ad35..109ad4a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -174,48 +174,50 @@
  *
  */
 struct pm8921_chg_chip {
-	struct device		*dev;
-	unsigned int		usb_present;
-	unsigned int		dc_present;
-	unsigned int		usb_charger_current;
-	unsigned int		max_bat_chg_current;
-	unsigned int		pmic_chg_irq[PM_CHG_MAX_INTS];
-	unsigned int		safety_time;
-	unsigned int		ttrkl_time;
-	unsigned int		update_time;
-	unsigned int		max_voltage;
-	unsigned int		min_voltage;
-	unsigned int		cool_temp;
-	unsigned int		warm_temp;
-	unsigned int		temp_check_period;
-	unsigned int		cool_bat_chg_current;
-	unsigned int		warm_bat_chg_current;
-	unsigned int		cool_bat_voltage;
-	unsigned int		warm_bat_voltage;
-	unsigned int		resume_voltage;
-	unsigned int		term_current;
-	unsigned int		vbat_channel;
-	unsigned int		batt_temp_channel;
-	unsigned int		batt_id_channel;
-	struct power_supply	usb_psy;
-	struct power_supply	dc_psy;
-	struct power_supply	batt_psy;
-	struct dentry		*dent;
-	struct bms_notify	bms_notify;
+	struct device			*dev;
+	unsigned int			usb_present;
+	unsigned int			dc_present;
+	unsigned int			usb_charger_current;
+	unsigned int			max_bat_chg_current;
+	unsigned int			pmic_chg_irq[PM_CHG_MAX_INTS];
+	unsigned int			safety_time;
+	unsigned int			ttrkl_time;
+	unsigned int			update_time;
+	unsigned int			max_voltage;
+	unsigned int			min_voltage;
+	unsigned int			cool_temp;
+	unsigned int			warm_temp;
+	unsigned int			temp_check_period;
+	unsigned int			cool_bat_chg_current;
+	unsigned int			warm_bat_chg_current;
+	unsigned int			cool_bat_voltage;
+	unsigned int			warm_bat_voltage;
+	unsigned int			resume_voltage;
+	unsigned int			term_current;
+	unsigned int			vbat_channel;
+	unsigned int			batt_temp_channel;
+	unsigned int			batt_id_channel;
+	struct power_supply		usb_psy;
+	struct power_supply		dc_psy;
+	struct power_supply		batt_psy;
+	struct dentry			*dent;
+	struct bms_notify		bms_notify;
 	DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
-	struct work_struct	battery_id_valid_work;
-	int64_t			batt_id_min;
-	int64_t			batt_id_max;
-	int			trkl_voltage;
-	int			weak_voltage;
-	int			trkl_current;
-	int			weak_current;
-	int			vin_min;
-	int			*thermal_mitigation;
-	int			thermal_levels;
-	struct delayed_work	update_heartbeat_work;
-	struct delayed_work	eoc_work;
-	struct wake_lock	eoc_wake_lock;
+	struct work_struct		battery_id_valid_work;
+	int64_t				batt_id_min;
+	int64_t				batt_id_max;
+	int				trkl_voltage;
+	int				weak_voltage;
+	int				trkl_current;
+	int				weak_current;
+	int				vin_min;
+	int				*thermal_mitigation;
+	int				thermal_levels;
+	struct delayed_work		update_heartbeat_work;
+	struct delayed_work		eoc_work;
+	struct wake_lock		eoc_wake_lock;
+	enum pm8921_chg_cold_thr	cold_thr;
+	enum pm8921_chg_hot_thr		hot_thr;
 };
 
 static int charging_disabled;
@@ -637,6 +639,34 @@
 					 temp);
 }
 
+#define PM8921_CHG_BATT_TEMP_THR_COLD	BIT(1)
+#define PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT	1
+static int pm_chg_batt_cold_temp_config(struct pm8921_chg_chip *chip,
+					enum pm8921_chg_cold_thr cold_thr)
+{
+	u8 temp;
+
+	temp = cold_thr << PM8921_CHG_BATT_TEMP_THR_COLD_SHIFT;
+	temp = temp & PM8921_CHG_BATT_TEMP_THR_COLD;
+	return pm_chg_masked_write(chip, CHG_CNTRL_2,
+					PM8921_CHG_BATT_TEMP_THR_COLD,
+					 temp);
+}
+
+#define PM8921_CHG_BATT_TEMP_THR_HOT		BIT(0)
+#define PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT	0
+static int pm_chg_batt_hot_temp_config(struct pm8921_chg_chip *chip,
+					enum pm8921_chg_hot_thr hot_thr)
+{
+	u8 temp;
+
+	temp = hot_thr << PM8921_CHG_BATT_TEMP_THR_HOT_SHIFT;
+	temp = temp & PM8921_CHG_BATT_TEMP_THR_HOT;
+	return pm_chg_masked_write(chip, CHG_CNTRL_2,
+					PM8921_CHG_BATT_TEMP_THR_HOT,
+					 temp);
+}
+
 static int64_t read_battery_id(struct pm8921_chg_chip *chip)
 {
 	int rc;
@@ -2097,6 +2127,18 @@
 		}
 	}
 
+	rc = pm_chg_batt_cold_temp_config(chip, chip->cold_thr);
+	if (rc) {
+		pr_err("Failed to set cold config %d  rc=%d\n",
+						chip->cold_thr, rc);
+	}
+
+	rc = pm_chg_batt_hot_temp_config(chip, chip->hot_thr);
+	if (rc) {
+		pr_err("Failed to set hot config %d  rc=%d\n",
+						chip->hot_thr, rc);
+	}
+
 	/* Workarounds for die 1.1 and 1.0 */
 	if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
 		pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
@@ -2320,6 +2362,9 @@
 	chip->thermal_mitigation = pdata->thermal_mitigation;
 	chip->thermal_levels = pdata->thermal_levels;
 
+	chip->cold_thr = pdata->cold_thr;
+	chip->hot_thr = pdata->hot_thr;
+
 	rc = pm8921_chg_hw_init(chip);
 	if (rc) {
 		pr_err("couldn't init hardware rc=%d\n", rc);
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 613e57a..9f98656 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -23,6 +23,16 @@
 	unsigned int	batt_id_channel;
 };
 
+enum pm8921_chg_cold_thr {
+	PM_SMBC_BATT_TEMP_COLD_THR__LOW,
+	PM_SMBC_BATT_TEMP_COLD_THR__HIGH
+};
+
+enum pm8921_chg_hot_thr	{
+	PM_SMBC_BATT_TEMP_HOT_THR__LOW,
+	PM_SMBC_BATT_TEMP_HOT_THR__HIGH
+};
+
 /**
  * struct pm8921_charger_platform_data -
  * @safety_time:	max charging time in minutes
@@ -63,7 +73,14 @@
  * @thermal_mitigation: the array of charge currents to use as temperature
  *			increases
  * @thermal_levels:	the number of thermal mitigation levels supported
- *
+ * @cold_thr:		if high battery will be cold when VBAT_THERM goes above
+ *			80% of VREF_THERM (typically 1.8volts), if low the
+ *			battery will be considered cold if VBAT_THERM goes above
+ *			70% of VREF_THERM. Hardware defaults to low.
+ * @hot_thr:		if high the battery will be considered hot when the
+ *			VBAT_THERM goes below 35% of VREF_THERM, if low the
+ *			battery will be considered hot when VBAT_THERM goes
+ *			below 25% of VREF_THERM. Hardware defaults to low.
  */
 struct pm8921_charger_platform_data {
 	struct pm8xxx_charger_core_data	charger_cdata;
@@ -92,6 +109,8 @@
 	int				vin_min;
 	int				*thermal_mitigation;
 	int				thermal_levels;
+	enum pm8921_chg_cold_thr	cold_thr;
+	enum pm8921_chg_hot_thr		hot_thr;
 };
 
 enum pm8921_charger_source {