msm: clock-8960: Support 8960ab gfx speed-push
Certain 8960ab devices have a graphics core capable of running at 440MHz.
These devices are distinguished from regular 8960ab devices through a
speed bin attribute located in efuse.
Configure PLL3 to provide 880 Mhz, which is divided down to the rate
graphics requires.
Change-Id: I9d9e8d52bff1345809450dc24ef55667f7317775
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 502fcfe..01ccb5e 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -85,7 +85,12 @@
#define BB_PLL8_CONFIG_REG REG(0x3154)
#define BB_PLL8_TEST_CTL_REG REG(0x3150)
#define BB_MMCC_PLL2_MODE_REG REG(0x3160)
+#define BB_MMCC_PLL2_L_REG REG(0x3164)
+#define BB_MMCC_PLL2_M_REG REG(0x3168)
+#define BB_MMCC_PLL2_N_REG REG(0x316C)
#define BB_MMCC_PLL2_TEST_CTL_REG REG(0x3170)
+#define BB_MMCC_PLL2_CONFIG_REG REG(0x3174)
+#define BB_MMCC_PLL2_STATUS_REG REG(0x3178)
#define BB_PLL14_MODE_REG REG(0x31C0)
#define BB_PLL14_L_VAL_REG REG(0x31C4)
#define BB_PLL14_M_VAL_REG REG(0x31C8)
@@ -3518,7 +3523,7 @@
.ctl_val = CC_BANKED(9, 6, n), \
}
-/*Shared by 8064, 8930, and 8960ab*/
+/*Shared by 8064, and 8930*/
static struct clk_freq_tbl clk_tbl_gfx3d[] = {
F_GFX3D( 0, gnd, 0, 0),
F_GFX3D( 27000000, pxo, 0, 0),
@@ -3541,6 +3546,28 @@
F_END
};
+static struct clk_freq_tbl clk_tbl_gfx3d_8960ab[] = {
+ F_GFX3D( 0, gnd, 0, 0),
+ F_GFX3D( 27000000, pxo, 0, 0),
+ F_GFX3D( 48000000, pll8, 1, 8),
+ F_GFX3D( 54857000, pll8, 1, 7),
+ F_GFX3D( 64000000, pll8, 1, 6),
+ F_GFX3D( 76800000, pll8, 1, 5),
+ F_GFX3D( 96000000, pll8, 1, 4),
+ F_GFX3D(128000000, pll8, 1, 3),
+ F_GFX3D(145455000, pll2, 2, 11),
+ F_GFX3D(160000000, pll2, 1, 5),
+ F_GFX3D(177778000, pll2, 2, 9),
+ F_GFX3D(192000000, pll8, 1, 2),
+ F_GFX3D(200000000, pll2, 1, 4),
+ F_GFX3D(228571000, pll2, 2, 7),
+ F_GFX3D(266667000, pll2, 1, 3),
+ F_GFX3D(320000000, pll2, 2, 5),
+ F_GFX3D(400000000, pll2, 1, 2),
+ F_GFX3D(440000000, pll3, 1, 2),
+ F_END
+};
+
static struct clk_freq_tbl clk_tbl_gfx3d_8960[] = {
F_GFX3D( 0, gnd, 0, 0),
F_GFX3D( 27000000, pxo, 0, 0),
@@ -3614,12 +3641,23 @@
[VDD_DIG_HIGH] = 500000000
};
-static unsigned long fmax_gfx3d_8960ab[VDD_DIG_NUM] = {
+static unsigned long fmax_gfx3d_8960ab_400[VDD_DIG_NUM] = {
[VDD_DIG_LOW] = 192000000,
[VDD_DIG_NOMINAL] = 325000000,
[VDD_DIG_HIGH] = 400000000
};
+static unsigned long fmax_gfx3d_8960ab_440[VDD_DIG_NUM] = {
+ [VDD_DIG_LOW] = 192000000,
+ [VDD_DIG_NOMINAL] = 325000000,
+ [VDD_DIG_HIGH] = 440000000
+};
+
+static unsigned long *fmax_gfx3d_8960ab[] = {
+ [0] = fmax_gfx3d_8960ab_400,
+ [1] = fmax_gfx3d_8960ab_440,
+};
+
static struct bank_masks bmnd_info_gfx3d = {
.bank_sel_mask = BIT(11),
.bank0_mask = {
@@ -6275,6 +6313,31 @@
writel_relaxed(regval, reg);
}
+static struct pll_config_regs pll3_regs __initdata = {
+ .l_reg = BB_MMCC_PLL2_L_REG,
+ .m_reg = BB_MMCC_PLL2_M_REG,
+ .n_reg = BB_MMCC_PLL2_N_REG,
+ .config_reg = BB_MMCC_PLL2_CONFIG_REG,
+ .mode_reg = BB_MMCC_PLL2_MODE_REG,
+};
+
+/* Program PLL3 to 880MHZ */
+static struct pll_config pll3_config __initdata = {
+ .l = (32 | BVAL(31, 7, 0x8)),
+ .m = 16,
+ .n = 27,
+ .vco_val = 0x0,
+ .vco_mask = BM(8, 7),
+ .pre_div_val = 0x0,
+ .pre_div_mask = BIT(15),
+ .post_div_val = 0x0,
+ .post_div_mask = BIT(16),
+ .mn_ena_val = 0,
+ .mn_ena_mask = 0,
+ .main_output_val = 0,
+ .main_output_mask = 0,
+};
+
static struct pll_config_regs pll4_regs __initdata = {
.l_reg = LCC_PLL0_L_VAL_REG,
.m_reg = LCC_PLL0_M_VAL_REG,
@@ -6539,6 +6602,9 @@
pll15_config.m = 0x1;
pll15_config.n = 0x3;
configure_sr_pll(&pll15_config, &pll15_regs, 0);
+ } else if (cpu_is_msm8960ab()) {
+ pll3_clk.c.rate = 880000000;
+ configure_sr_pll(&pll3_config, &pll3_regs, 0);
}
/*
@@ -6561,6 +6627,27 @@
}
}
+#define PTE_EFUSE_GFX_PHYS (0x007000BC)
+
+static unsigned long *select_gfx_fmax_plan(unsigned long **gfx_fmax, int size)
+{
+ void __iomem *pte_efuse;
+ u32 gfx_speed_bin;
+
+ pte_efuse = ioremap(PTE_EFUSE_GFX_PHYS, 4);
+ gfx_speed_bin = readl_relaxed(pte_efuse);
+ gfx_speed_bin = (gfx_speed_bin & BM(25, 24)) >> 24;
+ iounmap(pte_efuse);
+
+ if (gfx_speed_bin >= size) {
+ pr_err("GFX_SPEED_BIN: defaulting to 0\n");
+ gfx_speed_bin = 0;
+ }
+
+ pr_info("GFX_SPEED_BIN: %d\n", gfx_speed_bin);
+ return gfx_fmax[gfx_speed_bin];
+}
+
struct clock_init_data msm8960_clock_init_data __initdata;
static void __init msm8960_clock_pre_init(void)
{
@@ -6586,10 +6673,12 @@
memcpy(msm_clocks_8960, msm_clocks_8960_common,
sizeof(msm_clocks_8960_common));
if (cpu_is_msm8960ab()) {
- pll3_clk.c.rate = 650000000;
- gfx3d_clk.c.fmax = fmax_gfx3d_8960ab;
+ gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960ab;
mdp_clk.c.fmax = fmax_mdp_8960ab;
+ gfx3d_clk.c.fmax = select_gfx_fmax_plan(fmax_gfx3d_8960ab,
+ ARRAY_SIZE(fmax_gfx3d_8960ab));
+
memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
msm_clocks_8960ab_only, sizeof(msm_clocks_8960ab_only));
msm8960_clock_init_data.size -=