msm: acpuclock-krait: Port additional functionality from acpuclock-8960

The following features from acpuclock-8960 are copied to acpuclock-krait:
 - HFPLL droop controller programming
 - aux_clk_sel MUX programming at init
 - "vmin" fix-up, for enforcing limits on voltages for some CPUs
 - PLL8 support in frequency tables

This will allow for future migration of various targets from using
acpuclock-8960 to the new-and-improved acpuclock-krait driver

Change-Id: Ic1c3f1eab7caba21ea7d6d4244748b2a05d8dbb8
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index d747704..4dc47d2 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -53,7 +53,7 @@
 static DEFINE_SPINLOCK(l2_lock);
 
 static struct drv_data {
-	const struct acpu_level *acpu_freq_tbl;
+	struct acpu_level *acpu_freq_tbl;
 	const struct l2_level *l2_freq_tbl;
 	struct scalable *scalable;
 	u32 bus_perf_client;
@@ -473,6 +473,11 @@
 	writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->m_offset);
 	writel_relaxed(1, sc->hfpll_base + sc->hfpll_data->n_offset);
 
+	/* Program droop controller, if supported */
+	if (sc->hfpll_data->has_droop_ctl)
+		writel_relaxed(sc->hfpll_data->droop_val,
+			       sc->hfpll_base + sc->hfpll_data->droop_offset);
+
 	/* Set an initial rate and enable the PLL. */
 	hfpll_set_rate(sc, tgt_s);
 	hfpll_enable(sc, false);
@@ -573,10 +578,15 @@
 				      const struct core_speed *tgt_s)
 {
 	u32 regval;
+	void __iomem *aux_reg;
 
 	/* Program AUX source input to the secondary MUX. */
-	if (sc->aux_clk_sel_addr)
-		writel_relaxed(sc->aux_clk_sel, sc->aux_clk_sel_addr);
+	if (sc->aux_clk_sel_phys) {
+		aux_reg = ioremap(sc->aux_clk_sel_phys, 4);
+		BUG_ON(!aux_reg);
+		writel_relaxed(sc->aux_clk_sel, aux_reg);
+		iounmap(aux_reg);
+	}
 
 	/* Switch away from the HFPLL while it's re-initialized. */
 	set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
@@ -693,8 +703,27 @@
 	.notifier_call = acpuclk_cpu_callback,
 };
 
+static const int krait_needs_vmin(void)
+{
+	switch (read_cpuid_id()) {
+	case 0x511F04D0: /* KR28M2A20 */
+	case 0x511F04D1: /* KR28M2A21 */
+	case 0x510F06F0: /* KR28M4A10 */
+		return 1;
+	default:
+		return 0;
+	};
+}
+
+static void krait_apply_vmin(struct acpu_level *tbl)
+{
+	for (; tbl->speed.khz != 0; tbl++)
+		if (tbl->vdd_core < 1150000)
+			tbl->vdd_core = 1150000;
+}
+
 static const struct acpu_level __init *select_freq_plan(
-		const struct acpu_level *const *pvs_tbl, u32 qfprom_phys)
+		struct acpu_level *const *pvs_tbl, u32 qfprom_phys)
 {
 	const struct acpu_level *l, *max_acpu_level = NULL;
 	void __iomem *qfprom_base;
@@ -737,6 +766,9 @@
 	}
 	drv.acpu_freq_tbl = pvs_tbl[tbl_idx];
 
+	if (krait_needs_vmin())
+		krait_apply_vmin(drv.acpu_freq_tbl);
+
 	/* Find the max supported scaling frequency. */
 	for (l = drv.acpu_freq_tbl; l->speed.khz != 0; l++)
 		if (l->use_for_scaling)
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 19629de..7c1d2b6 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -40,6 +40,7 @@
 	PLL_0 = 0,
 	HFPLL,
 	QSB,
+	PLL_8,
 };
 
 /**
@@ -146,7 +147,7 @@
 	const int use_for_scaling;
 	const struct core_speed speed;
 	const struct l2_level *l2_level;
-	const int vdd_core;
+	int vdd_core;
 };
 
 /**
@@ -157,6 +158,10 @@
  * @n_offset: "N" value register offset from base address.
  * @config_offset: Configuration register offset from base address.
  * @config_val: Value to initialize the @config_offset register to.
+ * @has_droop_ctl: Indicates the presence of a voltage droop controller.
+ * @droop_offset: Droop controller register offset from base address.
+ * @droop_val: Value to initialize the @config_offset register to.
+ * @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW.
  * @vdd: voltage requirements for each VDD level.
  */
 struct hfpll_data {
@@ -166,6 +171,9 @@
 	const u32 n_offset;
 	const u32 config_offset;
 	const u32 config_val;
+	const bool has_droop_ctl;
+	const u32 droop_offset;
+	const u32 droop_val;
 	const u32 low_vdd_l_max;
 	const int vdd[NUM_HFPLL_VDD];
 };
@@ -174,7 +182,7 @@
  * struct scalable - Register locations and state associated with a scalable HW.
  * @hfpll_phys_base: Physical base address of HFPLL register.
  * @hfpll_base: Virtual base address of HFPLL registers.
- * @aux_clk_sel_addr: Virtual address of auxiliary MUX.
+ * @aux_clk_sel_phys: Physical address of auxiliary MUX.
  * @aux_clk_sel: Auxiliary mux input to select at boot.
  * @l2cpmr_iaddr: Indirect address of the CPMR MUX/divider CP15 register.
  * @hfpll_data: Descriptive data of HFPLL hardware.
@@ -183,9 +191,9 @@
  * @vreg: Array of voltage regulators needed by the scalable.
  */
 struct scalable {
-	const u32 hfpll_phys_base;
+	const phys_addr_t hfpll_phys_base;
 	void __iomem *hfpll_base;
-	void __iomem *aux_clk_sel_addr;
+	const phys_addr_t aux_clk_sel_phys;
 	const u32 aux_clk_sel;
 	const u32 l2cpmr_iaddr;
 	const struct hfpll_data *hfpll_data;
@@ -205,10 +213,10 @@
  */
 struct acpuclk_krait_params {
 	struct scalable *scalable;
-	const struct acpu_level *pvs_acpu_freq_tbl[NUM_PVS];
+	struct acpu_level *pvs_acpu_freq_tbl[NUM_PVS];
 	const struct l2_level *l2_freq_tbl;
 	const size_t l2_freq_tbl_size;
-	const u32 qfprom_phys_base;
+	const phys_addr_t qfprom_phys_base;
 	struct msm_bus_scale_pdata *bus_scale_data;
 };