power: pm8921-bms: use battery data based on battery id

Currently the battery data is passed via the board file. Instead
read the battery id and choose the appropriate battery data to use.

CRs-Fixed: 304376
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 863f1ff..f00ba8d 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -3606,7 +3606,6 @@
 	.i_test			= 2500,
 	.v_failure		= 3000,
 	.calib_delay_ms		= 600000,
-	.batt_data		= &palladium_1500_data,
 };
 
 #define	PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
diff --git a/arch/arm/mach-msm/board-msm8960.h b/arch/arm/mach-msm/board-msm8960.h
index 7a939af..1cfcfdd 100644
--- a/arch/arm/mach-msm/board-msm8960.h
+++ b/arch/arm/mach-msm/board-msm8960.h
@@ -41,6 +41,4 @@
 
 extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
 
-extern struct pm8921_bms_battery_data  palladium_1500_data;
-
 #endif
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index de1c698..20b7760 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -463,6 +463,7 @@
 		pdata->bms_pdata->bms_cdata.vbat_channel = CHANNEL_VBAT;
 		pdata->bms_pdata->bms_cdata.ref625mv_channel = CHANNEL_625MV;
 		pdata->bms_pdata->bms_cdata.ref1p25v_channel = CHANNEL_125V;
+		pdata->bms_pdata->bms_cdata.batt_id_channel = CHANNEL_BATT_ID;
 		bms_cell.platform_data = pdata->bms_pdata;
 		bms_cell.pdata_size = sizeof(struct pm8921_bms_platform_data);
 		ret = mfd_add_devices(pmic->dev, 0, &bms_cell, 1, NULL,
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 3a34a6a..b27d73f 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -84,6 +84,7 @@
 	unsigned int		vbat_channel;
 	unsigned int		ref625mv_channel;
 	unsigned int		ref1p25v_channel;
+	unsigned int		batt_id_channel;
 	unsigned int		pmic_bms_irq[PM_BMS_MAX_INTS];
 	DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
 };
@@ -1102,6 +1103,53 @@
 	pr_debug("ocv = %d last_ocv_uv = %d\n", ocv, last_ocv_uv);
 }
 
+static int64_t read_battery_id(struct pm8921_bms_chip *chip)
+{
+	int rc;
+	struct pm8921_adc_chan_result result;
+
+	rc = pm8921_adc_read(chip->batt_id_channel, &result);
+	if (rc) {
+		pr_err("error reading batt id channel = %d, rc = %d\n",
+					chip->vbat_channel, rc);
+		return rc;
+	}
+	pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
+						result.measurement);
+	return result.physical;
+}
+
+#define PALLADIUM_ID_MIN  2500
+#define PALLADIUM_ID_MAX  4000
+static int set_battery_data(struct pm8921_bms_chip *chip)
+{
+	int64_t battery_id;
+
+	battery_id = read_battery_id(chip);
+
+	if (battery_id < 0) {
+		pr_err("cannot read battery id err = %lld\n", battery_id);
+		return battery_id;
+	}
+
+	if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX, battery_id)) {
+		chip->fcc = palladium_1500_data.fcc;
+		chip->fcc_temp_lut = palladium_1500_data.fcc_temp_lut;
+		chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
+		chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
+		chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
+		return 0;
+	} else {
+		pr_warn("invalid battery id, palladium 1500 assumed\n");
+		chip->fcc = palladium_1500_data.fcc;
+		chip->fcc_temp_lut = palladium_1500_data.fcc_temp_lut;
+		chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
+		chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
+		chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
+		return 0;
+	}
+}
+
 enum {
 	CALC_RBATT,
 	CALC_FCC,
@@ -1366,17 +1414,17 @@
 	chip->i_test = pdata->i_test;
 	chip->v_failure = pdata->v_failure;
 	chip->calib_delay_ms = pdata->calib_delay_ms;
-	chip->fcc = pdata->batt_data->fcc;
-
-	chip->fcc_temp_lut = pdata->batt_data->fcc_temp_lut;
-	chip->fcc_sf_lut = pdata->batt_data->fcc_sf_lut;
-	chip->pc_temp_ocv_lut = pdata->batt_data->pc_temp_ocv_lut;
-	chip->pc_sf_lut = pdata->batt_data->pc_sf_lut;
+	rc = set_battery_data(chip);
+	if (rc) {
+		pr_err("%s bad battery data %d\n", __func__, rc);
+		return rc;
+	}
 
 	chip->batt_temp_channel = pdata->bms_cdata.batt_temp_channel;
 	chip->vbat_channel = pdata->bms_cdata.vbat_channel;
 	chip->ref625mv_channel = pdata->bms_cdata.ref625mv_channel;
 	chip->ref1p25v_channel = pdata->bms_cdata.ref1p25v_channel;
+	chip->batt_id_channel = pdata->bms_cdata.batt_id_channel;
 	chip->revision = pm8xxx_get_revision(chip->dev->parent);
 	INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index a8793e6..ac86b15 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -92,6 +92,7 @@
 	unsigned int	vbat_channel;
 	unsigned int	ref625mv_channel;
 	unsigned int	ref1p25v_channel;
+	unsigned int	batt_id_channel;
 };
 
 /**
@@ -101,7 +102,6 @@
  *			calculated or the peak system current (mA)
  * @v_failure:		the voltage at which the battery is considered empty(mV)
  * @calib_delay_ms:	how often should the adc calculate gain and offset
- * @batt_data:		the battery profile data for the one used in the board
  */
 struct pm8921_bms_platform_data {
 	struct pm8xxx_bms_core_data	bms_cdata;
@@ -109,10 +109,10 @@
 	unsigned int			i_test;
 	unsigned int			v_failure;
 	unsigned int			calib_delay_ms;
-	struct pm8921_bms_battery_data  *batt_data;
 };
 
 #if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
+extern struct pm8921_bms_battery_data  palladium_1500_data;
 /**
  * pm8921_bms_get_vsense_avg - return the voltage across the sense
  *				resitor in microvolts