platform: msm8974: Clock support for hs400

Add support for gpll4, sdc_ff & sdc_sleep clocks.
Also update sdc1 frquency table to run sdc1 core clock
at 400 MHZ

CRs-Fixed: 501718
Change-Id: I7c08a4f65c7850f23c0184342875a4bf035e6d5e
diff --git a/platform/msm8974/acpuclock.c b/platform/msm8974/acpuclock.c
index e66208c..da1b024 100644
--- a/platform/msm8974/acpuclock.c
+++ b/platform/msm8974/acpuclock.c
@@ -128,6 +128,10 @@
 	{
 		ret = clk_get_set_enable(clk_name, 400000, 1);
 	}
+	else if(freq == MMC_CLK_25MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 25000000, 1);
+	}
 	else if(freq == MMC_CLK_50MHZ)
 	{
 		ret = clk_get_set_enable(clk_name, 50000000, 1);
@@ -136,10 +140,18 @@
 	{
 		ret = clk_get_set_enable(clk_name, 100000000, 1);
 	}
+	else if(freq == MMC_CLK_192MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 192000000, 1);
+	}
 	else if(freq == MMC_CLK_200MHZ)
 	{
 		ret = clk_get_set_enable(clk_name, 200000000, 1);
 	}
+	else if(freq == MMC_CLK_400MHZ)
+	{
+		ret = clk_get_set_enable(clk_name, 384000000, 1);
+	}
 	else
 	{
 		dprintf(CRITICAL, "sdc frequency (%u) is not supported\n", freq);
@@ -159,6 +171,29 @@
 #endif
 }
 
+/* Configure clocks needed for CDCLP533 circuit */
+void clock_config_cdc(uint32_t interface)
+{
+	int ret = 0;
+	char clk_name[64];
+
+	snprintf(clk_name, sizeof(clk_name), "gcc_sdcc%u_cdccal_sleep_clk", interface);
+	ret = clk_get_set_enable(clk_name, 0 , 1);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to enable clock: %s\n", clk_name);
+		ASSERT(0);
+	}
+
+	snprintf(clk_name, sizeof(clk_name), "gcc_sdcc%u_cdccal_ff_clk", interface);
+	ret = clk_get_set_enable(clk_name, 0 , 1);
+	if (ret)
+	{
+		dprintf(CRITICAL, "Failed to enable clock: %s\n", clk_name);
+		ASSERT(0);
+	}
+}
+
 /* Configure UART clock based on the UART block id*/
 void clock_config_uart_dm(uint8_t id)
 {
diff --git a/platform/msm8974/include/platform/iomap.h b/platform/msm8974/include/platform/iomap.h
index 42a436f..dcb0ba8 100644
--- a/platform/msm8974/include/platform/iomap.h
+++ b/platform/msm8974/include/platform/iomap.h
@@ -150,6 +150,9 @@
 #define APCS_GPLL_ENA_VOTE          (CLK_CTL_BASE + 0x1480)
 #define APCS_CLOCK_BRANCH_ENA_VOTE  (CLK_CTL_BASE + 0x1484)
 
+/* GPLL4 */
+#define GPLL4_STATUS                (CLK_CTL_BASE + 0x1DDC)
+
 /* SDCC */
 #define SDCC1_BCR                   (CLK_CTL_BASE + 0x4C0) /* block reset */
 #define SDCC1_APPS_CBCR             (CLK_CTL_BASE + 0x4C4) /* branch control */
@@ -161,6 +164,10 @@
 #define SDCC1_N                     (CLK_CTL_BASE + 0x4DC) /* n */
 #define SDCC1_D                     (CLK_CTL_BASE + 0x4E0) /* d */
 
+/* SDCC clocks for CDC calibration*/
+#define SDCC1_CDCCAL_SLEEP_CBCR     (CLK_CTL_BASE + 0x04E4)
+#define SDCC1_CDCCAL_FF_CBCR        (CLK_CTL_BASE + 0x04E8)
+
 /* SDCC2 */
 #define SDCC2_BCR                   (CLK_CTL_BASE + 0x500) /* block reset */
 #define SDCC2_APPS_CBCR             (CLK_CTL_BASE + 0x504) /* branch control */
diff --git a/platform/msm8974/msm8974-clock.c b/platform/msm8974/msm8974-clock.c
index 68000d5..e2209c2 100644
--- a/platform/msm8974/msm8974-clock.c
+++ b/platform/msm8974/msm8974-clock.c
@@ -39,6 +39,7 @@
 /* Mux source select values */
 #define cxo_source_val    0
 #define gpll0_source_val  1
+#define gpll4_source_val  5
 #define cxo_mm_source_val 0
 #define mmpll0_mm_source_val 1
 #define mmpll1_mm_source_val 2
@@ -115,8 +116,41 @@
 	},
 };
 
+static struct pll_vote_clk gpll4_clk_src =
+{
+	.en_reg       = (void *) APCS_GPLL_ENA_VOTE,
+	.en_mask      = BIT(4),
+	.status_reg   = (void *) GPLL4_STATUS,
+	.status_mask  = BIT(17),
+	.parent       = &cxo_clk_src.c,
+
+	.c = {
+		.rate     = 768000000,
+		.dbg_name = "gpll4_clk_src",
+		.ops      = &clk_ops_pll_vote,
+	},
+};
+
 /* SDCC Clocks */
-static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] =
+/* This table is for sdc1 apps clk only for MSM8974 PRO AC */
+static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk_ac[] =
+{
+	F(   144000,    cxo,  16,   3,  25),
+	F(   400000,    cxo,  12,   1,   4),
+	F( 20000000,  gpll0,  15,   1,   2),
+	F( 25000000,  gpll0,  12,   1,   2),
+	F( 50000000,  gpll0,  12,   0,   0),
+	F(100000000,  gpll0,   6,   0,   0),
+	F(192000000,  gpll4,   4,   0,   0),
+	F(384000000,  gpll4,   2,   0,   0),
+	F_END
+};
+
+/* This table is for
+ * sdc[1-4] for all MSM8974 excluding MSM8974PROAC
+ * sdc[2-4] for MSM8974PRO AC
+ */
+static struct clk_freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] =
 {
 	F(   144000,    cxo,  16,   3,  25),
 	F(   400000,    cxo,  12,   1,   4),
@@ -137,7 +171,7 @@
 	.d_reg        = (uint32_t *) SDCC1_D,
 
 	.set_rate     = clock_lib2_rcg_set_rate_mnd,
-	.freq_tbl     = ftbl_gcc_sdcc1_2_apps_clk,
+	.freq_tbl     = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 
 	.c = {
@@ -168,6 +202,28 @@
 	},
 };
 
+static struct branch_clk gcc_sdcc1_cdccal_sleep_clk =
+{
+	.cbcr_reg = SDCC1_CDCCAL_SLEEP_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc1_cdccal_sleep_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc1_cdccal_ff_clk =
+{
+	.cbcr_reg = SDCC1_CDCCAL_FF_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc1_cdccal_ff_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct rcg_clk sdcc2_apps_clk_src =
 {
 	.cmd_reg      = (uint32_t *) SDCC2_CMD_RCGR,
@@ -177,7 +233,7 @@
 	.d_reg        = (uint32_t *) SDCC2_D,
 
 	.set_rate     = clock_lib2_rcg_set_rate_mnd,
-	.freq_tbl     = ftbl_gcc_sdcc1_2_apps_clk,
+	.freq_tbl     = ftbl_gcc_sdcc1_4_apps_clk,
 	.current_freq = &rcg_dummy_freq,
 
 	.c = {
@@ -761,6 +817,9 @@
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
 	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
 
+	CLK_LOOKUP("gcc_sdcc1_cdccal_sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c),
+	CLK_LOOKUP("gcc_sdcc1_cdccal_ff_clk",    gcc_sdcc1_cdccal_ff_clk.c),
+
 	CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c),
 	CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
 
@@ -804,8 +863,14 @@
 	CLK_LOOKUP("usb30_master_clk", gcc_usb30_master_clk.c),
 };
 
+void msm8974_ac_clock_override()
+{
+	sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_ac;
+}
 
 void platform_clock_init(void)
 {
+	if (platform_is_8974ac())
+		msm8974_ac_clock_override();
 	clk_init(msm_clocks_8974, ARRAY_SIZE(msm_clocks_8974));
 }
diff --git a/platform/msm8974/platform.c b/platform/msm8974/platform.c
index be35f84..460317c 100644
--- a/platform/msm8974/platform.c
+++ b/platform/msm8974/platform.c
@@ -87,6 +87,81 @@
 	return readl(MPM2_MPM_SLEEP_TIMETICK_COUNT_VAL);
 }
 
+/* Check for 8974 chip */
+int platform_is_8974()
+{
+	uint32_t platform = board_platform_id();
+	int ret = 0;
+
+	switch(platform)
+	{
+		case APQ8074:
+		case MSM8274:
+		case MSM8674:
+		case MSM8974:
+			ret = 1;
+			break;
+		default:
+			ret = 0;
+	};
+
+	return ret;
+}
+
+/* Check for 8974 PRO chip */
+int platform_is_8974Pro()
+{
+	uint32_t platform = board_platform_id();
+	int ret = 0;
+
+	switch(platform)
+	{
+		case MSM8974AC:
+		case MSM8674AC:
+		case MSM8274AC:
+		case APQ8074AC:
+			ret = 1;
+			break;
+		default:
+			ret = 0;
+	};
+
+	return ret;
+}
+
+/* Check for 8974PRO AC chip */
+int platform_is_8974ac()
+{
+	uint32_t platform = board_platform_id();
+	int ret = 0;
+
+	switch(platform)
+	{
+		case APQ8074AA:
+		case APQ8074AB:
+		case APQ8074AC:
+
+		case MSM8274AA:
+		case MSM8274AB:
+		case MSM8274AC:
+
+		case MSM8674AA:
+		case MSM8674AB:
+		case MSM8674AC:
+
+		case MSM8974AA:
+		case MSM8974AB:
+		case MSM8974AC:
+
+			ret = 1;
+			break;
+		default:
+			ret = 0;
+	};
+
+	return ret;
+}
+
 addr_t get_bs_info_addr()
 {
 	uint32_t soc_ver = board_soc_version();
diff --git a/target/msm8974/init.c b/target/msm8974/init.c
index 1ee89bf..9334710 100644
--- a/target/msm8974/init.c
+++ b/target/msm8974/init.c
@@ -239,10 +239,19 @@
 			config.bus_width = DATA_BUS_WIDTH_8BIT;
 	};
 
-	config.max_clk_rate = MMC_CLK_200MHZ;
-
 	/* Trying Slot 1*/
 	config.slot = 1;
+	/*
+	 * For 8974 AC platform the software clock
+	 * plan recommends to use the following frequencies:
+	 * 200 MHz --> 192 MHZ
+	 * 400 MHZ --> 384 MHZ
+	 * only for emmc slot
+	 */
+	if (platform_is_8974ac())
+		config.max_clk_rate = MMC_CLK_192MHZ;
+	else
+		config.max_clk_rate = MMC_CLK_200MHZ;
 	config.sdhc_base = mmc_sdhci_base[config.slot - 1];
 	config.pwrctl_base = mmc_sdc_base[config.slot - 1];
 	config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
@@ -250,6 +259,7 @@
 	if (!(dev = mmc_init(&config))) {
 		/* Trying Slot 2 next */
 		config.slot = 2;
+		config.max_clk_rate = MMC_CLK_200MHZ;
 		config.sdhc_base = mmc_sdhci_base[config.slot - 1];
 		config.pwrctl_base = mmc_sdc_base[config.slot - 1];
 		config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];