msm: acpuclock-8064: Add support for multiple speed and PVS bins.

Add support for 1.7 GHz and 2.0 GHz parts and their corresponding
L2 and memory bandwidth votes.

Support selecting different PVS tables based upon EFUSE speed bin
across all krait targets.

Signed-off-by: Patrick Daly <pdaly@codeaurora.org>

Conflicts:

	arch/arm/mach-msm/acpuclock-8064.c

Change-Id: I560371c3c5476f72444a8f2a88b9c441f3451ae1
Signed-off-by: Neha Pandey <nehap@codeaurora.org>
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 5c7e565..c429eec 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -934,58 +934,68 @@
 	}
 }
 
-static int __init select_freq_plan(u32 pte_efuse_phys)
+static int __init get_speed_bin(u32 pte_efuse)
+{
+	uint32_t speed_bin;
+
+	speed_bin = pte_efuse & 0xF;
+	if (speed_bin == 0xF)
+		speed_bin = (pte_efuse >> 4) & 0xF;
+
+	if (speed_bin == 0xF) {
+		speed_bin = 0;
+		dev_warn(drv.dev, "SPEED BIN: Defaulting to %d\n", speed_bin);
+	} else {
+		dev_info(drv.dev, "SPEED BIN: %d\n", speed_bin);
+	}
+
+	return speed_bin;
+}
+
+static int __init get_pvs_bin(u32 pte_efuse)
+{
+	uint32_t pvs_bin;
+
+	pvs_bin = (pte_efuse >> 10) & 0x7;
+	if (pvs_bin == 0x7)
+		pvs_bin = (pte_efuse >> 13) & 0x7;
+
+	if (pvs_bin == 0x7) {
+		pvs_bin = 0;
+		dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n", pvs_bin);
+	} else {
+		dev_info(drv.dev, "ACPU PVS: %d\n", pvs_bin);
+	}
+
+	return pvs_bin;
+}
+
+static struct pvs_table * __init select_freq_plan(u32 pte_efuse_phys,
+			struct pvs_table (*pvs_tables)[NUM_PVS])
 {
 	void __iomem *pte_efuse;
-	u32 pte_efuse_val, pvs, tbl_idx;
-	char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
+	u32 pte_efuse_val, tbl_idx, bin_idx;
 
 	pte_efuse = ioremap(pte_efuse_phys, 4);
-	/* Select frequency tables. */
-	if (pte_efuse) {
-		pte_efuse_val = readl_relaxed(pte_efuse);
-		pvs = (pte_efuse_val >> 10) & 0x7;
-		iounmap(pte_efuse);
-		if (pvs == 0x7)
-			pvs = (pte_efuse_val >> 13) & 0x7;
-
-		switch (pvs) {
-		case 0x0:
-		case 0x7:
-			tbl_idx = PVS_SLOW;
-			break;
-		case 0x1:
-			tbl_idx = PVS_NOMINAL;
-			break;
-		case 0x3:
-			tbl_idx = PVS_FAST;
-			break;
-		case 0x4:
-			tbl_idx = PVS_FASTER;
-			break;
-		default:
-			tbl_idx = PVS_UNKNOWN;
-			break;
-		}
-	} else {
-		tbl_idx = PVS_UNKNOWN;
+	if (!pte_efuse) {
 		dev_err(drv.dev, "Unable to map QFPROM base\n");
-	}
-	if (tbl_idx == PVS_UNKNOWN) {
-		tbl_idx = PVS_SLOW;
-		dev_warn(drv.dev, "ACPU PVS: Defaulting to %s\n",
-			 pvs_names[tbl_idx]);
-	} else {
-		dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
+		return NULL;
 	}
 
-	return tbl_idx;
+	pte_efuse_val = readl_relaxed(pte_efuse);
+	iounmap(pte_efuse);
+
+	/* Select frequency tables. */
+	bin_idx = get_speed_bin(pte_efuse_val);
+	tbl_idx = get_pvs_bin(pte_efuse_val);
+
+	return &pvs_tables[bin_idx][tbl_idx];
 }
 
 static void __init drv_data_init(struct device *dev,
 				 const struct acpuclk_krait_params *params)
 {
-	int tbl_idx;
+	struct pvs_table *pvs;
 
 	drv.dev = dev;
 	drv.scalable = kmemdup(params->scalable, params->scalable_size,
@@ -1008,12 +1018,12 @@
 		GFP_KERNEL);
 	BUG_ON(!drv.bus_scale->usecase);
 
-	tbl_idx = select_freq_plan(params->pte_efuse_phys);
-	drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
-				    params->pvs_tables[tbl_idx].size,
-				    GFP_KERNEL);
+	pvs = select_freq_plan(params->pte_efuse_phys, params->pvs_tables);
+	BUG_ON(!pvs->table);
+
+	drv.acpu_freq_tbl = kmemdup(pvs->table, pvs->size, GFP_KERNEL);
 	BUG_ON(!drv.acpu_freq_tbl);
-	drv.boost_uv = params->pvs_tables[tbl_idx].boost_uv;
+	drv.boost_uv = pvs->boost_uv;
 
 	acpuclk_krait_data.power_collapse_khz = params->stby_khz;
 	acpuclk_krait_data.wait_for_irq_khz = params->stby_khz;